def __init__(self, domroot=None, aces=None): """ Constructor should be called with either no parameters (create blank ACE), or one parameter (a DOM tree or ACE list). @param domroot: A DOM tree (default: None). @type domroot: L{webdav.WebdavResponse.Element} object @param aces: ACE objects (default: None) @type aces: C{list} of L{ACE} objects @raise WebdavError: When non-valid parameters are passed a L{WebdavError} is raised. """ self.withInherited = None self.aces = [] if domroot: for child in domroot.children: if child.name == Constants.TAG_ACE and child.ns == Constants.NS_DAV: self.addAce(ACE(child)) else: # This shouldn't happen, someone screwed up with the params ... raise WebdavError('Non-ACE tag handed to ACL constructor: ' + child.ns + child.name) elif isinstance(aces, list) or isinstance(aces, tuple): self.addAces(aces) elif domroot == None and aces == None: # no param ==> blank object pass else: # This shouldn't happen, someone screwed up with the params ... raise WebdavError('non-valid parameters handed to ACL constructor')
def __init__(self, privilege=None, domroot=None): """ Constructor should be called with either no parameters (create blank Privilege), one parameter (a DOM tree or privilege name to inicialize it directly). @param domroot: A DOM tree (default: None). @type domroot: L{webdav.WebdavResponse.Element} object @param privilege: The valid name of a privilege (default: None). @type privilege: C{string} @raise WebdavError: When non-valid parameters or sets of parameters are passed a L{WebdavError} is raised. """ self.name = None if domroot: if len(domroot.children) != 1: raise WebdavError('Wrong number of elements for Privilege constructor, we have: %i' \ % (len(domroot.children))) else: child = domroot.children[0] if child.ns == Constants.NS_DAV and child.name in self._TAG_LIST_PRIVILEGES or \ child.ns == Constants.NS_TAMINO and child.name in self._TAG_LIST_PRIVILEGES_TAMINO: self.name = child.name else: raise WebdavError('Not a valid privilege tag, we have: %s%s' \ % (child.ns, child.name)) elif privilege: if privilege in self._TAG_LIST_PRIVILEGES: self.name = privilege else: raise WebdavError('Not a valid privilege tag, we have: %s.' % str(privilege))
def __init__(self, domroot=None): """ Constructor should be called with either no parameters (create blank GrantDeny), or one parameter (a DOM tree). @param domroot: A DOM tree (default: None). @type domroot: L{webdav.WebdavResponse.Element} object @raise WebdavError: When non-valid parameters are passed a L{WebdavError} is raised. """ self.grantDeny = 0 # 0: deny, 1: grant self.privileges = [] if domroot: self.grantDeny = (domroot.name == Constants.TAG_GRANT) for child in domroot.children: if child.name == Constants.TAG_PRIVILEGE and child.ns == Constants.NS_DAV: self.privileges.append(Privilege(domroot=child)) else: # This shouldn't happen, someone screwed up with the params ... raise WebdavError('Non-privilege tag handed to GrantDeny constructor: %s' \ % child.name) elif domroot == None: # no param ==> blank object pass else: # This shouldn't happen, someone screwed up with the params ... raise WebdavError('Non-valid parameters handed to GrantDeny constructor.')
def testExists(self): """ Tests the normal behavior of the exists method. """ adapter = DataWebdavAdapter("/anotherIdentifier", SimpleMock(), SimpleMock(), SimpleMock(SimpleMock())) self.assertTrue(adapter.exists()) adapter = DataWebdavAdapter("/anotherIdentifier", SimpleMock(), SimpleMock(), SimpleMock(error=WebdavError("", 404))) self.assertFalse(adapter.exists()) adapter = DataWebdavAdapter("/anotherIdentifier", SimpleMock(), SimpleMock(), SimpleMock(error=WebdavError(""))) self.assertRaises(PersistenceError, adapter.exists)
def __init__(self, domroot=None, displayname=None, principalURL=None): """ Constructor should be called with either no parameters (create blank Principal), one parameter (a DOM tree), or two parameters (displayname and URL or property tag). @param domroot: A DOM tree (default: None). @type domroot: L{webdav.WebdavResponse.Element} object @param displayname: The display name of a principal (default: None). @type displayname: C{string} @param principalURL: The URL representing a principal (default: None). @type principalURL: C{string} @raise WebdavError: When non-valid parameters or sets of parameters are passed a L{WebdavError} is raised. """ self.displayname = None self.principalURL = None self.property = None if domroot: for child in domroot.children: if child.ns == Constants.NS_DAV and (child.name in self._TAG_LIST_PRINCIPALS): if child.name == Constants.TAG_PROP: self.displayname = \ child.find(Constants.PROP_DISPLAY_NAME, Constants.NS_DAV) elif child.name == Constants.TAG_HREF: self.principalURL = child.textof() if self.principalURL and self.property in self._TAG_LIST_STATUS: raise WebdavError('Principal cannot contain a URL and "%s"' % (self.property)) elif child.name == Constants.TAG_PROPERTY: if child.count() == 1: if self.property: raise WebdavError('Property for principal has already been set: old "%s", new "%s"' \ % (self.property, child.pop().name)) elif self.principalURL: raise WebdavError('Principal cannot contain a URL and "%s"' % (self.property)) else: self.property = child.pop().name else: raise WebdavError("There should be only one value in the property for a principal, we have: %s" \ % child.name) else: if self.property: raise WebdavError('Property for principal has already been set: old "%s", new "%s"' \ % (self.property, child.name)) else: self.property = child.name if self.principalURL and self.property in self._TAG_LIST_STATUS: raise WebdavError('Principal cannot contain a URL and "%s"' % (self.property)) else: # This shouldn't happen, something's wrong with the DOM tree raise WebdavError('Non-valid tag in principal DOM tree for constructor: %s' % child.name) elif displayname == None or principalURL == None: if displayname: self.displayname = displayname if principalURL: self.principalURL = principalURL else: # This shouldn't happen, someone screwed up with the params ... raise WebdavError('Non-valid parameters handed to Principal constructor.')
def _getterMock(self): """ Raises a WebDAV-error. """ if self.raiseError: raise WebdavError("") else: return self.result
def lock(self, owner): """ Locks this resource for exclusive write access. This means that for succeeding write operations the returned lock token has to be passed. If the methode does not throw an exception the lock has been granted. @param owner: describes the lock holder @return: lock token string (automatically generated) @rtype: L{LockToken} """ response = self.connection.lock(self.path, owner) if response.status == Constants.CODE_MULTISTATUS and response.msr.errorCount > 0: raise WebdavError( "Request failed: " + response.msr.reason, response.msr.code) if response.locktoken is None: raise WebdavError( "Request failed: No lock token in answer") return LockToken(self.url, response.locktoken)
def testErrorHandlingUsingLibraryInstances(self): """ Tests the error handling when using concrete library instances. """ adapter = MetadataWebdavAdapter( "identifier", SimpleMock(), SimpleMock(), SimpleMock(), SimpleMock(SimpleMock(error=WebdavError("")))) self.assertRaises(PersistenceError, adapter.retrieve) self.assertRaises(PersistenceError, adapter.update, dict()) self.assertRaises(PersistenceError, adapter.delete, [])
def move(self, toUrl): """ Moves this resource to the given path or renames it. @param toUrl: new (URI) path """ self.connection.logger.debug("Move to " + repr(toUrl)); _checkUrl(toUrl) response = self.connection.move(self.path, toUrl) if response.status == Constants.CODE_MULTISTATUS and response.msr.errorCount > 0: raise WebdavError("Request failed: " + response.msr.reason, response.msr.code)
def validate(self): """ Check whether this URL contains a WebDAV collection. Uses the WebDAV OPTION method. @raise WebdavError: L{WebdavError} if URL does not contain a WebDAV collection resource. """ super(CollectionStorer, self).validate() isCollection = self.readProperty(Constants.NS_DAV, Constants.PROP_RESOURCE_TYPE) if not (isCollection and isCollection.children): raise WebdavError("Not a collection URL.", 0)
def testErrorHandling(self): self._connectionHelper.error = PersistenceError("") self.assertRaises(PersistenceError, self._adapter.retrieveAcl) self.assertRaises(PersistenceError, self._adapter.updateAcl, dict()) self.assertRaises(PersistenceError, self._adapter.retrievePrivileges) self._connectionHelper.error = None self._connectionHelper.value = SimpleMock(error=WebdavError("")) self.assertRaises(PersistenceError, self._adapter.retrieveAcl) self.assertRaises(PersistenceError, self._adapter.updateAcl, dict()) self.assertRaises(PersistenceError, self._adapter.retrievePrivileges)
def validate(self): """ Check whether URL contains a WebDAV resource Uses the WebDAV OPTIONS method. @raise WebdavError: L{WebdavError} if URL does not contain a WebDAV resource """ #davHeader = response.getheader(HTTP_HEADER_DAV) davHeader = self.getSpecificOption(Constants.HTTP_HEADER_DAV) self.connection.logger.debug("HEADER DAV: %s" % davHeader) if not(davHeader) or davHeader.find("2") < 0: # DAV class 2 supported ? raise WebdavError("URL does not support WebDAV", 0)
def _filter_property_response(self, response): """ This is a workaround for servers which do not correctly handle the depth header. I.e., we simply try to identify the matching response for the resource. """ for key in [self.path, self.path[:-1], self.url]: # Server may return path or URL try: return response.msr[key] except KeyError: continue raise WebdavError("No property result for '%s'" % self.url)
def copy(self, other): """ Copy Privilege object. @param other: Another privilege to copy. @type other: L{Privilege} object @raise WebdavError: When an object that is not a L{Privilege} is passed a L{WebdavError} is raised. """ if not isinstance(other, Privilege): raise WebdavError('Non-Privilege object passed to copy method: %s' % other.__class__) self.name = other.name
def copy(self, other): '''Copy an ACL object. @param other: Another ACL to copy. @type other: L{ACL} object @raise WebdavError: When an object that is not an L{ACL} is passed a L{WebdavError} is raised. ''' if not isinstance(other, ACL): raise WebdavError('Non-ACL object passed to copy method: %s' % other.__class__) self.withInherited = other.withInherited if other.aces: self.addAces(other.aces)
def copy(self, other): """Copy Principal object. @param other: Another principal to copy. @type other: L{Principal} object @raise WebdavError: When an object that is not a L{Principal} is passed a L{WebdavError} is raised. """ if not isinstance(other, Principal): raise WebdavError('Non-Principal object passed to copy method: ' % other.__class__) self.displayname = other.displayname self.principalURL = other.principalURL self.property = other.property
def extractSupportedPrivilegeSet(userPrivileges): """ Returns a dictionary of supported privileges. @param userPrivileges: A DOM tree. @type userPrivileges: L{webdav.WebdavResponse.Element} object @raise WebdavError: When unknown elements appear in the C{DAV:supported-privilege} appear a L{WebdavError} is raised. @return: A dictionary with privilege names as keys and privilege descriptions as values. @rtype: C{dictionary} """ result = {} for element in userPrivileges.children: if element.name == Constants.TAG_SUPPORTED_PRIVILEGE: privName = '' privDescription = '' for privilege in element.children: if privilege.name == Constants.TAG_PRIVILEGE: privName = privilege.children[0].name elif privilege.name == Constants.TAG_DESCRIPTION: privDescription = privilege.textof() else: raise WebdavError( 'Unknown element in DAV:supported-privilege: ' + privilege.name) if privName and privDescription: result[privName] = privDescription privName = '' privDescription = '' else: raise WebdavError( 'Invalid element tag in DAV:supported-privilege-set: ' + element.name) return result
def testErrorHandlingUsingLibraryInstances(self): """ Tests the error handling when using concrete library instances. """ connectionHelperMock = SimpleMock(methodNameResultMap={ "determineResourceType": (None, WebdavError("")) }) adapter = DataWebdavAdapter("/anotherIdentifier", SimpleMock(), SimpleMock(""), connectionHelperMock) try: self.assertFalse(adapter.isLink) self.fail("PersistenceError not raised.") except PersistenceError: self.assertTrue(True) try: self.assertFalse(adapter.isLeaf) self.fail("PersistenceError not raised.") except PersistenceError: self.assertTrue(True) try: self.assertFalse(adapter.isCollection) self.fail("PersistenceError not raised.") except PersistenceError: self.assertTrue(True) self.assertRaises(PersistenceError, adapter.getChildren) connectionHelperMock = SimpleMock(SimpleMock(error=WebdavError(""))) adapter = DataWebdavAdapter("/anotherIdentifier", SimpleMock(), SimpleMock(""), connectionHelperMock) self.assertRaises(PersistenceError, adapter.createLink, self._defaultAdapter) self.assertRaises(PersistenceError, adapter.createResource) self.assertRaises(PersistenceError, adapter.createCollection) self.assertRaises(PersistenceError, adapter.writeData, StringIO("")) self.assertRaises(PersistenceError, adapter.readData) self.assertRaises(PersistenceError, adapter.delete) self.assertRaises(PersistenceError, adapter.move, self._defaultAdapter) self.assertRaises(PersistenceError, adapter.copy, self._defaultAdapter)
def delete(self, lockToken=None): """ Deletes this resource. @param lockToken: String returned by last lock operation or null. @type lockToken: L{LockToken} """ assert lockToken == None or isinstance(lockToken, LockToken), \ "Invalid lockToken argument %s" % type(lockToken) header = {} if lockToken: header = lockToken.toHeader() response = self.connection.delete(self.path, header) if response.status == Constants.CODE_MULTISTATUS and response.msr.errorCount > 0: raise WebdavError("Request failed: " + response.msr.reason, response.msr.code)
def readProperty(self, nameSpace, name): """ Reads the given property. @param nameSpace: XML-namespace @type nameSpace: string @param name: A property name. @type name: string @return: a map from property names to DOM Element or String values. """ results = self.readProperties((nameSpace, name)) if len(results) == 0: raise WebdavError("Property is missing: " + results.reason) return results.values()[0]
def copy(self, toUrl, infinity=True): """ Copies this resource. @param toUrl: target URI path @param infinity: Flag that indicates that the complete content of collection is copied. (default) """ self.connection.logger.debug("Copy to " + repr(toUrl)) _checkUrl(toUrl) if infinity: response = self.connection.copy(self.path, toUrl) else: response = self.connection.copy(self.path, toUrl, 0) if response.status == Constants.CODE_MULTISTATUS and response.msr.errorCount > 0: raise WebdavError("Request failed: " + response.msr.reason, response.msr.code)
def copy(self, other): """ Copy a GrantDeny object. @param other: Another grant or deny clause to copy. @type other: L{GrantDeny} object @raise WebdavError: When an object that is not an L{GrantDeny} is passed a L{WebdavError} is raised. """ if not isinstance(other, GrantDeny): raise WebdavError('Non-GrantDeny object passed to copy method: %s' \ % other) self.grantDeny = other.grantDeny if other.privileges: self.addPrivileges(other.privileges)
def __init__(self, domroot=None, principal=None, grantDenies=None): """ Constructor should be called with either no parameters (create blank ACE), one parameter (a DOM tree or principal), or two parameters (principal and sequence of GrantDenies). @param domroot: A DOM tree (default: None). @type domroot: L{webdav.WebdavResponse.Element} object @param principal: A principal (user or group), (default: None). @type principal: L{Principal} object @param grantDenies: Grant and deny clauses for privileges (default: None). @type grantDenies: sequence of L{GrantDeny} objects @raise WebdavError: When non-valid parameters are passed a L{WebdavError} is raised. """ self.principal = Principal() self.protected = None self.inherited = None self.invert = None self.grantDenies = [] if domroot: self.principal = Principal(domroot=domroot.find( Constants.TAG_PRINCIPAL, Constants.NS_DAV)) self.inherited = domroot.find(Constants.TAG_INHERITED, Constants.NS_DAV) if self.inherited: self.inherited = self.inherited.children[0].textof() if domroot.find(Constants.TAG_PROTECTED, Constants.NS_DAV): self.protected = 1 for child in domroot.children: if child.ns == Constants.NS_DAV \ and (child.name == Constants.TAG_GRANT or child.name == Constants.TAG_DENY): self.grantDenies.append(GrantDeny(domroot=child)) elif isinstance(principal, Principal): newPrincipal = Principal() newPrincipal.copy(principal) self.principal = newPrincipal if (isinstance(grantDenies, list) or isinstance(grantDenies, tuple)): self.addGrantDenies(grantDenies) elif domroot == None and grantDenies == None: # no param ==> blank ACE pass else: # This shouldn't happen, someone screwed up with the params ... raise WebdavError('non-valid parameters handed to ACE constructor')
def readProperties(self, *names): """ Reads the given properties. @param names: a list of property names. A property name is a (XmlNameSpace, propertyName) tuple. @return: a map from property names to DOM Element or String values. """ assert names, "Property names are missing." body = createFindBody(names, self.defaultNamespace) response = self.connection.propfind(self.path, body, depth=0) properties = response.msr.values()[0] if properties.errorCount > 0: raise WebdavError( "Property is missing on '%s': %s" % (self.path, properties.reason), properties.code) return properties
def deleteProperties(self, lockToken=None, *names): """ Removes the given properties from this resource. @param lockToken: if the resource has been locked this is the lock token. @type lockToken: L{LockToken} @param names: a collection of property names. A property name is a (XmlNameSpace, propertyName) tuple. """ assert lockToken == None or isinstance(lockToken, LockToken), \ "Invalid lockToken argument %s" % type(lockToken) header = {} if lockToken: header = lockToken.toHeader() body = createDeleteBody(names, self.defaultNamespace) response = self.connection.proppatch(self.path, body, header) if response.msr.errorCount > 0: raise WebdavError("Request failed: " + response.msr.reason, response.msr.code)
def readProperties(self, *names, **kwargs): """ Reads the given properties. @param names: a list of property names. A property name is a (XmlNameSpace, propertyName) tuple. @param ignore404: a boolean flag. Indicates if an error should be raised for missing properties. @return: a map from property names to DOM Element or String values. """ assert names, "Property names are missing." ignore404 = kwargs.pop('ignore404', False) body = createFindBody(names, self.defaultNamespace) response = self.connection.propfind(self.path, body, depth=0) properties = response.msr.values()[0] if not ignore404 and properties.errorCount > 0 : raise WebdavError("Property is missing on '%s': %s" % (self.path, properties.reason), properties.code) return properties
def __init__(self, url, connection=None, validateResourceNames=True): """ Creates an instance for the given URL User must invoke validate() after construction to check the resource on the server. @param url: Unique resource location for this storer. @type url: C{string} @param connection: this optional parameter contains a Connection object for the host part of the given URL. Passing a connection saves memory by sharing this connection. (defaults to None) @type connection: L{webdav.Connection} @raise WebdavError: If validation of resource name path parts fails. """ assert connection == None or isinstance(connection, Connection) parts = urlsplit(url, allow_fragments=False) self.path = parts[2] self.validateResourceNames = validateResourceNames # validate URL path for part in self.path.split('/'): if part != '' and not "ino:" in part: # explicitly allowing this character sequence as a part of a path (Tamino 4.4) if self.validateResourceNames: try: validateResourceName(part) except WrongNameError: raise WebdavError("Found invalid resource name part.") self.name = part # was: filter(lambda part: part and validateResourceName(part), self.path.split('/')) # but filter is deprecated self.defaultNamespace = None # default XML name space of properties if connection: self.connection = connection else: conn = parts[1].split(":") if len(conn) == 1: self.connection = Connection( conn[0], protocol=parts[0]) # host and protocol else: self.connection = Connection( conn[0], int(conn[1]), protocol=parts[0]) # host and port and protocol self.versionHandler = VersionHandler(self.connection, self.path)
def deleteResource(self, name, lockToken=None): """ Delete a collection which is contained within this collection @param name: leaf name of a contained collection resource @param lockToken: None or token returned by last lock operation @type lockToken: L{LockToken} """ assert isinstance(name, types.StringType) or isinstance(name, types.UnicodeType) assert lockToken == None or isinstance(lockToken, LockToken), \ "Invalid lockToken argument %s" % type(lockToken) header = {} if lockToken: header = lockToken.toHeader() if self.validateResourceNames: validateResourceName(name) response = self.connection.delete(self.path + name, header) if response.status == Constants.CODE_MULTISTATUS and response.msr.errorCount > 0: raise WebdavError("Request failed: %s" % response.msr.reason, response.msr.code)
def writeProperties(self, properties, lockToken=None): """ Sets or updates the given properties. @param lockToken: if the resource has been locked this is the lock token. @type lockToken: L{LockToken} @param properties: a map from property names to a String or DOM element value for each property to add or update. """ assert isinstance(properties, types.DictType) assert lockToken == None or isinstance(lockToken, LockToken), \ "Invalid lockToken argument %s" % type(lockToken) header = {} if lockToken: header = lockToken.toHeader() body = createUpdateBody(properties, self.defaultNamespace) response = self.connection.proppatch(self.path, body, header) if response.msr.errorCount > 0: raise WebdavError("Request failed: " + response.msr.reason, response.msr.code)
def copy(self, other): '''Copy an ACE object. @param other: Another ACE to copy. @type other: L{ACE} object @raise WebdavError: When an object that is not an L{ACE} is passed a L{WebdavError} is raised. ''' if not isinstance(other, ACE): raise WebdavError('Non-ACE object passed to copy method: %s.' % other.__class__) self.invert = other.invert self.protected = other.protected self.inherited = other.inherited self.principal = Principal() if other.principal: self.principal.copy(other.principal) if other.grantDenies: self.addGrantDenies(other.grantDenies)