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