Exemplo n.º 1
0
 def test_toxml(self):
     """
     L{WebDAVDocument.toxml} returns a C{str} giving the XML representation
     of the L{WebDAVDocument} instance.
     """
     document = WebDAVDocument(self.element)
     self.assertEquals(document, WebDAVDocument.fromString(document.toxml()))
Exemplo n.º 2
0
 def test_fromString(self):
     """
     The XML representation of L{WebDAVDocument} can be parsed into a
     L{WebDAVDocument} instance using L{WebDAVDocument.fromString}.
     """
     doc = WebDAVDocument.fromString(self.serialized)
     self.assertEquals(doc, WebDAVDocument(self.element))
Exemplo n.º 3
0
 def test_toxml(self):
     """
     L{WebDAVDocument.toxml} returns a C{str} giving the XML representation
     of the L{WebDAVDocument} instance.
     """
     document = WebDAVDocument(self.element)
     self.assertEquals(document,
                       WebDAVDocument.fromString(document.toxml()))
def moveCalendarTimezoneProperties(sqlStore):
    """
    Need to move all the CalDAV:calendar-timezone properties in the
    RESOURCE_PROPERTY table to the new CALENDAR_BIND table columns, extracting
    the new value from the XML property.
    """

    cb = schema.CALENDAR_BIND
    rp = schema.RESOURCE_PROPERTY

    try:
        calendars_for_id = {}
        while True:
            sqlTxn = sqlStore.newTransaction()
            rows = (yield rowsForProperty(sqlTxn, caldavxml.CalendarTimeZone, with_uid=True, batch=BATCH_SIZE))
            if len(rows) == 0:
                yield sqlTxn.commit()
                break
            delete_ids = []
            for calendar_rid, value, viewer in rows:
                delete_ids.append(calendar_rid)
                if calendar_rid not in calendars_for_id:
                    ids = yield Select(
                        [cb.CALENDAR_HOME_RESOURCE_ID, cb.BIND_MODE, ],
                        From=cb,
                        Where=cb.CALENDAR_RESOURCE_ID == calendar_rid,
                    ).on(sqlTxn)
                    calendars_for_id[calendar_rid] = ids

                if viewer:
                    calendarHome = (yield sqlTxn.calendarHomeWithUID(viewer))
                else:
                    calendarHome = None
                    for row in calendars_for_id[calendar_rid]:
                        home_id, bind_mode = row
                        if bind_mode == _BIND_MODE_OWN:
                            calendarHome = (yield sqlTxn.calendarHomeWithResourceID(home_id))
                            break

                if calendarHome is not None:
                    prop = WebDAVDocument.fromString(value).root_element
                    calendar = (yield calendarHome.childWithID(calendar_rid))
                    if calendar is not None:
                        yield calendar.setTimezone(prop.calendar())

            # Always delete the rows so that batch processing works correctly
            yield Delete(
                From=rp,
                Where=(rp.RESOURCE_ID.In(Parameter("ids", len(delete_ids)))).And
                      (rp.NAME == PropertyName.fromElement(caldavxml.CalendarTimeZone).toString()),
            ).on(sqlTxn, ids=delete_ids)

            yield sqlTxn.commit()

        yield cleanPropertyStore()

    except RuntimeError:
        f = Failure()
        yield sqlTxn.abort()
        f.raiseException()
Exemplo n.º 5
0
 def test_fromString(self):
     """
     The XML representation of L{WebDAVDocument} can be parsed into a
     L{WebDAVDocument} instance using L{WebDAVDocument.fromString}.
     """
     doc = WebDAVDocument.fromString(self.serialized)
     self.assertEquals(doc, WebDAVDocument(self.element))
def moveSupportedComponentSetProperties(sqlStore):
    """
    Need to move all the CalDAV:supported-component-set properties in the
    RESOURCE_PROPERTY table to the new CALENDAR_METADATA table column,
    extracting the new format value from the XML property.
    """

    sqlTxn = sqlStore.newTransaction()
    try:
        rows = (yield rowsForProperty(sqlTxn, caldavxml.SupportedCalendarComponentSet))
        for calendar_rid, value in rows:
            prop = WebDAVDocument.fromString(value).root_element
            supported_components = ",".join(sorted([comp.attributes["name"].upper() for comp in prop.children]))
            meta = schema.CALENDAR_METADATA
            yield Update(
                {
                    meta.SUPPORTED_COMPONENTS : supported_components
                },
                Where=(meta.RESOURCE_ID == calendar_rid)
            ).on(sqlTxn)

        yield removeProperty(sqlTxn, caldavxml.SupportedCalendarComponentSet)
        yield sqlTxn.commit()
    except RuntimeError:
        yield sqlTxn.abort()
        raise
