mssql_bind empty string converting to NULL - php

I am currently using SQL Server 2000 Stored Procedures with PHP. Following the PHP doc, I use mssql_bind to assign value of parameters and then execute the Stored Procedure.
The problem is that I got this bug which prevents me to bind empty strings to parameters (they are converted to NULL when the Stored Proc gets called)
I dont't want to have to convert every parameter inside the Stored Procedures to check if its NULL then convert back to an empty string. I want to be able to use empty strings as well as NULL which both have their own meaning.
Does anyone know a workaround for this in PHP ? PHP bugs website isn't very clear if that bug is fixed or when it will be fixed, I use PHP 5.2.11 (the lastest version from the 5.2 branch)

Assuming you do not want to do what you suggested, options left to you are
Download a cvs snapshot of php and install it if viable, see if it is fixed. If not viable or fixed via cvs then...
Use system() or exec() calls to use the stored procedures. If too much a hassle then...
Don't use stored procedures, do your functionality in php or other scripting code.
Alter the stored procedure to accept another value for '' strings and convert THAT to a '' string.
Do what you didn't want to do. Harsh :P But I do not see another way.

The bug #44325 proposed a patch to solve the problem, but it was not a correct solution, as it seems the problem is in ntwdblib.dll, and not in the code of the php_mssql extension.
See the comment from alexr at oplot dot com :
I'm sorry. This bug is not fixed. This
is a bug of the ntwdblib.dll. And
after latest updates the bug is
return.
When I bind a empty string, the stored
procedure received a chr(0) char
instead a empty string.
Please roll back last fixes. This bug
is irrecoverable.
Considering this, I'm not sure there's much that could be done on the PHP side :-(
Last time I worked with PHP+MSSQL on Windows, I had quite a lot of problems, like some quite similar to this one, actually ;-(
Maybe a possible solution, for you, might be to switch to the newer SQL Server Driver for PHP driver ? Note that is only works on Windows, though...

I personally don't have a MSSQL server available to test but have you tried using PDO instead of mssql directly?
PDOStatement->bindValue( mixed $parameter , mixed $value [, int $data_type ] )
bindValue()
Yes, I realize that PDO is only a wrapper but who knows, could work! :)

I have a solution that will work.
I am using ADODB (but that doesnt matter) and I have hacked the mssql driver (adodb-mssql.inc.php in the adodb5 drivers folder).
here is the code
if($var === ''){
//stupid hack to prevent mssql driver from converting empty strings to null. now they arent empty strings but they will get trimmed down to legth 0 ;-)
$var = ' ';
$type = SQLVARCHAR;
$isNull = false;
$maxLen = 0;
}
simply check if you are trying to bind an empty string and if you are change it to be non empty. it doesn't matter what value you use I just use a space.
make the type a sqlvarchar isnull should be false and now the trick is to make maxlen 0 so that the mssql driver will trim your string to an empty string.
those variables should get passsed to the mssql_bind function if that wasn't obvious.

Related

json_encode() turn non-UTF8 strings into null, but on live site returns false

In the framework I have to use for a project (Lithium) the output on a specific page goes through json_encode(). Locally and on live I try with one and the same data, and the result is:
Locally it returns the JSON, but some of the values are turned into null.
Live site - it returns false.
In both cases when I run json_last_error() - it gives me int(5). I can run phpinfo() on both places, if some setting is causing the problem.
(Locally I'm with PHP 5.3.*, on live it's 5.5.9.)
Actually you need to use optional parameters of json_encode in case of UTF8 characters
So You can use
JSON_UNESCAPED_UNICODE
option of
JSON_ENCODE
Example:
json_encode($array, JSON_UNESCAPED_UNICODE)
Visit php documentation here.
Although this is not documented on the version log here, non-UTF8 handling behaviour has changed in 5.5, in a way that can make debugging difficult.
Passing a non UTF-8 string to json_encode() will make the function return false in PHP 5.5, while it will only nullify this string (and only this one) in previous versions.
In a Latin-1 encoded file, write this:
$a = array('é', 1);
var_dump(json_encode($a));
PHP < 5.4: string(8) "[null,1]"
PHP >= 5.5: bool(false)
PHP 5.5 has it right of course (if encoding fails, return false) but its likely to introduce errors when updating to 5.5 because previously you could get the rest of the JSON even when one string was not in UTF8 (if this string wasn't used, you'd never notify it's nulled)
Finally - I used a slightly modified version of this gist - http://gist.github.com/oscar-broman/3653399 - but instead of encoding properties - I'm removing all the non-UTF8 strings ... and it's working. But - I had to modify the PHP framework the website is using ... and this is something I was really trying to avoid ... ... ... ... but anyway, this approach does the job for now :) ...
I get the same error with PhP 7.3.
You can fix it in multiple ways :
Ignore no-UTF8 char
json_encode(array("a" => "ç"), JSON_INVALID_UTF8_IGNORE);
This solution is fine if you just want to ignore all possible strange caractere, without trying to show them.
Replace no-UTF8 char
json_encode(array("a" => "ç"), JSON_INVALID_UTF8_SUBSTITUTE);
This is possible, but in my case I was getting "?" result.
UTF8-ize char
json_encode(array("a" => utf8_encode("ç")));
I'm using this solution which just convert into UTF8 format all char.

Using Multiple Defined Variables In MYSQL Connect

I wish to allow a user to login to their MySQL database. Their username and end of the SQL database is the same, however each Database name starts with;
linkycra_[username]
I'm attempting to use defined variables in connecting to the SQL.
It would work with a comma in an echo - however obviously, commas cannot be used in this format.
http://puu.sh/1IBJP.png
Use the concatenation operator.
Well, there is a lot of thing to fix in your code.
First, don't use an image to paste code, but directly in stackoverflow or if it's too long, in a pastebin-like website.
Then, you should not use mysql_* methods since they are deprecated (read the doc), but PDO instead.
Next, you should never use the value in the cookie directly like this. You must verify it, sanitize and filter it, to be sure the value returned is correct : I can modify this value and with some work, maybe hack your website. Not a good way.
Then, if it's lynkycra_[username], you can use the concatenation of strings (based on your code) :
$link = mysql_connect('server', 'linkycra_'.$_COOKIE['monlotronloggedin'], 'password');
See ?

Dynamically typed languages and remote method invocation

Some may know that PHP methods can be remotely invoked from Flash.
Sometimes the input parameter of a remote PHP method is an array of integers.
Because PHP is dynamically typed an attacker can pass an array of anything.
The array of integers has to be used in a SQL query.
At the moment I'm preventing injection like this:
foreach ($unsafeArray as $value)
$safeArray[] = (int)$value;
What would you recommend? Maybe I should start using Java :D
You could use this: $aSafeArray = array_map('intval', $aUnsafeArray); to make sure all passed values are an integer.
My advice would be to start using prepared statements!
Example:
$o->bindParam(':anint', $iInt, PDO::PARAM_INT);
What would you recommend?
I'm not a flash expert, but indeed PHP methods could be called just by knowing its name, and the parameters could be passed as array. So the issue is actually not the remote method invocation, but the input filtering and validation.
Depending on the intented behaviour, I would use intval as opposed to hard cast to int (AFAIR it would return 0 on invalid value), otherwise you could throw an exception or whatever. You have to define its behavior first.
Maybe I should start using Java
No, unless you want a bloated solution both in terms of development speed and huge memory requirement at compile and runtime :p

Storing PHP snippets in MySQL

I am storing PHP snippets in a MySQL database, I am using mysql_real_escape_string and all is well unless there is a & in the php code and then I get a MySQL error. Is there another why I should try and store this information?
Thanks
#Peter : unless you're building a website for helping developers, you have no reason to put php code into your database, it's a warning : this is gonna be a big nightmare to maintain/debug. Can't you link your pages to some parameters and then in your code use these parameters to build each request ?
it may seems a simple design solution at the beginning "how god I can do whatever I want in all my pages" but it might be the worse you're taking on your poject.
I don't know how to say this but you should really try to consider an other solution. And i'm not speaing about security : if you have an SQL Injection the guy can execute SQL AND php so he can really take all your system/server down, or even attack bigger site with yours (and then you'll be responsible).
I'm really surprised everyone is fine with it.
Use base64_encode when you save snippet into the database and base64_decode when you retreive it.
First, I am going to go on record and say I wholeheartedly agree with remi bourgarel. This is likely a bad idea.
But, from a technical standpoint here's how I'd do this IF I NEEDED TO:
$php_code = '
<?php
$var = "this is a string";
$var = strtoupper($var);
echo $var;
?>
';
$php_code = bin2hex($php_code);
$db->query("INSERT INTO php_code_snips (text_code) VALUES(x'{$php_code}')");
bin2hex will transform the string $php_code from a binary string to a hex string, and the x'{$php_code}' tells mysql to expect a hex string.
This means the string is stored as a string in the DB, and is fully searchable. But, since all chars are encoded as hex during the INSERT the special chars won't cause a problem.
Documentation:
bin2hex
Mysql Hex Values

MySQL/PDO::quote() putting quotes around integers despite using PDO::PARAM_INT parameter

It appears no matter what value/data-type pair I pass to $pdo->quote($value, $type);, it always quotes it as a string:
echo $pdo->quote('foo', PDO::PARAM_STR); /* 'foo', as expected */
echo $pdo->quote(42, PDO::PARAM_INT); /* '42', expected 42 unquoted */
I'm just curious to know if this is the intended functionality. I use prepared statements for actual query execution, but I'm trying to fetch create the final querystrings (for debugging/caching), and am constructing them manually.
As the title suggests, this is when $pdo is created using the MySQL driver. I haven't tried others due to unavailability.
The Oracle, SQLite, and Firebird drivers all quote as the PDO MySQL driver, ignoring the param type.
The MSSQL driver only checks the param type for whether it should use a national or regular character set (based on the PDO::PARAM_STR_NATL and PDO::PARAM_STR_CHAR flags); otherwise, it ignores the param type.
The PostgreSQL driver only distinguishes between binary large objects and all others.
The ODBC Driver doesn't implement a quoter.
The (lack of) behavior you expect was reported as a bug and closed as "bogus", meaning the behavior is by design. Perhaps the documentation is misleading when it states:
PDO::quote() places quotes around the input string (if required)
While this suggests there may be instances when values aren't surrounded by quotes, it doesn't say there definitely are, nor does it state what those instances are. If you feel this is a bug in documentation, submit a bug report, preferably with a fix.
public static function quote($value, $pdotype = PDO::PARAM_STR)
{
if ($pdotype == PDO::PARAM_INT)
return (int)$value;
return Db::pdo()->quote($value, $pdotype);
}
According to the PDO developers it's a intentional error in their code and in their documentation.
They do not seem to plan to correct it, so you can do it yourself by wrapping their errornous function and replacing the behaviour as needed.
You actually have no choice as in some cases you NEED a correct quote behaviour for numbers, you can't just use string quoting everywhere as SQL might just not take it.
As a sidenote, the above function will make a 0 out of any illegal data.
SQL injections are not possible but it will not throw an error.
If you want to catch errors you could do a "strlen" on both variables and if that differs you know there was a problem or an intrusion attempt.

Categories