1 17 package org.alfresco.repo.webdav; 18 19 import java.io.Serializable ; 20 import java.io.UnsupportedEncodingException ; 21 import java.net.URLDecoder ; 22 import java.net.URLEncoder ; 23 import java.text.SimpleDateFormat ; 24 import java.util.Date ; 25 import java.util.HashMap ; 26 import java.util.Hashtable ; 27 import java.util.Map ; 28 import java.util.StringTokenizer ; 29 30 import javax.servlet.http.HttpServletRequest ; 31 32 import org.alfresco.error.AlfrescoRuntimeException; 33 import org.alfresco.model.ContentModel; 34 import org.alfresco.service.cmr.repository.ContentData; 35 import org.alfresco.service.cmr.repository.NodeRef; 36 import org.alfresco.service.namespace.QName; 37 import org.apache.commons.logging.Log; 38 import org.apache.commons.logging.LogFactory; 39 40 45 public class WebDAV 46 { 47 49 private static Log logger = LogFactory.getLog("org.alfresco.webdav.protocol"); 50 51 53 public static final String DAV_NS = "D"; 54 public static final String DAV_NS_PREFIX = DAV_NS + ":"; 55 56 58 public static final int DEPTH_0 = 0; 59 public static final int DEPTH_1 = 1; 60 public static final int DEPTH_INFINITY = -1; 61 public static final short TIMEOUT_INFINITY = -1; 62 63 65 public static final int WEBDAV_SC_MULTI_STATUS = 207; 66 public static final int WEBDAV_SC_LOCKED = 423; 67 68 70 public static final String SC_OK_DESC = "OK"; 71 public static final String SC_NOT_FOUND_DESC = "Not Found"; 72 73 75 public static final String METHOD_PUT = "PUT"; 76 public static final String METHOD_POST = "POST"; 77 public static final String METHOD_GET = "GET"; 78 public static final String METHOD_DELETE = "DELETE"; 79 public static final String METHOD_HEAD = "HEAD"; 80 public static final String METHOD_OPTIONS = "OPTIONS"; 81 public static final String METHOD_PROPFIND = "PROPFIND"; 82 public static final String METHOD_PROPPATCH = "PROPPATCH"; 83 public static final String METHOD_MKCOL = "MKCOL"; 84 public static final String METHOD_MOVE = "MOVE"; 85 public static final String METHOD_COPY = "COPY"; 86 public static final String METHOD_LOCK = "LOCK"; 87 public static final String METHOD_UNLOCK = "UNLOCK"; 88 89 91 public static final String HEADER_CONTENT_LENGTH = "Content-Length"; 92 public static final String HEADER_CONTENT_TYPE = "Content-Type"; 93 public static final String HEADER_DEPTH = "Depth"; 94 public static final String HEADER_DESTINATION = "Destination"; 95 public static final String HEADER_ETAG = "ETag"; 96 public static final String HEADER_EXPECT = "Expect"; 97 public static final String HEADER_EXPECT_CONTENT = "100-continue"; 98 public static final String HEADER_IF = "If"; 99 public static final String HEADER_IF_MATCH = "If-Match"; 100 public static final String HEADER_IF_MODIFIED_SINCE = "If-Modified-Since"; 101 public static final String HEADER_IF_NONE_MATCH = "If-None-Match"; 102 public static final String HEADER_IF_RANGE = "If-Range"; 103 public static final String HEADER_IF_UNMODIFIED_SINCE = "If-Unmodified-Since"; 104 public static final String HEADER_LAST_MODIFIED = "Last-Modified"; 105 public static final String HEADER_LOCK_TOKEN = "Lock-Token"; 106 public static final String HEADER_OVERWRITE = "Overwrite"; 107 public static final String HEADER_RANGE = "Range"; 108 public static final String HEADER_TIMEOUT = "Timeout"; 109 110 112 public static final String HEADER_IF_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz"; 113 114 116 public static final String ASTERISK = "*"; 117 public static final String DEFAULT_NAMESPACE_URI = "DAV:"; 118 public static final String DIR_SEPARATOR = "/"; 119 public static final String FAKE_TOKEN = "faketoken"; 120 public static final String HTTP1_1 = "HTTP/1.1"; 121 public static final String INFINITE = "Infinite"; 122 public static final String INFINITY = "infinity"; 123 public static final String OPAQUE_LOCK_TOKEN = "opaquelocktoken:"; 124 public static final String NAMESPACE_SEPARATOR = ":"; 125 public static final String SECOND = "Second-"; 126 public static final String HEADER_VALUE_SEPARATOR = ","; 127 public static final String ZERO = "0"; 128 public static final String ONE = "1"; 129 public static final String T = "T"; 130 131 133 public static final String XML_NS = "xmlns"; 134 135 public static final String XML_ACTIVE_LOCK = "activelock"; 136 public static final String XML_ALLPROP = "allprop"; 137 public static final String XML_COLLECTION = "collection"; 138 public static final String XML_CREATION_DATE = "creationdate"; 139 public static final String XML_DEPTH = "depth"; 140 public static final String XML_DISPLAYNAME = "displayname"; 141 public static final String XML_EXCLUSIVE = "exclusive"; 142 public static final String XML_GET_CONTENT_LANGUAGE = "getcontentlanguage"; 143 public static final String XML_GET_CONTENT_LENGTH = "getcontentlength"; 144 public static final String XML_GET_CONTENT_TYPE = "getcontenttype"; 145 public static final String XML_GET_ETAG = "getetag"; 146 public static final String XML_GET_LAST_MODIFIED = "getlastmodified"; 147 public static final String XML_HREF = "href"; 148 public static final String XML_LOCK_DISCOVERY = "lockdiscovery"; 149 public static final String XML_LOCK_SCOPE = "lockscope"; 150 public static final String XML_LOCK_TOKEN = "locktoken"; 151 public static final String XML_LOCK_TYPE = "locktype"; 152 public static final String XML_MULTI_STATUS = "multistatus"; 153 public static final String XML_OWNER = "owner"; 154 public static final String XML_PROP = "prop"; 155 public static final String XML_PROPNAME = "propname"; 156 public static final String XML_PROPSTAT = "propstat"; 157 public static final String XML_RESOURCE_TYPE = "resourcetype"; 158 public static final String XML_RESPONSE = "response"; 159 public static final String XML_SHARED = "shared"; 160 public static final String XML_SOURCE = "source"; 161 public static final String XML_STATUS = "status"; 162 public static final String XML_SUPPORTED_LOCK = "supportedlock"; 163 public static final String XML_TIMEOUT = "timeout"; 164 public static final String XML_WRITE = "write"; 165 166 168 public static final String XML_NS_ACTIVE_LOCK = DAV_NS_PREFIX + "activelock"; 169 public static final String XML_NS_ALLPROP = DAV_NS_PREFIX + "allprop"; 170 public static final String XML_NS_COLLECTION = DAV_NS_PREFIX + "collection"; 171 public static final String XML_NS_CREATION_DATE = DAV_NS_PREFIX + "creationdate"; 172 public static final String XML_NS_DEPTH = DAV_NS_PREFIX + "depth"; 173 public static final String XML_NS_DISPLAYNAME = DAV_NS_PREFIX + "displayname"; 174 public static final String XML_NS_EXCLUSIVE = DAV_NS_PREFIX + "exclusive"; 175 public static final String XML_NS_GET_CONTENT_LANGUAGE = DAV_NS_PREFIX + "getcontentlanguage"; 176 public static final String XML_NS_GET_CONTENT_LENGTH = DAV_NS_PREFIX + "getcontentlength"; 177 public static final String XML_NS_GET_CONTENT_TYPE = DAV_NS_PREFIX + "getcontenttype"; 178 public static final String XML_NS_GET_ETAG = DAV_NS_PREFIX + "getetag"; 179 public static final String XML_NS_GET_LAST_MODIFIED = DAV_NS_PREFIX + "getlastmodified"; 180 public static final String XML_NS_HREF = DAV_NS_PREFIX + "href"; 181 public static final String XML_NS_LOCK_DISCOVERY = DAV_NS_PREFIX + "lockdiscovery"; 182 public static final String XML_NS_LOCK_SCOPE = DAV_NS_PREFIX + "lockscope"; 183 public static final String XML_NS_LOCK_TOKEN = DAV_NS_PREFIX + "locktoken"; 184 public static final String XML_NS_LOCK_TYPE = DAV_NS_PREFIX + "locktype"; 185 public static final String XML_NS_MULTI_STATUS = DAV_NS_PREFIX + "multistatus"; 186 public static final String XML_NS_OWNER = DAV_NS_PREFIX + "owner"; 187 public static final String XML_NS_PROP = DAV_NS_PREFIX + "prop"; 188 public static final String XML_NS_PROPNAME = DAV_NS_PREFIX + "propname"; 189 public static final String XML_NS_PROPSTAT = DAV_NS_PREFIX + "propstat"; 190 public static final String XML_NS_RESOURCE_TYPE = DAV_NS_PREFIX + "resourcetype"; 191 public static final String XML_NS_RESPONSE = DAV_NS_PREFIX + "response"; 192 public static final String XML_NS_SHARED = DAV_NS_PREFIX + "shared"; 193 public static final String XML_NS_SOURCE = DAV_NS_PREFIX + "source"; 194 public static final String XML_NS_STATUS = DAV_NS_PREFIX + "status"; 195 public static final String XML_NS_SUPPORTED_LOCK = DAV_NS_PREFIX + "supportedlock"; 196 public static final String XML_NS_TIMEOUT = DAV_NS_PREFIX + "timeout"; 197 public static final String XML_NS_WRITE = DAV_NS_PREFIX + "write"; 198 199 public static final String XML_CONTENT_TYPE = "text/xml; charset=UTF-8"; 200 201 private static HashMap s_codeDescriptions = null; 202 203 205 private static final String DIR_SEPERATOR = "\\"; 206 207 209 public static final String PathSeperator = "/"; 210 public static final char PathSeperatorChar = '/'; 211 212 214 public static final String LOCK_TOKEN_SEPERATOR = ":"; 215 216 218 private static final String RootPath = PathSeperator; 219 220 222 private static Hashtable <String , QName> _propertyNameMap; 223 224 226 private static SimpleDateFormat _creationDateFormatter = new SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ss'Z'"); 227 228 230 private static SimpleDateFormat _httpDateFormatter = new SimpleDateFormat (HEADER_IF_DATE_FORMAT); 231 232 238 public static String formatModifiedDate(Date date) 239 { 240 return _httpDateFormatter.format(date); 241 } 242 243 249 public static String formatModifiedDate(long ldate) 250 { 251 return _httpDateFormatter.format(new Date (ldate)); 252 } 253 254 260 public static String formatCreationDate(Date date) 261 { 262 return _creationDateFormatter.format(date); 263 } 264 265 271 public static String formatCreationDate(long ldate) 272 { 273 return _creationDateFormatter.format(new Date (ldate)); 274 } 275 276 282 public static String formatHeaderDate(Date date) 283 { 284 return _httpDateFormatter.format( date); 285 } 286 287 293 public static String formatHeaderDate(long date) 294 { 295 return _httpDateFormatter.format( new Date (date)); 296 } 297 298 305 public static Object getDAVPropertyValue( Map <QName, Serializable > props, String davPropName) 306 { 307 309 QName propName = _propertyNameMap.get( davPropName); 310 if ( propName == null) 311 throw new AlfrescoRuntimeException("No mapping for WebDAV property " + davPropName); 312 313 Object value = props.get(propName); 315 if (value instanceof ContentData) 316 { 317 ContentData contentData = (ContentData) value; 318 if (davPropName.equals(WebDAV.XML_GET_CONTENT_TYPE)) 319 { 320 value = contentData.getMimetype(); 321 } 322 else if (davPropName.equals(WebDAV.XML_GET_CONTENT_LENGTH)) 323 { 324 value = new Long (contentData.getSize()); 325 } 326 } 327 return value; 328 } 329 330 331 337 public static String getRepositoryPath(HttpServletRequest request) 338 { 339 341 String strPath = null; 342 343 try { 344 strPath = URLDecoder.decode( request.getRequestURI(), "UTF-8"); 345 } 346 catch (Exception ex) { 347 } 348 349 351 String servletPath = request.getServletPath(); 352 353 int rootPos = strPath.indexOf(servletPath); 354 if ( rootPos != -1) 355 strPath = strPath.substring( rootPos); 356 357 359 if (strPath == null) 360 { 361 strPath = request.getServletPath(); 362 } 363 364 366 if (strPath == null || strPath.length() == 0) 367 { 368 strPath = RootPath; 369 } 370 371 373 else if (strPath.endsWith(DIR_SEPARATOR)) 374 { 375 strPath = strPath.substring(0, strPath.length() - 1); 376 } 377 378 380 if ( strPath.startsWith(request.getServletPath())) 381 { 382 int len = request.getServletPath().length(); 383 384 if ( strPath.length() > len) 385 strPath = strPath.substring(len); 386 else 387 strPath = RootPath; 388 } 389 390 392 return strPath; 393 } 394 395 403 public static String getURLForPath(HttpServletRequest request, String path, boolean isCollection) 404 { 405 StringBuilder urlStr = new StringBuilder (request.getRequestURI()); 406 String servletPath = request.getServletPath(); 407 408 int rootPos = urlStr.indexOf(servletPath); 409 if (rootPos != -1) 410 { 411 urlStr.setLength(rootPos + servletPath.length()); 412 } 413 414 if (urlStr.charAt(urlStr.length() - 1) != PathSeperatorChar) 415 { 416 urlStr.append(PathSeperator); 417 } 418 419 if (path.equals(RootPath) == false) 420 { 421 for (StringTokenizer t = new StringTokenizer (path, PathSeperator); t.hasMoreTokens(); ) 423 { 424 urlStr.append( WebDAVHelper.encodeURL(t.nextToken()) ); 425 if (t.hasMoreTokens()) 426 { 427 urlStr.append(PathSeperator); 428 } 429 } 430 } 431 432 if (isCollection && urlStr.charAt( urlStr.length() - 1) != PathSeperatorChar) 434 { 435 urlStr.append( PathSeperator); 436 } 437 438 return urlStr.toString(); 440 } 441 442 450 public static String decodeURL(String strPath) 451 { 452 if (strPath == null) 453 return null; 454 455 459 String strNormalized = null; 460 461 try 462 { 463 strNormalized = URLDecoder.decode(strPath, "UTF-8"); 464 } 465 catch (Exception ex) 466 { 467 logger.error("Error in decodeURL, URL = " + strPath, ex); 468 } 469 470 if (strNormalized == null) 471 return (null); 472 473 475 if (strNormalized.indexOf('\\') >= 0) 476 strNormalized = strNormalized.replace('\\', '/'); 477 478 if (!strNormalized.startsWith("/")) 479 strNormalized = "/" + strNormalized; 480 481 483 while (true) 484 { 485 int index = strNormalized.indexOf("//"); 486 if (index < 0) 487 break; 488 strNormalized = strNormalized.substring(0, index) + strNormalized.substring(index + 1); 489 } 490 491 493 while (true) 494 { 495 int index = strNormalized.indexOf("/./"); 496 if (index < 0) 497 break; 498 strNormalized = strNormalized.substring(0, index) + strNormalized.substring(index + 2); 499 } 500 501 503 while (true) 504 { 505 int index = strNormalized.indexOf("/../"); 506 if (index < 0) 507 break; 508 if (index == 0) 509 return (null); 511 int index2 = strNormalized.lastIndexOf('/', index - 1); 512 strNormalized = strNormalized.substring(0, index2) + strNormalized.substring(index + 3); 513 } 514 515 517 return strNormalized; 518 } 519 520 527 public static final String makeLockToken(NodeRef lockNode, String owner) 528 { 529 StringBuilder str = new StringBuilder (); 530 531 str.append(WebDAV.OPAQUE_LOCK_TOKEN); 532 str.append(lockNode.getId()); 533 str.append(LOCK_TOKEN_SEPERATOR); 534 str.append(owner); 535 536 return str.toString(); 537 } 538 539 545 public static final String [] parseLockToken(String lockToken) 546 { 547 549 if ( lockToken == null) 550 return null; 551 552 554 if ( lockToken.startsWith(WebDAV.OPAQUE_LOCK_TOKEN)) 555 lockToken = lockToken.substring(WebDAV.OPAQUE_LOCK_TOKEN.length()); 556 557 559 int pos = lockToken.indexOf(LOCK_TOKEN_SEPERATOR); 560 if ( pos == -1) 561 return null; 562 563 String [] tokens = new String [2]; 564 565 tokens[0] = lockToken.substring(0,pos); 566 tokens[1] = lockToken.substring(pos + 1); 567 568 return tokens; 569 } 570 571 574 static 575 { 576 578 _propertyNameMap = new Hashtable <String , QName>(); 579 580 _propertyNameMap.put(XML_DISPLAYNAME, ContentModel.PROP_NAME); 581 _propertyNameMap.put(XML_CREATION_DATE, ContentModel.PROP_CREATED); 582 _propertyNameMap.put(XML_GET_LAST_MODIFIED, ContentModel.PROP_MODIFIED); 583 _propertyNameMap.put(XML_GET_CONTENT_TYPE, ContentModel.PROP_CONTENT); 584 } 585 } 586 | Popular Tags |