def testRelaxedBad(self): test_relaxed_data = ( ("P12DT", 12 * 24 * 60 * 60, "P12D"), ("-P1WT", -7 * 24 * 60 * 60, "-P1W"), ("-P1W1D", -7 * 24 * 60 * 60, "-P1W"), ) for text, seconds, result in test_relaxed_data: ParserContext.INVALID_DURATION_VALUE = ParserContext.PARSER_FIX self.assertEqual(Duration.parseText(text).getTotalSeconds(), seconds) self.assertEqual(Duration.parseText(text).getText(), result) ParserContext.INVALID_DURATION_VALUE = ParserContext.PARSER_RAISE self.assertRaises(ValueError, Duration.parseText, text)
def testRelaxedBad(self): test_relaxed_data = ( ("P12DT", 12 * 24 * 60 * 60, "P12D"), ("-P1WT", -7 * 24 * 60 * 60, "-P1W"), ("-P1W1D", -7 * 24 * 60 * 60, "-P1W"), ) for text, seconds, result in test_relaxed_data: ParserContext.INVALID_DURATION_VALUE = ParserContext.PARSER_FIX self.assertEqual( Duration.parseText(text).getTotalSeconds(), seconds) self.assertEqual(Duration.parseText(text).getText(), result) ParserContext.INVALID_DURATION_VALUE = ParserContext.PARSER_RAISE self.assertRaises(ValueError, Duration.parseText, text)
def parse(self, data, fullISO=False): try: splits = data.split('/', 1) if len(splits) == 2: start = splits[0] end = splits[1] self.mStart.parse(start, fullISO) if end[0] == 'P': self.mDuration = Duration.parseText(end) self.mUseDuration = True self.mEnd = None else: self.mEnd.parse(end, fullISO) self.mUseDuration = False self.mDuration = None else: raise ValueError except IndexError: raise ValueError
def _processFBURL(self, request): # # Check authentication and access controls # yield self.authorize(request, (davxml.Read(),)) # Extract query parameters from the URL args = ('start', 'end', 'duration', 'token', 'format', 'user',) for arg in args: setattr(self, arg, request.args.get(arg, [None])[0]) # Some things we do not handle if self.token or self.user: raise HTTPError(ErrorResponse( responsecode.NOT_ACCEPTABLE, (calendarserver_namespace, "supported-query-parameter"), "Invalid query parameter", )) # Check format if self.format: self.format = self.format.split(";")[0] if self.format not in ("text/calendar", "text/plain"): raise HTTPError(ErrorResponse( responsecode.NOT_ACCEPTABLE, (calendarserver_namespace, "supported-format"), "Invalid return format requested", )) else: self.format = "text/calendar" # Start/end/duration must be valid iCalendar DATE-TIME UTC or DURATION values try: if self.start: self.start = DateTime.parseText(self.start) if not self.start.utc(): raise ValueError() if self.end: self.end = DateTime.parseText(self.end) if not self.end.utc(): raise ValueError() if self.duration: self.duration = Duration.parseText(self.duration) except ValueError: raise HTTPError(ErrorResponse( responsecode.BAD_REQUEST, (calendarserver_namespace, "valid-query-parameters"), "Invalid query parameters", )) # Sanity check start/end/duration # End and duration cannot both be present if self.end and self.duration: raise HTTPError(ErrorResponse( responsecode.NOT_ACCEPTABLE, (calendarserver_namespace, "valid-query-parameters"), "Invalid query parameters", )) # Duration must be positive if self.duration and self.duration.getTotalSeconds() < 0: raise HTTPError(ErrorResponse( responsecode.BAD_REQUEST, (calendarserver_namespace, "valid-query-parameters"), "Invalid query parameters", )) # Now fill in the missing pieces if self.start is None: self.start = DateTime.getNowUTC() self.start.setHHMMSS(0, 0, 0) if self.duration: self.end = self.start + self.duration if self.end is None: self.end = self.start + Duration(days=config.FreeBusyURL.TimePeriod) # End > start if self.end <= self.start: raise HTTPError(ErrorResponse( responsecode.BAD_REQUEST, (calendarserver_namespace, "valid-query-parameters"), "Invalid query parameters", )) # TODO: We should probably verify that the actual time-range is within sensible bounds (e.g. not too far in the past or future and not too long) # Now lookup the principal details for the targeted user principal = (yield self.parent.principalForRecord()) # Pick the first mailto cu address or the first other type cuaddr = None for item in principal.calendarUserAddresses(): if cuaddr is None: cuaddr = item if item.startswith("mailto:"): cuaddr = item break # Get inbox details inboxURL = principal.scheduleInboxURL() if inboxURL is None: raise HTTPError(StatusResponse(responsecode.INTERNAL_SERVER_ERROR, "No schedule inbox URL for principal: %s" % (principal,))) try: inbox = (yield request.locateResource(inboxURL)) except: log.error("No schedule inbox for principal: {p}", p=principal) inbox = None if inbox is None: raise HTTPError(StatusResponse(responsecode.INTERNAL_SERVER_ERROR, "No schedule inbox for principal: %s" % (principal,))) organizer = recipient = LocalCalendarUser(cuaddr, principal.record) recipient.inbox = inbox._newStoreObject attendeeProp = Property("ATTENDEE", recipient.cuaddr) timerange = Period(self.start, self.end) fbresult = yield FreebusyQuery( organizer=organizer, recipient=recipient, attendeeProp=attendeeProp, timerange=timerange, ).generateAttendeeFreeBusyResponse() response = Response() response.stream = MemoryStream(str(fbresult)) response.headers.setHeader("content-type", MimeType.fromString("%s; charset=utf-8" % (self.format,))) returnValue(response)
def _processFBURL(self, request): # # Check authentication and access controls # yield self.authorize(request, (davxml.Read(),)) # Extract query parameters from the URL args = ('start', 'end', 'duration', 'token', 'format', 'user',) for arg in args: setattr(self, arg, request.args.get(arg, [None])[0]) # Some things we do not handle if self.token or self.user: raise HTTPError(ErrorResponse( responsecode.NOT_ACCEPTABLE, (calendarserver_namespace, "supported-query-parameter"), "Invalid query parameter", )) # Check format if self.format: self.format = self.format.split(";")[0] if self.format not in ("text/calendar", "text/plain"): raise HTTPError(ErrorResponse( responsecode.NOT_ACCEPTABLE, (calendarserver_namespace, "supported-format"), "Invalid return format requested", )) else: self.format = "text/calendar" # Start/end/duration must be valid iCalendar DATE-TIME UTC or DURATION values try: if self.start: self.start = DateTime.parseText(self.start) if not self.start.utc(): raise ValueError() if self.end: self.end = DateTime.parseText(self.end) if not self.end.utc(): raise ValueError() if self.duration: self.duration = Duration.parseText(self.duration) except ValueError: raise HTTPError(ErrorResponse( responsecode.BAD_REQUEST, (calendarserver_namespace, "valid-query-parameters"), "Invalid query parameters", )) # Sanity check start/end/duration # End and duration cannot both be present if self.end and self.duration: raise HTTPError(ErrorResponse( responsecode.NOT_ACCEPTABLE, (calendarserver_namespace, "valid-query-parameters"), "Invalid query parameters", )) # Duration must be positive if self.duration and self.duration.getTotalSeconds() < 0: raise HTTPError(ErrorResponse( responsecode.BAD_REQUEST, (calendarserver_namespace, "valid-query-parameters"), "Invalid query parameters", )) # Now fill in the missing pieces if self.start is None: self.start = DateTime.getNowUTC() self.start.setHHMMSS(0, 0, 0) if self.duration: self.end = self.start + self.duration if self.end is None: self.end = self.start + Duration(days=config.FreeBusyURL.TimePeriod) # End > start if self.end <= self.start: raise HTTPError(ErrorResponse( responsecode.BAD_REQUEST, (calendarserver_namespace, "valid-query-parameters"), "Invalid query parameters", )) # TODO: We should probably verify that the actual time-range is within sensible bounds (e.g. not too far in the past or future and not too long) # Now lookup the principal details for the targeted user principal = (yield self.parent.principalForRecord()) # Pick the first mailto cu address or the first other type cuaddr = None for item in principal.calendarUserAddresses(): if cuaddr is None: cuaddr = item if item.startswith("mailto:"): cuaddr = item break # Get inbox details inboxURL = principal.scheduleInboxURL() if inboxURL is None: raise HTTPError(StatusResponse(responsecode.INTERNAL_SERVER_ERROR, "No schedule inbox URL for principal: %s" % (principal,))) try: inbox = (yield request.locateResource(inboxURL)) except: log.error("No schedule inbox for principal: %s" % (principal,)) inbox = None if inbox is None: raise HTTPError(StatusResponse(responsecode.INTERNAL_SERVER_ERROR, "No schedule inbox for principal: %s" % (principal,))) organizer = recipient = LocalCalendarUser(cuaddr, principal.record) recipient.inbox = inbox._newStoreObject attendeeProp = Property("ATTENDEE", recipient.cuaddr) timerange = Period(self.start, self.end) fbresult = yield FreebusyQuery( organizer=organizer, recipient=recipient, attendeeProp=attendeeProp, timerange=timerange, ).generateAttendeeFreeBusyResponse() response = Response() response.stream = MemoryStream(str(fbresult)) response.headers.setHeader("content-type", MimeType.fromString("%s; charset=utf-8" % (self.format,))) returnValue(response)