PHP announcements system errors - php

I want to make a simple announcements system where you just type announcements in a box and it can be viewed by others. I get this error when I submit the form:
Edit:
Thanks, the php_announce.php now works, it does everything it's supposed to do, this is the new code :
<?php
// MySQL
$servername = "localhost";
$username = "testuser";
$password = "testpass";
$dbname = "testbase";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Content
$content = $conn->real_escape_string($_POST['content']);
$query="INSERT INTO announcements (content) VALUES ('$content')";
$conn->query($query)
?>
Edit: Thanks for the help I fixed the code like this:
after creating connection it does this:
$result=$conn->query("SELECT * FROM announcements");
#print_r($result);
while($row = $result->fetch_array(MYSQLI_ASSOC)){
echo $row['content']. " <br><br> ". "<b>Posted by: You</b>";
echo "<hr width=100%>";
}

In the first case, you need to provide a list of columns that correspond to the values you're trying to insert. e.g:
$query="INSERT INTO announcements (content) VALUES ('$content')";
Replace content with the name of the column in your table.
For the second one, the error message doesn't appear to correspond with the code you posted, but I'm guessing you forgot a semicolon on the preceding statement. Additionally, there's a missing ; in your last echo statement, although I'm not sure if that's what's causing the specific message you posted. Please repost the latest code from announce_out.php and I'll try to help.
There are some other issues with this approach in general. You're mixing mysqli and the older mysql, which is going to cause you additional errors. Instead of calling mysql_query(), you should be using $conn->query($query) so that you're actually using the connection you are establishing with new mysqli(). Additionally, to prevent injection attacks, you should escape your $content variable in this way:
$content = $conn->real_escape_string($_POST['content']);
This is a pretty basic way to escape strings and there are better methods like prepared statements that mysqli provides. I recommend checking out the page in the PHP manual: http://php.net/manual/en/mysqli.quickstart.php

The immediate answer to your problem is:
You need to escape the content and let the function quote it for you.
$content= mysql_real_escape_string($_POST['content'], $conn);
$query="INSERT INTO announcements VALUES ($content)";
and you need a missing semicolon at the end of the echo statement.
echo $row['content']. " <br><br> ". "<b>Posted by: You</b>";
The long term answer is you should really look into a database abstraction layers which help you avoid incredibly dangerous errors you're likely to make (like incorrectly escaping content). See php manual for some basic ones: http://php.net/manual/en/refs.database.abstract.php
But I also highly recommend using a higher level framework like Doctrine http://www.doctrine-project.org/.

Related

Multiple insert into from loop with check on existing field

I have read lots of forum threads and unable to solve my problem.
I'm parsing an XML file in a foreach loop and then want the parsed content to be inserted in a database table.
All is working fine but I have a problem while Inserting in the database.
Here's the code to make it "understandable" :
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
foreach ($articles->article as $article) {
$article_title = $article->title;
$article_alias = $article->alias;
...
$all_articles .= "('DEFAULT','$article_title','$article_alias'),";
}
$all_articles = rtrim($all_articles, ',');
$query = "INSERT INTO my_table (id,title, alias,) VALUES $all_articles";
My ID field is UNIQUE and Auto Increment.
What I want is to check if the alias field already exists, than update it or create new row.
I already checked ON DUPLICATE KEY UPDATE and REPLACE, but it doesn't fit my needs since it performs a duplicate check only on unique keys, or my alias field isn't and I can't change it.
Last thing I'm testing right now is to make a SELECT before INSERT INTO with a WHERE condition to look at my alias field.
I want to ask you a question here, and, if you can answer it, then you'll find the answer by yourself of your own question: What will happen if:
$article_title or $article_alias contain, hm, let's say something like "YMas's lazy programming skills"?
Let me help you - an SQL syntax error, because on this line:
$all_articles .= "('DEFAULT','$article_title','$article_alias'),";
you do not properly escape variables. Bingo, MySQL insert failed.
Rule number 1: ALWAYS, always properly handle your input data before INSERT/UPDATE/DELETE - i.e. either by using PDO and prepared statements (best), or by old-and-flawed mysqli_real_escape_string() function.
I solved it by using another joined table to be able to use ON DUPLICTAE KEY ENTRY on my alias field.
Thanks for those how helped !

User inputs, clean and sanitize before sending to db

