I'm writing some data to a database using php. 99% of the time, the data is correctly written to the database. But sometimes, blank data is being inserted into the database. I dont think its a issue with my code, since I can write the data to the database most of the time.
If the server on which the database resides have a slow internet connection, or if the user have a slow internet connection in their pc, can this happen?
Actually there is a slight mistake..Seems like the data that gets blank, comes from a session variable. How can be the session variable get blanked at some time ?
This is the code by which the data get stored into the session variable:
if(!preg_match('/^[a-zA-Z0-9._\-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/', $email))
$count = 2;
if(!preg_match('/^[A-Za-z0-9]{6}+$/',$key))
$count = 2;
if(!$count)
{
$result = mysql_query("SELECT * FROM test WHERE verify = '$key' AND email = '$email'");
$count = mysql_num_rows($result);
if($count == 1)
{
$row = mysql_fetch_row($result);
$_SESSION['id'] = $row[0];
$_SESSION['name'] = $row[1];
$_SESSION['email'] = $email;
$_SESSION['pass'] = $row[3];
$_SESSION['key'] = $key;
mysql_close();
}
}
When it happens, all the 5 variables id, name, email, pass and key, becomes blank. Email, and Key is not taken from the Database. The key field contains only alphanumeric content. So is there a way the data taken from the database as well at the GET variables to go blank? ( but even then $count should 1). Because, only if $count is 1, can the data be written to the new table ( where it get blanked )
There are 2 forms. When the user completes the first form, that data is stored in a table test, and a verification mail is sent to them. From the verification link, i find out their key and email, and check the table test, to see whether they are valid. If they are valid ( that means $count is 1 ), then a new form is displayed to the user, where they are asked to enter few more details. Then all the data ( this new data, and also the data that was written to the table test ), shall be written to a new table.
This is where things go wrong. The new data is written perfectly to the new table. But the old data, that was stored in the table test, and copied to the session variable, becomes blank sometimes. I have posted its code above, showing how the session variables are set.
It shall be helpful if someone could point out my mistake, if its something wrong in my code.
Programmers have at least five tactics to make sure data gets written to a database.
Check the content of variables for sanity before writing.
Design the database to reject bad data.
Trap errors. All of them.
Read back what you just wrote.
A verbose mode that writes to a log file.
Related
After submitting a payment form (credit cards, etc) to our payment gateway, we receive the "response_code" 1 when the payment is approved. We then use the following code to update a user's info in the database to reflect the approved transaction.
However, about every 1 out of 10 times, a user's info simply will not update even though the transaction returned an approved response. Is anything clearly wrong with this code? Or perhaps the response_code does not equal 1 for some reason?
<?php
session_start();
if ($_GET['response_code'] == 1)
{
require('scripts/global.php'); //connect to database
$email = $_SESSION['email'];
$level = 3;
$transaction_id = "" . htmlentities($_GET['transaction_id']);
mysql_query ("UPDATE `users` SET level = '$level', trans_id = '$transaction_id' WHERE `email` = '$email'"); //update user info
$error = "false";
}
else
{
$noerror = "true";
$message = "Sorry, an error occurred: " . htmlentities($_GET['response_reason_text']);
}
?>
Probably because there has been a session timeout? The WHERE uses the e-mail address, if this is not valid (not there) then you probably won't get an update.
Maybe you should check for transaction ID (or similar). I guess you've got something like that before the transaction starts?
edit: Also store if an error occurs, and try to store variables you need too. This makes it a lot easier to pinpoint the problem. Use a logfile for this for example.
Beyond the obvious security holes, you're not checking the results of your query. Try using mysql_error() and mysql_affected_rows() to see whether anything was updated. When either indicates something unusual, you'll also want to see the exact text of the query that ran. Things to check:
Was $email empty?
Did $transaction_id or $email have any apostrophes?
Do you have duplicate email addresses in the database?
Had the user already been set to level 3?
Did you lose connection to the database?
Did your script get called at all?
Currently I have a file called "hits.php" and on any page I want to track page hits I just use <?php include("hits.php"); ?>
How can I track unique visitors only though? My hits are false since it can be refreshed by the same person and hits go up.
Here's my source:
<?php
$hits = file_get_contents("./client/hits.txt");
$hits = $hits + 1;
$handle = fopen("./client/hits.txt", "w");
fwrite($handle, $hits);
fclose($handle);
print $hits;
?>
I don't really know how I could do cookie checking... is there a way to check IP's? Or what can I do?
Thanks StackO.
The simplest method would be cookie checking.
A better way would be to create an SQL database and assign the IP address as the primary key. Then whenever a user visits, you would insert that IP into the database.
Create a function included on all pages that checks for $_SESSION['logged'] which you can assign whatever 'flag' you want.
If $_SESSION['logged'] returns 'false' then insert their IP address into the MySQL database.
Set $_SESSION['logged'] to 'true' so you don't waste resources logging the IP multiple times.
Note: When creating the MySQL table, assign the IP address' field as the key.
<?php
session_start();
if (!$_SESSION['status']) {
$connection = mysql_connect("localhost", "user", "password");
mysql_select_db("ip_log", $connection);
$ip = $_SERVER['REMOTE_ADDR'];
mysql_query("INSERT INTO `database`.`table` (IP) VALUES ('$ip')");
mysql_close($connection);
$_SESSION['status'] = true;
}
?>
There isn't a perfect solution, but the first two methods (IP address and/or cookies) are the most reliable, and a combination might be even better.
Rather than reinventing the wheel I used an off the shelf solution. For commercial reasons I avoided Google Analytics (I don't want Google to know my web stats - their best interests are not mine). They're probably fine for non-commercial websites, or if you don't use Google for advertising. There are also dozens of alternatives. Eg I use Getclicky.com
At a basic level, you can get the client's IP address by using the PHP $_SERVER['REMOTE_ADDR'] property
Consider setting a cookie or using a session, though this can be defeated by deletion of a cookie or cookie rejection. See the PHP setcookie docs for more info.
There are other methods for browser fingerprinting - check out all the different data you could conceivably use at https://coveryourtracks.eff.org/
How about google analytics if you cant. you could do a database or create another file with the IPs in it, but it could get complicated with a flat file like that.
I found the solution of very poor quality and just a quick and dirty way of doing it.
I too was developing something similar and formulated a quick method which works without redundancy.
I needed a counter for every time someone accessed another user's profile.
Pseudo:
Create a table with viewer's name and viewee's name (daily_views table).
Check to see if exists the viewer's name with the viewee's name (on the same row).
If they do not exist, update user counter +1 (in users table).
Else do nothing.
Reset entire table values null every 24/12 hours via cron job.
This will deny the same person accessing the same user profile to add 1 to the
counter on refresh for the whole day (or 12 hours) whereas the above solution
by Glenn Nelson would indeed add 1 to the counter, but deny adding to every
user's counter at the same time.
Not only this, but if you were to logoff and log back in to the website, then
it would simply re-add to the counter in which some cases trolls and haxorz
wannabe's will exploit this (as the session is destroyed and started again).
Here are my sample tables:
users
{
user_id INT(8) auto increment, user_name varchar(32), user_counter INT(12)
};
daily_views
{
view_id INT(8) auto increment, viewer_name VARCHAR(32), viewee_name VARCHAR(32)
};
Here is sample code I've written:
<?php
session_start();
$uname = $_SESSION['username'];
$vieweepage = $_GET['name']; //gets the name of the persons page/profile via previous page/form
$connect = mysql_connect("localhost","user","password") or die("Couldn't connect; check your mysql_connect() settings");
$database = mysql_select_db("database") or die("Could not locate database!");
$query = mysql_query("SELECT user_counter from users");
$query = mysql_fetch_row($query);
$counter = $query[0];
$viewcheck = mysql_query("SELECT viewer_name from daily_views WHERE viewee_name='$vieweepage'");
$viewrow = mysql_num_rows($viewcheck);
$newcounter = $counter + 1;
if($viewrow == 0)
{
$update = mysql_query("UPDATE users SET user_counter='$newcounter' WHERE user_name='$vieweepage'");
$insert = mysql_query("INSERT into daily_views (viewer_name, viewee_name) VALUES ('$uname', '$vieweepage')");
}
?>
currently i am using remote address and session ID for visitor.i think its valid visitor because a single user can visit no of times in a days and counter not depends on refresh its only depends on new session.
You could save a timestamp to localStoage in javascript. LocalStoage isn't removed by the browser, so you should be save to check against that. I know that it isn't serverside checking, but it may be helpful anyway.
I'm trying to display the data here in order of:
Author Name
Book Name
Url
NOTE: There are many results for each piece of data. Im not sure how they are stored in the array when they are fetched.
The database schema is relational as you will see and connects these bits of information from different areas of the database.
Im new to programming as you may have figured.
Im at a loss here.
Here is my code:
<?php
//Starting session
session_start();
//Includes mass includes containing all the files needed to execute the full script
//Also shows homepage elements without customs
include ('includes/mass.php');
//Set the session variable
$username = $_SESSION['username'];
//Check to see if logged in
if (isset($username))
{
//Check all databases assoc with the notes for username submissions
$sql_for_username_submission = "SELECT notes.authname, notes.bookname, notes.url, notes.note_id, notes.user, smallnotes.chapter_name FROM notes INNER JOIN small_notes ON notes.note_id = small_notes.notes_id AND notes.user = small_notes.user ORDER BY notes.note_id";
$get_data = mysql_query($sql_for_username_submission);
while ($data_row = mysql_fetch_assoc($get_data))
{
$authnames = $data_row['authname'];
Stopped here. not sure how to progress
}
}
?>
I would imagine you need some UI controls to which you would bind the data in data_row. In other words, you need to have some placeholders on the screen.
Best Regards
You are fetching my assosciative array so it does not matter. You can just reference the array item by key and use it whenever and where ever you want.
You do not have to worry about how the array is sorted.
Need some help with how to handle sessions. I am using ajax techniques to implement a group discussion platform and alot of its success depends on whether or not i can handle sessions properly, be able to see who is online etc. How can i do this efficiently. Remember, this is a typical single url ajax application where the server only responds to request. All of the form validation is done on the client side as the user enters his data. I need help with this. Below what have written so far.
<?php
include_once "../database/dbconnect.php";
session_start();
$username = isset($_POST["userNameLogin"]) ? $_POST["userNameLogin"] : $_SESSION["userNameLogin"];
$pwd = isset($_POST["passwordLogin"]) ? $_POST["passwordLogin"] : $_SESSION["passwordLogin"];
// Sending these messages to my client side validation code json-style.
if(!isset($username)){
echo("{message : 'NoName'}");
}
elseif(!isset($pwd)){
echo("{message : 'NoPW'}");
}
// creating the session variables to hold username and pwd
$_SESSION['userNameLogin'] = $username;
$_SESSION['passwordLogin'] = $pwd;
// calling the function incuded above to make connection to mysql db
dbConnection();
//query retrieves username and pwd from db and counts the result. if it is one, then they //certianly exist and if not unset the variables created above. The varibles were created
//above so i do not have to check if they exist before unsetting them.
$sQuery = "SELECT * FROM users WHERE
username = '$username' AND password = '$pwd'";
$result = mysql_query($sQuery) or die(mysql_error());
$intFound = mysql_num_rows($result);
if ($intFound == 0) {
unset($_SESSION['userNameLogin']);
unset($_SESSION['passwordLogin']);
// AD - Access Denied
echo("{message : 'AD'}");
}
else{
//a flag to set in the database who is currently online. value of 1 for users who are //online and zero for users who are not. If i want a list of those online, i check the //column called online and then check to see if the $_SESSION['username'] exist. If it //does then i know the user is online. That is what the second script is for. New to this //stuff, and do not know a better way of doing it
mysql_query("UPDATE users SET online = '1' WHERE username = '$username'") or die(mysql_error);
}
The above script should let the user login or deny access by sending messages to the validation code on client side.
As you can see, i am new to this stuff i having my share of problems. What can i do to make sure that sessions are set and unset properly i.e when user logs out.
secondly how can i monitor who is online and who is not using sessions. This is how i am trying to check who is currently online and then building a json file with the user names and sending it to the client. Json is easier to parse.
The script below tries to determine who is online
<?php
// this script determines which sessions are currently active by
// 1.) checking to see which online fields in the users table are set to 1
// 2.) by determining if a session variable has been set for these users.
// If it is not set, it means user is no longer active and script sets its online field in the users table to zero.
// After doing this, the script, then queries the users table for online fields with values one, writes them to an
// array and passes them to the client.
include_once "../database/dbconnect.php";
//include "../validation/accessControl.php";
$tempActiveUsers = array();
$activeUsers = array();
$nonActiveUsers = array();
dbConnection();
$sql = "SELECT username from users WHERE online = '1' ";
$active_result = mysql_query($sql) or die(mysql_error);
if($active_result){
while($aValues = mysql_fetch_array($active_result)){
array_push($tempActiveUsers, $aValues['username']);
}
}
forEach($tempActiveUsers as $value){
/*if($_SESSION['$value'] == $value){
$activeUsers += $value;
} */
if(isset($_SESSION['userNameLogin']) == $value){
array_push($activeUsers, $value);
}else{
array_push($nonActiveUsers, $value);
}
}
forEach($nonActiveUsers as $value1){
$sql1 = "UPDATE users SET online='0' WHERE username = '$value1'";
$set_result = mysql_query($sql1) or die(mysql_error);
}
$length = sizeof($activeUsers);
$len = 1;
$json ='{"users" : {';
$json .= '"user":[';
forEach($activeUsers as $value2){
$json .= '{';
$json .= '"username" : "' .$value2.'" }';
if($len != $length){
$json .= ',';
}
$len++;
}
$json .= ']';
$json .= '}}';
echo $json;
Please look through and give some advice. Will appreciate that very much. My project framework is up and good, but i can implement much user functionality yet because i cann't track who is online and how to manage thier sessions. If you need more background info let me know. Thanks in advance
Add 'Log out' button and click event handler on it which makes an ajax request to server to stop session by unsetting session vars or destroying session completely, and on ajax completion callback put a function to update user interface to show user is logged out.
Log in procedure can be done as follows: user clicks 'Log in' button and some form asking for user name and password appears. Then submit this form with ajax to a server script like your first one. Server script checks whether user name and password are valid and returns authentication information to a client via callback: failure notice upon failed login or some information about user currently logged in, e.g. user name, fullname and anything you might need about this user on client side in js. Then your client script proceeds according to login status returned from server-side script.
You should always remember about security.
Before sending any sensitive data to a client side with json, you shoud always check if session is valid and started. Client-side scripts could be easily modified and executed without your control and you should prevent undesired activity only on server side.
You should apply some escaping on user-POSTed fields before using them in sql queries to avoid sql injection attacks, e.g. by using mysql_escape_string().
And instead of building json strings, you can use json_encode() which works good for primitives, objects and arrays, you'll save some time.
Below is a page that handles a login script and I am wondering if I have put it any security holes. I have been reading articles on protecting from injections and others and wanted to make sure that my code is secure.
It is submitted via ajax and returns JSON based on the login being correct or not.
<?php
ob_start();
session_start();
include ("config.inc.php");
include ("jsonEncode.php");
// ausername and apassword sent from form
$ausername = '';
$apassword = '';
$ausername = mysql_real_escape_string(stripslashes($_GET['username']));
$apassword = mysql_real_escape_string(stripslashes($_GET['password']));
$sql = "SELECT * FROM admin WHERE ausername='$ausername' AND apassword='$apassword' LIMIT 1";
$result = mysql_query($sql) or die(mysql_error());
$data = mysql_fetch_array($result);
$count = mysql_num_rows($result);
if($count==1){
$_SESSION['ausername'] = $ausername;
$_SESSION['apassword'] = $apassword;
$_SESSION['admin_id'] = $data['a_id'];
$a_id = $data['a_id'];
$_SESSION['LastLogin'] = $data['last_login'];
$query = "UPDATE admin SET last_login = Now() WHERE `a_id`= $a_id";
mysql_query($query);
//echo $query;
$_SESSION['aloggedin'] = "1234";
// valid
$var = array('avalid' => 1, 'ausername' => $ausername, 'apassword' => $apassword);
print php_json_encode($var);
}else{
// invalid
$var = array('avalid' => 0, 'ausername' => $ausername, 'apassword' => $apassword);
print php_json_encode($var);
}
?>
You might want to use the POST method rather than GET with the login form, otherwise their password will appear in the URL and URLs aren't very secure (they might get bookmarked or sent to another server as a referral URL, for example).
You don't need to strip the slashes. Unless you are also stripping slashes when these columns are populated, you've actually introduced a security hole -- if for whatever reason you don't have a unique constraint on the username field, and/or you have slashes in the in the stored username or password fields, and their passwords differed only by a slash, you could get one user logged in as another.
You should be using bound parameters to put user data into your SQL, not string concatenation.
Also, you should probably be storing password hashes in your database - not the original plaintext passwords.
Finally, not a security issue, but setting $ausername and $apassword to '' immediately before giving them new values is entirely pointless.
Also, don't store the password in the session. Php session data is stored in the OS tmp/temp directory by default so the data could be viewed by others. Normally, I'll just keep the username in the session and query the database when needed. That avoids problems when a user's information is changed, but the session isn't updated.
(I'm an MSSQL bod, so don't know if any of these points are irrelevant to MySQL)
This isn't really to do with security, just general observations in case helpful:
Don't use SELECT * - list the columns you want back - looks like you only need a_id & last_login. You might add a Blob in that table with their photograph in the future, or personal notes etc. - it will kill performance in all the places where you did SELECT * in the past and didn't need the picture.
I wouldn't do LIMIT 1 - I'd quite like to know if there are DUPs at this point, and raise an error.
I would put the last_login column in another table linked 1:1 with your User / password table. Its a frequent-change item, and if you decide to introduce an Audit table on the user/Password table (i.e. store the old values whenever it changes) having a frequently changing "info" column mucks that up a bit.
Personally I would want to keep the column naming convention and the SESSION / variable one the same.
admin_id / a_id, LastLogin / last_login
Personally I wouldn't store password in the session unless you need it later on. I would store something to indicate the "permissions" the user has, and then use that to decide if they can view PageX or PageY etc.
All good answers above.
Only one thing I want to add that hasn't been mentioned... I tend to fetch the account password and do a PHP comparison rather than putting the password in the query and looking if the row exists.