예제 #1
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
예제 #2
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
예제 #3
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
예제 #4
0
 def text(self):
     components = (
         ical.Timezone, ical.Event, ical.Todo, ical.Journal, ical.Card)
     items = set()
     for item in DBItem.objects.filter(collection__path=self.path):
         items.update(self._parse(item.text, components))
     return ical.serialize(
         self.tag, self.headers, sorted(items, key=lambda x: x.name))
예제 #5
0
 def append(self, name, text):
     new_items = self._parse(text, ICAL_TYPES, name)
     for new_item in new_items.values():
         collection, ccreated = DBCollection.objects.get_or_create(
             path=self.path, parent_path=os.path.dirname(self.path))
         item, icreated = DBItem.objects.get_or_create(
             collection=collection, name=name)
         item.text = ical.serialize(
             self.tag, self.headers, [new_item] + self.timezones)
         item.save()
예제 #6
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
예제 #7
0
 def write(self, headers=None, items=None):
     headers = headers or self.headers
     items = items if items is not None else self.items
     timezones = list(set(i for i in items if isinstance(i, ical.Timezone)))
     components = [i for i in items if isinstance(i, ical.Component)]
     for component in components:
         text = ical.serialize(self.tag, headers, [component] + timezones)
         collection, created = DBCollection.objects.get_or_create(
             path=self.path,
             parent_path='/'.join(self.path.split('/')[:-1]))
         item, created = DBItem.objects.get_or_create(
             collection=collection, name=component.name)
         item.text = text
         item.save()
예제 #8
0
    def test_serialization(self):
        name = '20160729T101032Z-9313-1000-4291-10_localhost-20160729T101116Z.ics'

        for input_text, stored_text in self.DATA_CASES:
            items = ical.Collection._parse(input_text, ICAL_TYPES, name)
            self.assertEqual(name in items, True)

            timezones = list(filter(
                lambda x: x.tag == ical.Timezone.tag, items.values()))
            serialized_text = ical.serialize(
                self.TAG, self.HEADERS, [items[name]] + timezones)
            self.assertEqual(serialized_text, stored_text)

            items2 = ical.Collection._parse(serialized_text, ICAL_TYPES, name)
            self.assertEqual(name in items2, True)
예제 #9
0
    def test_serialization(self):
        name = '20160729T101032Z-9313-1000-4291-10_localhost-20160729T101116Z.ics'

        for input_text, stored_text in self.DATA_CASES:
            items = ical.Collection._parse(input_text, ICAL_TYPES, name)
            self.assertEqual(name in items, True)

            timezones = list(
                filter(lambda x: x.tag == ical.Timezone.tag, items.values()))
            serialized_text = ical.serialize(self.TAG, self.HEADERS,
                                             [items[name]] + timezones)
            self.assertEqual(serialized_text, stored_text)

            items2 = ical.Collection._parse(serialized_text, ICAL_TYPES, name)
            self.assertEqual(name in items2, True)
예제 #10
0
    def append(self, name, text):
        new_items = self._parse(text, ICAL_TYPES, name)
        timezones = list(
            filter(lambda x: x.tag == ical.Timezone.tag, new_items.values()))

        for new_item in new_items.values():
            if new_item.tag == ical.Timezone.tag:
                continue

            collection, ccreated = DBCollection.objects.get_or_create(
                path=self.path, parent_path=os.path.dirname(self.path))
            item, icreated = DBItem.objects.get_or_create(
                collection=collection, name=name)

            item.text = ical.serialize(self.tag, self.headers,
                                       [new_item] + timezones)
            item.save()
예제 #11
0
파일: main.py 프로젝트: mediafactory/yats
    def append(self, name, text):
        new_items = self._parse(text, ICAL_TYPES, name)
        timezones = list(filter(
            lambda x: x.tag == ical.Timezone.tag, new_items.values()))

        for new_item in new_items.values():
            if new_item.tag == ical.Timezone.tag:
                continue

            collection, ccreated = DBCollection.objects.get_or_create(
                path=self.path, parent_path=os.path.dirname(self.path))
            item, icreated = DBItem.objects.get_or_create(
                collection=collection, name=name)

            item.text = ical.serialize(
                self.tag, self.headers, [new_item] + timezones)
            item.save()