I've searched a lot of the questions here and I found that they either very old or suggesting using prepared statements PDO which I am not using. So I need your help please.
I have a small discussion/chat box where a user submit a message using a <textarea>
What I need is sanitize and filter the user input so it only accepts plain texts (e.g. no tags, no html tags, no scripts no links, etc). Also, it is important to allow line breaks.
Based on my reading I am doing the following in the following order:
trim()
htmlentities($comment, ENT_NOQUOTES)
mysqli_real_escape_string()
nl2br()
Is what I am doing is right? or I am missing something?
Also is there anything I have to do when echoing the data from the db?
really, appreciate your help and kindness
First, keep the text logical and clean:
trim() -- OK
htmlentities($comment, ENT_NOQUOTES) -- No; do later
mysqli_real_escape_string() -- Yes; required by API
nl2br() -- No; see below
The logic behind those recommendations: The data in the database should be just plain data. Not htmlentities, not br-tags. But, you must do the escape_string in order to pass data from PHP to MySQL; the escapes will not be stored.
But... That is only the middle step. Where did the data come from? Older versions of PHP try to "protect" you be adding escapes and other junk that works OK for HTML, but screws up MySQL. Turn off such magic escaping, and get the raw data.
Where does the data go to? Probably HTML? After SELECTing the data back out of the table, then first do htmlentities() and (optionally) nl2br();
Note, if you are expecting to preserve things like <I> (for italic), you are asking for trouble -- big trouble. All a hacker needs to do is <script> ... to inject all sorts of nastiness into your web page and possibly your entire system.
You also have another option. You can use prepared statements with mysqli
They aren't very difficult to learn and work a bit better than mysqli_real_escape_string() in that you don't need to worry about escaping every single variable that will be in your query. They are by nature "prepared" before they go into the database. There are other advantages to this as well, in that:
you do not need to addslashes() to be able to handle characters with
apostrophes etc.
for large databases, they will considerably speed
up your queries (much like PDO).
Here's how to do it:
You connect to the database by creating a new mysqli object like this:
$conn = new mysqli($host, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $dbc->connect_error);
}
Next you want to convert your variables from your form.
Say you have a form field like this:
<input type="text" name="var1">
you can use htmlentities and trim together like so, and create your $var1 variable:
$var1 = htmlentities(trim($_POST['var1']));
Then you can create your transaction like this:
$stmt= $conn->prepare("insert into tablename (key1, key2) values (?,?)");
$stmt->bind_param("is",$var1, $var2);
$stmt->execute();
$stmt->close();
That's basically it. You do a query just like you normally would, but instead use the ? placeholders, assigning the datatype (above is i for integer, and s for string) and then bind them to your placeholders in the query.
That's basically it.
if you want to do it with a select with a variable, you use the normal select syntax and the same way with a ? with the variable, and then bind it. You can then bind your results into variables easily like so (assuming var3 is an integer):
$stmt= $conn->prepare("select var1, var2 from tablename where var3 = ?");
$stmt = bind_param("i", $var3);
$stmt->bind_result($var1, $var2);
$stmt->execute();
$stmt->close()
and then you can fetch your variables using this
$stmt->fetch();
or if your query brings back multiple rows
while ($stmt->fetch() {
echo $var1 . $var2;
}
nl2br() is used for output, you don't need to worry about input; it can be stored in the database as \n, and when you need it spits it out as breaks. If one of these variables needs the new lines turned into <br/> tags, you can, as you suggest use nl2br() on the variables (note this adds no security, but as you said you needed it), like so
echo nl2br($var1, false);
you can also use trim() and htmlentities() on this if it is being echoed into, say, a form input field and you don't want your form to break if there are html characters in the output.
Your question can lead me to build a full project with many features ;) lol
Before we start with out steps, we need a dummy (test) database for this scenario. We call out database chatbox with table called chat. You can simply create it by executing the following sql statement in your MySQL test environment:
CREATE TABLE `chat` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`msg` VARCHAR(200) NOT NULL DEFAULT '0',
`user_id` INT(11) NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
;
Now you can go a head and follow the steps here:
Step 1: Create project folder in your web server.
Build database connection based on PDO and call it dbConnect.inc.php:
<?php
// check if PDO driver not available
if (!defined('PDO::ATTR_DRIVER_NAME'))
echo 'PDO driver unavailable <br />';
// database configuration
$dbHost = "localhost";
$dbPort = "3306";
$dbName = "chatbox";
$dbUser = "root";
$dbPass = "";
$strDSN = "mysql:host=$dbHost:$dbPort;dbname=$dbName";
// database connection
try
{
$dbConn = new PDO($strDSN, $dbUser, $dbPass);
//Activate following line to view all error messages
$dbConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e)
{
die("Could not connect to the database $dbName, error info: <br />"
. $e->getMessage());
exit();
}
I will test this works before go to next step. Btw the prepared method does not require mysqli_real_escape_string().
I have used PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION in stead of if statements, this method will give you useful error details while development the project. You will find out which method is more practical for getting error message while your development process of the project.
Step2: Create a file call filter.inc.php:
<?php
// filter for input
function filterInput($content)
{
$content = trim($content);
$content = stripslashes($content);
return $content;
}
//filter for viewing data
function filterOutput($content)
{
$content = htmlentities($content, ENT_NOQUOTES);
$content = nl2br($content, false);
return $content;
}
This file contain a function to filterInput to sanitize or filter your input content for comments or other inputs. And filterOutput that effect your data view.
All depending on your strategy and what you need, like if you need to allow people post url's or email address, should url and email become active link or only viewed as text etc. that way you can define which filter should be use for your content input and which filter should be used for you content output.
You can add or delete extra features to functions. There are many features for text input and output, you can test those individually and evaluate it, and even extend the filter function or create your own function.
Final step 3: Now we put the puzzles together in our index.php file:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Chat box</title>
</head>
<body>
<?php include './dbConnect.inc.php'; ?>
<?php include './filter.inc.php'; ?>
<h1>Chat box</h1>
<p>
<?php
// this is dummy user id, but use the id over user id when login or the way you want
// this is only example
$user_id = 1;
if (isset($_POST["msg"]))
{
$msg = filterInput($_POST["msg"]);
$sql = "INSERT INTO chat "
. "(msg, user_id) "
. "VALUES "
. "(:msg, :user_id)";
$stmt = $dbConn->prepare($sql);
$fieldsArr = [':msg' => $msg, ':user_id' => $user_id];
$stmt->execute($fieldsArr)
// refresh page after insert
header("Location: " . $_SERVER['REQUEST_URI']);
}
?>
<form action="index.php" method="post">
<textarea name="msg" id="msg" required></textarea>
<input name="submit" type="submit">
</form>
</p>
<p>Comments</p>
<p>
<?php
$sql = "SELECT * FROM chat WHERE user_id = (:user_id);";
$stmt = $dbConn->prepare($sql);
$fieldsArr = [':user_id' => $user_id];
$stmt->execute($fieldsArr)
while ($result = $stmt->fetch())
echo "<h3>" . filterOutput($result['msg']) . "</h3>";
$dbConn = null;
?>
</p>
</body>
</html>
This is to demonstrate how things works. You have insert, select statement as example and filter functions. You can make tests, extend it the way you like or further develop your own project.
Here is screen shot of the chatbox example I made:
filter_input could be another one you are looking for. It can save you hours from writing sanitizing and validation code. Of course, it does not cover every single case, but there is enough so that you can focus more on specific filtering/validating code.
Though it is strongly recommended to use prepared statements with
PDO/mysqli. But sometimes it is not so easy to convert the whole
project in the tail end of the project. You should learn PDO/mysqli for
your next project.
$comment = filter_input(INPUT_POST, 'comment', FILTER_SANITIZE_STRING);
There are different Types of filters for you. You can select depending on your needs. You can also use filter_has_var to check for variable set.
Your code looks fine, if you don't want to prepare statements then escaping is the next best thing. And when you echo it should be straightforward, it's only plain text.

