Пример #1
0
def create_calendar(client, parent, name, id=None):
    """
    Create a new calendar with display name `name` in `parent`.
    """
    path = None
    if id is None:
        id = str(uuid.uuid1())

    name = dav.DisplayName(name)
    cal = cdav.CalendarCollection()
    coll = dav.Collection() + cal
    type = dav.ResourceType() + coll

    prop = dav.Prop() + [type, name]
    set = dav.Set() + prop

    mkcol = dav.Mkcol() + set

    q = etree.tostring(mkcol.xmlelement(),
                       encoding="utf-8",
                       xml_declaration=True)
    path = url.join(parent.url.path, id)

    r = client.mkcol(path, q)
    if r.status == 201:
        path = url.make(parent.url, path)
    else:
        raise error.MkcolError(r.raw)

    return (id, path)
Пример #2
0
    def _create(self,
                name=None,
                id=None,
                supported_calendar_component_set=None):
        """
        Create a new calendar with display name `name` in `parent`.
        """
        if id is None:
            id = str(uuid.uuid1())
        self.id = id

        path = self.parent.url.join(id)
        self.url = path

        # TODO: mkcalendar seems to ignore the body on most servers?
        # at least the name doesn't get set this way.
        # zimbra gives 500 (!) if body is omitted ...

        prop = dav.Prop()
        if name:
            display_name = dav.DisplayName(name)
            prop += [
                display_name,
            ]
        if supported_calendar_component_set:
            sccs = cdav.SupportedCalendarComponentSet()
            for scc in supported_calendar_component_set:
                sccs += cdav.Comp(scc)
            prop += sccs
        set = dav.Set() + prop

        mkcol = cdav.Mkcalendar() + set

        r = self._query(root=mkcol,
                        query_method='mkcalendar',
                        url=path,
                        expected_return_value=201)

        # COMPATIBILITY ISSUE
        # name should already be set, but we've seen caldav servers failing
        # on setting the DisplayName on calendar creation
        # (DAViCal, Zimbra, ...).  Doing an attempt on explicitly setting the
        # display name using PROPPATCH.
        if name:
            try:
                self.set_properties([display_name])
            except:
                try:
                    current_display_name = self.get_properties([display_name])
                    if current_display_name != name:
                        logging.warning(
                            "caldav server not complient with RFC4791. unable to set display name on calendar.  Wanted name: \"%s\" - gotten name: \"%s\".  Ignoring."
                            % (name, current_display_name))
                except:
                    logging.warning(
                        "calendar server does not support display name on calendar?  Ignoring",
                        exc_info=True)
Пример #3
0
def set_properties(client, object, props=[]):
    prop = dav.Prop() + props
    set = dav.Set() + prop
    root = dav.PropertyUpdate() + set

    q = etree.tostring(root.xmlelement(),
                       encoding="utf-8",
                       xml_declaration=True)
    r = client.proppatch(object.url.path, q)

    statuses = r.tree.findall(".//" + dav.Status.tag)
    for s in statuses:
        if not s.text.endswith("200 OK"):
            raise error.PropsetError(r.raw)
Пример #4
0
    def set_properties(self, props=[]):
        """
        Set properties (PROPPATCH) for this object.

         * props = [dav.DisplayName('name'), ...]

        Returns:
         * self
        """
        prop = dav.Prop() + props
        set = dav.Set() + prop
        root = dav.PropertyUpdate() + set

        r = self._query(root, query_method='proppatch')

        statuses = r.tree.findall(".//" + dav.Status.tag)
        for s in statuses:
            if ' 200 ' not in s.text:
                raise error.PropsetError(errmsg(r))

        return self
Пример #5
0
    def set_properties(self, props=[]):
        """
        Set properties (PROPPATCH) for this object.

        Parameters:
         * props = [dav.DisplayName('name'), ...]

        Returns:
         * self
        """
        prop = dav.Prop() + props
        set = dav.Set() + prop
        root = dav.PropertyUpdate() + set

        q = etree.tostring(root.xmlelement(), encoding="utf-8",
                           xml_declaration=True)
        r = self.client.proppatch(self.url, q)

        statuses = r.tree.findall(".//" + dav.Status.tag)
        for s in statuses:
            if not s.text.endswith("200 OK"):
                raise error.PropsetError(r.raw)

        return self