예제 #12
0
파일: xmlutils.py 프로젝트: oswjk/Radicale
def report(path, xml_request, collection):
    """Read and answer REPORT requests.

    Read rfc3253-3.6 for info.

    """
    # Reading request
    root = ET.fromstring(xml_request.encode("utf8"))

    prop_element = root.find(_tag("D", "prop"))
    props = [prop.tag for prop in prop_element]

    if collection:
        if root.tag in (_tag("C", "calendar-multiget"), _tag("CR", "addressbook-multiget")):
            # Read rfc4791-7.9 for info
            hreferences = set(href_element.text for href_element in root.findall(_tag("D", "href")))
        else:
            hreferences = (path,)
    else:
        hreferences = ()

    # Writing answer
    multistatus = ET.Element(_tag("D", "multistatus"))

    collection_tag = collection.tag
    collection_items = collection.items
    collection_headers = collection.headers
    collection_timezones = collection.timezones

    for hreference in hreferences:
        # Check if the reference is an item or a collection
        name = name_from_path(hreference, collection)
        if name:
            # Reference is an item
            path = "/".join(hreference.split("/")[:-1]) + "/"
            items = (item for item in collection_items if item.name == name)
        else:
            # Reference is a collection
            path = hreference
            items = collection.components

        for item in items:
            response = ET.Element(_tag("D", "response"))
            multistatus.append(response)

            href = ET.Element(_tag("D", "href"))
            href.text = "%s/%s" % (path.rstrip("/"), item.name)
            response.append(href)

            propstat = ET.Element(_tag("D", "propstat"))
            response.append(propstat)

            prop = ET.Element(_tag("D", "prop"))
            propstat.append(prop)

            for tag in props:
                element = ET.Element(tag)
                if tag == _tag("D", "getetag"):
                    element.text = item.etag
                elif tag in (_tag("C", "calendar-data"), _tag("CR", "address-data")):
                    if isinstance(item, ical.Component):
                        element.text = ical.serialize(collection_tag, collection_headers, collection_timezones + [item])
                prop.append(element)

            status = ET.Element(_tag("D", "status"))
            status.text = _response(200)
            propstat.append(status)

    return _pretty_xml(multistatus)
예제 #13
0
파일: xmlutils.py 프로젝트: oswjk/Radicale
def _propfind_response(path, item, props, user):
    """Build and return a PROPFIND response."""
    is_collection = isinstance(item, ical.Collection)
    if is_collection:
        with item.props as properties:
            collection_props = properties

    response = ET.Element(_tag("D", "response"))

    href = ET.Element(_tag("D", "href"))
    uri = item.url if is_collection else "%s/%s" % (path, item.name)
    href.text = uri.replace("//", "/")
    response.append(href)

    propstat404 = ET.Element(_tag("D", "propstat"))
    propstat200 = ET.Element(_tag("D", "propstat"))
    response.append(propstat200)

    prop200 = ET.Element(_tag("D", "prop"))
    propstat200.append(prop200)

    prop404 = ET.Element(_tag("D", "prop"))
    propstat404.append(prop404)

    for tag in props:
        element = ET.Element(tag)
        is404 = False
        if tag == _tag("D", "getetag"):
            element.text = item.etag
        elif tag == _tag("D", "principal-URL"):
            tag = ET.Element(_tag("D", "href"))
            tag.text = path
            element.append(tag)
        elif tag in (
            _tag("D", "principal-collection-set"),
            _tag("C", "calendar-user-address-set"),
            _tag("CR", "addressbook-home-set"),
            _tag("C", "calendar-home-set"),
        ):
            tag = ET.Element(_tag("D", "href"))
            tag.text = path
            element.append(tag)
        elif tag == _tag("C", "supported-calendar-component-set"):
            # This is not a Todo
            # pylint: disable=W0511
            for component in ("VTODO", "VEVENT", "VJOURNAL"):
                comp = ET.Element(_tag("C", "comp"))
                comp.set("name", component)
                element.append(comp)
            # pylint: enable=W0511
        elif tag == _tag("D", "current-user-principal") and user:
            tag = ET.Element(_tag("D", "href"))
            tag.text = "/%s/" % user
            element.append(tag)
        elif tag == _tag("D", "current-user-privilege-set"):
            privilege = ET.Element(_tag("D", "privilege"))
            privilege.append(ET.Element(_tag("D", "all")))
            privilege.append(ET.Element(_tag("D", "read")))
            privilege.append(ET.Element(_tag("D", "write")))
            privilege.append(ET.Element(_tag("D", "write-properties")))
            privilege.append(ET.Element(_tag("D", "write-content")))
            element.append(privilege)
        elif tag == _tag("D", "supported-report-set"):
            for report_name in (
                "principal-property-search",
                "sync-collection" "expand-property",
                "principal-search-property-set",
            ):
                supported = ET.Element(_tag("D", "supported-report"))
                report_tag = ET.Element(_tag("D", "report"))
                report_tag.text = report_name
                supported.append(report_tag)
                element.append(supported)
        elif is_collection:
            if tag == _tag("D", "getcontenttype"):
                element.text = item.mimetype
            elif tag == _tag("D", "resourcetype"):
                if item.is_principal:
                    tag = ET.Element(_tag("D", "principal"))
                    element.append(tag)
                if item.is_leaf(item.path):
                    tag = ET.Element(_tag("C", item.resource_type))
                    element.append(tag)
                if not item.exists and item.resource_type:
                    # Collection not stored yet, but guessed resource type
                    tag = ET.Element(_tag("C", item.resource_type))
                    element.append(tag)
                tag = ET.Element(_tag("D", "collection"))
                element.append(tag)
            elif tag == _tag("D", "owner") and item.owner_url:
                element.text = item.owner_url
            elif tag == _tag("CS", "getctag"):
                element.text = item.etag
            elif tag == _tag("C", "calendar-timezone"):
                element.text = ical.serialize(item.tag, item.headers, item.timezones)
            else:
                human_tag = _tag_from_clark(tag)
                if human_tag in collection_props:
                    element.text = collection_props[human_tag]
                else:
                    is404 = True
        # Not for collections
        elif tag == _tag("D", "getcontenttype"):
            element.text = "%s; component=%s" % (item.mimetype, item.tag.lower())
        elif tag == _tag("D", "resourcetype"):
            # resourcetype must be returned empty for non-collection elements
            pass
        else:
            is404 = True

        if is404:
            prop404.append(element)
        else:
            prop200.append(element)

    status200 = ET.Element(_tag("D", "status"))
    status200.text = _response(200)
    propstat200.append(status200)

    status404 = ET.Element(_tag("D", "status"))
    status404.text = _response(404)
    propstat404.append(status404)
    if len(prop404):
        response.append(propstat404)

    return response
