Пример #1
0
def report_urn_ietf_params_xml_ns_caldav_free_busy_query(self, request, freebusy):
    """
    Generate a free-busy REPORT.
    (CalDAV-access-09, section 7.8)
    """
    if not self.isCollection():
        log.error("freebusy report is only allowed on collection resources {s!r}", s=self)
        raise HTTPError(StatusResponse(responsecode.FORBIDDEN, "Not a calendar collection"))

    if freebusy.qname() != (caldavxml.caldav_namespace, "free-busy-query"):
        raise ValueError("{CalDAV:}free-busy-query expected as root element, not %s." % (freebusy.sname(),))

    timerange = freebusy.timerange
    if not timerange.valid():
        raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "Invalid time-range specified"))

    fbset = []

    accepted_type = bestAcceptType(request.headers.getHeader("accept"), Component.allowedTypes())
    if accepted_type is None:
        raise HTTPError(StatusResponse(responsecode.NOT_ACCEPTABLE, "Cannot generate requested data type"))

    def getCalendarList(calresource, uri):  # @UnusedVariable
        """
        Store the calendars that match the query in L{fbset} which will then be used with the
        freebusy query.

        @param calresource: the L{CalDAVResource} for a calendar collection.
        @param uri: the uri for the calendar collection resource.
        """

        fbset.append(calresource._newStoreObject)
        return succeed(True)

    # Run report taking depth into account
    depth = request.headers.getHeader("depth", "0")
    yield report_common.applyToCalendarCollections(self, request, request.uri, depth, getCalendarList, (caldavxml.ReadFreeBusy(),))

    # Do the actual freebusy query against the set of matched calendars
    principal = yield self.resourceOwnerPrincipal(request)
    organizer = recipient = LocalCalendarUser(principal.canonicalCalendarUserAddress(), principal.record)
    timerange = Period(timerange.start, timerange.end)
    try:
        fbresult = yield FreebusyQuery(organizer=organizer, recipient=recipient, timerange=timerange).generateAttendeeFreeBusyResponse(fbset=fbset, method=None)
    except NumberOfMatchesWithinLimits:
        log.error("Too many matching components in free-busy report")
        raise HTTPError(ErrorResponse(
            responsecode.FORBIDDEN,
            davxml.NumberOfMatchesWithinLimits(),
            "Too many components"
        ))
    except TimeRangeLowerLimit, e:
        raise HTTPError(ErrorResponse(
            responsecode.FORBIDDEN,
            caldavxml.MinDateTime(),
            "Time-range value too far in the past. Must be on or after %s." % (str(e.limit),)
        ))
        raise HTTPError(ErrorResponse(
            responsecode.FORBIDDEN,
            MaxInstances.fromString(str(ex.max_allowed)),
            "Too many instances",
        ))
    except NumberOfMatchesWithinLimits:
        log.error("Too many matching components in calendar-query report")
        raise HTTPError(ErrorResponse(
            responsecode.FORBIDDEN,
            davxml.NumberOfMatchesWithinLimits(),
            "Too many components",
        ))
    except TimeRangeLowerLimit, e:
        raise HTTPError(ErrorResponse(
            responsecode.FORBIDDEN,
            caldavxml.MinDateTime(),
            "Time-range value too far in the past. Must be on or after %s." % (str(e.limit),)
        ))
    except TimeRangeUpperLimit, e:
        raise HTTPError(ErrorResponse(
            responsecode.FORBIDDEN,
            caldavxml.MaxDateTime(),
            "Time-range value too far in the future. Must be on or before %s." % (str(e.limit),)
        ))

    if not hasattr(request, "extendedLogItems"):
        request.extendedLogItems = {}
    request.extendedLogItems["responses"] = len(responses)

    returnValue(MultiStatusResponse(responses))
Пример #3
0
def report_urn_ietf_params_xml_ns_caldav_free_busy_query(
        self, request, freebusy):  #@UnusedVariable
    """
    Generate a free-busy REPORT.
    (CalDAV-access-09, section 7.8)
    """
    if not self.isCollection():
        log.error(
            "freebusy report is only allowed on collection resources %s" %
            (self, ))
        raise HTTPError(
            StatusResponse(responsecode.FORBIDDEN,
                           "Not a calendar collection"))

    if freebusy.qname() != (caldavxml.caldav_namespace, "free-busy-query"):
        raise ValueError(
            "{CalDAV:}free-busy-query expected as root element, not %s." %
            (freebusy.sname(), ))

    timerange = freebusy.timerange
    if not timerange.valid():
        raise HTTPError(
            StatusResponse(responsecode.BAD_REQUEST,
                           "Invalid time-range specified"))

    # First list is BUSY, second BUSY-TENTATIVE, third BUSY-UNAVAILABLE
    fbinfo = ([], [], [])

    matchcount = [0]

    accepted_type = bestAcceptType(request.headers.getHeader("accept"),
                                   Component.allowedTypes())
    if accepted_type is None:
        raise HTTPError(
            StatusResponse(responsecode.NOT_ACCEPTABLE,
                           "Cannot generate requested data type"))

    def generateFreeBusyInfo(calresource, uri):  #@UnusedVariable
        """
        Run a free busy report on the specified calendar collection
        accumulating the free busy info for later processing.
        @param calresource: the L{CalDAVResource} for a calendar collection.
        @param uri: the uri for the calendar collecton resource.
        """
        def _gotResult(result):
            matchcount[0] = result
            return True

        d = report_common.generateFreeBusyInfo(request, calresource, fbinfo,
                                               timerange, matchcount[0])
        d.addCallback(_gotResult)
        return d

    # Run report taking depth into account
    try:
        depth = request.headers.getHeader("depth", "0")
        yield report_common.applyToCalendarCollections(
            self, request, request.uri, depth, generateFreeBusyInfo,
            (caldavxml.ReadFreeBusy(), ))
    except NumberOfMatchesWithinLimits:
        log.error("Too many matching components in free-busy report")
        raise HTTPError(
            ErrorResponse(responsecode.FORBIDDEN,
                          davxml.NumberOfMatchesWithinLimits(),
                          "Too many components"))
    except TimeRangeLowerLimit, e:
        raise HTTPError(
            ErrorResponse(
                responsecode.FORBIDDEN, caldavxml.MinDateTime(),
                "Time-range value too far in the past. Must be on or after %s."
                % (str(e.limit), )))
Пример #4
0
                responsecode.FORBIDDEN,
                MaxInstances.fromString(str(ex.max_allowed)),
                "Too many instances",
            ))
    except NumberOfMatchesWithinLimits:
        log.error("Too many matching components in calendar-query report")
        raise HTTPError(
            ErrorResponse(
                responsecode.FORBIDDEN,
                davxml.NumberOfMatchesWithinLimits(),
                "Too many components",
            ))
    except TimeRangeLowerLimit, e:
        raise HTTPError(
            ErrorResponse(
                responsecode.FORBIDDEN, caldavxml.MinDateTime(),
                "Time-range value too far in the past. Must be on or after %s."
                % (str(e.limit), )))
    except TimeRangeUpperLimit, e:
        raise HTTPError(
            ErrorResponse(
                responsecode.FORBIDDEN, caldavxml.MaxDateTime(),
                "Time-range value too far in the future. Must be on or before %s."
                % (str(e.limit), )))

    if not hasattr(request, "extendedLogItems"):
        request.extendedLogItems = {}
    request.extendedLogItems["responses"] = len(responses)

    returnValue(MultiStatusResponse(responses))