4 * Rewrites XMLHttpRequest to automatically send CSRF token with it. In theory
5 * plays nice with other JavaScript libraries, needs testing though.
7 // Here are the basic overloaded method definitions
8 // The wrapper must be set BEFORE onreadystatechange is written to, since
9 // a bug in ActiveXObject prevents us from properly testing for it.
10 var CsrfMagic = function (real) {
15 real.onreadystatechange = function() {
16 csrfMagic._updateProps();
17 return csrfMagic.onreadystatechange ? csrfMagic.onreadystatechange() : null;
19 csrfMagic._updateProps();
22 CsrfMagic.prototype.open = function(method, url, async, username, password) {
23 if (method == 'POST') this.csrf_isPost = true;
24 // deal with Opera bug, thanks jQuery
25 if (username) return this.csrf_open(method, url, async, username, password);
26 else return this.csrf_open(method, url, async);
28 CsrfMagic.prototype.csrf_open = function(method, url, async, username, password) {
29 if (username) return this.csrf.open(method, url, async, username, password);
30 else return this.csrf.open(method, url, async);
33 CsrfMagic.prototype.send = function(data) {
34 if (!this.csrf_isPost) this.csrf_send(data);
35 prepend = csrfMagicName + '=' + csrfMagicToken + '&';
36 if (this.csrf_purportedLength === undefined) {
37 this.csrf_setRequestHeader("Content-length", this.csrf_purportedLength + prepend.length);
38 delete this.csrf_purportedLength;
40 delete this.csrf_isPost;
41 return this.csrf_send(prepend + data);
43 CsrfMagic.prototype.csrf_send = function(data) {
44 return this.csrf.send(data);
47 CsrfMagic.prototype.setRequestHeader = function(header, value) {
48 // We have to auto-set this at the end, since we don't know how long the
49 // nonce is when added to the data.
50 if (this.csrf_isPost && header == "Content-length") {
51 this.csrf_purportedLength = value;
54 return this.csrf_setRequestHeader(header, value);
56 CsrfMagic.prototype.csrf_setRequestHeader = function(header, value) {
57 return this.csrf.setRequestHeader(header, value);
60 CsrfMagic.prototype.abort = function () {
61 return this.csrf.abort();
63 CsrfMagic.prototype.getAllResponseHeaders = function() {
64 return this.csrf.getAllResponseHeaders();
66 CsrfMagic.prototype.getResponseHeader = function(header) {
67 return this.csrf.getResponseHeader(header);
71 CsrfMagic.prototype._updateProps = function() {
72 this.readyState = this.csrf.readyState;
73 if (this.readyState == 4) {
74 this.responseText = this.csrf.responseText;
75 this.responseXML = this.csrf.responseXML;
76 this.status = this.csrf.status;
77 this.statusText = this.csrf.statusText;
80 CsrfMagic.process = function(base) {
81 var prepend = csrfMagicName + '=' + csrfMagicToken;
82 if (base) return prepend + '&' + base;
86 // Sets things up for Mozilla/Opera/nice browsers
87 if (window.XMLHttpRequest && window.XMLHttpRequest.prototype) {
88 XMLHttpRequest.prototype.csrf_open = XMLHttpRequest.prototype.open;
89 XMLHttpRequest.prototype.csrf_send = XMLHttpRequest.prototype.send;
90 XMLHttpRequest.prototype.csrf_setRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
92 XMLHttpRequest.prototype.open = CsrfMagic.prototype.open;
93 XMLHttpRequest.prototype.send = CsrfMagic.prototype.send;
94 XMLHttpRequest.prototype.setRequestHeader = CsrfMagic.prototype.setRequestHeader;
96 // The only way we can do this is by modifying a library you have been
97 // using. We plan to support YUI, script.aculo.us, prototype, MooTools,
98 // jQuery, Ext and Dojo.
100 // jQuery didn't implement a new XMLHttpRequest function, so we have
101 // to do this the hard way.
102 jQuery.csrf_ajax = jQuery.ajax;
103 jQuery.ajax = function( s ) {
104 if (s.type && s.type.toUpperCase() == 'POST') {
105 s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
106 if ( s.data && s.processData && typeof s.data != "string" ) {
107 s.data = jQuery.param(s.data);
109 s.data = CsrfMagic.process(s.data);
111 return jQuery.csrf_ajax( s );
113 } else if (window.Prototype) {
114 // This works for script.aculo.us too
115 Ajax.csrf_getTransport = Ajax.getTransport;
116 Ajax.getTransport = function() {
117 return new CsrfMagic(Ajax.csrf_getTransport());
119 } else if (window.MooTools) {
120 Browser.csrf_Request = Browser.Request;
121 Browser.Request = function () {
122 return new CsrfMagic(Browser.csrf_Request());
124 } else if (window.YAHOO) {
125 YAHOO.util.Connect.csrf_createXhrObject = YAHOO.util.Connect.createXhrObject;
126 YAHOO.util.Connect.createXhrObject = function (transaction) {
127 obj = YAHOO.util.Connect.csrf_createXhrObject(transaction);
129 obj.conn = new CsrfMagic(old);