예제 #14
0
파일: main.py 프로젝트: mediafactory/yats
 def text(self):
     return ical.serialize(self.tag, self.headers, self.items.values())
예제 #15
0
 def text(self):
     return ical.serialize(self.tag, self.headers, self.components)
예제 #16
0
파일: xmlutils.py 프로젝트: 9h37/Radicale
def _propfind_response(path, item, props, user):
    """Build and return a PROPFIND response."""
    is_collection = isinstance(item, ical.Collection)
    if is_collection:
        with item.props as properties:
            collection_props = properties

    response = ET.Element(_tag("D", "response"))

    href = ET.Element(_tag("D", "href"))
    uri = item.url if is_collection else "%s/%s" % (path, item.name)
    href.text = uri.replace("//", "/")
    response.append(href)

    propstat404 = ET.Element(_tag("D", "propstat"))
    propstat200 = ET.Element(_tag("D", "propstat"))
    response.append(propstat200)

    prop200 = ET.Element(_tag("D", "prop"))
    propstat200.append(prop200)

    prop404 = ET.Element(_tag("D", "prop"))
    propstat404.append(prop404)

    for tag in props:
        element = ET.Element(tag)
        is404 = False
        if tag == _tag("D", "getetag"):
            element.text = item.etag
        elif tag == _tag("D", "principal-URL"):
            tag = ET.Element(_tag("D", "href"))
            tag.text = path
            element.append(tag)
        elif tag in (_tag("D", "principal-collection-set"),
                     _tag("C", "calendar-user-address-set"),
                     _tag("CR", "addressbook-home-set"),
                     _tag("C", "calendar-home-set")):
            tag = ET.Element(_tag("D", "href"))
            tag.text = path
            element.append(tag)
        elif tag == _tag("C", "supported-calendar-component-set"):
            # This is not a Todo
            # pylint: disable=W0511
            for component in ("VTODO", "VEVENT", "VJOURNAL"):
                comp = ET.Element(_tag("C", "comp"))
                comp.set("name", component)
                element.append(comp)
            # pylint: enable=W0511
        elif tag == _tag("D", "current-user-principal") and user:
            tag = ET.Element(_tag("D", "href"))
            tag.text = '/%s/' % user
            element.append(tag)
        elif tag == _tag("D", "current-user-privilege-set"):
            privilege = ET.Element(_tag("D", "privilege"))
            privilege.append(ET.Element(_tag("D", "all")))
            element.append(privilege)
        elif tag == _tag("D", "supported-report-set"):
            for report_name in ("principal-property-search", "sync-collection"
                                "expand-property",
                                "principal-search-property-set"):
                supported = ET.Element(_tag("D", "supported-report"))
                report_tag = ET.Element(_tag("D", "report"))
                report_tag.text = report_name
                supported.append(report_tag)
                element.append(supported)
        elif is_collection:
            if tag == _tag("D", "getcontenttype"):
                element.text = item.mimetype
            elif tag == _tag("D", "resourcetype"):
                if item.is_principal:
                    tag = ET.Element(_tag("D", "principal"))
                    element.append(tag)
                else:
                    tag = ET.Element(_tag("C", item.resource_type))
                    element.append(tag)
                tag = ET.Element(_tag("D", "collection"))
                element.append(tag)
            elif tag == _tag("D", "owner") and item.owner_url:
                element.text = item.owner_url
            elif tag == _tag("CS", "getctag"):
                element.text = item.etag
            elif tag == _tag("C", "calendar-timezone"):
                element.text = ical.serialize(item.tag, item.headers,
                                              item.timezones)
            else:
                human_tag = _tag_from_clark(tag)
                if human_tag in collection_props:
                    element.text = collection_props[human_tag]
                else:
                    is404 = True
        # Not for collections
        elif tag == _tag("D", "getcontenttype"):
            element.text = "%s; component=%s" % (item.mimetype,
                                                 item.tag.lower())
        elif tag == _tag("D", "resourcetype"):
            # resourcetype must be returned empty for non-collection elements
            pass
        else:
            is404 = True

        if is404:
            prop404.append(element)
        else:
            prop200.append(element)

    status200 = ET.Element(_tag("D", "status"))
    status200.text = _response(200)
    propstat200.append(status200)

    status404 = ET.Element(_tag("D", "status"))
    status404.text = _response(404)
    propstat404.append(status404)
    if len(prop404):
        response.append(propstat404)

    return response
