Ejemplo n.º 1
0
 def _query(self,
            root=None,
            depth=0,
            query_method='propfind',
            url=None,
            expected_return_value=None):
     """
     This is an internal method for doing a query.  It's a
     result of code-refactoring work, attempting to consolidate
     similar-looking code into a common method.
     """
     if url is None:
         url = self.url
     body = ""
     if root:
         body = etree.tostring(root.xmlelement(),
                               encoding="utf-8",
                               xml_declaration=True)
     ret = getattr(self.client, query_method)(url, body, depth)
     if ret.status == 404:
         raise error.NotFoundError(ret.raw)
     if ((expected_return_value is not None
          and ret.status != expected_return_value) or ret.status >= 400):
         raise error.exception_by_method[query_method](ret.raw)
     return ret
Ejemplo n.º 2
0
def uid_search(client, calendar, uid):
    """
    Perform a uid search in the `calendar`.
    """
    data = cdav.CalendarData()
    prop = dav.Prop() + data

    match = cdav.TextMatch(uid)
    propf = cdav.PropFilter("UID") + match
    vevent = cdav.CompFilter("VEVENT") + propf
    vcal = cdav.CompFilter("VCALENDAR") + vevent
    filter = cdav.Filter() + vcal

    root = cdav.CalendarQuery() + [prop, filter]

    q = etree.tostring(root.xmlelement(),
                       encoding="utf-8",
                       xml_declaration=True)
    response = client.report(calendar.url.path, q, 1)
    r = response.tree.find(".//" + dav.Response.tag)
    if r is not None:
        href = r.find(".//" + dav.Href.tag).text
        data = r.find(".//" + cdav.CalendarData.tag).text
        info = (url.make(calendar.url, href), data)
    else:
        raise error.NotFoundError(response.raw)

    return info
Ejemplo n.º 3
0
    def object_by_uid(self, uid, comp_filter=None):
        """
        Get one event from the calendar.

        Parameters:
         * uid: the event uid

        Returns:
         * Event() or None
        """
        data = cdav.CalendarData()
        prop = dav.Prop() + data

        query = cdav.TextMatch(uid)
        query = cdav.PropFilter("UID") + query
        if comp_filter:
            query = comp_filter + query
        vcalendar = cdav.CompFilter("VCALENDAR") + query
        filter = cdav.Filter() + vcalendar

        root = cdav.CalendarQuery() + [prop, filter]

        response = self._query(root, 1, 'report')

        if response.status == 404:
            raise error.NotFoundError("%s not found on server" % uid)
        elif response.status == 400:
            raise error.ReportError(errmsg(response))

        items_found = response.tree.findall(".//" + dav.Response.tag)
        for r in items_found:
            href = unquote(r.find(".//" + dav.Href.tag).text)
            data = unquote(r.find(".//" + cdav.CalendarData.tag).text)
            # Ref Lucas Verney, we've actually done a substring search, if the
            # uid given in the query is short (i.e. just "0") we're likely to
            # get false positives back from the server.
            #
            # Long uids are folded, so splice the lines together here before
            # attempting a match.
            item_uid = re.search(r'\nUID:((.|\n[ \t])*)\n', data)
            if (not item_uid or
                    re.sub(r'\n[ \t]', '', item_uid.group(1)) != uid):
                continue
            return self._calendar_comp_class_by_data(data)(
                self.client, url=URL.objectify(href), data=data, parent=self)
        raise error.NotFoundError("%s not found on server" % uid)
Ejemplo n.º 4
0
 def load(self):
     """
     Load the object from the caldav server.
     """
     r = self.client.request(self.url)
     if r.status == 404:
         raise error.NotFoundError(errmsg(r))
     self.data = vcal.fix(r.raw)
     return self
Ejemplo n.º 5
0
    def object_by_uid(self, uid, comp_filter=None):
        """
        Get one event from the calendar.

        Parameters:
         * uid: the event uid

        Returns:
         * Event() or None
        """
        data = cdav.CalendarData()
        prop = dav.Prop() + data

        query = cdav.TextMatch(uid)
        query = cdav.PropFilter("UID") + query
        if comp_filter:
            query = comp_filter + query
        vcalendar = cdav.CompFilter("VCALENDAR") + query
        filter = cdav.Filter() + vcalendar

        root = cdav.CalendarQuery() + [prop, filter]

        response = self._query(root, 1, 'report')

        if response.status == 404:
            raise error.NotFoundError(errmsg(response))
        elif response.status == 400:
            raise error.ReportError(errmsg(response))

        items_found = response.tree.findall(".//" + dav.Response.tag)
        for r in items_found:
            href = unquote(r.find(".//" + dav.Href.tag).text)
            data = unquote(r.find(".//" + cdav.CalendarData.tag).text)
            # Ref Lucas Verney, we've actually done a substring search, if the
            # uid given in the query is short (i.e. just "0") we're likely to
            # get false positives back from the server.
            if not "\nUID:%s\n" % uid in data:
                # TODO: optimistic assumption, uid line is not folded.  We
                # need to unfold the content to be 100% sure that we won't
                # filter away true positives here.
                continue
            return self._calendar_comp_class_by_data(data)(
                self.client, url=URL.objectify(href), data=data, parent=self)
        raise error.NotFoundError(errmsg(response))
