PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/pdo_sqlite - sqlite_driver.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 307 386 79.5 %
Date: 2014-10-22 Functions: 25 26 96.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2014 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Author: Wez Furlong <wez@php.net>                                    |
      16             :   +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : #ifdef HAVE_CONFIG_H
      22             : #include "config.h"
      23             : #endif
      24             : 
      25             : #include "php.h"
      26             : #include "php_ini.h"
      27             : #include "ext/standard/info.h"
      28             : #include "pdo/php_pdo.h"
      29             : #include "pdo/php_pdo_driver.h"
      30             : #include "php_pdo_sqlite.h"
      31             : #include "php_pdo_sqlite_int.h"
      32             : #include "zend_exceptions.h"
      33             : 
      34         343 : int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC) /* {{{ */
      35             : {
      36         343 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
      37         343 :         pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
      38         343 :         pdo_sqlite_error_info *einfo = &H->einfo;
      39             : 
      40         343 :         einfo->errcode = sqlite3_errcode(H->db);
      41         343 :         einfo->file = file;
      42         343 :         einfo->line = line;
      43             : 
      44         343 :         if (einfo->errcode != SQLITE_OK) {
      45         343 :                 if (einfo->errmsg) {
      46         229 :                         pefree(einfo->errmsg, dbh->is_persistent);
      47             :                 }
      48         343 :                 einfo->errmsg = pestrdup((char*)sqlite3_errmsg(H->db), dbh->is_persistent);
      49             :         } else { /* no error */
      50           0 :                 strncpy(*pdo_err, PDO_ERR_NONE, sizeof(PDO_ERR_NONE));
      51           0 :                 return 0;
      52             :         }
      53         343 :         switch (einfo->errcode) {
      54             :                 case SQLITE_NOTFOUND:
      55           0 :                         strncpy(*pdo_err, "42S02", sizeof("42S02"));
      56           0 :                         break;  
      57             : 
      58             :                 case SQLITE_INTERRUPT:
      59           0 :                         strncpy(*pdo_err, "01002", sizeof("01002"));
      60           0 :                         break;
      61             : 
      62             :                 case SQLITE_NOLFS:
      63           0 :                         strncpy(*pdo_err, "HYC00", sizeof("HYC00"));
      64           0 :                         break;
      65             : 
      66             :                 case SQLITE_TOOBIG:
      67           0 :                         strncpy(*pdo_err, "22001", sizeof("22001"));
      68           0 :                         break;
      69             :         
      70             :                 case SQLITE_CONSTRAINT:
      71           0 :                         strncpy(*pdo_err, "23000", sizeof("23000"));
      72           0 :                         break;
      73             : 
      74             :                 case SQLITE_ERROR:
      75             :                 default:
      76         343 :                         strncpy(*pdo_err, "HY000", sizeof("HY000"));
      77             :                         break;
      78             :         }
      79             : 
      80         343 :         if (!dbh->methods) {
      81           1 :                 zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
      82             :                                 *pdo_err, einfo->errcode, einfo->errmsg);
      83             :         }
      84             :         
      85         343 :         return einfo->errcode;
      86             : }
      87             : /* }}} */
      88             : 
      89           9 : static int pdo_sqlite_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
      90             : {
      91           9 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
      92           9 :         pdo_sqlite_error_info *einfo = &H->einfo;
      93             : 
      94           9 :         if (einfo->errcode) {
      95           8 :                 add_next_index_long(info, einfo->errcode);
      96           8 :                 add_next_index_string(info, einfo->errmsg);
      97             :         }
      98             : 
      99           9 :         return 1;
     100             : }
     101             : 
     102         169 : static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H TSRMLS_DC)
     103             : {
     104             :         struct pdo_sqlite_func *func;
     105             : 
     106         342 :         while (H->funcs) {
     107           4 :                 func = H->funcs;
     108           4 :                 H->funcs = func->next;
     109             : 
     110           4 :                 if (H->db) {
     111             :                         /* delete the function from the handle */
     112           4 :                         sqlite3_create_function(H->db,
     113             :                                 func->funcname,
     114             :                                 func->argc,
     115             :                                 SQLITE_UTF8,
     116             :                                 func,
     117             :                                 NULL, NULL, NULL);
     118             :                 }
     119             : 
     120           4 :                 efree((char*)func->funcname);
     121           8 :                 if (!Z_ISUNDEF(func->func)) {
     122           3 :                         zval_ptr_dtor(&func->func);
     123             :                 }
     124           8 :                 if (!Z_ISUNDEF(func->step)) {
     125           1 :                         zval_ptr_dtor(&func->step);
     126             :                 }
     127           8 :                 if (!Z_ISUNDEF(func->fini)) {
     128           1 :                         zval_ptr_dtor(&func->fini);
     129             :                 }
     130           4 :                 efree(func);
     131             :         }
     132             : 
     133         339 :         while (H->collations) {
     134             :                 struct pdo_sqlite_collation *collation;
     135           1 :                 collation = H->collations;
     136           1 :                 H->collations = collation->next;
     137             : 
     138           1 :                 if (H->db) {
     139             :                         /* delete the collation from the handle */
     140           1 :                         sqlite3_create_collation(H->db,
     141             :                                 collation->name,
     142             :                                 SQLITE_UTF8,
     143             :                                 collation,
     144             :                                 NULL);
     145             :                 }
     146             : 
     147           1 :                 efree((char*)collation->name);
     148           2 :                 if (!Z_ISUNDEF(collation->callback)) {
     149           1 :                         zval_ptr_dtor(&collation->callback);
     150             :                 }
     151           1 :                 efree(collation);
     152             :         }
     153         169 : }
     154             : 
     155         164 : static int sqlite_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
     156             : {
     157         164 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     158             :         
     159         164 :         if (H) {
     160         164 :                 pdo_sqlite_error_info *einfo = &H->einfo;
     161             : 
     162         164 :                 pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
     163         164 :                 if (H->db) {
     164         164 :                         sqlite3_close(H->db);
     165         164 :                         H->db = NULL;
     166             :                 }
     167         164 :                 if (einfo->errmsg) {
     168         114 :                         pefree(einfo->errmsg, dbh->is_persistent);
     169         114 :                         einfo->errmsg = NULL;
     170             :                 }
     171         164 :                 pefree(H, dbh->is_persistent);
     172         164 :                 dbh->driver_data = NULL;
     173             :         }
     174         164 :         return 0;
     175             : }
     176             : /* }}} */
     177             : 
     178         173 : static int sqlite_handle_preparer(pdo_dbh_t *dbh, const char *sql, zend_long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
     179             : {
     180         173 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     181         173 :         pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
     182             :         int i;
     183             :         const char *tail;
     184             : 
     185         173 :         S->H = H;
     186         173 :         stmt->driver_data = S;
     187         173 :         stmt->methods = &sqlite_stmt_methods;
     188         173 :         stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
     189             : 
     190         173 :         if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC)) {
     191           0 :                 H->einfo.errcode = SQLITE_ERROR;
     192           0 :                 pdo_sqlite_error(dbh);
     193           0 :                 return 0;
     194             :         }
     195             : 
     196         173 :         i = sqlite3_prepare(H->db, sql, sql_len, &S->stmt, &tail);
     197         173 :         if (i == SQLITE_OK) {
     198         172 :                 return 1;
     199             :         }
     200             : 
     201           1 :         pdo_sqlite_error(dbh);
     202             : 
     203           1 :         return 0;
     204             : }
     205             : 
     206         507 : static zend_long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, zend_long sql_len TSRMLS_DC)
     207             : {
     208         507 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     209         507 :         char *errmsg = NULL;
     210             : 
     211         507 :         if (sqlite3_exec(H->db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
     212         339 :                 pdo_sqlite_error(dbh);
     213         339 :                 if (errmsg)
     214         339 :                         sqlite3_free(errmsg);
     215             : 
     216         339 :                 return -1;
     217             :         } else {
     218         168 :                 return sqlite3_changes(H->db);
     219             :         }
     220             : }
     221             : 
     222           1 : static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
     223             : {
     224           1 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     225             :         char *id;
     226             :         
     227           1 :         id = php_pdo_int64_to_str(sqlite3_last_insert_rowid(H->db) TSRMLS_CC);
     228           1 :         *len = strlen(id);
     229           1 :         return id;
     230             : }
     231             : 
     232             : /* NB: doesn't handle binary strings... use prepared stmts for that */
     233           1 : static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype  TSRMLS_DC)
     234             : {
     235           1 :         *quoted = safe_emalloc(2, unquotedlen, 3);
     236           1 :         sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted);
     237           1 :         *quotedlen = strlen(*quoted);
     238           1 :         return 1;
     239             : }
     240             : 
     241           5 : static int sqlite_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
     242             : {
     243           5 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     244           5 :         char *errmsg = NULL;
     245             : 
     246           5 :         if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
     247           0 :                 pdo_sqlite_error(dbh);
     248           0 :                 if (errmsg)
     249           0 :                         sqlite3_free(errmsg);
     250           0 :                 return 0;
     251             :         }
     252           5 :         return 1;
     253             : }
     254             : 
     255           2 : static int sqlite_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
     256             : {
     257           2 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     258           2 :         char *errmsg = NULL;
     259             : 
     260           2 :         if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
     261           0 :                 pdo_sqlite_error(dbh);
     262           0 :                 if (errmsg)
     263           0 :                         sqlite3_free(errmsg);
     264           0 :                 return 0;
     265             :         }
     266           2 :         return 1;
     267             : }
     268             : 
     269           3 : static int sqlite_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
     270             : {
     271           3 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     272           3 :         char *errmsg = NULL;
     273             : 
     274           3 :         if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
     275           0 :                 pdo_sqlite_error(dbh);
     276           0 :                 if (errmsg)
     277           0 :                         sqlite3_free(errmsg);
     278           0 :                 return 0;
     279             :         }
     280           3 :         return 1;
     281             : }
     282             : 
     283           2 : static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value TSRMLS_DC)
     284             : {
     285           2 :         switch (attr) {
     286             :                 case PDO_ATTR_CLIENT_VERSION:
     287             :                 case PDO_ATTR_SERVER_VERSION:
     288           4 :                         ZVAL_STRING(return_value, (char *)sqlite3_libversion());
     289           2 :                         break;
     290             :                 
     291             :                 default:
     292           0 :                         return 0;       
     293             :         }
     294             : 
     295           2 :         return 1;
     296             : }
     297             : 
     298          25 : static int pdo_sqlite_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val TSRMLS_DC)
     299             : {
     300          25 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     301             : 
     302          25 :         switch (attr) {
     303             :                 case PDO_ATTR_TIMEOUT:
     304          18 :                         convert_to_long(val);
     305          18 :                         sqlite3_busy_timeout(H->db, Z_LVAL_P(val) * 1000);
     306          18 :                         return 1;
     307             :         }
     308           7 :         return 0;
     309             : }
     310             : 
     311           5 : static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
     312             :                 int argc, sqlite3_value **argv, sqlite3_context *context,
     313             :                 int is_agg TSRMLS_DC)
     314             : {
     315           5 :         zval *zargs = NULL;
     316             :         zval retval;
     317             :         int i;
     318             :         int ret;
     319             :         int fake_argc;
     320           5 :         zend_reference *agg_context = NULL;
     321             :         
     322           5 :         if (is_agg) {
     323           3 :                 is_agg = 2;
     324             :         }
     325             :         
     326           5 :         fake_argc = argc + is_agg;
     327             :         
     328           5 :         fc->fci.size = sizeof(fc->fci);
     329           5 :         fc->fci.function_table = EG(function_table);
     330           5 :         ZVAL_COPY_VALUE(&fc->fci.function_name, cb);
     331           5 :         fc->fci.symbol_table = NULL;
     332           5 :         fc->fci.object = NULL;
     333           5 :         fc->fci.retval = &retval;
     334           5 :         fc->fci.param_count = fake_argc;
     335             :         
     336             :         /* build up the params */
     337             : 
     338           5 :         if (fake_argc) {
     339           5 :                 zargs = safe_emalloc(fake_argc, sizeof(zval), 0);
     340             :         }
     341             : 
     342           5 :         if (is_agg) {
     343           3 :                 agg_context = (zend_reference*)sqlite3_aggregate_context(context, sizeof(zend_reference));
     344           3 :                 if (!agg_context) {
     345           0 :                         ZVAL_NULL(&zargs[0]);
     346             :                 } else {
     347           6 :                         if (Z_ISUNDEF(agg_context->val)) {
     348           1 :                                 GC_REFCOUNT(agg_context) = 1;
     349           1 :                                 GC_TYPE_INFO(agg_context) = IS_REFERENCE;
     350           1 :                                 ZVAL_NULL(&agg_context->val);
     351             :                         }
     352           3 :                         ZVAL_REF(&zargs[0], agg_context);
     353             :                 }
     354           3 :                 ZVAL_LONG(&zargs[1], sqlite3_aggregate_count(context));
     355             :         }
     356             :         
     357           9 :         for (i = 0; i < argc; i++) {
     358             :                 /* get the value */
     359           4 :                 switch (sqlite3_value_type(argv[i])) {
     360             :                         case SQLITE_INTEGER:
     361           0 :                                 ZVAL_LONG(&zargs[i + is_agg], sqlite3_value_int(argv[i]));
     362           0 :                                 break;
     363             : 
     364             :                         case SQLITE_FLOAT:
     365           0 :                                 ZVAL_DOUBLE(&zargs[i + is_agg], sqlite3_value_double(argv[i]));
     366           0 :                                 break;
     367             : 
     368             :                         case SQLITE_NULL:
     369           0 :                                 ZVAL_NULL(&zargs[i + is_agg]);
     370           0 :                                 break;
     371             : 
     372             :                         case SQLITE_BLOB:
     373             :                         case SQLITE3_TEXT:
     374             :                         default:
     375           8 :                                 ZVAL_STRINGL(&zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]), sqlite3_value_bytes(argv[i]));
     376             :                                 break;
     377             :                 }
     378             :         }
     379             : 
     380           5 :         fc->fci.params = zargs;
     381             : 
     382           5 :         if ((ret = zend_call_function(&fc->fci, &fc->fcc TSRMLS_CC)) == FAILURE) {
     383           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
     384             :         }
     385             : 
     386             :         /* clean up the params */
     387           5 :         if (zargs) {
     388           9 :                 for (i = is_agg; i < fake_argc; i++) {
     389           4 :                         zval_ptr_dtor(&zargs[i]);
     390             :                 }
     391           5 :                 if (is_agg) {
     392           3 :                         zval_ptr_dtor(&zargs[1]);
     393             :                 }
     394           5 :                 efree(zargs);
     395             :         }
     396             : 
     397           8 :         if (!is_agg || !argv) {
     398             :                 /* only set the sqlite return value if we are a scalar function,
     399             :                  * or if we are finalizing an aggregate */
     400           3 :                 if (!Z_ISUNDEF(retval)) {
     401           3 :                         switch (Z_TYPE(retval)) {
     402             :                                 case IS_LONG:
     403           0 :                                         sqlite3_result_int(context, Z_LVAL(retval));
     404           0 :                                         break;
     405             : 
     406             :                                 case IS_NULL:
     407           0 :                                         sqlite3_result_null(context);
     408           0 :                                         break;
     409             : 
     410             :                                 case IS_DOUBLE:
     411           0 :                                         sqlite3_result_double(context, Z_DVAL(retval));
     412           0 :                                         break;
     413             : 
     414             :                                 default:
     415           3 :                                         convert_to_string_ex(&retval);
     416           3 :                                         sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
     417             :                                         break;
     418             :                         }
     419             :                 } else {
     420           0 :                         sqlite3_result_error(context, "failed to invoke callback", 0);
     421             :                 }
     422             : 
     423           3 :                 if (agg_context) {
     424           1 :                         zval_ptr_dtor(&agg_context->val);
     425             :                 }
     426             :         } else {
     427             :                 /* we're stepping in an aggregate; the return value goes into
     428             :                  * the context */
     429           2 :                 if (agg_context) {
     430           2 :                         zval_ptr_dtor(&agg_context->val);
     431             :                 }
     432           2 :                 if (!Z_ISUNDEF(retval)) {
     433           2 :                         ZVAL_COPY_VALUE(&agg_context->val, &retval);
     434           2 :                         ZVAL_UNDEF(&retval);
     435             :                 } else {
     436           0 :                         ZVAL_UNDEF(&agg_context->val);
     437             :                 }
     438             :         }
     439             : 
     440           5 :         if (!Z_ISUNDEF(retval)) {
     441           3 :                 zval_ptr_dtor(&retval);
     442             :         }
     443             : 
     444           5 :         return ret;
     445             : }
     446             : 
     447           2 : static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
     448             :         sqlite3_value **argv)
     449             : {
     450           2 :         struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
     451             :         TSRMLS_FETCH();
     452             : 
     453           2 :         do_callback(&func->afunc, &func->func, argc, argv, context, 0 TSRMLS_CC);
     454           2 : }
     455             : 
     456           2 : static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
     457             :         sqlite3_value **argv)
     458             : {
     459           2 :         struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
     460             :         TSRMLS_FETCH();
     461             : 
     462           2 :         do_callback(&func->astep, &func->step, argc, argv, context, 1 TSRMLS_CC);
     463           2 : }
     464             : 
     465           1 : static void php_sqlite3_func_final_callback(sqlite3_context *context)
     466             : {
     467           1 :         struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
     468             :         TSRMLS_FETCH();
     469             : 
     470           1 :         do_callback(&func->afini, &func->fini, 0, NULL, context, 1 TSRMLS_CC);
     471           1 : }
     472             : 
     473           2 : static int php_sqlite3_collation_callback(void *context,
     474             :         int string1_len, const void *string1,
     475             :         int string2_len, const void *string2)
     476             : {
     477             :         int ret;
     478             :         zval zargs[2];
     479             :         zval retval;
     480           2 :         struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
     481             :         TSRMLS_FETCH();
     482             : 
     483           2 :         collation->fc.fci.size = sizeof(collation->fc.fci);
     484           2 :         collation->fc.fci.function_table = EG(function_table);
     485           2 :         ZVAL_COPY_VALUE(&collation->fc.fci.function_name, &collation->callback);
     486           2 :         collation->fc.fci.symbol_table = NULL;
     487           2 :         collation->fc.fci.object = NULL;
     488           2 :         collation->fc.fci.retval = &retval;
     489             : 
     490             :         // Prepare the arguments.
     491           4 :         ZVAL_STRINGL(&zargs[0], (char *) string1, string1_len);
     492           4 :         ZVAL_STRINGL(&zargs[1], (char *) string2, string2_len);
     493           2 :         collation->fc.fci.param_count = 2;
     494           2 :         collation->fc.fci.params = zargs;
     495             : 
     496           2 :         if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc TSRMLS_CC)) == FAILURE) {
     497           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
     498           2 :         } else if (!Z_ISUNDEF(retval)) {
     499           2 :                 if (Z_TYPE(retval) != IS_LONG) {
     500           0 :                         convert_to_long_ex(&retval);
     501             :                 }
     502           2 :                 ret = 0;
     503           2 :                 if (Z_LVAL(retval) > 0) {
     504           0 :                         ret = 1;
     505           2 :                 } else if (Z_LVAL(retval) < 0) {
     506           2 :                         ret = -1;
     507             :                 }
     508           2 :                 zval_ptr_dtor(&retval);
     509             :         }
     510             : 
     511           2 :         zval_ptr_dtor(&zargs[0]);
     512           2 :         zval_ptr_dtor(&zargs[1]);
     513             : 
     514           2 :         return ret;
     515             : }
     516             : 
     517             : /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount])
     518             :    Registers a UDF with the sqlite db handle */
     519           4 : static PHP_METHOD(SQLite, sqliteCreateFunction)
     520             : {
     521             :         struct pdo_sqlite_func *func;
     522             :         zval *callback;
     523             :         char *func_name;
     524             :         size_t func_name_len;
     525           4 :         zend_long argc = -1;
     526           4 :         zend_string *cbname = NULL;
     527             :         pdo_dbh_t *dbh;
     528             :         pdo_sqlite_db_handle *H;
     529             :         int ret;
     530             : 
     531           4 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l",
     532             :                         &func_name, &func_name_len, &callback, &argc)) {
     533           0 :                 RETURN_FALSE;
     534             :         }
     535             :         
     536           4 :         dbh = Z_PDO_DBH_P(getThis());
     537           4 :         PDO_CONSTRUCT_CHECK;
     538             : 
     539           4 :         if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
     540           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname->val);
     541           1 :                 zend_string_release(cbname);
     542           1 :                 RETURN_FALSE;
     543             :         }
     544           3 :         zend_string_release(cbname);
     545             :         
     546           3 :         H = (pdo_sqlite_db_handle *)dbh->driver_data;
     547             : 
     548           3 :         func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
     549             : 
     550           3 :         ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
     551             :                         func, php_sqlite3_func_callback, NULL, NULL);
     552           3 :         if (ret == SQLITE_OK) {
     553           3 :                 func->funcname = estrdup(func_name);
     554             :                 
     555           3 :                 ZVAL_COPY(&func->func, callback);
     556             :                 
     557           3 :                 func->argc = argc;
     558             : 
     559           3 :                 func->next = H->funcs;
     560           3 :                 H->funcs = func;
     561             : 
     562           3 :                 RETURN_TRUE;
     563             :         }
     564             : 
     565           0 :         efree(func);
     566           0 :         RETURN_FALSE;
     567             : }
     568             : /* }}} */
     569             : 
     570             : /* {{{ bool SQLite::sqliteCreateAggregate(string name, mixed step, mixed fini [, int argcount])
     571             :    Registers a UDF with the sqlite db handle */
     572             : 
     573             : /* The step function should have the prototype:
     574             :    mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
     575             : 
     576             :    $context will be null for the first row; on subsequent rows it will have
     577             :    the value that was previously returned from the step function; you should
     578             :    use this to maintain state for the aggregate.
     579             : 
     580             :    The fini function should have the prototype:
     581             :    mixed fini(mixed $context, int $rownumber)
     582             : 
     583             :    $context will hold the return value from the very last call to the step function.
     584             :    rownumber will hold the number of rows over which the aggregate was performed.
     585             :    The return value of this function will be used as the return value for this
     586             :    aggregate UDF.
     587             : */
     588             :    
     589           3 : static PHP_METHOD(SQLite, sqliteCreateAggregate)
     590             : {
     591             :         struct pdo_sqlite_func *func;
     592             :         zval *step_callback, *fini_callback;
     593             :         char *func_name;
     594             :         size_t func_name_len;
     595           3 :         zend_long argc = -1;
     596           3 :         zend_string *cbname = NULL;
     597             :         pdo_dbh_t *dbh;
     598             :         pdo_sqlite_db_handle *H;
     599             :         int ret;
     600             : 
     601           3 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l",
     602             :                         &func_name, &func_name_len, &step_callback, &fini_callback, &argc)) {
     603           0 :                 RETURN_FALSE;
     604             :         }
     605             :         
     606           3 :         dbh = Z_PDO_DBH_P(getThis());
     607           3 :         PDO_CONSTRUCT_CHECK;
     608             : 
     609           3 :         if (!zend_is_callable(step_callback, 0, &cbname TSRMLS_CC)) {
     610           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname->val);
     611           1 :                 zend_string_release(cbname);
     612           1 :                 RETURN_FALSE;
     613             :         }
     614           2 :         zend_string_release(cbname);
     615           2 :         if (!zend_is_callable(fini_callback, 0, &cbname TSRMLS_CC)) {
     616           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname->val);
     617           1 :                 zend_string_release(cbname);
     618           1 :                 RETURN_FALSE;
     619             :         }
     620           1 :         zend_string_release(cbname);
     621             :         
     622           1 :         H = (pdo_sqlite_db_handle *)dbh->driver_data;
     623             : 
     624           1 :         func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
     625             : 
     626           1 :         ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
     627             :                         func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
     628           1 :         if (ret == SQLITE_OK) {
     629           1 :                 func->funcname = estrdup(func_name);
     630             :                 
     631           1 :                 ZVAL_COPY(&func->step, step_callback);
     632             : 
     633           1 :                 ZVAL_COPY(&func->fini, fini_callback);
     634             :                 
     635           1 :                 func->argc = argc;
     636             : 
     637           1 :                 func->next = H->funcs;
     638           1 :                 H->funcs = func;
     639             : 
     640           1 :                 RETURN_TRUE;
     641             :         }
     642             : 
     643           0 :         efree(func);
     644           0 :         RETURN_FALSE;
     645             : }
     646             : /* }}} */
     647             : 
     648             : /* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
     649             :    Registers a collation with the sqlite db handle */
     650           1 : static PHP_METHOD(SQLite, sqliteCreateCollation)
     651             : {
     652             :         struct pdo_sqlite_collation *collation;
     653             :         zval *callback;
     654             :         char *collation_name;
     655             :         size_t collation_name_len;
     656           1 :         zend_string *cbname = NULL;
     657             :         pdo_dbh_t *dbh;
     658             :         pdo_sqlite_db_handle *H;
     659             :         int ret;
     660             : 
     661           1 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz",
     662             :                 &collation_name, &collation_name_len, &callback)) {
     663           0 :                 RETURN_FALSE;
     664             :         }
     665             : 
     666           1 :         dbh = Z_PDO_DBH_P(getThis());
     667           1 :         PDO_CONSTRUCT_CHECK;
     668             : 
     669           1 :         if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
     670           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname->val);
     671           0 :                 zend_string_release(cbname);
     672           0 :                 RETURN_FALSE;
     673             :         }
     674           1 :         zend_string_release(cbname);
     675             : 
     676           1 :         H = (pdo_sqlite_db_handle *)dbh->driver_data;
     677             : 
     678           1 :         collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
     679             : 
     680           1 :         ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
     681           1 :         if (ret == SQLITE_OK) {
     682           1 :                 collation->name = estrdup(collation_name);
     683             : 
     684           1 :                 ZVAL_COPY(&collation->callback, callback);
     685             : 
     686           1 :                 collation->next = H->collations;
     687           1 :                 H->collations = collation;
     688             : 
     689           1 :                 RETURN_TRUE;
     690             :         }
     691             : 
     692           0 :         efree(collation);
     693           0 :         RETURN_FALSE;
     694             : }
     695             : /* }}} */
     696             : 
     697             : static const zend_function_entry dbh_methods[] = {
     698             :         PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC)
     699             :         PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC)
     700             :         PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC)
     701             :         PHP_FE_END
     702             : };
     703             : 
     704           7 : static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
     705             : {
     706           7 :         switch (kind) {
     707             :                 case PDO_DBH_DRIVER_METHOD_KIND_DBH:
     708           7 :                         return dbh_methods;
     709             : 
     710             :                 default:
     711           0 :                         return NULL;
     712             :         }
     713             : }
     714             : 
     715           5 : static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh TSRMLS_DC)
     716             : {
     717           5 :         pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
     718             :         /* unregister functions, so that they don't linger for the next
     719             :          * request */
     720           5 :         if (H) {
     721           5 :                 pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
     722             :         }
     723           5 : }
     724             : 
     725             : static struct pdo_dbh_methods sqlite_methods = {
     726             :         sqlite_handle_closer,
     727             :         sqlite_handle_preparer,
     728             :         sqlite_handle_doer,
     729             :         sqlite_handle_quoter,
     730             :         sqlite_handle_begin,
     731             :         sqlite_handle_commit,
     732             :         sqlite_handle_rollback,
     733             :         pdo_sqlite_set_attr,
     734             :         pdo_sqlite_last_insert_id,
     735             :         pdo_sqlite_fetch_error_func,
     736             :         pdo_sqlite_get_attribute,
     737             :         NULL,   /* check_liveness: not needed */
     738             :         get_driver_methods,
     739             :         pdo_sqlite_request_shutdown
     740             : };
     741             : 
     742         164 : static char *make_filename_safe(const char *filename TSRMLS_DC)
     743             : {
     744         164 :         if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
     745          14 :                 char *fullpath = expand_filepath(filename, NULL TSRMLS_CC);
     746             : 
     747          14 :                 if (!fullpath) {
     748           0 :                         return NULL;
     749             :                 }
     750             : 
     751          14 :                 if (php_check_open_basedir(fullpath TSRMLS_CC)) {
     752           0 :                         efree(fullpath);
     753           0 :                         return NULL;
     754             :                 }
     755          14 :                 return fullpath;
     756             :         }
     757         150 :         return estrdup(filename);
     758             : }
     759             : 
     760           0 : static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
     761             :                 const char *arg5, const char *arg6)
     762             : {
     763             :         char *filename;
     764           0 :         switch (access_type) {
     765             :                 case SQLITE_COPY: {
     766             :                         TSRMLS_FETCH();
     767           0 :                         filename = make_filename_safe(arg4 TSRMLS_CC);
     768           0 :                         if (!filename) {
     769           0 :                                 return SQLITE_DENY;
     770             :                         }
     771           0 :                         efree(filename);
     772           0 :                         return SQLITE_OK;
     773             :                 }
     774             : 
     775             :                 case SQLITE_ATTACH: {
     776             :                         TSRMLS_FETCH();
     777           0 :                         filename = make_filename_safe(arg3 TSRMLS_CC);
     778           0 :                         if (!filename) {
     779           0 :                                 return SQLITE_DENY;
     780             :                         }
     781           0 :                         efree(filename);
     782           0 :                         return SQLITE_OK;
     783             :                 }
     784             : 
     785             :                 default:
     786             :                         /* access allowed */
     787           0 :                         return SQLITE_OK;
     788             :         }
     789             : }
     790             : 
     791         164 : static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
     792             : {
     793             :         pdo_sqlite_db_handle *H;
     794         164 :         int i, ret = 0;
     795         164 :         zend_long timeout = 60;
     796             :         char *filename;
     797             : 
     798         166 :         H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
     799             :         
     800         164 :         H->einfo.errcode = 0;
     801         164 :         H->einfo.errmsg = NULL;
     802         164 :         dbh->driver_data = H;
     803             : 
     804         164 :         filename = make_filename_safe(dbh->data_source TSRMLS_CC);
     805             : 
     806         164 :         if (!filename) {
     807           0 :                 zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
     808             :                         "open_basedir prohibits opening %s",
     809             :                         dbh->data_source);
     810           0 :                 goto cleanup;
     811             :         }
     812             : 
     813         164 :         i = sqlite3_open(filename, &H->db);
     814         164 :         efree(filename);
     815             : 
     816         164 :         if (i != SQLITE_OK) {
     817           1 :                 pdo_sqlite_error(dbh);
     818           1 :                 goto cleanup;
     819             :         }
     820             : 
     821         163 :         if (PG(open_basedir) && *PG(open_basedir)) {
     822           0 :                 sqlite3_set_authorizer(H->db, authorizer, NULL);
     823             :         }
     824             : 
     825         163 :         if (driver_options) {
     826           3 :                 timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
     827             :         }
     828         163 :         sqlite3_busy_timeout(H->db, timeout * 1000);
     829             : 
     830         163 :         dbh->alloc_own_columns = 1;
     831         163 :         dbh->max_escaped_char_length = 2;
     832             : 
     833         163 :         ret = 1;
     834             :         
     835             : cleanup:
     836         164 :         dbh->methods = &sqlite_methods;
     837             :         
     838         164 :         return ret;
     839             : }
     840             : /* }}} */
     841             : 
     842             : pdo_driver_t pdo_sqlite_driver = {
     843             :         PDO_DRIVER_HEADER(sqlite),
     844             :         pdo_sqlite_handle_factory
     845             : };
     846             : 
     847             : /*
     848             :  * Local variables:
     849             :  * tab-width: 4
     850             :  * c-basic-offset: 4
     851             :  * End:
     852             :  * vim600: noet sw=4 ts=4 fdm=marker
     853             :  * vim<600: noet sw=4 ts=4
     854             :  */

Generated by: LCOV version 1.10

Generated at Wed, 22 Oct 2014 07:24:54 +0000 (14 hours ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.