• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/lighttpd-1.4.39/external_file/js/davclient.js/
1/*
2    davclient.js - Low-level JavaScript WebDAV client implementation
3    Copyright (C) 2004-2007 Guido Wesdorp
4    email johnny@johnnydebris.net
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20*/
21
22var global = this;
23// create a namespace for our stuff... notice how we define a class and create
24// an instance at the same time
25global.davlib = new function() {
26    /* WebDAV for JavaScript
27
28        This is a library containing a low-level and (if loaded, see
29        'davfs.js') a high-level API for working with WebDAV capable servers
30        from JavaScript.
31
32        Quick example of the low-level interface:
33
34          var client = new davlib.DavClient();
35          client.initialize();
36
37          function alertContent(status, statusstring, content) {
38            if (status != 200) {
39              alert('error: ' + statusstring);
40              return;
41            };
42            alert('content received: ' + content);
43          };
44
45          client.GET('/foo/bar.txt', alertContent);
46
47        Quick example of the high-level interface:
48
49          var fs = new davlib.DavFS();
50          fs.initialize();
51
52          function alertContent(error, content) {
53            if (error) {
54              alert('error: ' + error);
55              return;
56            };
57            alert('content: ' + content);
58          };
59
60          fs.read('/foo/bar.txt', alertContent);
61
62        (Note that since we only read a simple file here, changes between the
63        high- and low-level APIs are very small.)
64
65        For more examples and information, see the DavClient and DavFS
66        constructors, and the README.txt file and the tests in the package.
67        For references of single methods, see the comments in the code (sorry
68        folks, but keeping code and documents up-to-date is really a nuisance
69        and I'd like to avoid that until things are stable enough).
70
71    */
72    var davlib = this;
73	var g_storage = new myStorage();
74
75    this.DEBUG = 0;
76
77    this.STATUS_CODES = {
78        '100': 'Continue',
79        '101': 'Switching Protocols',
80        '102': 'Processing',
81        '200': 'OK',
82        '201': 'Created',
83        '202': 'Accepted',
84        '203': 'None-Authoritive Information',
85        '204': 'No Content',
86        // seems that there's some bug in IE (or Sarissa?) that
87        // makes it spew out '1223' status codes when '204' is
88        // received... needs some investigation later on
89        '1223': 'No Content',
90        '205': 'Reset Content',
91        '206': 'Partial Content',
92        '207': 'Multi-Status',
93        '300': 'Multiple Choices',
94        '301': 'Moved Permanently',
95        '302': 'Found',
96        '303': 'See Other',
97        '304': 'Not Modified',
98        '305': 'Use Proxy',
99        '307': 'Redirect',
100        '400': 'Bad Request',
101        '401': 'Unauthorized',
102        '402': 'Payment Required',
103        '403': 'Forbidden',
104        '404': 'Not Found',
105        '405': 'Method Not Allowed',
106        '406': 'Not Acceptable',
107        '407': 'Proxy Authentication Required',
108        '408': 'Request Time-out',
109        '409': 'Conflict',
110        '410': 'Gone',
111        '411': 'Length Required',
112        '412': 'Precondition Failed',
113        '413': 'Request Entity Too Large',
114        '414': 'Request-URI Too Large',
115        '415': 'Unsupported Media Type',
116        '416': 'Requested range not satisfiable',
117        '417': 'Expectation Failed',
118        '422': 'Unprocessable Entity',
119        '423': 'Locked',
120        '424': 'Failed Dependency',
121        '500': 'Internal Server Error',
122        '501': 'Not Implemented',
123        '502': 'Bad Gateway',
124        '503': 'Service Unavailable',
125        '504': 'Gateway Time-out',
126        '505': 'HTTP Version not supported',
127        '507': 'Insufficient Storage'
128    };
129
130    this.DavClient = function() {
131        /* Low level (subset of) WebDAV client implementation
132
133            Basically what one would expect from a basic DAV client, it
134            provides a method for every HTTP method used in basic DAV, it
135            parses PROPFIND requests to handy JS structures and accepts
136            similar structures for PROPPATCH.
137
138            Requests are handled asynchronously, so instead of waiting until
139            the response is sent back from the server and returning the
140            value directly, a handler is registered that is called when
141            the response is available and the method that sent the request
142            is ended. For that reason all request methods accept a 'handler'
143            argument, which will be called (with 3 arguments: statuscode,
144            statusstring and content (the latter only where appropriate))
145            when the request is handled by the browser.
146            The reason for this choice is that Mozilla sometimes freezes
147            when using XMLHttpRequest for synchronous requests.
148
149            The only 'public' methods on the class are the 'initialize'
150            method, that needs to be called first thing after instantiating
151            a DavClient object, and the methods that have a name similar to
152            an HTTP method (GET, PUT, etc.). The latter all get at least a
153            'path' argument, a 'handler' argument and a 'context' argument:
154
155                'path' - an absolute path to the target resource
156                'handler' - a function or method that will be called once
157                        the request has finished (see below)
158                'context' - the context used to call the handler, the
159                        'this' variable inside methods, so usually the
160                        object (instance) the handler is bound to (ignore
161                        when the handler is a function)
162
163            All handlers are called with the same 3 arguments:
164
165                'status' - the HTTP status code
166                'statusstring' - a string representation (see STATUS_CODES
167                        array above) of the status code
168                'content' - can be a number of different things:
169                        * when there was an error in a method that targets
170                            a single resource, this contains the error body
171                        * when there was an error in a method that targets
172                            a set of resources (multi-status) it contains
173                            a Root object instance (see below) that contains
174                            the error messages of all the objects
175                        * if the method was GET and there was no error, it
176                            will contain the contents of the resource
177                        * if the method was PROPFIND and there was no error,
178                            it will contain a Root object (see below) that
179                            contains the properties of all the resources
180                            targeted
181                        * if there was no error and there is no content to
182                            return, it will contain null
183                'headers' - a mapping (associative array) from lowercase header
184                            name to value (string)
185
186            Basic usage example:
187
188                function handler(status, statusstring, content, headers) {
189                    if (content) {
190                        if (status != '200' && status != '204') {
191                            if (status == '207') {
192                                alert('not going to show multi-status ' +
193                                        here...');
194                            };
195                            alert('Error: ' + statusstring);
196                        } else {
197                            alert('Content: ' + content);
198                        };
199                    };
200                };
201
202                var dc = new DavClient();
203                dc.initialize('localhost');
204
205                // create a directory
206                dc.MKCOL('/foo', handler);
207
208                // create a file and save some contents
209                dc.PUT('/foo/bar.txt', 'baz?', handler);
210
211                // load and alert it ( happens in the handler)
212                dc.GET('/foo/bar.txt', handler);
213
214                // lock the file, we need to store the lock token from
215                // the result
216                function lockhandler(status, statusstring, content, headers) {
217                    if (status != '200') {
218                        alert('Error unlocking: ' + statusstring);
219                    } else {
220                        window.CURRENT_LOCKTOKEN = headers.locktoken;
221                    };
222                };
223                dc.LOCK('/foo/bar.txt', 'http://johnnydebris.net/',
224                            lockhandler);
225
226                // run the following bit only if the lock was set properly
227                if (window.CURRENT_LOCKTOKEN) {
228                    // try to delete it: this will fail
229                    dc.DELETE('/foo/bar.txt', handler);
230
231                    // now unlock it using the lock token stored above
232                    dc.UNLOCK('/foo/bar.txt', window.CURRENT_LOCKTOKEN,
233                              handler);
234                };
235
236                // delete the dir
237                dc.DELETE('/foo', handler);
238
239            For detailed information about the HTTP methods and how they
240            can/should be used in a DAV context, see http://www.webdav.org.
241
242            This library depends on version 0.3 of the 'dommer' package
243            and version 0.2 of the 'minisax.js' package, both of which
244            should be available from http://johnnydebris.net under the
245            same license as this one (GPL).
246
247            If you have questions, bug reports, or patches, please send an
248            email to johnny@johnnydebris.net.
249        */
250    };
251
252    this.DavClient.prototype.initialize = function(host, port, protocol) {
253        /* the 'constructor' (needs to be called explicitly!!)
254
255            host - the host name or IP
256            port - HTTP port of the host (optional, defaults to 80)
257            protocol - protocol part of URLs (optional, defaults to http)
258        */
259
260        this.host = host || location.hostname;
261        this.port = port || location.port;// || 80;
262        this.protocol = (protocol ||
263                         location.protocol.substr(0,
264                                                  location.protocol.length - 1
265                                                  ) ||
266                         'http');
267
268        this.request = null;
269    };
270
271    this.DavClient.prototype.OPTIONS = function(path, handler, context) {
272        /* perform an OPTIONS request
273
274            find out which HTTP methods are understood by the server
275        */
276        // XXX how does this work with * paths?
277        var request = this._getRequest('OPTIONS', path, handler, context);
278        request.send('');
279    };
280
281    this.DavClient.prototype.GET = function(path, handler, context) {
282        /* perform a GET request
283
284            retrieve the contents of a resource
285        */
286        var request = this._getRequest('GET', path, handler, context);
287        request.send('');
288    };
289
290		//charles mark
291    this.DavClient.prototype.PUT = function(path, content, sliceAsBinary,
292											start, stop, filesize, autoCreateFolder,
293											handler,
294                                            updateProgress, context, locktoken ) {
295        /* perform a PUT request
296            save the contents of a resource to the server
297            'content' - the contents of the resource
298        */
299        var request = this._getRequest('PUT', path, handler, context);
300        request.setRequestHeader("Content-type", "text/xml,charset=UTF-8");
301		/*
302			 for example  Content-Range: bytes 21010-47021/47022
303		*/
304		//alert("set request start ="+start+"stop="+stop+"filesize="+filesize+", sliceAsBinary="+sliceAsBinary);
305        request.setRequestHeader("Content-Range", "bytes "+start+"-"+stop+"/"+filesize);
306
307        if (locktoken) {
308            request.setRequestHeader('If', '<' + locktoken + '>');
309        };
310
311        if(autoCreateFolder){
312        	request.setRequestHeader("Auto-CreateFolder", autoCreateFolder);
313      	}
314
315        if(request.upload){
316        	request.upload.onprogress = updateProgress;
317        }
318
319        try{
320        	if(sliceAsBinary == 0 && request.sendAsBinary != null){
321        		request.sendAsBinary(content);
322			}
323			else if(sliceAsBinary == 1){
324				request.send(content);
325        	}
326        	else{
327        		throw '';
328        	}
329        }
330        catch(e) {
331          // not a Mozilla or Konqueror based browser
332          alert("Fail to PUT data to webdav " + e);
333        };
334    };
335
336    this.DavClient.prototype.DELETE = function(path, handler,
337                                               context, locktoken) {
338        /* perform a DELETE request
339
340            remove a resource (recursively)
341        */
342        var request = this._getRequest('DELETE', path, handler, context);
343
344        if (locktoken) {
345            request.setRequestHeader('If', '<' + locktoken + '>');
346        };
347        //request.setRequestHeader("Depth", "Infinity");
348        request.send('');
349    };
350
351    this.DavClient.prototype.MKCOL = function(path, handler,
352                                              context, locktoken) {
353        /* perform a MKCOL request
354
355            create a collection
356        */
357        var request = this._getRequest('MKCOL', path, handler, context);
358        if (locktoken) {
359            request.setRequestHeader('If', '<' + locktoken + '>');
360        };
361        request.send('');
362    };
363
364    this.DavClient.prototype.COPY = function(path, topath, handler,
365                                             context, overwrite, locktoken) {
366        /* perform a COPY request
367
368            create a copy of a resource
369
370            'topath' - the path to copy the resource to
371            'overwrite' - whether or not to fail when the resource
372                    already exists (optional)
373        */
374        var request = this._getRequest('COPY', path, handler, context);
375        var tourl = this._generateUrl(topath);
376        request.setRequestHeader("Destination", tourl);
377        if (overwrite) {
378            request.setRequestHeader("Overwrite", overwrite);
379        };
380
381        if (locktoken) {
382            request.setRequestHeader('If', '<' + locktoken + '>');
383        };
384        request.send('');
385    };
386
387    this.DavClient.prototype.MOVE = function(path, topath, handler,
388                                             context, overwrite, locktoken) {
389        /* perform a MOVE request
390
391            move a resource from location
392
393            'topath' - the path to move the resource to
394            'overwrite' - whether or not to fail when the resource
395                    already exists (optional)
396        */
397        var request = this._getRequest('MOVE', path, handler, context);
398        var tourl = this._generateUrl(topath);
399
400        request.setRequestHeader("Destination", tourl);
401        if (overwrite) {
402            request.setRequestHeader("Overwrite", overwrite);
403        };
404
405        if (locktoken) {
406            request.setRequestHeader('If', '<' + locktoken + '>');
407        };
408        request.send('');
409    };
410
411    this.DavClient.prototype.PROPFIND = function(path, auth, handler,
412                                                 context, depth, mtype) {
413        /* perform a PROPFIND request
414
415            read the metadata of a resource (optionally including its children)
416
417            'depth' - control recursion depth, default 0 (only returning the
418                    properties for the resource itself)
419        */
420
421        var request = this._getRequest('PROPFIND', path, handler, context);
422        depth = depth || 0;
423
424        if(auth!=undefined){
425        	request.setRequestHeader('Authorization', auth);
426        	//alert("setRequestHeader->" + auth);
427       	}
428
429        request.setRequestHeader('Depth', depth);
430		request.setRequestHeader('Mtype', mtype);
431        request.setRequestHeader('Content-type', 'text/xml; charset=UTF-8');
432        // XXX maybe we want to change this to allow getting selected props
433
434        var xml = '<?xml version="1.0" encoding="UTF-8" ?>' +
435                  '<D:propfind xmlns:D="DAV:">' +
436                  '<D:allprop />' +
437                  '</D:propfind>';
438
439        /*
440        var xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>' +
441									'<D:propfind xmlns:D="DAV:">' +
442									'<D:prop>' +
443									'<D:getlastmodified/>' +
444									'<D:getcontentlength/>' +
445									'<D:getcontenttype/>' +
446									//'<D:resourcetype/>' +
447									//'<D:getetag/>' +
448									//'<D:lockdiscovery/>' +
449									'<D:getmac/>' +
450									'<D:getuniqueid/>' +
451									'<D:getonline/>' +
452									'<D:gettype/>' +
453									'<D:getattr/>' +
454									'</D:prop>' +
455									'</D:propfind>';
456        */
457
458        request.send(xml);
459    };
460
461	this.DavClient.prototype.OAUTH = function(path,auth,enc,handler,context,locktoken){
462		var request = this._getRequest('OAUTH',path,handler,context);
463		request.setRequestHeader('Authorization', auth);
464		request.setRequestHeader('Cookie', enc);
465
466		request.send('');
467	};
468
469	this.DavClient.prototype.WOL = function(path,mac,handler,context,locktoken){
470		var request = this._getRequest('WOL',path,handler,context);
471		request.setRequestHeader("WOLMAC",mac);
472		if(locktoken){
473			request.setRequestHeader('If','<'+locktoken+'>');
474		};
475		request.send('');
476	};
477
478	this.DavClient.prototype.GSL = function(path,urlPath,fileName,expire,toShare,handler,context,locktoken){
479		var request = this._getRequest('GSL',path,handler,context);
480		request.setRequestHeader("URL",urlPath);
481		request.setRequestHeader("FILENAME",fileName);
482		request.setRequestHeader("EXPIRE",expire);
483		request.setRequestHeader("TOSHARE",toShare);
484
485		if(locktoken){
486			request.setRequestHeader('If','<'+locktoken+'>');
487		};
488		request.send('');
489	};
490
491	this.DavClient.prototype.GSLL = function(path,handler,context,locktoken){
492		var request = this._getRequest('GSLL',path,handler,context);
493		if(locktoken){
494			request.setRequestHeader('If','<'+locktoken+'>');
495		};
496		request.send('');
497	};
498
499	this.DavClient.prototype.REMOVESL = function(path,sharelink,handler,context,locktoken){
500		var request = this._getRequest('REMOVESL',path,handler,context);
501		request.setRequestHeader("SHARELINK",sharelink);
502		if(locktoken){
503			request.setRequestHeader('If','<'+locktoken+'>');
504		};
505		request.send('');
506	};
507
508	this.DavClient.prototype.LOGOUT = function(path,handler,context,locktoken){
509		var request = this._getRequest('LOGOUT',path,handler,context);
510		if(locktoken){
511			request.setRequestHeader('If','<'+locktoken+'>');
512		};
513		request.send('');
514	};
515
516	this.DavClient.prototype.GETSRVTIME = function(path,handler,context,locktoken){
517		var request = this._getRequest('GETSRVTIME',path,handler,context);
518		if(locktoken){
519			request.setRequestHeader('If','<'+locktoken+'>');
520		};
521		request.send('');
522	};
523
524	this.DavClient.prototype.RESCANSMBPC = function(path,handler,context,locktoken){
525		var request = this._getRequest('RESCANSMBPC',path,handler,context);
526		if(locktoken){
527			request.setRequestHeader('If','<'+locktoken+'>');
528		};
529		request.send('');
530	};
531
532	this.DavClient.prototype.GETROUTERMAC = function(path,handler,context,locktoken){
533		var request = this._getRequest('GETROUTERMAC',path,handler,context);
534		if(locktoken){
535			request.setRequestHeader('If','<'+locktoken+'>');
536		};
537		request.send('');
538	};
539
540	this.DavClient.prototype.GETROUTERINFO = function(path,handler,context,locktoken){
541		var request = this._getRequest('GETROUTERINFO',path,handler,context);
542		if(locktoken){
543			request.setRequestHeader('If','<'+locktoken+'>');
544		};
545		request.send('');
546	};
547
548	this.DavClient.prototype.GETNOTICE = function(path,timestamp,handler,context,locktoken){
549		var request = this._getRequest('GETNOTICE',path,handler,context);
550		request.setRequestHeader("TIMESTAMP",timestamp);
551		request.send('');
552	};
553
554	this.DavClient.prototype.GETFIRMVER = function(path,handler,context,locktoken){
555		var request = this._getRequest('GETFIRMVER',path,handler,context);
556		if(locktoken){
557			request.setRequestHeader('If','<'+locktoken+'>');
558		};
559		request.send('');
560	};
561
562	this.DavClient.prototype.GETLATESTVER = function(path,handler,context,locktoken){
563		var request = this._getRequest('GETLATESTVER',path,handler,context);
564		if(locktoken){
565			request.setRequestHeader('If','<'+locktoken+'>');
566		};
567		request.send('');
568	};
569
570	this.DavClient.prototype.GETDISKSPACE = function(path,diskname,handler,context,locktoken){
571		var request = this._getRequest('GETDISKSPACE',path,handler,context);
572		request.setRequestHeader("DISKNAME",diskname);
573		if(locktoken){
574			request.setRequestHeader('If','<'+locktoken+'>');
575		};
576		request.send('');
577	};
578
579	this.DavClient.prototype.PROPFINDMEDIALIST = function(path, handler, context, media_type, start,
580			end, keyword, orderby, orderrule, parentid){
581		/* perform a PROPFINDMEDIALIST request
582		*/
583
584		var request = this._getRequest('PROPFINDMEDIALIST', path, handler, context);
585		request.setRequestHeader('Content-type', 'text/xml; charset=UTF-8');
586
587		if(media_type){
588			request.setRequestHeader("MediaType", media_type);
589		};
590
591		if(start) {
592			request.setRequestHeader("Start", start);
593		};
594
595		if (end) {
596			request.setRequestHeader("End", end);
597		};
598
599		if (keyword) {
600			request.setRequestHeader("Keyword", keyword);
601		};
602
603		if (orderby) {
604			request.setRequestHeader("Orderby", orderby);
605		};
606
607		if (orderrule) {
608			request.setRequestHeader("Orderrule", orderrule);
609		};
610
611		if (parentid) {
612			request.setRequestHeader("Parentid", parentid);
613		};
614		/*
615		var xml = '<?xml version="1.0" encoding="UTF-8" ?>' +
616                  '<D:propfind xmlns:D="DAV:">' +
617                  '<D:allprop />' +
618                  '</D:propfind>';
619		*/
620		var xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>' +
621				  '<D:propfind xmlns:D="DAV:">' +
622				  '<D:prop>' +
623 				  '<D:getlastmodified/>' +
624				  '<D:getcontentlength/>' +
625				  '<D:getcontenttype/>' +
626				  '<D:getmatadata/>' +
627				  '</D:prop>' +
628				  '</D:propfind>';
629
630		request.send(xml);
631	};
632
633	this.DavClient.prototype.GETMUSICCLASSIFICATION = function(path,classify,handler,context,locktoken){
634		var request = this._getRequest('GETMUSICCLASSIFICATION',path,handler,context);
635		if (classify) {
636			request.setRequestHeader("Classify", classify);
637		};
638		if(locktoken){
639			request.setRequestHeader('If','<'+locktoken+'>');
640		};
641		request.send('');
642	};
643
644	this.DavClient.prototype.GETMUSICPLAYLIST = function(path,id,handler,context,locktoken){
645		var request = this._getRequest('GETMUSICPLAYLIST',path,handler,context);
646		if (id) {
647			request.setRequestHeader("id", id);
648		};
649		if(locktoken){
650			request.setRequestHeader('If','<'+locktoken+'>');
651		};
652		request.send('');
653	};
654
655	this.DavClient.prototype.GETPRODUCTICON = function(path,handler,context,locktoken){
656		var request = this._getRequest('GETPRODUCTICON',path,handler,context);
657		if(locktoken){
658			request.setRequestHeader('If','<'+locktoken+'>');
659		};
660		request.send('');
661	};
662
663	this.DavClient.prototype.GETTHUMBIMAGE = function(path, file, handler,context,locktoken){
664		var request = this._getRequest('GETTHUMBIMAGE',path,handler,context);
665		if (file) {
666			request.setRequestHeader("File", file);
667		};
668		if(locktoken){
669			request.setRequestHeader('If','<'+locktoken+'>');
670		};
671		request.send('');
672	};
673
674	this.DavClient.prototype.GETVIDEOSUBTITLE = function(path,name,handler,context,locktoken){
675		var request = this._getRequest('GETVIDEOSUBTITLE',path,handler,context);
676		request.setRequestHeader("FILENAME", name);
677		if(locktoken){
678			request.setRequestHeader('If','<'+locktoken+'>');
679		};
680		request.send('');
681	};
682
683		this.DavClient.prototype.UPLOADTOFACEBOOK = function(path,name,title,album,token,handler,context,locktoken){
684			var request = this._getRequest('UPLOADTOFACEBOOK',path,handler,context);
685			request.setRequestHeader("FILENAME", name);
686			request.setRequestHeader("TITLE", title);
687			request.setRequestHeader("ALBUM", album);
688			request.setRequestHeader("TOKEN", token);
689			if(locktoken){
690				request.setRequestHeader('If','<'+locktoken+'>');
691			};
692			request.send('');
693		};
694
695		this.DavClient.prototype.UPLOADTOFLICKR = function(path,name,title,token,handler,context,locktoken){
696			var request = this._getRequest('UPLOADTOFLICKR',path,handler,context);
697			request.setRequestHeader("FILENAME", name);
698			request.setRequestHeader("TITLE", title);
699			request.setRequestHeader("TOKEN", token);
700			if(locktoken){
701				request.setRequestHeader('If','<'+locktoken+'>');
702			};
703			request.send('');
704		};
705
706		this.DavClient.prototype.UPLOADTOPICASA = function(path,name,title,uid,aid,token,handler,context,locktoken){
707			var request = this._getRequest('UPLOADTOPICASA',path,handler,context);
708			request.setRequestHeader("FILENAME", name);
709			request.setRequestHeader("TITLE", title);
710			request.setRequestHeader("UID", uid);
711			request.setRequestHeader("AID", aid);
712			request.setRequestHeader("TOKEN", token);
713			if(locktoken){
714				request.setRequestHeader('If','<'+locktoken+'>');
715			};
716			request.send('');
717		};
718
719		this.DavClient.prototype.UPLOADTOTWITTER = function(path,name,title,token,secret,nonce,timestamp,signature,photo_size_limit,handler,context,locktoken){
720			var request = this._getRequest('UPLOADTOTWITTER',path,handler,context);
721			request.setRequestHeader("FILENAME", name);
722			request.setRequestHeader("TITLE", title);
723			request.setRequestHeader("TOKEN", token);
724			request.setRequestHeader("SECRET", secret);
725			request.setRequestHeader("NONCE", nonce);
726			request.setRequestHeader("TIMESTAMP", timestamp);
727			request.setRequestHeader("SIGNATURE", signature);
728			request.setRequestHeader("PHOTOSIZELIMIT", photo_size_limit);
729			if(locktoken){
730				request.setRequestHeader('If','<'+locktoken+'>');
731			};
732			request.send('');
733		};
734
735		this.DavClient.prototype.GENROOTCERTIFICATE = function(path,keylen,caname,email,country,state,ln,orag,ounit,cn,handler,context,locktoken){
736			var request = this._getRequest('GENROOTCERTIFICATE',path,handler,context);
737			request.setRequestHeader("KEYLEN", keylen); //- Private key length
738			request.setRequestHeader("CANAME", caname); //- CA name
739			request.setRequestHeader("EMAIL", email); //- email address
740			request.setRequestHeader("COUNTRY", country); //- Country Name(2 letter code)
741			request.setRequestHeader("STATE", state); //- State or Province Name(full name)
742			request.setRequestHeader("LN", ln); //- Locality Name(eg, city)
743			request.setRequestHeader("ORAG", orag);//- Organization Name(eg, company)
744			request.setRequestHeader("OUNIT", ounit); //- Organizational Unit Name(eg, section)
745			request.setRequestHeader("CN", cn); //- Common Name(eg. your name or your server's hostname)
746			request.send('');
747		};
748
749		this.DavClient.prototype.SETROOTCERTIFICATE = function(path,key,cert,intermediate_crt,handler,context,locktoken){
750			var request = this._getRequest('SETROOTCERTIFICATE',path,handler,context);
751			request.setRequestHeader('Content-type', 'text/xml; charset=UTF-8');
752
753			var xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
754			xml += '<content>';
755			xml += '<key>' + key + '</key>';
756	 		xml += '<cert>' + cert + '</cert>';
757
758	 		if(intermediate_crt!="")
759	 			xml += '<intermediate_crt>' + intermediate_crt + '</intermediate_crt>';
760
761			xml += '</content>';
762
763			request.send(xml);
764		};
765
766		this.DavClient.prototype.GETX509CERTINFO = function(path, handler,context,locktoken){
767			var request = this._getRequest('GETX509CERTINFO',path,handler,context);
768			request.send('');
769		};
770
771		this.DavClient.prototype.APPLYAPP = function(path, action, nvram, service, handler,context,locktoken){
772			var request = this._getRequest('APPLYAPP',path,handler,context);
773			request.setRequestHeader("ACTION_MODE", action);
774			request.setRequestHeader("SET_NVRAM", nvram);
775			request.setRequestHeader("RC_SERVICE", service);
776			request.send('');
777		};
778
779		this.DavClient.prototype.NVRAMGET = function(path, key, handler,context,locktoken){
780			var request = this._getRequest('NVRAMGET',path,handler,context);
781			request.setRequestHeader("KEY", key);
782			request.send('');
783		};
784
785		this.DavClient.prototype.GETCPUUSAGE = function(path, handler,context,locktoken){
786			var request = this._getRequest('GETCPUUSAGE',path,handler,context);
787			request.send('');
788		};
789
790		this.DavClient.prototype.GETMEMORYUSAGE = function(path, handler,context,locktoken){
791			var request = this._getRequest('GETMEMORYUSAGE',path,handler,context);
792			request.send('');
793		};
794
795		this.DavClient.prototype.UPDATEACCOUNT = function(path,id,username,password,type,permission,handler,context,locktoken){
796			var request = this._getRequest('UPDATEACCOUNT',path,handler,context);
797
798			request.setRequestHeader('Content-type', 'text/xml; charset=UTF-8');
799
800			var xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
801			xml += '<content>';
802			xml += '<id>' + id + '</id>';
803			xml += '<username>' + username + '</username>';
804			xml += '<password>' + password + '</password>';
805			xml += '<type>' + type + '</type>';
806			xml += '<permission>' + permission + '</permission>';
807			xml += '</content>';
808
809			request.send(xml);
810		};
811
812		this.DavClient.prototype.GETACCOUNTINFO = function(path,username,handler,context,locktoken){
813			var request = this._getRequest('GETACCOUNTINFO',path,handler,context);
814			request.setRequestHeader("USERNAME", username);
815			request.send('');
816		};
817
818		this.DavClient.prototype.GETACCOUNTLIST = function(path,handler,context,locktoken){
819			var request = this._getRequest('GETACCOUNTLIST',path,handler,context);
820			request.send('');
821		};
822
823		this.DavClient.prototype.DELETEACCOUNT = function(path,username,handler,context,locktoken){
824			var request = this._getRequest('DELETEACCOUNT',path,handler,context);
825			request.setRequestHeader("USERNAME", username);
826			request.send('');
827		};
828
829		this.DavClient.prototype.UPDATEACCOUNTINVITE = function(path,invite_token,permission,enable_smart_access,security_code,handler,context,locktoken){
830			var request = this._getRequest('UPDATEACCOUNTINVITE',path,handler,context);
831
832			request.setRequestHeader('Content-type', 'text/xml; charset=UTF-8');
833
834			var xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
835			xml += '<content>';
836			xml += '<token>' + invite_token + '</token>';
837			xml += '<permission>' + permission + '</permission>';
838			xml += '<enable_smart_access>' + enable_smart_access + '</enable_smart_access>';
839			xml += '<security_code>' + security_code + '</security_code>';
840			xml += '</content>';
841
842			request.send(xml);
843		};
844
845		this.DavClient.prototype.GETACCOUNTINVITEINFO = function(path,token,handler,context,locktoken){
846			var request = this._getRequest('GETACCOUNTINVITEINFO',path,handler,context);
847			request.setRequestHeader("TOKEN", token);
848			request.send('');
849		};
850
851		this.DavClient.prototype.GETACCOUNTINVITELIST = function(path,handler,context,locktoken){
852			var request = this._getRequest('GETACCOUNTINVITELIST',path,handler,context);
853			request.send('');
854		};
855
856		this.DavClient.prototype.DELETEACCOUNTINVITE = function(path,token,handler,context,locktoken){
857			var request = this._getRequest('DELETEACCOUNTINVITE',path,handler,context);
858			request.setRequestHeader("TOKEN", token);
859			request.send('');
860		};
861
862		this.DavClient.prototype.OPENSTREAMINGPORT = function(path,open,handler,context,locktoken){
863			var request = this._getRequest('OPENSTREAMINGPORT',path,handler,context);
864			request.setRequestHeader("OPEN", open);
865			request.send('');
866		};
867
868    	// XXX not sure about the order of the args here
869    	this.DavClient.prototype.PROPPATCH = function(path, handler, context,
870                                                  setprops, delprops,
871                                                  locktoken) {
872        	/* perform a PROPPATCH request
873
874            set the metadata of a (single) resource
875
876            'setprops' - a mapping {<namespace>: {<key>: <value>}} of
877                    variables to set
878            'delprops' - a mapping {<namespace>: [<key>]} of variables
879                    to delete
880        	*/
881			var request = this._getRequest('PROPPATCH', path, handler, context);
882			request.setRequestHeader('Content-type', 'text/xml; charset=UTF-8');
883			if (locktoken) {
884				request.setRequestHeader('If', '<' + locktoken + '>');
885			};
886			var xml = this._getProppatchXml(setprops, delprops);
887			request.send(xml);
888		};
889
890    	this.DavClient.prototype.LOCK = function(path, owner, handler, context,
891                                             scope, type, depth, timeout,
892                                             locktoken) {
893	        /* perform a LOCK request
894
895	            set a lock on a resource
896
897	            'owner' - a URL to identify the owner of the lock to be set
898	            'scope' - the scope of the lock, can be 'exclusive' or 'shared'
899	            'type' - the type of lock, can be 'write' (somewhat strange, eh?)
900	            'depth' - can be used to lock (part of) a branch (use 'infinity' as
901	                        value) or just a single target (default)
902	            'timeout' - set the timeout in seconds
903	        */
904	        if (!scope) {
905	            scope = 'exclusive';
906	        };
907	        if (!type) {
908	            type = 'write';
909	        };
910	        var request = this._getRequest('LOCK', path, handler, context);
911	        if (depth) {
912	            request.setRequestHeader('Depth', depth);
913	        }else{
914	        	request.setRequestHeader('Depth', 0);
915	        }
916	        if (!timeout) {
917	            timeout = "Infinite, Second-4100000000";
918	        } else {
919	            timeout = 'Second-' + timeout;
920	        };
921	        if (locktoken) {
922	            request.setRequestHeader('If', '<' + locktoken + '>');
923	        };
924	        request.setRequestHeader("Content-Type", "text/xml; charset=UTF-8");
925	        request.setRequestHeader('Timeout', timeout);
926	        var xml = this._getLockXml(owner, scope, type);
927	        request.send(xml);
928	    };
929
930	    this.DavClient.prototype.UNLOCK = function(path, locktoken,
931	                                               handler, context) {
932	        /* perform an UNLOCK request
933
934	            unlock a previously locked file
935
936	            'token' - the opaque lock token, as can be retrieved from
937	                        content.locktoken using a LOCK request.
938	        */
939	        var request = this._getRequest('UNLOCK', path, handler, context);
940	        request.setRequestHeader("Lock-Token", '<' + locktoken + '>');
941	        request.send('');
942	    };
943
944	    this.DavClient.prototype._getRequest = function(method, path,
945	                                                    handler, context) {
946	        /* prepare a request */
947	        var request = davlib.getXmlHttpRequest();
948	        if (method == 'LOCK') {
949	            // LOCK requires parsing of the body on 200, so has to be treated
950	            // differently
951	            request.onreadystatechange = this._wrapLockHandler(handler,
952	                                                            request, context);
953	        } else {
954	            request.onreadystatechange = this._wrapHandler(handler,
955	                                                            request, context);
956	        };
957
958	        var url = this._generateUrl(path);
959	        request.open(method, url, true);
960
961	        // refuse all encoding, since the browsers don't seem to support it...
962	        //request.setRequestHeader('Accept-Encoding', ' ');
963
964	        /*
965	        var auth = g_storage.get("auth");
966	        if(auth!="" && auth!=undefined){
967	        	alert(path+" / " + auth);
968	        	request.setRequestHeader('Authorization', auth);
969	        }
970	        */
971
972	        return request
973	    };
974
975	    this.DavClient.prototype._wrapHandler = function(handler, request,
976	                                                     context) {
977	        /* wrap the handler with a callback
978
979	            The callback handles multi-status parsing and calls the client's
980	            handler when done
981	        */
982	        var self = this;
983	        function HandlerWrapper() {
984	            this.execute = function() {
985	                if (request.readyState == 4) {
986	                    var status = request.status.toString();
987	                    var headers = self._parseHeaders(
988	                                        request.getAllResponseHeaders());
989	                    var content = request.responseText;
990	                    if (status == '207') {
991	                        //content = self._parseMultiStatus(content);
992	                    };
993	                    var statusstring = davlib.STATUS_CODES[status];
994
995	                    if(handler!=null)
996	                    	handler.call(context, status, statusstring,
997	                                    content, headers);
998	                };
999	            };
1000	        };
1001	        return (new HandlerWrapper().execute);
1002	    };
1003
1004    this.DavClient.prototype._wrapLockHandler = function(handler, request,
1005                                                         context) {
1006        /* wrap the handler for a LOCK response
1007
1008            The callback handles parsing of specific XML for LOCK requests
1009        */
1010        var self = this;
1011        function HandlerWrapper() {
1012            this.execute = function() {
1013                if (request.readyState == 4) {
1014                    var status = request.status.toString();
1015                    var headers = self._parseHeaders(
1016                                        request.getAllResponseHeaders());
1017                    var content = request.responseText;
1018                    if (status == '200') {
1019                        content = self._parseLockinfo(content);
1020                    } else if (status == '207') {
1021                        content = self._parseMultiStatus(content);
1022                    };
1023                    var statusstring = davlib.STATUS_CODES[status];
1024                    handler.call(context, status, statusstring,
1025                                 content, headers);
1026                };
1027            };
1028        };
1029        return (new HandlerWrapper().execute);
1030    };
1031
1032    this.DavClient.prototype._generateUrl = function(path){
1033        /* convert a url from a path */
1034        var url = this.protocol + '://' + this.host;
1035
1036        //if (this.port && this.protocol!='https') {
1037        if (this.port) {
1038            url += ':' + this.port;
1039        };
1040
1041        url += path;
1042
1043        return url;
1044    };
1045
1046    this.DavClient.prototype._parseMultiStatus = function(xml) {
1047        /* parse a multi-status request
1048
1049            see MultiStatusSaxHandler below
1050        */
1051        var handler = new davlib.MultiStatusSAXHandler();
1052        var parser = new SAXParser();
1053        parser.initialize(xml, handler);
1054        parser.parse();
1055        return handler.root;
1056    };
1057
1058    this.DavClient.prototype._parseLockinfo = function(xml) {
1059        /* parse a multi-status request
1060
1061            see MultiStatusSaxHandler below
1062        */
1063        var handler = new davlib.LockinfoSAXHandler();
1064        var parser = new SAXParser();
1065        parser.initialize(xml, handler);
1066        parser.parse();
1067        return handler.lockInfo;
1068    };
1069
1070    this.DavClient.prototype._getProppatchXml = function(setprops, delprops) {
1071        /* create the XML for a PROPPATCH request
1072
1073            setprops is a mapping from namespace to a mapping
1074            of key/value pairs (where value is an *entitized* XML string),
1075            delprops is a mapping from namespace to a list of names
1076        */
1077        var xml = '<?xml version="1.0" encoding="UTF-8" ?>\n' +
1078                    '<D:propertyupdate xmlns:D="DAV:">\n';
1079
1080        var shouldsetprops = false;
1081        for (var attr in setprops) {
1082            shouldsetprops = true;
1083        };
1084        if (shouldsetprops) {
1085            xml += '<D:set>\n';
1086            for (var ns in setprops) {
1087                for (var key in setprops[ns]) {
1088                    xml += '<D:prop>\n' +
1089                            this._preparePropElement(ns, key,
1090                                                     setprops[ns][key]) +
1091                            '</D:prop>\n';
1092                };
1093            };
1094            xml += '</D:set>\n';
1095        };
1096
1097        var shoulddelprops = false;
1098        for (var attr in delprops) {
1099            shoulddelprops = true;
1100        };
1101        if (shoulddelprops) {
1102            xml += '<D:remove>\n<D:prop>\n';
1103            for (var ns in delprops) {
1104                for (var i=0; i < delprops[ns].length; i++) {
1105                    xml += '<' + delprops[ns][i] + ' xmlns="' + ns + '"/>\n';
1106                };
1107            };
1108            xml += '</D:prop>n</D:remove>\n';
1109        };
1110
1111        xml += '</D:propertyupdate>';
1112
1113        return xml;
1114    };
1115
1116    this.DavClient.prototype._getLockXml = function(owner, scope, type) {
1117        var xml = '<?xml version="1.0" encoding="utf-8"?>\n'+
1118                    '<D:lockinfo xmlns:D="DAV:">\n' +
1119                    '<D:lockscope><D:' + scope + ' /></D:lockscope>\n' +
1120                    '<D:locktype><D:' + type + ' /></D:locktype>\n' +
1121                    '<D:owner>\n<D:href>' +
1122                    string.entitize(owner) +
1123                    '</D:href>\n</D:owner>\n' +
1124                    '</D:lockinfo>\n';
1125        return xml;
1126    };
1127
1128    this.DavClient.prototype._preparePropElement = function(ns, key, value) {
1129        /* prepare the DOM for a property
1130
1131            all properties have a DOM value to allow the same structure
1132            as in WebDAV
1133        */
1134        var dom = new dommer.DOM();
1135        // currently we expect the value to be a well-formed bit of XML that
1136        // already contains the ns and key information...
1137        var doc = dom.parseXML(value);
1138        // ... so we don't need the following bit
1139        /*
1140        doc.documentElement._setProtected('nodeName', key);
1141        var pl = key.split(':');
1142        doc.documentElement._setProtected('prefix', pl[0]);
1143        doc.documentElement._setProtected('localName', pl[1]);
1144        doc.namespaceURI = ns;
1145        doc.documentElement._setProtected('namespaceURI', ns);
1146        */
1147        return doc.documentElement.toXML();
1148    };
1149
1150    this.DavClient.prototype._parseHeaders = function(headerstring) {
1151        var lines = headerstring.split('\n');
1152        var headers = {};
1153        for (var i=0; i < lines.length; i++) {
1154            var line = string.strip(lines[i]);
1155            if (!line) {
1156                continue;
1157            };
1158            var chunks = line.split(':');
1159            var key = string.strip(chunks.shift());
1160            var value = string.strip(chunks.join(':'));
1161            var lkey = key.toLowerCase();
1162            if (headers[lkey] !== undefined) {
1163                if (!headers[lkey].push) {
1164                    headers[lkey] = [headers[lkey, value]];
1165                } else {
1166                    headers[lkey].push(value);
1167                };
1168            } else {
1169                headers[lkey] = value;
1170            };
1171        };
1172        return headers;
1173    };
1174
1175    // MultiStatus parsing stuff
1176
1177    this.Resource = function(href, props) {
1178        /* a single resource in a multi-status tree */
1179        this.items = [];
1180        this.parent;
1181        this.properties = {}; // mapping from namespace to key/dom mappings
1182    };
1183
1184    this.Root = function() {
1185        /* although it subclasses from Resource this is merely a container */
1186    };
1187
1188    this.Root.prototype = new this.Resource;
1189
1190    // XXX this whole thing is rather messy...
1191    this.MultiStatusSAXHandler = function() {
1192        /* SAX handler to parse a multi-status response */
1193    };
1194
1195    this.MultiStatusSAXHandler.prototype = new SAXHandler;
1196
1197    this.MultiStatusSAXHandler.prototype.startDocument = function() {
1198        this.resources = [];
1199        this.depth = 0;
1200        this.current = null;
1201        this.current_node = null;
1202        this.current_prop_namespace = null;
1203        this.current_prop_name = null;
1204        this.current_prop_handler = null;
1205        this.prop_start_depth = null;
1206        // array with all nodenames to be able to build a path
1207        // to a node and check for parent and such
1208        this.elements = [];
1209    };
1210
1211    this.MultiStatusSAXHandler.prototype.endDocument = function() {
1212        this.buildTree();
1213    };
1214
1215    this.MultiStatusSAXHandler.prototype.startElement = function(namespace,
1216                                                        nodeName, attributes) {
1217        this.depth++;
1218        this.elements.push([namespace, nodeName]);
1219        davlib.debug('start: ' + namespace + ':' + nodeName);
1220        davlib.debug('parent: ' + (this.elements.length ?
1221                                   this.elements[this.elements.length - 2] :
1222                                   ''));
1223        if (this.current_node == 'property') {
1224            this.current_prop_handler.startElement(namespace, nodeName,
1225                                                   attributes);
1226            return;
1227        };
1228
1229        if (namespace == 'DAV:' && nodeName == 'response') {
1230            var resource = new davlib.Resource();
1231            if (this.current) {
1232                resource.parent = this.current;
1233            };
1234            this.current = resource;
1235            this.resources.push(resource);
1236        } else {
1237            var parent = this.elements[this.elements.length - 2];
1238            if (!parent) {
1239                return;
1240            };
1241            if (namespace == 'DAV:' && parent[0] == 'DAV:' &&
1242                    parent[1] == 'response' || parent[1] == 'propstat') {
1243                // default response vars
1244                if (nodeName == 'href') {
1245                    this.current_node = 'href';
1246                } else if (nodeName == 'status') {
1247                    this.current_node = 'status';
1248                };
1249            } else if (parent[0] == 'DAV:' && parent[1] == 'prop') {
1250                // properties
1251                this.current_node = 'property';
1252                this.current_prop_namespace = namespace;
1253                this.current_prop_name = nodeName;
1254                // use a DOMHandler to propagate calls to for props
1255                this.current_prop_handler = new dommer.DOMHandler();
1256                this.current_prop_handler.startDocument();
1257                this.current_prop_handler.startElement(namespace, nodeName,
1258                                                       attributes);
1259                this.start_prop_depth = this.depth;
1260                davlib.debug('start property');
1261            };
1262        };
1263    };
1264
1265    this.MultiStatusSAXHandler.prototype.endElement = function(namespace,
1266                                                               nodeName) {
1267        davlib.debug('end: ' + namespace + ':' + nodeName);
1268        if (namespace == 'DAV:' && nodeName == 'response') {
1269            if (this.current) {
1270                this.current = this.current.parent;
1271            };
1272        } else if (this.current_node == 'property' &&
1273                namespace == this.current_prop_namespace &&
1274                nodeName == this.current_prop_name &&
1275                this.start_prop_depth == this.depth) {
1276            davlib.debug('end property');
1277            this.current_prop_handler.endElement(namespace, nodeName);
1278            this.current_prop_handler.endDocument();
1279            var dom = new dommer.DOM();
1280            var doc = dom.buildFromHandler(this.current_prop_handler);
1281            if (!this.current.properties[namespace]) {
1282                this.current.properties[namespace] = {};
1283            };
1284            this.current.properties[namespace][this.current_prop_name] = doc;
1285            this.current_prop_namespace = null;
1286            this.current_prop_name = null;
1287            this.current_prop_handler = null;
1288        } else if (this.current_node == 'property') {
1289            this.current_prop_handler.endElement(namespace, nodeName);
1290            this.depth--;
1291            this.elements.pop();
1292            return;
1293        };
1294        this.current_node = null;
1295        this.elements.pop();
1296        this.depth--;
1297    };
1298
1299    this.MultiStatusSAXHandler.prototype.characters = function(data) {
1300        if (this.current_node) {
1301            if (this.current_node == 'status') {
1302                this.current[this.current_node] = data.split(' ')[1];
1303            } else if (this.current_node == 'href') {
1304                this.current[this.current_node] = data;
1305            } else if (this.current_node == 'property') {
1306                this.current_prop_handler.characters(data);
1307            };
1308        };
1309    };
1310
1311    this.MultiStatusSAXHandler.prototype.buildTree = function() {
1312        /* builds a tree from the list of elements */
1313        // XXX Splitting this up wouldn't make it less readable,
1314        // I'd say...
1315
1316        // first find root element
1317        var minlen = -1;
1318        var root;
1319        var rootpath;
1320        // var url_reg = /^.*:\/\/[^\/]*(\/.*)$/;
1321        for (var i=0; i < this.resources.length; i++) {
1322            var resource = this.resources[i];
1323            resource.path = resource.href.split('/');
1324            if (resource.path[resource.path.length - 1] == '') {
1325                resource.path.pop();
1326            };
1327            var len = resource.path.length;
1328            if (minlen == -1 || len < minlen) {
1329                minlen = len;
1330                root = resource;
1331                root.parent = null;
1332            };
1333        };
1334
1335        // now build the tree
1336        // first get a list without the root
1337        var elements = [];
1338        for (var i=0; i < this.resources.length; i++) {
1339            var resource = this.resources[i];
1340            if (resource == root) {
1341                continue;
1342            };
1343            elements.push(resource);
1344        };
1345        while (elements.length) {
1346            var leftovers = [];
1347            for (var i=0; i < elements.length; i++) {
1348                var resource = elements[i];
1349                var path = resource.path;
1350                var current = root;
1351                // we want to walk each element on the path to see if there's
1352                // a corresponding element already available, and if so
1353                // continue walking until we find the parent element of the
1354                // resource
1355                if (path.length == root.path.length + 1) {
1356                    root.items.push(resource);
1357                    resource.parent = root;
1358                } else {
1359                    // XXX still untested, and rather, ehrm, messy...
1360                    for (var j = root.path.length; j < path.length - 1;
1361                            j++) {
1362                        for (var k=0; k < current.items.length; k++) {
1363                            var item = current.items[k];
1364                            if (item.path[item.path.length - 1] ==
1365                                    path[j]) {
1366                                if (j == path.length - 2) {
1367                                    // we have a match at the end of the path
1368                                    // and all elements before that, this is
1369                                    // the current resource's parent
1370                                    item.items.push(resource);
1371                                    resource.parent = item;
1372                                } else {
1373                                    // a match means we this item is one in our
1374                                    // path to the root, follow it
1375                                    current = item;
1376                                };
1377                                break;
1378                            };
1379                        };
1380                    };
1381                    leftovers.push(resource);
1382                };
1383            };
1384            elements = leftovers;
1385        };
1386
1387        this.root = root;
1388    };
1389
1390    this.LockinfoSAXHandler = function() {
1391        /* SAX handler to parse a LOCK response */
1392    };
1393
1394    this.LockinfoSAXHandler.prototype = new SAXHandler;
1395
1396    this.LockinfoSAXHandler.prototype.startDocument = function() {
1397        this.lockInfo = {};
1398        this.currentItem = null;
1399        this.insideHref = false;
1400    };
1401
1402    this.LockinfoSAXHandler.prototype.startElement = function(namespace,
1403                                                              nodeName,
1404                                                              attributes) {
1405        if (namespace == 'DAV:') {
1406            if (nodeName == 'locktype' ||
1407                    nodeName == 'lockscope' ||
1408                    nodeName == 'depth' ||
1409                    nodeName == 'timeout' ||
1410                    nodeName == 'owner' ||
1411                    nodeName == 'locktoken') {
1412                this.currentItem = nodeName;
1413            } else if (nodeName == 'href') {
1414                this.insideHref = true;
1415            };
1416        };
1417    };
1418
1419    this.LockinfoSAXHandler.prototype.endElement = function(namespace,
1420                                                            nodeName) {
1421        if (namespace == 'DAV:') {
1422            if (nodeName == 'href') {
1423                this.insideHref = false;
1424            } else {
1425                this.currentItem = null;
1426            };
1427        };
1428    };
1429
1430    this.LockinfoSAXHandler.prototype.characters = function(data) {
1431        if (this.currentItem &&
1432                (this.currentItem != 'owner' || this.insideHref) &&
1433                (this.currentItem != 'locktoken' || this.insideHref)) {
1434            this.lockInfo[this.currentItem] = data;
1435        };
1436    };
1437
1438    // some helper functions
1439    this.getXmlHttpRequest = function() {
1440
1441    	var sAgent = navigator.userAgent.toLowerCase();
1442    	var isIE = (sAgent.indexOf("msie")!=-1); //IE
1443    	var getInternetExplorerVersion = function(){
1444			var rv = -1; // Return value assumes failure.
1445			if (navigator.appName == 'Microsoft Internet Explorer')
1446			{
1447				var ua = navigator.userAgent;
1448				var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
1449				if (re.exec(ua) != null)
1450					rv = parseFloat( RegExp.$1 );
1451			}
1452			return rv;
1453		};
1454
1455    	/*
1456        instantiate an XMLHTTPRequest
1457
1458        this can be improved by testing the user agent better and, in case
1459        of IE, finding out which MSXML is installed and such, but it
1460        seems to work just fine for now
1461        */
1462
1463        try{
1464        	if(isIE&&getInternetExplorerVersion()<=8&&window.ActiveXObject){
1465        		return new window.ActiveXObject("Microsoft.XMLHTTP");
1466          	}
1467        }
1468        catch(e) {
1469        };
1470
1471		try{
1472			return new XMLHttpRequest();
1473	    }
1474	    catch(e) {
1475	    	// not a Mozilla or Konqueror based browser
1476	    };
1477
1478        alert('Your browser does not support XMLHttpRequest, required for ' +
1479                'WebDAV access.');
1480        throw('Browser not supported');
1481    };
1482
1483    this.debug = function(text) {
1484        /* simple debug function
1485
1486            set the DEBUG global to some true value, and messages will appear
1487            on the bottom of the document
1488        */
1489        if (!davlib.DEBUG) {
1490            return;
1491        };
1492        var div = document.createElement('div');
1493        var text = document.createTextNode(text);
1494        div.appendChild(text);
1495        document.getElementsByTagName('body')[0].appendChild(div);
1496    };
1497}();
1498
1499