Exemplo n.º 7
0
 def parse(xml):
     try:
         doc = WebDAVDocument.fromString(xml)
         doc.root_element.validate()
         return doc
     except ValueError:
         log.error("Bad XML:\n%s" % (xml, ))
         raise
Exemplo n.º 8
0
 def parse(xml):
     try:
         doc = WebDAVDocument.fromString(xml)
         doc.root_element.validate()
         return doc
     except ValueError:
         log.err("Bad XML:\n%s" % (xml,))
         raise
Exemplo n.º 9
0
    def _getitem_uid(self, key, uid):
        validKey(key)

        try:
            value = self._cached[(key.toString(), uid)]
        except KeyError:
            raise KeyError(key)

        return WebDAVDocument.fromString(value).root_element
Exemplo n.º 10
0
    def _getitem_uid(self, key, uid):
        validKey(key)

        try:
            value = self._cached[(key.toString(), uid)]
        except KeyError:
            raise KeyError(key)

        return WebDAVDocument.fromString(value).root_element
Exemplo n.º 11
0
    def test_extractCalendarServerPrincipalSearchData(self):
        """
        Exercise the parser for calendarserver-principal-search documents
        """

        data = """<B:calendarserver-principal-search xmlns:A="DAV:" xmlns:B="http://calendarserver.org/ns/" context="attendee">
  <B:search-token>morgen</B:search-token>
  <A:prop>
    <A:principal-URL/>
    <A:displayname/>
  </A:prop>
</B:calendarserver-principal-search>
"""
        doc = WebDAVDocument.fromString(data)
        tokens, context, applyTo, clientLimit, _ignore_propElement = extractCalendarServerPrincipalSearchData(
            doc.root_element)
        self.assertEquals(tokens, ["morgen"])
        self.assertEquals(context, "attendee")
        self.assertFalse(applyTo)
        self.assertEquals(clientLimit, None)

        data = """<B:calendarserver-principal-search xmlns:A="DAV:" xmlns:B="http://calendarserver.org/ns/">
  <B:search-token>morgen</B:search-token>
  <B:search-token>sagen</B:search-token>
  <B:limit>
      <B:nresults>42</B:nresults>
  </B:limit>
  <A:prop>
    <A:principal-URL/>
    <A:displayname/>
  </A:prop>
  <A:apply-to-principal-collection-set/>
</B:calendarserver-principal-search>
"""
        doc = WebDAVDocument.fromString(data)
        tokens, context, applyTo, clientLimit, _ignore_propElement = extractCalendarServerPrincipalSearchData(
            doc.root_element)
        self.assertEquals(tokens, ["morgen", "sagen"])
        self.assertEquals(context, None)
        self.assertTrue(applyTo)
        self.assertEquals(clientLimit, 42)
    def test_extractCalendarServerPrincipalSearchData(self):
        """
        Exercise the parser for calendarserver-principal-search documents
        """

        data = """<B:calendarserver-principal-search xmlns:A="DAV:" xmlns:B="http://calendarserver.org/ns/" context="attendee">
  <B:search-token>morgen</B:search-token>
  <A:prop>
    <A:principal-URL/>
    <A:displayname/>
  </A:prop>
</B:calendarserver-principal-search>
"""
        doc = WebDAVDocument.fromString(data)
        tokens, context, applyTo, clientLimit, propElement =  extractCalendarServerPrincipalSearchData(doc.root_element)
        self.assertEquals(tokens, ["morgen"])
        self.assertEquals(context, "attendee")
        self.assertFalse(applyTo)
        self.assertEquals(clientLimit, None)


        data = """<B:calendarserver-principal-search xmlns:A="DAV:" xmlns:B="http://calendarserver.org/ns/">
  <B:search-token>morgen</B:search-token>
  <B:search-token>sagen</B:search-token>
  <B:limit>
      <B:nresults>42</B:nresults>
  </B:limit>
  <A:prop>
    <A:principal-URL/>
    <A:displayname/>
  </A:prop>
  <A:apply-to-principal-collection-set/>
</B:calendarserver-principal-search>
"""
        doc = WebDAVDocument.fromString(data)
        tokens, context, applyTo, clientLimit, propElement =  extractCalendarServerPrincipalSearchData(doc.root_element)
        self.assertEquals(tokens, ["morgen", "sagen"])
        self.assertEquals(context, None)
        self.assertTrue(applyTo)
        self.assertEquals(clientLimit, 42)
