cacert-testmgr/external/ZendFramework-1.9.5/externals/dojo/dojox/io/windowName.js

219 lines
7.9 KiB
JavaScript
Raw Normal View History

dojo.provide("dojox.io.windowName");
// Implements the window.name transport
dojox.io.windowName = {
send: function(/*String*/ method, /*dojo.__IoArgs*/ args){
// summary:
// Provides secure cross-domain request capability.
// Sends a request using an iframe (POST or GET) and reads the response through the
// frame's window.name.
//
// method:
// The method to use to send the request, GET or POST
//
// args:
// See dojo.xhr
//
// args.authElement: DOMNode?
// By providing an authElement, this indicates that windowName should use the
// authorized window.name protocol, relying on
// the loaded XD resource to return to the provided return URL on completion
// of authorization/authentication. The provided authElement will be used to place
// the iframe in, so the user can interact with the server resource for authentication
// and/or authorization to access the resource.
//
// args.onAuthLoad: Function?
// When using authorized access to resources, this function will be called when the
// authorization page has been loaded. (When authorization is actually completed,
// the deferred callback function is called with the result). The primary use for this
// is to make the authElement visible to the user once the resource has loaded
// (this can be preferable to showing the iframe while the resource is loading
// since it may not require authorization, it may simply return the resource).
//
// description:
// In order to provide a windowname transport accessible resources/web services, a server
// should check for the presence of a parameter window.name=true and if a request includes
// such a parameter, it should respond to the request with an HTML
// document that sets it's window.name to the string that is to be
// delivered to the client. For example, if a client makes a window.name request like:
// | http://othersite.com/greeting?windowname=true
// And server wants to respond to the client with "Hello", it should return an html page:
// | <html><script type="text/javascript">
// | window.name="Hello";
// | </script></html>
// One can provide XML or JSON data by simply quoting the data as a string, and parsing the data
// on the client.
// If you use the authorization window.name protocol, the requester should include an
// authElement element in the args, and a request will be created like:
// | http://othersite.com/greeting?windowname=auth
// And the server can respond like this:
// | <html><script type="text/javascript">
// | var loc = window.name;
// | authorizationButton.onclick = function(){
// | window.name="Hello";
// | location = loc;
// | };
// | </script></html>
args.url += (args.url.match(/\?/) ? '&' : '?') + "windowname=" + (args.authElement ? "auth" : true); // indicate our desire for window.name communication
var authElement = args.authElement;
var cleanup = function(result){
try{
// we have to do this to stop the wait cursor in FF
var innerDoc = dfd.ioArgs.frame.contentWindow.document;
innerDoc.write(" ");
innerDoc.close();
}catch(e){}
(authElement || dojo.body()).removeChild(dfd.ioArgs.outerFrame); // clean up
return result;
}
var dfd = dojo._ioSetArgs(args,cleanup,cleanup,cleanup);
if(args.timeout){
setTimeout(function(){
if(dfd.fired == -1){
dfd.callback(new Error("Timeout"));
}
},
args.timeout
);
}
var self = dojox.io.windowName;
if(dojo.body()){
// the DOM is ready
self._send(dfd, method, authElement, args.onAuthLoad);
}else{
// we will wait for the DOM to be ready to proceed
dojo.addOnLoad(function(){
self._send(dfd, method, authElement, args.onAuthLoad);
});
}
return dfd;
},
_send: function(dfd, method, authTarget, onAuthLoad){
var ioArgs = dfd.ioArgs;
var frameNum = dojox.io.windowName._frameNum++;
var sameDomainUrl = (dojo.config["dojoCallbackUrl"]||dojo.moduleUrl("dojo", "resources/blank.html")) + "#" + frameNum;
var frameName = new dojo._Url(window.location, sameDomainUrl);
var doc = dojo.doc;
var frameContainer = authTarget || dojo.body();
function styleFrame(frame){
frame.style.width="100%";
frame.style.height="100%";
frame.style.border="0px";
}
if(dojo.isMoz && ![].reduce){
// FF2 allows unsafe sibling frame modification,
// the fix for this is to create nested frames with getters and setters to protect access
var outerFrame = doc.createElement("iframe");
styleFrame(outerFrame);
if(!authTarget){
outerFrame.style.display='none';
}
frameContainer.appendChild(outerFrame);
var firstWindow = outerFrame.contentWindow;
doc = firstWindow.document;
doc.write("<html><body margin='0px'><iframe style='width:100%;height:100%;border:0px' name='protectedFrame'></iframe></body></html>");
doc.close();
var secondWindow = firstWindow[0];
firstWindow.__defineGetter__(0,function(){});
firstWindow.__defineGetter__("protectedFrame",function(){});
doc = secondWindow.document;
doc.write("<html><body margin='0px'></body></html>");
doc.close();
frameContainer = doc.body;
}
var frame = ioArgs.frame = frame = doc.createElement(dojo.isIE ? '<iframe name="' + frameName + '" onload="dojox.io.windowName['+frameNum+']()">' : 'iframe');
styleFrame(frame);
ioArgs.outerFrame = outerFrame = outerFrame || frame;
if(!authTarget){
outerFrame.style.display='none';
}
var state = 0;
function getData(){
var data = frame.contentWindow.name;
if(typeof data == 'string'){
if(data != frameName){
state = 2; // we are done now
dfd.ioArgs.hash = frame.contentWindow.location.hash;
dfd.callback(data);
}
}
}
dojox.io.windowName[frameNum] = frame.onload = function(){
try{
if(!dojo.isMoz && frame.contentWindow.location =='about:blank'){
// opera and safari will do an onload for about:blank first, we can ignore this first onload
return;
}
}catch(e){
// if we are in the target domain, frame.contentWindow.location will throw an ignorable error
}
if(!state){
// we have loaded the target resource, now time to navigate back to our domain so we can read the frame name
state=1;
if(authTarget){
// call the callback so it can make it visible
if(onAuthLoad){
onAuthLoad();
}
}else{
// we are doing a synchronous capture, go directly to our same domain URL and retrieve the resource
frame.contentWindow.location = sameDomainUrl;
}
}
// back to our domain, we should be able to access the frame name now
try{
if(state<2){
getData();
}
}
catch(e){
}
};
frame.name = frameName;
if(method.match(/GET/i)){
// if it is a GET we can just the iframe our src url
dojo._ioAddQueryToUrl(ioArgs);
frame.src = ioArgs.url;
frameContainer.appendChild(frame);
if(frame.contentWindow){
frame.contentWindow.location.replace(ioArgs.url);
}
}else if(method.match(/POST/i)){
// if it is a POST we will build a form to post it
frameContainer.appendChild(frame);
var form = dojo.doc.createElement("form");
dojo.body().appendChild(form);
var query = dojo.queryToObject(ioArgs.query);
for(var i in query){
var values = query[i];
values = values instanceof Array ? values : [values];
for(var j = 0; j < values.length; j++){
// create hidden inputs for all the parameters
var input = doc.createElement("input");
input.type = 'hidden';
input.name = i;
input.value = values[j];
form.appendChild(input);
}
}
form.method = 'POST';
form.action = ioArgs.url;
form.target = frameName;// connect the form to the iframe
form.submit();
form.parentNode.removeChild(form);
}else{
throw new Error("Method " + method + " not supported with the windowName transport");
}
if(frame.contentWindow){
frame.contentWindow.name = frameName; // IE likes it afterwards
}
},
_frameNum: 0
}