Index: httpParse.js
===================================================================
--- httpParse.js	(revision 0)
+++ httpParse.js	(revision 0)
@@ -0,0 +1,49 @@
+dojo.provide("dojox.io.httpParse");
+dojox.io.httpParse = function(/*String*/httpStream, /*String?*/topHeaders){
+	// summary:
+	//		Parses an HTTP stream for a message.
+	// httpStream:
+	// 		HTTP stream to parse 
+	// topHeaders:
+	//		Extra header information to add to each HTTP request (kind of HTTP inheritance)
+	// return:
+	// 		Returns an XHR-like object for reading the headers and body or an array of XHR objects
+	var headers = {};
+	var httpParts = httpStream.match(/(\n*[^\n]+)/);
+	if(!httpParts){ 
+		return;
+	}
+	httpStream = httpStream.substring(httpParts[0].length+1);
+	httpParts = httpParts[1];
+	var headerParts = httpStream.match(/([^\n]+\n)*/)[0];
+	httpStream = httpStream.substring(headerParts.length+1);
+	headerParts = (topHeaders || "") + headerParts;
+	var headerStr = headerParts;
+	headerParts = headerParts.match(/[^:\n]+:[^\n]+\n/g); // parse the containing and contained response headers with the contained taking precedence (by going last)
+	for(var j = 0; j < headerParts.length; j++){
+		var colonIndex = headerParts[j].indexOf(':');
+		headers[headerParts[j].substring(0,colonIndex)] = headerParts[j].substring(colonIndex+1).replace(/(^[ \r\n]*)|([ \r\n]*)$/g,''); // trim
+	}										
+
+	httpParts = httpParts.split(' ');
+	var xhr = { // make it look like an xhr object, at least for the response part of the API
+		status : parseInt(httpParts[1],10),
+		statusText : httpParts[2],
+		readyState : 3, // leave it at 3 until we get a full body
+		getAllResponseHeaders : function(){ return headerStr;},
+		getResponseHeader : function(name){ return headers[name];}}; 
+	
+	var contentLength = headers['Content-Length']; 
+	if(contentLength){
+		if(contentLength <= httpStream.length){
+			xhr.responseText = httpStream.substring(0,contentLength);
+			xhr.readyState = 4;
+			httpStream = httpStream.substring(contentLength);
+			this.lastIndex = xhr.responseText.length - httpStream.length; // need to pick up from where we left on streaming connections
+		}
+		else {
+			return; // the response not finished
+		}
+	}
+	return xhr;
+}
\ No newline at end of file
Index: tests/crossSite.php
===================================================================
--- tests/crossSite.php	(revision 0)
+++ tests/crossSite.php	(revision 0)
@@ -0,0 +1,12 @@
+<?php
+	header("XDomainRequestAllowed: 1");
+	header("Access-Control: allow <*>");
+	if ($_REQUEST["url"]) {
+		print "proxied";
+	}
+	if ($_REQUEST["windowname"]) {
+		print "<html><script type='text/javascript'>window.name='cross-site response'</script></html>";
+	}
+
+?>
+cross-site response
\ No newline at end of file
Index: tests/windowName.html
===================================================================
--- tests/windowName.html	(revision 0)
+++ tests/windowName.html	(revision 0)
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+	<title>Window Name Test</title>
+	<style type="text/css">
+		@import "../../../dojo/resources/dojo.css";
+		@import "../../../dijit/tests/css/dijitTests.css";
+	</style>
+
+	<script type="text/javascript" src="../../../dojo/dojo.js" djConfig="isDebug:true"></script>
+	<script type="text/javascript" src="../xhrWindowNamePlugin.js"></script>
+	<script type="text/javascript">
+	dojox.io.xhrWindowNamePlugin("http://192.168.0.66:8080");
+function test() {
+	var dfd = dojo.xhr("GET",{url:
+			prompt("Enter an address to retrieve data from",
+						"http://192.168.0.66:8080/root"),
+				timeout:10000,
+				handleAs:"json"});
+	dfd.addCallback(function(result){console.log(result)});		
+	dfd.addErrback(function(result){alert(result)});
+}
+function testPost() {
+	var dfd = dojox.io.windowName.send("POST",{url:
+			prompt("Enter an address to post data to",
+						"http://192.168.0.66:8080/Customer/"),
+						content:{foo:"bar"}
+			},true);
+	dfd.addCallback(function(result){alert(result)});		
+	dfd.addErrback(function(result){alert(result)});
+}
+	</script>
+</head>
+<body class="tundra">
+	<h1>Window Name Test</h1>
+	<p>Run this test from a web server, not from local disk.</p>
+	<button onclick="test()">get data</button>
+</body>
+</html>
Index: tests/windowName.js
===================================================================
--- tests/windowName.js	(revision 0)
+++ tests/windowName.js	(revision 0)
@@ -0,0 +1,59 @@
+dojo.provide("dojox.io.tests.xhrPlugins");
+dojo.require("dojox.io.xhrPlugins");
+
+dojox.io.xhrPlugins.addXdr("http://xdrsupportingsite.com/"); // make sure the registry is setup
+var url = dojo.moduleUrl("dojox.io.tests.crossSite");
+url = url.toString();
+url = url.substring(0,url.length-1) + ".php";
+
+doh.register("dojox.io.tests.xhrPlugins", [
+	function getLocal(t){
+		var d = new doh.Deferred();
+		var dfd = dojo.xhr("GET",{url:url});
+		dfd.addCallback(function(result){
+			d.callback(result.match(/response/));
+		});
+		return d;
+	},
+
+	function crossSiteRequest(t){
+		// Note: this isn't really testing much unless you are using IE8 (XDomainRequest) or a 
+		// browser that supports cross-site XHR (maybe FF3.1?) 
+		var d = new doh.Deferred();
+		// persevere supports both XDR and cross-site XHR so we can use it for cross-site testing for now
+		dojox.io.xhrPlugins.addXdr("http://persevere.sitepen.com/");
+		dojox.io.xhrPlugins.addCrossSiteXhr("http://persevere.sitepen.com/");
+		try {
+			var dfd = dojo.xhr("GET",{url:"http://persevere.sitepen.com/SMD"});
+		}
+		catch (e){
+			if(e.message.match(/No match/)){
+				return; // this browser doesn't support this transport
+			}
+			throw e;
+		}
+		dfd.addCallback(function(result){
+			d.callback(result.match(/transport/)); 
+		});
+		// TODO: This should run off a fixed URL on some Dojo server.  
+		
+/*		dojox.io.xhrPlugins.addXdr("http://dojotoolkit.org/...");
+		dojox.io.xhrPlugins.addCrossSiteXhr("http://dojotoolkit.org/...");
+				
+		var dfd = dojo.xhr("GET",{url:"http://dojotoolkit.org/.../dojox/io/tests/crossSite.php"});
+		dfd.addCallback(function(result){
+			d.callback(result.match(/response/));
+		}); */
+		return d;
+	},
+	function proxiedRequest(t){
+		var d = new doh.Deferred();
+		dojox.io.xhrPlugins.addProxy(url+"?url=");
+
+		var dfd = dojo.xhr("GET",{url:"http://someforeignsite.com/SMD"});
+		dfd.addCallback(function(result){
+			d.callback(result.match(/proxied/));
+		});
+		return d;
+	}
+]);
Index: windowName.js
===================================================================
--- windowName.js	(revision 0)
+++ windowName.js	(revision 0)
@@ -0,0 +1,118 @@
+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
+		//
+		//	description:
+		//		In order to provide a window.name 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
+		// 		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.
+		
+		args.url += (args.url.match(/\?/) ? '&' : '?') + "windowname=" + (args.windowName || true); // indicate our desire for window.name communication
+		var cleanup = function(result){
+			dojo.body().removeChild(frame); // clean up
+			return result;
+		}
+		var dfd = dojo._ioSetArgs(args,cleanup,cleanup,cleanup);
+		if(args.timeout){
+				setTimeout(function(){
+					if(state!=2){
+						dfd.callback(new Error("Timeout"));
+					}
+				},
+				args.timeout
+			);
+		}
+		var ioArgs = dfd.ioArgs;
+		var startName = "__starting__";
+		var frameName = "dojox.io.windowName" + Math.random();
+		var frameNum = dojox.io.windowName._frameNum++;
+
+		frame = dojo.doc.createElement(dojo.isIE ? '<iframe name="' + frameName + '" onload="dojox.io.windowName['+frameNum+']()">' : 'iframe');
+		frame.style.display='none';
+		var state = 0;
+		dojox.io.windowName[frameNum] = frame.onload = function(){
+			try{
+				if(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 == 1){
+				// back to our domain, we should be able to access the frame name now				
+				var data = frame.contentWindow.name;
+				if(data){
+					state = 2; // we are done now
+					if(data == startName){
+						data = new Error("The requested resource did not set it's window.name");
+					}
+					dfd.callback(data);
+				}
+			}
+			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;
+				var sameDomainUrl = (dojo.config["dojoBlankHtmlUrl"]||dojo.moduleUrl("dojo", "resources/blank.html"));
+				frame.contentWindow.location = sameDomainUrl;
+			}
+		};
+		frame.name = frameName;
+		//frame.setAttribute("name","targ");
+		//window.targ = frame;
+		dojo.body().appendChild(frame);
+		//frame.contentWindow && (frame.contentWindow.name = startName); // firefox likes it first
+		if(method.match(/GET/i)){
+			dojo._ioAddQueryToUrl(ioArgs);
+			frame.src = ioArgs.url;
+		}else if(method.match(/POST/i)){
+			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(j = 0; j < values.length; j++){
+					// create hidden inputs for all the parameters
+					var input = dojo.doc.createElement("input");
+					input.type = 'hidden';
+					input.name = i;
+					input.value = values[j];				
+					form.appendChild(input);	
+				}
+			}
+			form.method = 'POST';
+			form.action = args.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");
+		}
+		frame.contentWindow && (frame.contentWindow.name = startName); // IE likes it afterwards
+		return dfd;
+	},
+	_frameNum: 0
+	
+}
\ No newline at end of file
Index: xhrWindowNamePlugin.js
===================================================================
--- xhrWindowNamePlugin.js	(revision 0)
+++ xhrWindowNamePlugin.js	(revision 0)
@@ -0,0 +1,44 @@
+dojo.provide("dojox.io.xhrWindowNamePlugin");
+dojo.require("dojox.io.xhrPlugins");
+dojo.require("dojox.io.windowName");
+dojo.require("dojox.io.httpParse");
+
+dojox.io.xhrWindowNamePlugin = function(/*String*/url, /*Boolean?*/asHttp){
+	// summary:
+	//		Adds the windowName transport as an XHR plugin for the given site. See
+	//		dojox.io.windowName for more information on the transport.
+	//	url:
+	//		Url prefix of the site which can handle windowName requests.
+	//	asHttp:
+	//		Indicates whether the target site will be sending response as an HTTP
+	//		message (vs a direct response). If this is not defined, it will attempt to
+	//		auto-detect whether a message is HTTP
+	dojox.io.xhrPlugins.register(
+		"windowName",
+		function(method,args){
+			 return args.sync !== true && 
+				(method == "GET" || method == "POST" /*|| allowHeadersAndMethodsInURLParameters*/) && 
+				(args.url.substring(0,url.length) == url);
+		},
+		function(method,args){
+			if(asHttp !== false){
+				args = args || {};
+				args.windowName = "http"; // let the server know we want http 
+			}
+			var dfd = dojox.io.windowName.send(method, args); // use the windowName transport
+			dfd.addCallback(function(result){
+				var ioArgs = dfd.ioArgs;
+				ioArgs.xhr = (asHttp || 
+					// if asHttp isn't defined, we will try to auto-detect if it is HTTP
+					(asHttp !== false && result.match(/^HTTP\/\d\.\d \d\d\d[\w\s]*\n/))) ?
+					// parse as HTTP and put the resultant XHR emulation into ioArgs.xhr 
+					dfd.dojox.io.httpParse(result) :
+					// simple XHR emulation for direct windowName results  
+					{responseText : result}; 
+				// use the XHR content handlers for handling
+				return dojo._contentHandlers[ioArgs.handleAs || "text"](ioArgs.xhr); 
+			});
+			return dfd;
+		}
+	);
+};
\ No newline at end of file