Can't add records to MySQL if the record contains an apostrophe

UPDATED VERSION
<?php
$link = mysqli_connect("localhost", "root", "root", "metadata");
mysqli_set_charset($link, "utf8");
// Check connection
if($link === false){
die("ERROR: Could not connect. " . mysqli_connect_error());
}
// my form located in index.php posts the data here.
$add_movie_original_name = $_POST['movie_original_name'];
$add_movie_tr_name = $_POST['movie_tr_name'];
$add_movie_year = $_POST['movie_year'];
$sql = "INSERT INTO movie(movie_original_name,movie_tr_name,movie_year) VALUES('$add_movie_original_name','$add_movie_tr_name','$add_movie_year')";
if(mysqli_query($link, $sql)){
echo "Records added successfully.";
} else{
echo "ERROR: Could not able to execute $sql. " . mysqli_error($link);
}
// close connection
mysqli_close($link);
?>
I can't add records if there is an apostrophe in it. For instance, Uncle Sam's can't be added.
Here is the error I get. I tried to add a movie named Movie's Name.
ERROR: Could not able to execute INSERT INTO movie(movie_original_name,movie_tr_name,movie_year) VALUES('Movie's Name','','2014'). You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 's Name','','2014')' at line 1
(I deleted my comments, so line number will be different)
I think I should use a trick to escape the characters, but couldn't find out how.
You nee to be preparing your statements so that you aren't vulnerable to an SQL Injection attack. To do this, you should be using mysqli prepared statements. Your current code would look like this as a prepared statement
$mysqli = new Mysqli("localhost", "root", "root", "metadata");
$statement = $mysqli->prepare("INSERT INTO movie(movie_original_name,movie_tr_name,movie_year) VALUES('?','?','?')");
$statement->bind_param('sss', $add_movie_original_name, $add_movie_tr_name, add_movie_year);
$statement->execute();
Notice how in the actual SQL, I've replaced your variables with ?'s, this let's them be bound later on. In my bind_param method, the first parameter is how many variables you're binding, and what data types they are. There's one character for each variable, and they're all strings, so that character is "s". If you wanted to bind integers and strings, you would use
$statement->bind_param('sis', $string1, $int1, $string2);
Notice how the order of "sis" matches the order of what's passed it, string then integer then string again. According to the PHP Manual, there are four different types you can pass in, each with their own characters
s for string
i for integer
d for double
b for blob
So that's a short explanation of bound params. The problem you're having comes from the fact that your variables aren't escaped or bound, leaving them open to injection. This will fix your problem and make your code a little bit more secure.
Note: As pointed out by #bcintegrity, this isn't the be all end all for security. You're going to want to look into using htmlspecialchars() when echoing out your data that's been entered in by users in order to stop XSS (Cross Site Scripts) which can be very dangerous to not patch up.
Make it a priority to use prepared statements. Prepared statements simply send the query separate from the values, so the db knows the values are not to be run as code. Prepared statements escape the values automatically :)
Here is an example:
$sqli = #mysqli_connect("localhost", "root", "root","metadata");
if (!$sqli) {die("Can not connect to the database: " . mysqli_connect_error());}
$result = "INSERT INTO `movie`(movie_original_name,movie_tr_name,movie_year) VALUES (?,?,?)";
$stmt = mysqli_prepare($sqli, $result);
mysqli_stmt_bind_param($stmt,"sss",$_POST['movie_original_name'],$_POST['movie_tr_name'],$_POST['movie_year']);
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
Be sure to use htmlspecialchars() if echoing values onto the page to protect from XSS:
$original_name_onscreen = htmlspecialchars($_POST['movie_original_name']);
$tr_name_onscreen = htmlspecialchars($_POST['movie_tr_name']);
$year_onscreen = htmlspecialchars($_POST['movie_year']);
Note: #Gareth Parker's example is object oriented style, similar to PDO, while mine is procedural style, similar to MySQL. Both are acceptable.