def moveCalendarAvailabilityProperties(sqlStore):
    """
    Need to move all the CS:calendar-availability properties in the
    RESOURCE_PROPERTY table to the new CALENDAR_BIND table columns, extracting
    the new value from the XML property.
    """

    cb = schema.CALENDAR_BIND
    rp = schema.RESOURCE_PROPERTY

    try:
        while True:
            sqlTxn = sqlStore.newTransaction()
            rows = (yield rowsForProperty(sqlTxn, customxml.CalendarAvailability, batch=BATCH_SIZE))
            if len(rows) == 0:
                yield sqlTxn.commit()
                break

            # Map each calendar to a home id using a single query for efficiency
            calendar_ids = [row[0] for row in rows]

            home_map = yield Select(
                [cb.CALENDAR_RESOURCE_ID, cb.CALENDAR_HOME_RESOURCE_ID, ],
                From=cb,
                Where=(cb.CALENDAR_RESOURCE_ID.In(Parameter("ids", len(calendar_ids)))).And(cb.BIND_MODE == _BIND_MODE_OWN),
            ).on(sqlTxn, ids=calendar_ids)
            calendar_to_home = dict(home_map)

            # Move property to each home
            for calendar_rid, value in rows:
                if calendar_rid in calendar_to_home:
                    calendarHome = (yield sqlTxn.calendarHomeWithResourceID(calendar_to_home[calendar_rid]))

                    if calendarHome is not None:
                        prop = WebDAVDocument.fromString(value).root_element
                        yield calendarHome.setAvailability(prop.calendar())

            # Always delete the rows so that batch processing works correctly
            yield Delete(
                From=rp,
                Where=(rp.RESOURCE_ID.In(Parameter("ids", len(calendar_ids)))).And
                      (rp.NAME == PropertyName.fromElement(customxml.CalendarAvailability).toString()),
            ).on(sqlTxn, ids=calendar_ids)

            yield sqlTxn.commit()

        yield cleanPropertyStore()

    except RuntimeError:
        f = Failure()
        yield sqlTxn.abort()
        f.raiseException()
Exemplo n.º 14
0
    def _doPOSTSharerAccept(self, body, resultcode=responsecode.OK):
        request = SimpleStoreRequest(self, "POST", "/calendars/__uids__/user02/", content=body, authid="user02")
        request.headers.setHeader("content-type", MimeType("text", "xml"))
        response = yield self.send(request)
        response = IResponse(response)
        self.assertEqual(response.code, resultcode)

        if response.stream:
            xmldata = yield allDataFromStream(response.stream)
            doc = WebDAVDocument.fromString(xmldata)
            returnValue(doc)
        else:
            returnValue(None)
Exemplo n.º 15
0
    def _doPOSTSharerAccept(self, body, resultcode=responsecode.OK, sharer="user02"):
        authPrincipal = yield self.actualRoot.findPrincipalForAuthID(sharer)
        request = SimpleStoreRequest(self, "POST", "/calendars/__uids__/{}/".format(sharer), content=body, authPrincipal=authPrincipal)
        request.headers.setHeader("content-type", MimeType("text", "xml"))
        response = yield self.send(request)
        response = IResponse(response)
        self.assertEqual(response.code, resultcode)

        if response.stream:
            xmldata = yield allDataFromStream(response.stream)
            doc = WebDAVDocument.fromString(xmldata)
            returnValue(doc)
        else:
            returnValue(None)