Ejemplo n.º 6
0
    def event_by_uid(self, uid):
        """
        Get one event from the calendar.

        Parameters:
         * uid: the event uid

        Returns:
         * Event() or None
        """
        e = None

        data = cdav.CalendarData()
        prop = dav.Prop() + data

        match = cdav.TextMatch(uid)
        propf = cdav.PropFilter("UID") + match
        vevent = cdav.CompFilter("VEVENT") + propf
        vcalendar = cdav.CompFilter("VCALENDAR") + vevent
        filter = cdav.Filter() + vcalendar

        root = cdav.CalendarQuery() + [prop, filter]

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

        if response.status == 404:
            raise error.NotFoundError(response.raw)
        elif response.status == 400:
            raise error.ReportError(response.raw)
            
        r = response.tree.find(".//" + dav.Response.tag)
        if r is not None:
            href = URL.objectify(r.find(".//" + dav.Href.tag).text)
            data = r.find(".//" + cdav.CalendarData.tag).text
            e = Event(self.client, url=href, data=data, parent=self)
        else:
            raise error.NotFoundError(response.raw)

        return e
Ejemplo n.º 7
0
    def object_by_uid(self, uid, comp_filter=None):
        """
        Get one event from the calendar.

        Parameters:
         * uid: the event uid

        Returns:
         * Event() or None
        """
        data = cdav.CalendarData()
        prop = dav.Prop() + data

        query = cdav.TextMatch(uid)
        query = cdav.PropFilter("UID") + query
        if comp_filter:
            query = comp_filter + query
        else:
            raise Exception("Need a comp_filter")
        vcalendar = cdav.CompFilter("VCALENDAR") + query
        filter = cdav.Filter() + vcalendar

        root = cdav.CalendarQuery() + [prop, filter]

        response = self._query(root, 1, 'report')

        if response.status == 404:
            raise error.NotFoundError(response.raw)
        elif response.status == 400:
            raise error.ReportError(response.raw)

        r = response.tree.find(".//" + dav.Response.tag)
        if r is not None:
            href = r.find(".//" + dav.Href.tag).text
            data = r.find(".//" + cdav.CalendarData.tag).text
            return self._calendar_comp_class_by_data(data)(
                self.client, url=URL.objectify(href), data=data, parent=self)
        else:
            raise error.NotFoundError(response.raw)
Ejemplo n.º 8
0
    def _query(self,
               root=None,
               depth=0,
               query_method='propfind',
               url=None,
               expected_return_value=None):
        """
        This is an internal method for doing a query.  It's a
        result of code-refactoring work, attempting to consolidate
        similar-looking code into a common method.
        """
        # ref https://bitbucket.org/cyrilrbt/caldav/issues/46 -
        # COMPATIBILITY ISSUE. The lines below seems to solve real
        # world problems, though I believe it's the wrong place to
        # inject the missing slash.
        # TODO: find out why the slash is missing and fix
        # it properly.
        # Background: Collection URLs ends with a slash,
        # non-collection URLs does not end with a slash.  If the
        # slash is missing, Servers MAY pretend it's present (RFC
        # 4918, section 5.2, collection resources), hence only some
        # few servers break when the slash is missing.  RFC 4918
        # specifies that collection URLs end with a slash while
        # non-collection URLs should not end with a slash.
        if url is None:
            url = self.url
            if not url.endswith('/'):
                url = URL(str(url) + '/')

        body = ""
        if root:
            if hasattr(root, 'xmlelement'):
                body = etree.tostring(root.xmlelement(),
                                      encoding="utf-8",
                                      xml_declaration=True)
            else:
                body = root
        ret = getattr(self.client, query_method)(url, body, depth)
        if ret.status == 404:
            raise error.NotFoundError(errmsg(ret))
        if ((expected_return_value is not None
             and ret.status != expected_return_value) or ret.status >= 400):
            raise error.exception_by_method[query_method](errmsg(ret))
        return ret
Ejemplo n.º 9
0
    def object_by_uid(self, uid, comp_filter=None):
        """
        Get one event from the calendar.

        Parameters:
         * uid: the event uid

        Returns:
         * Event() or None
        """
        data = cdav.CalendarData()
        prop = dav.Prop() + data

        query = cdav.TextMatch(uid)
        query = cdav.PropFilter("UID") + query
        if comp_filter:
            query = comp_filter + query
        vcalendar = cdav.CompFilter("VCALENDAR") + query
        filter = cdav.Filter() + vcalendar

        root = cdav.CalendarQuery() + [prop, filter]

        items_found = self.search(root)

        # Ref Lucas Verney, we've actually done a substring search, if the
        # uid given in the query is short (i.e. just "0") we're likely to
        # get false positives back from the server, we need to do an extra
        # check that the uid is correct
        for item in items_found:
            # Long uids are folded, so splice the lines together here before
            # attempting a match.
            item_uid = re.search(r'\nUID:((.|\n[ \t])*)\n', item.data)
            if (not item_uid
                    or re.sub(r'\n[ \t]', '', item_uid.group(1)) != uid):
                continue
            return item
        raise error.NotFoundError("%s not found on server" % uid)