Ejemplo n.º 1
0
 def move(self, environ, collections, content, user):
     """Manage MOVE request."""
     from_collection = collections[0]
     from_name = xmlutils.name_from_path(
         environ["PATH_INFO"], from_collection)
     if from_name:
         item = from_collection.get_item(from_name)
         if item:
             # Move the item
             to_url_parts = urlparse(environ["HTTP_DESTINATION"])
             if to_url_parts.netloc == environ["HTTP_HOST"]:
                 to_url = to_url_parts.path
                 to_path, to_name = to_url.rstrip("/").rsplit("/", 1)
                 to_collection = ical.Collection.from_path(
                     to_path, depth="0")[0]
                 to_collection.append(to_name, item.text)
                 from_collection.remove(from_name)
                 return client.CREATED, {}, None
             else:
                 # Remote destination server, not supported
                 return client.BAD_GATEWAY, {}, None
         else:
             # No item found
             return client.GONE, {}, None
     else:
         # Moving collections, not supported
         return client.FORBIDDEN, {}, None
Ejemplo n.º 2
0
    def delete(self, environ, read_collections, write_collections, content,
               user):
        """Manage DELETE request."""
        if not len(write_collections):
            return NOT_ALLOWED

        collection = write_collections[0]

        if collection.path == environ["PATH_INFO"].strip("/"):
            # Path matching the collection, the collection must be deleted
            item = collection
        else:
            # Try to get an item matching the path
            item = collection.get_item(
                xmlutils.name_from_path(environ["PATH_INFO"], collection))

        if item:
            # Evolution bug workaround
            etag = environ.get("HTTP_IF_MATCH", item.etag).replace("\\", "")
            if etag == item.etag:
                # No ETag precondition or precondition verified, delete item
                answer = xmlutils.delete(environ["PATH_INFO"], collection)
                return client.OK, {}, answer

        # No item or ETag precondition not verified, do not delete item
        return client.PRECONDITION_FAILED, {}, None
Ejemplo n.º 3
0
    def do_GET(self, environ, read_collections, write_collections, content,
               user):
        """Manage GET request.

        In Radicale, GET requests create collections when the URL is not
        available. This is useful for clients with no MKCOL or MKCALENDAR
        support.

        """
        _logger.info('do_GET %s %s' % (content, user))

        # Display a "Radicale works!" message if the root URL is requested
        if environ["PATH_INFO"] == "/":
            headers = {"Content-type": "text/html"}
            answer = b"<!DOCTYPE html>\n<title>Radicale</title>Radicale works!"
            return client.OK, headers, answer

        if not len(read_collections):
            return NOT_ALLOWED

        collection = read_collections[0]

        item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection)

        if item_name:
            # Get collection item
            item = collection.items.get(item_name)
            if item:
                items = [item]
                if collection.resource_type == "calendar":
                    items.extend(collection.timezones)
                answer_text = ical.serialize(collection.tag,
                                             collection.headers, items)
                etag = item.etag
            else:
                return client.NOT_FOUND, {}, None
        else:
            # Create the collection if it does not exist
            if not collection.exists:
                if collection in write_collections:
                    log.LOGGER.debug("Creating collection %s" %
                                     collection.name)
                    collection.write()
                else:
                    log.LOGGER.debug(
                        "Collection %s not available and could not be created "
                        "due to missing write rights" % collection.name)
                    return NOT_ALLOWED

            # Get whole collection
            answer_text = collection.text
            etag = collection.etag

        headers = {
            "Content-Type": collection.mimetype,
            "Last-Modified": collection.last_modified,
            "ETag": etag
        }
        answer = answer_text.encode(self.encoding)
        return client.OK, headers, answer
