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