How do I make SQL changes without leaving the page? - php

I have a page which lists out book reviews which are pulled from an SQL database, and listed out in a loop with PHP.
The text of some of the reviews may contain "spoilers" (meaning the review reveals plot points and may "ruin the surprise" for would-be readers.)
I want to have a link/button which a reader clicks, saying "This Review Contains Spoilers". When they click it, there's a field in the SQL record for that review, which gets incremented. But, without leaving the page, as the viewer will continue reading the reviews.

You need to make use of Ajax, exactly of XMLHttpRequest (abbr.: XHR). jQuery is a good framework that has cross-browser support for the different XMLHttpRequest calls. With this technique you could send a http request to a server at any time on the loaded page you want. E. g. when the user clicks the spoiler. For more information about it see here: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest For more information about jQuery please see here: http://www.jquery.com

Related

How can I use PHP to prepopulate a form on OR send data to a 3rd party website?

I am building a web app that contains a form. Currently, the user enters data into this form, which is saved in my database. Then the user opens a 3rd party website where it enters a subset of the exact same data into a form on that website.
Ideally, on submitting the form on my website, I would like to open the 3rd-party website in an iframe with its form prepopulated with the data already collected from my form. The obvious goal is to prevent the user from having to enter this same data twice, first on my form and second on the 3rd party form. Another benefit would be the lack of focus from my site as the user would need to complete additional steps after submitting the form on the 3rd party site.
I know that there are ways to prepopulate forms on other websites. For instance, Google Forms allows for forms to be prepopulated by passing values to the corresponding inputs' name attributes in a query string. Here's an example I created to demonstrate this (notice the query string.): https://docs.google.com/forms/d/e/1FAIpQLScqua9AJLvRgCuH8o-XfAGeZcbue9ND7a4z2JM5EcAuVqAwag/viewform?vc=0&c=0&w=1&entry.2020941857=Whatever+and+whatever&entry.473490210=foobar
Unfortunately, the "target" website does not appear to handle the incoming GET requests in a similar manner, which obviously should come as no surprise. Of course, it can't always be that easy. I can't even manipulate the values of the inputs in the target website's form by manipulating the DOM using Chrome DevTools (not that I would have any real understanding how that would help me even if I could).
Furthermore, the form doesn't even submit using an action attribute. Instead, here are the form and button elements that I admittedly don't understand (omitting some attributes for brevity's sake):
<form name="theForm" ng-submit="submitForm(theForm.$valid)"
no-submit-on-enter="" novalidate="">
<button class="btn btn-full ng-binding" type="submit" id="send-form"
track-event="{category: 'theFormSubmit', action: 'clicked'}"
skip-click-tracker=""> Submit </button>
</form>
I have also tried using DevTools to watch the headers as I submit information using the form. The headers don't appear to change when I click the button. In fact, there appears to be no activity at all in the Network tab when I click the button. I don't see any "Form Data" at all. But it's possible I'm misunderstanding what I'm seeing.
For what it's worth, it appears that the target relies heavily on Angular.js, which I know practically nothing about, so I'm not sure if its even relevant. I also am aware that iframes cannot be manipulated by javascript on my site unless it is of the same domain, which it is not. I briefly looked into phantom.js, but (from the little I understand) it appears that there would be an issue with maintaining the user's session on the target site. A reload would be required which would wipe out the prepopulated data defeating the entire purpose.
Anyway, I'm left wondering if there is some way to achieve my goal using PHP curl or really anything. As a side note, in case it is not already obvious: I do not have access to the full source code of the target website nor will I likely be able to obtain access to it.
UPDATE:
Using DevTools Network Tab, I again tried submitting the form with one of the inputs being the first name of Jude. I was finally able to isolate the header that contained the information by filtering by "Jude". The redacted header info and request URL are below:
I feel like I am finally getting somewhere. Based on the above, I feel that I might actually be able to submit the form data to the 3rd party website (sidestepping the actual entering and submitting of that website's form). Because I was using the UI, I could see that the form was submitted successfully, and I had visual cues for how that information was being dealt with. However, the HTTP 204 header (No Content) seems to indicate that if I send the information programmatically, there will be nothing returned for me to analyze success or failure of the form nor how the information is being dealt with. Ultimately, in the end, this may all be a red herring regardless because I am not sure how I would deal with the browser_session_id part of it anyway.
If you are using an iframe you might be out of luck, since browser cross origin policies will deny your JavaScript from tampering with the DOM in the IFRAME.
If the target website is simple enough, you can proxy over the whole form request and responses, cookies, and headers thorough your server (especially if you are using PHP) and then you are free from cross origin problams since the browser will see them as one origin
then you could access the iframes DOM
window.frames[0]...
or the anguler scope using
angular.element("#appname").scope()

How to avoid some SQL queries in PHP?

I am developing a PHP web app with jQuery and Twitter Bootstrap. And it uses AJAX for everything. So, I show a form in HTML5, the user press a button (class="btn"), the form is sent to PHP (jQuery, AJAX), PHP makes a query to the MySQL and echoes an answer, which is shown in the form (jQuery). This is basically how the web app works.
But here's the deal, the first form it is showed, it's a div that shows some news. For example:
A new user was created.
There is new important date.
Someone wants to text you.
So I've created a table in MySQL called News where I saved some values than mean something like:
1: A new user was created
...
Everytime the user log in will se that. It means that there will be a query and a response as soon as the HTML5 get loaded when a user log in.
The index.html file has a navbar (Bootstrap), and a option call News. When the user clicks it, the same query will be executed, but not necessarily the same response.
I thought in modifying the div with news whenever the user does an action. But, an action can also be done by another user. So it is necessary to make the query again!
Is there any solution that allows me to avoid querying the database when the user wants to get the news? Or how can I know that it is necessary to update the div right now? I was taking a look at caching queries but didn't arrive to a conclution.
Sorry if my english is not too good, it is not my native language.
Thank you.
You can send a timestamp in every news response from the server and save it in javascript. The next time you make a request, send the timestamp you saved and the server checks if there are more recent news, sending nothing if there is none as the last response is still the newest.
Well, there is a downside here, you still need to make a query to the database (filtring the results with a WHERE clause like 'WHERE ... TIMESTAMP > last_timestamp_from_browser') which is perfectly valid, SGBDs are designed for this, and if you don't have thousands of users accessing your website at the same time there will not be any problem. With this approach you will only save bandwitdh as the connection to the database is still made.
There is another way that prevents this connection from being made, cache some values of last news inserted which could be user specific or global and save them in APC module (or memcached). You'll need to discover what to cache and when (you can't cache the entire database, just some well organized timestamps and maybe the most requested news for example). This way you prevent the database connection from being made. This will force you to do many many more code, so, use it only if you really need it, like thousands of user connections at once.

deny access to data(a video) when hitting back button on browser

Im doing a quiz (php and mysql) for some students, the quiz is based on a video they have to watch..
the order is this..
1)they enter a unique web page for every user
2)access a page with a video for the user to watch...
3)on the bottom of the page there's a button "Answer Quiz"
4)When they click the button, they are send to a page with the quiz
Here's where the problem happens, i want to prevent the user from watching the video again, but when they hit the back button, well there's the video again for them to watch
im blocking the video in a video table in mysql db, but the video is cached or something, so this is not the approach of preventing the user to watch the video again when hitting the back button...
.
any ideas of how to achieve this??
any help appreciated......
Checking from your latest comment, I would assume that you have a table, expired_quizzes with at least three columns, quiz_id, quiz_filename and the boolean is_active. I would also normalize the table to a userid as well, so if user A views it and takes the quiz, user B can still see the video (makes cheating with a friend easier, though). It is hard to know exactly what is going on without seeing any code or structure, but try checking a couple of these things:
If you look up the quiz based upon a search, and the webpage uses a variable $_GET, then anytime the webpage is visited, it will always load the quiz. So considering:
http//www.yourwebpage.com/?quizfilename=viewablequiz.mp4
Depending upon your PHP instructions, it will always load viewablequiz.mp4. There are two recommendations to prevent it.
Don't load $_GET['quizfilename']. Rather load $_GET['quizid'] and recall the filename from the query with additional search parameters, such as:
'SELECT * FROM expired_quizzes
WHERE quiz_id='{$_GET['quizid']}' AND is_active=1
LIMIT 1;'
Then, return row['filename'] in your PHP code, or handle with a response to the user if no results are found (no unexpired quizzes).
Load the video via AJAX. Use a similar query on the PHP side as mentioned above, but since it requires a look-up after loading, a refresh of the screen will not load anything.
To prevent cheating, you should probably also have another table which records every time the video is viewed, with a timestamp and userid. It can help detect a cheating attempt later by seeing who was testing and viewing at the same time.
Of course, always protect against SQL injection and don't put user input directly into the SQL statement.
For a more detailed analysis, you should post just the relevant PHP, HTML and SQL within the question.