def moveSupportedComponentSetProperties(sqlStore):
    """
    Need to move all the CalDAV:supported-component-set properties in the
    RESOURCE_PROPERTY table to the new CALENDAR_METADATA table column,
    extracting the new format value from the XML property.
    """

    logUpgradeStatus("Starting Move supported-component-set")

    sqlTxn = sqlStore.newTransaction(
        label="calendar_upgrade_from_1_to_2.moveSupportedComponentSetProperties"
    )
    try:
        # Do not move the properties if migrating, as migration will do a split and set supported-components,
        # however we still need to remove the old properties.
        if not sqlStore._migrating:
            calendar_rid = None
            rows = (yield
                    rowsForProperty(sqlTxn,
                                    caldavxml.SupportedCalendarComponentSet))
            total = len(rows)
            count = 0
            for calendar_rid, value in rows:
                prop = WebDAVDocument.fromString(value).root_element
                supported_components = ",".join(
                    sorted([
                        comp.attributes["name"].upper()
                        for comp in prop.children
                    ]))
                meta = schema.CALENDAR_METADATA
                yield Update(
                    {
                        meta.SUPPORTED_COMPONENTS: supported_components
                    },
                    Where=(meta.RESOURCE_ID == calendar_rid)).on(sqlTxn)
                count += 1
                logUpgradeStatus("Move supported-component-set", count, total)

        yield removeProperty(sqlTxn, caldavxml.SupportedCalendarComponentSet)
        yield sqlTxn.commit()

        logUpgradeStatus("End Move supported-component-set")
    except RuntimeError:
        yield sqlTxn.abort()
        logUpgradeError("Move supported-component-set",
                        "Last calendar: {}".format(calendar_rid))
        raise
def moveSupportedComponentSetProperties(sqlStore):
    """
    Need to move all the CalDAV:supported-component-set properties in the
    RESOURCE_PROPERTY table to the new CALENDAR_METADATA table column,
    extracting the new format value from the XML property.
    """

    logUpgradeStatus("Starting Move supported-component-set")

    sqlTxn = sqlStore.newTransaction()
    try:
        # Do not move the properties if migrating, as migration will do a split and set supported-components,
        # however we still need to remove the old properties.
        if not sqlStore._migrating:
            calendar_rid = None
            rows = (yield rowsForProperty(sqlTxn, caldavxml.SupportedCalendarComponentSet))
            total = len(rows)
            count = 0
            for calendar_rid, value in rows:
                prop = WebDAVDocument.fromString(value).root_element
                supported_components = ",".join(sorted([comp.attributes["name"].upper() for comp in prop.children]))
                meta = schema.CALENDAR_METADATA
                yield Update(
                    {
                        meta.SUPPORTED_COMPONENTS : supported_components
                    },
                    Where=(meta.RESOURCE_ID == calendar_rid)
                ).on(sqlTxn)
                count += 1
                logUpgradeStatus("Move supported-component-set", count, total)

        yield removeProperty(sqlTxn, caldavxml.SupportedCalendarComponentSet)
        yield sqlTxn.commit()

        logUpgradeStatus("End Move supported-component-set")
    except RuntimeError:
        yield sqlTxn.abort()
        logUpgradeError(
            "Move supported-component-set",
            "Last calendar: {}".format(calendar_rid)
        )
        raise
Exemplo n.º 18
0
    def _doPOSTSharerAccept(self,
                            body,
                            resultcode=responsecode.OK,
                            sharer="user02"):
        authPrincipal = yield self.actualRoot.findPrincipalForAuthID(sharer)
        request = SimpleStoreRequest(self,
                                     "POST",
                                     "/calendars/__uids__/{}/".format(sharer),
                                     content=body,
                                     authPrincipal=authPrincipal)
        request.headers.setHeader("content-type", MimeType("text", "xml"))
        response = yield self.send(request)
        response = IResponse(response)
        self.assertEqual(response.code, resultcode)

        if response.stream:
            xmldata = yield allDataFromStream(response.stream)
            doc = WebDAVDocument.fromString(xmldata)
            returnValue(doc)
        else:
            returnValue(None)
Exemplo n.º 19
0
def normalize(x):
    """
    Normalize some XML by parsing it, collapsing whitespace, and
    pretty-printing.
    """
    return WebDAVDocument.fromString(x).toxml()