예제 #17
0
 def text(self):
     return ical.serialize(self.tag, self.headers, self.items.values())
예제 #18
0
    def append(self, name, text):
        import pydevd
        pydevd.settrace('192.168.33.1', 5678)

        new_items = self._parse(text, ICAL_TYPES, name)
        timezones = list(filter(
            lambda x: x.tag == ical.Timezone.tag, new_items.values()))

        request = self._getRequestFromUrl(self.path)

        for new_item in new_items.values():
            if new_item.tag == ical.Timezone.tag:
                continue

            if new_item.name not in self.items:
                self.items[new_item.name] = new_item

            text = ical.serialize(self.tag, self.headers, [new_item] + timezones)
            cal = vobject.readOne(text)

            # close ticket
            if hasattr(cal.vtodo, 'status') and cal.vtodo.status.value == 'COMPLETED':
                ticket = get_ticket_model()
                try:
                    flow_end = get_flow_end()
                    resolution = get_default_resolution()
                    close_comment = _('closed via CalDAV')

                    tic = ticket.objects.get(uuid=cal.vtodo.uid.value)
                    tic.resolution = resolution
                    tic.closed = True
                    tic.close_date = timezone.now()
                    tic.state = flow_end
                    tic.save(user=request.user)

                    com = tickets_comments()
                    com.comment = _('ticket closed - resolution: %(resolution)s\n\n%(comment)s') % {'resolution': resolution.name, 'comment': close_comment}
                    com.ticket = tic
                    com.action = 1
                    com.save(user=request.user)

                    check_references(request, com)

                    touch_ticket(request.user, tic.id)

                    add_history(request, tic, 1, close_comment)

                    mail_comment(request, com.pk)
                    jabber_comment(request, com.pk)

                except Exception:
                    pass

            # change or new
            else:
                params = {
                    'caption': cal.vtodo.summary.value,
                    'description': cal.vtodo.description.value if hasattr(cal.vtodo, 'description') else None,
                    'uuid': cal.vtodo.uid.value,
                    'show_start': cal.vtodo.due.value if hasattr(cal.vtodo, 'due') else None,
                    'priority': convertPrio(cal.vtodo.priority.value) if hasattr(cal.vtodo, 'priority') else None
                }
                fakePOST = QueryDict(mutable=True)
                fakePOST.update(params)

                form = SimpleTickets(fakePOST)
                if form.is_valid():
                    cd = form.cleaned_data
                    ticket = get_ticket_model()

                    # change ticket
                    try:
                        tic = ticket.objects.get(uuid=cal.vtodo.uid.value)
                        tic.caption = cd['caption']
                        tic.description = cd['description']
                        tic.priority = cd['priority']
                        # tic.assigned = cd['assigned']
                        tic.show_start = cd['show_start']
                        tic.save(user=request.user)

                    # new ticket
                    except ticket.DoesNotExist:
                        tic = ticket()
                        tic.caption = cd['caption']
                        tic.description = cd['description']
                        if 'priority' not in cd or not cd['priority']:
                            if hasattr(settings, 'KEEP_IT_SIMPLE_DEFAULT_PRIORITY') and settings.KEEP_IT_SIMPLE_DEFAULT_PRIORITY:
                                tic.priority_id = settings.KEEP_IT_SIMPLE_DEFAULT_PRIORITY
                        else:
                            tic.priority = cd['priority']
                        tic.assigned = request.user
                        if hasattr(settings, 'KEEP_IT_SIMPLE_DEFAULT_CUSTOMER') and settings.KEEP_IT_SIMPLE_DEFAULT_CUSTOMER:
                            if settings.KEEP_IT_SIMPLE_DEFAULT_CUSTOMER == -1:
                                tic.customer = request.organisation
                            else:
                                tic.customer_id = settings.KEEP_IT_SIMPLE_DEFAULT_CUSTOME
                        if hasattr(settings, 'KEEP_IT_SIMPLE_DEFAULT_COMPONENT') and settings.KEEP_IT_SIMPLE_DEFAULT_COMPONENT:
                            tic.component_id = settings.KEEP_IT_SIMPLE_DEFAULT_COMPONENT
                        tic.show_start = cd['show_start']
                        tic.uuid = cal.vtodo.uid.value
                        tic.save(user=request.user)

                    if tic.assigned:
                        touch_ticket(tic.assigned, tic.pk)

                    for ele in form.changed_data:
                        form.initial[ele] = ''
                    remember_changes(request, form, tic)

                    touch_ticket(request.user, tic.pk)

                    mail_ticket(request, tic.pk, form, rcpt=settings.TICKET_NEW_MAIL_RCPT, is_api=True)
                    jabber_ticket(request, tic.pk, form, rcpt=settings.TICKET_NEW_JABBER_RCPT, is_api=True)

                else:
                    raise Exception(form.errors)