Ejemplo n.º 4
0
    def get(self, environ, collections, content, user):
        """Manage GET request."""
        # Display a "Radicale works!" message if the root URL is requested
        if environ["PATH_INFO"] == "/":
            headers = {"Content-type": "text/html"}
            answer = "<!DOCTYPE html>\n<title>Radicale</title>Radicale works!"
            return client.OK, headers, answer

        collection = collections[0]
        item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection)
        if item_name:
            # Get collection item
            item = collection.get_item(item_name)
            if item:
                items = collection.timezones
                items.append(item)
                answer_text = ical.serialize(collection.tag,
                                             collection.headers, items)
                etag = item.etag
            else:
                return client.GONE, {}, None
        else:
            # Get whole collection
            answer_text = collection.text
            etag = collection.etag

        headers = {
            "Content-Type": collection.mimetype,
            "Last-Modified": collection.last_modified,
            "ETag": etag
        }
        answer = answer_text.encode(self.encoding)
        return client.OK, headers, answer
Ejemplo n.º 5
0
 def move(self, environ, calendars, content, user):
     """Manage MOVE request."""
     from_calendar = calendars[0]
     from_name = xmlutils.name_from_path(
         environ["PATH_INFO"], from_calendar)
     if from_name:
         item = from_calendar.get_item(from_name)
         if item:
             # Move the item
             to_url_parts = urlparse(environ["HTTP_DESTINATION"])
             if to_url_parts.netloc == environ["HTTP_HOST"]:
                 to_path, to_name = posixpath.split(to_url_parts.path)
                 to_calendar = ical.Calendar.from_path(to_path)
                 to_calendar.append(to_name, item.text)
                 from_calendar.remove(from_name)
                 return client.CREATED, {}, None
             else:
                 # Remote destination server, not supported
                 return client.BAD_GATEWAY, {}, None
         else:
             # No item found
             return client.GONE, {}, None
     else:
         # Moving calendars, not supported
         return client.FORBIDDEN, {}, None
Ejemplo n.º 6
0
 def move(self, environ, collections, content, user):
     """Manage MOVE request."""
     from_collection = collections[0]
     from_name = xmlutils.name_from_path(environ["PATH_INFO"],
                                         from_collection)
     if from_name:
         item = from_collection.get_item(from_name)
         if item:
             # Move the item
             to_url_parts = urlparse(environ["HTTP_DESTINATION"])
             if to_url_parts.netloc == environ["HTTP_HOST"]:
                 to_url = to_url_parts.path
                 to_path, to_name = to_url.rstrip("/").rsplit("/", 1)
                 to_collection = ical.Collection.from_path(to_path,
                                                           depth="0")[0]
                 to_collection.append(to_name, item.text)
                 from_collection.remove(from_name)
                 return client.CREATED, {}, None
             else:
                 # Remote destination server, not supported
                 return client.BAD_GATEWAY, {}, None
         else:
             # No item found
             return client.GONE, {}, None
     else:
         # Moving collections, not supported
         return client.FORBIDDEN, {}, None
Ejemplo n.º 7
0
    def put(self, environ, read_collections, write_collections, content, user):
        """Manage PUT request."""
        if not len(write_collections):
            return NOT_ALLOWED

        collection = write_collections[0]

        collection.set_mimetype(environ.get("CONTENT_TYPE"))
        headers = {}
        item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection)
        item = collection.get_item(item_name)

        # Evolution bug workaround
        etag = environ.get("HTTP_IF_MATCH", "").replace("\\", "")
        match = environ.get("HTTP_IF_NONE_MATCH", "") == "*"
        if (not item and not etag) or (
                item and ((etag or item.etag) == item.etag) and not match):
            # PUT allowed in 3 cases
            # Case 1: No item and no ETag precondition: Add new item
            # Case 2: Item and ETag precondition verified: Modify item
            # Case 3: Item and no Etag precondition: Force modifying item
            xmlutils.put(environ["PATH_INFO"], content, collection)
            status = client.CREATED
            # Try to return the etag in the header.
            # If the added item doesn't have the same name as the one given
            # by the client, then there's no obvious way to generate an
            # etag, we can safely ignore it.
            new_item = collection.get_item(item_name)
            if new_item:
                headers["ETag"] = new_item.etag
        else:
            # PUT rejected in all other cases
            status = client.PRECONDITION_FAILED
        return status, headers, None