Exemplo n.º 20
0
class xattrPropertyStore(object):
    """

    This implementation uses Bob Ippolito's xattr package, available from::

        http://undefined.org/python/#xattr

    Note that the Bob's xattr package is specific to Linux and Darwin, at least
    presently.
    """
    #
    # Dead properties are stored as extended attributes on disk.  In order to
    # avoid conflicts with other attributes, prefix dead property names.
    #
    deadPropertyXattrPrefix = "WebDAV:"

    # Linux seems to require that attribute names use a "user." prefix.
    # FIXME: Is is a system-wide thing, or a per-filesystem thing?
    #   If the latter, how to we detect the file system?
    if sys.platform == "linux2":
        deadPropertyXattrPrefix = "user."

    def _encode(clazz, name, uid=None):
        result = urllib.quote(encodeXMLName(*name), safe='{}:')
        if uid:
            result = uid + result
        r = clazz.deadPropertyXattrPrefix + result
        return r

    def _decode(clazz, name):
        name = urllib.unquote(name[len(clazz.deadPropertyXattrPrefix):])

        index1 = name.find("{")
        index2 = name.find("}")

        if (index1 is -1 or index2 is -1 or not len(name) > index2):
            raise ValueError("Invalid encoded name: %r" % (name, ))
        if index1 == 0:
            uid = None
        else:
            uid = name[:index1]
        propnamespace = name[index1 + 1:index2]
        propname = name[index2 + 1:]

        return (propnamespace, propname, uid)

    _encode = classmethod(_encode)
    _decode = classmethod(_decode)

    def __init__(self, resource):
        self.resource = resource
        self.attrs = xattr.xattr(self.resource.fp.path)

    def get(self, qname, uid=None):
        """
        Retrieve the value of a property stored as an extended attribute on the
        wrapped path.

        @param qname: The property to retrieve as a two-tuple of namespace URI
            and local name.

        @param uid: The per-user identifier for per user properties.

        @raise HTTPError: If there is no value associated with the given
            property.

        @return: A L{WebDAVDocument} representing the value associated with the
            given property.
        """

        try:
            data = self.attrs.get(self._encode(qname, uid))
        except KeyError:
            raise HTTPError(
                StatusResponse(
                    responsecode.NOT_FOUND,
                    "No such property: %s" % (encodeXMLName(*qname), )))
        except IOError, e:
            if e.errno in _ATTR_MISSING or e.errno == errno.ENOENT:
                raise HTTPError(
                    StatusResponse(
                        responsecode.NOT_FOUND,
                        "No such property: %s" % (encodeXMLName(*qname), )))
            else:
                raise HTTPError(
                    StatusResponse(
                        statusForFailure(Failure()),
                        "Unable to read property: %s" %
                        (encodeXMLName(*qname), )))

        #
        # Unserialize XML data from an xattr.  The storage format has changed
        # over time:
        #
        #  1- Started with XML
        #  2- Started compressing the XML due to limits on xattr size
        #  3- Switched to pickle which is faster, still compressing
        #  4- Back to compressed XML for interoperability, size
        #
        # We only write the current format, but we also read the old
        # ones for compatibility.
        #
        legacy = False

        try:
            data = decompress(data)
        except zlib.error:
            legacy = True

        try:
            doc = WebDAVDocument.fromString(data)
        except ValueError:
            try:
                doc = unpickle(data)
            except UnpicklingError:
                format = "Invalid property value stored on server: %s %s"
                msg = format % (encodeXMLName(*qname), data)
                err(None, msg)
                raise HTTPError(
                    StatusResponse(responsecode.INTERNAL_SERVER_ERROR, msg))
            else:
                legacy = True

        if legacy:
            self.set(doc.root_element)

        return doc.root_element
def _processDefaultCalendarProperty(sqlStore, propname, colname):
    """
    Move the specified property value to the matching CALENDAR_HOME_METADATA table column.

    Since the number of calendar homes may well be large, we need to do this in batches.
    """

    cb = schema.CALENDAR_BIND
    rp = schema.RESOURCE_PROPERTY

    try:
        while True:
            sqlTxn = sqlStore.newTransaction()
            rows = (yield rowsForProperty(sqlTxn, propname, batch=BATCH_SIZE))
            if len(rows) == 0:
                yield sqlTxn.commit()
                break
            delete_ids = []
            for inbox_rid, value in rows:
                delete_ids.append(inbox_rid)
                ids = yield Select(
                    [cb.CALENDAR_HOME_RESOURCE_ID, ],
                    From=cb,
                    Where=cb.CALENDAR_RESOURCE_ID == inbox_rid,
                ).on(sqlTxn)
                if len(ids) > 0:

                    calendarHome = (yield sqlTxn.calendarHomeWithResourceID(ids[0][0]))
                    if calendarHome is not None:

                        prop = WebDAVDocument.fromString(value).root_element
                        defaultCalendar = str(prop.children[0])
                        parts = defaultCalendar.split("/")
                        if len(parts) == 5:

                            calendarName = parts[-1]
                            calendarHomeUID = parts[-2]
                            expectedHome = (yield sqlTxn.calendarHomeWithUID(calendarHomeUID))
                            if expectedHome is not None and expectedHome.id() == calendarHome.id():

                                calendar = (yield calendarHome.calendarWithName(calendarName))
                                if calendar is not None:
                                    yield calendarHome.setDefaultCalendar(
                                        calendar, tasks=(propname == customxml.ScheduleDefaultTasksURL)
                                    )

            # Always delete the rows so that batch processing works correctly
            yield Delete(
                From=rp,
                Where=(rp.RESOURCE_ID.In(Parameter("ids", len(delete_ids)))).And
                      (rp.NAME == PropertyName.fromElement(propname).toString()),
            ).on(sqlTxn, ids=delete_ids)

            yield sqlTxn.commit()

        yield cleanPropertyStore()

    except RuntimeError:
        f = Failure()
        yield sqlTxn.abort()
        f.raiseException()
