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 (f) { // Setup a self-destroying observer on the pending request to handle this request
69 obj.error.sdump('D_CACHE','Cached request pending, adding watch to handle current asynchronous request. key = \n' + key + '\n');
70 var id = data.observers.add('cached_request.'+key+'.status',function(p,o,n) {
71 obj.error.sdump('D_OBSERVERS','Entering watch function for key = \n' + key + '\np = ' + p + '\no = ' + js2JSON(o) + '\nn = ' + js2JSON(n) + '\nx = ' + js2JSON(x) + '\n');
72 if (n == 'complete') {
73 obj.error.sdump('D_CACHE','Cached request completed for key = \n' + key + '\nNow calling a previous async request watching this one.\n');
74 f( { 'getResultObject' : function() { return JSON2js( js2JSON( x.request ) ); } } );
75 setTimeout( function() { try { data.observers.remove(id); } catch(E) { alert(E); } }, 0 );
82 obj.error.sdump('D_CACHE','Pending request and synchronous request collision with key = \n' + key + '\nFalling through...\n');
86 if ( Number( new Date() ) < x.expire_time ) {
88 obj.error.sdump('D_CACHE','Cached request found completed, handling asynchronous request now. key = \n' + key + '\n');
89 f( { 'getResultObject' : function() { return JSON2js( js2JSON( x.request ) ); } } );
92 obj.error.sdump('D_CACHE','Cached request found completed, key = \n' + key + '\nreturning value =\n' + x.request + '\n');
93 return JSON2js( js2JSON( x.request ) ); // FIXME -- cloning the object is a workaround, otherwise instanceOf somehow silently fails
96 obj.error.sdump('D_CACHE','Cached request found completed, however, it has expired. key = \n' + key + '\nFalling through...\n');
101 obj.error.sdump('D_CACHE','Cached request not found for key = \n' + key + '\n');
105 var request = this._request(app,name,params,f,override_params,_params);
107 return this.get_result(request);
117 '_request' : function (app,name,params,f,override_params,_params) {
120 var sparams = js2JSON(params);
121 obj.error.sdump('D_SES','request '+app+' '+name+' '+obj.error.pretty_print(sparams.slice(1,sparams.length-1))+
122 '\noverride_params = ' + override_params + '\n_params = ' + _params +
123 '\nResult #' + (++obj.link_id) + ( f ? ' asynced' : ' synced' ) );
125 var key; var x; var data;
126 if (_params && obj.is_cacheable(_params.method_id)) {
127 JSAN.use('OpenILS.data'); data = new OpenILS.data(); data.init({'via':'stash'});
128 key = (app + '+' + name + '+' + js2JSON(params)).replace(/\./g,'_');
129 data.cached_request[key] = { 'test' : 'test', 'status' : 'pending', 'status_time' : Number(new Date()) };
130 data.stash('cached_request');
131 x = data.cached_request[key];
132 obj.error.sdump('D_CACHE','Current request is cacheable, setting pending status for key = \n' + key + '\nUpdating cache with ' + js2JSON(x) + '\n');
135 var request = new RemoteRequest( app, name );
136 if (_params && _params.secure) {
137 request.setSecure(true);
139 request.setSecure(false);
141 for(var index in params) {
142 request.addParam(params[index]);
146 request.setCompleteCallback(
149 var json_string = js2JSON(obj.get_result(req));
150 obj.error.sdump('D_SES_RESULT','asynced result #'
151 + obj.link_id + '\n\n'
152 + (json_string.length > 80 ? obj.error.pretty_print(json_string) : json_string)
153 + '\n\nOriginal Request:\n\n'
154 + 'request '+app+' '+name+' '+ sparams.slice(1,sparams.length-1));
155 req = obj.rerequest_on_session_timeout(app,name,params,req,override_params,_params);
156 req = obj.rerequest_on_perm_failure(app,name,params,req,override_params,_params);
157 if (override_params) {
158 req = obj.rerequest_on_override(app,name,params,req,override_params,_params);
160 req = obj.check_for_offline(app,name,params,req,override_params,_params);
161 if (_params && obj.is_cacheable(_params.method_id)) {
162 x.request = obj.get_result(req);
163 x.status = 'complete'; x.status_time = Number(new Date()); x.expire_time = Number(x.status_time) + api[_params.method_id].ttl;
164 data.stash('cached_request');
165 obj.error.sdump('D_CACHE','Previously pending cached request is now complete for key = \n' + key + '\nUpdating cache with ' + js2JSON(x) + '\n');
168 obj.NETWORK_FAILURE = null;
172 E.textcode = 'Server/Method Error';
174 f( { 'getResultObject' : function() { return E; } } );
190 var result = obj.get_result(request);
191 var json_string = js2JSON(result);
192 this.error.sdump('D_SES_RESULT','synced result #'
193 + obj.link_id + '\n\n' + ( json_string.length > 80 ? obj.error.pretty_print(json_string) : json_string )
194 + '\n\nOriginal Request:\n\n'
195 + 'request '+app+' '+name+' '+ sparams.slice(1,sparams.length-1));
196 request = obj.rerequest_on_session_timeout(app,name,params,request,override_params,_params);
197 request = obj.rerequest_on_perm_failure(app,name,params,request,override_params,_params);
198 if (override_params) {
199 request = obj.rerequest_on_override(app,name,params,request,override_params,_params);
201 request = obj.check_for_offline(app,name,params,request,override_params,_params);
202 obj.NETWORK_FAILURE = null;
203 if (_params && obj.is_cacheable(_params.method_id)) {
205 x.status = 'complete'; x.status_time = Number(new Date()); x.expire_time = Number(x.status_time) + api[_params.method_id].ttl;
206 data.stash('cached_request');
207 obj.error.sdump('D_CACHE','Previously pending cached request is now complete for key = \n' + key + '\nUpdating cache with ' + js2JSON(x) + '\n');
214 if (instanceOf(E,perm_ex)) {
215 alert('in util.network, _request : permission exception: ' + js2JSON(E));
221 'check_for_offline' : function (app,name,params,req,override_params,_params) {
223 var result = obj.get_result(req);
224 if (result != null) return req;
226 JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
235 if (data.proceed_offline) {
241 var network_failure_string;
242 var network_failure_status_string;
245 try { network_failure_string = String( obj.NETWORK_FAILURE ); } catch(E) { network_failure_string = E; }
246 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); }
248 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; }
250 try { obj.error.sdump('D_SES_ERROR',msg); } catch(E) { alert(E); }
252 r = obj.error.yns_alert(msg,'Network Failure','Retry Network','Ignore Errors',null,'Check here to confirm this message');
254 data.proceed_offline = true; data.stash('proceed_offline');
255 dump('Remembering proceed_offline for 200000 ms.\n');
258 data.proceed_offline = false; data.stash('proceed_offline');
259 dump('Setting proceed_offline back to false.\n');
265 dump( r == 0 ? 'Retry Network\n' : 'Ignore Errors\n' );
269 req = obj._request(app,name,params,null,override_params,_params);
270 if (obj.get_result(req)) proceed = true; /* daily WTF, why am I even doing this? :) */
274 return { 'getResultObject' : function() { return { 'ilsevent' : -1, 'textcode' : 'Network/Server Problem' }; } };
280 'reset_titlebars' : function(data) {
282 data.stash_retrieve();
284 JSAN.use('util.window'); var win = new util.window();
285 var windowManager = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService();
286 var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
287 var enumerator = windowManagerInterface.getEnumerator(null);
289 var w; // set title on all appshell windows
290 while ( w = enumerator.getNext() ) {
291 if (w.document.title.match(/^\d/)) {
293 win.appshell_name_increment()
294 + ': ' + data.list.au[0].usrname()
295 + '@' + data.ws_name;
296 + '.' + data.server_unadorned
300 obj.error.standard_unexpected_error_alert('Error setting window titles to match new login',E);
304 'get_new_session' : function(name,xulG,text) {
308 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
309 var url = urls.XUL_AUTH_SIMPLE;
310 if (typeof xulG != 'undefined' && typeof xulG.url_prefix == 'function') url = xulG.url_prefix( url );
313 + '?login_type=staff'
314 + '&desc_brief=' + window.escape( text ? 'Session Expired' : 'Operator Change' )
315 + '&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.'),
316 'simple_auth' + (new Date()).toString(),
317 'chrome,resizable,modal,width=700,height=500'
319 JSAN.use('OpenILS.data');
320 var data = new OpenILS.data(); data.init({'via':'stash'});
321 if (typeof data.temporary_session != 'undefined' && data.temporary_session != '') {
322 data.session.key = data.temporary_session.key;
323 data.session.authtime = data.temporary_session.authtime;
324 data.stash('session');
325 if (! data.list.au ) data.list.au = [];
326 data.list.au[0] = JSON2js(data.temporary_session.usr);
328 obj.reset_titlebars(data);
334 obj.error.standard_unexpected_error_alert('util.network.get_new_session',E);
338 'rerequest_on_session_timeout' : function(app,name,params,req,override_params,_params) {
341 var robj = obj.get_result(req);
342 if (robj != null && robj.ilsevent && robj.ilsevent == 1001) {
344 if (obj.get_new_session(name,undefined,true)) {
345 JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
346 params[0] = data.session.key;
347 req = obj._request(app,name,params,null,override_params,_params);
351 this.error.standard_unexpected_error_alert('rerequest_on_session_timeout',E);
356 'rerequest_on_perm_failure' : function(app,name,params,req,override_params,_params) {
359 var robj = obj.get_result(req);
360 if (robj != null && robj.ilsevent && robj.ilsevent == 5000) {
361 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
362 if (location.href.match(/^chrome/)) {
363 //alert('Permission denied.');
368 + '&desc_brief=' + window.escape('Permission Denied: ' + robj.ilsperm)
369 + '&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),
370 'simple_auth' + (new Date()).toString(),
371 'chrome,resizable,modal,width=700,height=500'
373 JSAN.use('OpenILS.data');
374 var data = new OpenILS.data(); data.init({'via':'stash'});
375 if (typeof data.temporary_session != 'undefined' && data.temporary_session != '') {
376 params[0] = data.temporary_session.key;
377 req = obj._request(app,name,params,null,override_params,_params);
382 this.error.sdump('D_ERROR',E);
387 'rerequest_on_override' : function (app,name,params,req,override_params,_params) {
390 if (!override_params.text) override_params.text = {};
391 function override(r) {
393 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
395 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">' +
396 '<groupbox><caption label="Exceptions"/>' +
397 '<grid><columns><column/><column/></columns><rows>';
398 for (var i = 0; i < r.length; i++) {
399 var t1 = String(r[i].ilsevent).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
400 var t2 = String(r[i].textcode).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
401 var t3 = String((override_params.text[r[i].ilsevent] ? override_params.text[r[i].ilsevent](r[i]) : '')).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
402 var t4 = String(r[i].desc).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
404 '<description style="color: red" tooltiptext="' + t1 + '">' + t2 + '</description>' +
405 '<description>' + t3 + '</description>' +
406 '</row><row>' + '<description>' + t4 + '</description>' + '</row>';
408 xml += '</rows></grid></groupbox><groupbox><caption label="Override"/><hbox>' +
409 '<description>Force this action?</description>' +
410 '<button accesskey="N" label="No" name="fancy_cancel"/>' +
411 '<button id="override" accesskey="Y" label="Yes" name="fancy_submit" value="override"/></hbox></groupbox></vbox>';
412 JSAN.use('OpenILS.data');
413 var data = new OpenILS.data(); data.init({'via':'stash'});
414 data.temp_override_xml = xml; data.stash('temp_override_xml');
416 urls.XUL_FANCY_PROMPT
417 + '?xml_in_stash=temp_override_xml'
418 + '&title=' + window.escape(override_params.title),
419 'fancy_prompt', 'chrome,resizable,modal,width=700,height=500'
421 data.init({'via':'stash'});
422 if (data.fancy_prompt_data != '') {
423 req = obj._request(app,name + '.override',params);
427 alert('in util.network, rerequest_on_override, override:' + E);
431 var result = obj.get_result(req);
432 if (!result) return req;
434 if ( (typeof result.ilsevent != 'undefined') && (override_params.overridable_events.indexOf(result.ilsevent) != -1) ) {
435 req = override([result]);
437 var found_good = false; var found_bad = false;
438 for (var i = 0; i < result.length; i++) {
439 if ( (result[i].ilsevent != 'undefined') && (override_params.overridable_events.indexOf(result[i].ilsevent) != -1) ) {
445 if (found_good && (!found_bad)) req = override(result);
458 function sample_callback(request) {
459 var result = request.getResultObject();
463 dump('exiting util/network.js\n');