Capture all links including form submission - javascript

I am wondering how to capture all links on a page using jQuery. The idea being similar to Facebook. In Facebook, if you click on a link it captures the link and loads the same link using ajax. Only when you open a link in new tab etc. will it load the page using regular call.
Any clue on how to achieve such kind of functionality? Am sure capturing links should not be a problem, but what about capture form submissions and then submitting the entire data via ajax and then displaying the results?
Is there any plugin which already exists?
Thank you for your time.

Alec,
You can definitely do this.
I have a form that is handled in just this way. It uses the jquery form plugin kgiannakakis mentioned above. Example javascript below shows how it might work.
$("form").ajaxForm({
beforeSubmit: function(){
//optional: startup a throbber to indicate form is being processed
var _valid = true;
var _msg = '';
//optional: validation code goes here. Example below checks all input
//elements with rel attribute set to required to make sure they are not empty
$(":input [rel='required']").each(function(i){
if (this.value == '') {
_valid = false;
_msg += this.name + " may not be empty.\n";
$(this).addClass("error");
}
});
alert(_msg);
return _valid;
},
success: function(response){
//success here means that the HTTP response code indicated success
//process response: example assumes JSON response
$("body").prepend('<div id="message" class="' + response.status + '"></div>');
$("#message").text(response.message).fadeIn("slow", function(){
$(this).fadeOut("slow").remove();
});
}
});

Form plug-in can transform a regular form to an Ajax one:
$("#myForm").ajaxForm(
{beforeSubmit: validate, success: showResponse} );
It would be difficult to do what you want however for an arbitrary form. What if the form uses validation or is submitted by Ajax to begin with? The same thing applies for links. What if there are some javascript navigations scripts (window.location = Url)? If you don't have full control of the page, it will be difficult to do what you want.

Usually pages like facebook, do each event and each form separately coded, as the server-side files are usually set for each single operation / group of operations. I doubt there will be a clean way to convert a page with just a plug-in. And if it is, I see a lot of overhead.
You can do it by hand, but again that's abuse of Ajax. This isn't flash, and with using ajax for all server communications you run into a lot of problems.
Lack of history tracking.
Watching out for concurrent events and the results of thereof.
Communicating to the user that the page is changing.
Users with javascript turned off.
And much more...

Related

Conceal URL in javascript code ( URL generated by PHP )

