source: Dev/trunk/src/client/dojox/io/proxy/xip_server.html

Last change on this file was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 10.2 KB
Line 
1<!--
2        /*
3                Copyright (c) 2004-2011, The Dojo Foundation
4                All Rights Reserved.
5       
6                Licensed under the Academic Free License version 2.1 or above OR the
7                modified BSD license. For more information on Dojo licensing, see:
8       
9                        http://dojotoolkit.org/community/licensing.shtml
10        */
11        Pieces taken from Dojo source to make this file stand-alone
12-->
13<html>
14<head>
15        <title></title>
16        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
17        <script type="text/javascript" src="isAllowed.js"></script>
18        <!--
19        BY DEFAULT THIS FILE DOES NOT WORK SO THAT YOU DON'T ACCIDENTALLY EXPOSE
20        ALL OF YOUR XHR-ENABLED SERVICES ON YOUR SITE.
21       
22        In order for this file to work, you need to uncomment the start and end script tags,
23        and you should define a function with the following signature:
24       
25        function isAllowedRequest(request){
26                return false;   
27        }
28       
29        Return true out of the function if you want to allow the cross-domain request.
30       
31        DON'T DEFINE THIS FUNCTION IN THIS FILE! Define it in a separate file called isAllowed.js
32        and include it in this page with a script tag that has a src attribute pointing to the file.
33        See the very first script tag in this file for an example. You do not have to place the
34        script file in the same directory as this file, just update the path above if you move it
35        somewhere else.
36       
37        Customize the isAllowedRequest function to restrict what types of requests are allowed
38        for this server. The request object has the following properties:
39        - requestHeaders: an object with the request headers that are to be added to
40                          the XHR request.
41        - method: the HTTP method (GET, POST, etc...)
42        - uri: The URI for the request.
43        - data: The URL-encoded data for the request. For a GET request, this would
44                be the querystring parameters. For a POST request, it wll be the
45                body data.
46               
47        See xip_client.html for more info on the xip fragment identifier protocol.     
48        -->
49       
50        <!-- Security protection: uncomment the script tag to enable. -->
51        <!-- script type="text/javascript" -->
52        // <!--
53                //Core XHR handling taken from Dojo IO code.
54                dojo = {};
55                dojo.hostenv = {};
56                // These are in order of decreasing likelihood; this will change in time.
57                dojo.hostenv._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
58               
59                dojo.hostenv.getXmlhttpObject = function(){
60                                var http = null;
61                        var last_e = null;
62                        try{ http = new XMLHttpRequest(); }catch(e){}
63                                if(!http){
64                                for(var i=0; i<3; ++i){
65                                        var progid = dojo.hostenv._XMLHTTP_PROGIDS[i];
66                                        try{
67                                                http = new ActiveXObject(progid);
68                                        }catch(e){
69                                                last_e = e;
70                                        }
71               
72                                        if(http){
73                                                dojo.hostenv._XMLHTTP_PROGIDS = [progid];  // so faster next time
74                                                break;
75                                        }
76                                }
77               
78                                /*if(http && !http.toString) {
79                                        http.toString = function() { "[object XMLHttpRequest]"; }
80                                }*/
81                        }
82               
83                        if(!http){
84                                throw "xip_server.html: XMLHTTP not available: " + last_e;
85                        }
86               
87                        return http;
88                }
89
90                dojo.setHeaders = function(http, headers){
91                        if(headers) {
92                                for(var header in headers) {
93                                        var headerValue = headers[header];
94                                        http.setRequestHeader(header, headerValue);
95                                }
96                        }
97                }
98
99        //MSIE has the lowest limit for URLs with fragment identifiers,
100        //at around 4K. Choosing a slightly smaller number for good measure.
101        xipUrlLimit = 4000;
102        xipIdCounter = 1;
103
104        function xipServerInit(){
105                xipStateId = "";
106                xipCurrentHash = "";
107                xipRequestMessage = "";
108                xipResponseParts = [];
109                xipPartIndex = 0;
110        }
111
112        function pollHash(){
113                //Can't use location.hash because at least Firefox does a decodeURIComponent on it.
114                var urlParts = window.location.href.split("#");
115                if(urlParts.length == 2){
116                        var newHash = urlParts[1];
117                        if(newHash != xipCurrentHash){
118                                try{
119                                        messageReceived(newHash);
120                                }catch(e){
121                                        //Make sure to not keep processing the error hash value.
122                                        xipCurrentHash = newHash;
123                                        throw e;
124                                }
125                                xipCurrentHash = newHash;
126                        }
127                }
128        }
129
130        function messageReceived(encodedData){
131                var msg = unpackMessage(encodedData);
132               
133                switch(msg.command){
134                        case "ok":
135                                sendResponsePart();
136                                break;
137                        case "start":
138                                xipRequestMessage = "";
139                                xipRequestMessage += msg.message;
140                                setClientUrl("ok");
141                                break;
142                        case "part":
143                                xipRequestMessage += msg.message;                       
144                                setClientUrl("ok");
145                                break;
146                        case "end":
147                                setClientUrl("ok");
148                                xipRequestMessage += msg.message;
149                                sendXhr();
150                                break;
151                }
152        }
153
154        function sendResponse(encodedData){
155                //Break the message into parts, if necessary.
156                xipResponseParts = [];
157                var resData = encodedData;
158                var urlLength = xipClientUrl.length;
159                var partLength = xipUrlLimit - urlLength;
160                var resIndex = 0;
161
162                while((resData.length - resIndex) + urlLength > xipUrlLimit){
163                        var part = resData.substring(resIndex, resIndex + partLength);
164                        //Safari will do some extra hex escaping unless we keep the original hex
165                        //escaping complete.
166                        var percentIndex = part.lastIndexOf("%");
167                        if(percentIndex == part.length - 1 || percentIndex == part.length - 2){
168                                part = part.substring(0, percentIndex);
169                        }
170                        xipResponseParts.push(part);
171                        resIndex += part.length;
172                }
173                xipResponseParts.push(resData.substring(resIndex, resData.length));
174               
175                xipPartIndex = 0;
176                sendResponsePart();
177        }
178       
179        function sendResponsePart(){
180                if(xipPartIndex < xipResponseParts.length){
181                        //Get the message part.
182                        var partData = xipResponseParts[xipPartIndex];
183                       
184                        //Get the command.
185                        var cmd = "part";
186                        if(xipPartIndex + 1 == xipResponseParts.length){
187                                cmd = "end";
188                        }else if (xipPartIndex == 0){
189                                cmd = "start";
190                        }
191
192                        setClientUrl(cmd, partData);
193                        xipPartIndex++;
194                }else{
195                        xipServerInit();
196                }
197        }
198
199        function setClientUrl(cmd, message){
200                var clientUrl = makeClientUrl(cmd, message);
201                //Safari won't let us replace across domains.
202                if(navigator.userAgent.indexOf("Safari") == -1){
203                        xipClientWindow.location.replace(clientUrl);
204                }else{
205                        xipClientWindow.location = clientUrl;
206                }
207        }
208
209        function makeClientUrl(cmd, message){
210                var clientUrl = xipClientUrl + "#" + (xipIdCounter++) + ":" + cmd;
211                if(message){
212                        clientUrl += ":" + message;
213                }
214                return clientUrl
215        }
216
217        function xhrDone(xhr){
218                /* Need to pull off and return the following data:
219                        - responseHeaders
220                        - status
221                        - statusText
222                        - responseText
223                */
224                var response = {};
225       
226                if(typeof(xhr.getAllResponseHeaders) != "undefined"){
227                        var allHeaders = xhr.getAllResponseHeaders();
228                        if(allHeaders){
229                                response.responseHeaders = allHeaders;
230                        }
231                }
232               
233                if(xhr.status == 0 || xhr.status){
234                        response.status = xhr.status;
235                }
236               
237                if(xhr.statusText){
238                        response.statusText = xhr.statusText;
239                }
240               
241                if(xhr.responseText){
242                        response.responseText = xhr.responseText;
243                }
244       
245                //Build a string of the response object.
246                var result = "";
247                var isFirst = true;
248                for (var param in response){
249                        if(isFirst){
250                                isFirst = false;
251                        }else{
252                                result += "&";
253                        }
254                        result += param + "=" + encodeURIComponent(response[param]);
255                }
256                sendResponse(result);
257        }
258
259        function sendXhr(){
260                var request = {};
261                var nvPairs = xipRequestMessage.split("&");
262                var i = 0;
263                var nameValue = null;
264                for(i = 0; i < nvPairs.length; i++){
265                        if(nvPairs[i]){
266                                var nameValue = nvPairs[i].split("=");
267                                request[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]);
268                        }
269                }
270
271                //Split up the request headers, if any.
272                var headers = {};
273                if(request.requestHeaders){
274                        nvPairs = request.requestHeaders.split("\r\n");
275                        for(i = 0; i < nvPairs.length; i++){
276                                if(nvPairs[i]){
277                                        nameValue = nvPairs[i].split(": ");
278                                        headers[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]);
279                                }
280                        }
281
282                        request.requestHeaders = headers;
283                }
284               
285                if(isAllowedRequest(request)){
286               
287                        //The request is allowed, so set up the XHR object.
288                        var xhr = dojo.hostenv.getXmlhttpObject();
289                       
290                        //Start timer to look for readyState.
291                        var xhrIntervalId = setInterval(function(){
292                       
293                                if(xhr.readyState == 4){
294                                        clearInterval(xhrIntervalId);
295                                        xhrDone(xhr);
296                                }
297                        }, 10);
298
299                        //Actually start up the XHR request.
300                        xhr.open(request.method, request.uri, true);
301                        dojo.setHeaders(xhr, request.requestHeaders);
302                       
303                        var content = "";
304                        if(request.data){
305                                content = request.data;
306                        }
307
308                        try{
309                                xhr.send(content);
310                        }catch(e){
311                                if(typeof xhr.abort == "function"){
312                                        xhr.abort();
313                                        xhrDone({status: 404, statusText: "xip_server.html error: " + e});
314                                }
315                        }
316                }
317        }
318
319        function unpackMessage(encodedMessage){
320                var parts = encodedMessage.split(":");
321                var command = parts[1];
322                encodedMessage = parts[2] || "";
323
324                var config = null;
325                if(command == "init"){
326                        var configParts = encodedMessage.split("&");
327                        config = {};
328                        for(var i = 0; i < configParts.length; i++){
329                                var nameValue = configParts[i].split("=");
330                                config[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]);
331                        }
332                }
333                return {command: command, message: encodedMessage, config: config};
334        }
335
336        function onServerLoad(){
337                xipServerInit();
338
339                //Decode the init params
340                var config = unpackMessage(window.location.href.split("#")[1]).config;
341
342                xipStateId = config.id;
343                xipClientUrl = config.client;
344               
345                //Make sure we don't have a javascript: url, just for good measure.
346                if(xipClientUrl.split(":")[0].match(/javascript/i)){
347                        throw "Invalid client URL";
348                }
349                if(!xipStateId.match(/^XhrIframeProxy[0-9]+$/)){
350                        throw "Invalid state ID";
351                }
352       
353                setInterval(pollHash, 10);
354               
355                var serverUrl = window.location.href.split("#")[0];
356                document.getElementById("iframeHolder").innerHTML = '<iframe name="'
357                        + xipStateId + '_clientEndPoint'
358                        + '" src="javascript:false">'
359                        + '</iframe>';
360                xipClientWindow = document.getElementsByTagName("iframe")[0];
361                xipClientWindow.src = makeClientUrl("init", 'id=' + xipStateId + "&callback=" + encodeURIComponent(config.callback));
362                if(xipClientWindow.contentWindow){
363                        xipClientWindow = xipClientWindow.contentWindow;
364                }
365        }
366
367        if(typeof(window.addEventListener) == "undefined"){
368                window.attachEvent("onload", onServerLoad);
369        }else{
370                window.addEventListener('load', onServerLoad, false);
371        }
372        // -->
373        <!-- </script> -->
374</head>
375<body>
376        <h4>The Dojo Toolkit -- xip_server.html</h4>
377
378        <p>This file is used for Dojo's XMLHttpRequest Iframe Proxy. This is the the file
379        that should go on the server that will actually be doing the XHR request.</p>
380        <div id="iframeHolder"></div>
381</body>
382</html>
Note: See TracBrowser for help on using the repository browser.