I currently am trying to store images from an Android application. The app converts the image from the ImageView object into a byte array and then uses Android's built in Base64.encodeToString function so that I could pass it within a HTTP Post Request to my PHP script(which conducts the Insert to Database logic).
For some reason, if in my PHP Script I try to call base64_decode before storing the image as a MEDIUMBLOB, the whole insertion process fails but if I skip the base64_decode within the PHP script, the insertion works successfully. Could anyone explain to me why? Been debugging for hours but can't seem to find out the reason
I was thinking that decoding it would help me save storage space on the DB. I'm aware of not storing images in DBs and using paths and stuff but for my current purpose, I've chosen to store it in the DB as it's much more convenient for me (it's not a huge scalable project as I am just developing something to run for a small study).
Thanks in advance!
<?php
/*
* Following code will create a new product row
* All product details are read from HTTP Post Request
*/
// array for JSON response
$response = array();
// check for required fields
if (isset($_POST['username']) && isset($_POST['drinkName']) && isset($_POST['caption']) && isset($_POST['photo']) )
{
$username = $_POST['username'];
$drinkName = $_POST['drinkName'];
$caption = $_POST['caption'];
$photoRaw = $_POST['photo'];
$photo = base64_decode($photoRaw);
// include db connect class
require_once __DIR__ . '/db_connect.php';
// connecting to db
$db = new DB_CONNECT();
// mysql inserting a new row
$result = mysql_query("INSERT INTO Memories(username, drinkName, caption, photo) VALUES('$username', '$drinkName', '$caption', '$photo')");
// check if row inserted or not
if ($result) {
// successfully inserted into database
$response["success"] = 1;
$response["message"] = "Product successfully created.";
// echoing JSON response
echo json_encode($response);
} else {
// failed to insert row
$response["success"] = 0;
$response["message"] = "Oops! An error occurred.";
// echoing JSON response
echo json_encode($response);
}
} else {
// required field is missing
$response["success"] = 0;
$response["message"] = "Required field(s) is missing";
// echoing JSON response
echo json_encode($response);
}
?>
What you have described is a problem with how you are trying to insert the raw binary data into the database. When you say it works as base64, that is because base64 generally won't have a single-quote character in it which would break the sql query you show you are using.
To escape the value using those old mysql_* functions, you would use mysql_escape_string...
Please do not use that old mysql method!
You should migrate to mysqli which has been around for many years (your server should support it). Since it looks like your DB_CONNECT method is built around the old mysql, you will have to restructure that for mysqli. Its not too difficult.
I can provide you with an example of how to do the mysqli insert using a safely prepared statement:
$mysqli = new mysqli("localhost", "my_user", "my_password", "db_name");// db connect
$stmt = $mysqli->prepare("INSERT INTO Memories (username, drinkName, caption, photo)
VALUES(?,?,?,?)");
$stmt->bind_param("ssss", $username, $drinkName, $caption, $photo);
$stmt->execute();
This treats the last value as a straight passthrough as a 'string' into your MEDIUMBLOB field to be inserted safely (as well as safely handle the other three variables protecting you from sql injection attacks).
An alternate way to send binary data in, in packets, is this method:
$mysqli = new mysqli("localhost", "my_user", "my_password", "db_name");// db connect
$stmt = $mysqli->prepare("INSERT INTO Memories (username, drinkName, caption, photo)
VALUES(?,?,?,?)");
$null = NULL; // this is just a holder to bind on
$stmt->bind_param("sssb", $username, $drinkName, $caption, $null); // note the 'b'
$stmt->send_long_data(3,$photo); // 3 indicates the 4th bound variable
$stmt->execute();
Some notes:
If your images are bigger than the max_allowed_packet of mysql, you will run into some errors in that regard.
If your field is a BLOB it would only hold an image < 64kb. If its MEDIUMBLOB it will hold a 16mb image, but you risk run over max_allowed_packet.
If you run over the packet issue, you would need to build a packet loop to pass smaller chunks through the send_long_data function.
Related
MySQL is not using the variables as it should. it is not taking any value from them it is incrementing the auto-increment numbers in the MYSQL table, however the row is not saved. I am not given any errors.
I have tried like this:
$sql = "INSERT INTO `tbl_bike` (`userID`, `ManuPartNo`, `BikeManufacturer`, `BikeModel`, `BikeType`, `BikeWheel`, `BikeColour`, `BikeSpeed`, `BrakeType`, `FrameGender`, `AgeGroup`, `DistFeatures`)
VALUES (“.$userID.”, “.$PartNo.”, “.$BikeManufacturer.”, “.$BikeModel.”, “.$BikeType.”, “.$BikeWheel.”, “.$BikeColour.”, “.$BikeSpeed.”, “.$BrakeType.”, “.$FrameGender.”, “.$AgeGroup.”, “.$DistFeatures.”)";
I have also tried replacing the " with ', Removing the . and even completely removing the ". Nothing has helped with this issue. When I use this query but remove the variables and instead put string, int etc in the correct places the query will function perfectly and put the results into the table. My variables are normally as follows:
$PartNo = $_POST['ManuPartNo’];
$BikeManufacturer = $_POST['BikeManufacturer’];
$BikeModel = $_POST['BikeModel’];
$BikeType = $_POST['BikeType’];
$BikeWheel = $_POST['BikeWheel’];
$BikeColour = $_POST['BikeColour’];
$BikeSpeed = $_POST['BikeSpeed’];
$BrakeType = $_POST['BrakeType’];
$FrameGender = $_POST['FrameGender’];
$AgeGroup = $_POST['AgeGroup’];
$DistFeatures = $_POST['DistFeatures’];
These variables normally take input from a separate PHP/HTML file with the '$_POST['DistFeatures’];'
I have tried removing the $_POST['DistFeatures’]; from the ends of each of them and just replacing the values with normal string or int values but still nothing helps. I am completely stuck and would appreciate any help with this.
This is all running on a plesk server.
Please stop using deprecated MySQL. I will suggest an answer using PDO. You can use this to frame your other queries using PDO.
// Establish a connection in db.php (or your connection file)
$dbname = "dbname"; // your database name
$username = "root"; // your database username
$password = ""; // your database password or leave blank if none
$dbhost = "localhost";
$dbport = "10832";
$dsn = "mysql:dbname=$dbname;host=$dbhost";
$pdo = new PDO($dsn, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
// Include db.php on every page where queries are executed and perform queries the following way
// Take Inputs this way (your method is obsolete and will return "Undefined Index" error)
$userId = (!empty($_SESSION['sessionname']))?$_SESSION['sessionname']:null; // If session is empty it will be set to Null else the session value will be set
$PartNo = (!empty($_POST['ManuPartNo']))?$_POST['ManuPartNo']:null; // If post value is empty it will be set to Null else the posted value will be set
$BikeManufacturer = (!empty($_POST['BikeManufacturer']))?$_POST['BikeManufacturer']:null;
$BikeModel = (!empty($_POST['BikeModel']))?$_POST['BikeModel']:null;
$BikeType = (!empty($_POST['BikeType']))?$_POST['BikeType']:null;
$BikeWheel = (!empty($_POST['BikeWheel']))?$_POST['BikeWheel']:null;
// Query like this
$stmt = $pdo->prepare("INSERT INTO(`userID`, `ManuPartNo`, `BikeManufacturer`, `BikeModel`, `BikeType`)VALUES(:uid, :manuptno, :bkman, :bkmodel, :bktype)");
$stmt-> bindValue(':uid', $userId);
$stmt-> bindValue(':manuptno', $PartNo);
$stmt-> bindValue(':bkman', $BikeManufacturer);
$stmt-> bindValue(':bkmodel', $BikeModel);
$stmt-> bindValue(':bktype', $BikeType);
$stmt-> execute();
if($stmt){
echo "Row inserted";
}else{
echo "Error!";
}
See, it's that simple. Use PDO from now on. It's more secured. To try this, just copy the whole code in a blank PHP file and and run it. Your database will receive an entry. Make sure to change your database values here.
You should try this
$sql = "INSERT INTO tbl_bike (userID, ManuPartNo, BikeManufacturer, BikeModel, BikeType, BikeWheel, BikeColour, BikeSpeed, BrakeType, FrameGender, AgeGroup, DistFeatures) VALUES ('$userID', '$PartNo', '$BikeManufacturer', '$BikeModel', '$BikeType', '$BikeWheel', '$BikeColour', '$BikeSpeed', '$BrakeType', '$FrameGender', '$AgeGroup', '$DistFeatures')";
If this doesn't work, enable the null property in sql values. So you can find out where the error originated.
I'm trying to convert some php code that uses mysql into mysqli code. I'm not sure why it doesn't work - I didn't write the original code and am not that comfortable with the hash part of it, and it seems to be where the issue is. As I show in the code below, the "error" part gets echo'ed so it's something to do with the hash strings, but I don't really understand why changing to mysqli has broken the code. Both versions of the code are below, and the original code works. I deleted the variables (host name, etc.) but otherwise this is the code I am working with.
Mysql Code:
// Send variables for the MySQL database class.
function db_connect($db_name)
{
$host_name = "";
$user_name = "";
$password = "";
$db_link = mysql_connect($host_name, $user_name, $password) //attempt to connect to the database
or die("Could not connect to $host_name" . mysql_connect_error());
mysql_select_db($db_name) //attempt to select the database
or die("Could not select database $db_name");
return $db_link;
}
$db_link = db_connect(""); //connect to the database using db_connect function
// Strings must be escaped to prevent SQL injection attack.
$name = mysql_real_escape_string($_GET['name'], $db_link);
$score = mysql_real_escape_string($_GET['score'], $db_link);
$hash = $_GET['hash'];
$secretKey=""; # Change this value to match the value stored in the client javascript below
$real_hash = md5($name . $score . $secretKey);
if($real_hash == $hash) {
// Send variables for the MySQL database class.
$query = "insert into scores values (NULL, '$name', '$score');";
$result = mysql_query($query) or die('Query failed: ' . mysql_error());
}
Mysqli code (doesn't work):
// Send variables for the MySQL database class.
function db_connect($db_name)
{
$host_name = "";
$user_name = "";
$password = "";
$db_link = mysqli_connect($host_name, $user_name, $password) //attempt to connect to the database
or die("Could not connect to $host_name" . mysqli_connect_error());
mysqli_select_db($db_link, $db_name) //attempt to select the database
or die("Could not select database $db_name");
return $db_link;
}
$db_link = db_connect(""); //connect to the database using db_connect function
// Strings must be escaped to prevent SQL injection attack.
$name = mysqli_real_escape_string($_GET['name'], $db_link);
$score = mysqli_real_escape_string($_GET['score'], $db_link);
$hash = $_GET['hash'];
$secretKey=""; # Change this value to match the value stored in the client javascript below
$real_hash = md5($name . $score . $secretKey);
if($real_hash == $hash) {
// Send variables for the MySQL database class.
$query = "INSERT INTO `scores` VALUES (NULL, '$name', '$score');";
$result = mysqli_query($db_link, $query) or die('Query failed: ' . mysqli_error($db_link));
echo $result;
}
else {
echo "error"; //added for testing. This part gets echoed.
}
mysqli_close($db_link); //close the database connection
One notable "gotchu" is that the argument order is not the same between mysql_real_escape_string and mysqli_real_escape_string, so you need to swap those arguments in your conversion.
$name = mysqli_real_escape_string($db_link, $_GET['name']);
$score = mysqli_real_escape_string($db_link, $_GET['score']);
It's good that you're taking the time to convert, though do convert fully to the object-oriented interface if mysqli is what you want to use:
// Send variables for the MySQL database class.
function db_connect($db_name)
{
$host_name = "";
$user_name = "";
$password = "";
// Enable exceptions
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$db = new mysqli($host_name, $user_name, $password);
$db->select_db($db_name);
return $db;
}
$db = db_connect(""); //connect to the database using db_connect function
$secretKey=""; # Change this value to match the value stored in the client javascript below
$real_hash = md5($name . $score . $secretKey);
if($real_hash == $_GET['hash']) {
// Don't include ; inside queries run through PHP, that's only
// necessary when using interactive MySQL shells.
// Specify the columns you're inserting into, don't leave them ambiguous
// ALWAYS use prepared statements with placeholder values
$stmt = $db->prepare("INSERT INTO `scores` (name, score) VALUES (?, ?)");
$stmt->bind_param("ss", $_GET['name'], $_GET['score']);
$result = $stmt->execute();
echo $result;
}
else {
echo "error"; //added for testing. This part gets echoed.
}
// Should use a connection pool here
$db->close();
The key here is to use prepared statements with placeholder values and to always specify which columns you're actually inserting into. You don't want a minor schema change to completely break your code.
The first step to solving a complex problem is to eliminate all of the mess from the solution so the mistakes become more obvious.
The last if statement is controlling whether the mysql query gets run or not. Since you say this script is echoing "error" form the else portion of that statement, it looks like the hashes don't match.
The $hash variable is getting passed in on the URL string in $_GET['hash']. I suggest echo'ing $_GET['hash'] and $real_hash (after its computed by the call to MD5) and verify that they're not identical strings.
My hunch is that the $secretKey value doesn't match the key that's being used to generate the hash that's passed in in $_GET['hash']. As the comment there hints at, the $secretKey value has to match the value that's used in the Javascript, or the hashes won't match.
Also, you may find that there's a difference in Javascript's md5 implementation compared to PHP's. They may be encoding the same input but are returning slightly different hashes.
Edit: It could also be a character encoding difference between Javascript and PHP, so the input strings are seen as different (thus generating different hashes). See: identical md5 for JS and PHP and Generate the same MD5 using javascript and PHP.
You're also using the values of $name and $score after they've been escaped though mysqli_real_string_escape, so I'd suggest making sure Javascript portion is handling that escaping as well (so the input strings match) and that the msqli escape function is still behaving identically to the previous version. I'd suggest echo'ing the values of $name and $score and make sure they match what the Javascript side is using too. If you're running the newer code on a different server, you may need to set the character set to match the old server. See the "default character set" warning at http://php.net/manual/en/mysqli.real-escape-string.php.
I wrote the following code to retrieve data from the database
<?php
$host = 'localhost';
$username = 'root';
$password = '';
$database = 'users';
$con = mysqli_connect($host, $username, $password, $database);
// catch the values that are passed by the POST method
$courseId=$_POST["courseId"];
$hall=$_POST["hall"];
$day=$_POST["day"];
$year=$_POST["year"];
$time=$_POST["time"];
$statement=mysqli_prepare($con,"SELECT * FROM Lectures WHERE day=? AND timeInterval=? AND courseId=? AND hall=? AND year=? ");
mysqli_stmt_bind_param($statement,"sssss",$courseId,$hall,$day,$year,$time);
mysqli_stmt_execute($statement);
// have to collect the results that are coming after the query is being executed
mysqli_stmt_store_result($statement); //storing the results in a buffer for temporary
// now we need to bind the results
mysqli_stmt_bind_result($statement,$day,$time,$courseId,$hall,$year,$noStudents,$courseRefName,$courseRefTelNo,$lecturer);
// to send the data via JSON string
$lectureDetails=array();
mysqli_stmt_fetch($statement);
$lectureDetails["day"]=$day;
$lectureDetails["time"]=$time;
$lectureDetails["courseId"]=$courseId;
$lectureDetails["hall"]=$hall;
$lectureDetails["year"]=$year;
$lectureDetails["noStudents"]=$noStudents;
$lectureDetails["courseRefName"]=$courseRefName;
$lectureDetails["courseRefTelNo"]=$courseRefTelNo;
$lectureDetails["lecturer"]=$lecturer;
// data are stored in the array. now we need to send them via a JSON string
echo json_encode($lectureDetails);
// the java file that calls this method will receive echo
//The PHP json_encode function returns a string, containing the JSON equivalent of the values passed to it
//so in here $lectureDetails array is passed throught throughe JSON String.
mysqli_stmt_close($statement); //closing the connection
mysqli_close($con); //closing the sql connection
?>
according to the working fetching file as below(this returns values as expected)
<?php
//database connection
$host = 'localhost';
$user1 = 'root';
$password1 = '';
$database = 'users';
$con = mysqli_connect($host, $user1, $password1, $database);
//checking the validity of the database
// if(!$con){
//die("connection Failed" . mysqli_connect_error());}
//echo "connected Successfully";
$userName=$_POST["userName"];
$password=$_POST["password"];
$statement=mysqli_prepare($con,"SELECT * FROM usersLogged WHERE userName=? AND password=?");
//to prevent from sql injection
mysqli_stmt_bind_param($statement,"ss",$userName,$password);
mysqli_stmt_execute($statement);
//after executing the command we will get all the results that were selected
mysqli_stmt_store_result($statement); //storing the results in a buffer for temporary
//we need to bind the results
mysqli_stmt_bind_result($statement, $userId, $userName, $firstName, $lastName, $password, $position,$birthDate,$qualification,$email);
//now we need to store them into an array inoder to send them via a JSON
$user=array();
mysqli_stmt_fetch($statement);
//fetch the result from a prepared statement into the variables bound by mysqli_stmt_bind_result.
//Data are transferred unbuffered without calling mysqli_stmt_store_result() which can decrease performance (but reduces memory cost).
//storing the values which are fetched from the database are kept in the array(#user)
$user["userName"]=$userName;
$user["firstName"]=$firstName;
$user["lastName"]=$lastName;
$user["password"]=$password;
$user["position"]=$position;
$user["birthDate"]=$birthDate;
$user["qualification"]=$qualification;
$user["email"]=$email;
//now we need to pass the content to the phone,we send the array in a json
echo json_encode($user); // the java file that calls this method will receive echo
//The PHP json_encode function returns a string, containing the JSON equivalent of the values passed to it
//so in here $user array is passed throught the JSON String.
mysqli_stmt_close($statement);
mysqli_close($con);
?>
but the above php file is not fetching data from the mysql database.
I have created a Lectures table at the current users database and day time courseId hall year courseRefName and lecuturer are of String data type , noStudents and courseRefTelNo are of integer datatype.
Is there any mistake in the mysqli_prepare or in the way this is encoded to JSON, because Iam not getting any return from this (above) php file to my java in android application
I found the problem, it was the mismatch between the data sent via POST and in the database had caused the problem. I have sent time in form of 08.00-10.00 and in database they were as 08-10 in form of 5 digits. So if anyone encounter problems like these be first check the data in the database and the values you passed through POST method
Basically I know how to add one row to an external mysql database using android. Now im looking to add multiple rows at once. Heres my code so far.
PHP Script
<?php
$host="db4free.net"; //replace with database hostname
$username="xxxxxx"; //replace with database username
$password="xxxxxxx"; //replace with database password
$db_name="xxxxxxx"; //replace with database name
$con=mysql_connect("$host", "$username", "$password")or die("cannot connect");
mysql_select_db("$db_name")or die("cannot select DB");
/* Get the value in the whichfunction parameter
sent from the android application which will
determine the fucntion to call. */
$getFunctionToCall = $_POST['whichfunction'];
/* Depending on the value of the whichfunction
parameter switch to call different function */
switch ($getFunctionToCall){
case "AddUser":
echo AddUser($_POST['name'],$_POST['password']);
break;
}
/* Function to add user to the user table */
function AddUser($name,$password){
$sql = "insert into users(name,password) values('$name','$password')";
if(mysql_query($sql)){
return 1; // Return 1 for success;
}else{
return 2;// Return 2 for database error;
}
}
?>
Android Method
protected void SendToPhpFile() {
ArrayList<NameValuePair> pp = new ArrayList<NameValuePair>();
pp.add(new BasicNameValuePair("whichfunction", "AddUser"));
String[] names = {"David","Jimmy","Shane"};
String[] passwords = {"mypass1","mypass2","mypass3"};
for (int i=0;i<names.length;i++){
pp.add(new BasicNameValuePair("names[]", String.valueOf(names[i])));
pp.add(new BasicNameValuePair("passwords[]", String.valueOf(passwords[i])));
}
try{
status = "";
status = CustomHttpClient.executeHttpPost(ConnectBase.link, pp);
String res=status.toString();
res= res.replaceAll("\\s+","");
/* Depending on value you return if insert was successful */
if(res.equals("1")){
Toaster("Data successfully added.");
}else{
Toaster(status);
}
}catch(Exception e){
Toaster("Data successfully added: " + e.toString());
}
}
So I think I have the android size more or less sorted but I'm not 100%. If you guys could come up with a solution to how I've started that would be great. I've got zero experience with php so don't really know where to start when adding more than 1 row.
Thank you
Something like this maybe?
INSERT INTO table (name, password ) VALUES ('Name1', 'Password1'), ('Name2', 'Password2'),('Name3', 'Password3'), ('Name4', 'Password4')
Using mysqli you can not only avoid deprecated mysql functions but you can easily loop over insert values using prepared statements.
Referencing
In the following example we will be inserting usernames and passwords into the database in a safe and efficient way.
$x = array(array('bob','mypasswordlol'),array('your_mother','knitting5000'));
$stmt = $mysqli->prepare("INSERT INTO table (`username`, `password`) VALUES (?, ?)");
foreach ( $x AS $k => $value) {
$stmt->bind_param($stmt, "ss", $value[0], $value[1]);
$stmt->execute();
}
// close your connection
Hopefully this helps. Prepared statements are the bees knees when it comes to mysqli. It will help you prevent database injection and increase performance as well!
A client of mine wants clients names to be encrypted in the database, don't ask why they are just intent of it so I have been trying to do MySQL AES_Encrypt and AES_Decrypt using PHP so I would REALLY appreciate some help...
Encrypt Code
function addname ($name, $refid) {
include("../config.php");
// Open up a new MySQLi connection to the MySQL database
mysql_connect($dbHost, $dbUsername, $dbPassword);
mysql_select_db($dbTable);
$code = substr($output, 0, 8);
if (!isset($refid)) {
$refid = "ERROR";
}
$query = "INSERT INTO `clients` (fname, code, refid, active) VALUES (AES_ENCRYPT('$fname', UNHEX('F3229A0B371ED2D9441B830D21A390C3')), '$code', '$refid', 0)";
$runQuery = mysql_query($query);
if ($runQuery != true) {
return mysql_error();
} else {
return $code;
}
}
Decrypt Code
function decryptname() {
$input=947270;
include("config.php");
// Open up a new MySQLi connection to the MySQL database
mysql_connect($dbHost, $dbUsername, $dbPassword);
mysql_select_db($dbTable);
// Build the query
$sqlToRun = "SELECT * FROM `clients` WHERE code='$input' AND active=0";
// Run it
$check = mysql_query($sqlToRun);
while($row = mysql_fetch_array($check)) {
$encryptedname = $row['fname'];
$decryptedname = mysql_query("AES_DECRYPT('$encryptedname', UNHEX('F3229A0B371ED2D9441B830D21A390C3'))");
$check2 = $row['fname'];
}
mysql_close();
if (!isset($check2)) {
$check2 = "wow there is no check2";
}
exit($check2);
}
decryptname();
The Problem
MySQL Database shows the following value, which to be looks normal
e309367d1867c3273a8f8b298ed8beb3
Basically when ever I don't include the $decryptedname I get the following as a output
ã6}gÃ':‹)ŽØ¾³
If I do include it, I get a blank screen and no PHP or MySQL Errors?
Some More Information
The database column structure for names is
varbinary(9999)
If anyone can help me I would really appreciate it, if you need more info please ask!
UPDATE
I ran the following command in SQL and it returned NULL
SELECT AES_DECRYPT('password', "UNHEX('F3229A0B371ED2D9441B830D21A390C3')") FROM passwords WHERE code=947270
Take a look at PHP AES encrypt / decrypt, that should help you a lot.
Don't encrypt using MySQL, use PHP instead. You don't want queries taking any longer than they currently do performing reads & writes on the database.
I was having similar problems. My encrypted data field was a CHAR field. I read somewhere online (https://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html) that mysql may be cropping trailing blanks from the data and as a result corrupting it for the decrypt. Using a BLOB instead solved my problem.