forked from ezyang/csrf-magic
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
dd2fdae
commit 6034adf
Showing
2 changed files
with
212 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,215 @@ | ||
'use strict'; | ||
/** | ||
* @file | ||
* | ||
* Rewrites XMLHttpRequest to automatically send CSRF token with it. In theory | ||
* plays nice with other JavaScript libraries, needs testing though. | ||
*/ | ||
|
||
function _typeof(o){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},_typeof(o)}// Sets things up for Mozilla/Opera/nice browsers | ||
// Here are the basic overloaded method definitions | ||
// The wrapper must be set BEFORE onreadystatechange is written to, since | ||
// a bug in ActiveXObject prevents us from properly testing for it. | ||
CsrfMagic = function (real) { | ||
// try to make it ourselves, if you didn't pass it | ||
if (!real) | ||
try { | ||
real = new XMLHttpRequest(); | ||
} catch (e) {} | ||
if (!real) | ||
try { | ||
real = new ActiveXObject('Msxml2.XMLHTTP'); | ||
} catch (e) {} | ||
if (!real) | ||
try { | ||
real = new ActiveXObject('Microsoft.XMLHTTP'); | ||
} catch (e) {} | ||
if (!real) | ||
try { | ||
real = new ActiveXObject('Msxml2.XMLHTTP.4.0'); | ||
} catch (e) {} | ||
this.csrf = real; | ||
// properties | ||
var csrfMagic = this; | ||
real.onreadystatechange = function () { | ||
csrfMagic._updateProps(); | ||
return csrfMagic.onreadystatechange ? csrfMagic.onreadystatechange() : null; | ||
}; | ||
csrfMagic._updateProps(); | ||
}; | ||
|
||
CsrfMagic.prototype = { | ||
open: function (method, url, async, username, password) { | ||
if (method == 'POST') this.csrf_isPost = true; | ||
this.csrf_url = url; | ||
// deal with Opera bug, thanks jQuery | ||
if (username) return this.csrf_open(method, url, async, username, password); | ||
else return this.csrf_open(method, url, async); | ||
}, | ||
csrf_open: function (method, url, async, username, password) { | ||
if (username) return this.csrf.open(method, url, async, username, password); | ||
else return this.csrf.open(method, url, async); | ||
}, | ||
|
||
send: function (data) { | ||
let url = null; | ||
try { | ||
url = new URL(this.csrf_url); | ||
} catch (e) { | ||
//for internal urls there could be no domain part | ||
//in that case it's not a valid url | ||
} | ||
//don't add token to external requests | ||
if (url !== null && typeof csrfMagicDomain !== 'undefined' && url.host !== csrfMagicDomain) { | ||
return this.csrf_send(data); | ||
} | ||
|
||
if (!this.csrf_isPost) return this.csrf_send(data); | ||
delete this.csrf_isPost; | ||
if (data instanceof FormData) { | ||
data.append(csrfMagicName, csrfMagicToken); | ||
return this.csrf_send(data); | ||
} else { | ||
return this.csrf_send(csrfMagicName + '=' + csrfMagicToken + '&' + data); | ||
} | ||
}, | ||
csrf_send: function (data) { | ||
return this.csrf.send(data); | ||
}, | ||
|
||
setRequestHeader: function (header, value) { | ||
// We have to auto-set this at the end, since we don't know how long the | ||
// nonce is when added to the data. | ||
if (this.csrf_isPost && header == 'Content-length') { | ||
this.csrf_purportedLength = value; | ||
return; | ||
} | ||
return this.csrf_setRequestHeader(header, value); | ||
}, | ||
csrf_setRequestHeader: function (header, value) { | ||
return this.csrf.setRequestHeader(header, value); | ||
}, | ||
|
||
abort: function () { | ||
return this.csrf.abort(); | ||
}, | ||
getAllResponseHeaders: function () { | ||
return this.csrf.getAllResponseHeaders(); | ||
}, | ||
getResponseHeader: function (header) { | ||
return this.csrf.getResponseHeader(header); | ||
} // , | ||
}; | ||
|
||
// proprietary | ||
CsrfMagic.prototype._updateProps = function () { | ||
this.readyState = this.csrf.readyState; | ||
if (this.readyState == 4) { | ||
this.responseText = this.csrf.responseText; | ||
this.responseXML = this.csrf.responseXML; | ||
this.status = this.csrf.status; | ||
this.statusText = this.csrf.statusText; | ||
} | ||
}; | ||
CsrfMagic.process = function (base) { | ||
if (typeof base == 'object') { | ||
base[csrfMagicName] = csrfMagicToken; | ||
return base; | ||
} | ||
var prepend = csrfMagicName + '=' + csrfMagicToken; | ||
if (base) return prepend + '&' + base; | ||
return prepend; | ||
}; | ||
// callback function for when everything on the page has loaded | ||
CsrfMagic.end = function () { | ||
// This rewrites forms AGAIN, so in case buffering didn't work this | ||
// certainly will. | ||
forms = document.getElementsByTagName('form'); | ||
for (var i = 0; i < forms.length; i++) { | ||
form = forms[i]; | ||
var method = form.getAttribute('method'); | ||
if (method && method.toUpperCase() !== 'POST') continue; | ||
if (form.elements[csrfMagicName]) continue; | ||
var input = document.createElement('input'); | ||
input.setAttribute('name', csrfMagicName); | ||
input.setAttribute('value', csrfMagicToken); | ||
input.setAttribute('type', 'hidden'); | ||
form.appendChild(input); | ||
} | ||
}; | ||
|
||
// Sets things up for Mozilla/Opera/nice browsers | ||
// We very specifically match against Internet Explorer, since they haven't | ||
// implemented prototypes correctly yet. | ||
if(CsrfMagic=function CsrfMagic(real){// try to make it ourselves, if you didn't pass it | ||
if(!real)try{real=new XMLHttpRequest;}catch(e){}if(!real)try{real=new ActiveXObject("Msxml2.XMLHTTP");}catch(e){}if(!real)try{real=new ActiveXObject("Microsoft.XMLHTTP");}catch(e){}if(!real)try{real=new ActiveXObject("Msxml2.XMLHTTP.4.0");}catch(e){}this.csrf=real;// properties | ||
var csrfMagic=this;real.onreadystatechange=function(){return csrfMagic._updateProps(),csrfMagic.onreadystatechange?csrfMagic.onreadystatechange():null},csrfMagic._updateProps();},CsrfMagic.prototype={open:function open(method,url,async,username,password){// deal with Opera bug, thanks jQuery | ||
return "POST"==method&&(this.csrf_isPost=!0),this.csrf_url=url,username?this.csrf_open(method,url,async,username,password):this.csrf_open(method,url,async)},csrf_open:function csrf_open(method,url,async,username,password){return username?this.csrf.open(method,url,async,username,password):this.csrf.open(method,url,async)},send:function send(data){var url=null;try{url=new URL(this.csrf_url);}catch(e){//for internal urls there could be no domain part | ||
//in that case it's not a valid url | ||
}//don't add token to external requests | ||
return null!==url&&"undefined"!=typeof csrfMagicDomain&&url.host!==csrfMagicDomain?this.csrf_send(data):this.csrf_isPost?(delete this.csrf_isPost,data instanceof FormData?(data.append(csrfMagicName,csrfMagicToken),this.csrf_send(data)):this.csrf_send(csrfMagicName+"="+csrfMagicToken+"&"+data)):this.csrf_send(data)},csrf_send:function csrf_send(data){return this.csrf.send(data)},setRequestHeader:function setRequestHeader(header,value){// We have to auto-set this at the end, since we don't know how long the | ||
// nonce is when added to the data. | ||
return this.csrf_isPost&&"Content-length"==header?void(this.csrf_purportedLength=value):this.csrf_setRequestHeader(header,value)},csrf_setRequestHeader:function csrf_setRequestHeader(header,value){return this.csrf.setRequestHeader(header,value)},abort:function abort(){return this.csrf.abort()},getAllResponseHeaders:function getAllResponseHeaders(){return this.csrf.getAllResponseHeaders()},getResponseHeader:function getResponseHeader(header){return this.csrf.getResponseHeader(header)}// , | ||
},CsrfMagic.prototype._updateProps=function(){this.readyState=this.csrf.readyState,4==this.readyState&&(this.responseText=this.csrf.responseText,this.responseXML=this.csrf.responseXML,this.status=this.csrf.status,this.statusText=this.csrf.statusText);},CsrfMagic.process=function(base){if("object"==_typeof(base))return base[csrfMagicName]=csrfMagicToken,base;var prepend=csrfMagicName+"="+csrfMagicToken;return base?prepend+"&"+base:prepend},CsrfMagic.end=function(){forms=document.getElementsByTagName("form");for(var i=0;i<forms.length;i++){form=forms[i];var method=form.getAttribute("method");if(!(method&&"POST"!==method.toUpperCase())&&!form.elements[csrfMagicName]){var input=document.createElement("input");input.setAttribute("name",csrfMagicName),input.setAttribute("value",csrfMagicToken),input.setAttribute("type","hidden"),form.appendChild(input);}}},window.XMLHttpRequest&&window.XMLHttpRequest.prototype&&!0){var x=XMLHttpRequest.prototype,c=CsrfMagic.prototype;// Save the original functions | ||
// Notice that CsrfMagic is itself an instantiatable object, but only | ||
// open, send and setRequestHeader are necessary as decorators. | ||
x.csrf_open=x.open,x.csrf_send=x.send,x.csrf_setRequestHeader=x.setRequestHeader,x.open=c.open,x.send=c.send,x.setRequestHeader=c.setRequestHeader;}else window.jQuery&&(jQuery.csrf_ajax=jQuery.ajax,jQuery.ajax=function(s){return s.type&&"POST"==s.type.toUpperCase()&&(s=jQuery.extend(!0,s,jQuery.extend(!0,{},jQuery.ajaxSettings,s)),s.data&&s.processData&&"string"!=typeof s.data&&(s.data=jQuery.param(s.data)),s.data=CsrfMagic.process(s.data)),jQuery.csrf_ajax(s)}),window.Prototype&&(Ajax.csrf_getTransport=Ajax.getTransport,Ajax.getTransport=function(){return new CsrfMagic(Ajax.csrf_getTransport())}),window.MooTools&&(Browser.csrf_Request=Browser.Request,Browser.Request=function(){return new CsrfMagic(Browser.csrf_Request())}),window.YAHOO&&(YAHOO.util.Connect.csrf_createXhrObject=YAHOO.util.Connect.createXhrObject,YAHOO.util.Connect.createXhrObject=function(transaction){return obj=YAHOO.util.Connect.csrf_createXhrObject(transaction),obj.conn=new CsrfMagic(obj.conn),obj}),window.Ext&&(Ext.lib.Ajax.csrf_createXhrObject=Ext.lib.Ajax.createXhrObject,Ext.lib.Ajax.createXhrObject=function(transaction){return obj=Ext.lib.Ajax.csrf_createXhrObject(transaction),obj.conn=new CsrfMagic(obj.conn),obj}),window.dojo&&(dojo.csrf__xhrObj=dojo._xhrObj,dojo._xhrObj=function(){return new CsrfMagic(dojo.csrf__xhrObj())}); | ||
//# sourceMappingURL=Csrf.min.js.map | ||
if (window.XMLHttpRequest && window.XMLHttpRequest.prototype && '\v' != 'v') { | ||
var x = XMLHttpRequest.prototype; | ||
var c = CsrfMagic.prototype; | ||
|
||
// Save the original functions | ||
x.csrf_open = x.open; | ||
x.csrf_send = x.send; | ||
x.csrf_setRequestHeader = x.setRequestHeader; | ||
|
||
// Notice that CsrfMagic is itself an instantiatable object, but only | ||
// open, send and setRequestHeader are necessary as decorators. | ||
x.open = c.open; | ||
x.send = c.send; | ||
x.setRequestHeader = c.setRequestHeader; | ||
} else { | ||
// The only way we can do this is by modifying a library you have been | ||
// using. We support YUI, script.aculo.us, prototype, MooTools, | ||
// jQuery, Ext and Dojo. | ||
if (window.jQuery) { | ||
// jQuery didn't implement a new XMLHttpRequest function, so we have | ||
// to do this the hard way. | ||
jQuery.csrf_ajax = jQuery.ajax; | ||
jQuery.ajax = function (s) { | ||
if (s.type && s.type.toUpperCase() == 'POST') { | ||
s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s)); | ||
if (s.data && s.processData && typeof s.data != 'string') { | ||
s.data = jQuery.param(s.data); | ||
} | ||
s.data = CsrfMagic.process(s.data); | ||
} | ||
return jQuery.csrf_ajax(s); | ||
}; | ||
} | ||
if (window.Prototype) { | ||
// This works for script.aculo.us too | ||
Ajax.csrf_getTransport = Ajax.getTransport; | ||
Ajax.getTransport = function () { | ||
return new CsrfMagic(Ajax.csrf_getTransport()); | ||
}; | ||
} | ||
if (window.MooTools) { | ||
Browser.csrf_Request = Browser.Request; | ||
Browser.Request = function () { | ||
return new CsrfMagic(Browser.csrf_Request()); | ||
}; | ||
} | ||
if (window.YAHOO) { | ||
// old YUI API | ||
YAHOO.util.Connect.csrf_createXhrObject = YAHOO.util.Connect.createXhrObject; | ||
YAHOO.util.Connect.createXhrObject = function (transaction) { | ||
obj = YAHOO.util.Connect.csrf_createXhrObject(transaction); | ||
obj.conn = new CsrfMagic(obj.conn); | ||
return obj; | ||
}; | ||
} | ||
if (window.Ext) { | ||
// Ext can use other js libraries as loaders, so it has to come last | ||
// Ext's implementation is pretty identical to Yahoo's, but we duplicate | ||
// it for comprehensiveness's sake. | ||
Ext.lib.Ajax.csrf_createXhrObject = Ext.lib.Ajax.createXhrObject; | ||
Ext.lib.Ajax.createXhrObject = function (transaction) { | ||
obj = Ext.lib.Ajax.csrf_createXhrObject(transaction); | ||
obj.conn = new CsrfMagic(obj.conn); | ||
return obj; | ||
}; | ||
} | ||
if (window.dojo) { | ||
// NOTE: this doesn't work with latest dojo | ||
dojo.csrf__xhrObj = dojo._xhrObj; | ||
dojo._xhrObj = function () { | ||
return new CsrfMagic(dojo.csrf__xhrObj()); | ||
}; | ||
} | ||
} |
Oops, something went wrong.