1 dump('entering util/network.js\n');
3 if (typeof util == 'undefined') util = {};
4 util.network = function () {
6 JSAN.use('util.error'); this.error = new util.error();
7 JSAN.use('util.sound'); this.sound = new util.sound();
12 util.network.prototype = {
16 'NETWORK_FAILURE' : null,
18 'simple_request' : function(method_id,params,f,override_params) {
19 if (typeof api[method_id] == 'undefined') throw( 'Method not found for ' + method_id );
20 var secure = true; if (typeof api[method_id].secure != 'undefined') secure = api[method_id].secure;
21 return this.request(api[method_id].app,api[method_id].method,params,f,override_params,{ 'secure' : secure, 'method_id' : method_id });
24 'cached_request' : function(method_id,params,f,override_params) {
25 if (typeof api[method_id] == 'undefined') throw( 'Method not found for ' + method_id );
26 var secure = true; if (typeof api[method_id].secure != 'undefined') secure = api[method_id].secure;
27 return this.request(api[method_id].app,api[method_id].method,params,f,override_params,{ 'secure' : secure, 'want_cached' : true, 'method_id' : method_id });
30 'get_result' : function (req) {
34 result = req.getResultObject();
37 if (instanceOf(E, NetworkFailure)) {
38 obj.NETWORK_FAILURE = E;
40 try { obj.NETWORK_FAILURE = js2JSON(E); } catch(F) { dump(F + '\n'); obj.NETWORK_FAILURE = E; };
43 obj.NETWORK_FAILURE = 'Unknown status';
50 'is_cacheable' : function(method_id) {
51 return (api[method_id].cacheable);
54 'request' : function (app,name,params,f,override_params,_params) {
60 if (_params && _params.want_cached) if ( this.is_cacheable(_params.method_id) ) {
61 JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
62 var key = (app + '+' + name + '+' + js2JSON(params)).replace(/\./g,'_');
63 var x = data.cached_request[key];
65 obj.error.sdump('D_CACHE','Cached request found for key = \n' + key + '\n' + js2JSON(x) + '\n');
68 if ( Number(new Date()) - Number(x.status_time) > 60000 ) break; // if pending request is taking too long
69 if (f) { // Setup a self-destroying observer on the pending request to handle this request
70 obj.error.sdump('D_CACHE','Cached request pending, adding watch to handle current asynchronous request. key = \n' + key + '\n');
71 var id = data.observers.add('cached_request.'+key+'.status',function(p,o,n) {
72 obj.error.sdump('D_OBSERVERS','Entering watch function for key = \n' + key + '\np = ' + p + '\no = ' + js2JSON(o) + '\nn = ' + js2JSON(n) + '\nx = ' + js2JSON(x) + '\n');
73 if (n == 'complete') {
74 obj.error.sdump('D_CACHE','Cached request completed for key = \n' + key + '\nNow calling a previous async request watching this one.\n');
75 f( { 'getResultObject' : function() { return JSON2js( js2JSON( x.request ) ); } } );
76 setTimeout( function() { try { data.observers.remove(id); } catch(E) { alert(E); } }, 0 );
83 obj.error.sdump('D_CACHE','Pending request and synchronous request collision with key = \n' + key + '\nFalling through...\n');
87 if ( Number( new Date() ) < x.expire_time ) {
89 obj.error.sdump('D_CACHE','Cached request found completed, handling asynchronous request now. key = \n' + key + '\n');
90 f( { 'getResultObject' : function() { return JSON2js( js2JSON( x.request ) ); } } );
93 obj.error.sdump('D_CACHE','Cached request found completed, key = \n' + key + '\nreturning value =\n' + x.request + '\n');
94 return JSON2js( js2JSON( x.request ) ); // FIXME -- cloning the object is a workaround, otherwise instanceOf somehow silently fails
97 obj.error.sdump('D_CACHE','Cached request found completed, however, it has expired. key = \n' + key + '\nFalling through...\n');
102 obj.error.sdump('D_CACHE','Cached request not found for key = \n' + key + '\n');
106 var request = this._request(app,name,params,f,override_params,_params);
108 return this.get_result(request);
118 '_request' : function (app,name,params,f,override_params,_params) {
121 var sparams = js2JSON(params);
122 obj.error.sdump('D_SES','request '+app+' '+name+' '+obj.error.pretty_print(sparams.slice(1,sparams.length-1))+
123 '\noverride_params = ' + override_params + '\n_params = ' + _params +
124 '\nResult #' + (++obj.link_id) + ( f ? ' asynced' : ' synced' ) );
126 var key; var x; var data;
127 if (_params && obj.is_cacheable(_params.method_id)) {
128 JSAN.use('OpenILS.data'); data = new OpenILS.data(); data.init({'via':'stash'});
129 key = (app + '+' + name + '+' + js2JSON(params)).replace(/\./g,'_');
130 data.cached_request[key] = { 'test' : 'test', 'status' : 'pending', 'status_time' : Number(new Date()) };
131 data.stash('cached_request');
132 x = data.cached_request[key];
133 obj.error.sdump('D_CACHE','Current request is cacheable, setting pending status for key = \n' + key + '\nUpdating cache with ' + js2JSON(x) + '\n');
136 var request = new RemoteRequest( app, name );
137 if (_params && _params.secure) {
138 request.setSecure(true);
140 request.setSecure(false);
142 for(var index in params) {
143 request.addParam(params[index]);
147 request.setCompleteCallback(
150 var json_string = js2JSON(obj.get_result(req));
151 obj.error.sdump('D_SES_RESULT','asynced result #'
152 + obj.link_id + '\n\n'
153 + (json_string.length > 80 ? obj.error.pretty_print(json_string) : json_string)
154 + '\n\nOriginal Request:\n\n'
155 + 'request '+app+' '+name+' '+ sparams.slice(1,sparams.length-1));
156 req = obj.rerequest_on_session_timeout(app,name,params,req,override_params,_params);
157 req = obj.rerequest_on_perm_failure(app,name,params,req,override_params,_params);
158 if (override_params) {
159 req = obj.rerequest_on_override(app,name,params,req,override_params,_params);
161 req = obj.check_for_offline(app,name,params,req,override_params,_params);
162 if (_params && obj.is_cacheable(_params.method_id)) {
163 x.request = obj.get_result(req);
164 x.status = 'complete'; x.status_time = Number(new Date()); x.expire_time = Number(x.status_time) + api[_params.method_id].ttl;
165 data.stash('cached_request');
166 obj.error.sdump('D_CACHE','Previously pending cached request is now complete for key = \n' + key + '\nUpdating cache with ' + js2JSON(x) + '\n');
169 obj.NETWORK_FAILURE = null;
173 E.textcode = 'Server/Method Error';
175 f( { 'getResultObject' : function() { return E; } } );
191 var result = obj.get_result(request);
192 var json_string = js2JSON(result);
193 this.error.sdump('D_SES_RESULT','synced result #'
194 + obj.link_id + '\n\n' + ( json_string.length > 80 ? obj.error.pretty_print(json_string) : json_string )
195 + '\n\nOriginal Request:\n\n'
196 + 'request '+app+' '+name+' '+ sparams.slice(1,sparams.length-1));
197 request = obj.rerequest_on_session_timeout(app,name,params,request,override_params,_params);
198 request = obj.rerequest_on_perm_failure(app,name,params,request,override_params,_params);
199 if (override_params) {
200 request = obj.rerequest_on_override(app,name,params,request,override_params,_params);
202 request = obj.check_for_offline(app,name,params,request,override_params,_params);
203 obj.NETWORK_FAILURE = null;
204 if (_params && obj.is_cacheable(_params.method_id)) {
206 x.status = 'complete'; x.status_time = Number(new Date()); x.expire_time = Number(x.status_time) + api[_params.method_id].ttl;
207 data.stash('cached_request');
208 obj.error.sdump('D_CACHE','Previously pending cached request is now complete for key = \n' + key + '\nUpdating cache with ' + js2JSON(x) + '\n');
215 if (instanceOf(E,perm_ex)) {
216 alert('in util.network, _request : permission exception: ' + js2JSON(E));
222 'check_for_offline' : function (app,name,params,req,override_params,_params) {
224 var result = obj.get_result(req);
225 if (result != null) return req;
227 JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
236 if (data.proceed_offline) {
242 var network_failure_string;
243 var network_failure_status_string;
246 try { network_failure_string = String( obj.NETWORK_FAILURE ); } catch(E) { network_failure_string = E; }
247 try { network_failure_status_string = typeof obj.NETWORK_FAILURE == 'object' && typeof obj.NETWORK_FAILURE != 'null' && typeof obj.NETWORK_FAILURE.status == 'function' ? obj.NETWORK_FAILURE.status() : ''; } catch(E) { network_failure_status_string = ''; obj.error.sdump('D_ERROR', 'setting network_failure_status_string: ' + E); }
249 try { msg = 'Network/server failure. Please check your Internet connection to ' + data.server_unadorned + ' and choose Retry Network. If you need to enter Offline Mode, choose Ignore Errors in this and subsequent dialogs. If you believe this error is due to a bug in Evergreen and not network problems, please contact your helpdesk or friendly Evergreen admins, and give them this information:\nmethod=' + name + '\nparams=' + js2JSON(params) + '\nTHROWN:\n' + network_failure_string + '\nSTATUS:\n' + network_failure_status_string; } catch(E) { msg = E; }
251 try { obj.error.sdump('D_SES_ERROR',msg); } catch(E) { alert(E); }
253 r = obj.error.yns_alert(msg,'Network Failure','Retry Network','Ignore Errors',null,'Check here to confirm this message');
255 data.proceed_offline = true; data.stash('proceed_offline');
256 dump('Remembering proceed_offline for 200000 ms.\n');
259 data.proceed_offline = false; data.stash('proceed_offline');
260 dump('Setting proceed_offline back to false.\n');
266 dump( r == 0 ? 'Retry Network\n' : 'Ignore Errors\n' );
270 req = obj._request(app,name,params,null,override_params,_params);
271 if (obj.get_result(req)) proceed = true; /* daily WTF, why am I even doing this? :) */
275 return { 'getResultObject' : function() { return { 'ilsevent' : -1, 'textcode' : 'Network/Server Problem' }; } };
281 'reset_titlebars' : function(data) {
283 data.stash_retrieve();
285 JSAN.use('util.window'); var win = new util.window();
286 var windowManager = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService();
287 var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
288 var enumerator = windowManagerInterface.getEnumerator(null);
290 var w; // set title on all appshell windows
291 while ( w = enumerator.getNext() ) {
292 if (w.document.title.match(/^\d/)) {
294 win.appshell_name_increment()
295 + ': ' + data.list.au[0].usrname()
296 + '@' + data.ws_name;
297 + '.' + data.server_unadorned
301 obj.error.standard_unexpected_error_alert('Error setting window titles to match new login',E);
305 'get_new_session' : function(name,xulG,text) {
309 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
310 var url = urls.XUL_AUTH_SIMPLE;
311 if (typeof xulG != 'undefined' && typeof xulG.url_prefix == 'function') url = xulG.url_prefix( url );
312 JSAN.use('util.window'); var win = new util.window();
313 var my_xulG = win.open(
315 //+ '?login_type=staff'
316 //+ '&desc_brief=' + window.escape( text ? 'Session Expired' : 'Operator Change' )
317 //+ '&desc_full=' + window.escape( text ? 'Please enter the credentials for a new login session.' : 'Please enter the credentials for the new login session. Note that the previous session is still active.'),
318 //'simple_auth' + (new Date()).toString(),
320 'chrome,resizable,modal,width=700,height=500',
322 'login_type' : 'staff',
323 'desc_brief' : text ? 'Session Expired' : 'Operator Change',
324 'desc_full' : text ? 'Please enter the credentials for a new login session.' : 'Please enter the credentials for the new login session. Note that the previous session is still active.',
325 //'simple_auth' : (new Date()).toString(),
328 JSAN.use('OpenILS.data');
329 var data = new OpenILS.data(); data.init({'via':'stash'});
330 if (typeof my_xulG.temporary_session != 'undefined' && my_xulG.temporary_session != '') {
331 data.session.key = my_xulG.temporary_session.key;
332 data.session.authtime = my_xulG.temporary_session.authtime;
333 data.stash('session');
334 if (! data.list.au ) data.list.au = [];
335 data.list.au[0] = JSON2js( my_xulG.temporary_session.usr );
337 obj.reset_titlebars(data);
339 } else { alert('here2'); }
343 obj.error.standard_unexpected_error_alert('util.network.get_new_session',E);
347 'rerequest_on_session_timeout' : function(app,name,params,req,override_params,_params) {
350 var robj = obj.get_result(req);
351 if (robj != null && robj.ilsevent && robj.ilsevent == 1001) {
353 if (obj.get_new_session(name,undefined,true)) {
354 JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
355 params[0] = data.session.key;
356 req = obj._request(app,name,params,null,override_params,_params);
360 this.error.standard_unexpected_error_alert('rerequest_on_session_timeout',E);
365 'rerequest_on_perm_failure' : function(app,name,params,req,override_params,_params) {
368 var robj = obj.get_result(req);
369 if (robj != null && robj.ilsevent && robj.ilsevent == 5000) {
370 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
371 if (location.href.match(/^chrome/)) {
372 //alert('Permission denied.');
374 JSAN.use('util.window'); var win = new util.window();
375 var my_xulG = win.open(
376 urls.XUL_AUTH_SIMPLE,
377 //+ '?login_type=temp'
378 //+ '&desc_brief=' + window.escape('Permission Denied: ' + robj.ilsperm)
379 //+ '&desc_full=' + window.escape('Another staff member with the above permission may authorize this specific action. Please notify your library administrator if you need this permission. If you feel you have received this exception in error, inform your friendly Evergreen developers of the above permission and this debug information: ' + name),
380 //'simple_auth' + (new Date()).toString(),
382 'chrome,resizable,modal,width=700,height=500',
384 'login_type' : 'temp',
385 'desc_brief' : 'Permission Denied: ' + robj.ilsperm,
386 'desc_full' : 'Another staff member with the above permission may authorize this specific action. Please notify your library administrator if you need this permission. If you feel you have received this exception in error, please inform your friendly Evergreen developers or helpdesk staff of the above permission and this debug information: ' + name,
387 //'simple_auth' : (new Date()).toString(),
390 JSAN.use('OpenILS.data');
391 //var data = new OpenILS.data(); data.init({'via':'stash'});
392 if (typeof my_xulG.temporary_session != 'undefined' && my_xulG.temporary_session != '') {
393 params[0] = my_xulG.temporary_session.key;
394 req = obj._request(app,name,params,null,override_params,_params);
399 this.error.sdump('D_ERROR',E);
404 'rerequest_on_override' : function (app,name,params,req,override_params,_params) {
407 if (!override_params.text) override_params.text = {};
408 function override(r) {
410 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
412 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">' +
413 '<groupbox><caption label="Exceptions"/>' +
414 '<grid><columns><column/><column/></columns><rows>';
415 for (var i = 0; i < r.length; i++) {
416 var t1 = String(r[i].ilsevent).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
417 var t2 = String(r[i].textcode).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
418 var t3 = String((override_params.text[r[i].ilsevent] ? override_params.text[r[i].ilsevent](r[i]) : '')).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
419 var t4 = String(r[i].desc).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
421 '<description style="color: red" tooltiptext="' + t1 + '">' + t2 + '</description>' +
422 '<description>' + t3 + '</description>' +
423 '</row><row>' + '<description>' + t4 + '</description>' + '</row>';
425 xml += '</rows></grid></groupbox><groupbox><caption label="Override"/><hbox>' +
426 '<description>Force this action?</description>' +
427 '<button accesskey="N" label="No" name="fancy_cancel"/>' +
428 '<button id="override" accesskey="Y" label="Yes" name="fancy_submit" value="override"/></hbox></groupbox></vbox>';
429 //JSAN.use('OpenILS.data');
430 //var data = new OpenILS.data(); data.init({'via':'stash'});
431 //data.temp_override_xml = xml; data.stash('temp_override_xml');
432 JSAN.use('util.window'); var win = new util.window();
433 var fancy_prompt_data = win.open(
434 urls.XUL_FANCY_PROMPT,
435 //+ '?xml_in_stash=temp_override_xml'
436 //+ '&title=' + window.escape(override_params.title),
437 'fancy_prompt', 'chrome,resizable,modal,width=700,height=500',
438 { 'xml' : xml, 'title' : override_params.title }
440 if (fancy_prompt_data.fancy_status == 'complete') {
441 req = obj._request(app,name + '.override',params);
445 alert('in util.network, rerequest_on_override, override:' + E);
449 var result = obj.get_result(req);
450 if (!result) return req;
452 if ( (typeof result.ilsevent != 'undefined') && (override_params.overridable_events.indexOf(result.ilsevent) != -1) ) {
453 req = override([result]);
455 var found_good = false; var found_bad = false;
456 for (var i = 0; i < result.length; i++) {
457 if ( (result[i].ilsevent != 'undefined') && (override_params.overridable_events.indexOf(result[i].ilsevent) != -1) ) {
463 if (found_good && (!found_bad)) req = override(result);
476 function sample_callback(request) {
477 var result = request.getResultObject();
481 dump('exiting util/network.js\n');