Get the code of a page generated with JavaScript - javascript

I'm trying to get the code of an URL page after it JavaScript executed.
For the exemple :
<?php
function getVideoURL($link){
$data = file_get_contents($link);
print($data);
}
$link = htmlentities($_POST["link"]);
getVideoURL($link);
?>
But this code give me the code of the url before javasript execution, is there a way to get it after javascript execution ?

file_get_contents get the original code of the page, it doesn't execute any client side code ( javascript )
To execute javascript you will need an entire browser emulation engine -- a headless browser.
http://jonnnnyw.github.io/php-phantomjs/
use JonnyW\PhantomJs\Client;
function getVideoURL($link){
$client = Client::getInstance();
$request = $client->getMessageFactory()->createRequest($link, 'GET');
$response = $client->getMessageFactory()->createResponse();
$client->send($request, $response);
if($response->getStatus() === 200) {
// Dump the requested page content
return $response->getContent();
} else {
return false;
}
}
$link = htmlentities($_POST["link"]);
getVideoURL($link);

Related

How can I run javascript after user login in joomla 3?

I try to use this function in a plugin, but is not working, maybe because javascript doesn't have time to execute after login an I end up redirected to homepage
public function onUserAfterLogin($text) {
$app = JFactory::getApplication();
$document = JFactory::getDocument();
$document->addScriptDeclaration('document.addEventListener("message", function(event) {
alert("test");
});
');
}
I have tried with even with echo
echo '<script type="text/javascript">
alert("test");
</script>';
One quick method is to redirect the user on login (this can be done at the menu item level) to a static HTML page/or a dynamic PHP page (depending on your needs) that contain the JavaScript code, and that page can then redirect to the page of your choice after firing the JS code.
thank you for the sugestion, but I've used the function in joomla
onAfterRender(), and inside the function you can do this:
//This event is triggered after the framework has rendered the application.
//When this event is triggered the output of the application is available in the response buffer.
public function onAfterRender() {
$app = JFactory::getApplication();
$user_id = JFactory::getUser()->id; // NOT 0
$is_guest = JFactory::getUser()->guest;
if ($user_id !== 0 && $is_guest !== 'guest') {
$myJScript = 'alert("Test");';
// retrieve all the response as an html string
$html = $app->getBody();
// Search and replace tag </body> with the new script+</body>
$html = str_replace('</body>','<script type="text/javascript">' . $myJScript . '</script></body>', $html);
// override the original response
$app->setBody($html);
}
}

php file's code not executing through ajax call

I have a button in my PHP file, and when I click on that button, I want another PHP file to run and save some data in a MySQL table. For that I am using AJAX call as suggested at this link (How to call a PHP function on the click of a button) which is an answer from StackOverflow itself.
Here is my show_schedule file from which I am trying to execute code of another PHP file:
$('.edit').click(function() {
var place_type = $(this).attr("id");
console.log(place_type);
$.ajax({
type: "POST",
url: "foursquare_api_call.php",
data: { place_type: place_type }
}).done(function( data ) {
alert("foursquare api called");
$('#userModal_2').modal('show');
});
});
here 'edit' is the class of the button and that button's id is being printed in the console correctly.
here is my foursquare_api_call.php file (which should be run when the button is clicked):
<?php
session_start();
include('connection.php');
if(isset($_POST['place_type'])){
$city = $_SESSION['city'];
$s_id = $_SESSION['sid'];
$query = $_POST['place_type'];
echo "<script>console.log('inside if, before url')</script>";
$url = "https://api.foursquare.com/v2/venues/search?client_id=MY_CLIENT_ID&client_secret=MY_CLIENT_SECRET&v=20180323&limit=10&near=$city&query=$query";
$json = file_get_contents($url);
echo "<script>console.log('inside if, after url')</script>";
$obj = json_decode($json,true);
for($i=0;$i<sizeof($obj['response']['venues']);$i++){
$name = $obj['response']['venues'][$i]['name'];
$latitude = $obj['response']['venues'][$i]['location']['lat'];
$longitude = $obj['response']['venues'][$i]['location']['lng'];
$address = $obj['response']['venues'][$i]['location']['address'];
if(isset($address)){
$statement = $connection->prepare("INSERT INTO temp (name, latitude, longitude, address) VALUES ($name, $latitude, $longitude, $address)");
$result = $statement->execute();
}
else{
$statement = $connection->prepare("INSERT INTO temp (name, latitude, longitude) VALUES ($name, $latitude, $longitude)");
$result = $statement->execute();
}
}
}
?>
none of the console.log is logged in the console and also the 'temp' table is not updated. Can anyone tell me where I am making mistake? Or is it even possible to execute the code of a PHP file like this?
Your JavaScript is making an HTTP request to the URL that executes you PHP program.
When it gets a response, you do this:
.done(function( data ) {
alert("foursquare api called");
$('#userModal_2').modal('show');
}
So you:
Alert something
Show a model
At no point do you do anything with data, which is where the response has been put.
Just sending some HTML containing a script element to the browser doesn't cause it to turn that HTML into a DOM and execute all the script elements.
You'd need to do that explicitly.
That said, sending chunks of HTML with embedded JS back through Ajax is messy at best.
This is why most web services return data formatted as JSON and leave it up to the client-side JS to process that data.
to return the contents of php code you can do something like this
you can use any call to this function
function check_foursquare_api_call(place_type) {
var place_type= encodeURIComponent(place_type);
var xhttp;
//last moment to check if the value exists and is of the correct type
if (place_type== "") {
document.getElementById("example_box").innerHTML = "missing or wrong place_type";
return;
}
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
document.getElementById("example_box").innerHTML = xhttp.responseText;
$('#userModal_2').modal('show');
}
};
xhttp.open("GET", "foursquare_api_call.php?place_type="+place_type, true);
xhttp.send();
}
this will allow you to send and execute the code of the foursquare_api_call file and return any elements to example_box, you can return the entire modal if you want,
you can use any POST / GET method, monitor the progress, see more here
XMLHttpRequest