GET an POST data for Mozilla

I am doing my work in PHP.
I have 3 pages,
A is plain HTML and contains a search field.
B is .php and returns results of the search.
C is also php and allows user to update some details for the displayed results.
When I'm doing Refresh my B page or Go-Back from C to then I
get this message
"To display this page, Firefox must
send information that will repeat any
action (such as a search or order
confirmation) that was performed
earlier."
I saw "When i'm using "POST" method then I get this message, if I'm used GET then
I don't.
Any buddy Explain me ,why???
The GET method should be used to obtain information from a web page.
The POST method should be used to send information to a web page.
The reason it asks you to confirm whether or not to send information again is because it's not always the user's intention to repost a form if they press back. One example is at an online store, you would not want to repost a form to purchase a product twice, otherwise you could be billed for the product twice. This is theoretical of course since someone who makes an online store should ensure that an accidental purchase can't happen.
Also, if you use GET, then all information is appended to the URL of the PHP page. This is a potential security issue, especially if the form contents are private. For such forms, you should be using POST.
A wild guess,
POST is not written in the URL, so you need to resend it, while GET, when you click to return to B, the arguments are still in the URL so you dont need to resend.
Mozilla added this message to warn you from sending the information twice.
Like in the form of registration, you don't want to register twice.
Firefox developers added that warning for POST method. It will warn you for POST in case of back/forward also.
This is an added safeguard for users. Because, most shopping carts/banking portals use POST method for checkout/transaction confirmation (actually I have not seen or developed any web app to use get method for this purpose).
So, Firefox (and most other common browsers) warn you in this scenario (when your are sending POST request indirectly, i.e. using back/forward/refresh button). This prevents the user from multiple checkout.
Another reason to add this warning is, sometimes chekout is time consuming. So, when some time is passed after the original submission, some impatient users think that the browser/server has stopped working. So, they tend to press the refresh button. This warning gives them a good hint.
I think the point is that GET requests should be used to get information without changing anything on the server so if you reload the same information there's no issue. POST requests should be used to change data on the server so when you reload the page that may have undesirable effects.
Firefox should normally allow you to navigate back to your B page from your C page. However if your B page is not in the cache, possibly because it sends a Cache-control: no-store header, then you will get the POSTDATA warning.
On the other hand explicitly reloading page B will always generate a POSTDATA warning.
When you submit data in the POST method, it sends headers to the page you submit to. When you refresh the page or go back, your browser repeats your POST request and Firefox warns you of this.