Some posts not updating in database

I'm using a forum type system for users to ask questions or say whats on their minds and I'm having a problem related to updating database information. I have no idea what's wrong here but I do know what's happening.
Some posts cannot be edited. Everything will happen as usual but will not update the database. Some posts have the wrong body but the correct title.
It doesn't make sense and I'll do some tests to check if the mysql is working.. but until then, any thoughts?
UPDATE:
This query is passing... but the database isn't updating for this particular row. This one only...
$new_body = $_POST['new_body'];
$old_body = $_POST['old_body'];
mysql_query("UPDATE questions SET body='".htmlspecialchars($new_body, ENT_QUOTES)."' WHERE body='".htmlspecialchars($old_body, ENT_QUOTES)."'") or die(mysql_error());
Also, if someone could enlighten me on SQL Injections and how to prevent them, I'd greatly appreciate it.
The columns are id, pin, locked, body, date, numberofcomments (i know I can just use php to read the amount of comments but I did this prior to learning that) and views.
UPDATE: Works now. Replaced the WHERE body to WHERE id. Stupid mistake. I could still use some sql injection enlightening though!
As I mentioned in comments first of all use a primary key in your WHERE clause to target specific record in your table instead of using body column. That being said your update statement should look something like this
UPDATE questions SET body = ? WHERE id = ?
Now to prevent sql injections use switch to mysqli_* or PDO extension and use prepared statements instead of interpolating query strings.
Your code using prepared statements with mysqli_* might look like
$id = $_POST['id'];
$new_body = $_POST['new_body'];
$old_body = $_POST['old_body'];
//Do validation, sanitation, and encoding if necessary here before you put into database
...
$db = new mysqli('localhost', 'user', 'password', 'dbname');
if ($db->connect_errno) {
die('Connection failed: %s\n' . $db->connect_error); //TODO better error handling
}
$sql = 'UPDATE questions SET body = ? WHERE id = ?';
$stmt = $db->prepare($sql);
if (!$stmt) {
die('Can\'t prepare: ' . $db->error); //TODO better error handling
}
$stmt->bind_param('si', $new_body, $id);
$stmt->execute();
$stmt->close();
$db-close();
Further reading:
How can I prevent SQL injection in PHP? It's the absolute must read
Please use Mysqli or PDO. Mysql_* is deprecated and insecure.
Have you tried checking if the post exists? As it seems a problem that the post doesn't exist or it's not finding it.
Do you get any mysql_error's or any output from mysql?
Also have you tried updating using phpmyadmin - Seeing if it outputs any errors there?
$new_body = $_POST['new_body'];
$old_body = $_POST['old_body'];
mysql_query("UPDATE questions SET body='".htmlspecialchars($new_body, ENT_QUOTES)."' WHERE body='".htmlspecialchars($old_body, ENT_QUOTES)."'") or die(mysql_error());
I haven't used mysql_ in a while, in favour of PDO, so this syntax may be incorrect. But you could try this:*
$new_body = htmlentities($_POST['new_body']);
$old_body = htmlentities($_POST['old_body']);
$sql1=mysql_query("SELECT * FROM questions WHERE body='$old_body'") or die(mysql_error());
if(mysql_num_rows($sql1)>"0")
{
$res=mysql_query("UPDATE questions SET body='$new_body'") or die(mysql_error());
echo 'Updated';
}
else
{
//Insert.
}

