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

Generated by: LCOV version 1.10

Generated at Wed, 24 Aug 2016 12:20:27 +0000 (3 days ago)

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