зеркало из https://github.com/microsoft/msphpsql.git
Update how PHP drivers handle Encrypt keyword
This commit is contained in:
Родитель
1a45ee10e2
Коммит
dad6e4c245
|
@ -125,7 +125,7 @@ struct pdo_int_conn_str_func {
|
|||
|
||||
static void func( _In_ connection_option const* option, _In_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str )
|
||||
{
|
||||
SQLSRV_ASSERT( Z_TYPE_P( value ) == IS_STRING, "Wrong zval type for this keyword" )
|
||||
SQLSRV_ASSERT(Z_TYPE_P(value) == IS_STRING, "Wrong zval type for this keyword");
|
||||
|
||||
std::string val_str = Z_STRVAL_P( value );
|
||||
|
||||
|
@ -136,6 +136,42 @@ struct pdo_int_conn_str_func {
|
|||
}
|
||||
};
|
||||
|
||||
struct pdo_encrypt_set_func
|
||||
{
|
||||
static void func(_In_ connection_option const* option, _Inout_ zval* value_z, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str)
|
||||
{
|
||||
SQLSRV_ASSERT(Z_TYPE_P(value_z) == IS_STRING, "Wrong zval type for this keyword");
|
||||
std::string val_str = Z_STRVAL_P(value_z);
|
||||
std::string whitespaces(" \t\f\v\n\r");
|
||||
|
||||
// Trim white spaces
|
||||
std::size_t found = val_str.find_last_not_of(whitespaces);
|
||||
if (found != std::string::npos)
|
||||
val_str.erase(found + 1);
|
||||
|
||||
const char TRUE_VALUE_1[] = "true";
|
||||
const char TRUE_VALUE_2[] = "1";
|
||||
const char FALSE_VALUE_1[] = "false";
|
||||
const char FALSE_VALUE_2[] = "0";
|
||||
|
||||
// For backward compatibility, convert true/1 to yes and false/0 to no
|
||||
std::string attr;
|
||||
if (!val_str.compare(TRUE_VALUE_1) || !val_str.compare(TRUE_VALUE_2)) {
|
||||
attr = "yes";
|
||||
} else if (!val_str.compare(FALSE_VALUE_1) || !val_str.compare(FALSE_VALUE_2)) {
|
||||
attr = "no";
|
||||
} else {
|
||||
// simply pass the attribute value to ODBC driver
|
||||
attr = val_str;
|
||||
}
|
||||
|
||||
conn_str += option->odbc_name;
|
||||
conn_str += "={";
|
||||
conn_str += attr;
|
||||
conn_str += "};";
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned int Attr>
|
||||
struct pdo_int_conn_attr_func {
|
||||
|
||||
|
@ -303,8 +339,8 @@ const connection_option PDO_CONN_OPTS[] = {
|
|||
SQLSRV_CONN_OPTION_ENCRYPT,
|
||||
ODBCConnOptions::Encrypt,
|
||||
sizeof( ODBCConnOptions::Encrypt ),
|
||||
CONN_ATTR_BOOL,
|
||||
pdo_bool_conn_str_func::func
|
||||
CONN_ATTR_MIXED,
|
||||
pdo_encrypt_set_func::func
|
||||
},
|
||||
{
|
||||
PDOConnOptionNames::Failover_Partner,
|
||||
|
|
|
@ -1124,34 +1124,22 @@ void ce_akv_str_set_func::func(_In_ connection_option const* option, _In_ zval*
|
|||
// Values = ("true" or "1") are treated as true values. Everything else is treated as false.
|
||||
// Returns 1 for true and 0 for false.
|
||||
|
||||
size_t core_str_zval_is_true( _Inout_ zval* value_z )
|
||||
size_t core_str_zval_is_true(_Inout_ zval* value_z)
|
||||
{
|
||||
SQLSRV_ASSERT( Z_TYPE_P( value_z ) == IS_STRING, "core_str_zval_is_true: This function only accepts zval of type string." );
|
||||
std::string val_str = Z_STRVAL_P(value_z);
|
||||
std::string whitespaces(" \t\f\v\n\r");
|
||||
|
||||
char* value_in = Z_STRVAL_P( value_z );
|
||||
size_t val_len = Z_STRLEN_P( value_z );
|
||||
// Trim white spaces
|
||||
std::size_t found = val_str.find_last_not_of(whitespaces);
|
||||
if (found != std::string::npos)
|
||||
val_str.erase(found + 1);
|
||||
|
||||
// strip any whitespace at the end (whitespace is the same value in ASCII and UTF-8)
|
||||
size_t last_char = val_len - 1;
|
||||
while( isspace(( unsigned char )value_in[last_char] )) {
|
||||
value_in[last_char] = '\0';
|
||||
val_len = last_char;
|
||||
--last_char;
|
||||
const char TRUE_VALUE_1[] = "true";
|
||||
const char TRUE_VALUE_2[] = "1";
|
||||
if (!val_str.compare(TRUE_VALUE_1) || !val_str.compare(TRUE_VALUE_2)) {
|
||||
return 1; // true
|
||||
}
|
||||
|
||||
// save adjustments to the value made by stripping whitespace at the end
|
||||
Z_STRLEN_P( value_z ) = val_len;
|
||||
|
||||
const char VALID_TRUE_VALUE_1[] = "true";
|
||||
const char VALID_TRUE_VALUE_2[] = "1";
|
||||
|
||||
if(( val_len == ( sizeof( VALID_TRUE_VALUE_1 ) - 1 ) && !strnicmp( value_in, VALID_TRUE_VALUE_1, val_len )) ||
|
||||
( val_len == ( sizeof( VALID_TRUE_VALUE_2 ) - 1 ) && !strnicmp( value_in, VALID_TRUE_VALUE_2, val_len ))
|
||||
) {
|
||||
|
||||
return 1; // true
|
||||
}
|
||||
|
||||
return 0; // false
|
||||
}
|
||||
|
||||
|
|
|
@ -1215,6 +1215,7 @@ enum CONN_ATTR_TYPE {
|
|||
CONN_ATTR_INT,
|
||||
CONN_ATTR_BOOL,
|
||||
CONN_ATTR_STRING,
|
||||
CONN_ATTR_MIXED,
|
||||
CONN_ATTR_INVALID,
|
||||
};
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ struct format_decimals_func
|
|||
|
||||
struct decimal_places_func
|
||||
{
|
||||
|
||||
static void func(connection_option const* /*option*/, _In_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/)
|
||||
{
|
||||
// first check if the input is an integer
|
||||
|
@ -73,6 +72,33 @@ struct decimal_places_func
|
|||
}
|
||||
};
|
||||
|
||||
struct srv_encrypt_set_func {
|
||||
static void func(connection_option const* option, _In_ zval* value_z, _Inout_ sqlsrv_conn* conn, std::string& conn_str)
|
||||
{
|
||||
std::string attr;
|
||||
|
||||
if (Z_TYPE_P(value_z) == IS_LONG) {
|
||||
long val = Z_LVAL_P(value_z);
|
||||
if (val == 1) {
|
||||
attr = "yes";
|
||||
} else if (val == 0) {
|
||||
attr = "no";
|
||||
} else {
|
||||
attr = std::to_string(val);
|
||||
}
|
||||
} else if (Z_TYPE_P(value_z) == IS_TRUE || Z_TYPE_P(value_z) == IS_FALSE) {
|
||||
attr = zend_is_true(value_z) ? "yes" : "no";
|
||||
} else {
|
||||
attr = Z_STRVAL_P(value_z);
|
||||
}
|
||||
|
||||
char temp_str[MAX_CONN_VALSTRING_LEN];
|
||||
snprintf(temp_str, MAX_CONN_VALSTRING_LEN, "%s={%s};", option->odbc_name, attr.c_str());
|
||||
|
||||
conn_str += temp_str;
|
||||
}
|
||||
};
|
||||
|
||||
struct conn_char_set_func {
|
||||
|
||||
static void func( connection_option const* /*option*/, _Inout_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ )
|
||||
|
@ -421,8 +447,8 @@ const connection_option SS_CONN_OPTS[] = {
|
|||
SQLSRV_CONN_OPTION_ENCRYPT,
|
||||
ODBCConnOptions::Encrypt,
|
||||
sizeof( ODBCConnOptions::Encrypt ),
|
||||
CONN_ATTR_BOOL,
|
||||
bool_conn_str_func::func
|
||||
CONN_ATTR_MIXED,
|
||||
srv_encrypt_set_func::func
|
||||
},
|
||||
{
|
||||
SSConnOptionNames::Failover_Partner,
|
||||
|
@ -1336,6 +1362,8 @@ int get_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In
|
|||
// if we ever introduce a boolean connection option that maps to a string connection
|
||||
// attribute.
|
||||
break;
|
||||
case CONN_ATTR_MIXED:
|
||||
break;
|
||||
case CONN_ATTR_INT:
|
||||
{
|
||||
CHECK_CUSTOM_ERROR( (Z_TYPE_P( value_z ) != IS_LONG ), ctx, SQLSRV_ERROR_INVALID_OPTION_TYPE_INT,
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
--TEST--
|
||||
Test various encrypt attributes
|
||||
--SKIPIF--
|
||||
<?php require('skipif.inc');?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once 'MsSetup.inc';
|
||||
|
||||
try {
|
||||
$encrypt = ' true ';
|
||||
$trust = 'true ';
|
||||
$connectionInfo = "Database = $databaseName; Encrypt = $encrypt; TrustServerCertificate = $trust;";
|
||||
$conn1 = new PDO("sqlsrv:server = $server ; $connectionInfo", $uid, $pwd);
|
||||
echo 'Test case 1' . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
echo 'Failed to connect (test case 1)' . PHP_EOL;
|
||||
print_r($e->getMessage());
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
unset($conn1);
|
||||
|
||||
try {
|
||||
$encrypt = ' 1 ';
|
||||
$trust = 'true ';
|
||||
$connectionInfo = "Database = $databaseName; Encrypt = $encrypt; TrustServerCertificate = $trust;";
|
||||
$conn2 = new PDO("sqlsrv:server = $server ; $connectionInfo", $uid, $pwd);
|
||||
echo 'Test case 2' . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
echo 'Failed to connect (test case 2)' . PHP_EOL;
|
||||
print_r($e->getMessage());
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
unset($conn2);
|
||||
|
||||
try {
|
||||
$encrypt = ' yes ';
|
||||
$trust = 'true';
|
||||
$connectionInfo = "Database = $databaseName; Encrypt = $encrypt; TrustServerCertificate = $trust;";
|
||||
$conn3 = new PDO("sqlsrv:server = $server ; $connectionInfo", $uid, $pwd);
|
||||
echo 'Test case 3' . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
echo 'Failed to connect (test case 3)' . PHP_EOL;
|
||||
print_r($e->getMessage());
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
unset($conn3);
|
||||
|
||||
try {
|
||||
$encrypt = ' 0 ';
|
||||
$trust = 'false ';
|
||||
$connectionInfo = "Database = $databaseName; Encrypt = $encrypt; TrustServerCertificate = $trust;";
|
||||
$conn4 = new PDO("sqlsrv:server = $server ; $connectionInfo", $uid, $pwd);
|
||||
echo 'Test case 4' . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
echo 'Failed to connect (test case 4)' . PHP_EOL;
|
||||
print_r($e->getMessage());
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
unset($conn4);
|
||||
|
||||
try {
|
||||
$encrypt = ' false ';
|
||||
$trust = 'false ';
|
||||
$connectionInfo = "Database = $databaseName; Encrypt = $encrypt; TrustServerCertificate = $trust;";
|
||||
$conn5 = new PDO("sqlsrv:server = $server ; $connectionInfo", $uid, $pwd);
|
||||
echo 'Test case 5' . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
echo 'Failed to connect (test case 5)' . PHP_EOL;
|
||||
print_r($e->getMessage());
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
unset($conn5);
|
||||
|
||||
try {
|
||||
$encrypt = 'no ';
|
||||
$trust = 'false ';
|
||||
$connectionInfo = "Database = $databaseName; Encrypt = $encrypt; TrustServerCertificate = $trust;";
|
||||
$conn6 = new PDO("sqlsrv:server = $server ; $connectionInfo", $uid, $pwd);
|
||||
echo 'Test case 6' . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
echo 'Failed to connect (test case 6)' . PHP_EOL;
|
||||
print_r($e->getMessage());
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
unset($conn6);
|
||||
echo 'Done' . PHP_EOL;
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Test case 1
|
||||
Test case 2
|
||||
Test case 3
|
||||
Test case 4
|
||||
Test case 5
|
||||
Test case 6
|
||||
Done
|
|
@ -0,0 +1,79 @@
|
|||
--TEST--
|
||||
Test various encrypt attributes
|
||||
--SKIPIF--
|
||||
<?php require('skipif.inc');?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once 'MsSetup.inc';
|
||||
|
||||
echo 'Test case 1' . PHP_EOL;
|
||||
$connectionOptions = array('Encrypt' => true, 'TrustServerCertificate' => true);
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
sqlsrv_close($conn);
|
||||
|
||||
echo 'Test case 2' . PHP_EOL;
|
||||
$connectionOptions = array('Encrypt' => 1, 'TrustServerCertificate' => true);
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
sqlsrv_close($conn);
|
||||
|
||||
echo 'Test case 3' . PHP_EOL;
|
||||
$connectionOptions = array('Encrypt' => "yes", 'TrustServerCertificate' => true);
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
sqlsrv_close($conn);
|
||||
|
||||
echo 'Test case 4' . PHP_EOL;
|
||||
$connectionOptions = array('Encrypt' => "no");
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
sqlsrv_close($conn);
|
||||
|
||||
echo 'Test case 5' . PHP_EOL;
|
||||
$connectionOptions = array('Encrypt' => false);
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
sqlsrv_close($conn);
|
||||
|
||||
echo 'Test case 6' . PHP_EOL;
|
||||
$connectionOptions = array('Encrypt' => 0);
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
die(print_r(sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
echo 'Test case 7' . PHP_EOL;
|
||||
$connectionOptions = array('Encrypt' => 3);
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn !== false) {
|
||||
echo 'Expect this to fail' . PHP_EOL;
|
||||
}
|
||||
|
||||
echo 'Done' . PHP_EOL;
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Test case 1
|
||||
Test case 2
|
||||
Test case 3
|
||||
Test case 4
|
||||
Test case 5
|
||||
Test case 6
|
||||
Test case 7
|
||||
Done
|
Загрузка…
Ссылка в новой задаче