i am trying to get data from input box and pass it to the database need help not able to get result

i am trying to get data from input box and pass it to the database to show appropriate records and results but need help not able to get result
<html>
<body>
</body>
</html>
<?php>
$prod_name = $_POST["name_of_the_product"];
echo [$prod_name];
$db_host = "localhost";
$db_username = "acwj_price";
$db_pass = "";
$db_name = "acwj_price";
mysql_connect("$db_host","$db_username","$db_pass") or die ("Please Try Again");
mysql_select_db("wikiacwj_price") or die ("no data");
$sql = mysql_query("SELECT * FROM price_comparsion where product_name="prod_name"");
//write the results
while ($row = mysql_fetch_array($sql)) {
echo $row['product_name'];}
?>
</body>
</html>
Warning: CARGO CULT PROGRAMMING DETECTED!. You've got syntax errors galore, you've got SQL injection holes, you've got useless error handling, blah blah blah. In other words, the code is a mess.
1) echo [$prod_name]; what are the [] for here? This is a flat out syntax error
2) mysql_connect("$db_host" etc... - why the "" around variables? You'r creating a new empty string, embedding another string inside that - a total waste of cpu cycles.
3) or die ("Please Try Again"); - of what use is it to tell your site's user to try again? If your code can't log into mysql, how is the user supposed to fix this? Hammering on reload won't make an invalid mysql login magically start working again. If you're the only user of the code, at least have a useful error message output, explaining why the script is dying, e.g. or die(mysql_error()).
4) ... where product_name="prod_name""). You've got another horrendous syntax error here - you cannot embed quotes within a string that is built with the same type of quotes you're trying to embed.
4a) Should that be ... product_name='$prod_name'", perhaps, so you're actually embedding the form value that was passed in?
4b) $prod_name is now your SQL injection source, and you should have AT MINIMUIM $prod_name = mysql_real_escape_string($_POST['name_of_product']), and have it somewhere AFTER you connect to the DB, since m_r_e_s() only works when you have an active DB connection.
We need more context to give you a solid answer, however reviewing your code I've found the following things that are causing problems:
echo [$prod_name]; is incorrect - should be echo $prod_name;
Also, the mysql_connect is incorrect - should be: mysql_connect($db_host,$db_username,$db_pass) or die ("Please Try Again");
(you should not have quotes around the variables)
And the sql statement is incorrect - should be:
$sql = mysql_query("SELECT * FROM price_comparsion where product_name='" . mysql_real_escape_string($prod_name) . "'");
(corrected the quoting, changed to pass in the variable, and added mysql_real_escape_string as minimum sql error prevention)
Note: This does NOT reflect best practices with SQL - there's all sorts of SQL Injection attack vulnerabilities in the original code - this code is only revised to work. If you will be writing code like this, you should should read about SQL Injection prevention. There's plenty of good information on StackOverflow - here's just one example: SQL Injection, Quotes and PHP

Categories