Annotation of embedaddon/php/ext/sqlite/pdo_sqlite2.c, revision 1.1.1.1
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2012 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: pdo_sqlite2.c 321634 2012-01-01 13:15:04Z felipe $ */
20: #ifdef HAVE_CONFIG_H
21: #include "config.h"
22: #endif
23: #include "php.h"
24:
25: #ifdef PHP_SQLITE2_HAVE_PDO
26: #include "sqlite.h"
27: #include "pdo/php_pdo.h"
28: #include "pdo/php_pdo_driver.h"
29: #include "zend_exceptions.h"
30:
31: #define php_sqlite_encode_binary(in, n, out) sqlite_encode_binary((const unsigned char *)in, n, (unsigned char *)out)
32: #define php_sqlite_decode_binary(in, out) sqlite_decode_binary((const unsigned char *)in, (unsigned char *)out)
33:
34:
35: typedef struct {
36: const char *file;
37: int line;
38: unsigned int errcode;
39: char *errmsg;
40: } pdo_sqlite2_error_info;
41:
42: typedef struct {
43: sqlite *db;
44: pdo_sqlite2_error_info einfo;
45: } pdo_sqlite2_db_handle;
46:
47: typedef struct {
48: pdo_sqlite2_db_handle *H;
49: sqlite_vm *vm;
50: const char **rowdata, **colnames;
51: int ncols;
52: unsigned pre_fetched:1;
53: unsigned done:1;
54: pdo_sqlite2_error_info einfo;
55: } pdo_sqlite2_stmt;
56:
57: extern int _pdo_sqlite2_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *errmsg, const char *file, int line TSRMLS_DC);
58: #define pdo_sqlite2_error(msg, s) _pdo_sqlite2_error(s, NULL, msg, __FILE__, __LINE__ TSRMLS_CC)
59: #define pdo_sqlite2_error_stmt(msg, s) _pdo_sqlite2_error(stmt->dbh, stmt, msg, __FILE__, __LINE__ TSRMLS_CC)
60:
61: extern struct pdo_stmt_methods sqlite2_stmt_methods;
62:
63: static int pdo_sqlite2_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC)
64: {
65: pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
66:
67: if (S->vm) {
68: char *errmsg = NULL;
69: sqlite_finalize(S->vm, &errmsg);
70: if (errmsg) {
71: sqlite_freemem(errmsg);
72: }
73: S->vm = NULL;
74: }
75: if (S->einfo.errmsg) {
76: pefree(S->einfo.errmsg, stmt->dbh->is_persistent);
77: }
78: efree(S);
79: return 1;
80: }
81:
82: static int pdo_sqlite2_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
83: {
84: pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
85: char *errmsg = NULL;
86: const char *tail;
87:
88: if (stmt->executed && !S->done) {
89: sqlite_finalize(S->vm, &errmsg);
90: pdo_sqlite2_error_stmt(errmsg, stmt);
91: errmsg = NULL;
92: S->vm = NULL;
93: }
94:
95: S->einfo.errcode = sqlite_compile(S->H->db, stmt->active_query_string, &tail, &S->vm, &errmsg);
96: if (S->einfo.errcode != SQLITE_OK) {
97: pdo_sqlite2_error_stmt(errmsg, stmt);
98: return 0;
99: }
100:
101: S->done = 0;
102: S->einfo.errcode = sqlite_step(S->vm, &S->ncols, &S->rowdata, &S->colnames);
103: switch (S->einfo.errcode) {
104: case SQLITE_ROW:
105: S->pre_fetched = 1;
106: stmt->column_count = S->ncols;
107: return 1;
108:
109: case SQLITE_DONE:
110: stmt->column_count = S->ncols;
111: stmt->row_count = sqlite_changes(S->H->db);
112: S->einfo.errcode = sqlite_reset(S->vm, &errmsg);
113: if (S->einfo.errcode != SQLITE_OK) {
114: pdo_sqlite2_error_stmt(errmsg, stmt);
115: }
116: S->done = 1;
117: return 1;
118:
119: case SQLITE_ERROR:
120: case SQLITE_MISUSE:
121: case SQLITE_BUSY:
122: default:
123: pdo_sqlite2_error_stmt(errmsg, stmt);
124: return 0;
125: }
126: }
127:
128: static int pdo_sqlite2_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
129: enum pdo_param_event event_type TSRMLS_DC)
130: {
131: return 1;
132: }
133:
134: static int pdo_sqlite2_stmt_fetch(pdo_stmt_t *stmt,
135: enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
136: {
137: pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
138: char *errmsg = NULL;
139:
140: if (!S->vm) {
141: return 0;
142: }
143: if (S->pre_fetched) {
144: S->pre_fetched = 0;
145: return 1;
146: }
147: if (S->done) {
148: return 0;
149: }
150:
151: S->einfo.errcode = sqlite_step(S->vm, &S->ncols, &S->rowdata, &S->colnames);
152: switch (S->einfo.errcode) {
153: case SQLITE_ROW:
154: return 1;
155:
156: case SQLITE_DONE:
157: S->done = 1;
158: S->einfo.errcode = sqlite_reset(S->vm, &errmsg);
159: if (S->einfo.errcode != SQLITE_OK) {
160: pdo_sqlite2_error_stmt(errmsg, stmt);
161: errmsg = NULL;
162: }
163: return 0;
164:
165: default:
166: pdo_sqlite2_error_stmt(errmsg, stmt);
167: return 0;
168: }
169: }
170:
171: static int pdo_sqlite2_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC)
172: {
173: pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
174:
175: if(colno >= S->ncols) {
176: /* error invalid column */
177: pdo_sqlite2_error_stmt(NULL, stmt);
178: return 0;
179: }
180:
181: stmt->columns[colno].name = estrdup(S->colnames[colno]);
182: stmt->columns[colno].namelen = strlen(stmt->columns[colno].name);
183: stmt->columns[colno].maxlen = 0xffffffff;
184: stmt->columns[colno].precision = 0;
185: stmt->columns[colno].param_type = PDO_PARAM_STR;
186:
187: return 1;
188: }
189:
190: static int pdo_sqlite2_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC)
191: {
192: pdo_sqlite2_stmt *S = (pdo_sqlite2_stmt*)stmt->driver_data;
193: if (!S->vm) {
194: return 0;
195: }
196: if(colno >= S->ncols) {
197: /* error invalid column */
198: pdo_sqlite2_error_stmt(NULL, stmt);
199: return 0;
200: }
201: if (S->rowdata[colno]) {
202: if (S->rowdata[colno][0] == '\x01') {
203: /* encoded */
204: *caller_frees = 1;
205: *ptr = emalloc(strlen(S->rowdata[colno]));
206: *len = php_sqlite_decode_binary(S->rowdata[colno]+1, *ptr);
207: (*(char**)ptr)[*len] = '\0';
208: } else {
209: *ptr = (char*)S->rowdata[colno];
210: *len = strlen(*ptr);
211: }
212: } else {
213: *ptr = NULL;
214: *len = 0;
215: }
216: return 1;
217: }
218:
219: struct pdo_stmt_methods sqlite2_stmt_methods = {
220: pdo_sqlite2_stmt_dtor,
221: pdo_sqlite2_stmt_execute,
222: pdo_sqlite2_stmt_fetch,
223: pdo_sqlite2_stmt_describe,
224: pdo_sqlite2_stmt_get_col,
225: pdo_sqlite2_stmt_param_hook,
226: NULL, /* set_attr */
227: NULL, /* get_attr */
228: NULL
229: };
230:
231:
232: int _pdo_sqlite2_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *errmsg, const char *file, int line TSRMLS_DC) /* {{{ */
233: {
234: pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
235: pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
236: pdo_sqlite2_error_info *einfo = &H->einfo;
237: pdo_sqlite2_stmt *S;
238:
239: if (stmt) {
240: S = stmt->driver_data;
241: einfo = &S->einfo;
242: }
243:
244: einfo->file = file;
245: einfo->line = line;
246:
247: if (einfo->errmsg) {
248: pefree(einfo->errmsg, dbh->is_persistent);
249: einfo->errmsg = NULL;
250: }
251:
252: if (einfo->errcode != SQLITE_OK) {
253: if (errmsg) {
254: einfo->errmsg = pestrdup(errmsg, dbh->is_persistent);
255: sqlite_freemem(errmsg);
256: } else {
257: einfo->errmsg = pestrdup(sqlite_error_string(einfo->errcode), dbh->is_persistent);
258: }
259: } else { /* no error */
260: strcpy(*pdo_err, PDO_ERR_NONE);
261: return 0;
262: }
263: switch (einfo->errcode) {
264: case SQLITE_NOTFOUND:
265: strcpy(*pdo_err, "42S02");
266: break;
267:
268: case SQLITE_INTERRUPT:
269: strcpy(*pdo_err, "01002");
270: break;
271:
272: case SQLITE_NOLFS:
273: strcpy(*pdo_err, "HYC00");
274: break;
275:
276: case SQLITE_TOOBIG:
277: strcpy(*pdo_err, "22001");
278: break;
279:
280: case SQLITE_CONSTRAINT:
281: strcpy(*pdo_err, "23000");
282: break;
283:
284: case SQLITE_ERROR:
285: default:
286: strcpy(*pdo_err, "HY000");
287: break;
288: }
289:
290: if (!dbh->methods) {
291: zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
292: *pdo_err, einfo->errcode, einfo->errmsg);
293: }
294:
295: return einfo->errcode;
296: }
297: /* }}} */
298:
299: static int pdo_sqlite2_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
300: {
301: pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
302: pdo_sqlite2_error_info *einfo = &H->einfo;
303: pdo_sqlite2_stmt *S;
304:
305: if (stmt) {
306: S = stmt->driver_data;
307: einfo = &S->einfo;
308: }
309:
310: if (einfo->errcode) {
311: add_next_index_long(info, einfo->errcode);
312: if (einfo->errmsg) {
313: add_next_index_string(info, einfo->errmsg, 1);
314: }
315: }
316:
317: return 1;
318: }
319:
320: static int sqlite2_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
321: {
322: pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
323:
324: if (H) {
325: if (H->db) {
326: sqlite_close(H->db);
327: H->db = NULL;
328: }
329: if (H->einfo.errmsg) {
330: pefree(H->einfo.errmsg, dbh->is_persistent);
331: H->einfo.errmsg = NULL;
332: }
333: pefree(H, dbh->is_persistent);
334: dbh->driver_data = NULL;
335: }
336: return 0;
337: }
338: /* }}} */
339:
340: static int sqlite2_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
341: {
342: pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
343: pdo_sqlite2_stmt *S = ecalloc(1, sizeof(pdo_sqlite2_stmt));
344:
345: S->H = H;
346: stmt->driver_data = S;
347: stmt->methods = &sqlite2_stmt_methods;
348: stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
349:
350: if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC)) {
351: H->einfo.errcode = SQLITE_ERROR;
352: pdo_sqlite2_error(NULL, dbh);
353: return 0;
354: }
355:
356: return 1;
357: }
358:
359: static long sqlite2_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
360: {
361: pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
362: char *errmsg = NULL;
363:
364: if ((H->einfo.errcode = sqlite_exec(H->db, sql, NULL, NULL, &errmsg)) != SQLITE_OK) {
365: pdo_sqlite2_error(errmsg, dbh);
366: return -1;
367: } else {
368: return sqlite_changes(H->db);
369: }
370: }
371:
372: static char *pdo_sqlite2_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
373: {
374: pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
375: char *id;
376:
377: id = php_pdo_int64_to_str(sqlite_last_insert_rowid(H->db) TSRMLS_CC);
378: *len = strlen(id);
379: return id;
380: }
381:
382: static int sqlite2_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype TSRMLS_DC)
383: {
384: char *ret;
385:
386: if (unquotedlen && (unquoted[0] == '\x01' || memchr(unquoted, '\0', unquotedlen) != NULL)) {
387: /* binary string */
388: int len;
389: ret = safe_emalloc(1 + unquotedlen / 254, 257, 5);
390: ret[0] = '\'';
391: ret[1] = '\x01';
392: len = php_sqlite_encode_binary(unquoted, unquotedlen, ret+2);
393: ret[len + 2] = '\'';
394: ret[len + 3] = '\0';
395: *quoted = ret;
396: *quotedlen = len + 3;
397: /* fprintf(stderr, "Quoting:%d:%.*s:\n", *quotedlen, *quotedlen, *quoted); */
398: return 1;
399: } else if (unquotedlen) {
400: ret = sqlite_mprintf("'%q'", unquoted);
401: if (ret) {
402: *quoted = estrdup(ret);
403: *quotedlen = strlen(ret);
404: sqlite_freemem(ret);
405: return 1;
406: }
407: return 0;
408: } else {
409: *quoted = estrdup("''");
410: *quotedlen = 2;
411: return 1;
412: }
413: }
414:
415: static int sqlite2_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
416: {
417: pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
418: char *errmsg = NULL;
419:
420: if (sqlite_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
421: pdo_sqlite2_error(errmsg, dbh);
422: return 0;
423: }
424: return 1;
425: }
426:
427: static int sqlite2_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
428: {
429: pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
430: char *errmsg = NULL;
431:
432: if (sqlite_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
433: pdo_sqlite2_error(errmsg, dbh);
434: return 0;
435: }
436: return 1;
437: }
438:
439: static int sqlite2_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
440: {
441: pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
442: char *errmsg = NULL;
443:
444: if (sqlite_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
445: pdo_sqlite2_error(errmsg, dbh);
446: return 0;
447: }
448: return 1;
449: }
450:
451: static int pdo_sqlite2_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC)
452: {
453: switch (attr) {
454: case PDO_ATTR_CLIENT_VERSION:
455: case PDO_ATTR_SERVER_VERSION:
456: ZVAL_STRING(return_value, (char *)sqlite_libversion(), 1);
457: break;
458:
459: default:
460: return 0;
461: }
462:
463: return 1;
464: }
465:
466: static int pdo_sqlite2_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
467: {
468: pdo_sqlite2_db_handle *H = (pdo_sqlite2_db_handle *)dbh->driver_data;
469:
470: switch (attr) {
471: case PDO_ATTR_TIMEOUT:
472: convert_to_long(val);
473: sqlite_busy_timeout(H->db, Z_LVAL_P(val) * 1000);
474: return 1;
475: }
476: return 0;
477: }
478:
479: static PHP_FUNCTION(sqlite2_create_function)
480: {
481: /* TODO: implement this stuff */
482: }
483:
484: static const zend_function_entry dbh_methods[] = {
485: PHP_FE(sqlite2_create_function, NULL)
486: {NULL, NULL, NULL}
487: };
488:
489: static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
490: {
491: switch (kind) {
492: case PDO_DBH_DRIVER_METHOD_KIND_DBH:
493: return dbh_methods;
494:
495: default:
496: return NULL;
497: }
498: }
499:
500: static struct pdo_dbh_methods sqlite2_methods = {
501: sqlite2_handle_closer,
502: sqlite2_handle_preparer,
503: sqlite2_handle_doer,
504: sqlite2_handle_quoter,
505: sqlite2_handle_begin,
506: sqlite2_handle_commit,
507: sqlite2_handle_rollback,
508: pdo_sqlite2_set_attr,
509: pdo_sqlite2_last_insert_id,
510: pdo_sqlite2_fetch_error_func,
511: pdo_sqlite2_get_attribute,
512: NULL, /* check_liveness: not needed */
513: get_driver_methods
514: };
515:
516: static char *make_filename_safe(const char *filename TSRMLS_DC)
517: {
518: if (*filename && strncmp(filename, ":memory:", sizeof(":memory:")-1)) {
519: char *fullpath = expand_filepath(filename, NULL TSRMLS_CC);
520:
521: if (!fullpath) {
522: return NULL;
523: }
524:
525: if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
526: efree(fullpath);
527: return NULL;
528: }
529:
530: if (php_check_open_basedir(fullpath TSRMLS_CC)) {
531: efree(fullpath);
532: return NULL;
533: }
534: return fullpath;
535: }
536: return estrdup(filename);
537: }
538:
539: static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
540: const char *arg5, const char *arg6)
541: {
542: char *filename;
543: switch (access_type) {
544: case SQLITE_COPY: {
545: TSRMLS_FETCH();
546: filename = make_filename_safe(arg4 TSRMLS_CC);
547: if (!filename) {
548: return SQLITE_DENY;
549: }
550: efree(filename);
551: return SQLITE_OK;
552: }
553:
554: case SQLITE_ATTACH: {
555: TSRMLS_FETCH();
556: filename = make_filename_safe(arg3 TSRMLS_CC);
557: if (!filename) {
558: return SQLITE_DENY;
559: }
560: efree(filename);
561: return SQLITE_OK;
562: }
563:
564: default:
565: /* access allowed */
566: return SQLITE_OK;
567: }
568: }
569:
570: static int pdo_sqlite2_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
571: {
572: pdo_sqlite2_db_handle *H;
573: int ret = 0;
574: long timeout = 60;
575: char *filename;
576: char *errmsg = NULL;
577:
578: H = pecalloc(1, sizeof(pdo_sqlite2_db_handle), dbh->is_persistent);
579:
580: H->einfo.errcode = 0;
581: H->einfo.errmsg = NULL;
582: dbh->driver_data = H;
583:
584: filename = make_filename_safe(dbh->data_source TSRMLS_CC);
585:
586: if (!filename) {
587: zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
588: "safe_mode/open_basedir prohibits opening %s",
589: dbh->data_source);
590: goto cleanup;
591: }
592:
593: H->db = sqlite_open(filename, 0666, &errmsg);
594: efree(filename);
595:
596: if (!H->db) {
597: H->einfo.errcode = SQLITE_ERROR;
598: pdo_sqlite2_error(errmsg, dbh);
599: goto cleanup;
600: }
601:
602: sqlite_set_authorizer(H->db, authorizer, NULL);
603:
604: if (driver_options) {
605: timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
606: }
607: sqlite_busy_timeout(H->db, timeout * 1000);
608:
609: dbh->alloc_own_columns = 1;
610: dbh->max_escaped_char_length = 2;
611:
612: ret = 1;
613:
614: cleanup:
615: dbh->methods = &sqlite2_methods;
616:
617: return ret;
618: }
619: /* }}} */
620:
621: pdo_driver_t pdo_sqlite2_driver = {
622: PDO_DRIVER_HEADER(sqlite2),
623: pdo_sqlite2_handle_factory
624: };
625:
626:
627:
628: #endif
629:
630:
631: /*
632: * Local variables:
633: * tab-width: 4
634: * c-basic-offset: 4
635: * End:
636: * vim600: noet sw=4 ts=4 fdm=marker
637: * vim<600: noet sw=4 ts=4
638: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>