Ejemplo n.º 8
0
    def get(self, environ, calendars, content, user):
        """Manage GET request."""
        # Display a "Radicale works!" message if the root URL is requested
        if environ["PATH_INFO"] == "/":
            headers = {"Content-type": "text/html"}
            answer = "<!DOCTYPE html>\n<title>Radicale</title>Radicale works!"
            return client.OK, headers, answer

        calendar = calendars[0]
        item_name = xmlutils.name_from_path(environ["PATH_INFO"], calendar)
        if item_name:
            # Get calendar item
            item = calendar.get_item(item_name)
            if item:
                items = calendar.timezones
                items.append(item)
                answer_text = ical.serialize(
                    headers=calendar.headers, items=items)
                etag = item.etag
            else:
                return client.GONE, {}, None
        else:
            # Get whole calendar
            answer_text = calendar.text
            etag = calendar.etag

        headers = {
            "Content-Type": "text/calendar",
            "Last-Modified": calendar.last_modified,
            "ETag": etag}
        answer = answer_text.encode(self.encoding)
        return client.OK, headers, answer
Ejemplo n.º 9
0
    def do_DELETE(self, content, user):
        """Manage DELETE request."""
        _logger.info('do_delete %s %s' % (content, user))
        if not len(write_collections):
            return NOT_ALLOWED

        collection = write_collections[0]

        if collection.path == environ["PATH_INFO"].strip("/"):
            # Path matching the collection, the collection must be deleted
            item = collection
        else:
            # Try to get an item matching the path
            name = xmlutils.name_from_path(environ["PATH_INFO"], collection)
            item = collection.items.get(name)

        if item:
            # Evolution bug workaround
            if_match = environ.get("HTTP_IF_MATCH", "*").replace("\\", "")
            if if_match in ("*", item.etag):
                # No ETag precondition or precondition verified, delete item
                answer = xmlutils.delete(environ["PATH_INFO"], collection)
                return client.OK, {}, answer
            else:
                # ETag precondition not verified, do not delete item
                return client.PRECONDITION_FAILED, {}, None

        # No item
        return client.NOT_FOUND, {}, None
Ejemplo n.º 10
0
    def get(self, environ, read_collections, write_collections, content, user):
        """Manage GET request.

        In Radicale, GET requests create collections when the URL is not
        available. This is useful for clients with no MKCOL or MKCALENDAR
        support.

        """
        # Display a "Radicale works!" message if the root URL is requested
        if environ["PATH_INFO"] == "/":
            headers = {"Content-type": "text/html"}
            answer = b"<!DOCTYPE html>\n<title>Radicale</title>Radicale works!"
            return client.OK, headers, answer

        if not len(read_collections):
            return NOT_ALLOWED

        collection = read_collections[0]

        item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection)

        if item_name:
            # Get collection item
            item = collection.get_item(item_name)
            if item:
                items = collection.timezones
                items.append(item)
                answer_text = ical.serialize(
                    collection.tag, collection.headers, items)
                etag = item.etag
            else:
                return client.GONE, {}, None
        else:
            # Create the collection if it does not exist
            if not collection.exists:
                if collection in write_collections:
                    log.LOGGER.debug(
                        "Creating collection %s" % collection.name)
                    collection.write()
                else:
                    log.LOGGER.debug(
                        "Collection %s not available and could not be created "
                        "due to missing write rights" % collection.name)
                    return NOT_ALLOWED

            # Get whole collection
            answer_text = collection.text
            etag = collection.etag

        headers = {
            "Content-Type": collection.mimetype,
            "Last-Modified": collection.last_modified,
            "ETag": etag}
        answer = answer_text.encode(self.encoding)
        return client.OK, headers, answer
