i've read a lot of posts concerning similair problem with utf-8 issues and tried some too but i can't find the cause.
I'm using livecode and i want to encrypt some strings to a database. So i encrypt in Livecode then base64encode then send to database via PHP/PDO.
encrypt-->base64encode-->base64decode-->decrypt within livecode works ok.
Now when i send the base64encoded data to the MariaDB database it saves it, except + has become a space.
The database, table and columns are all utf8mb4_unicode_ci.
If i change the space to + manually via phpmyadmin in the database and read out with Livecode then it base64decodes-->decrypts correct!
This are the php files i use to connect and update the db:
<?php
// the connect.php file
$servername = "localhost";
$username = "blabla";
$password = "blabla";
try {
//$db = new PDO("mysql:host=$servername;dbname=blabla",$username, $password);
$db = new PDO("mysql:host=$servername;dbname=blabla;charset=utf8", $username, $password);
//$db = new PDO("mysql:host=$servername;dbname=blabla;charset=utf8mb4", $username, $password,array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'"));
// set the PDO error mode to exception
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//echo "Connected successfully";
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
?>
you can see i tried some charsets in the connect file also
<?php
//this is the file to update the DB
require_once 'connect.php';
//
try {
$stmt = $db->prepare("UPDATE tabel_users SET user=:user,
password=:password, email=:email, userlevel=:userlevel WHERE
id_user=:id_user");
$stmt->bindParam(':id_user', $_POST['id_user'], PDO::PARAM_INT);
$stmt->bindParam(':user', $_POST['user'], PDO::PARAM_STR);
$stmt->bindParam(':password', $_POST['password'], PDO::PARAM_STR);
$stmt->bindParam(':email', $_POST['email'], PDO::PARAM_STR);
$stmt->bindParam(':userlevel', $_POST['userlevel'], PDO::PARAM_STR);
//$stmt->bindParam(':user', $_POST['user'], PDO::PARAM_LOB);
//$stmt->bindParam(':password', $_POST['password'], PDO::PARAM_LOB);
//$stmt->bindParam(':email', $_POST['email'], PDO::PARAM_LOB);
//$stmt->bindParam(':userlevel', $_POST['userlevel'], PDO::PARAM_LOB);
$affected_rows = $stmt->rowCount();
if($stmt->execute()) { echo "Ge-update informatie verzonden naar de
database!"; } else { echo "Failure!"; };
}
catch(PDOException $e)
{
echo "Not updated: " . $e->getMessage();
}
//var_dump($_POST)
$db = NULL;
?>
Also tried PDO::PARAM_LOB
Tried VARCHAR VARBIN BLOB but this did not change a thing.
My first guess was that Livecode does something weird while posting it to the php file. But checking the variable just before it is send has the + in the string to send. So i don't really get it where it goes wrong.
Your issue is not with the database it is that php is url decoding your base64 string, that will convert '+' to ' ' (plus to space). You need to urlencode your password parameter before posting it. Here's the LiveCode doc for URLEncode.
It depends on the content type of your post as explained in more detail here.
I had the same problem but going from PHP to livecode and I got as far as concluding that the problem was with php encryption vs livecode encryption. if you try base encoding without encryption they will play nice. I don't have an answer for it though, but I remember the experts saying its got to do with the "header" of the encrypted binary. ideally i would like to see an answer to this problemnas I ended up going without encryption to get around it.
When I use base64 encoding to share data with another system (javascript)I always use this code after encoding:
Replace space with empty in tEncodedData.
LC adds spaces for base64encode. It works fine when I remove them.
Related
Sometimes it sucks when you have these ; " ' (semicolon, single and double quotation marks) everything in a string.
Question is simple what is the easiest way to send those sting into the database.
base64_encode();
base64_decode();
// Is not an option. I need to keep those data just same as it is.
You need
addslashes('your text') // in your php page
PDO statements is the best solution to your problem of executing SQL queries to your database with values that have single/double quotation marks... but more importantly PDO statements help prevent SQL injection.
To show you how this works, this very simple example gives you a basic understanding of how PDO statements work. All this example does is make the connection to the database and insert the username, email and password to the users table.
<?php
// START ESTABLISHING CONNECTION...
$dsn = 'mysql:host=host_name_here;dbname=db_name_here';
//DB username
$uname = 'username_here';
//DB password
$pass = 'password_here';
try
{
$db = new PDO($dsn, $uname, $pass);
$db->setAttribute(PDO::ERRMODE_SILENT, PDO::ATTR_EMULATE_PREPARES);
error_reporting(0);
} catch (PDOException $ex)
{
echo "Database error:" . $ex->getMessage();
}
// END ESTABLISHING CONNECTION - CONNECTION IS MADE.
$username = $_POST['username'];
$email = $_POST['email'];
$password = $_POST['password'];
$hashed_password = password_hash($password, DEFAULT_BCRYPT);
//Validation on inputs here...
// Your SQL query... here is a sample one.
$query = "INSERT INTO users (userName, email, password) VALUES (:userName, :email, :password)";
$statement = $db->prepare($query);
// The values you wish to put in.
$statementInputs = array("userName" => $username, "email" => $email, "password" => $hashed_password);
$statement->execute($statementInputs);
$statement->closeCursor();
?>
You could put the establishing connection part in a separate file and require_once that file to avoid having to write the same code, again and again to establish a connection to your database.
Use mysqli_real_escape_string
$someText = mysqli_real_escape_string($con,"It's a test.");
where $con is your database connection variable.
I have a simple question. I'm not too good at programming yet but is this safe and correct?
Currently I am using functions to grab the username, avatars, etc.
Looks like this:
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
config.php ^^
function getUsername($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT username FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$name = $stmt->fetch();
return $name["username"];
}
function getProfilePicture($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$image = $stmt->fetch();
return $image["profilepicture"];
}
Is this correct and even more important, is this safe?
Yes, it's safe with respect to SQL injections.
Some other answers are getting off topic into XSS protection, but the code you show doesn't echo anything, it just fetches from the database and returns values from functions. I recommend against pre-escaping values as you return them from functions, because it's not certain that you'll be calling that function with the intention of echoing the result to an HTML response.
It's unnecessary to use is_int() because MySQL will automatically cast to an integer when you use a parameter in a numeric context. A non-numeric string is interpreted as zero. In other words, the following predicates give the same results.
WHERE id = 0
WHERE id = '0'
WHERE id = 'banana'
I recommend against connecting to the database in every function. MySQL's connection code is fairly quick (especially compared to some other RDBMS), but it's still wasteful to make a new connection for every SQL query. Instead, connect to the database once and pass the connection to the function.
When you connect to your database, you catch the exception and echo an error, but then your code is allowed to continue as if the connection succeeded. Instead, you should make your script die if there's a problem. Also, don't output the system error message to users, since they can't do anything with that information and it might reveal too much about your code. Log the error for your own troubleshooting, but output something more general.
You may also consider defining a function for your connection, and a class for your user. Here's an example, although I have not tested it:
function dbConnect() {
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
error_log("PDO connection failed: " . $e->getMessage());
die("Application failure, please contact administrator");
}
}
class User {
protected $row;
public function __construct($userid) {
global $conn;
if (!isset($conn)) {
$conn = dbConnect();
}
$stmt = $conn->prepare("SELECT username, profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$this->row = $stmt->fetch(PDO::FETCH_ASSOC);
}
function getUsername() {
return $this->row["username"]
}
function getProfilePicture() {
return $this->row["profilepicture"]
}
}
Usage:
$user = new User(123);
$username = $user->getUsername();
$profilePicture = $user->getProfilePicture();
That looks like it would work assuming that your config file is correct. Because it is a prepared statement it looks fine as far as security.
They are only passing in the id. One thing you could do to add some security is ensure that the $userid that is passed in is the proper type. (I am assuming an int).
For example if you are expecting an integer ID coming in and you get a string that might be phishy (possible SQL injection), but if you can confirm that it is an int (perhaps throw an error if it isn't) then you can be sure you are getting what you want.
You can use:
is_int($userid);
To ensure it is an int
More details for is_int() at http://php.net/manual/en/function.is-int.php
Hope this helps.
It is safe (at least this part of the code, I have no idea about the database connection part as pointed out by #icecub), but some things you should pay attention to are:
You only need to require your config.php once on the start of the file
You only need to prepare the statement once then call it on the function, preparing it every time might slow down your script:
The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query. - PHP Docs
(Not an error but I personally recommend it) Use Object Orientation to help organize your code better and make easier to mantain/understand
As stated by #BHinkson, you could use is_int to validate the ID of the user (if you are using the IDs as numbers)
Regarding HTML escaping, I'd recommend that you already register your username and etc. HTML escaped.
I'm trying to get a simple PDO insert to work. I have successfully created a tabled named mydb10 using PDO, and the next part I want to do is insert data into that table. Running the script does not return any errors (PDO error mode exception is enabled), but the table still contains null values.
I'm using a local server to run the PHP file, and am connecting to an Amazon RDS database. Currently all inbound traffic through SSH, HTTP, HTTPS, and MYSQL is allowed through the database's security group
$link = new PDO("mysql:host=$dbhost;dbname=$dbname",$username,$password);
$statement = $link->prepare("INSERT INTO mydb10 (selectedMain, selectedSide)
VALUES(:selectedMain, :selectedSide)");
$statement->execute(array(
"selectedMain" => "test",
"selectedSide" => "test2"
));
This might be silly, but I've been stuck for a while now and any help is appreciated. If you'd like any more information, let me know. I'm trying to utilize PHP in my app, but can't even get this simple test to work, so it's a bit discouraging.
EDIT # 1
This snippet is part of a larger file. I am able to successfully
connect to the database with my credentials and create new tables on the server. I do have PDO error reporting enabled in exception mode, and it has helped me work past syntax errors, but I am no longer getting any errors when I run the code. There are also no errors on the MYSQL server log.
I can provide any additional information that may be useful in debugging if desired.
First you need to properly set connection to MySQL database. You can write this code to sql.php:
<?php
$ServerName = "******";
$Username = "******";
$Password = "******";
$DataBase = "******";
try {
$CONN = new PDO("mysql:host=$ServerName; dbname=$DataBase", $Username, $Password);
$CONN->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$CONN->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
?>
Now, when you properly set connection, you need to execute sql, but before this you need to include sql.php:
try {
$SQL = 'INSERT INTO MyDB10 (SelectedMain, SelectedSide) VALUES(:SelectedMain, :SelectedSide)'; // Write SQL Query to variable
$SQL = $CONN->prepare($SQL); // Prepare SQL Query
$SQL->execute(array('SelectedMain' => 'Test', 'SelectedSide' => 'Test2')); // Execute data to Insert in MySQL Databse
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
When you finish all queries you must close connection with:
$CONN = null;
The following script has been outputting images from a BLOB column in MySQL for a good time now:
<?
$dbname="usr_web5_1";
$db = new mysqli($dbhost, $dbuser, $dbpwd, $dbname);
$sql = "SELECT foto, fototype, modified FROM `Komplettverzeichnis_extras` WHERE `WPID`= ?";
$stmt = $db->prepare($sql);
$stmt->bind_param("s",$_GET['id']);
if (!$stmt->execute()) $error=true;
$stmt->bind_result($file,$filetype,$modified);
$stmt->fetch();
if (!isset($filetype)) $filetype = "image/jpeg";
if (!$error) {
header("Content-type: $filetype;");
header("Last-Modified: $modified;");
} else {
echo "Error";
echo $db->error;
}
echo $file;
$stmt->close();
$db->close();
}
?>
I have tried both altering the column to LONGBLOB and replacing it by a new LONGBLOB colument; the images will not show. This is regardless wether I try to show the images already in place or I try and upload new ones.
The closest problem I found is here (german). For altering the column I used
ALTER TABLE `Komplettverzeichnis_extras` CHANGE `foto` `foto` LONGBLOB DEFAULT NULL
Obviously I am willing to provide more information if necessary.
I use phpMyAdmin in version 3.5.2.2, PHP 5.3.17, and mysql client API version (is that the mysql version?) 5.1.63.
Thanks in advance!
Okay I figured out the problem:
For a BLOB, the mySQLi Methods for strings will work that are used in my code as you can see above. This is not the case for Longblob. After the execute() and before the bind_result(), a store_result() is necessariy. Also, When saving, I cannot simply use bind_param(). Instead, the following construction using a NULL has to be used:
if (!$stmt = $db->prepare($sql)) printf($db->error);
$null = NULL;
$stmt->bind_param("bsi",$null,$type,$id);
$stmt->send_long_data(0,$data);
if (!$stmt->execute()) printf($db->error);
$stmt->close();
To cut it short, the following ressource helped me out:
Oswald#Work
Thank you all anyway for your efforts!
I have a register.php file which takes the input from a form and tries to create a user account in a database. I have an innoDB MySQL database which has a 'UNIQUE' key added to the 'username' field of the users table. This is to prevent duplicate usernames.
Below is an extract from my php code. In my database I currently have a user called 'testUser'. However, when running the code below with $username = testUser, the php file returns 'Account created', even though a duplicate row is not created in the database. I would have expected there to be an exception thrown if the user already existed?
try{
$stmt = $db->prepare("INSERT INTO users (username, password, salt) VALUES (:username, :password, :salt)");
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $hash);
$stmt->bindParam(':salt', $salt);
$stmt->execute();
}catch(PDOException $e){
returnJSON(0,'Error creating account');
}
returnJSON(1,'Account created');
function returnJSON($errorCode, $message){
$arr = array("returnCode" => $errorCode, "returnMessage" => $message);
echo json_encode($arr);
die();
}
----
try{
$db = new PDO('mysql:host='.$host.';dbname='.$dbname, $username, $password);
}
catch(PDOException $e){
$arr = array("returnCode" => 0, "returnMessage" => "unable to connect to server");
echo json_encode($arr);
die();
}
My question is, how should I find out if the user's account was successfully added to the database.
PS. I do have code to query the database first and see if there exists a user with the same name before calling this code. But I'd still like to fix/understand this as well.
PDO by default has silent errors: you need to check then yourself by actually looking for them.
If you want to use exceptions, you need to tell PDO to do it. Check http://php.net/manual/en/pdo.error-handling.php
The specific code you want is
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
in the try/catch immediately after you create the connection.
catch (PDOException $er) {print("error".$er."<br />");}
When you catch an Error, the flow of the program continues, try catching the Error and stopping the flow, using exit();
What I am saying is , even if an exception is caught, the following line of code should stil execute,
returnJSON(1,'Account created');
unless you are stopping the flow somehow. Would really appreciate if you post the entire file, including functions you are using.