AJAX In Action [127]
Listing 7.1 Security-aware ContentLoader object
net.ContentLoader=function(
url,onload,onerror,method,params,contentType, headers,secure
){
this.req=null;
this.onload=onload;
this.onerror=(onerror) ? onerror : this.defaultError;
this.secure=secure;
this.loadXMLDoc(url,method,params,contentType, headers);
}
Licensed to jonathan zheng 256 CHAPTER 7 Security and Ajax net.ContentLoader.prototype={ loadXMLDoc:function(url,method,params,contentType,headers){ if (!method){ method="GET"; } if (!contentType && method=="POST"){ contentType='application/x-www-form-urlencoded'; } if (window.XMLHttpRequest){ this.req=new XMLHttpRequest(); } else if (window.ActiveXObject){ this.req=new ActiveXObject("Microsoft.XMLHTTP"); } if (this.req){ try{ try{ if (this.secure && netscape && netscape.security.PrivilegeManager.enablePrivilege) { netscape.security.PrivilegeManager b Ask for privilege .enablePrivilege('UniversalBrowserRead'); to make request } }catch (err){} this.req.open(method,url,true); if (contentType){ this.req.setRequestHeader('Content-Type', contentType); } if (headers){ c Add custom HTTP headers for (var h in headers){ this.req.setRequestHeader(h,headers[h]); } } var loader=this; this.req.onreadystatechange=function(){ loader.onReadyState.call(loader); } this.req.send(params); }catch (err){ this.onerror.call(this); } } }, onReadyState:function(){ var req=this.req; var ready=req.readyState; if (ready==net.READY_STATE_COMPLETE){ var httpStatus=req.status; if (httpStatus==200 || httpStatus==0){ try{ if (this.secure && netscape && netscape.security.PrivilegeManager.enablePrivilege) { Licensed to jonathan zheng Communicating with remote services 257 netscape.security.PrivilegeManager Ask for privilege to .enablePrivilege('UniversalBrowserRead'); parse response } }catch (err){} this.onload.call(this); }else{ this.onerror.call(this); } } }, defaultError:function(){ alert("error fetching data!" +"\n\nreadyState:"+this.req.readyState +"\nstatus: "+this.req.status +"\nheaders: "+this.req.getAllResponseHeaders()); } } We have added two new arguments to our constructor. The first is an array of additional HTTP headers c, because we will need to pass these in during the construction of the SOAP request. The second is a boolean flag indicating whether the loader should request privileges at key points. When we request privileges from the netscape.PrivilegeManager object, we are granted them only for the scope of the current function. Therefore, we request them at two points: when the request to the remote server is made b, and when we try to read the response that is returned c. We call the custom onload handler function within the scope of the onReadyState function, so the privilege will persist through any custom logic that we pass in there. Internet Explorer doesn’t understand the PrivilegeManager, and will throw an exception when it is referred to. For this reason, we simply wrap the references to it in try...catch blocks, allowing the exception to be caught and swallowed silently. When the previous code runs in Internet Explorer, it will fail silently within the try...catch block, pick itself up again, and keep going with no ill results. Under Mozilla, the PrivilegeManager will be communicated with and no exception will be thrown. Let’s make use of our modified ContentLoader,