1 17 18 19 package org.apache.catalina.servlets; 20 21 22 import java.io.IOException ; 23 import java.io.StringWriter ; 24 import java.io.Writer ; 25 import java.security.MessageDigest ; 26 import java.security.NoSuchAlgorithmException ; 27 import java.text.SimpleDateFormat ; 28 import java.util.Date ; 29 import java.util.Enumeration ; 30 import java.util.Hashtable ; 31 import java.util.Stack ; 32 import java.util.TimeZone ; 33 import java.util.Vector ; 34 35 import javax.naming.NameClassPair ; 36 import javax.naming.NamingEnumeration ; 37 import javax.naming.NamingException ; 38 import javax.naming.directory.DirContext ; 39 import javax.servlet.ServletException ; 40 import javax.servlet.UnavailableException ; 41 import javax.servlet.http.HttpServletRequest ; 42 import javax.servlet.http.HttpServletResponse ; 43 import javax.xml.parsers.DocumentBuilder ; 44 import javax.xml.parsers.DocumentBuilderFactory ; 45 import javax.xml.parsers.ParserConfigurationException ; 46 47 import org.apache.catalina.util.DOMWriter; 48 import org.apache.catalina.util.MD5Encoder; 49 import org.apache.catalina.util.RequestUtil; 50 import org.apache.catalina.util.XMLWriter; 51 import org.apache.naming.resources.CacheEntry; 52 import org.apache.naming.resources.Resource; 53 import org.apache.naming.resources.ResourceAttributes; 54 import org.apache.tomcat.util.http.FastHttpDateFormat; 55 import org.w3c.dom.Document ; 56 import org.w3c.dom.Element ; 57 import org.w3c.dom.Node ; 58 import org.w3c.dom.NodeList ; 59 import org.xml.sax.InputSource ; 60 import org.xml.sax.SAXException ; 61 62 63 64 71 72 public class WebdavServlet 73 extends DefaultServlet { 74 75 76 78 79 private static final String METHOD_HEAD = "HEAD"; 80 private static final String METHOD_PROPFIND = "PROPFIND"; 81 private static final String METHOD_PROPPATCH = "PROPPATCH"; 82 private static final String METHOD_MKCOL = "MKCOL"; 83 private static final String METHOD_COPY = "COPY"; 84 private static final String METHOD_MOVE = "MOVE"; 85 private static final String METHOD_LOCK = "LOCK"; 86 private static final String METHOD_UNLOCK = "UNLOCK"; 87 88 89 92 private static final int INFINITY = 3; 94 95 98 private static final int FIND_BY_PROPERTY = 0; 99 100 101 104 private static final int FIND_ALL_PROP = 1; 105 106 107 110 private static final int FIND_PROPERTY_NAMES = 2; 111 112 113 116 private static final int LOCK_CREATION = 0; 117 118 119 122 private static final int LOCK_REFRESH = 1; 123 124 125 128 private static final int DEFAULT_TIMEOUT = 3600; 129 130 131 134 private static final int MAX_TIMEOUT = 604800; 135 136 137 140 protected static final String DEFAULT_NAMESPACE = "DAV:"; 141 142 143 146 protected static final SimpleDateFormat creationDateFormat = 147 new SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ss'Z'"); 148 149 150 153 protected static MessageDigest md5Helper; 154 155 156 159 protected static final MD5Encoder md5Encoder = new MD5Encoder(); 160 161 162 163 static { 164 creationDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); 165 } 166 167 168 170 171 177 private Hashtable resourceLocks = new Hashtable (); 178 179 180 188 private Hashtable lockNullResources = new Hashtable (); 189 190 191 197 private Vector collectionLocks = new Vector (); 198 199 200 203 private String secret = "catalina"; 204 205 206 208 209 212 public void init() 213 throws ServletException { 214 215 super.init(); 216 217 if (getServletConfig().getInitParameter("secret") != null) 218 secret = getServletConfig().getInitParameter("secret"); 219 220 try { 222 md5Helper = MessageDigest.getInstance("MD5"); 223 } catch (NoSuchAlgorithmException e) { 224 throw new UnavailableException ("No MD5"); 225 } 226 227 } 228 229 230 232 233 236 protected DocumentBuilder getDocumentBuilder() 237 throws ServletException { 238 DocumentBuilder documentBuilder = null; 239 DocumentBuilderFactory documentBuilderFactory = null; 240 try { 241 documentBuilderFactory = DocumentBuilderFactory.newInstance(); 242 documentBuilderFactory.setNamespaceAware(true); 243 documentBuilder = documentBuilderFactory.newDocumentBuilder(); 244 } catch(ParserConfigurationException e) { 245 throw new ServletException 246 (sm.getString("webdavservlet.jaxpfailed")); 247 } 248 return documentBuilder; 249 } 250 251 252 255 protected void service(HttpServletRequest req, HttpServletResponse resp) 256 throws ServletException , IOException { 257 258 String method = req.getMethod(); 259 260 if (debug > 0) { 261 String path = getRelativePath(req); 262 log("[" + method + "] " + path); 263 } 264 265 if (method.equals(METHOD_PROPFIND)) { 266 doPropfind(req, resp); 267 } else if (method.equals(METHOD_PROPPATCH)) { 268 doProppatch(req, resp); 269 } else if (method.equals(METHOD_MKCOL)) { 270 doMkcol(req, resp); 271 } else if (method.equals(METHOD_COPY)) { 272 doCopy(req, resp); 273 } else if (method.equals(METHOD_MOVE)) { 274 doMove(req, resp); 275 } else if (method.equals(METHOD_LOCK)) { 276 doLock(req, resp); 277 } else if (method.equals(METHOD_UNLOCK)) { 278 doUnlock(req, resp); 279 } else { 280 super.service(req, resp); 282 } 283 284 } 285 286 287 298 protected boolean checkIfHeaders(HttpServletRequest request, 299 HttpServletResponse response, 300 ResourceAttributes resourceAttributes) 301 throws IOException { 302 303 if (!super.checkIfHeaders(request, response, resourceAttributes)) 304 return false; 305 306 return true; 308 309 } 310 311 312 320 protected void doOptions(HttpServletRequest req, HttpServletResponse resp) 321 throws ServletException , IOException { 322 323 resp.addHeader("DAV", "1,2"); 324 325 StringBuffer methodsAllowed = determineMethodsAllowed(resources, 326 req); 327 328 resp.addHeader("Allow", methodsAllowed.toString()); 329 resp.addHeader("MS-Author-Via", "DAV"); 330 331 } 332 333 334 337 protected void doPropfind(HttpServletRequest req, HttpServletResponse resp) 338 throws ServletException , IOException { 339 340 if (!listings) { 341 StringBuffer methodsAllowed = determineMethodsAllowed(resources, 343 req); 344 345 resp.addHeader("Allow", methodsAllowed.toString()); 346 resp.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED); 347 return; 348 } 349 350 String path = getRelativePath(req); 351 if (path.endsWith("/")) 352 path = path.substring(0, path.length() - 1); 353 354 if ((path.toUpperCase().startsWith("/WEB-INF")) || 355 (path.toUpperCase().startsWith("/META-INF"))) { 356 resp.sendError(WebdavStatus.SC_FORBIDDEN); 357 return; 358 } 359 360 Vector properties = null; 362 int depth = INFINITY; 364 int type = FIND_ALL_PROP; 366 367 String depthStr = req.getHeader("Depth"); 368 369 if (depthStr == null) { 370 depth = INFINITY; 371 } else { 372 if (depthStr.equals("0")) { 373 depth = 0; 374 } else if (depthStr.equals("1")) { 375 depth = 1; 376 } else if (depthStr.equals("infinity")) { 377 depth = INFINITY; 378 } 379 } 380 381 Node propNode = null; 382 383 DocumentBuilder documentBuilder = getDocumentBuilder(); 384 385 try { 386 Document document = documentBuilder.parse 387 (new InputSource (req.getInputStream())); 388 389 Element rootElement = document.getDocumentElement(); 391 NodeList childList = rootElement.getChildNodes(); 392 393 for (int i=0; i < childList.getLength(); i++) { 394 Node currentNode = childList.item(i); 395 switch (currentNode.getNodeType()) { 396 case Node.TEXT_NODE: 397 break; 398 case Node.ELEMENT_NODE: 399 if (currentNode.getNodeName().endsWith("prop")) { 400 type = FIND_BY_PROPERTY; 401 propNode = currentNode; 402 } 403 if (currentNode.getNodeName().endsWith("propname")) { 404 type = FIND_PROPERTY_NAMES; 405 } 406 if (currentNode.getNodeName().endsWith("allprop")) { 407 type = FIND_ALL_PROP; 408 } 409 break; 410 } 411 } 412 } catch (SAXException e) { 413 } catch (IOException e) { 415 } 417 418 if (type == FIND_BY_PROPERTY) { 419 properties = new Vector (); 420 NodeList childList = propNode.getChildNodes(); 421 422 for (int i=0; i < childList.getLength(); i++) { 423 Node currentNode = childList.item(i); 424 switch (currentNode.getNodeType()) { 425 case Node.TEXT_NODE: 426 break; 427 case Node.ELEMENT_NODE: 428 String nodeName = currentNode.getNodeName(); 429 String propertyName = null; 430 if (nodeName.indexOf(':') != -1) { 431 propertyName = nodeName.substring 432 (nodeName.indexOf(':') + 1); 433 } else { 434 propertyName = nodeName; 435 } 436 properties.addElement(propertyName); 438 break; 439 } 440 } 441 442 } 443 444 boolean exists = true; 445 Object object = null; 446 try { 447 object = resources.lookup(path); 448 } catch (NamingException e) { 449 exists = false; 450 int slash = path.lastIndexOf('/'); 451 if (slash != -1) { 452 String parentPath = path.substring(0, slash); 453 Vector currentLockNullResources = 454 (Vector ) lockNullResources.get(parentPath); 455 if (currentLockNullResources != null) { 456 Enumeration lockNullResourcesList = 457 currentLockNullResources.elements(); 458 while (lockNullResourcesList.hasMoreElements()) { 459 String lockNullPath = (String ) 460 lockNullResourcesList.nextElement(); 461 if (lockNullPath.equals(path)) { 462 resp.setStatus(WebdavStatus.SC_MULTI_STATUS); 463 resp.setContentType("text/xml; charset=UTF-8"); 464 XMLWriter generatedXML = 466 new XMLWriter(resp.getWriter()); 467 generatedXML.writeXMLHeader(); 468 generatedXML.writeElement 469 (null, "multistatus" 470 + generateNamespaceDeclarations(), 471 XMLWriter.OPENING); 472 parseLockNullProperties 473 (req, generatedXML, lockNullPath, type, 474 properties); 475 generatedXML.writeElement(null, "multistatus", 476 XMLWriter.CLOSING); 477 generatedXML.sendData(); 478 return; 479 } 480 } 481 } 482 } 483 } 484 485 if (!exists) { 486 resp.sendError(HttpServletResponse.SC_NOT_FOUND, path); 487 return; 488 } 489 490 resp.setStatus(WebdavStatus.SC_MULTI_STATUS); 491 492 resp.setContentType("text/xml; charset=UTF-8"); 493 494 XMLWriter generatedXML = new XMLWriter(resp.getWriter()); 496 generatedXML.writeXMLHeader(); 497 498 generatedXML.writeElement(null, "multistatus" 499 + generateNamespaceDeclarations(), 500 XMLWriter.OPENING); 501 502 if (depth == 0) { 503 parseProperties(req, generatedXML, path, type, 504 properties); 505 } else { 506 Stack stack = new Stack (); 508 stack.push(path); 509 510 Stack stackBelow = new Stack (); 512 513 while ((!stack.isEmpty()) && (depth >= 0)) { 514 515 String currentPath = (String ) stack.pop(); 516 parseProperties(req, generatedXML, currentPath, 517 type, properties); 518 519 try { 520 object = resources.lookup(currentPath); 521 } catch (NamingException e) { 522 continue; 523 } 524 525 if ((object instanceof DirContext ) && (depth > 0)) { 526 527 try { 528 NamingEnumeration enumeration = resources.list(currentPath); 529 while (enumeration.hasMoreElements()) { 530 NameClassPair ncPair = 531 (NameClassPair ) enumeration.nextElement(); 532 String newPath = currentPath; 533 if (!(newPath.endsWith("/"))) 534 newPath += "/"; 535 newPath += ncPair.getName(); 536 stackBelow.push(newPath); 537 } 538 } catch (NamingException e) { 539 resp.sendError 540 (HttpServletResponse.SC_INTERNAL_SERVER_ERROR, 541 path); 542 return; 543 } 544 545 String lockPath = currentPath; 548 if (lockPath.endsWith("/")) 549 lockPath = 550 lockPath.substring(0, lockPath.length() - 1); 551 Vector currentLockNullResources = 552 (Vector ) lockNullResources.get(lockPath); 553 if (currentLockNullResources != null) { 554 Enumeration lockNullResourcesList = 555 currentLockNullResources.elements(); 556 while (lockNullResourcesList.hasMoreElements()) { 557 String lockNullPath = (String ) 558 lockNullResourcesList.nextElement(); 559 parseLockNullProperties 560 (req, generatedXML, lockNullPath, type, 561 properties); 562 } 563 } 564 565 } 566 567 if (stack.isEmpty()) { 568 depth--; 569 stack = stackBelow; 570 stackBelow = new Stack (); 571 } 572 573 generatedXML.sendData(); 574 575 } 576 } 577 578 generatedXML.writeElement(null, "multistatus", 579 XMLWriter.CLOSING); 580 581 generatedXML.sendData(); 582 583 } 584 585 586 589 protected void doProppatch(HttpServletRequest req, 590 HttpServletResponse resp) 591 throws ServletException , IOException { 592 593 if (readOnly) { 594 resp.sendError(WebdavStatus.SC_FORBIDDEN); 595 return; 596 } 597 598 if (isLocked(req)) { 599 resp.sendError(WebdavStatus.SC_LOCKED); 600 return; 601 } 602 603 resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED); 604 605 } 606 607 608 611 protected void doMkcol(HttpServletRequest req, HttpServletResponse resp) 612 throws ServletException , IOException { 613 614 if (readOnly) { 615 resp.sendError(WebdavStatus.SC_FORBIDDEN); 616 return; 617 } 618 619 if (isLocked(req)) { 620 resp.sendError(WebdavStatus.SC_LOCKED); 621 return; 622 } 623 624 String path = getRelativePath(req); 625 626 if ((path.toUpperCase().startsWith("/WEB-INF")) || 627 (path.toUpperCase().startsWith("/META-INF"))) { 628 resp.sendError(WebdavStatus.SC_FORBIDDEN); 629 return; 630 } 631 632 boolean exists = true; 633 Object object = null; 634 try { 635 object = resources.lookup(path); 636 } catch (NamingException e) { 637 exists = false; 638 } 639 640 if (exists) { 643 StringBuffer methodsAllowed = determineMethodsAllowed(resources, 645 req); 646 647 resp.addHeader("Allow", methodsAllowed.toString()); 648 649 resp.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED); 650 return; 651 } 652 653 if (req.getInputStream().available() > 0) { 654 DocumentBuilder documentBuilder = getDocumentBuilder(); 655 try { 656 Document document = documentBuilder.parse 657 (new InputSource (req.getInputStream())); 658 resp.sendError(WebdavStatus.SC_NOT_IMPLEMENTED); 660 return; 661 662 } catch(SAXException saxe) { 663 resp.sendError(WebdavStatus.SC_BAD_REQUEST); 665 return; 666 } 667 } 668 669 boolean result = true; 670 try { 671 resources.createSubcontext(path); 672 } catch (NamingException e) { 673 result = false; 674 } 675 676 if (!result) { 677 resp.sendError(WebdavStatus.SC_CONFLICT, 678 WebdavStatus.getStatusText 679 (WebdavStatus.SC_CONFLICT)); 680 } else { 681 resp.setStatus(WebdavStatus.SC_CREATED); 682 lockNullResources.remove(path); 684 } 685 686 } 687 688 689 692 protected void doDelete(HttpServletRequest req, HttpServletResponse resp) 693 throws ServletException , IOException { 694 695 if (readOnly) { 696 resp.sendError(WebdavStatus.SC_FORBIDDEN); 697 return; 698 } 699 700 if (isLocked(req)) { 701 resp.sendError(WebdavStatus.SC_LOCKED); 702 return; 703 } 704 705 deleteResource(req, resp); 706 707 } 708 709 710 719 protected void doPut(HttpServletRequest req, HttpServletResponse resp) 720 throws ServletException , IOException { 721 722 if (isLocked(req)) { 723 resp.sendError(WebdavStatus.SC_LOCKED); 724 return; 725 } 726 727 super.doPut(req, resp); 728 729 String path = getRelativePath(req); 730 731 lockNullResources.remove(path); 733 734 } 735 736 739 protected void doCopy(HttpServletRequest req, HttpServletResponse resp) 740 throws ServletException , IOException { 741 742 if (readOnly) { 743 resp.sendError(WebdavStatus.SC_FORBIDDEN); 744 return; 745 } 746 747 copyResource(req, resp); 748 749 } 750 751 752 755 protected void doMove(HttpServletRequest req, HttpServletResponse resp) 756 throws ServletException , IOException { 757 758 if (readOnly) { 759 resp.sendError(WebdavStatus.SC_FORBIDDEN); 760 return; 761 } 762 763 if (isLocked(req)) { 764 resp.sendError(WebdavStatus.SC_LOCKED); 765 return; 766 } 767 768 String path = getRelativePath(req); 769 770 if (copyResource(req, resp)) { 771 deleteResource(path, req, resp, false); 772 } 773 774 } 775 776 777 780 protected void doLock(HttpServletRequest req, HttpServletResponse resp) 781 throws ServletException , IOException { 782 783 if (readOnly) { 784 resp.sendError(WebdavStatus.SC_FORBIDDEN); 785 return; 786 } 787 788 if (isLocked(req)) { 789 resp.sendError(WebdavStatus.SC_LOCKED); 790 return; 791 } 792 793 LockInfo lock = new LockInfo(); 794 795 797 799 String depthStr = req.getHeader("Depth"); 800 801 if (depthStr == null) { 802 lock.depth = INFINITY; 803 } else { 804 if (depthStr.equals("0")) { 805 lock.depth = 0; 806 } else { 807 lock.depth = INFINITY; 808 } 809 } 810 811 813 int lockDuration = DEFAULT_TIMEOUT; 814 String lockDurationStr = req.getHeader("Timeout"); 815 if (lockDurationStr == null) { 816 lockDuration = DEFAULT_TIMEOUT; 817 } else { 818 int commaPos = lockDurationStr.indexOf(","); 819 if (commaPos != -1) { 821 lockDurationStr = lockDurationStr.substring(0,commaPos); 822 } 823 if (lockDurationStr.startsWith("Second-")) { 824 lockDuration = 825 (new Integer (lockDurationStr.substring(7))).intValue(); 826 } else { 827 if (lockDurationStr.equalsIgnoreCase("infinity")) { 828 lockDuration = MAX_TIMEOUT; 829 } else { 830 try { 831 lockDuration = 832 (new Integer (lockDurationStr)).intValue(); 833 } catch (NumberFormatException e) { 834 lockDuration = MAX_TIMEOUT; 835 } 836 } 837 } 838 if (lockDuration == 0) { 839 lockDuration = DEFAULT_TIMEOUT; 840 } 841 if (lockDuration > MAX_TIMEOUT) { 842 lockDuration = MAX_TIMEOUT; 843 } 844 } 845 lock.expiresAt = System.currentTimeMillis() + (lockDuration * 1000); 846 847 int lockRequestType = LOCK_CREATION; 848 849 Node lockInfoNode = null; 850 851 DocumentBuilder documentBuilder = getDocumentBuilder(); 852 853 try { 854 Document document = documentBuilder.parse(new InputSource 855 (req.getInputStream())); 856 857 Element rootElement = document.getDocumentElement(); 859 lockInfoNode = rootElement; 860 } catch (IOException e) { 861 lockRequestType = LOCK_REFRESH; 862 } catch (SAXException e) { 863 lockRequestType = LOCK_REFRESH; 864 } 865 866 if (lockInfoNode != null) { 867 868 870 NodeList childList = lockInfoNode.getChildNodes(); 871 StringWriter strWriter = null; 872 DOMWriter domWriter = null; 873 874 Node lockScopeNode = null; 875 Node lockTypeNode = null; 876 Node lockOwnerNode = null; 877 878 for (int i=0; i < childList.getLength(); i++) { 879 Node currentNode = childList.item(i); 880 switch (currentNode.getNodeType()) { 881 case Node.TEXT_NODE: 882 break; 883 case Node.ELEMENT_NODE: 884 String nodeName = currentNode.getNodeName(); 885 if (nodeName.endsWith("lockscope")) { 886 lockScopeNode = currentNode; 887 } 888 if (nodeName.endsWith("locktype")) { 889 lockTypeNode = currentNode; 890 } 891 if (nodeName.endsWith("owner")) { 892 lockOwnerNode = currentNode; 893 } 894 break; 895 } 896 } 897 898 if (lockScopeNode != null) { 899 900 childList = lockScopeNode.getChildNodes(); 901 for (int i=0; i < childList.getLength(); i++) { 902 Node currentNode = childList.item(i); 903 switch (currentNode.getNodeType()) { 904 case Node.TEXT_NODE: 905 break; 906 case Node.ELEMENT_NODE: 907 String tempScope = currentNode.getNodeName(); 908 if (tempScope.indexOf(':') != -1) { 909 lock.scope = tempScope.substring 910 (tempScope.indexOf(':') + 1); 911 } else { 912 lock.scope = tempScope; 913 } 914 break; 915 } 916 } 917 918 if (lock.scope == null) { 919 resp.setStatus(WebdavStatus.SC_BAD_REQUEST); 921 } 922 923 } else { 924 resp.setStatus(WebdavStatus.SC_BAD_REQUEST); 926 } 927 928 if (lockTypeNode != null) { 929 930 childList = lockTypeNode.getChildNodes(); 931 for (int i=0; i < childList.getLength(); i++) { 932 Node currentNode = childList.item(i); 933 switch (currentNode.getNodeType()) { 934 case Node.TEXT_NODE: 935 break; 936 case Node.ELEMENT_NODE: 937 String tempType = currentNode.getNodeName(); 938 if (tempType.indexOf(':') != -1) { 939 lock.type = 940 tempType.substring(tempType.indexOf(':') + 1); 941 } else { 942 lock.type = tempType; 943 } 944 break; 945 } 946 } 947 948 if (lock.type == null) { 949 resp.setStatus(WebdavStatus.SC_BAD_REQUEST); 951 } 952 953 } else { 954 resp.setStatus(WebdavStatus.SC_BAD_REQUEST); 956 } 957 958 if (lockOwnerNode != null) { 959 960 childList = lockOwnerNode.getChildNodes(); 961 for (int i=0; i < childList.getLength(); i++) { 962 Node currentNode = childList.item(i); 963 switch (currentNode.getNodeType()) { 964 case Node.TEXT_NODE: 965 lock.owner += currentNode.getNodeValue(); 966 break; 967 case Node.ELEMENT_NODE: 968 strWriter = new StringWriter (); 969 domWriter = new DOMWriter(strWriter, true); 970 domWriter.setQualifiedNames(false); 971 domWriter.print(currentNode); 972 lock.owner += strWriter.toString(); 973 break; 974 } 975 } 976 977 if (lock.owner == null) { 978 resp.setStatus(WebdavStatus.SC_BAD_REQUEST); 980 } 981 982 } else { 983 lock.owner = new String (); 984 } 985 986 } 987 988 String path = getRelativePath(req); 989 990 lock.path = path; 991 992 boolean exists = true; 993 Object object = null; 994 try { 995 object = resources.lookup(path); 996 } catch (NamingException e) { 997 exists = false; 998 } 999 1000 Enumeration locksList = null; 1001 1002 if (lockRequestType == LOCK_CREATION) { 1003 1004 String lockTokenStr = req.getServletPath() + "-" + lock.type + "-" 1006 + lock.scope + "-" + req.getUserPrincipal() + "-" 1007 + lock.depth + "-" + lock.owner + "-" + lock.tokens + "-" 1008 + lock.expiresAt + "-" + System.currentTimeMillis() + "-" 1009 + secret; 1010 String lockToken = 1011 md5Encoder.encode(md5Helper.digest(lockTokenStr.getBytes())); 1012 1013 if ( (exists) && (object instanceof DirContext ) && 1014 (lock.depth == INFINITY) ) { 1015 1016 1018 Vector lockPaths = new Vector (); 1021 locksList = collectionLocks.elements(); 1022 while (locksList.hasMoreElements()) { 1023 LockInfo currentLock = (LockInfo) locksList.nextElement(); 1024 if (currentLock.hasExpired()) { 1025 resourceLocks.remove(currentLock.path); 1026 continue; 1027 } 1028 if ( (currentLock.path.startsWith(lock.path)) && 1029 ((currentLock.isExclusive()) || 1030 (lock.isExclusive())) ) { 1031 lockPaths.addElement(currentLock.path); 1033 } 1034 } 1035 locksList = resourceLocks.elements(); 1036 while (locksList.hasMoreElements()) { 1037 LockInfo currentLock = (LockInfo) locksList.nextElement(); 1038 if (currentLock.hasExpired()) { 1039 resourceLocks.remove(currentLock.path); 1040 continue; 1041 } 1042 if ( (currentLock.path.startsWith(lock.path)) && 1043 ((currentLock.isExclusive()) || 1044 (lock.isExclusive())) ) { 1045 lockPaths.addElement(currentLock.path); 1047 } 1048 } 1049 1050 if (!lockPaths.isEmpty()) { 1051 1052 1055 Enumeration lockPathsList = lockPaths.elements(); 1056 1057 resp.setStatus(WebdavStatus.SC_CONFLICT); 1058 1059 XMLWriter generatedXML = new XMLWriter(); 1060 generatedXML.writeXMLHeader(); 1061 1062 generatedXML.writeElement 1063 (null, "multistatus" + generateNamespaceDeclarations(), 1064 XMLWriter.OPENING); 1065 1066 while (lockPathsList.hasMoreElements()) { 1067 generatedXML.writeElement(null, "response", 1068 XMLWriter.OPENING); 1069 generatedXML.writeElement(null, "href", 1070 XMLWriter.OPENING); 1071 generatedXML 1072 .writeText((String ) lockPathsList.nextElement()); 1073 generatedXML.writeElement(null, "href", 1074 XMLWriter.CLOSING); 1075 generatedXML.writeElement(null, "status", 1076 XMLWriter.OPENING); 1077 generatedXML 1078 .writeText("HTTP/1.1 " + WebdavStatus.SC_LOCKED 1079 + " " + WebdavStatus 1080 .getStatusText(WebdavStatus.SC_LOCKED)); 1081 generatedXML.writeElement(null, "status", 1082 XMLWriter.CLOSING); 1083 1084 generatedXML.writeElement(null, "response", 1085 XMLWriter.CLOSING); 1086 } 1087 1088 generatedXML.writeElement(null, "multistatus", 1089 XMLWriter.CLOSING); 1090 1091 Writer writer = resp.getWriter(); 1092 writer.write(generatedXML.toString()); 1093 writer.close(); 1094 1095 return; 1096 1097 } 1098 1099 boolean addLock = true; 1100 1101 locksList = collectionLocks.elements(); 1103 while (locksList.hasMoreElements()) { 1104 1105 LockInfo currentLock = (LockInfo) locksList.nextElement(); 1106 if (currentLock.path.equals(lock.path)) { 1107 1108 if (currentLock.isExclusive()) { 1109 resp.sendError(WebdavStatus.SC_LOCKED); 1110 return; 1111 } else { 1112 if (lock.isExclusive()) { 1113 resp.sendError(WebdavStatus.SC_LOCKED); 1114 return; 1115 } 1116 } 1117 1118 currentLock.tokens.addElement(lockToken); 1119 lock = currentLock; 1120 addLock = false; 1121 1122 } 1123 1124 } 1125 1126 if (addLock) { 1127 lock.tokens.addElement(lockToken); 1128 collectionLocks.addElement(lock); 1129 } 1130 1131 } else { 1132 1133 1135 LockInfo presentLock = (LockInfo) resourceLocks.get(lock.path); 1137 if (presentLock != null) { 1138 1139 if ((presentLock.isExclusive()) || (lock.isExclusive())) { 1140 resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED); 1143 return; 1144 } else { 1145 presentLock.tokens.addElement(lockToken); 1146 lock = presentLock; 1147 } 1148 1149 } else { 1150 1151 lock.tokens.addElement(lockToken); 1152 resourceLocks.put(lock.path, lock); 1153 1154 exists = true; 1156 try { 1157 object = resources.lookup(path); 1158 } catch (NamingException e) { 1159 exists = false; 1160 } 1161 if (!exists) { 1162 1163 int slash = lock.path.lastIndexOf('/'); 1165 String parentPath = lock.path.substring(0, slash); 1166 1167 Vector lockNulls = 1168 (Vector ) lockNullResources.get(parentPath); 1169 if (lockNulls == null) { 1170 lockNulls = new Vector (); 1171 lockNullResources.put(parentPath, lockNulls); 1172 } 1173 1174 lockNulls.addElement(lock.path); 1175 1176 } 1177 resp.addHeader("Lock-Token", "<opaquelocktoken:" 1180 + lockToken + ">"); 1181 } 1182 1183 } 1184 1185 } 1186 1187 if (lockRequestType == LOCK_REFRESH) { 1188 1189 String ifHeader = req.getHeader("If"); 1190 if (ifHeader == null) 1191 ifHeader = ""; 1192 1193 1195 LockInfo toRenew = (LockInfo) resourceLocks.get(path); 1196 Enumeration tokenList = null; 1197 if (lock != null) { 1198 1199 1201 tokenList = toRenew.tokens.elements(); 1202 while (tokenList.hasMoreElements()) { 1203 String token = (String ) tokenList.nextElement(); 1204 if (ifHeader.indexOf(token) != -1) { 1205 toRenew.expiresAt = lock.expiresAt; 1206 lock = toRenew; 1207 } 1208 } 1209 1210 } 1211 1212 1214 Enumeration collectionLocksList = collectionLocks.elements(); 1215 while (collectionLocksList.hasMoreElements()) { 1216 toRenew = (LockInfo) collectionLocksList.nextElement(); 1217 if (path.equals(toRenew.path)) { 1218 1219 tokenList = toRenew.tokens.elements(); 1220 while (tokenList.hasMoreElements()) { 1221 String token = (String ) tokenList.nextElement(); 1222 if (ifHeader.indexOf(token) != -1) { 1223 toRenew.expiresAt = lock.expiresAt; 1224 lock = toRenew; 1225 } 1226 } 1227 1228 } 1229 } 1230 1231 } 1232 1233 XMLWriter generatedXML = new XMLWriter(); 1236 generatedXML.writeXMLHeader(); 1237 generatedXML.writeElement(null, "prop" 1238 + generateNamespaceDeclarations(), 1239 XMLWriter.OPENING); 1240 1241 generatedXML.writeElement(null, "lockdiscovery", 1242 XMLWriter.OPENING); 1243 1244 lock.toXML(generatedXML); 1245 1246 generatedXML.writeElement(null, "lockdiscovery", 1247 XMLWriter.CLOSING); 1248 1249 generatedXML.writeElement(null, "prop", XMLWriter.CLOSING); 1250 1251 resp.setStatus(WebdavStatus.SC_OK); 1252 resp.setContentType("text/xml; charset=UTF-8"); 1253 Writer writer = resp.getWriter(); 1254 writer.write(generatedXML.toString()); 1255 writer.close(); 1256 1257 } 1258 1259 1260 1263 protected void doUnlock(HttpServletRequest req, HttpServletResponse resp) 1264 throws ServletException , IOException { 1265 1266 if (readOnly) { 1267 resp.sendError(WebdavStatus.SC_FORBIDDEN); 1268 return; 1269 } 1270 1271 if (isLocked(req)) { 1272 resp.sendError(WebdavStatus.SC_LOCKED); 1273 return; 1274 } 1275 1276 String path = getRelativePath(req); 1277 1278 String lockTokenHeader = req.getHeader("Lock-Token"); 1279 if (lockTokenHeader == null) 1280 lockTokenHeader = ""; 1281 1282 1284 LockInfo lock = (LockInfo) resourceLocks.get(path); 1285 Enumeration tokenList = null; 1286 if (lock != null) { 1287 1288 1290 tokenList = lock.tokens.elements(); 1291 while (tokenList.hasMoreElements()) { 1292 String token = (String ) tokenList.nextElement(); 1293 if (lockTokenHeader.indexOf(token) != -1) { 1294 lock.tokens.removeElement(token); 1295 } 1296 } 1297 1298 if (lock.tokens.isEmpty()) { 1299 resourceLocks.remove(path); 1300 lockNullResources.remove(path); 1302 } 1303 1304 } 1305 1306 1308 Enumeration collectionLocksList = collectionLocks.elements(); 1309 while (collectionLocksList.hasMoreElements()) { 1310 lock = (LockInfo) collectionLocksList.nextElement(); 1311 if (path.equals(lock.path)) { 1312 1313 tokenList = lock.tokens.elements(); 1314 while (tokenList.hasMoreElements()) { 1315 String token = (String ) tokenList.nextElement(); 1316 if (lockTokenHeader.indexOf(token) != -1) { 1317 lock.tokens.removeElement(token); 1318 break; 1319 } 1320 } 1321 1322 if (lock.tokens.isEmpty()) { 1323 collectionLocks.removeElement(lock); 1324 lockNullResources.remove(path); 1326 } 1327 1328 } 1329 } 1330 1331 resp.setStatus(WebdavStatus.SC_NO_CONTENT); 1332 1333 } 1334 1335 1344 protected String normalize(String path) { 1345 1346 if (path == null) 1347 return null; 1348 1349 String normalized = path; 1351 1352 if (normalized == null) 1353 return (null); 1354 1355 if (normalized.equals("/.")) 1356 return "/"; 1357 1358 if (normalized.indexOf('\\') >= 0) 1360 normalized = normalized.replace('\\', '/'); 1361 if (!normalized.startsWith("/")) 1362 normalized = "/" + normalized; 1363 1364 while (true) { 1366 int index = normalized.indexOf("//"); 1367 if (index < 0) 1368 break; 1369 normalized = normalized.substring(0, index) + 1370 normalized.substring(index + 1); 1371 } 1372 1373 while (true) { 1375 int index = normalized.indexOf("/./"); 1376 if (index < 0) 1377 break; 1378 normalized = normalized.substring(0, index) + 1379 normalized.substring(index + 2); 1380 } 1381 1382 while (true) { 1384 int index = normalized.indexOf("/../"); 1385 if (index < 0) 1386 break; 1387 if (index == 0) 1388 return (null); int index2 = normalized.lastIndexOf('/', index - 1); 1390 normalized = normalized.substring(0, index2) + 1391 normalized.substring(index + 3); 1392 } 1393 1394 return (normalized); 1396 1397 } 1398 1399 1400 1402 1405 private String generateNamespaceDeclarations() { 1406 return " xmlns=\"" + DEFAULT_NAMESPACE + "\""; 1407 } 1408 1409 1410 1420 private boolean isLocked(HttpServletRequest req) { 1421 1422 String path = getRelativePath(req); 1423 1424 String ifHeader = req.getHeader("If"); 1425 if (ifHeader == null) 1426 ifHeader = ""; 1427 1428 String lockTokenHeader = req.getHeader("Lock-Token"); 1429 if (lockTokenHeader == null) 1430 lockTokenHeader = ""; 1431 1432 return isLocked(path, ifHeader + lockTokenHeader); 1433 1434 } 1435 1436 1437 1446 private boolean isLocked(String path, String ifHeader) { 1447 1448 1450 LockInfo lock = (LockInfo) resourceLocks.get(path); 1451 Enumeration tokenList = null; 1452 if ((lock != null) && (lock.hasExpired())) { 1453 resourceLocks.remove(path); 1454 } else if (lock != null) { 1455 1456 1458 tokenList = lock.tokens.elements(); 1459 boolean tokenMatch = false; 1460 while (tokenList.hasMoreElements()) { 1461 String token = (String ) tokenList.nextElement(); 1462 if (ifHeader.indexOf(token) != -1) 1463 tokenMatch = true; 1464 } 1465 if (!tokenMatch) 1466 return true; 1467 1468 } 1469 1470 1472 Enumeration collectionLocksList = collectionLocks.elements(); 1473 while (collectionLocksList.hasMoreElements()) { 1474 lock = (LockInfo) collectionLocksList.nextElement(); 1475 if (lock.hasExpired()) { 1476 collectionLocks.removeElement(lock); 1477 } else if (path.startsWith(lock.path)) { 1478 1479 tokenList = lock.tokens.elements(); 1480 boolean tokenMatch = false; 1481 while (tokenList.hasMoreElements()) { 1482 String token = (String ) tokenList.nextElement(); 1483 if (ifHeader.indexOf(token) != -1) 1484 tokenMatch = true; 1485 } 1486 if (!tokenMatch) 1487 return true; 1488 1489 } 1490 } 1491 1492 return false; 1493 1494 } 1495 1496 1497 1504 private boolean copyResource(HttpServletRequest req, 1505 HttpServletResponse resp) 1506 throws ServletException , IOException { 1507 1508 1510 String destinationPath = req.getHeader("Destination"); 1511 1512 if (destinationPath == null) { 1513 resp.sendError(WebdavStatus.SC_BAD_REQUEST); 1514 return false; 1515 } 1516 1517 destinationPath = RequestUtil.URLDecode(destinationPath, "UTF8"); 1519 1520 int protocolIndex = destinationPath.indexOf("://"); 1521 if (protocolIndex >= 0) { 1522 int firstSeparator = 1525 destinationPath.indexOf("/", protocolIndex + 4); 1526 if (firstSeparator < 0) { 1527 destinationPath = "/"; 1528 } else { 1529 destinationPath = destinationPath.substring(firstSeparator); 1530 } 1531 } else { 1532 String hostName = req.getServerName(); 1533 if ((hostName != null) && (destinationPath.startsWith(hostName))) { 1534 destinationPath = destinationPath.substring(hostName.length()); 1535 } 1536 1537 int portIndex = destinationPath.indexOf(":"); 1538 if (portIndex >= 0) { 1539 destinationPath = destinationPath.substring(portIndex); 1540 } 1541 1542 if (destinationPath.startsWith(":")) { 1543 int firstSeparator = destinationPath.indexOf("/"); 1544 if (firstSeparator < 0) { 1545 destinationPath = "/"; 1546 } else { 1547 destinationPath = 1548 destinationPath.substring(firstSeparator); 1549 } 1550 } 1551 } 1552 1553 destinationPath = normalize(destinationPath); 1555 1556 String contextPath = req.getContextPath(); 1557 if ((contextPath != null) && 1558 (destinationPath.startsWith(contextPath))) { 1559 destinationPath = destinationPath.substring(contextPath.length()); 1560 } 1561 1562 String pathInfo = req.getPathInfo(); 1563 if (pathInfo != null) { 1564 String servletPath = req.getServletPath(); 1565 if ((servletPath != null) && 1566 (destinationPath.startsWith(servletPath))) { 1567 destinationPath = destinationPath 1568 .substring(servletPath.length()); 1569 } 1570 } 1571 1572 if (debug > 0) 1573 log("Dest path :" + destinationPath); 1574 1575 if ((destinationPath.toUpperCase().startsWith("/WEB-INF")) || 1576 (destinationPath.toUpperCase().startsWith("/META-INF"))) { 1577 resp.sendError(WebdavStatus.SC_FORBIDDEN); 1578 return false; 1579 } 1580 1581 String path = getRelativePath(req); 1582 1583 if ((path.toUpperCase().startsWith("/WEB-INF")) || 1584 (path.toUpperCase().startsWith("/META-INF"))) { 1585 resp.sendError(WebdavStatus.SC_FORBIDDEN); 1586 return false; 1587 } 1588 1589 if (destinationPath.equals(path)) { 1590 resp.sendError(WebdavStatus.SC_FORBIDDEN); 1591 return false; 1592 } 1593 1594 1596 boolean overwrite = true; 1597 String overwriteHeader = req.getHeader("Overwrite"); 1598 1599 if (overwriteHeader != null) { 1600 if (overwriteHeader.equalsIgnoreCase("T")) { 1601 overwrite = true; 1602 } else { 1603 overwrite = false; 1604 } 1605 } 1606 1607 1609 boolean exists = true; 1610 try { 1611 resources.lookup(destinationPath); 1612 } catch (NamingException e) { 1613 exists = false; 1614 } 1615 1616 if (overwrite) { 1617 1618 if (exists) { 1620 if (!deleteResource(destinationPath, req, resp, true)) { 1621 return false; 1622 } 1623 } else { 1624 resp.setStatus(WebdavStatus.SC_CREATED); 1625 } 1626 1627 } else { 1628 1629 if (exists) { 1631 resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED); 1632 return false; 1633 } 1634 1635 } 1636 1637 1639 Hashtable errorList = new Hashtable (); 1640 1641 boolean result = copyResource(resources, errorList, 1642 path, destinationPath); 1643 1644 if ((!result) || (!errorList.isEmpty())) { 1645 1646 sendReport(req, resp, errorList); 1647 return false; 1648 1649 } 1650 1651 lockNullResources.remove(destinationPath); 1654 1655 return true; 1656 1657 } 1658 1659 1660 1669 private boolean copyResource(DirContext resources, Hashtable errorList, 1670 String source, String dest) { 1671 1672 if (debug > 1) 1673 log("Copy: " + source + " To: " + dest); 1674 1675 Object object = null; 1676 try { 1677 object = resources.lookup(source); 1678 } catch (NamingException e) { 1679 } 1680 1681 if (object instanceof DirContext ) { 1682 1683 try { 1684 resources.createSubcontext(dest); 1685 } catch (NamingException e) { 1686 errorList.put 1687 (dest, new Integer (WebdavStatus.SC_CONFLICT)); 1688 return false; 1689 } 1690 1691 try { 1692 NamingEnumeration enumeration = resources.list(source); 1693 while (enumeration.hasMoreElements()) { 1694 NameClassPair ncPair = (NameClassPair ) enumeration.nextElement(); 1695 String childDest = dest; 1696 if (!childDest.equals("/")) 1697 childDest += "/"; 1698 childDest += ncPair.getName(); 1699 String childSrc = source; 1700 if (!childSrc.equals("/")) 1701 childSrc += "/"; 1702 childSrc += ncPair.getName(); 1703 copyResource(resources, errorList, childSrc, childDest); 1704 } 1705 } catch (NamingException e) { 1706 errorList.put 1707 (dest, new Integer (WebdavStatus.SC_INTERNAL_SERVER_ERROR)); 1708 return false; 1709 } 1710 1711 } else { 1712 1713 if (object instanceof Resource) { 1714 try { 1715 resources.bind(dest, object); 1716 } catch (NamingException e) { 1717 errorList.put 1718 (source, 1719 new Integer (WebdavStatus.SC_INTERNAL_SERVER_ERROR)); 1720 return false; 1721 } 1722 } else { 1723 errorList.put 1724 (source, 1725 new Integer (WebdavStatus.SC_INTERNAL_SERVER_ERROR)); 1726 return false; 1727 } 1728 1729 } 1730 1731 return true; 1732 1733 } 1734 1735 1736 1743 private boolean deleteResource(HttpServletRequest req, 1744 HttpServletResponse resp) 1745 throws ServletException , IOException { 1746 1747 String path = getRelativePath(req); 1748 1749 return deleteResource(path, req, resp, true); 1750 1751 } 1752 1753 1754 1763 private boolean deleteResource(String path, HttpServletRequest req, 1764 HttpServletResponse resp, boolean setStatus) 1765 throws ServletException , IOException { 1766 1767 if ((path.toUpperCase().startsWith("/WEB-INF")) || 1768 (path.toUpperCase().startsWith("/META-INF"))) { 1769 resp.sendError(WebdavStatus.SC_FORBIDDEN); 1770 return false; 1771 } 1772 1773 String ifHeader = req.getHeader("If"); 1774 if (ifHeader == null) 1775 ifHeader = ""; 1776 1777 String lockTokenHeader = req.getHeader("Lock-Token"); 1778 if (lockTokenHeader == null) 1779 lockTokenHeader = ""; 1780 1781 if (isLocked(path, ifHeader + lockTokenHeader)) { 1782 resp.sendError(WebdavStatus.SC_LOCKED); 1783 return false; 1784 } 1785 1786 boolean exists = true; 1787 Object object = null; 1788 try { 1789 object = resources.lookup(path); 1790 } catch (NamingException e) { 1791 exists = false; 1792 } 1793 1794 if (!exists) { 1795 resp.sendError(WebdavStatus.SC_NOT_FOUND); 1796 return false; 1797 } 1798 1799 boolean collection = (object instanceof DirContext ); 1800 1801 if (!collection) { 1802 try { 1803 resources.unbind(path); 1804 } catch (NamingException e) { 1805 resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR); 1806 return false; 1807 } 1808 } else { 1809 1810 Hashtable errorList = new Hashtable (); 1811 1812 deleteCollection(req, resources, path, errorList); 1813 try { 1814 resources.unbind(path); 1815 } catch (NamingException e) { 1816 errorList.put(path, new Integer 1817 (WebdavStatus.SC_INTERNAL_SERVER_ERROR)); 1818 } 1819 1820 if (!errorList.isEmpty()) { 1821 1822 sendReport(req, resp, errorList); 1823 return false; 1824 1825 } 1826 1827 } 1828 if (setStatus) { 1829 resp.setStatus(WebdavStatus.SC_NO_CONTENT); 1830 } 1831 return true; 1832 1833 } 1834 1835 1836 1843 private void deleteCollection(HttpServletRequest req, 1844 DirContext resources, 1845 String path, Hashtable errorList) { 1846 1847 if (debug > 1) 1848 log("Delete:" + path); 1849 1850 if ((path.toUpperCase().startsWith("/WEB-INF")) || 1851 (path.toUpperCase().startsWith("/META-INF"))) { 1852 errorList.put(path, new Integer (WebdavStatus.SC_FORBIDDEN)); 1853 return; 1854 } 1855 1856 String ifHeader = req.getHeader("If"); 1857 if (ifHeader == null) 1858 ifHeader = ""; 1859 1860 String lockTokenHeader = req.getHeader("Lock-Token"); 1861 if (lockTokenHeader == null) 1862 lockTokenHeader = ""; 1863 1864 Enumeration enumeration = null; 1865 try { 1866 enumeration = resources.list(path); 1867 } catch (NamingException e) { 1868 errorList.put(path, new Integer 1869 (WebdavStatus.SC_INTERNAL_SERVER_ERROR)); 1870 return; 1871 } 1872 1873 while (enumeration.hasMoreElements()) { 1874 NameClassPair ncPair = (NameClassPair ) enumeration.nextElement(); 1875 String childName = path; 1876 if (!childName.equals("/")) 1877 childName += "/"; 1878 childName += ncPair.getName(); 1879 1880 if (isLocked(childName, ifHeader + lockTokenHeader)) { 1881 1882 errorList.put(childName, new Integer (WebdavStatus.SC_LOCKED)); 1883 1884 } else { 1885 1886 try { 1887 Object object = resources.lookup(childName); 1888 if (object instanceof DirContext ) { 1889 deleteCollection(req, resources, childName, errorList); 1890 } 1891 1892 try { 1893 resources.unbind(childName); 1894 } catch (NamingException e) { 1895 if (!(object instanceof DirContext )) { 1896 errorList.put 1899 (childName, new Integer 1900 (WebdavStatus.SC_INTERNAL_SERVER_ERROR)); 1901 } 1902 } 1903 } catch (NamingException e) { 1904 errorList.put 1905 (childName, new Integer 1906 (WebdavStatus.SC_INTERNAL_SERVER_ERROR)); 1907 } 1908 } 1909 1910 } 1911 1912 } 1913 1914 1915 1923 private void sendReport(HttpServletRequest req, HttpServletResponse resp, 1924 Hashtable errorList) 1925 throws ServletException , IOException { 1926 1927 resp.setStatus(WebdavStatus.SC_MULTI_STATUS); 1928 1929 String absoluteUri = req.getRequestURI(); 1930 String relativePath = getRelativePath(req); 1931 1932 XMLWriter generatedXML = new XMLWriter(); 1933 generatedXML.writeXMLHeader(); 1934 1935 generatedXML.writeElement(null, "multistatus" 1936 + generateNamespaceDeclarations(), 1937 XMLWriter.OPENING); 1938 1939 Enumeration pathList = errorList.keys(); 1940 while (pathList.hasMoreElements()) { 1941 1942 String errorPath = (String ) pathList.nextElement(); 1943 int errorCode = ((Integer ) errorList.get(errorPath)).intValue(); 1944 1945 generatedXML.writeElement(null, "response", XMLWriter.OPENING); 1946 1947 generatedXML.writeElement(null, "href", XMLWriter.OPENING); 1948 String toAppend = errorPath.substring(relativePath.length()); 1949 if (!toAppend.startsWith("/")) 1950 toAppend = "/" + toAppend; 1951 generatedXML.writeText(absoluteUri + toAppend); 1952 generatedXML.writeElement(null, "href", XMLWriter.CLOSING); 1953 generatedXML.writeElement(null, "status", XMLWriter.OPENING); 1954 generatedXML 1955 .writeText("HTTP/1.1 " + errorCode + " " 1956 + WebdavStatus.getStatusText(errorCode)); 1957 generatedXML.writeElement(null, "status", XMLWriter.CLOSING); 1958 1959 generatedXML.writeElement(null, "response", XMLWriter.CLOSING); 1960 1961 } 1962 1963 generatedXML.writeElement(null, "multistatus", XMLWriter.CLOSING); 1964 1965 Writer writer = resp.getWriter(); 1966 writer.write(generatedXML.toString()); 1967 writer.close(); 1968 1969 } 1970 1971 1972 1983 private void parseProperties(HttpServletRequest req, 1984 XMLWriter generatedXML, 1985 String path, int type, 1986 Vector propertiesVector) { 1987 1988 if (path.toUpperCase().startsWith("/WEB-INF") || 1991 path.toUpperCase().startsWith("/META-INF")) 1992 return; 1993 1994 CacheEntry cacheEntry = resources.lookupCache(path); 1995 1996 generatedXML.writeElement(null, "response", XMLWriter.OPENING); 1997 String status = new String ("HTTP/1.1 " + WebdavStatus.SC_OK + " " 1998 + WebdavStatus.getStatusText 1999 (WebdavStatus.SC_OK)); 2000 2001 generatedXML.writeElement(null, "href", XMLWriter.OPENING); 2003 2004 String href = req.getContextPath() + req.getServletPath(); 2005 if ((href.endsWith("/")) && (path.startsWith("/"))) 2006 href += path.substring(1); 2007 else 2008 href += path; 2009 if ((cacheEntry.context != null) && (!href.endsWith("/"))) 2010 href += "/"; 2011 2012 generatedXML.writeText(rewriteUrl(href)); 2013 2014 generatedXML.writeElement(null, "href", XMLWriter.CLOSING); 2015 2016 String resourceName = path; 2017 int lastSlash = path.lastIndexOf('/'); 2018 if (lastSlash != -1) 2019 resourceName = resourceName.substring(lastSlash + 1); 2020 2021 switch (type) { 2022 2023 case FIND_ALL_PROP : 2024 2025 generatedXML.writeElement(null, "propstat", XMLWriter.OPENING); 2026 generatedXML.writeElement(null, "prop", XMLWriter.OPENING); 2027 2028 generatedXML.writeProperty 2029 (null, "creationdate", 2030 getISOCreationDate(cacheEntry.attributes.getCreation())); 2031 generatedXML.writeElement(null, "displayname", XMLWriter.OPENING); 2032 generatedXML.writeData(resourceName); 2033 generatedXML.writeElement(null, "displayname", XMLWriter.CLOSING); 2034 if (cacheEntry.resource != null) { 2035 generatedXML.writeProperty 2036 (null, "getlastmodified", FastHttpDateFormat.formatDate 2037 (cacheEntry.attributes.getLastModified(), null)); 2038 generatedXML.writeProperty 2039 (null, "getcontentlength", 2040 String.valueOf(cacheEntry.attributes.getContentLength())); 2041 String contentType = getServletContext().getMimeType 2042 (cacheEntry.name); 2043 if (contentType != null) { 2044 generatedXML.writeProperty(null, "getcontenttype", 2045 contentType); 2046 } 2047 generatedXML.writeProperty(null, "getetag", 2048 getETag(cacheEntry.attributes)); 2049 generatedXML.writeElement(null, "resourcetype", 2050 XMLWriter.NO_CONTENT); 2051 } else { 2052 generatedXML.writeElement(null, "resourcetype", 2053 XMLWriter.OPENING); 2054 generatedXML.writeElement(null, "collection", 2055 XMLWriter.NO_CONTENT); 2056 generatedXML.writeElement(null, "resourcetype", 2057 XMLWriter.CLOSING); 2058 } 2059 2060 generatedXML.writeProperty(null, "source", ""); 2061 2062 String supportedLocks = "<lockentry>" 2063 + "<lockscope><exclusive/></lockscope>" 2064 + "<locktype><write/></locktype>" 2065 + "</lockentry>" + "<lockentry>" 2066 + "<lockscope><shared/></lockscope>" 2067 + "<locktype><write/></locktype>" 2068 + "</lockentry>"; 2069 generatedXML.writeElement(null, "supportedlock", 2070 XMLWriter.OPENING); 2071 generatedXML.writeText(supportedLocks); 2072 generatedXML.writeElement(null, "supportedlock", 2073 XMLWriter.CLOSING); 2074 2075 generateLockDiscovery(path, generatedXML); 2076 2077 generatedXML.writeElement(null, "prop", XMLWriter.CLOSING); 2078 generatedXML.writeElement(null, "status", XMLWriter.OPENING); 2079 generatedXML.writeText(status); 2080 generatedXML.writeElement(null, "status", XMLWriter.CLOSING); 2081 generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING); 2082 2083 break; 2084 2085 case FIND_PROPERTY_NAMES : 2086 2087 generatedXML.writeElement(null, "propstat", XMLWriter.OPENING); 2088 generatedXML.writeElement(null, "prop", XMLWriter.OPENING); 2089 2090 generatedXML.writeElement(null, "creationdate", 2091 XMLWriter.NO_CONTENT); 2092 generatedXML.writeElement(null, "displayname", 2093 XMLWriter.NO_CONTENT); 2094 if (cacheEntry.resource != null) { 2095 generatedXML.writeElement(null, "getcontentlanguage", 2096 XMLWriter.NO_CONTENT); 2097 generatedXML.writeElement(null, "getcontentlength", 2098 XMLWriter.NO_CONTENT); 2099 generatedXML.writeElement(null, "getcontenttype", 2100 XMLWriter.NO_CONTENT); 2101 generatedXML.writeElement(null, "getetag", 2102 XMLWriter.NO_CONTENT); 2103 generatedXML.writeElement(null, "getlastmodified", 2104 XMLWriter.NO_CONTENT); 2105 } 2106 generatedXML.writeElement(null, "resourcetype", 2107 XMLWriter.NO_CONTENT); 2108 generatedXML.writeElement(null, "source", XMLWriter.NO_CONTENT); 2109 generatedXML.writeElement(null, "lockdiscovery", 2110 XMLWriter.NO_CONTENT); 2111 2112 generatedXML.writeElement(null, "prop", XMLWriter.CLOSING); 2113 generatedXML.writeElement(null, "status", XMLWriter.OPENING); 2114 generatedXML.writeText(status); 2115 generatedXML.writeElement(null, "status", XMLWriter.CLOSING); 2116 generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING); 2117 2118 break; 2119 2120 case FIND_BY_PROPERTY : 2121 2122 Vector propertiesNotFound = new Vector (); 2123 2124 2126 generatedXML.writeElement(null, "propstat", XMLWriter.OPENING); 2127 generatedXML.writeElement(null, "prop", XMLWriter.OPENING); 2128 2129 Enumeration properties = propertiesVector.elements(); 2130 2131 while (properties.hasMoreElements()) { 2132 2133 String property = (String ) properties.nextElement(); 2134 2135 if (property.equals("creationdate")) { 2136 generatedXML.writeProperty 2137 (null, "creationdate", 2138 getISOCreationDate(cacheEntry.attributes.getCreation())); 2139 } else if (property.equals("displayname")) { 2140 generatedXML.writeElement 2141 (null, "displayname", XMLWriter.OPENING); 2142 generatedXML.writeData(resourceName); 2143 generatedXML.writeElement 2144 (null, "displayname", XMLWriter.CLOSING); 2145 } else if (property.equals("getcontentlanguage")) { 2146 if (cacheEntry.context != null) { 2147 propertiesNotFound.addElement(property); 2148 } else { 2149 generatedXML.writeElement(null, "getcontentlanguage", 2150 XMLWriter.NO_CONTENT); 2151 } 2152 } else if (property.equals("getcontentlength")) { 2153 if (cacheEntry.context != null) { 2154 propertiesNotFound.addElement(property); 2155 } else { 2156 generatedXML.writeProperty 2157 (null, "getcontentlength", 2158 (String.valueOf(cacheEntry.attributes.getContentLength()))); 2159 } 2160 } else if (property.equals("getcontenttype")) { 2161 if (cacheEntry.context != null) { 2162 propertiesNotFound.addElement(property); 2163 } else { 2164 generatedXML.writeProperty 2165 (null, "getcontenttype", 2166 getServletContext().getMimeType 2167 (cacheEntry.name)); 2168 } 2169 } else if (property.equals("getetag")) { 2170 if (cacheEntry.context != null) { 2171 propertiesNotFound.addElement(property); 2172 } else { 2173 generatedXML.writeProperty 2174 (null, "getetag", getETag(cacheEntry.attributes)); 2175 } 2176 } else if (property.equals("getlastmodified")) { 2177 if (cacheEntry.context != null) { 2178 propertiesNotFound.addElement(property); 2179 } else { 2180 generatedXML.writeProperty 2181 (null, "getlastmodified", FastHttpDateFormat.formatDate 2182 (cacheEntry.attributes.getLastModified(), null)); 2183 } 2184 } else if (property.equals("resourcetype")) { 2185 if (cacheEntry.context != null) { 2186 generatedXML.writeElement(null, "resourcetype", 2187 XMLWriter.OPENING); 2188 generatedXML.writeElement(null, "collection", 2189 XMLWriter.NO_CONTENT); 2190 generatedXML.writeElement(null, "resourcetype", 2191 XMLWriter.CLOSING); 2192 } else { 2193 generatedXML.writeElement(null, "resourcetype", 2194 XMLWriter.NO_CONTENT); 2195 } 2196 } else if (property.equals("source")) { 2197 generatedXML.writeProperty(null, "source", ""); 2198 } else if (property.equals("supportedlock")) { 2199 supportedLocks = "<lockentry>" 2200 + "<lockscope><exclusive/></lockscope>" 2201 + "<locktype><write/></locktype>" 2202 + "</lockentry>" + "<lockentry>" 2203 + "<lockscope><shared/></lockscope>" 2204 + "<locktype><write/></locktype>" 2205 + "</lockentry>"; 2206 generatedXML.writeElement(null, "supportedlock", 2207 XMLWriter.OPENING); 2208 generatedXML.writeText(supportedLocks); 2209 generatedXML.writeElement(null, "supportedlock", 2210 XMLWriter.CLOSING); 2211 } else if (property.equals("lockdiscovery")) { 2212 if (!generateLockDiscovery(path, generatedXML)) 2213 propertiesNotFound.addElement(property); 2214 } else { 2215 propertiesNotFound.addElement(property); 2216 } 2217 2218 } 2219 2220 generatedXML.writeElement(null, "prop", XMLWriter.CLOSING); 2221 generatedXML.writeElement(null, "status", XMLWriter.OPENING); 2222 generatedXML.writeText(status); 2223 generatedXML.writeElement(null, "status", XMLWriter.CLOSING); 2224 generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING); 2225 2226 Enumeration propertiesNotFoundList = propertiesNotFound.elements(); 2227 2228 if (propertiesNotFoundList.hasMoreElements()) { 2229 2230 status = new String ("HTTP/1.1 " + WebdavStatus.SC_NOT_FOUND 2231 + " " + WebdavStatus.getStatusText 2232 (WebdavStatus.SC_NOT_FOUND)); 2233 2234 generatedXML.writeElement(null, "propstat", XMLWriter.OPENING); 2235 generatedXML.writeElement(null, "prop", XMLWriter.OPENING); 2236 2237 while (propertiesNotFoundList.hasMoreElements()) { 2238 generatedXML.writeElement 2239 (null, (String ) propertiesNotFoundList.nextElement(), 2240 XMLWriter.NO_CONTENT); 2241 } 2242 2243 generatedXML.writeElement(null, "prop", XMLWriter.CLOSING); 2244 generatedXML.writeElement(null, "status", XMLWriter.OPENING); 2245 generatedXML.writeText(status); 2246 generatedXML.writeElement(null, "status", XMLWriter.CLOSING); 2247 generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING); 2248 2249 } 2250 2251 break; 2252 2253 } 2254 2255 generatedXML.writeElement(null, "response", XMLWriter.CLOSING); 2256 2257 } 2258 2259 2260 2270 private void parseLockNullProperties(HttpServletRequest req, 2271 XMLWriter generatedXML, 2272 String path, int type, 2273 Vector propertiesVector) { 2274 2275 if (path.toUpperCase().startsWith("/WEB-INF") || 2278 path.toUpperCase().startsWith("/META-INF")) 2279 return; 2280 2281 LockInfo lock = (LockInfo) resourceLocks.get(path); 2283 2284 if (lock == null) 2285 return; 2286 2287 generatedXML.writeElement(null, "response", XMLWriter.OPENING); 2288 String status = new String ("HTTP/1.1 " + WebdavStatus.SC_OK + " " 2289 + WebdavStatus.getStatusText 2290 (WebdavStatus.SC_OK)); 2291 2292 generatedXML.writeElement(null, "href", XMLWriter.OPENING); 2294 2295 String absoluteUri = req.getRequestURI(); 2296 String relativePath = getRelativePath(req); 2297 String toAppend = path.substring(relativePath.length()); 2298 if (!toAppend.startsWith("/")) 2299 toAppend = "/" + toAppend; 2300 2301 generatedXML.writeText(rewriteUrl(normalize(absoluteUri + toAppend))); 2302 2303 generatedXML.writeElement(null, "href", XMLWriter.CLOSING); 2304 2305 String resourceName = path; 2306 int lastSlash = path.lastIndexOf('/'); 2307 if (lastSlash != -1) 2308 resourceName = resourceName.substring(lastSlash + 1); 2309 2310 switch (type) { 2311 2312 case FIND_ALL_PROP : 2313 2314 generatedXML.writeElement(null, "propstat", XMLWriter.OPENING); 2315 generatedXML.writeElement(null, "prop", XMLWriter.OPENING); 2316 2317 generatedXML.writeProperty 2318 (null, "creationdate", 2319 getISOCreationDate(lock.creationDate.getTime())); 2320 generatedXML.writeElement 2321 (null, "displayname", XMLWriter.OPENING); 2322 generatedXML.writeData(resourceName); 2323 generatedXML.writeElement 2324 (null, "displayname", XMLWriter.CLOSING); 2325 generatedXML.writeProperty(null, "getlastmodified", 2326 FastHttpDateFormat.formatDate 2327 (lock.creationDate.getTime(), null)); 2328 generatedXML.writeProperty 2329 (null, "getcontentlength", String.valueOf(0)); 2330 generatedXML.writeProperty(null, "getcontenttype", ""); 2331 generatedXML.writeProperty(null, "getetag", ""); 2332 generatedXML.writeElement(null, "resourcetype", 2333 XMLWriter.OPENING); 2334 generatedXML.writeElement(null, "lock-null", XMLWriter.NO_CONTENT); 2335 generatedXML.writeElement(null, "resourcetype", 2336 XMLWriter.CLOSING); 2337 2338 generatedXML.writeProperty(null, "source", ""); 2339 2340 String supportedLocks = "<lockentry>" 2341 + "<lockscope><exclusive/></lockscope>" 2342 + "<locktype><write/></locktype>" 2343 + "</lockentry>" + "<lockentry>" 2344 + "<lockscope><shared/></lockscope>" 2345 + "<locktype><write/></locktype>" 2346 + "</lockentry>"; 2347 generatedXML.writeElement(null, "supportedlock", 2348 XMLWriter.OPENING); 2349 generatedXML.writeText(supportedLocks); 2350 generatedXML.writeElement(null, "supportedlock", 2351 XMLWriter.CLOSING); 2352 2353 generateLockDiscovery(path, generatedXML); 2354 2355 generatedXML.writeElement(null, "prop", XMLWriter.CLOSING); 2356 generatedXML.writeElement(null, "status", XMLWriter.OPENING); 2357 generatedXML.writeText(status); 2358 generatedXML.writeElement(null, "status", XMLWriter.CLOSING); 2359 generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING); 2360 2361 break; 2362 2363 case FIND_PROPERTY_NAMES : 2364 2365 generatedXML.writeElement(null, "propstat", XMLWriter.OPENING); 2366 generatedXML.writeElement(null, "prop", XMLWriter.OPENING); 2367 2368 generatedXML.writeElement(null, "creationdate", 2369 XMLWriter.NO_CONTENT); 2370 generatedXML.writeElement(null, "displayname", 2371 XMLWriter.NO_CONTENT); 2372 generatedXML.writeElement(null, "getcontentlanguage", 2373 XMLWriter.NO_CONTENT); 2374 generatedXML.writeElement(null, "getcontentlength", 2375 XMLWriter.NO_CONTENT); 2376 generatedXML.writeElement(null, "getcontenttype", 2377 XMLWriter.NO_CONTENT); 2378 generatedXML.writeElement(null, "getetag", 2379 XMLWriter.NO_CONTENT); 2380 generatedXML.writeElement(null, "getlastmodified", 2381 XMLWriter.NO_CONTENT); 2382 generatedXML.writeElement(null, "resourcetype", 2383 XMLWriter.NO_CONTENT); 2384 generatedXML.writeElement(null, "source", 2385 XMLWriter.NO_CONTENT); 2386 generatedXML.writeElement(null, "lockdiscovery", 2387 XMLWriter.NO_CONTENT); 2388 2389 generatedXML.writeElement(null, "prop", XMLWriter.CLOSING); 2390 generatedXML.writeElement(null, "status", XMLWriter.OPENING); 2391 generatedXML.writeText(status); 2392 generatedXML.writeElement(null, "status", XMLWriter.CLOSING); 2393 generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING); 2394 2395 break; 2396 2397 case FIND_BY_PROPERTY : 2398 2399 Vector propertiesNotFound = new Vector (); 2400 2401 2403 generatedXML.writeElement(null, "propstat", XMLWriter.OPENING); 2404 generatedXML.writeElement(null, "prop", XMLWriter.OPENING); 2405 2406 Enumeration properties = propertiesVector.elements(); 2407 2408 while (properties.hasMoreElements()) { 2409 2410 String property = (String ) properties.nextElement(); 2411 2412 if (property.equals("creationdate")) { 2413 generatedXML.writeProperty 2414 (null, "creationdate", 2415 getISOCreationDate(lock.creationDate.getTime())); 2416 } else if (property.equals("displayname")) { 2417 generatedXML.writeElement 2418 (null, "displayname", XMLWriter.OPENING); 2419 generatedXML.writeData(resourceName); 2420 generatedXML.writeElement 2421 (null, "displayname", XMLWriter.CLOSING); 2422 } else if (property.equals("getcontentlanguage")) { 2423 generatedXML.writeElement(null, "getcontentlanguage", 2424 XMLWriter.NO_CONTENT); 2425 } else if (property.equals("getcontentlength")) { 2426 generatedXML.writeProperty 2427 (null, "getcontentlength", (String.valueOf(0))); 2428 } else if (property.equals("getcontenttype")) { 2429 generatedXML.writeProperty 2430 (null, "getcontenttype", ""); 2431 } else if (property.equals("getetag")) { 2432 generatedXML.writeProperty(null, "getetag", ""); 2433 } else if (property.equals("getlastmodified")) { 2434 generatedXML.writeProperty 2435 (null, "getlastmodified", 2436 FastHttpDateFormat.formatDate 2437 (lock.creationDate.getTime(), null)); 2438 } else if (property.equals("resourcetype")) { 2439 generatedXML.writeElement(null, "resourcetype", 2440 XMLWriter.OPENING); 2441 generatedXML.writeElement(null, "lock-null", 2442 XMLWriter.NO_CONTENT); 2443 generatedXML.writeElement(null, "resourcetype", 2444 XMLWriter.CLOSING); 2445 } else if (property.equals("source")) { 2446 generatedXML.writeProperty(null, "source", ""); 2447 } else if (property.equals("supportedlock")) { 2448 supportedLocks = "<lockentry>" 2449 + "<lockscope><exclusive/></lockscope>" 2450 + "<locktype><write/></locktype>" 2451 + "</lockentry>" + "<lockentry>" 2452 + "<lockscope><shared/></lockscope>" 2453 + "<locktype><write/></locktype>" 2454 + "</lockentry>"; 2455 generatedXML.writeElement(null, "supportedlock", 2456 XMLWriter.OPENING); 2457 generatedXML.writeText(supportedLocks); 2458 generatedXML.writeElement(null, "supportedlock", 2459 XMLWriter.CLOSING); 2460 } else if (property.equals("lockdiscovery")) { 2461 if (!generateLockDiscovery(path, generatedXML)) 2462 propertiesNotFound.addElement(property); 2463 } else { 2464 propertiesNotFound.addElement(property); 2465 } 2466 2467 } 2468 2469 generatedXML.writeElement(null, "prop", XMLWriter.CLOSING); 2470 generatedXML.writeElement(null, "status", XMLWriter.OPENING); 2471 generatedXML.writeText(status); 2472 generatedXML.writeElement(null, "status", XMLWriter.CLOSING); 2473 generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING); 2474 2475 Enumeration propertiesNotFoundList = propertiesNotFound.elements(); 2476 2477 if (propertiesNotFoundList.hasMoreElements()) { 2478 2479 status = new String ("HTTP/1.1 " + WebdavStatus.SC_NOT_FOUND 2480 + " " + WebdavStatus.getStatusText 2481 (WebdavStatus.SC_NOT_FOUND)); 2482 2483 generatedXML.writeElement(null, "propstat", XMLWriter.OPENING); 2484 generatedXML.writeElement(null, "prop", XMLWriter.OPENING); 2485 2486 while (propertiesNotFoundList.hasMoreElements()) { 2487 generatedXML.writeElement 2488 (null, (String ) propertiesNotFoundList.nextElement(), 2489 XMLWriter.NO_CONTENT); 2490 } 2491 2492 generatedXML.writeElement(null, "prop", XMLWriter.CLOSING); 2493 generatedXML.writeElement(null, "status", XMLWriter.OPENING); 2494 generatedXML.writeText(status); 2495 generatedXML.writeElement(null, "status", XMLWriter.CLOSING); 2496 generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING); 2497 2498 } 2499 2500 break; 2501 2502 } 2503 2504 generatedXML.writeElement(null, "response", XMLWriter.CLOSING); 2505 2506 } 2507 2508 2509 2516 private boolean generateLockDiscovery 2517 (String path, XMLWriter generatedXML) { 2518 2519 LockInfo resourceLock = (LockInfo) resourceLocks.get(path); 2520 Enumeration collectionLocksList = collectionLocks.elements(); 2521 2522 boolean wroteStart = false; 2523 2524 if (resourceLock != null) { 2525 wroteStart = true; 2526 generatedXML.writeElement(null, "lockdiscovery", 2527 XMLWriter.OPENING); 2528 resourceLock.toXML(generatedXML); 2529 } 2530 2531 while (collectionLocksList.hasMoreElements()) { 2532 LockInfo currentLock = 2533 (LockInfo) collectionLocksList.nextElement(); 2534 if (path.startsWith(currentLock.path)) { 2535 if (!wroteStart) { 2536 wroteStart = true; 2537 generatedXML.writeElement(null, "lockdiscovery", 2538 XMLWriter.OPENING); 2539 } 2540 currentLock.toXML(generatedXML); 2541 } 2542 } 2543 2544 if (wroteStart) { 2545 generatedXML.writeElement(null, "lockdiscovery", 2546 XMLWriter.CLOSING); 2547 } else { 2548 return false; 2549 } 2550 2551 return true; 2552 2553 } 2554 2555 2556 2559 private String getISOCreationDate(long creationDate) { 2560 StringBuffer creationDateValue = new StringBuffer 2561 (creationDateFormat.format 2562 (new Date (creationDate))); 2563 2580 return creationDateValue.toString(); 2581 } 2582 2583 2587 private StringBuffer determineMethodsAllowed(DirContext resources, 2588 HttpServletRequest req) { 2589 2590 StringBuffer methodsAllowed = new StringBuffer (); 2591 boolean exists = true; 2592 Object object = null; 2593 try { 2594 String path = getRelativePath(req); 2595 2596 object = resources.lookup(path); 2597 } catch (NamingException e) { 2598 exists = false; 2599 } 2600 2601 if (!exists) { 2602 methodsAllowed.append("OPTIONS, MKCOL, PUT, LOCK"); 2603 return methodsAllowed; 2604 } 2605 2606 methodsAllowed.append("OPTIONS, GET, HEAD, POST, DELETE, TRACE"); 2607 methodsAllowed.append(", PROPPATCH, COPY, MOVE, LOCK, UNLOCK"); 2608 2609 if (listings) { 2610 methodsAllowed.append(", PROPFIND"); 2611 } 2612 2613 if (!(object instanceof DirContext )) { 2614 methodsAllowed.append(", PUT"); 2615 } 2616 2617 return methodsAllowed; 2618 } 2619 2620 2622 2623 2626 private class LockInfo { 2627 2628 2629 2631 2632 2635 public LockInfo() { 2636 2637 } 2638 2639 2640 2642 2643 String path = "/"; 2644 String type = "write"; 2645 String scope = "exclusive"; 2646 int depth = 0; 2647 String owner = ""; 2648 Vector tokens = new Vector (); 2649 long expiresAt = 0; 2650 Date creationDate = new Date (); 2651 2652 2653 2655 2656 2659 public String toString() { 2660 2661 String result = "Type:" + type + "\n"; 2662 result += "Scope:" + scope + "\n"; 2663 result += "Depth:" + depth + "\n"; 2664 result += "Owner:" + owner + "\n"; 2665 result += "Expiration:" 2666 + FastHttpDateFormat.formatDate(expiresAt, null) + "\n"; 2667 Enumeration tokensList = tokens.elements(); 2668 while (tokensList.hasMoreElements()) { 2669 result += "Token:" + tokensList.nextElement() + "\n"; 2670 } 2671 return result; 2672 2673 } 2674 2675 2676 2679 public boolean hasExpired() { 2680 return (System.currentTimeMillis() > expiresAt); 2681 } 2682 2683 2684 2687 public boolean isExclusive() { 2688 2689 return (scope.equals("exclusive")); 2690 2691 } 2692 2693 2694 2698 public void toXML(XMLWriter generatedXML) { 2699 2700 generatedXML.writeElement(null, "activelock", XMLWriter.OPENING); 2701 2702 generatedXML.writeElement(null, "locktype", XMLWriter.OPENING); 2703 generatedXML.writeElement(null, type, XMLWriter.NO_CONTENT); 2704 generatedXML.writeElement(null, "locktype", XMLWriter.CLOSING); 2705 2706 generatedXML.writeElement(null, "lockscope", XMLWriter.OPENING); 2707 generatedXML.writeElement(null, scope, XMLWriter.NO_CONTENT); 2708 generatedXML.writeElement(null, "lockscope", XMLWriter.CLOSING); 2709 2710 generatedXML.writeElement(null, "depth", XMLWriter.OPENING); 2711 if (depth == INFINITY) { 2712 generatedXML.writeText("Infinity"); 2713 } else { 2714 generatedXML.writeText("0"); 2715 } 2716 generatedXML.writeElement(null, "depth", XMLWriter.CLOSING); 2717 2718 generatedXML.writeElement(null, "owner", XMLWriter.OPENING); 2719 generatedXML.writeText(owner); 2720 generatedXML.writeElement(null, "owner", XMLWriter.CLOSING); 2721 2722 generatedXML.writeElement(null, "timeout", XMLWriter.OPENING); 2723 long timeout = (expiresAt - System.currentTimeMillis()) / 1000; 2724 generatedXML.writeText("Second-" + timeout); 2725 generatedXML.writeElement(null, "timeout", XMLWriter.CLOSING); 2726 2727 generatedXML.writeElement(null, "locktoken", XMLWriter.OPENING); 2728 Enumeration tokensList = tokens.elements(); 2729 while (tokensList.hasMoreElements()) { 2730 generatedXML.writeElement(null, "href", XMLWriter.OPENING); 2731 generatedXML.writeText("opaquelocktoken:" 2732 + tokensList.nextElement()); 2733 generatedXML.writeElement(null, "href", XMLWriter.CLOSING); 2734 } 2735 generatedXML.writeElement(null, "locktoken", XMLWriter.CLOSING); 2736 2737 generatedXML.writeElement(null, "activelock", XMLWriter.CLOSING); 2738 2739 } 2740 2741 2742 } 2743 2744 2745 2747 2748 private class Property { 2749 2750 public String name; 2751 public String value; 2752 public String namespace; 2753 public String namespaceAbbrev; 2754 public int status = WebdavStatus.SC_OK; 2755 2756 } 2757 2758 2759}; 2760 2761 2762 2764 2765 2774class WebdavStatus { 2775 2776 2777 2779 2780 2785 private static Hashtable mapStatusCodes = new Hashtable (); 2786 2787 2788 2790 2791 2794 public static final int SC_OK = HttpServletResponse.SC_OK; 2795 2796 2797 2801 public static final int SC_CREATED = HttpServletResponse.SC_CREATED; 2802 2803 2804 2808 public static final int SC_ACCEPTED = HttpServletResponse.SC_ACCEPTED; 2809 2810 2811 2815 public static final int SC_NO_CONTENT = HttpServletResponse.SC_NO_CONTENT; 2816 2817 2818 2823 public static final int SC_MOVED_PERMANENTLY = 2824 HttpServletResponse.SC_MOVED_PERMANENTLY; 2825 2826 2827 2832 public static final int SC_MOVED_TEMPORARILY = 2833 HttpServletResponse.SC_MOVED_TEMPORARILY; 2834 2835 2836 2840 public static final int SC_NOT_MODIFIED = 2841 HttpServletResponse.SC_NOT_MODIFIED; 2842 2843 2844 2848 public static final int SC_BAD_REQUEST = 2849 HttpServletResponse.SC_BAD_REQUEST; 2850 2851 2852 2856 public static final int SC_UNAUTHORIZED = 2857 HttpServletResponse.SC_UNAUTHORIZED; 2858 2859 2860 2864 public static final int SC_FORBIDDEN = HttpServletResponse.SC_FORBIDDEN; 2865 2866 2867 2871 public static final int SC_NOT_FOUND = HttpServletResponse.SC_NOT_FOUND; 2872 2873 2874 2878 public static final int SC_INTERNAL_SERVER_ERROR = 2879 HttpServletResponse.SC_INTERNAL_SERVER_ERROR; 2880 2881 2882 2886 public static final int SC_NOT_IMPLEMENTED = 2887 HttpServletResponse.SC_NOT_IMPLEMENTED; 2888 2889 2890 2895 public static final int SC_BAD_GATEWAY = 2896 HttpServletResponse.SC_BAD_GATEWAY; 2897 2898 2899 2903 public static final int SC_SERVICE_UNAVAILABLE = 2904 HttpServletResponse.SC_SERVICE_UNAVAILABLE; 2905 2906 2907 2913 public static final int SC_CONTINUE = 100; 2914 2915 2916 2920 public static final int SC_METHOD_NOT_ALLOWED = 405; 2921 2922 2923 2928 public static final int SC_CONFLICT = 409; 2929 2930 2931 2936 public static final int SC_PRECONDITION_FAILED = 412; 2937 2938 2939 2944 public static final int SC_REQUEST_TOO_LONG = 413; 2945 2946 2947 2953 public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415; 2954 2955 2956 2958 2959 2963 public static final int SC_MULTI_STATUS = 207; 2964 2967 2968 2972 public static final int SC_UNPROCESSABLE_ENTITY = 418; 2973 2976 2977 2982 public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419; 2983 2986 2987 2993 public static final int SC_METHOD_FAILURE = 420; 2994 2995 2996 3002 public static final int SC_LOCKED = 423; 3003 3004 3005 3007 3008 static { 3009 addStatusCodeMap(SC_OK, "OK"); 3011 addStatusCodeMap(SC_CREATED, "Created"); 3012 addStatusCodeMap(SC_ACCEPTED, "Accepted"); 3013 addStatusCodeMap(SC_NO_CONTENT, "No Content"); 3014 addStatusCodeMap(SC_MOVED_PERMANENTLY, "Moved Permanently"); 3015 addStatusCodeMap(SC_MOVED_TEMPORARILY, "Moved Temporarily"); 3016 addStatusCodeMap(SC_NOT_MODIFIED, "Not Modified"); 3017 addStatusCodeMap(SC_BAD_REQUEST, "Bad Request"); 3018 addStatusCodeMap(SC_UNAUTHORIZED, "Unauthorized"); 3019 addStatusCodeMap(SC_FORBIDDEN, "Forbidden"); 3020 addStatusCodeMap(SC_NOT_FOUND, "Not Found"); 3021 addStatusCodeMap(SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); 3022 addStatusCodeMap(SC_NOT_IMPLEMENTED, "Not Implemented"); 3023 addStatusCodeMap(SC_BAD_GATEWAY, "Bad Gateway"); 3024 addStatusCodeMap(SC_SERVICE_UNAVAILABLE, "Service Unavailable"); 3025 addStatusCodeMap(SC_CONTINUE, "Continue"); 3026 addStatusCodeMap(SC_METHOD_NOT_ALLOWED, "Method Not Allowed"); 3027 addStatusCodeMap(SC_CONFLICT, "Conflict"); 3028 addStatusCodeMap(SC_PRECONDITION_FAILED, "Precondition Failed"); 3029 addStatusCodeMap(SC_REQUEST_TOO_LONG, "Request Too Long"); 3030 addStatusCodeMap(SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type"); 3031 addStatusCodeMap(SC_MULTI_STATUS, "Multi-Status"); 3033 addStatusCodeMap(SC_UNPROCESSABLE_ENTITY, "Unprocessable Entity"); 3034 addStatusCodeMap(SC_INSUFFICIENT_SPACE_ON_RESOURCE, 3035 "Insufficient Space On Resource"); 3036 addStatusCodeMap(SC_METHOD_FAILURE, "Method Failure"); 3037 addStatusCodeMap(SC_LOCKED, "Locked"); 3038 } 3039 3040 3041 3043 3044 3053 public static String getStatusText(int nHttpStatusCode) { 3054 Integer intKey = new Integer (nHttpStatusCode); 3055 3056 if (!mapStatusCodes.containsKey(intKey)) { 3057 return ""; 3058 } else { 3059 return (String ) mapStatusCodes.get(intKey); 3060 } 3061 } 3062 3063 3064 3066 3067 3074 private static void addStatusCodeMap(int nKey, String strVal) { 3075 mapStatusCodes.put(new Integer (nKey), strVal); 3076 } 3077 3078}; 3079 3080 | Popular Tags |