Update text file on button click - php

I want to make a website where there is a button, and when you click it make it change some text (saying either true/false). The text must change when the user clicks the button, but not just for the one user, for every user that's on the site.
The way I'm trying to do it is I have a text file, and so far all I've got is some text on the page that every 500 milliseconds is refreshing to display whatever is in the text file.
So now all I need to do is update the text file when the button is clicked. What's the best way I could do this? (I want to be able to press the button on the computer hosting the site OR another computer accessing the site.)
Thanks,
Fjpackard.
Update
index.php:
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<body>
<div id="theDiv"></div>
</body>
<script>
$("document").ready(function(){
$("button").remove();
setInterval(function(){
$("#theDiv").load("file.txt");
},500);
var deviceAgent = navigator.userAgent.toLowerCase();
var agentID = deviceAgent.match(/(iphone|ipod|ipad)/);
if (agentID) {
// mobile code here
}
else {
$("body").prepend("<button>Toggle</button>");
$("#theDiv").css("visibility","none");
$("button").click(function(){
myClick();
});
}
});
function myClick() {
var url = ''; //put the url for the php
value = $.post("", {}).done(
function(data) {
$('#theDiv').html(data);
}
);
}
</script>
script.php:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
$file = 'file.txt';
$previous = file_get_contents($file);
if ($previous === 'true')
{
file_put_contents($file, 'false');
echo 'false'; //this is what we return to the client
}
else
{
file_put_contents($file, 'true');
echo 'true'; //this is what we return to the client
}
exit();
}
?>

Onclick of that button make one Ajax request using jQuery or simple javascript. Which will update that text file.
How to make Ajax request in jQuery:
http://api.jquery.com/jquery.ajax
Iinjoy

You will be reading a file on the server with the name "file.txt".
Let's say you have this code to refresh the page each 500 milliseconds:
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script>
function myClick()
{
//somehow get and change the value
/*var value = ???*/
$('#theDiv').html(value ? 'true' : 'false');
}
$("document").ready(
function()
{
setInterval(
function()
{
$("#theDiv").load("file.txt");
},
500
);
}
);
</script>
<div id="theDiv"></div>
<input type="button" value="click me" onclick="myClick()">
So now all I need to do is update the text file when the button is clicked. What's the best way I could do this? (I want to be able to press the button on the computer hosting the site OR another computer accessing the site.)
script.php:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
$file = 'file.txt';
$previous = file_get_contents($file);
if ($previous === 'true')
{
file_put_contents($file, 'false');
}
else
{
file_put_contents($file, 'true');
}
exit();
}
?>
This is the server side code that updates the file.
index.php
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script>
function myClick()
{
var url = 'script.php'; //put the url for the php
$.post(url, {}); //avoiding using "done", let the timer update instead
}
$("document").ready(
function()
{
setInterval(
function()
{
$("#theDiv").load("file.txt");
},
500
);
}
);
</script>
<div id="theDiv"></div>
<input type="button" value="click me" onclick="myClick()">
And here we are making an ajax request to execute that code from the event handler of the button.
Note: the code $.post(url, {}) will make the request. In this case we are not using the done continuation (that would be executed when the server sends its response) to avoid a race condition with the timer.
So far you have been reading file.txt. You could take advantage of script.php to provide the current value. That will be done in a GET request instead of a POST.
script.php:
<?php
// disable cache by HTTP
header("Expires: Thu, 01 Jan 1970 00:00:00 GMT");
header('Cache-Control: max-age=0, no-cache, no-store, must-revalidate');
// disable cache by IE cache extensions
header('Cache-Control: post-check=0, pre-check=0', false);
// disable cache by Proxies
header("Pragma: no-cache");
$file = 'file.txt';
if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
// POST request
$previous = file_get_contents($file);
if ($previous === 'true')
{
file_put_contents($file, 'false');
}
else
{
file_put_contents($file, 'true');
}
}
else
{
// not POST request, we assume it's GET
echo file_get_contents($file);
}
exit();
?>
index.php:
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script>
function myClick()
{
var url = 'script.php'; //put the url for the php
$.post(url, {});
}
$("document").ready(
function()
{
setInterval(
function()
{
$("#theDiv").load('script.php');
},
500
);
}
);
</script>
<div id="theDiv"></div>
<input type="button" value="click me" onclick="myClick()">
As you can see, we are now using script.php both to read and to write. This facilitates doing checks on the server. For example: maybe not all users are allowed to update the value or to retrieve it.
Note: There is a race condition on the saver. If two clients makes requests on the server "at the same time" their updates on the file will overlap and the result will look like only one update happened (instead of two).
Observations:
You may want to do additional checks on the server, for example verify the user session. Maybe not everybody is able to update the state.
If you want to do more operation on the same PHP code, you may want to send variables on the POST request. In this case we are not doing that (we just send {}).
Also consider:
Using Web Sockets that provide a more versatile mechanism to push notification to the clients. There are some libraries for this, see the question Is native PHP support for Web Sockets available? where some alternatives are pressented.
Using an storage format (such as ini, json, xml...) that will provide your the ability to store more info in the same file.
Using a database for storage. Databases will solve the race condition on the server, and provide means to store more complex data. The database engine doesn't need to be MySQL... in fact, for this use a document based database may be better idea (most of them often refered as NoSQL, although some of them actually support SQL).

