]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/web/opac/common/js/RemoteRequest.js
09a14227c90b2796b1fbcf8a0b5d2ae561795205
[Evergreen.git] / Open-ILS / web / opac / common / js / RemoteRequest.js
1 var XML_HTTP_GATEWAY = "osrf-gateway-v1";
2 var XML_HTTP_SERVER = "";
3
4
5 /* This object is thrown when network failures occur */
6 function NetworkFailure(stat, url) { 
7         this._status = stat; 
8         this._url = url;
9 }
10
11 NetworkFailure.prototype.status = function() { return this._status; }
12 NetworkFailure.prototype.url = function() { return this._url; }
13 NetworkFailure.prototype.toString = function() { 
14         return "Network Failure: status = " + this.status() +'\n'+this.url(); 
15 }
16
17
18
19 function isXUL() { try { if(IAMXUL) return true;}catch(e){return false;}; }
20 var _allrequests = {};
21
22 // If the legacy JSON gateway is needed by the staff client, uncomment this
23 /* 
24 if(isXUL()) {
25     XML_HTTP_GATEWAY = 'gateway';
26 }
27 */
28
29 function cleanRemoteRequests() {
30         for( var i in _allrequests ) 
31                 destroyRequest(_allrequests[i]);
32 }
33
34 function abortAllRequests() {
35         for( var i in _allrequests ) {
36                 var r = _allrequests[i];
37                 if(r) { 
38                         r.abort();
39                         destroyRequest(r);
40                 }
41         }
42 }
43
44 function destroyRequest(r) {
45         if(r == null) return;
46
47         if( r.xmlhttp ) {
48                 r.xmlhttp.onreadystatechange = function(){};
49                 r.xmlhttp = null;
50         }
51
52         r.callback                              = null;
53         r.userdata                              = null;
54         _allrequests[r.id]      = null;
55 }
56
57 /* ----------------------------------------------------------------------- */
58 /* Request object */
59 var rrId = 0;
60 function RemoteRequest( service, method ) {
61
62
63         this.service    = service;
64         this.method             = method;
65         this.xmlhttp    = false;
66         this.name               = null;
67         this.alertEvent = true; /* only used when isXUL is false */
68
69         this.type               = "POST"; /* default */
70         this.id                 = rrId++;
71         this.cancelled = false;
72
73         this.setSecure(false);
74         if(isXUL()) this.setSecure(true);
75
76         _allrequests[this.id] = this;
77
78         var i = 2;
79         this.params = ""; 
80
81         while(i < arguments.length) {
82                 var object = js2JSON(arguments[i++]);
83                 this.params += "&param=" + encodeURIComponent(object);
84         }
85
86         if(!this.params) { this.params = ""; }
87         this.param_string = "service=" + service + "&method=" + method + this.params;
88         if( this.buildXMLRequest() == null ) alert("Browser is not supported!");
89
90 }
91
92
93 RemoteRequest.prototype.timeout = function(t) {
94         t *= 1000
95         var req = this;
96         req.timeoutFunc = setTimeout(
97                 function() {
98                         if( req && req.xmlhttp ) {
99                                 req.cancelled = true;
100                                 req.abort();
101                                 if( req.abtCallback ) {
102                                         req.abtCallback(req);
103                                 }
104                         }
105                 },
106                 t
107         );
108 }
109
110 RemoteRequest.prototype.abortCallback = function(func) {
111         this.abtCallback = func;
112 }
113
114 RemoteRequest.prototype.event = function(evt) {
115         if( arguments.length > 0 )
116                 this.evt = evt;
117         return this.evt;
118 }
119
120 RemoteRequest.prototype.abort = function() {
121         if( this.xmlhttp ) {
122                 /* this has to come before abort() or IE will puke on you */
123                 this.xmlhttp.onreadystatechange = function(){};
124                 this.xmlhttp.abort();
125         }
126 }
127
128 /* constructs our XMLHTTPRequest object */
129 RemoteRequest.prototype.buildXMLRequest = function() {
130         this.xmlhttp = buildXMLRequest();
131         return true;
132 }
133
134
135 function buildXMLRequest() {
136     try {
137             return new XMLHttpRequest();
138     } catch(e) {
139             try { 
140                     return new ActiveXObject("Msxml2.XMLHTTP"); 
141             } catch (e2) {
142                     try { 
143                             return new ActiveXObject("Microsoft.XMLHTTP"); 
144                     } catch (e3) {
145                         alert("NEEDS NEWER JAVASCRIPT for XMLHTTPRequest()");
146                 return null;
147                     }
148             }
149     }
150 }
151
152
153 function _remoteRequestCallback(id) {
154
155         var object = _allrequests[id];
156         if(object.cancelled) return;
157
158         if( object.xmlhttp.readyState == 4 ) {
159
160         try {
161             object.duration = new Date().getTime() - object.sendTime;
162             dump('request ' + object.id + ': duration = ' + object.duration + ' ms\n');
163         } catch(ee){}
164
165                 try {
166                         object.callback(object);
167                 } catch(E) {
168             throw E
169                 } finally { 
170                         destroyRequest(object); 
171                         object = null; 
172                 }  
173         }
174 }
175
176
177 /* define the callback we use when this request has received
178         all of its data */
179 RemoteRequest.prototype.setCompleteCallback = function(callback) {
180         if(this.cancelled) return;
181         this.callback = callback;
182         var id = this.id;
183         this.xmlhttp.onreadystatechange = function() { _remoteRequestCallback(id); }
184 }
185
186
187 /* http by default.  This makes it https. *ONLY works when
188         embedded in a XUL app. */
189 RemoteRequest.prototype.setSecure = function(bool) {
190         this.secure = bool; 
191 }
192
193 RemoteRequest.prototype.send = function(blocking) {
194
195         if(this.cancelled) return;
196
197         /* determine the xmlhttp server dynamically */
198         var url = location.protocol + "//" + location.host + "/" + XML_HTTP_GATEWAY;
199
200         if(isXUL()) {
201                 if( XML_HTTP_SERVER ) 
202                         url = 'http://'+XML_HTTP_SERVER+'/'+XML_HTTP_GATEWAY;
203
204                 if( url.match(/^http:/) && 
205                                 (this.secure || location.href.match(/^https:/)) ) {
206                         netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
207                         url = url.replace(/^http:/, 'https:');
208                 }
209         }
210
211         var data = null;
212         if( this.type == 'GET' ) url +=  "?" + this.param_string; 
213
214         this.url = url;
215
216    //if( isXUL() ) dump('request URL = ' + url + '?' + this.param_string + '\n');
217
218         try {
219
220                 if(blocking) this.xmlhttp.open(this.type, url, false);
221                 else this.xmlhttp.open(this.type, url, true);
222                 
223         } catch(E) {
224                 alert("Fatal error opening XMLHTTPRequest for URL:\n" + url + '\n' + E);
225                 return;
226         }
227
228         if( this.type == 'POST' ) {
229                 data = this.param_string;
230                 this.xmlhttp.setRequestHeader('Content-Type',
231                                 'application/x-www-form-urlencoded');
232         }
233
234         try {
235                 var auth;
236                 try { auth = cookieManager.read(COOKIE_SES) } catch(ee) {}
237                 if( isXUL() ) auth = fetchXULStash().session.key;
238                 if( auth ) 
239                         this.xmlhttp.setRequestHeader('X-OILS-Authtoken', auth);
240
241         } catch(e) {}
242
243         if(data && data.match(/param=undefined/)) {
244                 /* we get a bogus param .. replace with NULL */
245                 try{dump('!+! UNDEFINED PARAM IN QUERY: ' + this.service + ' : ' + this.method+'\n');}catch(r){}
246                 data = data.replace(/param=undefined/g,'param=null');
247         }
248
249
250     this.sendTime = new Date().getTime();
251         try{ this.xmlhttp.send( data ); } catch(e){}
252
253         return this;
254 }
255
256 /* returns the actual response text from the request */
257 RemoteRequest.prototype.getText = function() {
258         return this.xmlhttp.responseText;
259 }
260
261 RemoteRequest.prototype.isReady = function() {
262         return this.xmlhttp.readyState == 4;
263 }
264
265
266 /* returns the JSON->js result object  */
267 RemoteRequest.prototype.getResultObject = function() {
268
269         if(this.cancelled) return null;
270         if(!this.xmlhttp) return null;
271
272         var failed = false;
273         var status = null;
274         this.event(null);
275
276         /*
277         try {
278                 dump(this.url + '?' + this.param_string + '\n' +
279                         'Returned with \n\tstatus = ' + this.xmlhttp.status + 
280                         '\n\tpayload= ' + this.xmlhttp.responseText + '\n');
281         } catch(e) {}
282         */
283
284         try {
285                 status = this.xmlhttp.status;
286                 if( status != 200 ) failed = true;
287         } catch(e) { failed = true; }
288
289         if( failed ) {
290                 if(!status) status = '<unknown>';
291                 try{dump('! NETWORK FAILURE.  HTTP STATUS = ' +status+'\n'+this.param_string+'\n');}catch(e){}
292                 if(isXUL()) 
293                         throw new NetworkFailure(status, this.param_string);
294                 else return null;
295         }
296
297         var text = this.xmlhttp.responseText;
298
299         //try{if(getDebug()) _debug('response: ' + text + '\n')}catch(e){}
300
301         if(text == "" || text == " " || text == null) {
302                 try { dump('dbg: Request returned no text!\n'); } catch(E) {}
303                 if(isXUL()) 
304                         throw new NetworkFailure(status, this.param_string);
305                 return null;
306         }
307
308         var obj = JSON2js(text);
309         if(!obj) return null;
310
311         if( obj.status != 200 ) {
312
313                 var str = 'A server error occurred. Debug information follows: ' +
314                                         '\ncode = '             + obj.status + 
315                                         '\ndebug: '             + obj.debug + 
316                                         '\npayload: '   + js2JSON(obj.payload); 
317
318                 if(isXUL()) {
319                         dump(str);
320                         throw obj;
321
322                 } else {
323                         _debug(str);
324                         throw str;
325                 }
326         }
327
328         var payload = obj.payload;
329         if(!payload || payload.length == 0) return null;
330         payload = (payload.length == 1) ? payload[0] : payload;
331
332         if(!isXUL()) {
333                 if( checkILSEvent(payload) ) {
334                         this.event(payload);
335                         if( this.alertEvent ) {
336                                 alertILSEvent(payload);
337                                 return null;
338                         }
339                 } 
340         }
341
342         return payload;
343 }
344
345 /* adds a new parameter to the request */
346 RemoteRequest.prototype.addParam = function(param) {
347         var string = encodeURIComponent(js2JSON(param));
348         this.param_string += "&param=" + string;
349 }
350
351 function fetchXULStash() {
352         if( isXUL() ) {
353                 try {
354                         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
355                         var __OILS = new Components.Constructor("@mozilla.org/openils_data_cache;1", "nsIOpenILS");
356                         var data_cache = new __OILS( );
357                         return data_cache.wrappedJSObject.OpenILS.prototype.data;
358         
359                 } catch(E) {
360                         _debug('Error in OpenILS.data._debug_stash(): ' + js2JSON(E) );
361                 }
362         }
363         return {};
364 }
365
366