Merge pull request #989 from david-puglielli/issue-432-fix
Issue #432 fix
This commit is contained in:
commit
f369ce6212
|
@ -386,7 +386,7 @@ SQLRETURN core_odbc_connect( _Inout_ sqlsrv_conn* conn, _Inout_ std::string& con
|
|||
|
||||
// We only support UTF-8 encoding for connection string.
|
||||
// Convert our UTF-8 connection string to UTF-16 before connecting with SQLDriverConnnectW
|
||||
wconn_string = utf16_string_from_mbcs_string( SQLSRV_ENCODING_UTF8, conn_str.c_str(), static_cast<unsigned int>( conn_str.length() ), &wconn_len );
|
||||
wconn_string = utf16_string_from_mbcs_string( SQLSRV_ENCODING_UTF8, conn_str.c_str(), static_cast<unsigned int>( conn_str.length() ), &wconn_len, true );
|
||||
|
||||
CHECK_CUSTOM_ERROR( wconn_string == 0, conn, SQLSRV_ERROR_CONNECT_STRING_ENCODING_TRANSLATE, get_last_error_message())
|
||||
{
|
||||
|
|
|
@ -1808,7 +1808,7 @@ struct sqlsrv_buffered_result_set : public sqlsrv_result_set {
|
|||
bool convert_string_from_utf16_inplace( _In_ SQLSRV_ENCODING encoding, _Inout_updates_z_(len) char** string, _Inout_ SQLLEN& len);
|
||||
bool validate_string( _In_ char* string, _In_ SQLLEN& len);
|
||||
bool convert_string_from_utf16( _In_ SQLSRV_ENCODING encoding, _In_reads_bytes_(cchInLen) const SQLWCHAR* inString, _In_ SQLINTEGER cchInLen, _Inout_updates_bytes_(cchOutLen) char** outString, _Out_ SQLLEN& cchOutLen );
|
||||
SQLWCHAR* utf16_string_from_mbcs_string( _In_ SQLSRV_ENCODING php_encoding, _In_reads_bytes_(mbcs_len) const char* mbcs_string, _In_ unsigned int mbcs_len, _Out_ unsigned int* utf16_len );
|
||||
SQLWCHAR* utf16_string_from_mbcs_string( _In_ SQLSRV_ENCODING php_encoding, _In_reads_bytes_(mbcs_len) const char* mbcs_string, _In_ unsigned int mbcs_len, _Out_ unsigned int* utf16_len, bool use_strict_conversion = false );
|
||||
|
||||
//*********************************************************************************************************************************
|
||||
// Error handling routines and Predefined Errors
|
||||
|
|
|
@ -34,7 +34,7 @@ char last_err_msg[2048] = {'\0'}; // 2k to hold the error messages
|
|||
unsigned int convert_string_from_default_encoding( _In_ unsigned int php_encoding, _In_reads_bytes_(mbcs_len) char const* mbcs_in_string,
|
||||
_In_ unsigned int mbcs_len,
|
||||
_Out_writes_(utf16_len) __transfer( mbcs_in_string ) SQLWCHAR* utf16_out_string,
|
||||
_In_ unsigned int utf16_len );
|
||||
_In_ unsigned int utf16_len, bool use_strict_conversion = false );
|
||||
}
|
||||
|
||||
// SQLSTATE for all internal errors
|
||||
|
@ -172,11 +172,11 @@ bool convert_string_from_utf16( _In_ SQLSRV_ENCODING encoding, _In_reads_bytes_(
|
|||
// allocation of the destination string. An empty string passed in returns
|
||||
// failure since it's a failure case for convert_string_from_default_encoding.
|
||||
SQLWCHAR* utf16_string_from_mbcs_string( _In_ SQLSRV_ENCODING php_encoding, _In_reads_bytes_(mbcs_len) const char* mbcs_string, _In_ unsigned int mbcs_len,
|
||||
_Out_ unsigned int* utf16_len )
|
||||
_Out_ unsigned int* utf16_len, bool use_strict_conversion )
|
||||
{
|
||||
*utf16_len = (mbcs_len + 1);
|
||||
SQLWCHAR* utf16_string = reinterpret_cast<SQLWCHAR*>( sqlsrv_malloc( *utf16_len * sizeof( SQLWCHAR )));
|
||||
*utf16_len = convert_string_from_default_encoding( php_encoding, mbcs_string, mbcs_len, utf16_string, *utf16_len );
|
||||
*utf16_len = convert_string_from_default_encoding( php_encoding, mbcs_string, mbcs_len, utf16_string, *utf16_len, use_strict_conversion );
|
||||
|
||||
if( *utf16_len == 0 ) {
|
||||
// we preserve the error and reset it because sqlsrv_free resets the last error
|
||||
|
@ -384,7 +384,7 @@ namespace {
|
|||
// to convert.
|
||||
unsigned int convert_string_from_default_encoding( _In_ unsigned int php_encoding, _In_reads_bytes_(mbcs_len) char const* mbcs_in_string,
|
||||
_In_ unsigned int mbcs_len, _Out_writes_(utf16_len) __transfer( mbcs_in_string ) SQLWCHAR* utf16_out_string,
|
||||
_In_ unsigned int utf16_len )
|
||||
_In_ unsigned int utf16_len, bool use_strict_conversion )
|
||||
{
|
||||
unsigned int win_encoding = CP_ACP;
|
||||
switch( php_encoding ) {
|
||||
|
@ -400,7 +400,13 @@ unsigned int convert_string_from_default_encoding( _In_ unsigned int php_encodin
|
|||
break;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
unsigned int required_len = SystemLocale::ToUtf16( win_encoding, mbcs_in_string, mbcs_len, utf16_out_string, utf16_len );
|
||||
unsigned int required_len;
|
||||
if (use_strict_conversion) {
|
||||
required_len = SystemLocale::ToUtf16Strict( win_encoding, mbcs_in_string, mbcs_len, utf16_out_string, utf16_len );
|
||||
}
|
||||
else {
|
||||
required_len = SystemLocale::ToUtf16( win_encoding, mbcs_in_string, mbcs_len, utf16_out_string, utf16_len );
|
||||
}
|
||||
#else
|
||||
unsigned int required_len = MultiByteToWideChar( win_encoding, MB_ERR_INVALID_CHARS, mbcs_in_string, mbcs_len, utf16_out_string, utf16_len );
|
||||
#endif // !_Win32
|
||||
|
|
|
@ -214,12 +214,12 @@ bool ss_error_handler( _Inout_ sqlsrv_context& ctx, _In_ unsigned int sqlsrv_err
|
|||
// returned in utf16_out_string.
|
||||
unsigned int convert_string_from_default_encoding( _In_ unsigned int php_encoding, _In_reads_bytes_(mbcs_len) char const* mbcs_in_string,
|
||||
_In_ unsigned int mbcs_len, _Out_writes_(utf16_len) __transfer(mbcs_in_string) wchar_t* utf16_out_string,
|
||||
_In_ unsigned int utf16_len );
|
||||
_In_ unsigned int utf16_len, bool use_strict_conversion = false );
|
||||
// create a wide char string from the passed in mbcs string. NULL is returned if the string
|
||||
// could not be created. No error is posted by this function. utf16_len is the number of
|
||||
// wchar_t characters, not the number of bytes.
|
||||
SQLWCHAR* utf16_string_from_mbcs_string( _In_ unsigned int php_encoding, _In_reads_bytes_(mbcs_len) const char* mbcs_string,
|
||||
_In_ unsigned int mbcs_len, _Out_ unsigned int* utf16_len );
|
||||
_In_ unsigned int mbcs_len, _Out_ unsigned int* utf16_len, bool use_strict_conversion = false );
|
||||
|
||||
// *** internal error macros and functions ***
|
||||
bool handle_error( sqlsrv_context const* ctx, int log_subsystem, const char* function,
|
||||
|
|
|
@ -38,7 +38,7 @@ function invalidServer()
|
|||
echo "Should have failed to connect to invalid server.\n";
|
||||
} catch (PDOException $e) {
|
||||
$error1 = '*Login timeout expired';
|
||||
$error2 = '*An error occurred translating the connection string to UTF-16: No mapping for the Unicode character exists in the target multi-byte code page*';
|
||||
$error2 = '*An error occurred translating the connection string to UTF-16: *';
|
||||
if (fnmatch($error1, $e->getMessage()) || fnmatch($error2, $e->getMessage())) {
|
||||
; // matched at least one of the expected error messages
|
||||
} else {
|
||||
|
@ -102,7 +102,7 @@ function invalidPassword()
|
|||
$options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
// Possible errors
|
||||
$error = "*An error occurred translating the connection string to UTF-16: No mapping for the Unicode character exists in the target multi-byte code page.*";
|
||||
$error = "*An error occurred translating the connection string to UTF-16: *";
|
||||
$error1 = "*Login failed for user \'*\'.";
|
||||
$error2 = "*Login timeout expired*";
|
||||
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
--TEST--
|
||||
UTF-8 connection strings
|
||||
--SKIPIF--
|
||||
<?php require('skipif_unix.inc'); ?>
|
||||
<?php require('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once('MsSetup.inc');
|
||||
|
||||
// Expected errors
|
||||
$gibberishEncoding = array('IMSSP', '-48', "The encoding 'gibberish' is not a supported encoding for the CharacterSet connection option.");
|
||||
$binaryEncoding = array('IMSSP', '-48', "The encoding 'binary' is not a supported encoding for the CharacterSet connection option.");
|
||||
$utf16Error = array('IMSSP', '-47', "An error occurred translating the connection string to UTF-16: *");
|
||||
$userLoginFailed = array('28000', '18456', "*Login failed for user *");
|
||||
|
||||
function connect($options=array())
|
||||
{
|
||||
global $server, $uid, $pwd, $databaseName;
|
||||
|
@ -22,6 +29,17 @@ function connect($options=array())
|
|||
return sqlsrv_connect($server, $options);
|
||||
}
|
||||
|
||||
function checkErrors($expectedError)
|
||||
{
|
||||
// On Windows one call returns two identical errors, so just take the first element
|
||||
$error = sqlsrv_errors()[0];
|
||||
if (!fnmatch($expectedError[0], $error[0]) ||
|
||||
!fnmatch($expectedError[1], $error[1]) ||
|
||||
!fnmatch($expectedError[2], $error[2])) {
|
||||
fatalError("Errors do not match!\n");
|
||||
}
|
||||
}
|
||||
|
||||
sqlsrv_configure('WarningsReturnAsErrors', 0);
|
||||
sqlsrv_configure('LogSeverity', SQLSRV_LOG_SEVERITY_ALL);
|
||||
|
||||
|
@ -30,13 +48,13 @@ $c = connect(array( 'CharacterSet' => 'gibberish' ));
|
|||
if ($c !== false) {
|
||||
fatalError("Should have errored on an invalid encoding.");
|
||||
}
|
||||
print_r(sqlsrv_errors());
|
||||
checkErrors($gibberishEncoding);
|
||||
|
||||
$c = connect(array( 'CharacterSet' => SQLSRV_ENC_BINARY ));
|
||||
if ($c !== false) {
|
||||
fatalError("Should have errored on an invalid encoding.");
|
||||
}
|
||||
print_r(sqlsrv_errors());
|
||||
checkErrors($binaryEncoding);
|
||||
|
||||
$c = connect(array( 'CharacterSet' => SQLSRV_ENC_CHAR ));
|
||||
if ($c === false) {
|
||||
|
@ -50,7 +68,7 @@ $c = sqlsrv_connect($server_invalid, array( 'Database' => 'test', 'CharacterSet'
|
|||
if ($c !== false) {
|
||||
fatalError("sqlsrv_connect(1) should have failed");
|
||||
}
|
||||
print_r(sqlsrv_errors());
|
||||
checkErrors($utf16Error);
|
||||
|
||||
// APP has a UTF-8 name
|
||||
$c = connect(array(
|
||||
|
@ -67,7 +85,7 @@ $c = connect(array(
|
|||
if ($c !== false) {
|
||||
fatalError("sqlsrv_connect(3) should have failed");
|
||||
}
|
||||
print_r(sqlsrv_errors());
|
||||
checkErrors($userLoginFailed);
|
||||
|
||||
// invalid UTF-8 in the pwd
|
||||
$c = connect(array(
|
||||
|
@ -77,89 +95,10 @@ $c = connect(array(
|
|||
if ($c !== false) {
|
||||
fatalError("sqlsrv_connect(4) should have failed");
|
||||
}
|
||||
print_r(sqlsrv_errors());
|
||||
checkErrors($utf16Error);
|
||||
|
||||
echo "Test succeeded.\n";
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Array
|
||||
(
|
||||
[0] => Array
|
||||
(
|
||||
[0] => IMSSP
|
||||
[SQLSTATE] => IMSSP
|
||||
[1] => -48
|
||||
[code] => -48
|
||||
[2] => The encoding 'gibberish' is not a supported encoding for the CharacterSet connection option.
|
||||
[message] => The encoding 'gibberish' is not a supported encoding for the CharacterSet connection option.
|
||||
)
|
||||
|
||||
)
|
||||
Array
|
||||
(
|
||||
[0] => Array
|
||||
(
|
||||
[0] => IMSSP
|
||||
[SQLSTATE] => IMSSP
|
||||
[1] => -48
|
||||
[code] => -48
|
||||
[2] => The encoding 'binary' is not a supported encoding for the CharacterSet connection option.
|
||||
[message] => The encoding 'binary' is not a supported encoding for the CharacterSet connection option.
|
||||
)
|
||||
|
||||
)
|
||||
Array
|
||||
(
|
||||
[0] => Array
|
||||
(
|
||||
[0] => IMSSP
|
||||
[SQLSTATE] => IMSSP
|
||||
[1] => -47
|
||||
[code] => -47
|
||||
[2] => An error occurred translating the connection string to UTF-16: No mapping for the Unicode character exists in the target multi-byte code page.
|
||||
|
||||
[message] => An error occurred translating the connection string to UTF-16: No mapping for the Unicode character exists in the target multi-byte code page.
|
||||
|
||||
)
|
||||
|
||||
)
|
||||
Array
|
||||
(
|
||||
[0] => Array
|
||||
(
|
||||
[0] => 28000
|
||||
[SQLSTATE] => 28000
|
||||
[1] => 18456
|
||||
[code] => 18456
|
||||
[2] => %SLogin failed for user '%s'.
|
||||
[message] => %SLogin failed for user '%s'.
|
||||
)
|
||||
|
||||
[1] => Array
|
||||
(
|
||||
[0] => 28000
|
||||
[SQLSTATE] => 28000
|
||||
[1] => 18456
|
||||
[code] => 18456
|
||||
[2] => %SLogin failed for user '%s'.
|
||||
[message] => %SLogin failed for user '%s'.
|
||||
)
|
||||
|
||||
)
|
||||
Array
|
||||
(
|
||||
[0] => Array
|
||||
(
|
||||
[0] => IMSSP
|
||||
[SQLSTATE] => IMSSP
|
||||
[1] => -47
|
||||
[code] => -47
|
||||
[2] => An error occurred translating the connection string to UTF-16: No mapping for the Unicode character exists in the target multi-byte code page.
|
||||
|
||||
[message] => An error occurred translating the connection string to UTF-16: No mapping for the Unicode character exists in the target multi-byte code page.
|
||||
|
||||
)
|
||||
|
||||
)
|
||||
--EXPECT--
|
||||
Test succeeded.
|
||||
|
|
Loading…
Reference in a new issue