I set up a new MySQL database and created some PHP Web pages. The IDs for each entry are composed of three digits and have leading zeros (e.g., 000, 001, 002).
My main page that shows every ID as a separate row in an HTML table works fine -- it displays every entry. But my individual entry page is not returning specific entries. For example, the URL entry.php?id=001 and entry.php?id=002 returns the entry for every ID.
I believe the error is at the beginning of the entry.php code, which looks like this:
$query = 'SELECT * FROM databasetablename';
if (isset($_GET['id']) && is_numeric($_GET['id']))
{
$query .= ' WHERE id = ' . (int)$_GET['id'];
}
$result = mysql_query($query);
while($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
... and the code goes on. But I think the error is in this part.
You are casting $_GET['id'] as int after which $_GET['id'] is now = 1
I assume page IDs in database are not of a numeric type, but of CHAR/VARCHAR/TEXT. In this case you should try this:
$query = 'SELECT * FROM databasetablename';
if (isset($_GET['id']) && is_numeric($_GET['id']))
{
$query .= ' WHERE CAST(id AS INTEGER) = ' . (int)$_GET['id'];
}
$result = mysql_query($query);
As a side note: consider using PDO with parameter binding instead of building queries directly from request parameters. This would be extremely dangerous:
$query = ' WHERE CAST(id AS INTEGER) = ' . $_GET['id'];
EDIT: You could also try using mysql_real_escape_string():
$query .= ' WHERE id = ' . mysql_real_escape_string($_GET['id']);
but in this case you should read the security warning about character sets here: http://php.net/manual/en/function.mysql-real-escape-string.php
EDIT2: Sorry, I cannot write comments at the moment, but since you said that it returns every entry it could only mean that the WHERE condition is not added. Check if you actually receive the "id" request parameter in entry.php by using var_dump($_GET).
Related
1) I have url like this :
http://example.com/post.php?id=1234
And inside : my article
2) but for this url
http://example.com/post.php?1234somewords
It's also work, i see my article
3) and for this url
http://example.com/post.php?somewords
I have good 404 page error
Question is : how could i have 404 error for the 2) url ?
(alternative question : how could i redirect "1234somewords" to "1234" ?)
php mysql query inside post.php is :
require_once('conn_sql.php');
$post = $_GET['post'];
$nQuery = mysqli_query($conn, "SELECT * FROM `post` WHERE post_id = '$post'");
$res = mysqli_fetch_array($nQuery);
It seems that the query "post=1234somewords" works, and this is not what i want.
however, if i search "post=1234somewords" in phpmyadmin, this not works, and this is what i want !
What is the problem with my code ?
this happen because mysql use the beginning part of the string as a valid id .. (this i related to the implic data conversion performed by mysql) you should check if your parameter are valid number before perform the query
you could try removing the not numeric value from the string
$result = preg_replace("/[^0-9]/", "", $_GET['post']; );
if (is_numeric( $result)) {
$nQuery = mysqli_query($conn, "SELECT * FROM `post` WHERE post_id = '$post'");
$res = mysqli_fetch_array($nQuery);
} else {
......
}
My database fields are not populating but the page is confirming that it exists. So the first SQL is working, but the second is not pulling the info. If i take the page check out. It doesn't find the page and redirects to page_not_found. Am I going about this correctly? What am i doing wrong here?
//get page url and query db
$this_page = $_GET['page'];
$this_page = escape_data($_GET['page']);
//Make sure page exist
$SQL_page_exist = "SELECT page_title FROM learn_more WHERE page_title = '$this_page'";
$SPE_result = mysql_query($SQL_page_exist);
if(mysql_num_rows($SPE_result) == 0)
{
echo '<META HTTP-EQUIV="Refresh" Content="0; URL=page_not_found.php">';
}
else {
$SQL =
"SELECT * FROM learn_more AS lm
INNER JOIN learn_more_to_reference_key AS lmtrk
ON lm.id = lmtrk.learn_more_id
INNER JOIN reference_keys AS rk
ON rk.keys_id = lmtrk.reference_key_id
WHERE page_title = '$this_page'";
$result = mysql_query($SQL);
while ($db_field = mysql_fetch_assoc($result));
{
$id = $db_field['ID'];
$main_title = $db_field['main_title'];
$main_content = $db_field['main_content'];
$reference_keys = $db_field['keys_href'];
$sub_title = $db_field['sub_title'];
$sub_content = $db_field['sub_content'];
}
}
mysql_close($dbc);
You should remove the semi-colon after your while statement since it won't execute the following enclosure (meaning your query is fine, but the while statement is invalid).
Also, I'm not sure, but the statement:
$id = $db_field['ID'];
Might generate an error if the mysql field is 'id' (lowercase). While MySQL isn't (usually) case sensitive, php array keys are, so it may be that the key is only available as 'id' and not 'ID'...
Turns out that an empty field from a relational db table (just 1 black field) which is set to not null was causing this undefined break error.. ON ALL PAGES except the home page..
Thank you to all the people who tried to help me.
As i am trying to increment the counter to plus 1 every time when the user clicks on the image. I have written the following code but it says some error "Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\xampp\htdocs\tkboom\includes\core.php on line 72". Can anyone look into this where i made a mistake..
Actually i have created 2 php files one for incrementing the counter and one for displaying the counter. In core.php file i have written the function and for displaying the count i have created a file called view.php
core.php
function GenerateCount($id, $playCount) {
global $setting;
$counter_query = "SELECT hits FROM ava_games WHERE id=".$_GET['id']."";
$counter_res = mysql_query($counter_query);
while($counter_row = mysql_fetch_array($counter_res)){
$counter = $counter_row['hits'] + 1;
$update_counter_query = "UPDATE ava_games SET hits=".$counter." WHERE id=".$_GET['id']."";
$playCount = mysql_query($update_counter_query);
$playCount = $row['hits'];
}
return $playCount;
// Get count END
}
view.php
<?php
$sql = mysql_query("SELECT * FROM ava_games WHERE published=1 ORDER BY id desc LIMIT 30");
while($row = mysql_fetch_array($sql)) {
$url = GameUrl($row['id'], $row['seo_url'], $row['category_id']);
$name = shortenStr($row['name'], $template['module_max_chars']);
$playRt = GenerateRating($row['rating'], $row['homepage']);
$playCt = GenerateCount($row['id'], $row['hits']);
if ($setting['module_thumbs'] == 1) {
$image_url = GameImageUrl($row['image'], $row['import'], $row['url']);
$image = '<div class="homepage_game"><div class="home_game_image"><img src="'.$image_url.'" width= 180 height= 135/></div><div class="home_game_info"><div class="home_game_head">'.$name.'</div></div><div class="home_game_options"><img class="home_game_options_icon" src="'.$setting['site_url'].'/templates/hightek/images/joystick-icon.png" /> '.$playRt.' <b>|</b> '.$playCt.' plays </div></div>';
echo $image;
}
}
?>
That most likely means that there's an error in the sql statement. You can get more information about the error via mysql_error().
In its simplest form:
$counter_res = mysql_query($counter_query) or die(mysql_error());
(edit: ...simplest form, but with this approach you don't give the application a chance to react to the problem, "die" as in "dead". And mysql_error() can leak too much information to a user of your webservice/website, see https://www.owasp.org/index.php/Top_10_2007-Information_Leakage_and_Improper_Error_Handling)
Your code is also prone to
sql injections, because the $_GET parameter is put into the statement without sanitizing it first
race conditions because you have a compound operation consisting of one SELECT and one UPDATE without any locking mechanism.
This is because you get the error in your SQL query.
I'd change it a little bit:
$counter_query = 'SELECT hits FROM ava_games WHERE id = ' . (int)$_GET['id'];
to make sure you always compare id against integer value.
After all, this query does not look good. First point: why are you using two queries to increment a value? UPDATE ava_games SET hits=hits+1 WHERE id=".$_GET['id'].""should do this in one step. Second point: have you heard about SQL injections? Escape or cast $_GET['id'] to avoid surprises ;)
Convert the value in int first like that:
function GenerateCount($playCount) {
global $setting;
$counter_query = "SELECT hits FROM ava_games WHERE id=".$_GET['id']."";
$counter_res = mysql_query($counter_query);
while($counter_row = mysql_fetch_array($counter_res)){
$counter = intval($counter_row['hits']) + 1;
$update_counter_query = "UPDATE ava_games SET hits=".$counter." WHERE id=".$_GET['id']."";
$playCount = mysql_query($update_counter_query);
$playCount = $row['hits'];
}
return $playCount;
// Get count END
}
and check link:
Convert into int
If mysql_query returns a Boolean, your query failed.
Presuming id is the primary key, you can use the following function to update on a database level which will prevent race conditions:
function GenerateCount($playCount) {
global $setting;
$update_counter_query = "UPDATE ava_games SET hits=hits + 1 WHERE id=".intval($_GET['id'])."";
mysql_query($update_counter_query) or die(mysql_error());
$counter_query = "SELECT hits FROM ava_games WHERE id=".intval($_GET['id'])." LIMIT 1";
list($playCount) = mysql_fetch_row(mysql_query($counter_query));
return $playCount;
// Get count END
}
also note the intval() around the $_GET variable to prevent SQL injection
I have php application which gets information from a SAML POST and creates a record in the MySQL database, if the record is already present it just updates it
Here is the code
//getMemberRecord returns true for successful insertion.
$row = $this->getMemberRecord($data);
if ($row) {
//if the row already exists
$this->updateMemberRecord($data)
} else {
// creates a new record
$this->setMemberRecord($data);
}
This code is causing double inserts in the database, we don't have a unique key for the table due to some poor design constraints, but I see two HTTP posts in the access logs happening at the same time.
The create date column is same or differs by a second for the duplicate record.
This issue is happening for only select few, it works for most of them.
The table is innoDB table and we can not use sessions on our architecture.
Any ideas of why this would happen
You said:
I see two HTTP posts in the access logs
You should try avoiding this and have just one http POST invocation
May be it is a problem related to concurrency and mutual exclusion. The provided code must be executed in a mutually exclusion zone, so you must use some semaphore / mutex to prevent simultaneous execution.
If you have two HTTP POST happening your problem is not on the PHP/MYSQL side.
One thing is allowing a second 'transparent' HTTP POST in the HTTP protocol. It's the empty url. If you have an empty GET url in the page most browsers will replay the request which rendered the page. Some recent browser are not doing it, but most of them are still doing it (and it's the official way of HTTP). An empty GET url on a page is for example <img src=""> or < script url=""> but also an url() in a css file.
The fact you have one second between the two posts make me think it's what's happening for you. The POST response page is quite certainly containing an empty Get that the browser fill by replaying the POST... I hate this behaviour.
I found that the double inserts were happening becuase double submits and our application doesnot handle double submits efficiently, I read up on some articles on this, here are some of the solutions
it always best to handle double posts at the server side
best solution is to set a UNIQUE KEY on the table or do a INSERT ON DUPLICATE KEY UPDATE
if you have sessions then use the unique token , one of the technique in this article
http://www.freeopenbook.com/php-hacks/phphks-CHP-6-SECT-6.html
or use can use the Post/Redirect/Get technique which will handle most double submit problems
http://en.wikipedia.org/wiki/Post/Redirect/Get
note: the Double submit problem only happens on a POST request, GET request is immune
public function setMemberRecord($data, $brand_id, $organization_id, $context = null)
{
global $gRegDbManager;
$sql = "insert into member ......"
$gRegDbManager->DbQuery($sql);
// Popuplate the iid from the insert
$params['iid'] = $gRegDbManager->DbLastInsertId();
$data = some operations
return (int)$data;
}
public function getMemberRecord($field, $id, $brand_id, $organization_id, $organization_level_account = null)
{
global $gRegDbManager;
$field = mysql_escape_string($field);
$id = mysql_escape_string($id);
$sql = "SELECT * FROM " . DB_REGISTRATION_DATABASE . ".member WHERE $field = '$id' ";
if($organization_level_account) {
$sql .= "AND organization_fk = " . $organization_id;
} else {
$sql .= "AND brand_fk = " . $brand_id;
}
$sql .= " LIMIT 1";
$results = $gRegDbManager->DbGetAll($sql);
if(count($results) > 0) {
return $results[0];
}
return;
}
/* * ******************************************************************************************************
* Updates member record in the member table
* *******************************************************************************************************
*/
public function updateMemberRecord($id, $changes)
{
global $gRegDbManager;
$id = mysql_escape_string($id);
if(!empty($changes)) {
$sql = "UPDATE " . DB_REGISTRATION_DATABASE . ".member SET ";
foreach($changes as $field => $value) {
$sql .= mysql_escape_string($field) . " = '" . mysql_escape_string($value) . "', ";
}
$sql = rtrim($sql, ", ");
$sql .= " WHERE iid = '$id'";
$gRegDbManager->DbQuery($sql);
} else {
return false;
}
}
I want to add an edit button for a script called spiral url, but the problem is that I can't get the URL id. This is what I've tried:
/** get url id **/
$id = isset($_GET['id']) ? $_GET['id'] : '';
#mysql_query("UPDATE short_urls SET long_url = 'test' WHERE url_id = '".$id."' LIMIT 1");
What am I doing wrong?
Also I emailed the author and his response:
"I recommend you post on Stackoverflow - https://stackoverflow.com/.
I would love to help you but I don't see what you are doing wrong. I'm still learning PHP as well."
You're wide open to SQL injection attacks.
You're supressing errors with the # operator. NEVER suppress errors
You're not checking the return value of mysql_query(), which returns a boolean FALSE on failure.
Scrap that code and use this:
if (!isset($_GET['id'])) {
die("missing query parameter");
}
$id = intval($_GET['id']);
if ($id === '') {
die("Invalid query parameter");
}
$sql = "UPDATE short_urls SET long_url = 'test' WHERE url_id=$id LIMIT 1";
$result = mysql_query($sql);
if ($result === FALSE) {
die("Mysql error: " . mysql_error() . $sql);
}
Note that I'm assuming that the id parameter is numeric. If it's not, then remove the intval() stuff.
Make sure the value of $_GET['id'] actually has a value. Your URL will look something like http://myurl.com/index.phtml?id=yourvalue. You can do this by doing a:
print "id=".$_GET['id'];
Also, whenever doing a query, please be sure to escape any and all variables that can be manipulated by the user. Without doing this, you're opening yourself up to SQL injection attacks.
mysql_real_escape_string - http://php.net/manual/en/function.mysql-real-escape-string.php
#mysql_query("UPDATE short_urls SET long_url = 'test' WHERE url_id = '".mysql_real_escape_string($id)."' LIMIT 1");
If the url is like this: domain.com/something.php?id=65
$_GET['id'] should be equal to 65
if there is no id there then when you try to access $_GET['id'] you will get an error.
Also try removing the # symbol (that suppresses PHP warning).
And you are waaaay open to bobby-tables
Also (side note), get a new developer who knows what they are doing ;-)
Have you checked the url
http://www.somewebsite.com?id=56&other_car=test
specifically for the "?" after the end of the url and also check all the parts are broken up by the ampersand.
failing that you can view all of your available get array variables by
print_r($_GET);