def _processDefaultAlarmProperty(sqlStore, propname, vevent, timed):
    """
    Move the specified property value to the matching CALENDAR_HOME_METADATA or CALENDAR_BIND table column.

    Since the number of properties may well be large, we need to do this in batches.
    """

    hm = schema.CALENDAR_HOME_METADATA
    cb = schema.CALENDAR_BIND
    rp = schema.RESOURCE_PROPERTY

    try:
        calendars_for_id = {}
        while True:
            sqlTxn = sqlStore.newTransaction()
            rows = (yield rowsForProperty(sqlTxn, propname, with_uid=True, batch=BATCH_SIZE))
            if len(rows) == 0:
                yield sqlTxn.commit()
                break
            delete_ids = []
            for rid, value, viewer in rows:
                delete_ids.append(rid)

                prop = WebDAVDocument.fromString(value).root_element
                alarm = str(prop.children[0]) if prop.children else None

                # First check if the rid is a home - this is the most common case
                ids = yield Select(
                    [hm.RESOURCE_ID, ],
                    From=hm,
                    Where=hm.RESOURCE_ID == rid,
                ).on(sqlTxn)

                if len(ids) > 0:
                    # Home object
                    calendarHome = (yield sqlTxn.calendarHomeWithResourceID(ids[0][0]))
                    if calendarHome is not None:
                        yield calendarHome.setDefaultAlarm(alarm, vevent, timed)
                else:
                    # rid is a calendar - we need to find the per-user calendar for the resource viewer
                    if rid not in calendars_for_id:
                        ids = yield Select(
                            [cb.CALENDAR_HOME_RESOURCE_ID, cb.BIND_MODE, ],
                            From=cb,
                            Where=cb.CALENDAR_RESOURCE_ID == rid,
                        ).on(sqlTxn)
                        calendars_for_id[rid] = ids

                    if viewer:
                        calendarHome = (yield sqlTxn.calendarHomeWithUID(viewer))
                    else:
                        calendarHome = None
                        for row in calendars_for_id[rid]:
                            home_id, bind_mode = row
                            if bind_mode == _BIND_MODE_OWN:
                                calendarHome = (yield sqlTxn.calendarHomeWithResourceID(home_id))
                                break

                    if calendarHome is not None:
                        calendar = yield calendarHome.childWithID(rid)
                        if calendar is not None:
                            yield calendar.setDefaultAlarm(alarm, vevent, timed)

            # Always delete the rows so that batch processing works correctly
            yield Delete(
                From=rp,
                Where=(rp.RESOURCE_ID.In(Parameter("ids", len(delete_ids)))).And
                      (rp.NAME == PropertyName.fromElement(propname).toString()),
            ).on(sqlTxn, ids=delete_ids)

            yield sqlTxn.commit()

        yield cleanPropertyStore()

    except RuntimeError:
        f = Failure()
        yield sqlTxn.abort()
        f.raiseException()
Exemplo n.º 23
0
def normalize(x):
    """
    Normalize some XML by parsing it, collapsing whitespace, and
    pretty-printing.
    """
    return WebDAVDocument.fromString(x).toxml()
Exemplo n.º 24
0
        #  2- Started compressing the XML due to limits on xattr size
        #  3- Switched to pickle which is faster, still compressing
        #  4- Back to compressed XML for interoperability, size
        #
        # We only write the current format, but we also read the old
        # ones for compatibility.
        #
        legacy = False

        try:
            data = decompress(data)
        except ZlibError:
            legacy = True

        try:
            doc = WebDAVDocument.fromString(data)
        except ValueError:
            try:
                doc = unpickle(data)
            except UnpicklingError:
                msg = "Invalid property value stored on server: %s %s" % (
                    key.toString(), data
                )
                self.log.error(msg)
                raise PropertyStoreError(msg)
            else:
                legacy = True

        if legacy:
            # XXX untested: CDT catches this though.
            self._setitem_uid(key, doc.root_element, uid)