Prevent Back button from showing POST confirmation alert

I have an application that supplies long list of parameters to a web page, so I have to use POST instead of GET. The problem is that when page gets displayed and user clicks the Back button, Firefox shows up a warning:
To display this page, Firefox must send information that will repeat any action (such as a search or order confirmation) that was performed earlier.
Since application is built in such way that going Back is a quite common operation, this is really annoying to end users.
Basically, I would like to do it the way this page does:
http://www.pikanya.net/testcache/
Enter something, submit, and click Back button. No warning, it just goes back.
Googling I found out that this might be a bug in Firefox 3, but I'd like to somehow get this behavior even after they "fix" it.
I guess it could be doable with some HTTP headers, but which exactly?
See my golden rule of web programming here:
Stop data inserting into a database twice
It says: “Never ever respond with a body to a POST-request. Always do the work, and then respond with a Location: header to redirect to the updated page so that browser requests it with GET”
If browser ever asks user about re-POST, your web app is broken. User should not ever see this question.
One way round it is to redirect the POST to a page which redirects to a GET - see Post/Redirect/Get on wikipedia.
Say your POST is 4K of form data. Presumably your server does something with that data rather than just displaying it once and throwing it away, such as saving it in a database. Keep doing that, or if it's a huge search form create a temporary copy of it in a database that gets purged after a few days or on a LRU basis when a space limit is used. Now create a representation of the data which can be accessed using GET. If it's temporary, generate an ID for it and use that as the URL; if it's a permanent set of data it probably has an ID or something that can be used for the URL. At the worst case, an algorithm like tiny url uses can collapse a big URL to a much smaller one. Redirect the POST to GET the representation of the data.
As a historical note, this technique was established practice in 1995.
One way to avoid that warning/behavior is to do the POST via AJAX, then send the user to another page (or not) separately.
I have been using the Session variable to help in this situation. Here's the method I use that has been working great for me for years:
//If there's something in the POST, move it to the session and then redirect right back to where we are
if ($_POST) {
$_SESSION['POST']=$_POST;
redirect($_SERVER["REQUEST_URI"]);
}
//If there's something in the SESSION POST, move it back to the POST and clear the SESSION POST
if ($_SESSION['POST']) {
$_POST=$_SESSION['POST'];
unset($_SESSION['POST']);
}
Technically you don't even need to put it back into a variable called $_POST. But it helps me in keeping track of what data has come from where.
I have an application that supplies long list of parameters to a web page, so I have to use POST instead of GET. The problem is that when page gets displayed and user clicks the Back button, Firefox shows up a warning:
Your reasoning is wrong. If the request is without side effects, it should be GET. If it has side effects, it should be POST. The choice should not be based on the number of parameters you need to pass.
As another solution you may stop to use redirecting at all.
You may process and render the processing result at once with no POST confirmation alert. You should just manipulate the browser history object:
history.replaceState("", "", "/the/result/page")
See full or short answers

Categories