Initial commit, implements basic form rewriting, tokens and JavaScript.
[csrf-magic.git] / csrf-magic.js
blob883aeaf65700b05a6dfcc860d71c9986125eb348
1 /**
2  * @file
3  *
4  * Rewrites XMLHttpRequest to automatically send CSRF token with it. In theory
5  * plays nice with other JavaScript libraries, needs testing though.
6  */
8 // Here are the basic overloaded method definitions
9 CsrfMagic = new Object;
10 CsrfMagic.open = function(method, url, async, username, password) {
11     if (method == 'POST') this.csrf_isPost = true;
12     // deal with Opera bug, thanks jQuery
13     if (username) return this.csrf_open(method, url, async, username, password);
14     else return this.csrf_open(method, url, async);
16 CsrfMagic.send = function(data) {
17     if (!this.csrf_isPost) this.csrf_send(data);
18     prepend = csrfMagicName + '=' + csrfMagicToken + '&';
19     if (this.csrf_purportedLength === undefined) {
20         this.csrf_setRequestHeader("Content-length", this.csrf_purportedLength + prepend.length);
21         delete this.csrf_purportedLength;
22     }
23     delete this.csrf_isPost;
24     return this.csrf_send(prepend + data);
26 CsrfMagic.setRequestHeader = function(header, value) {
27     // We have to auto-set this at the end, since we don't know how long the
28     // nonce is when added to the data.
29     if (this.csrf_isPost && header == "Content-length") {
30         this.csrf_purportedLength = value;
31         return;
32     }
33     return this.csrf_setRequestHeader(header, value);
36 // Sets things up for Mozilla/Opera/nice browsers
37 if (window.XMLHttpRequest && window.XMLHttpRequest.prototype) {
38     XMLHttpRequest.prototype.csrf_open = XMLHttpRequest.prototype.open;
39     XMLHttpRequest.prototype.csrf_send = XMLHttpRequest.prototype.send;
40     XMLHttpRequest.prototype.csrf_setRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
41     
42     XMLHttpRequest.prototype.open = CsrfMagic.open;
43     XMLHttpRequest.prototype.send = CsrfMagic.send;
44     XMLHttpRequest.prototype.setRequestHeader = CsrfMagic.setRequestHeader
45 } else {
46     // The only way we can do this is by modifying a library you have been
47     // using. We plan to support YUI, script.aculo.us, prototype, MooTools, 
48     // jQuery, Ext and Dojo.
49     if (window.jQuery) {
50         jQuery.csrf_ajax = jQuery.ajax;
51         jQuery.ajax = function( s ) {
52             if (s.type && s.type.toUpperCase() == 'POST') {
53                 if ( s.data && s.processData && typeof s.data != "string" ) {
54                     s.data = jQuery.param(s.data);
55                 }
56                 var append = csrfMagicName + '=' + csrfMagicToken;
57                 if (!s.data) s.data = append;
58                 else s.data = append + '&' + s.data;
59             }
60             return jQuery.csrf_ajax( s );
61         }
62     }