def updateNotification(txn, notification):
    """
    For this notification home, update the associated child resources.
    """

    # Convert the type value to JSON
    xmltype = WebDAVDocument.fromString(
        notification.notificationType()).root_element
    shared_type = "calendar"
    if xmltype.children[0].qname() == customxml.InviteNotification.qname():
        jsontype = {"notification-type": "invite-notification"}
        if "shared-type" in xmltype.children[0].attributes:
            shared_type = xmltype.children[0].attributes["shared-type"]
        jsontype["shared-type"] = shared_type
    elif xmltype.children[0].qname() == customxml.InviteReply.qname():
        jsontype = {"notification-type": "invite-reply"}

    # Convert the data value to JSON
    xmldata = (yield notification.notificationData())
    xmldata = WebDAVDocument.fromString(xmldata).root_element

    def _extract_UID(uri):
        if uri.startswith("urn:uuid:"):
            return uri[len("urn:uuid:"):]
        elif uri[0] == "/":
            return uri.rstrip("/").split("/")[-1]
        elif uri.startswith("mailto:"):
            return uri[7:].split("@")[0]
        else:
            return ""

    if xmldata.childOfType(customxml.InviteNotification) is not None:
        ntype = xmldata.childOfType(customxml.InviteNotification)
        dtstamp = str(xmldata.childOfType(customxml.DTStamp))
        owner = _extract_UID(
            str(
                ntype.childOfType(customxml.Organizer).childOfType(
                    element.HRef)))
        sharee = _extract_UID(str(ntype.childOfType(element.HRef)))
        uid = str(ntype.childOfType(customxml.UID))
        for xml in invitationBindStatusFromXMLMap.keys():
            if ntype.childOfType(xml) is not None:
                state = invitationBindStatusFromXMLMap[xml]
                break
        else:
            state = _BIND_STATUS_INVITED
        mode = invitationBindModeFromXMLMap[type(
            ntype.childOfType(customxml.InviteAccess).children[0])]
        name = str(
            ntype.childOfType(customxml.HostURL).childOfType(
                element.HRef)).rstrip("/").split("/")[-1]
        summary = str(ntype.childOfType(customxml.InviteSummary))

        jsondata = {
            "notification-type": "invite-notification",
            "shared-type": shared_type,
            "dtstamp": dtstamp,
            "owner": owner,
            "sharee": sharee,
            "uid": uid,
            "status": state,
            "access": mode,
            "name": name,
            "summary": summary,
        }
        if ntype.childOfType(caldavxml.SupportedCalendarComponentSet):
            comps = [
                child.attributes["name"] for child in ntype.childOfType(
                    caldavxml.SupportedCalendarComponentSet).children
            ]
            jsondata["supported-components"] = ",".join(comps)

    elif xmldata.childOfType(customxml.InviteReply) is not None:
        ntype = xmldata.childOfType(customxml.InviteReply)
        dtstamp = str(xmldata.childOfType(customxml.DTStamp))
        sharee = _extract_UID(str(ntype.childOfType(element.HRef)))
        for xml in invitationBindStatusFromXMLMap.keys():
            if ntype.childOfType(xml) is not None:
                state = invitationBindStatusFromXMLMap[xml]
                break
        else:
            state = _BIND_STATUS_INVITED
        name = str(
            ntype.childOfType(customxml.HostURL).childOfType(
                element.HRef)).rstrip("/").split("/")[-1]
        inreplyto = str(ntype.childOfType(customxml.InReplyTo))
        summary = str(ntype.childOfType(
            customxml.InviteSummary)) if ntype.childOfType(
                customxml.InviteSummary) is not None else ""

        owner = str(
            ntype.childOfType(customxml.HostURL).childOfType(
                element.HRef)).rstrip("/").split("/")[-2]

        jsondata = {
            "notification-type": "invite-reply",
            "shared-type": shared_type,
            "dtstamp": dtstamp,
            "owner": owner,
            "sharee": sharee,
            "status": state,
            "name": name,
            "in-reply-to": inreplyto,
            "summary": summary,
        }

    yield notification.setData(notification.uid(), jsontype, jsondata)
