My HTML file calls functions on the JS file which pass parameters to the PHP file to call specific functions. My problem is that I would like the PHP session to stay alive so that when the user calls the login function, the $connection variable stays alive and can be used when the user eventually calls the loadBD function and Ajax calls the PHP file, the $connection variable is empty. I know I could use a file with the login details and include it at the start of the PHP file, but that won't work, because I don't know the details yet. How can I only login once?
Here is the JS file:
function runScript(params) {
xhr = new XMLHttpRequest();
xhr.open('POST', 'scripts.php', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
if (xhr.status === 200) {
document.getElementById("demo").innerHTML = xhr.responseText;
}
else {
alert('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send(encodeURI(params));
}
function login() {
var params = "func=login";
params += "&svr=" + document.getElementById('srv').value;
params += "&name=" + document.getElementById('name').value;
params += "&psw=" + document.getElementById('psw').value;
;
runScript(params);
}
function loadBD() {
var params = "func=load_db";
runScript(params);
}
Here is my PHP file:
<?php
$func = $_POST["func"];
$connection;
switch ($func) {
case 'login':
login();
break;
case 'load_db':
load_db();
break;
default: echo 'Function Error';
break;
}
function login() {
$connection = #mysqli_connect($_POST["svr"], $_POST["name"], $_POST["psw"]) or die("initial host/db connection problem");
if(errorCheck($connection)) {
getDatabases($connection);
}
}
function errorCheck($connection) {
if (!$connection) {
echo "internal error " . mysqli_errno();
return FALSE;
} else {
return TRUE;
}
}
function getDatabases($connection) {
$result = mysqli_query($connection, "SHOW DATABASES");
$available = array();
$index = 0;
while( $row = mysqli_fetch_row( $result ) ){
if (($row[0]!="information_schema") && ($row[0]!="mysql")) {
echo $row[0];
$available[$index] = $row[0];
$index += 1;
echo "<a href='javascript:loadDB();' >Load $row[0]</a>";
echo "<br>";
}
}
}
function load_db() {
echo "loading";
echo $connection;
}
?>
This is extremely insecure and a very bad idea. You are exposing your database credentials to the world on your web page. Standard practice is to store your database configuration in a secure location on your server and reference that config file directly from PHP.
Keeping database connections alive between requests is separate from PHP sessions. It depends very much on the details of your setup, so see the official docs for details.
PHP sessions themselves are "alive" in the sense they are tracked across requests via the session cookie. As long as the same cookie exists and the session hasn't expired, you do not need to do anything extra to keep it "alive".
You can't keep the connection open between requests; that's not really how PHP works (by default, anyway). What you could do is store the connection details for the user session in PHP's $_SESSION and use that to reestablish the connection to the database when the user hits your PHP script.
Related
I building a website, which must get data both from a MySQL database on the same server, and from an external API.
I have a javascript function which calls 5 other functions, and each of them creates an XMLHttpRequest to get different kinds of data:
function getData(){
getGi(); //Function which calls an external API (Curl request) via a local php file
getPQ(); //Gets data from a MySQL DB, also via a local php file, same as next 3 functions:
getBS();
getCV();
getTP();
}
All 5 functions call a php file via XMLHttpRequest. The first php file's call is a simple curl request to an external API. The other 4 access a DB on the same server. Example (they are all similar):
function getCV(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "../php/getDB.php?t=CV", true);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
dados = JSON.parse(this.responseText.slice(0, -1));
initCV(dados);
}
}
}
However, upon loading the website, a few Error 500 are thrown:
CV.js:14 GET https://<url>/php/getDB.php?t=CV 500 (Internal Server Error)
The number of errors or which of the requests throw errors seem random. Sometimes I get just one error, sometimes 3 or 4, and they are never the same files. Right now I've "solved" the issue by forcing the request to try again if it fails the first time:
xmlhttp.addEventListener("load", function() {
if (xmlhttp.status == 500) {
getCV();
return
}
});
But obviously this is not a proper solution. Any ideas on how I can debug/fix this? Or is this a server issue and I should contact my webhost?
Edit: here's the php code:
<?php
//Settings
$dbhost ="localhost";
$dbuser = "user";
$dbpass = "hunter2";
$dbname ="database";
//Read parameter
$tipo = $_GET['t'];
if (is_null($tipo)) {
exit("Sem parĂ¢metro.");
}
//connect to database
$conn = #mysqli_connect($dbhost, $dbuser, $dbpass, $dbname) or die('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error());
//query options
mysqli_query($conn,"SET character_set_results = 'utf8mb4', character_set_client = 'utf8mb4', character_set_connection = 'utf8mb4', character_set_database = 'utf8mb4', character_set_server = 'utf8mb4'");
switch($tipo) {
case "CV":
$query = "SELECT * FROM table1";
break;
case "PI":
$query = "SELECT * FROM table2";
break;
case "PQ":
$query = "SELECT * FROM table3";
break;
case "TP":
$query = "SELECT * FROM table4";
break;
case "BS":
$query = "SELECT * FROM table5";
break;
default:
exit("Parametro invalido.");
}
//Execute query
$result = mysqli_query($conn, $query);
if (!$result){
echo "Couldn't execute the query";
die();
}
else{
$data = array();
while($row = mysqli_fetch_assoc($result)){
$data[]=$row;
}
}
mysqli_close($conn);
echo json_encode($data, JSON_PRETTY_PRINT);
?>
I am trying to check the result from a function and determine where on my page it should go by using the Session Variable "alernativeRD". It goes to the correct element on the first try, but after that it keeps going only to the first element regardless of whether its right or not. After some testing I've found that "alernativeRD" does get changed every time in the PHP function, but it doesn't change in the Javascript part.
PHP PART
function firstSignInDefault(){
global $con;
$clubUsername= $_SESSION['clubUsername'];
$_SESSION['alternativeRD']='false'; //sets it back to false to avoid having alternativeRD be true for next user
$lastName= mysqli_real_escape_string($con, $_POST['lastNameF']);
$firstName= mysqli_real_escape_string($con, $_POST['firstNameF']);
$memberID= mysqli_real_escape_string($con, $_POST['idNumberF']);
if(!(is_numeric($memberID))){
die("<h3> Student ID must be a number </h3>");
}
$getMemberRow= mysqli_query($con, "SELECT * FROM memberstable WHERE MemberMadeID='$memberID' AND Club='$clubUsername'");
if(mysqli_num_rows($getMemberRow)==0){
$sql="INSERT INTO memberstable (MemberMadeID,FirstName,LastName,Club)
VALUES ('$memberID','$firstName','$lastName', '$clubUsername')";
$test=false; //checks to make sure sql statement runs fine
if(mysqli_query($con,$sql))
$test=true;
else {
echo "<h3> Error running sql </h3>";
}
$date=date("Y-m-d h:i:sa");
$getMemberRow= mysqli_query($con, "SELECT * FROM memberstable WHERE MemberMadeID='$memberID' AND Club='$clubUsername'");
$memberRowArray=mysqli_fetch_array($getMemberRow);
$memberPanID=$memberRowArray['UniquePanDBID'];
$sql2="INSERT INTO signinstable (TimeOfSignIn, UniquePanDBID, ClubUsername, FirstName, LastName) VALUES ('$date','$memberPanID','$clubUsername', '$firstName', '$lastName')";
//THE FOCUS OF THIS QUESTION IS BELOW THIS COMMENT
if(mysqli_query($con, $sql2) && $test==true){
$_SESSION['alternativeRD']='true';
echo " <h2 id='signedInPeople' >".$date. " ".$firstName ." ". $lastName ."</h2>";
}
}
else {
echo "<h3> ID Number already in use</h3>";
}
}
JAVASCRIPT/AJAX PART
function processFSIF(){
var xmlHttp= makeXMLHTTP();
// Create some variables we need to send to our PHP file
var url = "signInDataPlace.php";
var idNumberF = document.getElementById("idNumberF").value;
var lastNameF = document.getElementById("lastNameF").value;
var firstNameF = document.getElementById("firstNameF").value;
var typeSignIn="first";
var vars = "idNumberF="+idNumberF +"&lastNameF="+lastNameF +"&firstNameF="+firstNameF +"&typeSignIn=" +typeSignIn;
xmlHttp.open("POST", url, true);
// Set content type header information for sending url encoded variables in the request
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// Access the onreadystatechange event for the XMLHttpRequest object
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
var return_data = xmlHttp.responseText;
//AREA OF PROBLEM BELOW
<?php
if($_SESSION['alternativeRD']=='true'){ ///YOU ARE HERE, alternativeRD is acting stupid
?>
document.getElementById("serverInputList").innerHTML = return_data;
<?php
}else{
?>
document.getElementById("serverInputFSIF").innerHTML = return_data;
<?php
}
?>
}
}
// Send the data to PHP now... and wait for response to update the status div
xmlHttp.send(vars); // Actually executes the request
document.getElementById("serverInputFSIF").innerHTML = "processing...";
}
Your Javascript was printed only once, before you use AJAX. You can return the session value together with response, or you can set the cookie in PHP, than use it in javascript.
I'm trying to use a class that is already declared.
When the user types in something in the username text box I've used a javascript function to load a php file where it checks wether a username is available. this file is recalled for every keypress.
A connection to my database, which is a class, is already declared on the main page, however, the php file can't actually use the database classes. What can I do?
If I wrote a separate script to connect to the database it works, but I don't want to do that.
Contents of Php File:
$query("SELECT username FROM client WHERE username = :username");
$query_params = array(
':username' => $username
);
$db->DoQuery($query);
$check_num_rows = $db->fetch();
if ($username == NULL)
echo 'Choose a Username';
else if (strlen($username)<=3)
echo 'too short.';
else {
if ($check_num_rows ==0)
echo "Available!";
else if ($check_num_rows >= 1)
echo "Not Available.";
}
?>
body.php
<script type="text/javascript">
$(document).ready(function() {
$('#wowson').load('functions/check_username.php').show();
$('#username_').keyup(function() {
$.get('functions/check_username.php', { username: forms.username.value },
function(result) {
$('#wowson').html(result).show();
});
});
});
</script>
<label>Username:</label><br>
<input id="username_" name="username" required="required" type="text" placeholder="Username"/>
<div id="wowson">
</div>
database class
class database {
public function initiate() {
try
{
$this->database = new PDO("mysql:host='host';dbname='db", 'user, 'pass');
}
catch(PDOException $e)
{
$error = "I'm unable to connect to the database server.";
die("Failed to connect to database: " . $e->getMessage());
}
}
public function DoQuery($query, $query_params) {
try
{
$this->result = $this->database->prepare($query);
if ($query_params != null)
{
$this->result->execute($query_params);
}
else
{
$this->result->execute();
}
}
catch(PDOException $e)
{
die();
}
}
public function fetch() {
return $this->result->fetch();
}
}
When you load your original page, you are creating your object from your database class, right?
Well, when you are using Ajax to query the server about the username, that is a totally new request, and it knows nothing about the previous requests.
As such, just add something like require_once('my/path/database.php'); $db = new database(); to your PHP script which responds to the ajax request.
I'll make this as short and sweet as possible.
I have this script called usernameget.php which echos the currently logged in username:
<?php
include 'functions.php';
include 'db_connect.php';
sec_session_start();
$userId = $_SESSION['user_id'];
if(login_check($mysqli) == true) {
$con=mysqli_connect("localhost","myusername","mypass","mysqldb");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT members.username FROM members WHERE id= $userId");
while ($row = mysqli_fetch_assoc($result))
{
echo $row['username'];
}
/* free result set */
mysqli_free_result($result);
mysqli_close($con);
} else {
echo 'Null User <br/>';
}
?>
This script uses functions.php (part of a secure login script located here: http://www.wikihow.com/Create-a-Secure-Login-Script-in-PHP-and-MySQL#Create_PHP_Functions ) in order to function. sec_session_start(); is just a custom session_start, but functions.php also makes it possible to get the username via $user_id.
The problem is, when I include usernameget.php in the main page (which also uses functions.php to secure,) it throws errors because it's trying to redeclare sec_session_start();
I can strip usernameget.php of this security but obviously since it banks on functions.php / sec_session_start(); it doesn't work afterwards. I've tried to write a specific USERNAMEGETfunctions.php without the session stuff for usernameget.php to use but I'm not adept enough to get it working, and it feels like an inelegant solution.
So as I understand it: functions.php and sec_session_start(); are used to secure the main page so the includes on the main page can't use functions.php or it will conflict. Would anyone be able to show me how to get this script going without redeclaring/conflicting?
Included below is the entire functions.php
<?php
function sec_session_start() {
$session_name = 'sec_session_id'; // Set a custom session name
$secure = false; // Set to true if using https.
$httponly = true; // This stops javascript being able to access the session id.
ini_set('session.use_only_cookies', 1); // Forces sessions to only use cookies.
$cookieParams = session_get_cookie_params(); // Gets current cookies params.
session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $secure, $httponly);
session_name($session_name); // Sets the session name to the one set above.
session_start(); // Start the php session
session_regenerate_id(); // regenerated the session, delete the old one.
}
function login($email, $password, $mysqli) {
// Using prepared Statements means that SQL injection is not possible.
if ($stmt = $mysqli->prepare("SELECT id, username, password, salt FROM members WHERE email = ? LIMIT 1")) {
$stmt->bind_param('s', $email); // Bind "$email" to parameter.
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
$stmt->bind_result($user_id, $username, $db_password, $salt); // get variables from result.
$stmt->fetch();
$password = hash('sha512', $password.$salt); // hash the password with the unique salt.
if($stmt->num_rows == 1) { // If the user exists
// We check if the account is locked from too many login attempts
if(checkbrute($user_id, $mysqli) == true) {
// Account is locked
// Send an email to user saying their account is locked
return false;
} else {
if($db_password == $password) { // Check if the password in the database matches the password the user submitted.
// Password is correct!
$user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.
$user_id = preg_replace("/[^0-9]+/", "", $user_id); // XSS protection as we might print this value
$_SESSION['user_id'] = $user_id;
$username = preg_replace("/[^a-zA-Z0-9_\-]+/", "", $username); // XSS protection as we might print this value
$_SESSION['username'] = $username;
$_SESSION['login_string'] = hash('sha512', $password.$user_browser);
// Login successful.
return true;
} else {
// Password is not correct
// We record this attempt in the database
$now = time();
$mysqli->query("INSERT INTO login_attempts (user_id, time) VALUES ('$user_id', '$now')");
return false;
}
}
} else {
// No user exists.
return false;
}
}
}
function checkbrute($user_id, $mysqli) {
// Get timestamp of current time
$now = time();
// All login attempts are counted from the past 2 hours.
$valid_attempts = $now - (2 * 60 * 60);
if ($stmt = $mysqli->prepare("SELECT time FROM login_attempts WHERE user_id = ? AND time > '$valid_attempts'")) {
$stmt->bind_param('i', $user_id);
// Execute the prepared query.
$stmt->execute();
$stmt->store_result();
// If there has been more than 5 failed logins
if($stmt->num_rows > 5) {
return true;
} else {
return false;
}
}
}
function login_check($mysqli) {
// Check if all session variables are set
if(isset($_SESSION['user_id'], $_SESSION['username'], $_SESSION['login_string'])) {
$user_id = $_SESSION['user_id'];
$login_string = $_SESSION['login_string'];
$username = $_SESSION['username'];
$user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.
if ($stmt = $mysqli->prepare("SELECT password FROM members WHERE id = ? LIMIT 1")) {
$stmt->bind_param('i', $user_id); // Bind "$user_id" to parameter.
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
if($stmt->num_rows == 1) { // If the user exists
$stmt->bind_result($password); // get variables from result.
$stmt->fetch();
$login_check = hash('sha512', $password.$user_browser);
if($login_check == $login_string) {
// Logged In!!!!
return true;
} else {
// Not logged in
return false;
}
} else {
// Not logged in
return false;
}
} else {
// Not logged in
return false;
}
} else {
// Not logged in
return false;
}
}
?>
Don't use plain include for core function libraries, the kind which tend to get included in ALL your scripts. Use include_once instead, so that PHP will only ever include the file once, and then ignore any further include attempts. This will prevent your function redeclaration errors.
You must use require_once instead include_once because your program not will run without that files...
include_once produce warning when try to include the file and it fails.
require_once produce fatal error when try to include the and it fails.
For core libs, you should use require_once. (http://www.php.net/manual/pt_BR/function.require.php)
require is identical to include except upon failure it will also produce a fatal E_COMPILE_ERROR level error. In other words, it will halt the script whereas include only emits a warning (E_WARNING) which allows the script to continue.
In this page where this code is,there is a form of 3 details
country,gender,topic
So the idea is to send these 3 details to startChat.php and so that the php can extract the 3 details.
The code is as below
function startChat()
{
xmlHttp2 = GetXmlHttpObject();
if (xmlHttp2 == null)
{
alert("Browser does not support HTTP Request");
return;
}
var url = "startChat.php";
var params = "country,gender,topic";<<<<<<<<<<<<<<<<<<<<<<<what coding this should be?????
xmlHttp2.open("GET", url, true);
xmlHttp2.send(params);<<<<<<<<is this correct?????
xmlHttp2.onreadystatechange = stateChanged2;
}
And also i would need help with the startChat.php part
<?php
include('config.inc.php');
$preference="$_GET[params]";<<<<<<<<<<<<<<<<<<<<<<<<<<<<what coding this should be????????????????????????????????????
include('database.inc.php');
mysql_query("INSERT INTO users (inchat,preference) values('N','$preference')");
echo mysql_insert_id();
mysql_close($con);
?>
Please help,asking sincerely :(
First off, you ought to use a POST request instead of a GET, because it's clear from your code that this request is supposed to change state on the server.
Your params variable should be form encoded. You can do this with encodeURIComponent, like so:
var params = 'country=' + encodeURIComponent(userCountry) +
'&gender=' + encodeURIComponent(userGender) +
'&topic=' + encodeURIComponent(userTopic);
Second, you ought to sanitize the data before you insert it into your DB. Otherwise you expose yourself to SQL injection attacks.
<
?php
include('config.inc.php');
// need to create db connection before mysql_real_escape_string is called
include('database.inc.php');
$country = mysql_real_escape_string($_POST['country'], $con);
$gender = mysql_real_escape_string($_POST['gender'], $con);
$topic = mysql_real_escape_string($_POST['topic'], $con);
mysql_query("
INSERT INTO users(inchat, country, gender, topic)
VALUES('N','$country', '$gender', '$topic')
");
echo mysql_insert_id();
mysql_close($con);
?>
Note that I've also changed your DB structure. In general, it's best to avoid putting more than one piece of data into a single field (DB normalization).