Пример #6
0
    def _create(self, name, id=None, supported_calendar_component_set=None):
        """
        Create a new calendar with display name `name` in `parent`.
        """
        if id is None:
            id = str(uuid.uuid1())
        self.id = id

        path = self.parent.url.join(id)
        self.url = path

        # TODO: mkcalendar seems to ignore the body on most servers?
        # at least the name doesn't get set this way.
        # zimbra gives 500 (!) if body is omitted ...

        # ehm ... this element seems non-existent in the RFC?
        # Breaks with baikal, too ...
        # cal = cdav.CalendarCollection()
        # coll = dav.Collection() # + cal # also breaks on baikal,
        #                                # and probably not needed?
        # type = dav.ResourceType() ## probably not needed?

        prop = dav.Prop()  # + [type,]
        if name:
            display_name = dav.DisplayName(name)
            prop += [display_name, ]
        if supported_calendar_component_set:
            sccs = cdav.SupportedCalendarComponentSet()
            for scc in supported_calendar_component_set:
                sccs += cdav.Comp(scc)
            prop += sccs
        set = dav.Set() + prop

        mkcol = cdav.Mkcalendar() + set

        r = self._query(root=mkcol, query_method='mkcalendar', url=path,
                        expected_return_value=201)

        # COMPATIBILITY ISSUE
        # name should already be set, but we've seen caldav servers failing
        # on setting the DisplayName on calendar creation
        # (DAViCal, Zimbra, ...).  Better to be explicit.
        if name:
            try:
                self.set_properties([display_name])
            except:
                self.delete()
                raise

        # Special hack for Zimbra!  The calendar we've made exists at
        # the specified URL, and we can do operations like ls, even
        # PUT an event to the calendar.  Zimbra will enforce that the
        # event uuid matches the event url, and return either 201 or
        # 302 - but alas, try to do a GET towards the event and we
        # get 404!  But turn around and replace the calendar ID with
        # the calendar name in the URL and hey ... it works!

        # TODO: write test cases for calendars with non-trivial
        # names and calendars with names already matching existing
        # calendar urls and ensure they pass.
        zimbra_url = self.parent.url.join(name)
        try:
            ret = self.client.request(zimbra_url)
            if ret.status == 404:
                raise error.NotFoundError
            # special hack for radicale.
            # It will happily accept any calendar-URL without returning 404.
            ret = self.client.request(self.parent.url.join(
                'ANYTHINGGOESHEREthisshouldforsurereturn404'))
            if ret.status == 404:
                # insane server
                self.url = zimbra_url
        except error.NotFoundError:
            # sane server
            pass
Пример #7
0
    def _create(self, name, id=None, supported_calendar_component_set=None):
        """
        Create a new calendar with display name `name` in `parent`.
        """
        if id is None:
            id = str(uuid.uuid1())
        self.id = id

        path = self.parent.url.join(id)
        self.url = path

        ## TODO: mkcalendar seems to ignore the body on most servers?
        ## at least the name doesn't get set this way.
        ## zimbra gives 500 (!) if body is omitted ...

        cal = cdav.CalendarCollection()
        coll = dav.Collection() + cal
        type = dav.ResourceType() + coll

        prop = dav.Prop() + [
            type,
        ]
        if name:
            display_name = dav.DisplayName(name)
            prop += [
                display_name,
            ]
        if supported_calendar_component_set:
            sccs = cdav.SupportedCalendarComponentSet()
            for scc in supported_calendar_component_set:
                sccs += cdav.Comp(scc)
            prop += sccs
        set = dav.Set() + prop

        mkcol = cdav.Mkcalendar() + set

        r = self._query(root=mkcol,
                        query_method='mkcalendar',
                        url=path,
                        expected_return_value=201)

        if name:
            try:
                self.set_properties([display_name])
            except:
                self.delete()
                raise

        ## Special hack for Zimbra!  The calendar we've made exists at
        ## the specified URL, and we can do operations like ls, even
        ## PUT an event to the calendar.  Zimbra will enforce that the
        ## event uuid matches the event url, and return either 201 or
        ## 302 - but alas, try to do a GET towards the event and we
        ## get 404!  But turn around and replace the calendar ID with
        ## the calendar name in the URL and hey ... it works!

        ## TODO: write test cases for calendars with non-trivial
        ## names and calendars with names already matching existing
        ## calendar urls and ensure they pass.
        zimbra_url = self.parent.url.join(name)
        try:
            ret = self.client.request(zimbra_url)
            if ret.status == 404:
                raise error.NotFoundError
            ## insane server
            self.url = zimbra_url
        except error.NotFoundError:
            ## sane server
            pass
Пример #8
0
    def _create(self, name, id=None):
        """
        Create a new calendar with display name `name` in `parent`.
        """
        if id is None:
            id = str(uuid.uuid1())
        self.id = id
            
        path = self.parent.url.join(id)
        self.url = path

        ## TODO: mkcalendar seems to ignore the body on most servers?  
        ## at least the name doesn't get set this way.
        ## zimbra gives 500 (!) if body is omitted ...

        if name:
            display_name = dav.DisplayName(name)
        cal = cdav.CalendarCollection()
        coll = dav.Collection() + cal
        type = dav.ResourceType() + coll

        prop = dav.Prop() + [type,]
        if name:
            prop += [display_name,]
        set = dav.Set() + prop

        mkcol = cdav.Mkcalendar() + set

        q = etree.tostring(mkcol.xmlelement(), encoding="utf-8",
                           xml_declaration=True)

        r = self.client.mkcalendar(path, q)

        if r.status != 201:
            raise error.MkcalendarError(r.raw)

        if name:
            try:
                self.set_properties([display_name])
            except:
                self.delete()
                raise

        ## Special hack for Zimbra!  The calendar we've made exists at
        ## the specified URL, and we can do operations like ls, even
        ## PUT an event to the calendar.  Zimbra will enforce that the
        ## event uuid matches the event url, and return either 201 or
        ## 302 - but alas, try to do a GET towards the event and we
        ## get 404!  But turn around and replace the calendar ID with
        ## the calendar name in the URL and hey ... it works!  

        ## TODO: write test cases for calendars with non-trivial
        ## names and calendars with names already matching existing
        ## calendar urls and ensure they pass.
        zimbra_url = self.parent.url.join(name)
        try:
            ret = self.client.request(zimbra_url)
            if ret.status == 404:
                raise error.NotFoundError
            ## insane server
            self.url = zimbra_url
        except error.NotFoundError:
            ## sane server
            pass