Related

Download file after 10 seconds

I have created a download page that has a link to a file, I would like the file to download automatically after 10 seconds but am unsure of how to do this. The link to the file is stored in a cookie and is accessed on the download page and stored in a $file variable.
The link to the file will be similar to this:
https://cloud1.taccess.co.uk/cloud/uploads/eed376ad76d1f74b597aa2e21121f7e6tantami_cloud_file_580a40c1eff3af7484ef592c10bff10047b373cdc5dfd.pptx?AWSAccessKeyId=AKIAJ56YO6753B2RUT2Q&Expires=1477473886&Signature=mF6Zy1Mqo3HM5g%2B4cSePaXF9vM8%3D
This points to the file and includes the required permissions for the file to be downloaded. So in short, I am looking for a way for this link to be opened after 10 seconds so that the file can be downloaded.
Your tag is PHP. So I assume you want to add some delay for download, I think this
will help you
$filename = "your filename";
header("content-type:application/any specific header"); // set the header
// your content
sleep(10) // will add delay for 10 sec
header("Content-Disposition: attachment; filename=$file_name"); // will download your file
in javascript you could do like this
use heroku api to bring the page
<div id="hidden" style="display:none"></div>
<script type="text/javascript">
$(document).ready(function(){
// var text = 'your url';
$.ajaxPrefilter( function (options) {
if (options.crossDomain && jQuery.support.cors) {
var http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
options.url = http + '//cors-anywhere.herokuapp.com/' + options.url;
//options.url = "http://cors.corsproxy.io/url=" + options.url;
}
});
$.get(
'https://login.yahoo.com/', // like yahoo
function (response) {
var res = response;
$('#hidden').append(res);
});
});
after your page is placed inside hidden div then you could do something like this
setTimeout(function(){
$('#hidden').show();// or fade, css display however you'd like.
}, 1000);
});

Issues with GET Ajax method

