Subversion Repositories Applications.papyrus

Rev

Rev 1422 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1318 alexandre_ 1
<!--
2
	/*
3
		Copyright (c) 2004-2006, 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
 
1422 alexandre_ 22
	In order for this file to work, you need to uncomment the script element,
23
	and you should define a function with the following signature:
1318 alexandre_ 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
	-->
1422 alexandre_ 49
 
50
	<!-- Security protection: uncomment the script tag to enable. -->
51
	<!-- script type="text/javascript" -->
1318 alexandre_ 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
			parent.location.replace(clientUrl);
204
		}else{
205
			parent.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;
1422 alexandre_ 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
 
1318 alexandre_ 353
		xipUseFrameRecursion = config["fr"];
354
 
355
		setInterval(pollHash, 10);
356
 
357
		if(xipUseFrameRecursion == "true"){
358
			var serverUrl = window.location.href.split("#")[0];
1422 alexandre_ 359
			document.getElementById("iframeHolder").innerHTML = '<iframe name="'
360
				+ xipStateId + '_clientEndPoint'
361
				+ '" src="javascript:false">'
362
				+ '</iframe>';
363
			var iframeNode = document.getElementsByTagName("iframe")[0];
364
			iframeNode.src = makeClientUrl("init", 'id=' + xipStateId + '&server='
365
				+ encodeURIComponent(serverUrl) + '&fr=endpoint');
1318 alexandre_ 366
		}else{
367
			setClientUrl("loaded");
368
		}
369
	}
370
 
371
	if(typeof(window.addEventListener) == "undefined"){
372
		window.attachEvent("onload", onServerLoad);
373
	}else{
374
		window.addEventListener('load', onServerLoad, false);
375
	}
376
	// -->
377
	</script>
378
</head>
379
<body>
380
	<h4>The Dojo Toolkit -- xip_server.html</h4>
381
 
382
	<p>This file is used for Dojo's XMLHttpRequest Iframe Proxy. This is the the file
383
	that should go on the server that will actually be doing the XHR request.</p>
384
	<div id="iframeHolder"></div>
385
</body>
386
</html>