Add compat header that allows PDO head to compile against PHP 5.0 and PHP 5.1.
<license>PHP</license>
<release>
<state>beta</state>
- <version>0.9</version>
- <date>2005-07-27</date>
+ <version>1.1dev</version>
+ <date>2005-09-11</date>
<notes>
You need to install a PDO database driver to make use of PDO,
<file role="src" name="pdo_sql_parser.re"/>
<file role="src" name="pdo_sql_parser.c"/>
<file role="src" name="pdo_sqlstate.c"/>
+ <file role="src" name="php_pdo_phpvers_compat.h"/>
<file role="src" name="Makefile.frag"/>
<file role="doc" name="README"/>
return U_CLASS_ENTRY(pdo_exception_ce);
}
+PDO_API char *php_pdo_str_tolower_dup(const char *src, int len)
+{
+ char *dest = emalloc(len + 1);
+ zend_str_tolower_copy(dest, src, len);
+ return dest;
+}
+
zend_class_entry *pdo_dbh_ce, *pdo_dbstmt_ce, *pdo_row_ce;
/* proto array pdo_drivers()
PHP_RINIT(pdo),
PHP_RSHUTDOWN(pdo),
PHP_MINFO(pdo),
- "0.9",
+ "1.1dev",
STANDARD_MODULE_PROPERTIES
};
/* }}} */
le_ppdo = zend_register_list_destructors_ex(NULL, php_pdo_pdbh_dtor,
"PDO persistent database", module_number);
+ REGISTER_LONG_CONSTANT("PDO_PARAM_BOOL", (long)PDO_PARAM_BOOL, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_PARAM_NULL", (long)PDO_PARAM_NULL, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_PARAM_INT", (long)PDO_PARAM_INT, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_PARAM_STR", (long)PDO_PARAM_STR, CONST_CS|CONST_PERSISTENT);
ZVAL_ASCII_STRINGL(&z_key, "queryString", sizeof("queryString")-1, 0);
std_object_handlers.write_property(object, &z_key, query_string TSRMLS_CC);
zval_ptr_dtor(&query_string);
+#ifdef UG
if (UG(unicode)) {
zval_dtor(&z_key);
}
+#endif
if (dbstmt_ce->constructor) {
zend_fcall_info fci;
if (ZEND_NUM_ARGS() > 1 && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(options), PDO_ATTR_STATEMENT_CLASS, (void**)&opt)) {
if (zend_hash_index_find(Z_ARRVAL_PP(opt), 0, (void**)&item) == FAILURE
- || (Z_TYPE_PP(item) != IS_STRING && Z_TYPE_PP(item) != IS_UNICODE)
+ || !PDO_ZVAL_PP_IS_TEXT(item)
|| zend_u_lookup_class(Z_TYPE_PP(item), Z_UNIVAL_PP(item), Z_UNILEN_PP(item), &pce TSRMLS_CC) == FAILURE
) {
pdo_raise_impl_error(dbh, NULL, "HY000",
}
/* }}} */
+/* {{{ proto int PDO::__wakeup()
+ Prevents use of a PDO instance that has been unserialized */
+static PHP_METHOD(PDO, __wakeup)
+{
+ zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "You cannot serialize or unserialize PDO instances");
+}
+/* }}} */
+
+/* {{{ proto int PDO::__sleep()
+ Prevents serialization of a PDO instance */
+static PHP_METHOD(PDO, __sleep)
+{
+ zend_throw_exception_ex(php_pdo_get_exception(TSRMLS_C), 0 TSRMLS_CC, "You cannot serialize or unserialize PDO instances");
+}
+/* }}} */
function_entry pdo_dbh_functions[] = {
PHP_ME_MAPPING(__construct, dbh_constructor, NULL)
PHP_ME(PDO, errorCode, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, errorInfo, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, getAttribute, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(PDO, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
+ PHP_ME(PDO, __sleep, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(PDO, quote, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
zval *object = *object_pp;
#endif
pdo_dbh_t *dbh = zend_object_store_get_object(object TSRMLS_CC);
- zend_uchar ztype = UG(unicode)?IS_UNICODE:IS_STRING;
+#ifdef IS_UNICODE
+ zend_uchar ztype = UG(unicode) ? IS_UNICODE : IS_STRING;
+#endif
lc_method_name = zend_u_str_tolower_dup(ztype, method_name, method_len);
plc->freeq = 0;
break;
- case IS_BOOL:
- convert_to_long(param->parameter);
case IS_LONG:
case IS_DOUBLE:
convert_to_string(param->parameter);
plc->freeq = 0;
break;
+ case IS_BOOL:
+ convert_to_long(param->parameter);
default:
convert_to_string(param->parameter);
if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
case PDO_PARAM_STR:
if (value && !(value_len == 0 && stmt->dbh->oracle_nulls == PDO_NULL_EMPTY_STRING)) {
+#ifdef IS_UNICODE
if (UG(unicode)) {
UErrorCode status = U_ZERO_ERROR;
UChar *u_str;
if (caller_frees) {
efree(value);
}
- } else {
+ } else
+#endif
+ {
ZVAL_STRINGL(dest, value, value_len, !caller_frees);
}
if (caller_frees) {
object = (zval**)Z_ARRVAL_P(callable)->pListHead->pData;
method = (zval**)Z_ARRVAL_P(callable)->pListHead->pListNext->pData;
- if (Z_TYPE_PP(object) == IS_STRING || Z_TYPE_PP(object) == IS_UNICODE) { /* static call */
+ if (PDO_ZVAL_PP_IS_TEXT(object)) { /* static call */
if (zend_u_lookup_class(Z_TYPE_PP(object), Z_UNIVAL_PP(object), Z_UNILEN_PP(object), &pce TSRMLS_CC) == FAILURE) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied class does not exist" TSRMLS_CC);
return 0;
return 0;
}
- if (Z_TYPE_PP(method) != IS_STRING && Z_TYPE_PP(method) != IS_UNICODE) {
+ if (!PDO_ZVAL_PP_IS_TEXT(method)) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied function must be a valid callback; bogus method name" TSRMLS_CC);
return 0;
}
- } else if (Z_TYPE_P(callable) == IS_STRING || Z_TYPE_P(callable) == IS_UNICODE) {
+ } else if (PDO_ZVAL_P_IS_TEXT(callable)) {
method = &callable;
}
/* no break */
case 2:
stmt->fetch.cls.ctor_args = ctor_args; /* we're not going to free these */
- if (Z_TYPE_P(arg2) != IS_STRING && Z_TYPE_P(arg2) != IS_UNICODE) {
+ if (!PDO_ZVAL_P_IS_TEXT(arg2)) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Invalid class name (should be a string)" TSRMLS_CC);
error = 1;
break;
return really_register_bound_param(¶m, stmt, is_param TSRMLS_CC);
} /* }}} */
+/* {{{ proto bool PDOStatement::bindValue(mixed $paramno, mixed $param [, int $type ])
+ bind an input parameter to the value of a PHP variable. $paramno is the 1-based position of the placeholder in the SQL statement (but can be the parameter name for drivers that support named placeholders). It should be called prior to execute(). */
+static PHP_METHOD(PDOStatement, bindValue)
+{
+ pdo_stmt_t *stmt = (pdo_stmt_t*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ struct pdo_bound_param_data param = {0};
+
+ param.paramno = -1;
+ param.param_type = PDO_PARAM_STR;
+
+ if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
+ "lz/|l", ¶m.paramno, ¶m.parameter, ¶m.param_type)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/|l", ¶m.name,
+ ¶m.namelen, ¶m.parameter, ¶m.param_type)) {
+ RETURN_FALSE;
+ }
+ }
+
+ if (param.paramno > 0) {
+ --param.paramno; /* make it zero-based internally */
+ } else if (!param.name) {
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "Columns/Parameters are 1-based" TSRMLS_CC);
+ RETURN_FALSE;
+ }
+
+ RETURN_BOOL(really_register_bound_param(¶m, stmt, TRUE TSRMLS_CC));
+}
+/* }}} */
+
+
/* {{{ proto bool PDOStatement::bindParam(mixed $paramno, mixed &$param [, int $type [, int $maxlen [, mixed $driverdata]]])
bind a parameter to a PHP variable. $paramno is the 1-based position of the placeholder in the SQL statement (but can be the parameter name for drivers that support named placeholders). This isn't supported by all drivers. It should be called prior to execute(). */
static PHP_METHOD(PDOStatement, bindParam)
case PDO_FETCH_BOTH:
case PDO_FETCH_OBJ:
case PDO_FETCH_BOUND:
+ case PDO_FETCH_NAMED:
break;
case PDO_FETCH_COLUMN:
break;
default:
- pdo_raise_impl_error(stmt->dbh, stmt, "22003", "mode is out of range" TSRMLS_CC);
+ if ((mode & ~PDO_FETCH_FLAGS) < PDO_FETCH__MAX && (mode & ~PDO_FETCH_FLAGS) >= 0) {
+ pdo_raise_impl_error(stmt->dbh, stmt, "22003", "unhandled mode; this is a PDO bug, please report it" TSRMLS_CC);
+ } else {
+ pdo_raise_impl_error(stmt->dbh, stmt, "22003", "mode is out of range" TSRMLS_CC);
+ }
return FAILURE;
}
}
/* }}} */
+/* {{{ proto int PDOStatement::__wakeup()
+ Prevents use of a PDOStatement instance that has been unserialized */
+static PHP_METHOD(PDOStatement, __wakeup)
+{
+ zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "You cannot serialize or unserialize PDOStatement instances");
+}
+/* }}} */
+
+/* {{{ proto int PDOStatement::__sleep()
+ Prevents serialization of a PDOStatement instance */
+static PHP_METHOD(PDOStatement, __sleep)
+{
+ zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "You cannot serialize or unserialize PDOStatement instances");
+}
+/* }}} */
function_entry pdo_dbstmt_functions[] = {
PHP_ME(PDOStatement, execute, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, fetch, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, bindParam, second_arg_force_ref, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, bindColumn, second_arg_force_ref, ZEND_ACC_PUBLIC)
+ PHP_ME(PDOStatement, bindValue, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, rowCount, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, fetchColumn, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, fetchAll, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, nextRowset, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, closeCursor, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDOStatement, debugDumpParams, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(PDOStatement, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
+ PHP_ME(PDOStatement, __sleep, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
{NULL, NULL, NULL}
};
convert_to_text(member);
- if ((Z_UNILEN_P(member) == sizeof("queryString")-1) && (ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "queryString", sizeof("queryString")-1))) {
+ if (PDO_MEMBER_IS(member, "queryString")) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only" TSRMLS_CC);
} else {
std_object_handlers.write_property(object, member, value TSRMLS_CC);
convert_to_text(member);
- if ((Z_UNILEN_P(member) == sizeof("queryString")-1) && (ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "queryString", sizeof("queryString")-1))) {
+ if (PDO_MEMBER_IS(member, "queryString")) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only" TSRMLS_CC);
} else {
std_object_handlers.unset_property(object, member TSRMLS_CC);
#if PHP_API_VERSION >= 20041225
zval *object = *object_pp;
#endif
- zend_uchar ztype = UG(unicode)?IS_UNICODE:IS_STRING;
+#ifdef IS_UNICODE
+ zend_uchar ztype = UG(unicode) ? IS_UNICODE : IS_STRING;
+#endif
lc_method_name = zend_u_str_tolower_dup(ztype, method_name, method_len);
/* $Id$ */
+#include "php_pdo_phpvers_compat.h"
+
/* Stuff private to the PDO extension and not for consumption by PDO drivers
* */
extern zend_class_entry *pdo_exception_ce;
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2005 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Wez Furlong <wez@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+/* macros for backwards compatibility with PHP 5, so that HEAD of PDO and its
+ * drivers may still build against PHP 5 */
+
+#ifndef PHP_PDO_PHPVERS_COMPAT_H
+# define PHP_PDO_PHPVERS_COMPAT_H
+# if PHP_MAJOR_VERSION < 6
+
+# define ZVAL_RT_STRINGL(a, b, c, d) ZVAL_STRINGL(a, b, c, d)
+# define ZVAL_ASCII_STRINGL(a, b, c, d) ZVAL_STRINGL(a, b, c, d)
+# define U_CLASS_ENTRY(ce) ce
+# define PDO_ZVAL_PP_IS_TEXT(pp) (Z_TYPE_PP(pp) == IS_STRING)
+# define PDO_ZVAL_P_IS_TEXT(pp) (Z_TYPE_P(pp) == IS_STRING)
+# define Z_UNIVAL_PP(x) Z_STRVAL_PP(x)
+# define Z_UNIVAL_P(x) Z_STRVAL_P(x)
+# define Z_UNIVAL(x) Z_STRVAL(x)
+# define Z_UNILEN_PP(x) Z_STRLEN_PP(x)
+# define Z_UNILEN_P(x) Z_STRLEN_P(x)
+# define Z_UNILEN(x) Z_STRLEN(x)
+# define zend_u_hash_find(a, b, c, d, e) zend_hash_find(a, c, d, e)
+# define zend_u_lookup_class(a, b, c, d) zend_lookup_class(b, c, d)
+PDO_API char *php_pdo_str_tolower_dup(const char *src, int len);
+# define zend_u_str_tolower_dup(a, b, c) php_pdo_str_tolower_dup(b, c)
+# define convert_to_text(x) convert_to_string(x)
+# define zend_u_fetch_class(a, b, c, d) zend_fetch_class(b, c, d)
+# define PDO_MEMBER_IS(z, strlit) ((Z_STRLEN_P(z) == sizeof(strlit)-1) && 0 == strcmp(Z_STRVAL_P(z), strlit))
+
+# else
+
+# define PDO_ZVAL_PP_IS_TEXT(pp) ((Z_TYPE_PP(pp) == IS_STRING) || (Z_TYPE_PP(pp) == IS_UNICODE))
+# define PDO_ZVAL_P_IS_TEXT(pp) ((Z_TYPE_P(pp) == IS_STRING) || (Z_TYPE_P(pp) == IS_UNICODE))
+
+# define PDO_MEMBER_IS(z, strlit) ((Z_UNILEN_P(z) == sizeof(strlit)-1) && (ZEND_U_EQUAL(Z_TYPE_P(z), Z_UNIVAL_P(z), Z_UNILEN_P(z), strlit, sizeof(strlit)-1)))
+
+# endif
+#endif
+
--- /dev/null
+--TEST--
+PDO Common: PECL Bug #5217: serialize/unserialze safety
+--SKIPIF--
+<?php # vim:ft=php
+if (!extension_loaded('pdo')) die('skip');
+$dir = getenv('REDIR_TEST_DIR');
+if (false == $dir) die('skip no driver');
+require_once $dir . 'pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
+$db = PDOTest::factory();
+try {
+ $ser = serialize($db);
+ debug_zval_dump($ser);
+ $db = unserialize($ser);
+ $db->exec('CREATE TABLE test (id int NOT NULL PRIMARY KEY, val VARCHAR(10))');
+} catch (Exception $e) {
+ echo "Safely caught " . $e->getMessage() . "\n";
+}
+
+echo "PHP Didn't crash!\n";
+?>
+--EXPECT--
+Safely caught You cannot serialize or unserialize PDO instances
+PHP Didn't crash!