]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/chrome/content/util/network.js
don't let util.error create sound objects (trying to reduce proliferation of such...
[working/Evergreen.git] / Open-ILS / xul / staff_client / chrome / content / util / network.js
1 dump('entering util/network.js\n');
2 // vim:noet:sw=4:ts=4:
3
4 var offlineStrings;
5
6 if (typeof util == 'undefined') util = {};
7 util.network = function () {
8
9     try {
10
11         JSAN.use('util.error'); this.error = new util.error();
12         JSAN.use('util.sound'); this.sound = new util.sound();
13
14         offlineStrings = document.getElementById('offlineStrings');
15
16     } catch(E) {
17         alert('error in util.network constructor: ' + E);
18         throw(E);
19     }
20
21     return this;
22 };
23
24 util.network.prototype = {
25
26     'link_id' : 0,
27
28     'network_timeout' : 55, /* seconds */
29
30     'NETWORK_FAILURE' : null,
31
32     'simple_request' : function(method_id,params,f,override_params) {
33         //var obj = this;
34         //var sparams = js2JSON(params);
35         //obj.error.sdump('D_SES','simple_request '+ method_id +' '+obj.error.pretty_print(sparams.slice(1,sparams.length-1))+
36         //    '\noverride_params = ' + override_params + '\n');
37         if (typeof api[method_id] == 'undefined') {
38             throw( offlineStrings.getFormattedString('network.method_not_found.error', [method_id]) );
39         }
40         var secure = true; if (typeof api[method_id].secure != 'undefined') secure = api[method_id].secure;
41         return this.request(api[method_id].app,api[method_id].method,params,f,override_params,{ 'secure' : secure, 'method_id' : method_id });
42     },
43
44     'get_result' : function (req) {
45         var obj = this;
46         var result;
47         var fake_ilsevent_for_network_errors = { 'ilsevent' : -1, 'textcode' : offlineStrings.getString('network.server_or_method.error') }; 
48         try {
49             if (req.cancelled) {
50                 result = fake_ilsevent_for_network_errors;
51             } else {
52                 result = req.getResultObject();    
53             }
54         } catch(E) {
55             try {
56                 if (instanceOf(E, NetworkFailure)) {
57                     obj.NETWORK_FAILURE = E;
58                 } else {
59                     try { obj.NETWORK_FAILURE = js2JSON(E); } catch(F) { dump(F + '\n'); obj.NETWORK_FAILURE = E; };
60                 }
61             } catch(I) { 
62                 obj.NETWORK_FAILURE = offlineStrings.getString('network.unknown_status');
63             }
64             result = fake_ilsevent_for_network_errors;
65         }
66         return result;
67     },
68
69     'request' : function (app,name,params,f,override_params,_params) {
70
71         var obj = this;
72         
73         //var sparams = js2JSON(params);
74         //obj.error.sdump('D_SES','request '+ app + ' ' + name +' '+obj.error.pretty_print(sparams.slice(1,sparams.length-1))+
75         //    '\noverride_params = ' + override_params + '\n_params = ' + _params + '\n');
76
77         try { 
78
79             var request =  this._request(app,name,params,f,override_params,_params);
80             if (request) {
81                 return this.get_result(request);
82             } else {
83                 return null;
84             }
85     
86         } catch(E) {
87             alert('1: ' + E); 
88         }
89     },
90
91     '_request' : function (app,name,params,f,override_params,_params) {
92         var obj = this;
93         try {
94             var sparams = js2JSON(params);
95             obj.error.sdump('D_SES','_request '+app+' '+name+' '+obj.error.pretty_print(sparams.slice(1,sparams.length-1))+
96                 '\noverride_params = ' + override_params + '\n_params = ' + _params +
97                 '\nResult #' + (++obj.link_id) + ( f ? ' asynced' : ' synced' ) +
98                 '\nlocation.href = ' + location.href );
99
100             if (document.getElementById('network_progress')) {
101                 if (g && g.menu && g.menu.network_meter && typeof g.menu.network_meter.inc == 'function') g.menu.network_meter.inc(app,name);
102             } else if (typeof xulG != 'undefined') {
103                 if (xulG && xulG.network_meter && typeof xulG.network_meter.inc == 'function') xulG.network_meter.inc(app,name);
104             }
105
106             var request = new RemoteRequest( app, name );
107             if (_params && _params.secure) {
108                 request.setSecure(true);
109             } else {
110                 request.setSecure(false);
111             }
112             for(var index in params) {
113                 request.addParam(params[index]);
114             }
115
116             var start_timer = (new Date).getTime();    
117             if (f)  {
118                 request.setCompleteCallback(
119                     function(req) {
120                         try {
121                             var duration = ( (new Date).getTime() - start_timer )/1000;
122                             if ( obj.get_result(req) == null && duration > obj.network_timeout ) req.cancelled = true;
123
124                             if (document.getElementById('network_progress')) {
125                                 if (g && g.menu && g.menu.network_meter && typeof g.menu.network_meter.dec == 'function') g.menu.network_meter.dec(app,name);
126                             } else if (typeof xulG != 'undefined') {
127                                 if (xulG && xulG.network_meter && typeof xulG.network_meter.dec == 'function') xulG.network_meter.dec(app,name);
128                             }
129
130                             var json_string = js2JSON(obj.get_result(req));
131                             obj.error.sdump('D_SES_RESULT','asynced result #' 
132                                 + obj.link_id + '\n\n' 
133                                 + (json_string.length > 80 ? obj.error.pretty_print(json_string) : json_string) 
134                                 + '\n\nOriginal Request:\n\n' 
135                                 + 'request '+app+' '+name+' '+ sparams.slice(1,sparams.length-1));
136                             obj.play_sounds( request );
137                             req = obj.rerequest_on_session_timeout(app,name,params,req,override_params,_params);
138                             req = obj.rerequest_on_perm_failure(app,name,params,req,override_params,_params);
139                             if (override_params) {
140                                 req = obj.rerequest_on_override(app,name,params,req,override_params,_params);
141                             }
142                             req = obj.check_for_offline(app,name,params,req,override_params,_params);
143                             f(req);
144                             obj.NETWORK_FAILURE = null;
145                         } catch(E) {
146                             try {
147                                 E.ilsevent = -2;
148                                 E.textcode = offlineStrings.getString('network.server_or_method.error');
149                             } catch(F) {}
150                             f( { 'getResultObject' : function() { return E; } } );
151                         }
152                     }
153                 );
154                 try {
155                     request.send(false);
156                 } catch(E) {
157                     throw(E);
158                 }
159                 return null;
160             } else {
161                 try {
162                     request.send(true);
163                     var duration = ( (new Date).getTime() - start_timer )/1000;
164                     if ( obj.get_result(request) == null && duration > obj.network_timeout ) request.cancelled = true;
165
166                     if (document.getElementById('network_progress')) {
167                         if (g && g.menu && g.menu.network_meter && typeof g.menu.network_meter.dec == 'function') g.menu.network_meter.dec(app,name);
168                     } else if (typeof xulG != 'undefined') {
169                         if (xulG && xulG.network_meter && typeof xulG.network_meter.dec == 'function') xulG.network_meter.dec(app,name);
170                     }
171
172                 } catch(E) {
173                     throw(E);
174                 }
175                 var result = obj.get_result(request);
176                 var json_string = js2JSON(result);
177                 this.error.sdump('D_SES_RESULT','synced result #' 
178                     + obj.link_id + '\n\n' + ( json_string.length > 80 ? obj.error.pretty_print(json_string) : json_string ) 
179                     + '\n\nOriginal Request:\n\n' 
180                     + 'request '+app+' '+name+' '+ sparams.slice(1,sparams.length-1));
181                 obj.play_sounds( request );
182                 request = obj.rerequest_on_session_timeout(app,name,params,request,override_params,_params);
183                 request = obj.rerequest_on_perm_failure(app,name,params,request,override_params,_params);
184                 if (override_params) {
185                     request = obj.rerequest_on_override(app,name,params,request,override_params,_params);
186                 }
187                 request = obj.check_for_offline(app,name,params,request,override_params,_params);
188                 obj.NETWORK_FAILURE = null;
189                 return request;
190             }
191
192         } catch(E) {
193             alert('2: ' + E);
194             if (instanceOf(E,perm_ex)) {
195                 alert('in util.network, _request : permission exception: ' + js2JSON(E));
196             }
197             throw(E);
198         }
199     },
200
201     'check_for_offline' : function (app,name,params,req,override_params,_params) {
202         try {
203             var obj = this;
204             var result = obj.get_result(req);
205             if (result == null) return req;
206             if (typeof result.ilsevent == 'undefined') return req;
207             if (result.ilsevent != -1) return req;
208
209             JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
210             var proceed = true;
211
212             while(proceed) {
213
214                 proceed = false;
215
216                 var r;
217
218                 if (data.proceed_offline) {
219
220                     r = 1;
221
222                 } else {
223
224                     var network_failure_string;
225                     var network_failure_status_string;
226                     var msg;
227
228                     try { network_failure_string = String( obj.NETWORK_FAILURE ); } catch(E) { network_failure_string = E; }
229                     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); }
230                     
231                     try { msg = offlineStrings.getFormattedString('network.server.failure.exception', [data.server_unadorned]) + '\n' +
232                                 offlineStrings.getFormattedString('network.server.method', [name]) + '\n' + 
233                                 offlineStrings.getFormattedString('network.server.params', [js2JSON(params)]) + '\n' + 
234                                 offlineStrings.getString('network.server.thrown_label') + '\n' + network_failure_string + '\n' + 
235                                 offlineStrings.getString('network.server.status_label') + '\n' + network_failure_status_string;
236                     } catch(E) { msg = E; }
237
238                     try { obj.error.sdump('D_SES_ERROR',msg); } catch(E) { alert('3: ' + E); }
239
240                     r = obj.error.yns_alert(
241                         msg,
242                         offlineStrings.getString('network.network_failure'),
243                         offlineStrings.getString('network.retry_network'),
244                         offlineStrings.getString('network.ignore_errors'),
245                         null,
246                         offlineStrings.getString('common.confirm')
247                     );
248                     if (r == 1) {
249                         data.proceed_offline = true; data.stash('proceed_offline');
250                         dump('Remembering proceed_offline for 200000 ms.\n');
251                         setTimeout(
252                             function() {
253                                 data.proceed_offline = false; data.stash('proceed_offline');
254                                 dump('Setting proceed_offline back to false.\n');
255                             }, 200000
256                         );
257                     }
258                 }
259
260                 dump( r == 0 ? 'Retry Network\n' : 'Ignore Errors\n' );
261
262                 switch(r) {
263                     case 0: 
264                         req = obj._request(app,name,params,null,override_params,_params);
265                         if (obj.get_result(req)) proceed = true; /* daily WTF, why am I even doing this? :) */
266                         return req;
267                     break;
268
269                     case 1: 
270                         return req;
271                     break;
272                 }
273             }
274         } catch(E) {
275             alert('4: ' + E);
276             throw(E);
277         }
278     },
279
280     'reset_titlebars' : function(data) {
281         var obj = this;
282         data.stash_retrieve();
283         try {
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);
288
289             var w; // set title on all appshell windows
290             while ( w = enumerator.getNext() ) {
291                 if (w.document.title.match(/^\d/)) {
292                     w.document.title = 
293                         win.appshell_name_increment() 
294                         + ': ' + data.list.au[0].usrname() 
295                         + '@' + data.ws_name;
296                         + '.' + data.server_unadorned 
297                 }
298             }
299         } catch(E) {
300             obj.error.standard_unexpected_error_alert(offlineStrings.getString('network.window_title.error'),E);
301         }
302     },
303
304     'get_new_session' : function(name,xulG,text) {
305         var obj = this;
306         try {
307
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 );
311         JSAN.use('util.window'); var win = new util.window();
312         var my_xulG = win.open(
313             url,
314             //+ '?login_type=staff'
315             //+ '&desc_brief=' + window.escape( text ? 'Session Expired' : 'Operator Change' )
316             //+ '&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.'),
317             //'simple_auth' + (new Date()).toString(),
318             offlineStrings.getString('network.new_session.authorize'),
319             'chrome,resizable,modal,width=700,height=500',
320             {
321                 'login_type' : 'staff',
322                 'desc_brief' : text ? offlineStrings.getString('network.new_session.expired') : offlineStrings.getString('network.new_session.operator_change'),
323                 'desc_full' : text ? offlineStrings.getString('network.new_session.expired.prompt') : offlineStrings.getString('network.new_session.operator_change.prompt')
324                 //'simple_auth' : (new Date()).toString(),
325             }
326         );
327         JSAN.use('OpenILS.data');
328         var data = new OpenILS.data(); data.init({'via':'stash'});
329         if (typeof data.temporary_session != 'undefined' && data.temporary_session != '') {
330             data.session.key = data.temporary_session.key; 
331             data.session.authtime = data.temporary_session.authtime; 
332             data.stash('session');
333             try {
334                 var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
335                 var cookieUri = ios.newURI("http://" + data.server_unadorned, null, null);
336                 var cookieUriSSL = ios.newURI("https://" + data.server_unadorned, null, null);
337                 var cookieSvc = Components.classes["@mozilla.org/cookieService;1"].getService(Components.interfaces.nsICookieService);
338
339                 cookieSvc.setCookieString(cookieUri, null, "ses="+data.session.key, null);
340                 cookieSvc.setCookieString(cookieUriSSL, null, "ses="+data.session.key, null);
341
342             } catch(E) {
343                 alert(offineStrings.getFormattedString('main.session_cookie.error', [E]));
344             }
345             if (! data.list.au ) data.list.au = [];
346             data.list.au[0] = JSON2js( data.temporary_session.usr );
347             data.stash('list');
348             obj.reset_titlebars(data);
349             return true;
350         } else {
351             obj.error.sdump('D_TRACE','No new session key after simple_auth in util/network\n');
352         }
353         return false;
354
355         } catch(E) {
356             obj.error.standard_unexpected_error_alert('util.network.get_new_session',E);
357         }
358     },
359
360     'rerequest_on_session_timeout' : function(app,name,params,req,override_params,_params) {
361         try {
362             var obj = this;
363             var robj = obj.get_result(req);
364             if (robj != null && robj.ilsevent && robj.ilsevent == 1001 /* NO_SESSION */) {
365
366                 if (obj.get_new_session(name,undefined,true)) {
367                     JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
368                     params[0] = data.session.key;
369                     req = obj._request(app,name,params,null,override_params,_params);
370                 }
371             }
372         } catch(E) {
373             this.error.standard_unexpected_error_alert('rerequest_on_session_timeout',E);
374         }
375         return req;
376     },
377     
378     'rerequest_on_perm_failure' : function(app,name,params,req,override_params,_params) {
379         try {
380             var obj = this;
381             var robj = obj.get_result(req);
382             if (robj != null && robj.ilsevent && robj.ilsevent == 5000) {
383                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
384                 if (location.href.match(/^chrome/)) {
385                     //alert('Permission denied.');
386                 } else {
387                     JSAN.use('util.window'); var win = new util.window();
388                     var my_xulG = win.open(
389                         urls.XUL_AUTH_SIMPLE,
390                         //+ '?login_type=temp'
391                         //+ '&desc_brief=' + window.escape('Permission Denied: ' + robj.ilsperm)
392                         //+ '&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),
393                         //'simple_auth' + (new Date()).toString(),
394                         offlineStrings.getFormattedString('network.permission.authorize'),
395                         'chrome,resizable,modal,width=700,height=500',
396                         {
397                             'login_type' : 'temp',
398                             'desc_brief' : offlineStrings.getFormattedString('network.permission.description.brief', [robj.ilsperm]),
399                             'desc_full' : offlineStrings.getFormattedString('network.permission.description.full', [name])
400                             //'simple_auth' : (new Date()).toString(),
401                         }
402                     );
403                     JSAN.use('OpenILS.data');
404                     //var data = new OpenILS.data(); data.init({'via':'stash'});
405                     if (typeof my_xulG.temporary_session != 'undefined' && my_xulG.temporary_session != '') {
406                         params[0] = my_xulG.temporary_session.key;
407                         req = obj._request(app,name,params,null,override_params,_params);
408                     }
409                 }
410             }
411         } catch(E) {
412             this.error.sdump('D_ERROR',E);
413         }
414         return req;
415     },
416
417     'rerequest_on_override' : function (app,name,params,req,override_params,_params) {
418         var obj = this;
419         try {
420             if (!override_params.text) override_params.text = {};
421             if (!override_params.auto_override_these_events) override_params.auto_override_these_events = [];
422             function override(r) {
423                 try {
424                     // test to see if we can suppress this dialog and auto-override
425                     var auto_override = false;
426                     if (override_params.auto_override_these_events.length > 0) {
427                         auto_override = true;
428                         for (var i = 0; i < r.length; i++) {
429                             if ( 
430                                 (r[i].ilsevent != 'undefined') && 
431                                 (
432                                     (override_params.auto_override_these_events.indexOf( r[i].ilsevent == null ? null : Number(r[i].ilsevent) ) != -1) ||
433                                     (override_params.auto_override_these_events.indexOf( r[i].textcode ) != -1) 
434                                 )
435                             ) {
436                                 // so far so good
437                             } else {
438                                 // showstopper
439                                 auto_override = false;
440                             }
441                         }
442                     }
443                     if (auto_override) {
444                         obj.sound.bad();
445                         req = obj._request(app,name + '.override',params);
446                         return req;
447                     }
448
449                     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserWrite');
450                     var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">' + 
451                         '<groupbox><caption label="' + offlineStrings.getString('network.override.exceptions') + '"/>' + 
452                         '<grid><columns><column/><column/></columns><rows>';
453                     for (var i = 0; i < r.length; i++) {
454                         var t1 = String(r[i].ilsevent).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
455                         var t2 = String(r[i].textcode).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
456                         var t3 = String((override_params.text[r[i].ilsevent] ? override_params.text[r[i].ilsevent](r[i]) : '')).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
457                         var t4 = String(r[i].desc).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
458                         xml += '<row>' + 
459                             '<description class="oils_event" tooltiptext="' + t1 + '">' + t2 + '</description>' + 
460                             '<description>' + t3 + '</description>' + 
461                             '</row><row>' + '<description>' + t4 + '</description>' + '</row>';
462                     }
463                     xml += '</rows></grid></groupbox><groupbox><caption label="' + offlineStrings.getString('network.override.override') +'"/><hbox>' + 
464                         '<description>' + offlineStrings.getString('network.override.force.prompt') + '</description>' + 
465                         '<button accesskey="' + offlineStrings.getString('common.no.accesskey') + '" label="' + offlineStrings.getString('common.no') + '" name="fancy_cancel"/>' + 
466                         '<button id="override" accesskey="' + offlineStrings.getString('common.yes.accesskey') + '" label="' + offlineStrings.getString('common.yes') + '" name="fancy_submit" value="override"/></hbox></groupbox></vbox>';
467                     //JSAN.use('OpenILS.data');
468                     //var data = new OpenILS.data(); data.init({'via':'stash'});
469                     //data.temp_override_xml = xml; data.stash('temp_override_xml');
470                     JSAN.use('util.window'); var win = new util.window();
471                     var fancy_prompt_data = win.open(
472                         urls.XUL_FANCY_PROMPT,
473                         //+ '?xml_in_stash=temp_override_xml'
474                         //+ '&title=' + window.escape(override_params.title),
475                         'fancy_prompt', 'chrome,resizable,modal,width=700,height=500',
476                         { 'xml' : xml, 'title' : override_params.title, 'sound' : 'bad' }
477                     );
478                     if (fancy_prompt_data.fancy_status == 'complete') {
479                         req = obj._request(app,name + '.override',params);
480                     }
481                     return req;
482                 } catch(E) {
483                     alert('in util.network, rerequest_on_override, override:' + E);
484                 }
485             }
486
487             var result = obj.get_result(req);
488             if (!result) return req;
489
490             if ( 
491                 (typeof result.ilsevent != 'undefined') && 
492                 (
493                     (override_params.overridable_events.indexOf( result.ilsevent == null ? null : Number(result.ilsevent) ) != -1) ||
494                     (override_params.overridable_events.indexOf( result.textcode ) != -1)
495                 )
496             ) {
497                 req = override([result]);
498             } else {
499                 var found_good = false; var found_bad = false;
500                 for (var i = 0; i < result.length; i++) {
501                     if ( 
502                         (result[i].ilsevent != 'undefined') && 
503                         (
504                             (override_params.overridable_events.indexOf( result[i].ilsevent == null ? null : Number(result[i].ilsevent) ) != -1) ||
505                             (override_params.overridable_events.indexOf( result[i].textcode ) != -1) 
506                         )
507                     ) {
508                         found_good = true;
509                     } else {
510                         found_bad = true;
511                     }
512                 }
513                 if (found_good && (!found_bad)) req = override(result);
514             }
515
516             return req;
517         } catch(E) {
518             throw(E);
519         }
520     },
521
522     'ping' : function() {
523         try {
524             JSAN.use('util.file'); JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.init({'via':'stash'});
525             var file = new util.file('ping.bat');
526             var path = file._file.path;
527             file.write_content('truncate+exec',
528                 '#!/bin/sh\n' +
529                 'ping -n 15 ' + data.server_unadorned + ' > "' + path + '.txt"\n' + /* windows */
530                 'ping -c 15 ' + data.server_unadorned + ' >> "' + path + '.txt"\n'  /* unix */
531             );
532             file.close();
533             file = new util.file('ping.bat');
534
535             var process = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
536             process.init(file._file);
537
538             var args = [];
539
540             dump('process.run = ' + process.run(true, args, args.length) + '\n');
541
542             file.close();
543
544             var file = new util.file('ping.bat.txt');
545             var output = file.get_content();
546             file.close();
547
548             return output;
549         } catch(E) {
550             alert(E);
551         }
552     },
553
554     'play_sounds' : function(req) {
555         var obj = this;
556         try {
557             var result = req.getResultObject();
558             if (result == null) { return; }
559             if (typeof result.textcode != 'undefined') {
560                 obj.sound.event( result );
561             } else {
562                 if (typeof result.length != 'undefined') {
563                     for (var i = 0; i < result.length; i++) {
564                         if (typeof result[i].textcode != 'undefined') {
565                             obj.sound.event( result[i] );
566                         }
567                     }
568                 }
569             }
570         } catch(E) {
571             dump('Error in network.js, play_sounds() : ' + E + '\n');
572         }
573     }
574 }
575
576 /*
577 function sample_callback(request) {
578     var result = request.getResultObject();
579 }
580 */
581
582 dump('exiting util/network.js\n');