Ejemplo n.º 11
0
 def delete(self, environ, calendars, content, user):
     """Manage DELETE request."""
     calendar = calendars[0]
     item = calendar.get_item(
         xmlutils.name_from_path(environ["PATH_INFO"], calendar))
     if item and environ.get("HTTP_IF_MATCH", item.etag) == item.etag:
         # No ETag precondition or precondition verified, delete item
         answer = xmlutils.delete(environ["PATH_INFO"], calendar)
         status = client.NO_CONTENT
     else:
         # No item or ETag precondition not verified, do not delete item
         answer = None
         status = client.PRECONDITION_FAILED
     return status, {}, answer
Ejemplo n.º 12
0
 def put(self, environ, calendars, content, user):
     """Manage PUT request."""
     calendar = calendars[0]
     headers = {}
     item_name = xmlutils.name_from_path(environ["PATH_INFO"], calendar)
     item = calendar.get_item(item_name)
     if (not item and not environ.get("HTTP_IF_MATCH")) or (
         item and environ.get("HTTP_IF_MATCH", item.etag) == item.etag):
         # PUT allowed in 3 cases
         # Case 1: No item and no ETag precondition: Add new item
         # Case 2: Item and ETag precondition verified: Modify item
         # Case 3: Item and no Etag precondition: Force modifying item
         xmlutils.put(environ["PATH_INFO"], content, calendar)
         status = client.CREATED
         headers["ETag"] = calendar.get_item(item_name).etag
     else:
         # PUT rejected in all other cases
         status = client.PRECONDITION_FAILED
     return status, headers, None
Ejemplo n.º 13
0
 def put(self, environ, collections, content, user):
     """Manage PUT request."""
     collection = collections[0]
     collection.set_mimetype(environ.get("CONTENT_TYPE"))
     headers = {}
     item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection)
     item = collection.get_item(item_name)
     if (not item and not environ.get("HTTP_IF_MATCH")) or (
             item and environ.get("HTTP_IF_MATCH", item.etag) == item.etag):
         # PUT allowed in 3 cases
         # Case 1: No item and no ETag precondition: Add new item
         # Case 2: Item and ETag precondition verified: Modify item
         # Case 3: Item and no Etag precondition: Force modifying item
         xmlutils.put(environ["PATH_INFO"], content, collection)
         status = client.CREATED
         headers["ETag"] = collection.get_item(item_name).etag
     else:
         # PUT rejected in all other cases
         status = client.PRECONDITION_FAILED
     return status, headers, None
Ejemplo n.º 14
0
    def delete(self, environ, collections, content, user):
        """Manage DELETE request."""
        collection = collections[0]

        if collection.path == environ["PATH_INFO"].strip("/"):
            # Path matching the collection, the collection must be deleted
            item = collection
        else:
            # Try to get an item matching the path
            item = collection.get_item(
                xmlutils.name_from_path(environ["PATH_INFO"], collection))

        if item and environ.get("HTTP_IF_MATCH", item.etag) == item.etag:
            # No ETag precondition or precondition verified, delete item
            answer = xmlutils.delete(environ["PATH_INFO"], collection)
            status = client.NO_CONTENT
        else:
            # No item or ETag precondition not verified, do not delete item
            answer = None
            status = client.PRECONDITION_FAILED
        return status, {}, answer
Ejemplo n.º 15
0
    def delete(self, environ, collections, content, user):
        """Manage DELETE request."""
        collection = collections[0]

        if collection.path == environ["PATH_INFO"].strip("/"):
            # Path matching the collection, the collection must be deleted
            item = collection
        else:
            # Try to get an item matching the path
            item = collection.get_item(
                xmlutils.name_from_path(environ["PATH_INFO"], collection))

        if item and environ.get("HTTP_IF_MATCH", item.etag) == item.etag:
            # No ETag precondition or precondition verified, delete item
            answer = xmlutils.delete(environ["PATH_INFO"], collection)
            status = client.NO_CONTENT
        else:
            # No item or ETag precondition not verified, do not delete item
            answer = None
            status = client.PRECONDITION_FAILED
        return status, {}, answer