예제 #19
0
def report(path, xml_request, calendar):
    """Read and answer REPORT requests.

    Read rfc3253-3.6 for info.

    """
    # Reading request
    root = ET.fromstring(xml_request.encode("utf8"))

    start = end = None
    expand = limit_recurrence_set = False
    prop_element = root.find(_tag("D", "prop"))
    props = []
    for prop in prop_element:
        props.append(prop.tag)
        for child in prop:
            if child.tag == _tag("C", "expand"):
                expand = True
            elif child.tag == _tag("C", "expand"):
                expand = limit_recurrence_set = True

    filter_element = root.find(_tag("C", "filter"))
    if filter_element is not None:
        for c in filter_element:
            for v in c:
                for filter_ in v:
                    if filter_.tag == _tag("C", "time-range"):
                        if 'start' in filter_.keys():
                            start = datetime.strptime(filter_.get('start'),
                                    '%Y%m%dT%H%M%SZ')
                        if 'end' in filter_.keys():
                            end = datetime.strptime(filter_.get('end'),
                                    '%Y%m%dT%H%M%SZ')

    if calendar:
        if root.tag == _tag("C", "calendar-multiget"):
            # Read rfc4791-7.9 for info
            hreferences = set(
                href_element.text for href_element
                in root.findall(_tag("D", "href")))
        else:
            hreferences = (path,)
    else:
        hreferences = ()

    # Writing answer
    multistatus = ET.Element(_tag("D", "multistatus"))

    for hreference in hreferences:
        # Check if the reference is an item or a calendar
        name = name_from_path(hreference, calendar)
        if name:
            # Reference is an item
            path = "/".join(hreference.split("/")[:-1]) + "/"
            items = (item for item in calendar.items if item.name == name)
        else:
            # Reference is a calendar
            path = hreference
            items = calendar.components

        new_items = []
        if expand:
            # Expand events
            for item in items:
                if item.rrule and end:
                    i = -1
                    for dtstart in rrulestr(item.rrule.rrule,
                            dtstart = item.dtstart):
                        if dtstart >= end:
                            break

                        if not start or dtstart > start:
                            i += 1
                            text = item.text
                            if i > 0:
                                text = re.sub(r"RRULE:.*\n",
                                        r"RECURRENCE-ID:%s\n" % \
                                        item.dtstart.strftime("%Y%m%dT%H%M%SZ"),
                                        text)
                                text = re.sub(r"SUMMARY:(.*)\n",
                                        r"SUMMARY:\1 (#%d)\n" % (i+1), text)

                            if not limit_recurrence_set:
                                # Remove rrule line
                                text = re.sub(r"RRULE:.*\n", "", text)

                            # Update start and end dates
                            dtend = dtstart + (item.dtend - item.dtstart)
                            text = re.sub(r"DTSTART:.*\n", "DTSTART:%s\n" % \
                                    dtstart.strftime("%Y%m%dT%H%M%SZ"), text)
                            text = re.sub(r"DTEND:.*\n", "DTEND:%s\n" % \
                                    dtend.strftime("%Y%m%dT%H%M%SZ"), text)
                            new_items.append(ical.Event(text, item.name))

                else:
                    if (not start or start < item.dtstart) and \
                            (not end or end > item.dtstart):
                        new_items.append(item)

        # Order events by start date
        if len(new_items) > 0:
            items = sorted(new_items, key=lambda item: item.dtstart)

        for item in items:
            response = ET.Element(_tag("D", "response"))
            multistatus.append(response)

            href = ET.Element(_tag("D", "href"))
            href.text = "%s/%s" % (path, item.name)
            response.append(href)

            propstat = ET.Element(_tag("D", "propstat"))
            response.append(propstat)

            prop = ET.Element(_tag("D", "prop"))
            propstat.append(prop)

            for tag in props:
                element = ET.Element(tag)
                if tag == _tag("D", "getetag"):
                    element.text = item.etag
                elif tag == _tag("C", "calendar-data"):
                    if isinstance(item, (ical.Event, ical.Todo, ical.Journal)):
                        element.text = ical.serialize(
                            calendar.headers, calendar.timezones + [item])
                prop.append(element)

            status = ET.Element(_tag("D", "status"))
            status.text = _response(200)
            propstat.append(status)

    return _pretty_xml(multistatus)
