Context
I store image in BLOBs columns in a MySql DB with PDO (yeah, this is needed).
I upload a base64_encoded .png from client's browser to a .php webservice through AJAX, and store it on my data base using base64_decode().
Later, I get it back on the client's browser. And upload it again, and so on until space-time continuum breaks.
Retrieving a valid BLOB (imported directly on phpMyAdmin, so 100% sure) from the database is fine, I can print it well on browser.
But storing it on MySql...
Issue
Setting looks like that :
$dbh = new PDO('mysql:host=localhost;dbname=Me', 'My', 'Myself');
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->exec("SET CHARACTER SET utf8"); //I tried playing with charset too
$query = $dbh->prepare("UPDATE i_like_underscores SET `my_blob`=:my_blob WHERE `it`=`:belongs");
$my_blob = base64_decode($_POST['my_blob']);
$query->bindParam(':my_blob', $my_blob, PDO::PARAM_LOB);
//The WHERE clause has really no importance here, so I don't even bind it
$query->execute();
It seems that PDO systematically removes some special characters of my blob during this process (but I can't diagnostic when exactly), cause when I later get my picture back (and encode it on base64), all the + and = are gone from my base64 string (while / stills) === corrupted.
I guess it automatically escapes when I bind it, but I can't tell as base64_decoded .png data is encoded in a unreadable weird charset.
I spent many hours on it, and tried :
Changing the encoding
PDO::quote() after base64_decode()
Putting various quotes on my SQL query
Prepared statements and direct PDO::query
Surfing the web for docs on all the PDO function I used
Finding similar cases, on StackOverflow too, no luck
To see how it's done in phpMyAdmin
Setting type PDO::PARAM_STR
Not thinking about quitting PDO just for that special case
Writing all my code backwards
And black magic
Without luck... Could someone give me a clue?
Thanks to davidstrachan, I've solved the removal of = using :
$dbh->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
Then, I came back to that problem later, just to see that the serialization of my form in jQuery was done wrong.
It escaped all the + as spaces (or %20) instead of %2B.
Related
Is it possible to escape a serialized string using PDO before it is inserted in the database?
I've built something where content from a WYSIWYG editor will be serialized. If someone pastes text from Word to the editor, and saves, I'll get the following error because multiple style tags where added:
unserialize(): Error at offset 105 of 1020
I've tried saying don't paste from Word haha, however I would like to build it so that it is possible even it's not the best way to do it.
I found the PDO function quote, but I'm not sure if that is what I'm looking for.
Besides that function, I couldn't find any other solutions. I'm already using PDO prepared statements.
I would like to know if it is possible. Thanks for the effort.
I believe it is related to encoding.
You should do base64_encode before save and base64_decode after it. As wrote here:
$toDatabse = base64_encode(serialize($data)); // Save to database
$fromDatabase = unserialize(base64_decode($data)); //Getting Save Format
Also, to avoid problems with encoding when you connect to database execute this SQL request:
"SET NAMES 'utf8'"
im letting my users type in texts, then take them to server side php and process them, and if everything goes as it should, i just append the text with jquery without the page having to load all over again.
This is the procedure:
$post_text = htmlspecialchars(mysql_real_escape_string($_POST['post_text']));
some logic...
everything ok!
stripslashes(str_replace("\\n", "", $post_text))
and then i send all the nessesary data witj json
echo json_encode($return);
on the client side i append the html chunk saved in a variable from the server side.
this seems to work on localhost, it removes all the slashes and so on, but online it just doenst remove the slashes, and they keep coming up, when i hit refresh they dissapear becouse then its a
stripslashes($comment['statusmsg_text'])
written out with php straight from the database. Is it the json that adds some extra stuff? i dont get it becouse it works perfectly on localhost.
best of regards,
alexander
The additional slashes might be magic quotes. You shouldn’t rely on them and disable them.
Additionally, mysql_real_escape_string should only be used to prepare strings to be put into a string context in an MySQL statement. Similar applies to htmlspecialchars that should only be used for sanitizing data to be put into an HTML context.
It may be, that on your server and your localhost the magic_quotes_gpc directive is set differently, so your string is double encoded on server side.
Try it without stripslashes, json_encode should handle that. All you need to do is use mysql_real_escape once, before your string touches your database.
i have problems with encoding when using json and ajax.
chrome and ie encode umlauts as unicode when jsonifying, firefox and safari returning those utf-8 escaped umlauts like ¼Ã.
where is the best place to give all the same encoding?
js / php-get or by writing them to the database.
and i think the next trouble is, when i reload the utf-8 encoded stuff from the db, and write them to the browser and then rewrite them to the db, again via ajax-request a get a real chaos?
can i avoid the chaous? can i handle the encoding in an easy way?
pls. help :-)
very important is to also provide security
You must set everything to UTF-8, this means :
Database collation
Table collation
Field collation
Your coding software (example notepad++) encryption.
Had a similar problem. Maybe you are actually interpreting encoding the wrong way, clientwise. Try setting the frontend encoding before your queries.
<?php
$connection = pg_pconnect("dbname=data");
pg_set_client_encoding($connection, "encoding goes here"); //check enconding aletrnatives on PostgreSQL
$result = pg_query($connection, "SELECT whatever FROM wherever");
//and so on...
?>
I'm a newbie, but it may help. Also won't affect security in anyway if you are already protected against db injection.
Cheers
I am attempting to upload a .pdf file into a mysql database using php.
It is all good except for the contents of the file. No matter how I seem try to escape special characters, the query always fails, mostly with "Unknown Command \n".
I have used addslashes, mysql_real_escape_string, removeslashes etc.
Does anyone have any ideas on how to escape file contents?
Many Thanks,
I don't see why you would want to store a file in a database, but I suggest you take a look at prepared statements.
I've used the following sequence before, which seems to work nicely, and will store any data into the db, including images, pdfs, arrays of data, etc... :)
Storing the data (can be a string, array, object, etc.);
First, turn the data into a base64 encoded string
$strData = strtr(
base64_encode(
addslashes(
gzcompress( serialize($dataToStore) , 9)
)
) , '+/=', '-_,');
Then store that string data in the db...
Retrieving the data;
Extract the string data from the db
decode the data back to what you want (you may need to perform an extra step after this depending on the input data, array, image, etc.)
$returnData = unserialize(
gzuncompress(
stripslashes(
base64_decode(
strtr($strDataFromDb, '-_,', '+/=')
)
)
)
);
This certainly helped me to store what I needed to store in a mySQL db!
Guess: You may be encountering errors due to the incompatibility between character sets. PDF is probably a binary file so you need to make sure that db column is set up to handle it that.
Beside the escaping problem you might run into "packet too large" errors if the (MySQL) system variable max_allowed_packet is set to a "small" value.
Using the mysqli extension, prepared statements and mysqli_stmt::send_long_data you can avoid both problems.
When I insert some data with Zend_Form to database with non a-z characters like chrząszcz it cuts me this string and in database I have saved only chrz.
Everyting in MySql is set as utf8_general_ci, when connecting with MySql I call SET CHARACTER SET 'utf8', files are also UTF-8.
I have no idea what to do with that.
I wrote also standalone script and it inserts and reads me that string correct. ZendFramework reads it also correct. The problem is only with inserting.
Do anyone know how to fix it ?
UPDATE:
If I insert data with:
$db->query("INSERT INTO unit SET name = 'chrząszcz'");
in ZendFramework it works. Problem is with inserting that way:
$unitTable = new Model_Unit_Table();
$unit = $unitTable->createRow();
$unit->setFromArray($form->getValues());
$unit->save();
UPDATE 2:
Problem is with using Zend_Filter_StringToLower - it modifies string chrząszcz into chrz�szcz.
How to get this filterto work correct ?
Responding to your comment:
No. var_dump of $form->getValue()
gives chrz�szcz. When var_dump a
$_POST superglobal it gives correct
chrząszcz.
Does this work?
$testArray = array('name' => 'chrząszcz');
$unitTable = new Model_Unit_Table();
$unit = $unitTable->createRow();
$unit->setFromArray($testArray);
$unit->save();
If yes, your problem may be more Zend_Form related.
Edit:
Your filter needs to use mb_strtolower() instead of strtolower().
Edit2:
Try this:
$filter = new Zend_Filter_StringToLower();
$filter->setEncoding('UTF-8');
I'm pretty sure this is an encoding problem. Strings dropping off at the point of the first non-standard (i.e. above the ASCII character set) character is most often caused by inserting UTF-8 data in a non-UTF8 context so my first suspicion would be that the encoding of the database connection is not properly set.
Can you try $db->query("SET NAMES utf8"); before calling the insertion commands?
Is the connection Zend_form uses definitely $db?
Are you 100% sure the page your form is in is UTF-8 encoded?