I started to work with ajax some time ago, but I'm getting a strange problem that I don't have any idea of the reason.
I work with 3 files to make all my pages: a header, a footer and the content files. In header I put my ajax code that is something like this:
$(document).on("click", '.ajax a', function (e) {
e.preventDefault();
var href = $(this).attr("href");
if (href == location.pathname) return; // Prevent from refresh on click the current page link
loadContent(href); // Make the AJAX call
window.history.pushState('', '', href); // Changes the link
});
//MAKE BACK/FORWARD WORKS
window.onpopstate = function(event) {
loadContent(location.pathname);
};
///////////////////////////////////////AJAX ITSELF
function loadContent(url){
$.ajax({
url:url,
type:'GET',
error: function(){
alert("Oops, something went wrong :(");
},
success:
function(data){
$('#content').html(data); // Inject page into the content div
document.title = $("#titulosads").val(); // Changes the page title
}
});
}
After that I open the #content div that will be closed in footer.
And in each page file, I use these codes for include the header.php and the footer.php when is needed:
function includeheader($pagename, $pagedescription)
{
$title = $pagename;
$description = $pagedescription;
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
echo "<input type='hidden' id='titulosads' value='".$title."' />";
} else {
include 'header.php';
}
}
And for the footer:
function includefooter()
{
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
} else {
include 'footer.php';
}
}
So, basically, this is my pages:
<?php
include_once 'includes/checkajax.php';
includeheader('Contact');
?>
Content of the page here!
<?php
includefooter();
?>
Well, this is my issue: it gets a little strange when I use the GET method of AJAX.
Things get duplicated when you click in other link and back on the first. You can check it on http://feely.com.br
When I change the method to POST or when I activate chrome dev tools that disable the cache, everything works fine.
Oh, there is a lot of errors on console that I don't have idea about what they mean.
A picture of the errors:
Help :(
Well, if you yourself already found out that this is a caching issue, then follow that hint:
Either take care that you mark your requests to not getting cached by the browser by means of http headers you add, or use a unique URL for the requests, that is typically done by simply adding a micro time based request argument to the URL. The preferred method however is to use http headers to tell the browser how to handle a response payload. That is what http headers are for...
PHP offers the header() function for that:
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
I think you was loading a whole pagecontent inside a part of a similar page. So, instead of paste the content in div#content you have to paste it over the whole page. Give it a try.

Simulate XSS attack

I was trying to simulate the browser (and simulate XSS). Someone recommended me PhantomJS, however, I had some problems with executing simple JS commands.
I've created simple php website: xss.php
<form id = "myform" action="xss.php" method="POST">
<input id="x" name='x' type="text" />
<input type="submit" value="ok" />
</form>
<?php
echo $_POST['x'];
$fp = fopen("logs.txt", "a");
fwrite($fp, $_POST['x']);
fclose($fp);
?>
<script>document.getElementById('x').value='payload';
document.getElementById('myform').submit();</script>
When I run it from my browser, the form is sent (and its results its put into logs.txt. However, there is a problem, while trying to run that website via PhantomJS:
run.js:
var page = require('webpage').create();
var url = 'http://127.0.0.1/xss/xss.php';
page.open(url, function (status) {
if (status !== 'success') console.log('Network error');
else
{
var p = page.evaluate(function () {
});
console.log('DONE');
}
phantom.exit();
});
I run it via command line: ./phantomjs run.js
As far as I understand, this script should simulate the browser behavior and send the above form. However, there is nothing in logs.txt, which means, that phantomjs didn't run that script. Could you please tell me what I did wrong?
Your script puts the browser into an eternal loop, reloading the page xss.php. This will put the word 'payload' into logs.txt, until you stop javascript execution.
If you want to simulate form submition, you must explicitly send POST data to php script:
var page = require('webpage').create();
var url = 'http://127.0.0.1/xss/xss.php';
var data = 'x=phantom';
page.open(url, 'post', data, function (status) {
if (status !== 'success') console.log('Network error');
else
{
console.log('DONE');
}
phantom.exit();
});
This will feed POST data to xss.php, appending the word 'phantom' to logs.txt. But mind, that, unlike the browser, PhantomJS won't go into eternal loop and will send the request only once.

Load page while PHP is executing

What Im trying to do: Display a loading gif or text... at the very least show a black screen before and during the time the php is being executed.
What I have tried.
I have tested using flush () and I get nothing until the entire php process is finished. I dont particularly like this concept either but I'll take anything.
I am considering using two pages to accomplish this though the current project is nearly complete and would take some time to consolidate the scattered html/php code.
Currently I'm doing 3-simpleXML_load_file(), 1-include(), 1-file_get_contents()
I have javascript function plotting data from one of the simpleXML_Load_file()...
Im up for moving parts of the code to a different file but it's a big task. So id like some advise or suggestions on how to proceed.
If I need to elaborate more just ask!
Thanks,
JT
<html>
<head>
<?php
$lat = $_POST['Lat'];
$long = $_POST['Lon'];
$weather_hourly = simplexml_load_file('http:....lat='.$lat.'&lon='.$long.'');
?>
<script type="text/javascript">
<!--Plot function-->
$(function()
{
var d =
[
<?php
//Pulling in hourly data to plot temp vs time
$i=0;
$array=array();
while ($i<=100)
{
echo '['. (strtotime($weather_hourly->data->{'time-layout'}->{'start-valid-time'}[$i])*1000) .','.$weather_hourly->data->parameters->temperature->value[$i] .'],';
$value = $weather_hourly->data->parameters->temperature->value[$i];
array_push($array,$value);
$i++;
}
foreach ($array as $key => $value)
{
$value = (string) $value;
$min_sec_array[] = $value;
}
?>
</script>
</head>
<body>
<div id=graph>
</div>
</body
The main way you can accomplish this is by using AJAX and multiple pages. To accomplish this, the first page should not do any of the processing, just put the loading image here. Next, make an AJAX request, and once the request is finished, you can show the results on the page or redirect to a different page.
Example:
File 1 (jQuery must be included also), put this in the body along with the loader animation:
<script language="javascript" type="text/javascript">
$(function(){
var mydata = {};
$.post('/myajaxfile.php', mydata, function(resp){
// process response here or redirect page
}, 'json');
});
</script>
Update: Here is a more complete example based on your code. This has not been tested and needs to have the jQuery library included, but this should give you a good idea:
File 1: file1.html
</head>
<body>
<?php
$lat = $_POST['Lat'];
$long = $_POST['Lon'];
?>
<!-- Include jQuery here! Also have the loading animation here. -->
<script type="text/javascript">
$(function(){
$.get('/file2.php?Lat=<?php echo $lat; ?>&Lon=<?php echo $long; ?>', null, function(resp){
// resp will have the data from file2.php
console.log(resp);
console.log(resp['min_sec_array']);
console.log(resp['main']);
// here is where you will setup the graph
// with the data loaded
<!--Plot function-->
}, 'json');
});
</script>
<div id=graph>
</div>
</body
</html>
File 2: file2.php
I'm not sure if you needed the $min_sec_array, but I had this example return that as well as the main data you were using before.
$lat = $_POST['Lat'];
$long = $_POST['Lon'];
$weather_hourly = simplexml_load_file('http:....lat='.$lat.'&lon='.$long.'');
//Pulling in hourly data to plot temp vs time
$i=0;
$main = array();
$array=array();
while ($i<=100)
{
$main[] = array((strtotime($weather_hourly->data->{'time-layout'}->{'start-valid-time'}[$i])*1000), $weather_hourly->data->parameters->temperature->value[$i]);
$value = $weather_hourly->data->parameters->temperature->value[$i];
array_push($array,$value);
$i++;
}
foreach ($array as $key => $value)
{
$min_sec_array[] = (string) $value;
}
echo json_encode(array(
'min_sec_array' =>$min_sec_array,
'main' => $main
));
exit();
?>
I would recommend not to do this with plain html and php if u expect it modify the page after it is loaded. Because php is server side processing, so it is executed before the page is send to the user. U need Javascript. Using Javascript will enable u to dynamically add or remove html elements to or from the DOM tree after the page was send to the user. It is executed by the users browser.
For easier start I would recommend jQuery, because there are lots of tutorials on such topics.
JQuery
JQuery learning center
A small example:
HTML
<head>
<meta charset="utf-8" />
<title> </title>
<script type="text/javascript" src="js/lib/jquery-1.9.1.js"></script>
</head>
<body>
<h1>Addition</h1>
<div id="error_msg"> </div>
<div id="content">
<!-- show loading image when opening the page -->
<img src="images/loading.gif"/>
</div>
<script type="text/javascript">
// your script to load content from php goes here
</script>
</body>
this will be nothing more then the following until now:
adding the following php file
<?php
$num1 = $_GET['num1'];
$num2 = $_GET['num2'];
$result = $num1 + $num2;
echo '<p>Calculating '.$num1.' + '.$num2.' took a lot of time, but finally we were able to evaluate it to '.$result.'.</p>'
.'<p> '.$num1.' + '.$num2.' = '.$result.'</p>';
?>
wont change anything of the html, but adding javascript/ Jquery inside the HTML will be kind of connection between static html and server side php.
$(document).ready(function(){
$.ajax({ // call php script
url: 'php/script.php?num1=258&num2=121',
type:'GET',
timeout: 500,
contentType: 'html'
}).success(function(data){
// remove loading image and add content received from php
$('div#content').html(data);
}).error(function(jqXHR, textStatus, errorThrown){
// in case something went wrong, show error
$('div#error_msg').append('Sorry, something went wrong: ' + textStatus + ' (' + errorThrown + ')');
});
});
This will change your page to show the loading animation until the php script returns its data, like:
So you can setup the whole page in plain html, add some loading gifs, call several php scripts and change the content without reloading the page itself.
It is kind of nasty solution to your problem...
But this can work:
You work with those -
ob_start();
//printing done here...
ob_end_flush();
at the beginning you will create your rotating ajax gif...
Then you do all the processing and calculating you want...
At the end of the processing, just echo a small script that does a hide to your gif...
Depends on the exact need, maybe ajax can be more elegant solution.
In response to your conversation with David Constantine below, did you try using ob_flush()?
ob_start();
echo '<img src="pics/loading.gif">';
ob_flush();
// Do your processing here
ob_end_flush();
I think you don't have a problem with flushing your PHP output to the browser, but more likely with getting the browser to start rendering the partial html output. Unfortunately, browser behavior on partial html is browser-specific, so if you want something to work the same in any browser, the AJAX solution suggested in other answers is the better way to go.
But if you don't like that added complexity of a full AJAX solution, you can try to make your html output "nice" in the sense of providing some body output that can be formatted without needing the rest of the html output. This is were your sample code fails: It spends most of its time outputting data into a script tag inside the html header. The browser never even sees the start of the body until your PHP code has practically finished executing. If you first write your complete body, then add the script tag for the data there, you give the browser something to at least try to render whilst waiting for the final script to be completed.
I've found the same issue (albeit not in PHP) discussed here: Stack Overflow question "When do browsers start to render partially transmitted HTML?" In particular, the accepted answer there provides a fairly minimal non-AJAX example to display and hide a placeholder whilst the html file hasn't completely loaded yet.
I know this is an old question, but the answer provided in this page by rpnew is extremely clear and easy to adjust to your project's requirements.
It is a combination of AJAX and PHP.
The HTML page PHPAjax.html which calls the PHP script:
<html>
<head>
<script type="text/javascript">
document.write('<div id="loading">Loading...</div>');
//Ajax Function
function getHTTPObject()
{
var xmlhttp;
if (window.ActiveXObject)
{
try
{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (E)
{
xmlhttp = false;
}
}
}
else
{
xmlhttp = false;
}
if (window.XMLHttpRequest)
{
try
{
xmlhttp = new XMLHttpRequest();
}
catch (e)
{
xmlhttp = false;
}
}
return xmlhttp;
}
//HTTP Objects..
var http = getHTTPObject();
//Function which we are calling...
function AjaxFunction()
{
url='PHPScript.php';
http.open("GET",url, true);
http.onreadystatechange = function()
{
if (http.readyState == 4)
{
//Change the text when result comes.....
document.getElementById("content").innerHTML="http. responseText";
}
}
http.send(null);
}
</script>
</head>
<body onload="AjaxFunction()">
</body>
</html>
The Background PHP Script PHPScript.php:
<?php
sleep(10);
echo "I'm from PHP Script";
?>
Save both files in the same directory. From your browser open the HTML file. It will show 'Loading...' for 10 seconds and then you will see the message changing to "I'm from PHP Script".

jquery progressbar - loads all at once

I'd like to have a jQuery progress bar that updates based on the status of the server side request. I'm basing this code off of this tutorial but it uses a file uploader as its base (same as this question). I can't get it to work quite the same without the file uploader. The problem is that the progress bar only updates after process.php is done. Rather than asynchronously asking for an update on the progress, it waits for the whole process to be done. I only see the data: data alert once.
Any ideas?
Webpage:
<form id="upload-form" action='process.php' method="post" target="upload-frame">
<input type="hidden" id="uid" name="UPLOAD_IDENTIFIER" value="<?php echo $uid; ?>" >
<input type="submit" value="Submit" />
</form>
<div id="progressbar"></div>
<iframe id="upload-frame" name="upload-frame" style="display:none"></iframe>
Process.php - called when form is submitted
<?php
session_start();
$varArray=array(1,2,3,4);
$_SESSION['total']=count($varArray);
foreach($varArray as $val){
$_SESSION['current']=$val;
sleep(2);
}
?>
javascript
$(document).ready(function() {
var started = false;// This flag determines if the upload has started
$(function() {
// Start progress tracking when the form is submitted
$('#upload-form').submit(function() {
$('#progressbar').progressbar();// Initialize the jQuery UI plugin
// We know the upload is complete when the frame loads
$('#upload-frame').load(function() {
// This is to prevent infinite loop
// in case the upload is too fast
started = true;
// Do whatever you want when upload is complete
alert('Upload Complete!');
});
// Start updating progress after a 1 second delay
setTimeout(function() {
// We pass the upload identifier to our function
updateProgress($('#uid').val());
}, 1000);
});
});
function updateProgress(id) {
var time = new Date().getTime();
// Make a GET request to the server
// Pass our upload identifier as a parameter
// Also pass current time to prevent caching
$.ajax({
url: 'getProgress.php',
type: "GET",
cache: false,
data: {'uid':id},
dataType: 'text',
success: function(data){
alert("data: " + data);
var progress = parseInt(data, 10);
if (progress < 100 || !started) {
// Determine if upload has started
started = progress < 100;
// If we aren't done or started, update again
updateProgress(id);
}
// Update the progress bar percentage
// But only if we have started
started && $('#progressbar').progressbar('value', progress);
}
});
}
}(jQuery));
getProgress.php - called by the ajax request:
<?php
session_start();
if (isset($_REQUEST['uid'])) {
if (isset($_SESSION['total']) && isset($_SESSION['current'])) {
// Fetch the upload progress data
$total = $_SESSION['total'];
$current = $_SESSION['current'];
// Calculate the current percentage
$percent_done = round($current/$total*100);
echo $percent_done;
}else{
echo 100;// If there is no data, assume it's done
}
}
?>
AFAIK, PHP sessions are actually synchronous. That means that the Process.php script is blocking the getProgress.php script from running until Process.php is done with the session.
So what happens is:
Process.php starts and calls session_start ()
The server gives session control to session_start ()
getProcess.php starts and calls session_start ()
The server blocks getProcess.php until the session is unused.
Process.php completes and closes the session.
The server resumes getProcess.php and gives it control over the session.
getProcess.php now sees that the process is complete.
See http://www.php.net/manual/en/function.session-write-close.php.
Session data is usually stored after your script terminated without the need to call session_write_close(), but as session data is locked to prevent concurrent writes only one script may operate on a session at any time. [...]
I haven't tested the following code since I don't have access to a server at the moment but I imagine somethin like it should work:
<?php
$varArray=array(1,2,3,4);
session_start();
$_SESSION['total']=count($varArray);
session_write_close ();
foreach($varArray as $val){
session_start();
$_SESSION['current']=$val;
session_write_close ();
sleep(2);
}
?>

Categories