| <!-- |
| /* |
| Copyright (c) 2004-2008, The Dojo Foundation |
| All Rights Reserved. |
| |
| Licensed under the Academic Free License version 2.1 or above OR the |
| modified BSD license. For more information on Dojo licensing, see: |
| |
| http://dojotoolkit.org/community/licensing.shtml |
| */ |
| Pieces taken from Dojo source to make this file stand-alone |
| --> |
| <html> |
| <head> |
| <title></title> |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta> |
| <script type="text/javascript" src="isAllowed.js"></script> |
| <!-- |
| BY DEFAULT THIS FILE DOES NOT WORK SO THAT YOU DON'T ACCIDENTALLY EXPOSE |
| ALL OF YOUR XHR-ENABLED SERVICES ON YOUR SITE. |
| |
| In order for this file to work, you need to uncomment the start and end script tags, |
| and you should define a function with the following signature: |
| |
| function isAllowedRequest(request){ |
| return false; |
| } |
| |
| Return true out of the function if you want to allow the cross-domain request. |
| |
| DON'T DEFINE THIS FUNCTION IN THIS FILE! Define it in a separate file called isAllowed.js |
| and include it in this page with a script tag that has a src attribute pointing to the file. |
| See the very first script tag in this file for an example. You do not have to place the |
| script file in the same directory as this file, just update the path above if you move it |
| somewhere else. |
| |
| Customize the isAllowedRequest function to restrict what types of requests are allowed |
| for this server. The request object has the following properties: |
| - requestHeaders: an object with the request headers that are to be added to |
| the XHR request. |
| - method: the HTTP method (GET, POST, etc...) |
| - uri: The URI for the request. |
| - data: The URL-encoded data for the request. For a GET request, this would |
| be the querystring parameters. For a POST request, it wll be the |
| body data. |
| |
| See xip_client.html for more info on the xip fragment identifier protocol. |
| --> |
| |
| <!-- Security protection: uncomment the script tag to enable. --> |
| <!-- script type="text/javascript" --> |
| // <!-- |
| //Core XHR handling taken from Dojo IO code. |
| dojo = {}; |
| dojo.hostenv = {}; |
| // These are in order of decreasing likelihood; this will change in time. |
| dojo.hostenv._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0']; |
| |
| dojo.hostenv.getXmlhttpObject = function(){ |
| var http = null; |
| var last_e = null; |
| try{ http = new XMLHttpRequest(); }catch(e){} |
| if(!http){ |
| for(var i=0; i<3; ++i){ |
| var progid = dojo.hostenv._XMLHTTP_PROGIDS[i]; |
| try{ |
| http = new ActiveXObject(progid); |
| }catch(e){ |
| last_e = e; |
| } |
| |
| if(http){ |
| dojo.hostenv._XMLHTTP_PROGIDS = [progid]; // so faster next time |
| break; |
| } |
| } |
| |
| /*if(http && !http.toString) { |
| http.toString = function() { "[object XMLHttpRequest]"; } |
| }*/ |
| } |
| |
| if(!http){ |
| throw "xip_server.html: XMLHTTP not available: " + last_e; |
| } |
| |
| return http; |
| } |
| |
| dojo.setHeaders = function(http, headers){ |
| if(headers) { |
| for(var header in headers) { |
| var headerValue = headers[header]; |
| http.setRequestHeader(header, headerValue); |
| } |
| } |
| } |
| |
| //MSIE has the lowest limit for URLs with fragment identifiers, |
| //at around 4K. Choosing a slightly smaller number for good measure. |
| xipUrlLimit = 4000; |
| xipIdCounter = 1; |
| |
| function xipServerInit(){ |
| xipStateId = ""; |
| xipCurrentHash = ""; |
| xipRequestMessage = ""; |
| xipResponseParts = []; |
| xipPartIndex = 0; |
| } |
| |
| function pollHash(){ |
| //Can't use location.hash because at least Firefox does a decodeURIComponent on it. |
| var urlParts = window.location.href.split("#"); |
| if(urlParts.length == 2){ |
| var newHash = urlParts[1]; |
| if(newHash != xipCurrentHash){ |
| try{ |
| messageReceived(newHash); |
| }catch(e){ |
| //Make sure to not keep processing the error hash value. |
| xipCurrentHash = newHash; |
| throw e; |
| } |
| xipCurrentHash = newHash; |
| } |
| } |
| } |
| |
| function messageReceived(encodedData){ |
| var msg = unpackMessage(encodedData); |
| |
| switch(msg.command){ |
| case "ok": |
| sendResponsePart(); |
| break; |
| case "start": |
| xipRequestMessage = ""; |
| xipRequestMessage += msg.message; |
| setClientUrl("ok"); |
| break; |
| case "part": |
| xipRequestMessage += msg.message; |
| setClientUrl("ok"); |
| break; |
| case "end": |
| setClientUrl("ok"); |
| xipRequestMessage += msg.message; |
| sendXhr(); |
| break; |
| } |
| } |
| |
| function sendResponse(encodedData){ |
| //Break the message into parts, if necessary. |
| xipResponseParts = []; |
| var resData = encodedData; |
| var urlLength = xipClientUrl.length; |
| var partLength = xipUrlLimit - urlLength; |
| var resIndex = 0; |
| |
| while((resData.length - resIndex) + urlLength > xipUrlLimit){ |
| var part = resData.substring(resIndex, resIndex + partLength); |
| //Safari will do some extra hex escaping unless we keep the original hex |
| //escaping complete. |
| var percentIndex = part.lastIndexOf("%"); |
| if(percentIndex == part.length - 1 || percentIndex == part.length - 2){ |
| part = part.substring(0, percentIndex); |
| } |
| xipResponseParts.push(part); |
| resIndex += part.length; |
| } |
| xipResponseParts.push(resData.substring(resIndex, resData.length)); |
| |
| xipPartIndex = 0; |
| sendResponsePart(); |
| } |
| |
| function sendResponsePart(){ |
| if(xipPartIndex < xipResponseParts.length){ |
| //Get the message part. |
| var partData = xipResponseParts[xipPartIndex]; |
| |
| //Get the command. |
| var cmd = "part"; |
| if(xipPartIndex + 1 == xipResponseParts.length){ |
| cmd = "end"; |
| }else if (xipPartIndex == 0){ |
| cmd = "start"; |
| } |
| |
| setClientUrl(cmd, partData); |
| xipPartIndex++; |
| }else{ |
| xipServerInit(); |
| } |
| } |
| |
| function setClientUrl(cmd, message){ |
| var clientUrl = makeClientUrl(cmd, message); |
| //Safari won't let us replace across domains. |
| if(navigator.userAgent.indexOf("Safari") == -1){ |
| xipClientWindow.location.replace(clientUrl); |
| }else{ |
| xipClientWindow.location = clientUrl; |
| } |
| } |
| |
| function makeClientUrl(cmd, message){ |
| var clientUrl = xipClientUrl + "#" + (xipIdCounter++) + ":" + cmd; |
| if(message){ |
| clientUrl += ":" + message; |
| } |
| return clientUrl |
| } |
| |
| function xhrDone(xhr){ |
| /* Need to pull off and return the following data: |
| - responseHeaders |
| - status |
| - statusText |
| - responseText |
| */ |
| var response = {}; |
| |
| if(typeof(xhr.getAllResponseHeaders) != "undefined"){ |
| var allHeaders = xhr.getAllResponseHeaders(); |
| if(allHeaders){ |
| response.responseHeaders = allHeaders; |
| } |
| } |
| |
| if(xhr.status == 0 || xhr.status){ |
| response.status = xhr.status; |
| } |
| |
| if(xhr.statusText){ |
| response.statusText = xhr.statusText; |
| } |
| |
| if(xhr.responseText){ |
| response.responseText = xhr.responseText; |
| } |
| |
| //Build a string of the response object. |
| var result = ""; |
| var isFirst = true; |
| for (var param in response){ |
| if(isFirst){ |
| isFirst = false; |
| }else{ |
| result += "&"; |
| } |
| result += param + "=" + encodeURIComponent(response[param]); |
| } |
| sendResponse(result); |
| } |
| |
| function sendXhr(){ |
| var request = {}; |
| var nvPairs = xipRequestMessage.split("&"); |
| var i = 0; |
| var nameValue = null; |
| for(i = 0; i < nvPairs.length; i++){ |
| if(nvPairs[i]){ |
| var nameValue = nvPairs[i].split("="); |
| request[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]); |
| } |
| } |
| |
| //Split up the request headers, if any. |
| var headers = {}; |
| if(request.requestHeaders){ |
| nvPairs = request.requestHeaders.split("\r\n"); |
| for(i = 0; i < nvPairs.length; i++){ |
| if(nvPairs[i]){ |
| nameValue = nvPairs[i].split(": "); |
| headers[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]); |
| } |
| } |
| |
| request.requestHeaders = headers; |
| } |
| |
| if(isAllowedRequest(request)){ |
| |
| //The request is allowed, so set up the XHR object. |
| var xhr = dojo.hostenv.getXmlhttpObject(); |
| |
| //Start timer to look for readyState. |
| var xhrIntervalId = setInterval(function(){ |
| |
| if(xhr.readyState == 4){ |
| clearInterval(xhrIntervalId); |
| xhrDone(xhr); |
| } |
| }, 10); |
| |
| //Actually start up the XHR request. |
| xhr.open(request.method, request.uri, true); |
| dojo.setHeaders(xhr, request.requestHeaders); |
| |
| var content = ""; |
| if(request.data){ |
| content = request.data; |
| } |
| |
| try{ |
| xhr.send(content); |
| }catch(e){ |
| if(typeof xhr.abort == "function"){ |
| xhr.abort(); |
| xhrDone({status: 404, statusText: "xip_server.html error: " + e}); |
| } |
| } |
| } |
| } |
| |
| function unpackMessage(encodedMessage){ |
| var parts = encodedMessage.split(":"); |
| var command = parts[1]; |
| encodedMessage = parts[2] || ""; |
| |
| var config = null; |
| if(command == "init"){ |
| var configParts = encodedMessage.split("&"); |
| config = {}; |
| for(var i = 0; i < configParts.length; i++){ |
| var nameValue = configParts[i].split("="); |
| config[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]); |
| } |
| } |
| return {command: command, message: encodedMessage, config: config}; |
| } |
| |
| function onServerLoad(){ |
| xipServerInit(); |
| |
| //Decode the init params |
| var config = unpackMessage(window.location.href.split("#")[1]).config; |
| |
| xipStateId = config.id; |
| xipClientUrl = config.client; |
| |
| //Make sure we don't have a javascript: url, just for good measure. |
| if(xipClientUrl.split(":")[0].match(/javascript/i)){ |
| throw "Invalid client URL"; |
| } |
| if(!xipStateId.match(/^XhrIframeProxy[0-9]+$/)){ |
| throw "Invalid state ID"; |
| } |
| |
| setInterval(pollHash, 10); |
| |
| var serverUrl = window.location.href.split("#")[0]; |
| document.getElementById("iframeHolder").innerHTML = '<iframe name="' |
| + xipStateId + '_clientEndPoint' |
| + '" src="javascript:false">' |
| + '</iframe>'; |
| xipClientWindow = document.getElementsByTagName("iframe")[0]; |
| xipClientWindow.src = makeClientUrl("init", 'id=' + xipStateId + "&callback=" + encodeURIComponent(config.callback)); |
| if(xipClientWindow.contentWindow){ |
| xipClientWindow = xipClientWindow.contentWindow; |
| } |
| } |
| |
| if(typeof(window.addEventListener) == "undefined"){ |
| window.attachEvent("onload", onServerLoad); |
| }else{ |
| window.addEventListener('load', onServerLoad, false); |
| } |
| // --> |
| <!-- </script> --> |
| </head> |
| <body> |
| <h4>The Dojo Toolkit -- xip_server.html</h4> |
| |
| <p>This file is used for Dojo's XMLHttpRequest Iframe Proxy. This is the the file |
| that should go on the server that will actually be doing the XHR request.</p> |
| <div id="iframeHolder"></div> |
| </body> |
| </html> |