Estou procurando uma alternativa mysql_real_escape_string()
para o SQL Server. É a addslashes()
minha melhor opção ou existe outra função alternativa que pode ser usada?
Uma alternativa para mysql_error()
também seria útil.
Estou procurando uma alternativa mysql_real_escape_string()
para o SQL Server. É a addslashes()
minha melhor opção ou existe outra função alternativa que pode ser usada?
Uma alternativa para mysql_error()
também seria útil.
Respostas:
addslashes()
não é totalmente adequado, mas o pacote mssql do PHP não oferece nenhuma alternativa decente. A solução feia, mas totalmente geral, é codificar os dados como um bytestring hexadecimal, ou seja,
$unpacked = unpack('H*hex', $data);
mssql_query('
INSERT INTO sometable (somecolumn)
VALUES (0x' . $unpacked['hex'] . ')
');
Abstrato, isso seria:
function mssql_escape($data) {
if(is_numeric($data))
return $data;
$unpacked = unpack('H*hex', $data);
return '0x' . $unpacked['hex'];
}
mssql_query('
INSERT INTO sometable (somecolumn)
VALUES (' . mssql_escape($somevalue) . ')
');
mysql_error()
equivalente é mssql_get_last_message()
.
SQLSTATE[22007]: Invalid datetime format: 210 [Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting datetime from binary/varbinary string.
acredito que este método pode ser correto apenas se funcionar com todos os tipos de dados MSSQL.
mssql_escape()
função retornada não está fazendo isso para mim. A exibição de texto depois de fazer uma seleção fica 0x4a2761696d65206269656e206c652063686f636f6c6174
assim ilegível.
function ms_escape_string($data) {
if ( !isset($data) or empty($data) ) return '';
if ( is_numeric($data) ) return $data;
$non_displayables = array(
'/%0[0-8bcef]/', // url encoded 00-08, 11, 12, 14, 15
'/%1[0-9a-f]/', // url encoded 16-31
'/[\x00-\x08]/', // 00-08
'/\x0b/', // 11
'/\x0c/', // 12
'/[\x0e-\x1f]/' // 14-31
);
foreach ( $non_displayables as $regex )
$data = preg_replace( $regex, '', $data );
$data = str_replace("'", "''", $data );
return $data;
}
Parte do código aqui foi roubado do CodeIgniter. Funciona bem e é uma solução limpa.
EDIT: Existem muitos problemas com esse trecho de código acima. Por favor, não use isso sem ler os comentários para saber o que são. Melhor ainda, por favor, não use isso. As consultas parametrizadas são seus amigos: http://php.net/manual/en/pdo.prepared-statements.php
preg_replace
? Não é o str_replace
suficiente?
empty($value)
vai voltar true
não só para ''
, mas também para null
, 0
e '0'
! Você retornaria uma string vazia em todos esses casos.
Por que você se incomodaria em escapar de qualquer coisa quando você pode usar parâmetros em sua consulta ?!
sqlsrv_query(
$connection,
'UPDATE some_table SET some_field = ? WHERE other_field = ?',
array($_REQUEST['some_field'], $_REQUEST['id'])
)
Ele funciona bem em seleções, exclusões e atualizações, independentemente de seus parâmetros de valores serem null
ou não. Faça uma questão de princípio - Não concatene SQL e você estará sempre seguro e suas consultas serão lidas muito melhor.
Você pode dar uma olhada na Biblioteca PDO . Você pode usar instruções preparadas com PDO, que automaticamente escapará de quaisquer caracteres inválidos em suas strings se você fizer as instruções preparadas corretamente. Isso é apenas para PHP 5, eu acho.
Outra maneira de lidar com aspas simples e duplas é:
function mssql_escape($str)
{
if(get_magic_quotes_gpc())
{
$str = stripslashes($str);
}
return str_replace("'", "''", $str);
}
Para escapar das aspas simples e duplas, você precisa dobrá-las:
$value = 'This is a quote, "I said, 'Hi'"';
$value = str_replace( "'", "''", $value );
$value = str_replace( '"', '""', $value );
$query = "INSERT INTO TableName ( TextFieldName ) VALUES ( '$value' ) ";
etc ...
e atribuição: caractere de escape no Microsoft SQL Server 2000
Depois de lutar com isso por horas, eu encontrei uma solução que parece quase a melhor.
A resposta do caos de converter valores em hexstring não funciona com todos os tipos de dados, especificamente com colunas datetime.
Eu uso PHP's PDO::quote()
, mas como vem com PHP, PDO::quote()
não tem suporte para MS SQL Server e retorna FALSE
. A solução para que funcionasse era baixar alguns pacotes da Microsoft:
Depois disso, você pode se conectar em PHP com PDO usando um DSN como o exemplo a seguir:
sqlsrv:Server=192.168.0.25; Database=My_Database;
O uso dos parâmetros UID
e PWD
no DSN não funcionou, então o nome de usuário e a senha são passados como o segundo e o terceiro parâmetros no construtor PDO ao criar a conexão. Agora você pode usar PHP PDO::quote()
. Aproveitar.
Uma resposta de 22-02-2009T121000 pelo caos do usuário não se aplica a todas as perguntas.
Por exemplo, "CREATE LOGIN [0x6f6c6f6c6f] FROM WINDOWS" apresentará uma exceção.
PS: veja o driver do SQL Server para PHP, http://msdn.microsoft.com/library/cc296181%28v=sql.90%29.aspx e a função sqlsrv_prepare, que pode vincular parâmetros.
PSS: O que também não o ajudou com a consulta acima;)
Aviso: Esta função foi REMOVIDA no PHP 7.0.0.
http://php.net/manual/en/function.mssql-query.php
Para quem ainda usa essas funções mssql_ *, lembre-se de que elas foram removidas do PHP a partir da v7.0.0. Então, isso significa que você eventualmente terá que reescrever seu código de modelo para usar a biblioteca PDO, sqlsrv_ * etc. Se você estiver procurando por algo com um método "citando / escapando", eu recomendaria PDO.
Alternativas para esta função incluem: PDO :: query (), sqlsrv_query () e odbc_exec ()
Se você estiver usando PDO, você pode usar o PDO::quote
método.
Para a conversão para obter os valores hexadecimais em SQL de volta para ASCII, aqui está a solução que encontrei (usando a função do caos do usuário para codificar em hexadecimal)
function hexEncode($data) {
if(is_numeric($data))
return $data;
$unpacked = unpack('H*hex', $data);
return '0x' . $unpacked['hex'];
}
function hexDecode($hex) {
$str = '';
for ($i=0; $i<strlen($hex); $i += 2)
$str .= chr(hexdec(substr($hex, $i, 2)));
return $str;
}
$stringHex = hexEncode('Test String');
var_dump($stringHex);
$stringAscii = hexDecode($stringHex);
var_dump($stringAscii);
É melhor também escapar das palavras reservadas do SQL. Por exemplo:
function ms_escape_string($data) {
if (!isset($data) or empty($data))
return '';
if (is_numeric($data))
return $data;
$non_displayables = array(
'/%0[0-8bcef]/', // URL encoded 00-08, 11, 12, 14, 15
'/%1[0-9a-f]/', // url encoded 16-31
'/[\x00-\x08]/', // 00-08
'/\x0b/', // 11
'/\x0c/', // 12
'/[\x0e-\x1f]/', // 14-31
'/\27/'
);
foreach ($non_displayables as $regex)
$data = preg_replace( $regex, '', $data);
$reemplazar = array('"', "'", '=');
$data = str_replace($reemplazar, "*", $data);
return $data;
}
Tenho usado isso como uma alternativa de mysql_real_escape_string()
:
function htmlsan($htmlsanitize){
return $htmlsanitize = htmlspecialchars($htmlsanitize, ENT_QUOTES, 'UTF-8');
}
$data = "Whatever the value's is";
$data = stripslashes(htmlsan($data));
Você poderia rolar sua própria versão mysql_real_escape_string
, (e melhorá-lo) com a seguinte expressão regular: [\000\010\011\012\015\032\042\047\134\140]
. Isso cuida dos seguintes caracteres: nulo, backspace, tabulação horizontal, nova linha, retorno de carro, substituto, aspas duplas, aspas simples, barra invertida, acento grave. Backspace e tabulação horizontal não são suportados por mysql_real_escape_string
.