Exemplo n.º 26
0
        #  2- Started compressing the XML due to limits on xattr size
        #  3- Switched to pickle which is faster, still compressing
        #  4- Back to compressed XML for interoperability, size
        #
        # We only write the current format, but we also read the old
        # ones for compatibility.
        #
        legacy = False

        try:
            data = decompress(data)
        except ZlibError:
            legacy = True

        try:
            doc = WebDAVDocument.fromString(data)
        except ValueError:
            try:
                doc = unpickle(data)
            except UnpicklingError:
                msg = "Invalid property value stored on server: %s %s" % (
                    key.toString(), data
                )
                self.log.error(msg)
                raise PropertyStoreError(msg)
            else:
                legacy = True

        if legacy:
            # XXX untested: CDT catches this though.
            self._setitem_uid(key, doc.root_element, uid)
def updateNotification(txn, notification):
    """
    For this notification home, update the associated child resources.
    """

    # Convert the type value to JSON
    xmltype = WebDAVDocument.fromString(notification.notificationType()).root_element
    shared_type = "calendar"
    if xmltype.children[0].qname() == customxml.InviteNotification.qname():
        jsontype = {"notification-type": "invite-notification"}
        if "shared-type" in xmltype.children[0].attributes:
            shared_type = xmltype.children[0].attributes["shared-type"]
        jsontype["shared-type"] = shared_type
    elif xmltype.children[0].qname() == customxml.InviteReply.qname():
        jsontype = {"notification-type": "invite-reply"}

    # Convert the data value to JSON
    xmldata = (yield notification.notificationData())
    xmldata = WebDAVDocument.fromString(xmldata).root_element

    def _extract_UID(uri):
        if uri.startswith("urn:uuid:"):
            return uri[len("urn:uuid:"):]
        elif uri[0] == "/":
            return uri.rstrip("/").split("/")[-1]
        elif uri.startswith("mailto:"):
            return uri[7:].split("@")[0]
        else:
            return ""

    if xmldata.childOfType(customxml.InviteNotification) is not None:
        ntype = xmldata.childOfType(customxml.InviteNotification)
        dtstamp = str(xmldata.childOfType(customxml.DTStamp))
        owner = _extract_UID(str(ntype.childOfType(customxml.Organizer).childOfType(element.HRef)))
        sharee = _extract_UID(str(ntype.childOfType(element.HRef)))
        uid = str(ntype.childOfType(customxml.UID))
        for xml in invitationBindStatusFromXMLMap.keys():
            if ntype.childOfType(xml) is not None:
                state = invitationBindStatusFromXMLMap[xml]
                break
        else:
            state = _BIND_STATUS_INVITED
        mode = invitationBindModeFromXMLMap[type(ntype.childOfType(customxml.InviteAccess).children[0])]
        name = str(ntype.childOfType(customxml.HostURL).childOfType(element.HRef)).rstrip("/").split("/")[-1]
        summary = str(ntype.childOfType(customxml.InviteSummary))

        jsondata = {
            "notification-type": "invite-notification",
            "shared-type": shared_type,
            "dtstamp": dtstamp,
            "owner": owner,
            "sharee": sharee,
            "uid": uid,
            "status": state,
            "access": mode,
            "name": name,
            "summary": summary,
        }
        if ntype.childOfType(caldavxml.SupportedCalendarComponentSet):
            comps = [child.attributes["name"] for child in ntype.childOfType(caldavxml.SupportedCalendarComponentSet).children]
            jsondata["supported-components"] = ",".join(comps)

    elif xmldata.childOfType(customxml.InviteReply) is not None:
        ntype = xmldata.childOfType(customxml.InviteReply)
        dtstamp = str(xmldata.childOfType(customxml.DTStamp))
        sharee = _extract_UID(str(ntype.childOfType(element.HRef)))
        for xml in invitationBindStatusFromXMLMap.keys():
            if ntype.childOfType(xml) is not None:
                state = invitationBindStatusFromXMLMap[xml]
                break
        else:
            state = _BIND_STATUS_INVITED
        name = str(ntype.childOfType(customxml.HostURL).childOfType(element.HRef)).rstrip("/").split("/")[-1]
        inreplyto = str(ntype.childOfType(customxml.InReplyTo))
        summary = str(ntype.childOfType(customxml.InviteSummary)) if ntype.childOfType(customxml.InviteSummary) is not None else ""

        owner = str(ntype.childOfType(customxml.HostURL).childOfType(element.HRef)).rstrip("/").split("/")[-2]

        jsondata = {
            "notification-type": "invite-reply",
            "shared-type": shared_type,
            "dtstamp": dtstamp,
            "owner": owner,
            "sharee": sharee,
            "status": state,
            "name": name,
            "in-reply-to": inreplyto,
            "summary": summary,
        }

    yield notification.setData(notification.uid(), jsontype, jsondata)