/// <summary> /// Loads address book folder by ID. Returns null if addressbook folder was not found. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> /// <param name="addressbookFolderId">ID of the address book folder to load.</param> /// <returns><see cref="IAddressbookFolderAsync"/> instance.</returns> public static async Task <IAddressbookFolderAsync> LoadByIdAsync(DavContext context, Guid addressbookFolderId) { // Load only address book that the use has access to. // Also load complete ACL for this address book. string sql = @"SELECT * FROM [card_AddressbookFolder] WHERE [AddressbookFolderId] = @AddressbookFolderId AND [AddressbookFolderId] IN (SELECT [AddressbookFolderId] FROM [card_Access] WHERE [UserId]=@UserId) ; SELECT * FROM [card_Access] WHERE [AddressbookFolderId] = @AddressbookFolderId AND [AddressbookFolderId] IN (SELECT [AddressbookFolderId] FROM [card_Access] WHERE [UserId]=@UserId)"; return((await LoadAsync(context, sql, "@UserId", context.UserId , "@AddressbookFolderId", addressbookFolderId )).FirstOrDefault()); }
/// <summary> /// Loads calendar folder by ID. Returns null if calendar folder was not found. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> /// <param name="calendarFolderId">ID of the calendar folder to load.</param> /// <returns><see cref="ICalendarFolderAsync"/> instance.</returns> public static async Task <ICalendarFolderAsync> LoadByIdAsync(DavContext context, Guid calendarFolderId) { // Load only calendar that the use has access to. // Also load complete ACL for this calendar. string sql = @"SELECT * FROM [cal_CalendarFolder] WHERE [CalendarFolderId] = @CalendarFolderId AND [CalendarFolderId] IN (SELECT [CalendarFolderId] FROM [cal_Access] WHERE [UserId]=@UserId) ; SELECT * FROM [cal_Access] WHERE [CalendarFolderId] = @CalendarFolderId AND [CalendarFolderId] IN (SELECT [CalendarFolderId] FROM [cal_Access] WHERE [UserId]=@UserId)"; return((await LoadAsync(context, sql, "@UserId", context.UserId , "@CalendarFolderId", calendarFolderId )).FirstOrDefault()); }
/// <summary> /// Returns calendar file that corresponds to path or null if no calendar file is found. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/></param> /// <param name="path">Encoded path relative to WebDAV root.</param> /// <returns>CalendarFile instance or null if not found.</returns> public static CalendarFile GetCalendarFile(DavContext context, string path) { string pattern = string.Format(@"^/?{0}/(?<user_name>[^/]+)/(?<calendar_name>[^/]+)/(?<file_name>[^/]+\.ics)$", CalendarsRootFolder.CalendarsRootFolderPath.Trim(new char[] { '/' }).Replace("/", "/?")); if (!Regex.IsMatch(path, pattern)) { return(null); } FileInfo file = new FileInfo(context.MapPath(path)); if (!file.Exists) { return(null); } return(new CalendarFile(file, context, path)); }
/// <summary> /// Gets object representing ACL folder/user/group. /// </summary> /// <param name="path">Relative path requested.</param> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> /// <returns>Object implemening LogicalFolder/IPrincipalFolder</returns> internal static async Task <IHierarchyItemAsync> GetAclItemAsync(DavContext context, string path) { //If this is /acl - return fake folder which contains users and groups. if (path == AclFolder.PREFIX) { return(new AclFolder(context)); } //if this is /acl/users - return fake folder which contains users. if (path == UserFolder.PREFIX) { return(new UserFolder(context)); } //if this is /acl/groups - return fake folder which contains groups. if (path == GroupFolder.PREFIX) { return(new GroupFolder(context)); } //if this is /acl/users/<user name> - return instance of User. if (path.StartsWith(UserFolder.PATH)) { string name = EncodeUtil.DecodeUrlPart(path.Substring(UserFolder.PATH.Length)); //we don't need an exception here - so check for validity. if (PrincipalBase.IsValidUserName(name)) { return(User.FromName(name, context)); } } //if this is /acl/groups/<group name> - return instance of Group. if (path.StartsWith(GroupFolder.PATH)) { string name = EncodeUtil.DecodeUrlPart(path.Substring(GroupFolder.PATH.Length)); if (PrincipalBase.IsValidUserName(name)) { return(Group.FromName(name, context)); } } return(null); }
public async Task <StatusCode> HandleAsync(DavContext context, ResourceResponse resource) { if (resource.Resource != null) { var headOnly = string.Equals(context.Request.Method, Methods.Head, StringComparison.OrdinalIgnoreCase); if (resource.Resource.ResourceType == ResourceType.Collection) { if (context.Config.AllowDirectoryBrowsing) { await ShowDirectoryListingAsync(context, resource.Resource, headOnly); } } else if (resource.Resource.ResourceType == ResourceType.Resource) { await SendFileAsync(context, resource.Resource, headOnly); } return(StatusCode.OK); } return(StatusCode.NotFound); }
/// <summary> /// Returns calendar folder that corresponds to path. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/></param> /// <param name="path">Encoded path relative to WebDAV root.</param> /// <returns>CalendarFolder instance or null if not found.</returns> public static CalendarFolder GetCalendarFolder(DavContext context, string path) { string pattern = string.Format("^/?{0}/(?<user_name>[^/]+)/(?<calendar_name>[^/]+)/?", CalendarsRootFolder.CalendarsRootFolderPath.Trim(new char[] { '/' }).Replace("/", "/?")); if (!Regex.IsMatch(path, pattern)) { return(null); } string folderPath = context.MapPath(path).TrimEnd(System.IO.Path.DirectorySeparatorChar); DirectoryInfo folder = new DirectoryInfo(folderPath); // to block vulnerability when "%20" folder can be injected into path and folder.Exists returns 'true' if (!folder.Exists || String.Compare(folder.FullName.TrimEnd(System.IO.Path.DirectorySeparatorChar), folderPath, StringComparison.OrdinalIgnoreCase) != 0) { return(null); } return(new CalendarFolder(folder, context, path)); }
/// <summary> /// Creates a new address book folder. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> /// <param name="name">Address book name.</param> /// <param name="description">Address book description.</param> internal static async Task CreateAddressbookFolderAsync(DavContext context, string name, string description) { // 1. Create address book. // 2. Grant owner privileges to the user on the created address book(s). string sql = @"INSERT INTO [card_AddressbookFolder] ( [AddressbookFolderId] , [Name] , [Description] ) VALUES ( @AddressbookFolderId , @Name , @Description ) ; INSERT INTO [card_Access] ( [AddressbookFolderId] , [UserId] , [Owner] , [Read] , [Write] ) VALUES ( @AddressbookFolderId , @UserId , @Owner , @Read , @Write )"; Guid addressbookFolderId = Guid.NewGuid(); await context.ExecuteNonQueryAsync(sql, "@AddressbookFolderId", addressbookFolderId , "@Name", name , "@Description", description , "@UserId", context.UserId , "@Owner", true , "@Read", true , "@Write", true ); }
/// <summary> /// Creates a new calendar folder. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> /// <param name="name">Calendar folder name.</param> public static async Task CreateCalendarFolderAsync(DavContext context, string name, string description) { // 1. Create calendar. // 2. Grant owner privileges to the user on the created calendar. string sql = @"INSERT INTO [cal_CalendarFolder] ( [CalendarFolderId] , [Name] , [Description] ) VALUES ( @CalendarFolderId , @Name , @Description ) ; INSERT INTO [cal_Access] ( [CalendarFolderId] , [UserId] , [Owner] , [Read] , [Write] ) VALUES ( @CalendarFolderId , @UserId , @Owner , @Read , @Write )"; Guid calendarFolderId = Guid.NewGuid(); await context.ExecuteNonQueryAsync(sql, "@CalendarFolderId", calendarFolderId , "@Name", name , "@Description", description , "@UserId", context.UserId , "@Owner", true , "@Read", true , "@Write", true ); }
static async Task SendFileAsync(DavContext context, IResource resource, bool headOnly) { if (resource.Length > 0) { context.Response.Headers.ContentLength = resource.Length; } context.Response.Headers.ContentType = resource.ContentType; context.Response.Headers.Append("Content-Disposition", "inline; filename=" + Uri.EscapeUriString(resource.DisplayName)); if (!headOnly) { using (Stream fs = context.Config.DataStore.Read(resource)) { byte[] buff = new byte[4096]; int read = 0; while ((read = await fs.ReadAsync(buff, 0, buff.Length)) > 0) { await context.Response.Body.WriteAsync(buff, 0, read, context.CancellationToken); } } } }
/// <summary> /// Gets CalDAV items. /// </summary> /// <param name="path">Relative path requested.</param> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> /// <returns>Object implementing various CalDAV items or null if no object corresponding to path is found.</returns> internal static IHierarchyItemAsync GetCalDavItem(DavContext context, string path) { IHierarchyItemAsync item = null; item = CalendarsRootFolder.GetCalendarsRootFolder(context, path); if (item != null) { return(item); } item = CalendarFolder.GetCalendarFolder(context, path); if (item != null) { return(item); } item = CalendarFile.GetCalendarFile(context, path); if (item != null) { return(item); } return(null); }
/// <summary> /// Gets object representing ACL folder, user or group. /// </summary> /// <param name="path">Relative path requested.</param> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> /// <returns>Object implemening ACL principal or folder</returns> internal static async Task <IHierarchyItemAsync> GetAclItemAsync(DavContext context, string path) { // If this is [DAVLocation]/acl - return folder which contains users and groups. if (path.Equals(AclFolder.AclFolderPath.Trim('/'), System.StringComparison.InvariantCultureIgnoreCase)) { return(new AclFolder(context)); } // If this is [DAVLocation]/acl/users - return folder which contains users. if (path.Equals(UsersFolder.UsersFolderPath.Trim('/'), System.StringComparison.InvariantCultureIgnoreCase)) { return(new UsersFolder(context)); } // If this is [DAVLocation]/acl/users/[UserID] - return instance of User. if (path.StartsWith(UsersFolder.UsersFolderPath.Trim('/'), System.StringComparison.InvariantCultureIgnoreCase)) { string[] segments = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); string userId = EncodeUtil.DecodeUrlPart(segments.Last()); return(await User.GetUserAsync(context, userId)); } return(null); }
/// <summary> /// Gets CardDAV items. /// </summary> /// <param name="path">Relative path requested.</param> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> /// <returns>Object implementing various CardDAV items or null if no object corresponding to path is found.</returns> internal static IHierarchyItemAsync GetCardDavItem(DavContext context, string path) { IHierarchyItemAsync item = null; item = AddressbooksRootFolder.GetAddressbooksRootFolder(context, path); if (item != null) { return(item); } item = AddressbookFolder.GetAddressbookFolder(context, path); if (item != null) { return(item); } item = CardFile.GetCardFile(context, path); if (item != null) { return(item); } return(null); }
public static async Task <User> GetUserAsync(DavContext context, string userId) { DavUser user = context.Users.FirstOrDefault(p => p.UserName.Equals(userId, StringComparison.InvariantCultureIgnoreCase)); return(new User(context, userId, user.UserName, user.Email, new DateTime(2000, 1, 1), new DateTime(2000, 1, 1))); }
/// <summary> /// Initializes a new instance of the <see cref="CalendarFolder"/> class. /// </summary> /// <param name="directoryInfo">Instance of <see cref="DirectoryInfo"/> class with information about the folder in file system.</param> /// <param name="context">Instance of <see cref="DavContext"/>.</param> /// <param name="path">Relative to WebDAV root folder path.</param> private CalendarFolder(DirectoryInfo directoryInfo, DavContext context, string path) : base(directoryInfo, context, path) { }
public FolderResource(DavContext context, string logicalPath, string physicalPath) : base(context, logicalPath) { _info = new DirectoryInfo(physicalPath); }
/// <summary> /// Initializes a new instance of the AclFolder class. /// </summary> /// <param name="context">Instace of <see cref="DavContext"/>.</param> public AclFolder(DavContext context) : base(context, "acl", PATH) { }
/// <summary> /// Initializes a new instance of the <see cref="CalendarFile"/> class. /// </summary> /// <param name="file"><see cref="FileInfo"/> for corresponding object in file system.</param> /// <param name="context">Instance of <see cref="DavContext"/></param> /// <param name="path">Encoded path relative to WebDAV root.</param> private CalendarFile(FileInfo file, DavContext context, string path) : base(file, context, path) { }
/// <summary> /// Initializes a new instance of the AclFolder class. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/></param> /// <param name="name">Folder name.</param> /// <param name="path">Encoded path relative to WebDAV root.</param> public AclFolder(DavContext context) : base(context, AclFolderPath) { }
/// <summary> /// Creates instance of User class. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> /// <param name="userId">ID of this user</param> /// <remarks> /// This consturctor is called when user URL is required, typically when discovering user calendars, /// no need to populate all properties, only user ID is required. /// </remarks> public User(DavContext context, string userId) : this(context, userId, null, null, new DateTime(2000, 1, 1), new DateTime(2000, 1, 1)) { }
public FakeFileResource(DavContext context, string logicalPath) : base(context, logicalPath) { }
/// <summary> /// Initializes a new instance of the <see cref="GroupFolder"/> class. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> public GroupFolder(DavContext context) : base(context, "groups", PATH) { }
private AddressbooksRootFolder(DirectoryInfo directory, DavContext context, string path) : base(directory, context, path) { }
/// <summary> /// Initializes a new instance of the Group class. /// </summary> /// <param name="groupPrincipal">Corresponding .net GroupPrincipal object.</param> /// <param name="context">Instance of <see cref="DavContext"/>.</param> public Group(GroupPrincipal groupPrincipal, DavContext context) : base(groupPrincipal, GroupFolder.PATH, context) { this.groupPrincipal = groupPrincipal; }
/// <summary> /// Loads all address books. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> /// <returns>List of <see cref="IAddressbookFolderAsync"/> items.</returns> public static async Task <IEnumerable <IAddressbookFolderAsync> > LoadAllAsync(DavContext context) { // Load only address books that the use has access to. // Also load complete ACL for each address book, but only if user has access to that address book. string sql = @"SELECT * FROM [card_AddressbookFolder] WHERE [AddressbookFolderId] IN (SELECT [AddressbookFolderId] FROM [card_Access] WHERE [UserId]=@UserId) ; SELECT * FROM [card_Access] WHERE [AddressbookFolderId] IN (SELECT [AddressbookFolderId] FROM [card_Access] WHERE [UserId]=@UserId)"; return(await LoadAsync(context, sql, "@UserId", context.UserId)); }
/// <summary> /// Initializes a new instance of the <see cref="UsersFolder"/> class. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> public UsersFolder(DavContext context) : base(context, UsersFolderPath) { }
/// <summary> /// Initializes a new instance of the PrincipalBase class. /// </summary> /// <param name="principal">Instance of <see cref="Principal"/>.</param> /// <param name="parentPath">Encoded path to parent folder.</param> /// <param name="context">Instance of <see cref="DavContext"/>.</param> protected PrincipalBase(Principal principal, string parentPath, DavContext context) : base(context) { this.Principal = principal; this.parentPath = parentPath; this.Context = context; }
/// <summary> /// Initializes a new instance of the <see cref="UserFolder"/> class. /// </summary> /// <param name="context">Instance of <see cref="DavContext"/> class.</param> public UserFolder(DavContext context) : base(context, "users", PATH) { }
public async Task <StatusCode> HandleAsync(DavContext context, ResourceResponse resource) { int maxDepth = context.Depth; context.Config.Log.LogDebug("Depth={0}", maxDepth); if (maxDepth == int.MaxValue && !context.Config.AllowInfiniteDepth) { // TODO: correct? return(StatusCode.BadRequest); } if (resource.Resource == null) { return(StatusCode.NotFound); } bool nameOnly = false; var filter = new List <PropertyFilter>(); var reqXml = context.ReadRequestAsXml(); if (reqXml != null) { context.Config.Log.LogDebug("Request:{0}{1}", Environment.NewLine, reqXml.OuterXml.PrettyXml()); if (reqXml.DocumentElement.Name == ElementNames.PropFind && reqXml.DocumentElement.NamespaceURI == XmlNamespace) { foreach (XmlNode node in reqXml.DocumentElement.ChildNodes) { if (node.NamespaceURI == XmlNamespace) { switch (node.Name) { case ElementNames.PropName: nameOnly = true; break; case ElementNames.Prop: foreach (XmlNode propNode in node.ChildNodes) { filter.Add(new PropertyFilter { Name = propNode.Name, XmlNamespace = propNode.NamespaceURI }); } break; } } } } else { return(StatusCode.BadRequest); } } var list = new List <ResourceResponse>(); WalkResourceTree(context, maxDepth, 0, list, resource); return(await WriteMultiStatusReponse(context, list, nameOnly, filter)); }
public AddressbooksRootFolder(DavContext context) : base(context, AddressbooksRootFolderPath) { }
public CalendarsRootFolder(DavContext context) : base(context, CalendarsRootFolderPath) { }