Ejemplo n.º 16
0
    def do_MOVE(self, environ, read_collections, write_collections, content,
                user):
        """Manage MOVE request."""

        _logger.info('do_MOVE %s %s' % (content, user))

        if not len(write_collections):
            return NOT_ALLOWED

        from_collection = write_collections[0]

        from_name = xmlutils.name_from_path(environ["PATH_INFO"],
                                            from_collection)
        if from_name:
            item = from_collection.items.get(from_name)
            if item:
                # Move the item
                to_url_parts = urlparse(environ["HTTP_DESTINATION"])
                if to_url_parts.netloc == environ["HTTP_HOST"]:
                    to_url = to_url_parts.path
                    to_path, to_name = to_url.rstrip("/").rsplit("/", 1)
                    to_collection = ical.Collection.from_path(to_path,
                                                              depth="0")[0]
                    if to_collection in write_collections:
                        to_collection.append(to_name, item.text)
                        from_collection.remove(from_name)
                        return client.CREATED, {}, None
                    else:
                        return NOT_ALLOWED
                else:
                    # Remote destination server, not supported
                    return client.BAD_GATEWAY, {}, None
            else:
                # No item found
                return client.GONE, {}, None
        else:
            # Moving collections, not supported
            return client.FORBIDDEN, {}, None
Ejemplo n.º 17
0
    def do_PUT(self, environ, read_collections, write_collections, content,
               user):
        """Manage PUT request."""
        _logger.info('do_PUT %s %s' % (content, user))

        if not len(write_collections):
            return NOT_ALLOWED

        collection = write_collections[0]

        collection.set_mimetype(environ.get("CONTENT_TYPE"))
        headers = {}
        item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection)
        item = collection.items.get(item_name)

        # Evolution bug workaround
        etag = environ.get("HTTP_IF_MATCH", "").replace("\\", "")
        match = environ.get("HTTP_IF_NONE_MATCH", "") == "*"
        if (not item and not etag) or (item and
                                       ((etag or item.etag) == item.etag)
                                       and not match):
            # PUT allowed in 3 cases
            # Case 1: No item and no ETag precondition: Add new item
            # Case 2: Item and ETag precondition verified: Modify item
            # Case 3: Item and no Etag precondition: Force modifying item
            xmlutils.put(environ["PATH_INFO"], content, collection)
            status = client.CREATED
            # Try to return the etag in the header.
            # If the added item doesn't have the same name as the one given
            # by the client, then there's no obvious way to generate an
            # etag, we can safely ignore it.
            new_item = collection.items.get(item_name)
            if new_item:
                headers["ETag"] = new_item.etag
        else:
            # PUT rejected in all other cases
            status = client.PRECONDITION_FAILED
        return status, headers, None
Ejemplo n.º 18
0
    def put(self, environ, collections, content, user):
        """Manage PUT request."""
        collection = collections[0]
        collection.set_mimetype(environ.get("CONTENT_TYPE"))
        headers = {}
        item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection)
        item = collection.get_item(item_name)

        # Evolution bug workaround
        etag = environ.get("HTTP_IF_MATCH", "").replace("\\", "")
        if (not item and not etag) or (
            item and ((etag or item.etag) == item.etag)):
            # PUT allowed in 3 cases
            # Case 1: No item and no ETag precondition: Add new item
            # Case 2: Item and ETag precondition verified: Modify item
            # Case 3: Item and no Etag precondition: Force modifying item
            xmlutils.put(environ["PATH_INFO"], content, collection)
            status = client.CREATED
            headers["ETag"] = collection.get_item(item_name).etag
        else:
            # PUT rejected in all other cases
            status = client.PRECONDITION_FAILED
        return status, headers, None