1318 |
alexandre_ |
1 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
|
2 |
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
|
3 |
|
|
|
4 |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
|
5 |
<head>
|
|
|
6 |
<title></title>
|
|
|
7 |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
|
1422 |
alexandre_ |
8 |
<!-- Security protection: uncomment the script tag to enable. -->
|
|
|
9 |
<!-- script type="text/javascript" -->
|
1318 |
alexandre_ |
10 |
// <!--
|
|
|
11 |
/*
|
|
|
12 |
This file is really focused on just sending one message to the server, and
|
|
|
13 |
receiving one response. The code does not expect to be re-used for multiple messages.
|
|
|
14 |
This might be reworked later if performance indicates a need for it.
|
|
|
15 |
|
|
|
16 |
xip fragment identifier/hash values have the form:
|
|
|
17 |
#id:cmd:realEncodedMessage
|
|
|
18 |
|
|
|
19 |
id: some ID that should be unique among messages. No inherent meaning,
|
|
|
20 |
just something to make sure the hash value is unique so the message
|
|
|
21 |
receiver knows a new message is available.
|
|
|
22 |
|
|
|
23 |
cmd: command to the receiver. Valid values are:
|
|
|
24 |
- init: message used to init the frame. Sent as the first URL when loading
|
|
|
25 |
the page. Contains some config parameters.
|
|
|
26 |
- loaded: the remote frame is loaded. Only sent from server to client.
|
|
|
27 |
- ok: the message that this page sent was received OK. The next message may
|
|
|
28 |
now be sent.
|
|
|
29 |
- start: the start message of a block of messages (a complete message may
|
|
|
30 |
need to be segmented into many messages to get around the limitiations
|
|
|
31 |
of the size of an URL that a browser accepts.
|
|
|
32 |
- part: indicates this is a part of a message.
|
|
|
33 |
- end: the end message of a block of messages. The message can now be acted upon.
|
|
|
34 |
If the message is small enough that it doesn't need to be segmented, then
|
|
|
35 |
just one hash value message can be sent with "end" as the command.
|
|
|
36 |
|
|
|
37 |
To reassemble a segmented message, the realEncodedMessage parts just have to be concatenated
|
|
|
38 |
together.
|
|
|
39 |
*/
|
|
|
40 |
|
|
|
41 |
//MSIE has the lowest limit for URLs with fragment identifiers,
|
|
|
42 |
//at around 4K. Choosing a slightly smaller number for good measure.
|
|
|
43 |
xipUrlLimit = 4000;
|
|
|
44 |
xipIdCounter = 1;
|
|
|
45 |
|
|
|
46 |
function xipInit(){
|
|
|
47 |
xipStateId = "";
|
|
|
48 |
xipIsSending = false;
|
|
|
49 |
xipServerUrl = null;
|
|
|
50 |
xipStateId = null;
|
|
|
51 |
xipRequestData = null;
|
|
|
52 |
xipCurrentHash = "";
|
|
|
53 |
xipResponseMessage = "";
|
|
|
54 |
xipRequestParts = [];
|
|
|
55 |
xipPartIndex = 0;
|
|
|
56 |
xipServerWindow = null;
|
|
|
57 |
xipUseFrameRecursion = false;
|
|
|
58 |
}
|
|
|
59 |
xipInit();
|
|
|
60 |
|
|
|
61 |
function send(encodedData){
|
|
|
62 |
if(xipUseFrameRecursion == "true"){
|
|
|
63 |
var clientEndPoint = window.open(xipStateId + "_clientEndPoint");
|
|
|
64 |
clientEndPoint.send(encodedData);
|
|
|
65 |
}else{
|
|
|
66 |
if(!xipIsSending){
|
|
|
67 |
xipIsSending = true;
|
|
|
68 |
|
|
|
69 |
xipRequestData = encodedData || "";
|
|
|
70 |
|
|
|
71 |
//Get a handle to the server iframe.
|
|
|
72 |
xipServerWindow = frames[xipStateId + "_frame"];
|
|
|
73 |
if (!xipServerWindow){
|
|
|
74 |
xipServerWindow = document.getElementById(xipStateId + "_frame").contentWindow;
|
|
|
75 |
}
|
|
|
76 |
|
|
|
77 |
sendRequestStart();
|
|
|
78 |
}
|
|
|
79 |
}
|
|
|
80 |
}
|
|
|
81 |
|
|
|
82 |
//Modify the server URL if it is a local path and
|
|
|
83 |
//This is done for local/same domain testing.
|
|
|
84 |
function fixServerUrl(ifpServerUrl){
|
|
|
85 |
if(ifpServerUrl.indexOf("..") == 0){
|
|
|
86 |
var parts = ifpServerUrl.split("/");
|
|
|
87 |
ifpServerUrl = parts[parts.length - 1];
|
|
|
88 |
}
|
|
|
89 |
return ifpServerUrl;
|
|
|
90 |
}
|
|
|
91 |
|
|
|
92 |
|
|
|
93 |
function pollHash(){
|
|
|
94 |
//Can't use location.hash because at least Firefox does a decodeURIComponent on it.
|
|
|
95 |
var urlParts = window.location.href.split("#");
|
|
|
96 |
if(urlParts.length == 2){
|
|
|
97 |
var newHash = urlParts[1];
|
|
|
98 |
if(newHash != xipCurrentHash){
|
|
|
99 |
try{
|
|
|
100 |
messageReceived(newHash);
|
|
|
101 |
}catch(e){
|
|
|
102 |
//Make sure to not keep processing the error hash value.
|
|
|
103 |
xipCurrentHash = newHash;
|
|
|
104 |
throw e;
|
|
|
105 |
}
|
|
|
106 |
xipCurrentHash = newHash;
|
|
|
107 |
}
|
|
|
108 |
}
|
|
|
109 |
}
|
|
|
110 |
|
|
|
111 |
function messageReceived(encodedData){
|
|
|
112 |
var msg = unpackMessage(encodedData);
|
|
|
113 |
|
|
|
114 |
switch(msg.command){
|
|
|
115 |
case "loaded":
|
|
|
116 |
xipMasterFrame.dojo.io.XhrIframeProxy.clientFrameLoaded(xipStateId);
|
|
|
117 |
break;
|
|
|
118 |
case "ok":
|
|
|
119 |
sendRequestPart();
|
|
|
120 |
break;
|
|
|
121 |
case "start":
|
|
|
122 |
xipResponseMessage = "";
|
|
|
123 |
xipResponseMessage += msg.message;
|
|
|
124 |
setServerUrl("ok");
|
|
|
125 |
break;
|
|
|
126 |
case "part":
|
|
|
127 |
xipResponseMessage += msg.message;
|
|
|
128 |
setServerUrl("ok");
|
|
|
129 |
break;
|
|
|
130 |
case "end":
|
|
|
131 |
setServerUrl("ok");
|
|
|
132 |
xipResponseMessage += msg.message;
|
|
|
133 |
xipMasterFrame.dojo.io.XhrIframeProxy.receive(xipStateId, xipResponseMessage);
|
|
|
134 |
break;
|
|
|
135 |
}
|
|
|
136 |
}
|
|
|
137 |
|
|
|
138 |
function sendRequestStart(){
|
|
|
139 |
//Break the message into parts, if necessary.
|
|
|
140 |
xipRequestParts = [];
|
|
|
141 |
var reqData = xipRequestData;
|
|
|
142 |
var urlLength = xipServerUrl.length;
|
|
|
143 |
var partLength = xipUrlLimit - urlLength;
|
|
|
144 |
var reqIndex = 0;
|
|
|
145 |
|
|
|
146 |
while((reqData.length - reqIndex) + urlLength > xipUrlLimit){
|
|
|
147 |
var part = reqData.substring(reqIndex, reqIndex + partLength);
|
|
|
148 |
//Safari will do some extra hex escaping unless we keep the original hex
|
|
|
149 |
//escaping complete.
|
|
|
150 |
var percentIndex = part.lastIndexOf("%");
|
|
|
151 |
if(percentIndex == part.length - 1 || percentIndex == part.length - 2){
|
|
|
152 |
part = part.substring(0, percentIndex);
|
|
|
153 |
}
|
|
|
154 |
xipRequestParts.push(part);
|
|
|
155 |
reqIndex += part.length;
|
|
|
156 |
}
|
|
|
157 |
xipRequestParts.push(reqData.substring(reqIndex, reqData.length));
|
|
|
158 |
|
|
|
159 |
xipPartIndex = 0;
|
|
|
160 |
sendRequestPart();
|
|
|
161 |
|
|
|
162 |
}
|
|
|
163 |
|
|
|
164 |
function sendRequestPart(){
|
|
|
165 |
if(xipPartIndex < xipRequestParts.length){
|
|
|
166 |
//Get the message part.
|
|
|
167 |
var partData = xipRequestParts[xipPartIndex];
|
|
|
168 |
|
|
|
169 |
//Get the command.
|
|
|
170 |
var cmd = "part";
|
|
|
171 |
if(xipPartIndex + 1 == xipRequestParts.length){
|
|
|
172 |
cmd = "end";
|
|
|
173 |
}else if (xipPartIndex == 0){
|
|
|
174 |
cmd = "start";
|
|
|
175 |
}
|
|
|
176 |
|
|
|
177 |
setServerUrl(cmd, partData);
|
|
|
178 |
xipPartIndex++;
|
|
|
179 |
}
|
|
|
180 |
}
|
|
|
181 |
|
|
|
182 |
function setServerUrl(cmd, message){
|
|
|
183 |
var serverUrl = makeServerUrl(cmd, message);
|
|
|
184 |
|
|
|
185 |
//Safari won't let us replace across domains.
|
|
|
186 |
if(navigator.userAgent.indexOf("Safari") == -1){
|
|
|
187 |
xipServerWindow.location.replace(serverUrl);
|
|
|
188 |
}else{
|
|
|
189 |
xipServerWindow.location = serverUrl;
|
|
|
190 |
}
|
|
|
191 |
}
|
|
|
192 |
|
|
|
193 |
function makeServerUrl(cmd, message){
|
|
|
194 |
var serverUrl = xipServerUrl + "#" + (xipIdCounter++) + ":" + cmd;
|
|
|
195 |
if(message){
|
|
|
196 |
serverUrl += ":" + message;
|
|
|
197 |
}
|
|
|
198 |
return serverUrl;
|
|
|
199 |
}
|
|
|
200 |
|
|
|
201 |
function unpackMessage(encodedMessage){
|
|
|
202 |
var parts = encodedMessage.split(":");
|
|
|
203 |
var command = parts[1];
|
|
|
204 |
encodedMessage = parts[2] || "";
|
|
|
205 |
|
|
|
206 |
var config = null;
|
|
|
207 |
if(command == "init"){
|
|
|
208 |
var configParts = encodedMessage.split("&");
|
|
|
209 |
config = {};
|
|
|
210 |
for(var i = 0; i < configParts.length; i++){
|
|
|
211 |
var nameValue = configParts[i].split("=");
|
|
|
212 |
config[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]);
|
|
|
213 |
}
|
|
|
214 |
}
|
|
|
215 |
return {command: command, message: encodedMessage, config: config};
|
|
|
216 |
}
|
|
|
217 |
|
|
|
218 |
function onClientLoad(){
|
|
|
219 |
//Decode the init params
|
|
|
220 |
var config = unpackMessage(window.location.href.split("#")[1]).config;
|
|
|
221 |
|
|
|
222 |
xipStateId = config.id;
|
|
|
223 |
|
|
|
224 |
//Remove the query param for the IE7 recursive case.
|
|
|
225 |
xipServerUrl = fixServerUrl(config.server).replace(/(\?|\&)dojo\.fr\=1/, "");
|
1422 |
alexandre_ |
226 |
|
|
|
227 |
//Make sure we don't have a javascript: url, just for good measure.
|
|
|
228 |
if(xipServerUrl.split(":")[0].match(/javascript/i)){
|
|
|
229 |
throw "Invalid server URL";
|
|
|
230 |
}
|
|
|
231 |
|
1318 |
alexandre_ |
232 |
xipUseFrameRecursion = config["fr"];
|
|
|
233 |
|
|
|
234 |
if(xipUseFrameRecursion == "endpoint"){
|
|
|
235 |
xipMasterFrame = parent.parent;
|
|
|
236 |
}else{
|
|
|
237 |
xipMasterFrame = parent;
|
|
|
238 |
}
|
|
|
239 |
|
|
|
240 |
//Start counter to inspect hash value.
|
|
|
241 |
setInterval(pollHash, 10);
|
|
|
242 |
|
|
|
243 |
var clientUrl = window.location.href.split("#")[0];
|
1422 |
alexandre_ |
244 |
var iframeNode = document.getElementsByTagName("iframe")[0];
|
|
|
245 |
iframeNode.id = xipStateId + "_frame";
|
|
|
246 |
iframeNode.src = makeServerUrl("init", 'id=' + xipStateId + '&client='
|
|
|
247 |
+ encodeURIComponent(clientUrl) + '&fr=' + xipUseFrameRecursion);
|
1318 |
alexandre_ |
248 |
}
|
|
|
249 |
|
|
|
250 |
if(typeof(window.addEventListener) == "undefined"){
|
|
|
251 |
window.attachEvent("onload", onClientLoad);
|
|
|
252 |
}else{
|
|
|
253 |
window.addEventListener('load', onClientLoad, false);
|
|
|
254 |
}
|
|
|
255 |
|
|
|
256 |
// -->
|
|
|
257 |
</script>
|
|
|
258 |
</head>
|
|
|
259 |
<body>
|
|
|
260 |
<h4>The Dojo Toolkit -- xip_client.html</h4>
|
|
|
261 |
|
|
|
262 |
<p>This file is used for Dojo's XMLHttpRequest Iframe Proxy. This is the "client" file used
|
|
|
263 |
internally by dojo.io.XhrIframeProxy.</p>
|
|
|
264 |
|
1422 |
alexandre_ |
265 |
<iframe src="javascript:false"></iframe>
|
1318 |
alexandre_ |
266 |
</body>
|
|
|
267 |
</html>
|