OwlCyberSecurity - MANAGER
Edit File: static.py
# -*- test-case-name: txweb2.dav.test.test_static -*- ## # Copyright (c) 2005-2017 Apple Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # DRI: Wilfredo Sanchez, wsanchez@apple.com ## """ WebDAV-aware static resources. """ __all__ = ["DAVFile"] from twisted.python.filepath import InsecurePath from twisted.internet.defer import succeed, deferredGenerator, waitForDeferred from twext.python.log import Logger from txweb2 import http_headers from txweb2 import responsecode from txweb2.dav.resource import DAVResource, davPrivilegeSet from txweb2.dav.resource import TwistedGETContentMD5 from txweb2.dav.util import bindMethods from txweb2.http import HTTPError, StatusResponse from txweb2.static import File log = Logger() try: from txweb2.dav.xattrprops import xattrPropertyStore as DeadPropertyStore except ImportError: log.info("No dead property store available; using nonePropertyStore.") log.info("Setting of dead properties will not be allowed.") from txweb2.dav.noneprops import NonePropertyStore as DeadPropertyStore class DAVFile (DAVResource, File): """ WebDAV-accessible File resource. Extends txweb2.static.File to handle WebDAV methods. """ def __init__( self, path, defaultType="text/plain", indexNames=None, principalCollections=() ): """ @param path: the path of the file backing this resource. @param defaultType: the default mime type (as a string) for this resource and (eg. child) resources derived from it. @param indexNames: a sequence of index file names. @param acl: an L{IDAVAccessControlList} with the . """ File.__init__( self, path, defaultType=defaultType, ignoredExts=(), processors=None, indexNames=indexNames, ) DAVResource.__init__(self, principalCollections=principalCollections) def __repr__(self): return "<%s: %s>" % (self.__class__.__name__, self.fp.path) ## # WebDAV ## def etag(self): if not self.fp.exists(): return succeed(None) if self.hasDeadProperty(TwistedGETContentMD5): return succeed(http_headers.ETag(str(self.readDeadProperty(TwistedGETContentMD5)))) else: return super(DAVFile, self).etag() def davComplianceClasses(self): return ("1", "access-control") # Add "2" when we have locking def deadProperties(self): if not hasattr(self, "_dead_properties"): self._dead_properties = DeadPropertyStore(self) return self._dead_properties def isCollection(self): """ See L{IDAVResource.isCollection}. """ return self.fp.isdir() ## # ACL ## def supportedPrivileges(self, request): return succeed(davPrivilegeSet) ## # Quota ## def quotaSize(self, request): """ Get the size of this resource. TODO: Take into account size of dead-properties. Does stat include xattrs size? @return: an L{Deferred} with a C{int} result containing the size of the resource. """ if self.isCollection(): def walktree(top): """ Recursively descend the directory tree rooted at top, calling the callback function for each regular file @param top: L{FilePath} for the directory to walk. """ total = 0 for f in top.listdir(): child = top.child(f) if child.isdir(): # It's a directory, recurse into it result = waitForDeferred(walktree(child)) yield result total += result.getResult() elif child.isfile(): # It's a file, call the callback function total += child.getsize() else: # Unknown file type, print a message pass yield total walktree = deferredGenerator(walktree) return walktree(self.fp) else: return succeed(self.fp.getsize()) ## # Workarounds for issues with File ## def ignoreExt(self, ext): """ Does nothing; doesn't apply to this subclass. """ pass def locateChild(self, req, segments): """ See L{IResource}C{.locateChild}. """ # If getChild() finds a child resource, return it try: child = self.getChild(segments[0]) if child is not None: return (child, segments[1:]) except InsecurePath: raise HTTPError(StatusResponse(responsecode.FORBIDDEN, "Invalid URL path")) # If we're not backed by a directory, we have no children. # But check for existance first; we might be a collection resource # that the request wants created. self.fp.restat(False) if self.fp.exists() and not self.fp.isdir(): return (None, ()) # OK, we need to return a child corresponding to the first segment path = segments[0] if path == "": # Request is for a directory (collection) resource return (self, ()) return (self.createSimilarFile(self.fp.child(path).path), segments[1:]) def createSimilarFile(self, path): return self.__class__( path, defaultType=self.defaultType, indexNames=self.indexNames[:], principalCollections=self.principalCollections()) # # Attach method handlers to DAVFile # import txweb2.dav.method bindMethods(txweb2.dav.method, DAVFile)