예제 #20
0
파일: xmlutils.py 프로젝트: 9h37/Radicale
def report(path, xml_request, collection):
    """Read and answer REPORT requests.

    Read rfc3253-3.6 for info.

    """
    # Reading request
    root = ET.fromstring(xml_request.encode("utf8"))

    prop_element = root.find(_tag("D", "prop"))
    props = [prop.tag for prop in prop_element]

    if collection:
        if root.tag in (_tag("C", "calendar-multiget"),
                        _tag("CR", "addressbook-multiget")):
            # Read rfc4791-7.9 for info
            hreferences = set(
                href_element.text
                for href_element in root.findall(_tag("D", "href")))
        else:
            hreferences = (path, )
    else:
        hreferences = ()

    # Writing answer
    multistatus = ET.Element(_tag("D", "multistatus"))

    collection_tag = collection.tag
    collection_items = collection.items
    collection_headers = collection.headers
    collection_timezones = collection.timezones

    for hreference in hreferences:
        # Check if the reference is an item or a collection
        name = name_from_path(hreference, collection)
        if name:
            # Reference is an item
            path = "/".join(hreference.split("/")[:-1]) + "/"
            items = (item for item in collection_items if item.name == name)
        else:
            # Reference is a collection
            path = hreference
            items = collection.components

        for item in items:
            response = ET.Element(_tag("D", "response"))
            multistatus.append(response)

            href = ET.Element(_tag("D", "href"))
            href.text = "%s/%s" % (path.rstrip("/"), item.name)
            response.append(href)

            propstat = ET.Element(_tag("D", "propstat"))
            response.append(propstat)

            prop = ET.Element(_tag("D", "prop"))
            propstat.append(prop)

            for tag in props:
                element = ET.Element(tag)
                if tag == _tag("D", "getetag"):
                    element.text = item.etag
                elif tag in (_tag("C",
                                  "calendar-data"), _tag("CR",
                                                         "address-data")):
                    if isinstance(item, ical.Component):
                        element.text = ical.serialize(
                            collection_tag, collection_headers,
                            collection_timezones + [item])
                prop.append(element)

            status = ET.Element(_tag("D", "status"))
            status.text = _response(200)
            propstat.append(status)

    return _pretty_xml(multistatus)
예제 #21
0
 def text(self):
     """
     Docs:
       Collection as plain text.
     """
     return ical.serialize(self.tag, self.headers, self.items.values())