I am looking for a solution to the following:
I have a piece of JS code, that performs a redirection to a URL that is constructed with PHP, and that redirection is only done when the user presses a button on a confirmation dialog.
The code is, as follows:
function one() {
window.location.replace("<?php
if($new_redir == "1") {
echo "$new_second_redirect_URL/?token=$hash";
}
else {
echo "$second_redirect_URL/?token=$hash";
}
?>");
}
It works perfectly fine. What I wanna do is conceal the URL that is displayed in the source code when a user opens the page.
What would be the best way to do that?
You're thinking too much into this to be honest.
If they want to avoid the confirmation screen and get the URL from the source, there's not really much you could do.
The best really is possibly performing an AJAX request on confirmation and getting a CSRF token based URL from the response and using that, but that could end up being overkill as well.
You could also make it into an actual <form></form> form with a few hidden fields (again, such as a CSRF token), and perform the post validation onclick. If it a success - redirect them.
UPDATE:
Use robots.txt to stop bots
Build the QS with JS to stop most bots, something like:
var csrftoken='XJIWHEOU324uipHFOFUHR';
var url="http://url.com/page.php?token=";
url=url+csrftoken;
What you could also do, is something like us actually, although for your use case it could be too much.
Log every single page load into the DB, and check if if they're a first time visitor to the page after confirmation.
AJAX call (jQuery example):
$.post( "url_to_backend_page_to_get_url", {hasSubmittedForm:"true"}, function( data ) {
window.location.href = data;
});

Preventing XSS Attack on Form

All:
I have an issue with a project I am working on using C# MVC4
In the project, I am accepting a URL and other parameters from a user, then do some processing and send the result of the processing to the URL provided by the user.
The result is being sent using the following code:
var context = HttpContext.Current;
context.Response.Write("<html><head>");
context.Response.Write("</head><body>");
context.Response.Write(string.Format("<form name=\"myform\" method=\"post\" action=\"{0}\" >", postUrl));
context.Response.Write("</form>");
context.Response.Write("<script type=\"text/javascript\">document.myform.submit();</script></body></html>");
context.Response.Write("</body>");
context.Response.Flush();
context.Response.Clear();
context.ApplicationInstance.CompleteRequest();
Whenever a user attempts an XSS like passing a url value of javascript%3aalert('xss')%2f%2f, the JavaScript runs and the pop up shows up.
I've tried Antixss.HtmlEncode() to encode the URL before passing it into string.Format but still doesn't work. I've tried Antixss.UrlEncode() also, but this gives error as the form doesn't submit to the URL.
Please help me out, Is there something I am missing? What else can I do?
Thanks in advance.
You will need a three pronged approach to solve this issue.
Preventing XSS injection:
Note that if a user injected the url value
" /> <script>alert('xss')</script>
this would also leave you vulnerable:
<form name="myform" method="post" action="" /> <script>alert('xss')</script>" >
Therefore you should use the HttpUtility.HtmlAttributeEncode function to solve this one.
However, don't stop there. As noted, you should project against javascript: style URLs. For this I would ensure that the URL begins with http:// or https://. If not, throw a SecurityException which you should be logging and handling server-side, and showing the user a custom error page.
Finally, you want to protect against Open Redirect Vulnerabilities. This is to stop phishing attacks by redirecting users to other domains. Again, use a whitelist approach and ensure that the domain redirected to is one of your own. Be careful on the parsing here, as it is easy to get it wrong - a URL of http://example.org?http://example.com will pass the validation filter for example.com on many badly written validation routines. I recommend using the Uri object in .NET and retrieving the domain through that rather than rolling your own string functions.
You could also check if the URL is a relative URL, and allow it if acceptable. Use something like this function which uses a built in .NET library to ensure that it is relative or not.
Just a thought - try putting this script in rather than just document.myform.submit (and remove the form's action property):
if("{0}".indexOf('http') !== 0) {
//this is some sort of injection, or it's pointing at something on your server. Should cover http and https.
//Specifically, it makes sure that the url starts with 'http' - so a 'javascript' url isn't going to work.
} else {
document.myform.action="{0}"
document.myform.submit();
}
There is more you could do, but this should help.
Since you are adding the postUrl as an attribute "action" of the form tag, you can try using HtmlAttributeEncode method in the HttpUtility
[ValidateInput(false)]
public ActionResult Test(string url)
{
var context = System.Web.HttpContext.Current;
context.Response.Write("<html><head>");
context.Response.Write("</head><body>");
context.Response.Write(string.Format("<form name=\"myform\" method=\"post\" action=\"{0}\" >", HttpUtility.HtmlAttributeEncode(url)));
context.Response.Write("</form>");
context.Response.Write("<script type=\"text/javascript\">document.myform.submit();</script></body></html>");
context.Response.Write("</body>");
context.Response.Flush();
context.Response.Clear();
context.ApplicationInstance.CompleteRequest();
return null;
}
http://localhost:39200/home/test?url=https%3A%2F%2Fwww.google.com - Worked
http://localhost:39200/home/test?url=%3Cscript%3Ealert(%27test%27)%3C%2Fscript%3E - Worked(Did not show alert)
It is always good practice to Validate the user input against a white list of inputs, to prevent XSS exploits.
try using HttpUtility.UrlEncode
something like Response.Write(HttpUtility.UrlEncode(urlString));
see How To: Prevent Cross-Site Scripting in ASP.NET for more steps =)

Altering the DOM with the Play! Framework

Hello again StackOverflow.
I've been tasked with modifying a website that runs on Scala's Play! framework and Twitter Bootstrap. I've hit a roadblock concerning altering the DOM. I need to accomplish the following:
(The page being talked about takes user input and passes the server a Form, which if
valid writes the mapped Data in the Form to a database.)
Have the user choose a category from a drop-down. This particular drop-down has nothing to do with the Form.
Based on their choice, query the database for all objects of a certain type that relate to the chosen category via a foreign key.
Alter the DOM (that is, show without reloading the page) to display those objects for the user to select them. Their selections are added to the Form.
Submit the Form, write to the database, etc.
Questions:
Is this a good way to go about what I'm trying to accomplish?
If so, is there a way to alter the DOM via Scala/Play HTML templates without reloading the page?
If that's not possible, what ilk of manually written Javascript is necessary?
Admissions:
I have very little experience with web development other than Play.
I have very little experience with Javascript.
Resources I've been looking at:
This SO post
Play docs on Javascript routing
Scala.js
Thank you!
For anyone who might come upon this in future, the short answer is Javascript.
Long answer:
To do any AJAX work, you'll need a method like the following in your top-level Controller to set up Javascript routing:
def javascriptRoutes = Action { implicit request =>
Ok(
Routes.javascriptRouter("jsRoutes")(
SomeOtherController.someMethod // Returns a JsValue!
)
).as("text/javascript")
}
Then in the HTML template (*.scala.html) which will contain some AJAXy Javascript:
<script type="text/javascript" src="#routes.ApplicationController.javascriptRoutes"></script>
And finally in your actual JS file (assuming you're using jQuery):
$("someSelector").click(function() {
// Notice that this matches the method name that exists in Scala!
// Make sure to pass `someMethod` what it needs.
var req = jsRoutes.controllers.SomeOtherController.someMethod(...)
$.ajax({
url: req.url,
type: req.type,
success: function(json) {
// DOM manipulation, etc., here.
},
error: function(xhr, status, errorThrown) {
console.log( "Error: " + errorThrown );
console.log( "Status: " + status );
console.dir( xhr );
}
}); // ajax
}); // handler

JS/JQuery/PHP - How to echo errors on form validate failure, and jump to div on success?

I have a fixed-position form that can be scrolled out onto the document and filled out anywhere on the page. If they fail to fill out the form properly, the errors are currently echod out onto the form, which is the intended design for that aspect. What I don't currently know how to do is, if the form is completed and $errors[] is empty, to use jQuery scrollTop() to jump down to the bottom.
Could anyone help me out with this? Current javascript involved is:
$("#A_FORM_submit_button").click(function() {
$("#FORM_A").submit( function () {
$.post(
'ajax/FORM_A_processing.php',
$(this).serialize(),
function(data){
$("#A_errors_").html(data);
}
);
return false;
});
});
The PHP involved is simply
if (!empty($errors)){
// echo errors
} else { // echo success message} <-- would like to jump to div as well
edit-- for clarity: not looking to make the page jump happen in the php file, so much as return a value for the jq $.post function to check and then perform an if/else
I might be jumping the gun here but I believe your design is wrong which is why you are running into this problem.
The ideal way of handling form validation is to validate forms via Javascript and when users enter in their information you immediately show some indicator to ask them to correct it. As long as the validation is incorrect, you should not be accepting a form request or making any AJAX calls.
In the off-chance that they do successfully send the data, you should be doing a validation check via PHP as well which, if failed, would redirect to the original page with the form. From there you could do whatever error handling you want but ideally you would retain the information they entered and indicate why it was wrong (Javascript should catch this but I guess if it gets here the user might have JS off or your validation logic might be wrong)
If I understand correctly, it seems like you are doing your error handling with Javascript (that's fine) but showing the error via PHP. As Hydra IO said don't confuse client-side and server side. Make them handle what they need to handle.
Hope this helps.
#aug described the scenario very clearly.
In code it translates in something like this
$('form').submit(function(){
form_data = $(this).serialize();
if(!validate(form_data))
{
// deal with validation, show error messages
return false;
}
else
{
// Submit form, either via Ajax $.post() or by just returning TRUE
}
});
The validate() function is up to you to work out.

Using PUT/POST/DELETE with JSONP and jQuery

I am working on creating a RESTful API that supports cross-domain requests, JSON/JSONP support, and the main HTTP method (PUT/GET/POST/DELETE). Now while will be easy to accessing this API through server side code , it would nice to exposed it to javascript. From what I can tell, when doing a JSONP requests with jQuery, it only supports the GET method. Is there a way to do a JSONP request using POST/PUT/DELETE?
Ideally I would like a way to do this from within jQuery (through a plugin if the core does not support this), but I will take a plain javascript solution too. Any links to working code or how to code it would be helpful, thanks.
Actually - there is a way to support POST requests.
And there is no need in a PROXI server - just a small utility HTML page that is described bellow.
Here's how you get Effectively a POST cross-domain call, including attached files and multi-part and all :)
Here first are the steps in understanding the idea, after that - find an implementation sample.
How JSONP of jQuery is implemented, and why doesn't it support POST requests?
While the traditional JSONP is implemented by creating a script element and appending it into the DOM - what results inforcing the browser to fire an HTTP request to retrieve the source for the tag, and then execute it as JavaScript, the HTTP request that the browser fires is simple GET.
What is not limited to GET requests?
A FORM. Submit the FORM while specifing action the cross-domain server.
A FORM tag can be created completely using a script, populated with all fields using script, set all necessary attributes, injected into the DOM, and then submitted - all using script.
But how can we submit a FORM without refreshing the page?
We specify the target the form to an IFRAME in the same page.
An IFRAME can also be created, set, named and injected to the DOM using script.
But How can we hide this work from the user?
We'll contain both FORM and IFRAME in a hidden DIV using style="display:none"
(and here's the most complicated part of the technique, be patient)
But IFRAME from another domain cannot call a callback on it's top-level document. How to overcome that?
Indeed , if a response from FORM submit is a page from another domain, any script communication between the top-level page and the page in the IFRAME results in "access denied". So the server cannot callback using a script. What can the server can do? redirect. The server may redirect to any page - including pages in the same domain as the top-level document - pages that can invoke the callback for us.
How can a server redirect?
two ways:
Using client side script like <Script>location.href = 'some-url'</script>
Using HTTP-Header. See: http://www.webconfs.com/how-to-redirect-a-webpage.php
So I end up with another page? How does it help me?
This is a simple utility page that will be used from all cross-domain calls. Actually, this page is in-fact a kind of a proxi, but it is not a server, but a simple and static HTML page, that anybody with notepad and a browser can use.
All this page has to do is invoke the callback on the top-level document, with the response-data from the server. Client-Side scripting has access to all URL parts, and the server can put it's response there encoded as part of it, as well as the name of the callback that has to be invoked. Means - this page can be a static and HTML page, and does not have to be a dynamic server-side page :)
This utility page will take the information from the URL it runs in - specifically in my implementation bellow - the Query-String parameters (or you can write your own implementation using anchor-ID - i.e the part of a url right to the "#" sign). And since this page is static - it can be even allowed to be cached :)
Won't adding for every POST request a DIV, a SCRIPT and an IFRAME eventually leak memory?
If you leave it in the page - it will. If you clean after you - it will not. All we have to do is give an ID to the DIV that we can use to celan-up the DIV and the FORM and IFRAME inside it whenever the response arrives from the server, or times out.
What do we get?
Effectively a POST cross-domain call, including attached files and multi-part and all :)
What are the limits?
The server response is limited to whatever fits into a redirection.
The server must ALWAYS return a REDIRECT to a POST requests. That include 404 and 500 errors.
Alternatively - create a timeout on the client just before firing the request, so you'll have a chance to detect requests that have not returned.
not everybody can understand all this and all the stages involved. it's a kind of an infrastructure level work, but once you get it running - it rocks :)
Can I use it for PUT and DELETE calls?
FORM tag does not PUT and DELETE.
But that's better then nothing :)
Ok, got the concept. How is it done technically?
What I do is:
I create the DIV, style it as invisible, and append it to the DOM. I also give it an ID that I can clean it up from the DOM after the server response has arrived (the same way JQuery cleans it's JSONP SCRIPT tasgs - but the DIV).
Then I compose a string that contains both IFRAME and FORM - with all attributes, properties and input fields, and inject it into the invisible DIV. it is important to inject this string into the DIV only AFTER the div is in the DOM. If not - it will not work on all browsers.
After that - I obtain a reference to the FORM and submit it.
Just remember one line before that - to set a Timeout callback in case the server does not respond, or responds in a wrong way.
The callback function contains the clean-up code. It is also called by timer in case of a response-timeout (and cleans it's timeout-timer when a server response arrives).
Show me the code!
The code snippet bellow is totally "neutral" on "pure" javascript, and declares whatever utility it needs. Just for simplification of explaining the idea - it all runs on the global scope, however it should be a little more sophisticated...
Organize it in functions as you may and parameterize what you need - but make sure that all parts that need to see each other run on the same scope :)
For this example - assume the client runs on http://samedomain.com and the server runs on http://crossdomain.com.
The script code on the top-level document
//declare the Async-call callback function on the global scope
function myAsyncJSONPCallback(data){
//clean up
var e = document.getElementById(id);
if (e) e.parentNode.removeChild(e);
clearTimeout(timeout);
if (data && data.error){
//handle errors & TIMEOUTS
//...
return;
}
//use data
//...
}
var serverUrl = "http://crossdomain.com/server/page"
, params = { param1 : "value of param 1" //I assume this value to be passed
, param2 : "value of param 2" //here I just declare it...
, callback: "myAsyncJSONPCallback"
}
, clientUtilityUrl = "http://samedomain.com/utils/postResponse.html"
, id = "some-unique-id"// unique Request ID. You can generate it your own way
, div = document.createElement("DIV") //this is where the actual work start!
, HTML = [ "<IFRAME name='ifr_",id,"'></IFRAME>"
, "<form target='ifr_",id,"' method='POST' action='",serverUrl
, "' id='frm_",id,"' enctype='multipart/form-data'>"
]
, each, pval, timeout;
//augment utility func to make the array a "StringBuffer" - see usage bellow
HTML.add = function(){
for (var i =0; i < arguments.length; i++)
this[this.length] = arguments[i];
}
//add rurl to the params object - part of infrastructure work
params.rurl = clientUtilityUrl //ABSOLUTE URL to the utility page must be on
//the SAME DOMAIN as page that makes the request
//add all params to composed string of FORM and IFRAME inside the FORM tag
for(each in params){
pval = params[each].toString().replace(/\"/g,""");//assure: that " mark will not break
HTML.add("<input name='",each,"' value='",pval,"'/>"); // the composed string
}
//close FORM tag in composed string and put all parts together
HTML.add("</form>");
HTML = HTML.join(""); //Now the composed HTML string ready :)
//prepare the DIV
div.id = id; // this ID is used to clean-up once the response has come, or timeout is detected
div.style.display = "none"; //assure the DIV will not influence UI
//TRICKY: append the DIV to the DOM and *ONLY THEN* inject the HTML in it
// for some reason it works in all browsers only this way. Injecting the DIV as part
// of a composed string did not always work for me
document.body.appendChild(div);
div.innerHTML = HTML;
//TRICKY: note that myAsyncJSONPCallback must see the 'timeout' variable
timeout = setTimeout("myAsyncJSONPCallback({error:'TIMEOUT'})",4000);
document.getElementById("frm_"+id+).submit();
The server on the cross-domain
The response from the server is expected to be a REDIRECTION, either by HTTP-Header or by writing a SCRIPT tag. (redirection is better, SCRIPT tag is easier to debug with JS breakpoints).
Here's the example of the header, assuming the rurl value from above
Location: http://samedomain.com/HTML/page?callback=myAsyncJSONPCallback&data=whatever_the_server_has_to_return
Note that
the value of the data argument can be a JavaScript Object-Literal or JSON expression, however it better be url-encoded.
the length of the server response is limited to the length of a URL a browser can process.
Also - in my system the server has a default value for the rurl so that this parameter is optional. But you can do that only if your client-application and server-application are coupled.
APIs to emit redirection header:
http://www.webconfs.com/how-to-redirect-a-webpage.php
Alternatively, you can have the server write as a response the following:
<script>
location.href="http://samedomain.com/HTML/page?callback=myAsyncJSONPCallback&data=whatever_the_server_has_to_return"
</script>
But HTTP-Headers would be considered more clean ;)
The utility page on the same domain as the top-level document
I use the same utility page as rurl for all my post requests: all it does is take the name of the callback and the parameters from the Query-String using client side code, and call it on the parent document. It can do it ONLY when this page runs in the EXACT same domain as the page that fired the request! Important: Unlike cookies - subdomains do not count!! It has to he the exact same domain.
It's also make it more efficient if this utility page contains no references to other resources -including JS libraries. So this page is plain JavaScript. But you can implement it however you like.
Here's the responder page that I use, who's URL is found in the rurl of the POST request (in the example: http://samedomain.com/utils/postResponse.html )
<html><head>
<script type="text/javascript">
//parse and organize all QS parameters in a more comfortable way
var params = {};
if (location.search.length > 1) {
var i, arr = location.search.substr(1).split("&");
for (i = 0; i < arr.length; i++) {
arr[i] = arr[i].split("=");
params[arr[i][0]] = unescape(arr[i][1]);
}
}
//support server answer as JavaScript Object-Literals or JSON:
// evaluate the data expression
try {
eval("params.data = " + params.data);
} catch (e) {
params.data = {error: "server response failed with evaluation error: " + e.message
,data : params.data
}
}
//invoke the callback on the parent
try{
window.parent[ params.callback ](params.data || "no-data-returned");
}catch(e){
//if something went wrong - at least let's learn about it in the
// console (in addition to the timeout)
throw "Problem in passing POST response to host page: \n\n" + e.message;
}
</script>
</head><body></body></html>
It's not much automation and 'ready-made' library like jQuery and involes some 'manual' work - but it has the charm :)
If you're a keen fan of ready-made libraries - you can also check on Dojo Toolkit that when last I checked (about a year ago) - had their own implementation for the same mechanism.
http://dojotoolkit.org/
Good luck buddy, I hope it helps...
Is there a way to do a JSONP request using POST/PUT/DELETE?
No there isn't.
No. Consider what JSONP is: an injection of a new <script> tag in the document. The browser performs a GET request to pull the script pointed to by the src attribute. There's no way to specify any other HTTP verb when doing this.
Rather than banging our heads with JSONP method, that actually won't
support POST method by default, we can go for CORS .That will provide no big changes in the conventional way of programming. By simple Jquery Ajax call we can go with cross domains.
In CORS method, you have to add headers in server side scripting file, or in the server itself(in remote domain), for enabling this access. This is much reliable, since we can prevent/restrict the domains making unwanted calls.
It can be found in detail in wikipedia page.

Categories