Alright, I have been trying to work on this issue for days, and have found no fix. I've asked about 4-5 different questions pertaining to my issue, but have found no solution.
file.php on example1.com:
I have a JavaScript function on this page that sends a POST request to a PHP file on example2.com (a DIFFERENT domain).
function buttonFunction() {
$.post("http://example2.com/core/runner.php",{username:username, password:pword, coins:coins}, function(data) {
// Stuff
});
}
This function dynamically loads the result of runner.php into a div on the page.
Now if the user leaves the page in the middle of execution (the result hasn't been generated yet) and then he/she refreshes the page, and then decides to run the function again, then two PHP proccesses would be running from the same user at the same time (that is, if the old one was still running).
Now I need a fix, whether that be in the PHP file on example2.com or within the JavaScript on example1.com that can abort/stop the previous PHP request before starting a new one.
What I've Tried:
#1
I've tried this, but unfortunately cross-domain cookies is practically impossible:
PHP session files saved, but no cookies and session not read
The goal was to store the PHP pid in a SESSION variable, and on every run, to check if the old proccess with that pid was still running (by grabbing the pid from the SESSION variable), if so, then I would kill that processes and change the value of the SESSION variable to the new pid.
#2
I've also tried to run a loop to check if the connection has been aborted while the main script runs. However, that also did not work:
PHP run loop and script at same time
#3
I also thought about doing something like this:
window.onbeforeunload = function(event) {
http.abort();
};
So it would abort the request before the user left/refreshed the page/browser. However, I was unsure about the reliability of this (Safe Way to Send POST Request via Javascript).
As pointed up by the other user, using files are the best way for doing this. My logic would be something like this:
When the runner.php runs:
First check if a file named username+number exists
If exists then delete that file, and create a new file named username + (number+1)
If does not exist then create a file named username+1
Store this number (i.e. 1 or number+1) in a variable
Do whatever processing is required
Before sending out the response back, check if the file named (username+ your number in var) exists
If yes, send out the response
If no, it means that another (later) process is running (only for that user because we name the file with username) and that process has deleted your current process's file, so just terminate without doing anything.
Of course this might not be the optimal solution, but should work for your use case.
Check the file functions in PHP, there are no complicated magic code required for this.
When You execute Your script runner.php for the first time You can create a file and lock it until script ends, so when there is another request to that script You can check if file is locked - and then You have information if You can run script again, example:
$fo = fopen('lock.txt', 'r+');
if (flock($fo, LOCK_EX))
{
// File was not locked, You have locked it successfully right now, do your logic
flock($fo, LOCK_UN); // unlock file afer script logic
}
else
{
// File is locked right now, don't run script
}
After that You can send message to user that he can try later (cause first script is running) instead of killing first script.
I think this is design problem when it comes to killing script, it doesn't look well. What about data when You kill script in middle of its execution? This can lead to some serious issues.
Related
Exactly when and where should I use session_start() in PHP?
For example, say I have a login script that sets a session variable to tell whether or not the user is logged in. Must I then put the session_start() at the top of the script, or only right before I actually set the session variable if the login was successful?
<?php
// session_start(); here?
if (login($username, $password)) {
// session_start(); or here?
$_SESSION["username"] = $username;
}
?>
Another case is this, according to w3schools
Note: The session_start() function must be the very first thing in your document. Before any HTML tags.
As others have said, the absolute requirements of what you must do are:
You must run session_start before you read or write to $_SESSION (otherwise it will just be an ordinary array and not saved anywhere).
You must not run session_start twice during a single script execution (page load) unless you use session_write_close to close it in between.
There is an extra rule that technically has exceptions, but is best treated as absolute:
Do not start the session after you have written any output (echo, HTML outside PHP blocks, etc), because PHP may not be able to send cookies to the browser if the server has already started sending the content.
There are two reasons you might want to avoid starting the session:
PHP locks the session when you open it to avoid two processes writing conflicting data into it, so if you have several requests happening at once, you want to avoid them waiting for each other unless they really need to. For instance, if you're responding to an AJAX request, and don't need any data from the session, don't open it.
As mentioned by symcbean, there is some cost to creating a new session, so if your site is busy with either legitimate or malicious traffic, you might want to serve some landing pages or error messages without starting it at all.
After that, it becomes a matter of style and architecture, but the rule of thumb that covers most of the above is "as soon as possible, if you're sure the page needs it".
Unless you have output buffering enabled, the session_start() must come before anything other than headers are sent to the browser (as it sets a cookie in the header).
It must come before you attempt to reference the $_SESSION data.
In your example there are no html tags being output before either instance - so both would work.
There some cost to opening a session, so if you are doing additional, non-session based validation of the request, then deferring session_start() till these checks have passed does give you a bit more resillience against DOS attacks.
Starting the session at the top of the page is most of the times the best. But if you don't need the session for the whole document/code, you could always put it, as in this example, after the if() clause.
The session_start() function can go anywhere in your code. You should just place it at the beginning of your document for consistency and call it a day. If you have a separate database or config file you are including on all your login/database driven pages, you should place it in there so you don't have to recode it into every page.
I am new to web development and I am trying to build my first website.
I am having some troubles because web development is dependant on several programming languages like PHP and JS, and the most difficult part for me is to communicate between these languages.
For example, I am trying to create a function that compresses a folder and generate a download link to that new archive, this can be easily done by PHP. However, when the user clicks the zip button, I also wish to display a pop-up window that tells the user to wait while the folder is being compressed, and when the compression is done I want to change the text on that pop-up and display the download link, and this, of course, requires JS.
I've tried many solutions but none of them seemed perfect for me, and I feel like that these solutions are quick and dirty, which I don't want.
If there is a secret I do not know, please tell me about so I can finally work with these languages as if they are a single language.
Also, if you can help me with my current problem, I would be extra grateful.
I just want to know how to construct a form that can call the JS function that displays the pop-up, then calls the PHP Zip_Folder function, and once the PHP function is done, I want to display the download link on the pop-up window.
This is my form code: (It only calls the javascript function that displays the pop-up)
<input type = 'button' onclick = 'Show_PopUP(\"Folder_to_zip\")' value = 'Download Folder'>
And this is the Show_PopUP function code:
function Show_PopUP(folder) {
var e = document.getElementById('Folder_Download_PopUp');
if(e.style.display == 'block')
e.style.display = 'none';
else {
e.style.display = 'block';}}
I already have the PHP function that compresses and generate a download link for the archive, so what I need now is a way to call it after the pop-up is displayed, and a way to print the download link on the pop-up once the function is done.
This might not be the best approach since I am a beginner, so if you have suggestions on how to get my task done without this complexity, I would be very happy.
Sorry if my question is too long, and thanks in advance for your help.
What you need to do is use these things called XHRs, or XMLHttpRequest (Google it), from within JavaScript to php, which basically is kind of like an invisible browser going to the php page behind the scenes and "loading" whatever the php page gives back, only this is all happening within JavaScript itself, so you can read that this "invisible page" loaded, which is from php, and do stuff with that, without actually refreshing the page. This process is known as AJAX (look it up)
What you can do is, when you set up this "invisible page", you can also send certain kinds of information along with it that the php page can read, and when it's done the php page can echo something back to the invisible page, which can then be read with JavaScript. This easy you can communicate between php and JavaScript, by sending certain values, in JavaScript, along with this invisible page, and waiting for php to echo something back to it, then reading that with JavaScript
So how do we actually do this?
First on the JavaScript side, we need to make this "invisible page", which is really not technically a page, it just does the sane thing as what is done to display any other web page, which is technically called a "request" since it's like asking the server for some data, it's basically "requesting" it, then when the server echoes something back, that's called he "response" to what was requested
So to make this new request in JavaScript we can do the following
var asking= new XMLHttpRequest ()
now that it as if an invisible page was created, but not yet navigated to anything, but we have to now metaphorically "enter in the URL" to this invisible page (without actually "navigating" to it yet) to do that we do
asking.open("GET", "pathToPHPpage.php?hi=there")
So the first part is called "GET" because we want to simply get a response back, without actually sending anything (if we were sending a file though, we would instead use "POST" then put the file date in the next step), then we enter in the URL to the php page that you want to get. If it's the same as the JavaScript page just put location.href instead, but it's important to add at least something to the end of the URL, notice the "?hi=there", you can call it anything, but it's important to have a question mark immediately following the .php page, then the name of something (in this case"hi") followed by it's value (in this case "there"), because the php page is able to read that, and give a different response back depending on what it says
Ok so now we have to actually "send" that request to the server, which is like metaphorically "navigating" to the URL on the invisible page, to do that
asking.send()
(And if you put "POST" before, you can add the date you want to send in between the parenthesis, usually in the form of a string but it can be different depending on the data, look it up for more reference)
Now, before we continue in the JS side, let's quickly switch over to PHP (doesn't have to be in this order though) to see what happened
We need to listen for any "requests" on the php page, that contain the name "hi" (since that's what we at the end of the URL before), to do that, around the top of PHP (technically anywhere in php though) we do
$isHi = $_GET["hi"];
if(isset ($isHi)) {
//Do some php code
echo "hi back!".$isHi;
}
Basically we just looked for the *hi" name in our "GET" request that was sent to PHP, we checked if it is "set", meaning not nulll, then we echoed some message back to JS, now let's listen for that message on the JavaScript side
Back to JS, after the .send line (or before), we need to listen for when the page echoes back.
To do that we check if it successfully loaded, because sometimes there can be errors, so let's do
asking.onreadstatechange= function () {
if(asking.readyState == 4 && asking.status==200) {
alert(asking.responseText)
} else alert("ooh something happened")
}
Now we have access to the response the php code gave us
You can extend this to other forms of communication, let me know if you have any questions
I was wondering if there was any way to create something like a txt file in Ajax. I'm using this to save logs created by the user on my site, this is the link if its helpful: site. If this cannot be done with ajax can it be done with cookies? Or would the log be to big for cookies? Thanks(sorry if this is a duplicate, some I looked around and everything was about loading/reading from a file).
AJAX is just making asynchronus HTTP calls on the browser.
So, can you create a file just making an ajax call? No. You would need to setup somekind of script on the server that will handle the file creation and writing and call that script with AJAX.
The short answer is - no. You can not do this DIRECTLY with AJAX.
The longer answer is - what you are looking for should be done using a database and SQL. Not that PHP couldn't do it directly - but a good database is better able to handle this problem.
AJAX is mainly used to just send and receive messages, files, etc... It isn't for storing anything. With that being said, the steps would be to have a small PHP script that just reads and writes to a database and make that database be a log file. So your SQL database (I'd just call it log) would have two entries. These are the date the log entry went into it and the entry itself. You could also throw in last_accessed if you want or other fields you think you might need. Your PHP script, in its simplest form, would open the database and, depending upon whether you send it a "GET" or "PUT" command it would read from or write to the log file. If it writes to the log file, it sends back an ACK or NAK (meaning everything is ok or the program had a problem). If it is reading from the log file, you supply how many lines you want to read and the PHP script either sends back the lines or a NAK again to signify something went wrong. You can also replace the simple NAK with the actual error if you want but then your customers are seeing the error. Better to have just a generic "There has been a problem, we have contacted our system people and the site should be back up shortly" kind of message. Save the actual errors for you to see via e-mail.
That's it. You should be able to write this in about ten to fifteen minutes and have your log file readily available to you in no time.
Some of our customers are reporting that they are unable to execute some javascript actions. Our error data collecting is on the server and when javascript breaks we are unable to get notified it since ajax calls can't be run before page refresh.
Is there a way to collect javascript errors on client side and send them to the server as soon as javascript is running fine again.
Example:
User goes to page a.php.
There's faulty javascript on a.php and it breaks user's javascript.
User's client logs the errors and stores it locally.
User goes to page b.php.
There are no faulty javascript on b.php and the client detects that there's javascript error logs stored locally and proceeds to send them to the server.
The server writes the log up.
There is no need to refresh the page to make AJAX calls. You just need to make sure that the error handling code is in its own script tag so that it won't break if there is a syntax error in the other code.
Here is part of the code that we are using to catch script errors and send them to the server (The AJAX code is in a separate method, but I trust that you already know how to do that):
window.onerror = function (message, url, line, column) {
Ajax.logError(message, url, line, column);
$('body').append($('<div>').addClass('ErrorPanel').text('An error occured in the browser.').delay(5000).animate({ height: 0 }, 2000, function() { $(this).remove(); }));
return false;
};
Maybe you should take a look at New Relic. New Relic is a monitoring tool for software analysis and it's able to show you various information about JavaScript errors (and much more):
http://newrelic.com/browser-monitoring
I'm currently creating an image hosting script and so far so good. I've used several plugins to create the local uploading process with drag & drog + AJAX which works totally fine. Now I've moved to the part where I need to create the remote uploading process with jQuery AJAX and a PHP script to handle the whole thing.
How it's gonna work
My thought are like this: There is a big box in the middle of the page that accepts the URLs to be remote uploaded. Once valid URL(s) are passed into the text area, they will be immediately sent to the server side script via jQuery AJAX. It's bound with a keyup event.
This is how it looks like: http://i.imgur.com/NhkLKii.png.
The "HERE COME THE URLS" part is already a text area - So that part's already done.
Where I need help
The issue with this whole situation is: Once there are valid URLs pasted into the text area, those must be immediately be converted to some sort of box which also includes an uploading progress. Something that looks like this (copied from the local uploading part): http://i.imgur.com/q7RyDmb.png
It was easy implement the progress indicator for the local uploading, since it was a feature offered by the plugin I've used, but I don't know how to indicate the progress of remote uploading, which is totally being made from scratch.
So this is how I've imagined the logic to flow:
User pastes some URLs into the text area
There is a client-side check to validate the pasted URLs
Validated URLs are send to upload.php on keyup (?)
URLs are being processed
While the upload goes on, we show the users the progress in the knob (?)
PHP script finishes the process and returns back the uploaded URLs
I update the page in the AJAX success callback to display the uploaded files
So, the two process flows marked with (?) are unclear to me - I don't know how to achieve those...
What I have tried
Well, I didn't just come here and ask you to do everything for me, but I've come across a dead end and I don't know how to continue. What I've done so far is collect the URLs from the text area, and if there are multiple URLs separated by a line break (\n), I simply use split to get an array of pasted text and then use another function inside the loop to validate if they are URLs. If there is no line break detected inside the text area value, then I simply check the one line that was provided. On each case, I send the whole text area to the PHP script, because I don't know how to get rid of the invalid URLs in jQuery. I've created a function called debug() in PHP which stores anything into a debug.log file and this is what I'm getting (in one try) when I paste something into the text area:
https://www.google.com/https://www.google.com/
I paste https://www.google.com/ once in the text area, but it gets logged twice in the PHP side and I can't determine why.
This is how my jQuery looks like:
// Remote upload
var char_start = 10;
var index = 0;
var urls = $('.remote-area');
var val_ary = [];
urls.keyup(function(){
if (urls.val().length >= char_start)
{
var has_lbrs = /\r|\n/i.test(urls.val());
val_ary = urls.val().split('\n');
if (has_lbrs)
{
for (var i = 0; i < val_ary.length; i++)
{
if (!validate_url(val_ary[i]))
{
val_ary.splice(i, 1);
continue;
}
}
$.ajax({
type: 'POST',
url: 'upload.php',
data: {
upload_type: 'remote', // Used to determine the upload type in PHP
urls: val_ary, // Sending the whole array here
},
});
}
else
{
if (!validate_url(urls.val()))
{
// Display an error here
return;
}
$.ajax({
type: 'POST',
url: 'upload.php',
data: {
upload_type: 'remote', // Used to determine the upload type in PHP
urls: urls.val(), // Sending what's in the text area
},
});
}
}
});
The questions
So the final questions are:
How do I send my information correctly to the PHP script, only valid URLs and have them kind of "process-able" in my PHP script.
How do I indicate the progress of the upload?
If I was somewhere unclear during my question, please let me know, I'll try to reexplain.
Thank you.
Updates
09/12/2013
I think I have managed to solve the double-sending issue where my AJAX would send the same information twice to the PHP script. What I did was code in a delay anonymous function that sends the text area content to the PHP script after an user stops typing for 2 seconds. Once the user stops typing again, the timer resets and a new AJAX request will be made. So, I'm assuming that this issue has been solved. I'll come back to it if anything strange occurs.
Now I'm still left with the progress indicators part. I'd appreciate your thoughts on that one.
My new code: http://pastebin.com/SaFSLeE9
What you're looking for in terms of communicating progress back and forth is "pushing". That refers to the technique of server sending data to the client, rather than the other way around, which is the standard HTTP way of doing things.
You've got plenty of options available, as described in the explanatory Wikipedia article, though perhaps more relevant to this topic would be Comet. What happens is you trigger and $.ajax call just like the one you have now, but you set a very long timeout. That essentially gives the server a "channel" to send data back to the page whenever it's available.
So what you need is a .php on the server that is capable of handling long polling and will send data back to the page as the upload progress changes (probably in array form for multiple uploads). This article should get you started with some jQuery code. Just remember that this request doesn't go to upload.php. This request goes to a different script that deals solely with upload percentages and only returns data when that is available, it doesn't return immediately as all others scripts - the Ajax will happily wait for the data.
Also, don't separate your code like that with has_lbrs. One line or many are not distinct cases, one line is just an edge case of many lines. You're duplicating the code unnecessarily. What does the else case do that would break in the general case? Further, the "error handling" in the else case is misleading. The only error reporting you do is if there is only one line and it's wrong. What if you have two lines and they're both wrong? Your code will happily send an empty array to upload.php.
This is why I think you shouldn't separate your code like that, because then you'll split logic and not even notice it.
In my opinoin, the best way is to call your cURL script with ajax and use it to upload your files on remote server. You need ajax.js, curl.php, index.php (whatever name you want) on your app server. And image.php, class.image.php (whatever name you want) on your remote server.
Steps that I did for my app
1) I am going to upload an image from my index.php file. It will call curl.php file using ajax.js and the cURL file will check file's extension and all (for your app's security, make sure what you want to allow users to upload).
2) Now the curl file will upload the file to your pre defined temporary folder with the default file name.
3) Now if move_uploaded_file function (which I used in my script) run successfully, you can call your cURL function to send your data as post on your remote server, where image file will receive posts and will process further. You can keep your class in image.php or you can create two PHP files on your remote server, as you want.
4) Now in your class file, you should check file once again that it is image file (and whatever you want to allow) or not for better security. If file is good, process to rename it and add file into folder if you want to.
5) Add file's new name and folder name into your database by using remote database connection. So, cURL will show you result on the same page.
Now, why cURL? I prefer cURL because, you can add secret key or API for your communication to make it more secure, with if else conditions. Your remote server file which is going to receive all posts, will check if API == 'yourKey' then will process other wise it wont process and nobody will be able to send images on your server with bots and all.
I don't know that my answer is going to help you or not, probably my method is lengthy or not good for your app, but try to Google about cURL and you will understand what I am trying to say. Hope you like it and understood it. If any doubt, you can ask me any time.