Error updating webpage elements in real time with JavaScript

I am working on a webpage that shows the amount of online players on a game server that I am running, that is updated in real time.
The problem is that I can get the amount of players online in the game server to display, but it never updates and always shows the amount of players that were on the server when the page was loaded although people leave and join the server every second.
This is the PHP code that shows the numbers (it's simple, just for testing):
<?php
echo "<a id='a1' href='#' class='online'>Loading...</a>";
?>
What I am doing is to update 'a1' every second with the new amount of online players using javascript, which calls a php function called getplayers():
<script language="JavaScript">
setInterval(function(){
document.getElementById("a1").innerHTML = '<?php echo getplayers()?>';
}, 1000);
</script>
The function getplayers() it's exactly this:
<?php
include "Status.php";
function getplayers() {
$serverb = new Status("mc.spainpvp.com", '25565');
return $serverb->online_players;
}
?>
Lastly, Status.php is a script that gets the amount of players online and more things about the server, which I am sure that works:
<html>
<?php
class Status {
public $server;
public $online, $motd, $online_players, $max_players;
public $error = "OK";
function __construct($url, $port = '25565') {
$this->server = array(
"url" => $url,
"port" => $port
);
if ( $sock = #stream_socket_client('tcp://'.$url.':'.$port, $errno, $errstr, 1) ) {
$this->online = true;
fwrite($sock, "\xfe");
$h = fread($sock, 2048);
$h = str_replace("\x00", '', $h);
$h = substr($h, 2);
$data = explode("\xa7", $h);
unset($h);
fclose($sock);
if (sizeof($data) == 3) {
$this->motd = $data[0];
$this->online_players = (int) $data[1];
$this->max_players = (int) $data[2];
}
else {
$this->error = "Cannot retrieve server info.";
}
}
else {
$this->online = false;
$this->error = "Cannot connect to server.";
}
}
}
?>
</html>
So my question is if someone knows why it always updates with the first number of players instead of putting the new number of players?
You can not call PHP functions by Javascript. PHP is processed on a server in time of request. No piece of PHP code will be visible in response, because it's already processed.
So your javascript code will actually look like:
<script language="JavaScript">
setInterval(function(){
document.getElementById("a1").innerHTML = 'XXXXX';
}, 1000);
</script>
where XXXXX is amount of players in the time of request.
So your code will every second replace elements innerHTML with the static content.
If you want to get new amount of players every second, you need to use Ajax.
You can create request on your own using XMLHttpRequest or you may use some library like jQuery and it's $.ajax method.
You also need a PHP code on a server that will provide such information.

To pass argument from a php file to javascript file

I am facing some trouble in passing a simple variable from a php to javascript file.
I have a form which submits through a php file which basically updates the record at the server end. And if the updation is succesful, I just want to pass the message back to the javascript where I can update it on a certain section of the page.
My codes are:
Javascript code - abc.js
function expand_cards(project, SlNo)
{
name = project['project_name'];
j = "ShowForm-"+SlNo+"";
s = "<div class='edit_project_card'>";
s += "<form method='post' action='Edit_Project.php'><div class='project_form'>
// Form Contents
s += "<div class='Form_button'> <input type='submit'> </div>";
s += "</form></div>";
$("#"+j+"").html(s);
response = $.parseJSON(data);
$("#"+j+"").html(response);
}
PHP file - Edit_Project.php
<?php
//The updation stuff at the server end
if (!mysqli_query($connection,$sqlquery)) {
$response = "'Error in your code: ' . mysqli_error($connection)";
}
else {
$response = "1 record updated";
}
echo json_encode($response);
mysqli_close($connection);
?>
But the problem is the screen is printing $response variable as it is and not exactly passing it back to the javascript function as wished. I know I can use a $.post function which can can receive argument but it's a long form and passing parameters would be difficult in that.
Can anybody help me out here ?
Thanks
Dirty, but it will work:
<script type="text/javascript">
var my_var = <?php echo $some_variable; ?>
// Do something with the new my_var
some_func(my_var);
</script>
I wouldn't do too much detailed stuff with this though, if you can use AJAX that is better.
Note, this can only work on a .php file or one being read as such.
you'll want to do some variable handling in your php side because if the string is empty you'll end up with a
var my_var = ;
which will break the script. so something like:
var my_var = <?php echo "'" . $some_variable . "'";?>
if it's a string or if it's a number:
var my_var = <?php echo (empty($some_variable) ? null : $some_variable);
This is int specific, I'm sure you can come up with a function that will handle it better.
References:
empty function http://php.net/manual/en/function.empty.php
shorthand if http://davidwalsh.name/php-ternary-examples
Since you're submitting the form to the PHP file directly the browser loads the Edit_Project.php file as it would a normal page. If you want a json response to the already loaded page you'll have to use $.post or $.ajax
You can post the whole form simply by using serialize() like this:
$('#form_id').on('submit', function(e) {
// Stop the browser from posting the form
e.preventDefault();
// Post the form via Ajax
$.ajax({
url : 'Edit_Project.php',
type : 'POST',
data : $(this).serialize(),
success : function(response) {
// Here you do the HTML update
$("#"+j+"").html(response.reply);
}
});
});
The Edit_Project.php needs to be changed as well:
//The updation stuff at the server end
if (!mysqli_query($connection,$sqlquery)) {
$response = "'Error in your code: ' . mysqli_error($connection)";
}
else {
$response = "1 record updated";
}
mysqli_close($connection);
/*
* As SuperDJ suggested, you need to tell the browser that it's
* receiving a JSON ojbect although he did use the wrong content type:
*/
header('Content-Type: application/json');
/*
* According to php.net most decoders should handle a simple string as
* json object but to be safe always encode an array or an object since
* you can't know how the decoder will respond.
*/
echo json_encode(array('reply' => $response));

PHP: Running Multiple Scripts at the Same Time for the Same Client

I have one PHP script that can take several minutes to complete. The script downloads a file to the user PC.
I have another PHP script and its role is to monitor progress of the main download script. That script is called by the client via AJAX calls and should return download progress information.
Right now, my tests show, that during the execution of the main script(in other words, during file download), the AJAX - monitor script returns no values at all. It starts behaving normally, when the main - Download script finishes.
Is it possible that PHP can not run two or more scripts simultaneously and it allows to run script only in sequential order?
I could insert my code, but I think for the purpose of my question, it is not needed. I simply need to know, if two or more PHP scripts may run simultaneously for the same client.
I use:
WAMP
PHP Version 5.4.12
JavaScript without jQuery
Code Used:
As I was asked to show you my code, please, see the below code parts.
Main PHP(later Download) Script:
<?php
// disable script expiry
set_time_limit(0);
// start session if session is not already started
if (session_status() !== PHP_SESSION_ACTIVE)
{
session_start();
}
// prepare session variable
$_SESSION['DownloadProgress'] = 0;
for( $count = 0; $count < 60; $count++)
{
sleep(1);
echo "Iteration No: " . $count;
$_SESSION['DownloadProgress']++;
echo '$_SESSION[\'DownloadProgress\'] = ' . $_SESSION['DownloadProgress'];
flush();
ob_flush();
}
?>
Monitoring PHP script:
// construct JSON
$array = array("result" => 1, "download_progress" => $_SESSION['DownloadProgress']);
echo json_encode($array);
?>
JavaScript code, where I call the both PHP scripts:
SearchResults.myDownloadFunction = function()
{
console.log( "Calling: PHP/fileDownload.php" );
window.location.href = 'PHP/fileDownload.php?upload_id=1';
console.log( "Calling: getUploadStatus()" );
FileResort.SearchResults.getUploadStatus();
console.log( "Called both functions" );
};
JavaScript AJAX:
// call AJAX function to get upload status from the server
SearchResults.getUploadStatus = function ()
{
var SearchResultsXMLHttpRequest = FileResort.Utils.createRequest();
if (SearchResultsXMLHttpRequest == null)
{
console.log("unable to create request object.");
}
else
{
SearchResultsXMLHttpRequest.onreadystatechange = function ()
{
console.log("Response Text: " + SearchResultsXMLHttpRequest.responseText);
console.log("AJAX Call Returned");
if ((SearchResultsXMLHttpRequest.readyState == 4) && (SearchResultsXMLHttpRequest.status == 200))
{
//if (that.responseJSON.result == "true")
{
var responseJSON = eval('(' + SearchResultsXMLHttpRequest.responseText + ')');
console.log("Download Progress: " + responseJSON.download_progress);
}
}
}
var url = "PHP/fileDownloadStatus.php";
SearchResultsXMLHttpRequest.open("POST", url, true);
SearchResultsXMLHttpRequest.send();
}
};
Code Update I:
PHP Script that will later download files:
<?php
// disable script expiry
set_time_limit(0);
for( $count = 0; $count < 60; $count++)
{
sleep(1);
}
?>
PHP Monitoring script that outputs test values:
<?php
$test_value = 25;
// construct JSON
$array = array("result" => 1, "download_progress" => $test_value);
//session_write_close();
echo json_encode($array);
?>
Both scripts are called followingly:
SearchResults.myDownloadFunction = function()
{
console.log( "Calling: PHP/fileDownload.php" );
window.setTimeout(FileResort.SearchResults.fileDownload(), 3000);
console.log( "Calling: getUploadStatus()" );
window.setInterval(function(){FileResort.SearchResults.getDownloadStatus()}, 1000);
console.log( "Called both functions" );
};
Without more info there are a few possibilities here, but I suspect that the issue is your session. When a script that uses the session file start, PHP will lock the session file until session_write_close() is called or the script completes. While the session is locked any other files that access the session will be unable to do anything until the first script is done and writes/closes the session file (so the ajax calls have to wait until the session file is released). Try writing the session as soon as you've done validation, etc on the first script and subsequent scripts should be able to start.
Here's a quick and dirty approach:
The "Landing" page:
This is the page that the user is going to click the download link
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
$(document).ready(function(e) {
//Every 500ms check monitoring script to see what the progress is
$('#large_file_link').click(function(){
window.p_progress_checker = setInterval( function(){
$.get( "monitor.php", function( data ) {
$( ".download_status" ).html( data +'% complete' );
//we it's done or aborted we stop the interval
if (parseInt(data) >= 100 || data=='ABORTED'){
clearInterval(window.p_progress_checker);
}
//if it's aborted we display that
if (data=='ABORTED'){
$( ".download_status" ).html( data );
$( ".download_status" ).css('color','red').css('font-weight','bold');
}
})
}, 500);
});
});
</script>
</head>
<body>
<div class="download_status"><!-- GETS POPULATED BY AJAX CALL --></div>
<p>Start downloading large file</p>
</body>
</html>
The "File Uploader"
This is the PHP script that serves the large file... it breaks it into chunks and after sending each chunk it closes the session so the session becomes available to other scripts. Also notice that I've added a ignore_user_abort/connection_aborted handler so that it can take a special action should the connection be terminated. This is the section that actually deals with the session_write_close() issue, so focus on this script.
<?php
/*Ignore user abort so we can catch it with connection_aborted*/
ignore_user_abort(true);
function send_file_to_user($filename) {
//Set the appropriate headers:
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($filename));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filename));
$chunksize = 10*(1024); // how many bytes per chunk (i.e. 10K per chunk)
$buffer = '';
$already_transferred =0;
$file_size = filesize( $filename );
$handle = fopen($filename, 'rb');
if ($handle === false) {
return false;
}
while (!feof($handle)) {
/*if we're using a session variable to commnicate just open the session
when sending a chunk and then close the session again so that other
scripts which have request the session are able to access it*/
session_start();
//see if the user has aborted the connection, if so, set the status
if (connection_aborted()) {
$_SESSION['file_progress'] = "ABORTED";
return;
}
//otherwise send the next packet...
$buffer = fread($handle, $chunksize);
echo $buffer;
ob_flush();
flush();
//now update the session variable with our progress
$already_transferred += strlen($buffer);
$percent_complete = round( ($already_transferred / $file_size) * 100);
$_SESSION['file_progress'] = $percent_complete;
/*now close the session again so any scripts which need the session
can use it before the next chunk is sent*/
session_write_close();
}
$status = fclose($handle);
return $status;
}
send_file_to_user( 'large_example_file.pdf');
?>
The "File Monitor"
This is a script that is called via Ajax and is in charge of reporting progress back to the Landing Page.
<?
session_start();
echo $_SESSION['file_progress'];
?>

Categories