/// <summary> /// The CALDAV:calendar-query REPORT performs a search for all calendar object resources that match a /// specified filter. The response of this report will contain all the WebDAV properties and calendar object /// resource data specified in the request. In the case of the CALDAV:calendar-data XML element, one can /// explicitly specify the calendar components and properties that should be returned in the calendar object /// resource data that matches the filter. /// </summary> /// <param name="xmlDoc">The body of the request.</param> /// <param name="collectionURl"></param> /// <param name="httpContext"></param> /// <returns></returns> public async Task CalendarQuery(IXMLTreeStructure xmlDoc, string collectionURl, HttpContext httpContext) { IFileSystemManagement fs = new FileSystemManagement(); // take the first prop node to know the data that // should ne returned IXMLTreeStructure propNode; xmlDoc.GetChildAtAnyLevel("prop", out propNode); //get the filters to be applied IXMLTreeStructure componentFilter; xmlDoc.GetChildAtAnyLevel("filter", out componentFilter); var userResources = new Dictionary <string, string>(); await fs.GetAllCalendarObjectResource(collectionURl, userResources); var userCalendars = userResources.ToDictionary(userResource => userResource.Key, userResource => VCalendar.Parse(userResource.Value)); //apply the filters to the calendars var filteredCalendars = userCalendars.Where(x => x.Value.FilterResource(componentFilter)); await ReportResponseBuilder(filteredCalendars, propNode, httpContext); }
/// <summary> /// The CALDAV:calendar-multiget REPORT is used to retrieve specific calendar object resources from within a /// collection, if the Request-URI is a collection, or to retrieve a specific calendar object resource, if the /// Request-URI is a calendar object resource. This report is similar to the CALDAV:calendar-query REPORT /// (see Section 7.8), except that it takes a list of DAV:href elements, instead of a CALDAV:filter element, to /// determine which calendar object resources to return /// </summary> /// <returns></returns> private async Task CalendarMultiget(IXMLTreeStructure xmlBody, HttpContext httpContext) { // take the first prop node to know the data that // should ne returned IXMLTreeStructure propNode; xmlBody.GetChildAtAnyLevel("prop", out propNode); //take the href nodes. Contain the direction of the resources files that //are requested var hrefs = xmlBody.Children.Where(node => node.NodeName == "href").Select(href => href.Value); var result = new Dictionary <string, string>(); // process the requested resources foreach (var href in hrefs) { var fs = new FileSystemManagement(); var resourceContent = await fs.GetCalendarObjectResource(href); result.Add(href, resourceContent); } await ReportResponseBuilder(result .Select( x => new KeyValuePair <string, VCalendar>(x.Key, string.IsNullOrEmpty(x.Value) ? null : VCalendar.Parse(x.Value))), propNode, httpContext); }
public async Task AclPrincipalPropSet(IXMLTreeStructure body, HttpResponse response) { //take the requested properties from the body // of the request IXMLTreeStructure propNode; //first take the node container of the property names body.GetChildAtAnyLevel("prop", out propNode); //take the children of the node, these are the proeprties var requestedProperties = propNode.Children.Select(x => new KeyValuePair <string, string>(x.NodeName, x.MainNamespace)); var colUrl = ""; //Take the resource with the href == to the given url //TODO: should the href property be store in a property? var resource = await _resourceRepository.GetAsync(colUrl); //take the string representation of the acl property //this property is stored in xml format so is needed to //be parsed to xml var aclProperty = resource.Properties.First(x => x.Name == "acl"); var aclXmlProperty = XDocument.Parse(aclProperty.Value); //take the href of the principals of the property var principalsURLs = aclXmlProperty.Elements("principal") .Select(x => x.Descendants("href").FirstOrDefault()); var principals = new Dictionary <Principal, IEnumerable <Property> >(); //take all the principals with its url equal to the givens foreach (var pUrl in principalsURLs) { var principal = _principalRepository.Get(pUrl.Value); if (principal != null) { principals.Add(principal, null); } } //take the requested properties from the principals foreach (var principal in principals) { principals[principal.Key] = principal.Key.TakeProperties(requestedProperties); } await WriteBody(response, principals); }
/// <summary> /// The filters have to be applied in an specific component, property /// or param of a property. This method go deep in the calCOmponents following the /// treeStructure of the filter till it get the component where to apply the filter. /// </summary> /// <param name="container">The container of the components.</param> /// <param name="treeStructure">The IXMLTree where is the filter.</param> /// <param name="filter">Return The XmlTreeStructure node that contains the filter.</param> /// <param name="component">The final component where to apply the filter.</param> /// <returns>True if found the component, false otherwise.</returns> public static bool ComponentSeeker(this ICalendarComponentsContainer container, IXMLTreeStructure treeStructure, out IXMLTreeStructure filter, out ICalendarComponent component) { filter = null; component = null; while (true) { ICalendarComponent comp = null; IXMLTreeStructure compNode = null; treeStructure.GetChildAtAnyLevel("comp-filter", out compNode); if (compNode == null) { //if the filter doesn't has a child with comp-filter name //and the name of the current container is the same if (((ICalendarObject)container).Name == treeStructure.Attributes["name"]) { filter = treeStructure; component = container as ICalendarComponent; return(true); } else { return(false); } } var compName = compNode.Attributes["name"]; //if the container doesn't has a calComponent with the desired compName //then return false if (!container.CalendarComponents.ContainsKey(compName)) { return(false); } //take the comp with the desired name comp = container.CalendarComponents[compName].First(); var componentsContainer = comp as ICalendarComponentsContainer; //if the the filter has more components and the container has more calendarComp //then go deeper if (componentsContainer != null && compNode.Children.Any(x => x.NodeName == "comp-filter")) { container = componentsContainer; treeStructure = compNode; continue; } //if not then apply the filter in the comp component = comp; filter = compNode; return(true); } }
/// <summary> /// Extract all property names and property namespace from a prop element of a propfind body. /// </summary> /// <param name="propFindTree"></param> /// <returns></returns> private List <KeyValuePair <string, string> > ExtractPropertiesNameMainNS(IXMLTreeStructure propFindTree) { var retList = new List <KeyValuePair <string, string> >(); IXMLTreeStructure props; if (propFindTree.GetChildAtAnyLevel("prop", out props)) { retList.AddRange( props.Children.Select( child => new KeyValuePair <string, string>(child.NodeName, string.IsNullOrEmpty(child.MainNamespace) ? "DAV:" : child.MainNamespace))); } return(retList); }
/// <summary> /// Apply different filters to the given calendar. /// </summary> /// <param name="calendar">THe calendar to apply the filter.</param> /// <param name="filterTree">The filter container. The node in the xml with name = "filter"</param> /// <returns>True if the calendar pass the filter, false otherwise</returns> public static bool FilterResource(this VCalendar calendar, IXMLTreeStructure filterTree) { //first get the component in the calendar where to apply the filter. IXMLTreeStructure filtersContainer; ICalendarComponent component; //take the first node with "comp-filter" name, // this is the node with name="VCALENDAR" filterTree.GetChildAtAnyLevel("comp-filter", out filterTree); //get the component and filter in the position of the first component // required by the filter that is a child of VCALENDAR if (!ComponentSeeker(calendar, filterTree, out filtersContainer, out component)) { return(false); //if the container doesn't have the requested comp then return false; } foreach (var filter in filtersContainer.Children) { switch (filter.NodeName) { case "prop-filter": var result = component.PropertyFilter(filter); if (!result) { return(false); } break; case "time-range": result = component.ApplyTimeFilter(filter); if (!result) { return(false); } break; default: throw new NotImplementedException($"The filter with name{filter.NodeName} isn't implemented yet"); } } return(true); }