Namespace: ITHit.WebDAV.Server.CardDav
The IAddressbookFolder type exposes the following members.
Name | Description | |
---|---|---|
AddressbookDescription |
Gets a human-readable description of the address book.
| |
Created |
Gets the creation date of the item in repository expressed as the coordinated universal time (UTC).
(Inherited from IHierarchyItemBase.) | |
Modified |
Gets the last modification date of the item in repository expressed as the coordinated universal time (UTC).
(Inherited from IHierarchyItemBase.) | |
Name |
Gets the name of the item in repository.
(Inherited from IHierarchyItemBase.) | |
Path |
Unique item path in the repository relative to storage root.
(Inherited from IHierarchyItemBase.) |
Name | Description | |
---|---|---|
CopyToAsync |
Creates a copy of this item with a new name in the destination folder.
(Inherited from IHierarchyItem.) | |
CreateFileAsync |
Creates new WebDAV file with the specified name in this folder.
(Inherited from IFolder.) | |
CreateFolderAsync |
Creates new WebDAV folder with the specified name in this folder.
(Inherited from IFolder.) | |
DeleteAsync |
Deletes this item.
(Inherited from IHierarchyItem.) | |
GetChildrenAsync |
Gets direct children of this folder.
(Inherited from IItemCollection.) | |
GetPropertiesAsync |
Gets values of all properties or selected properties for this item.
(Inherited from IHierarchyItem.) | |
GetPropertyNamesAsync |
Gets names of all properties for this item.
(Inherited from IHierarchyItem.) | |
MoveToAsync |
Moves this item to the destination folder under a new name.
(Inherited from IHierarchyItem.) | |
MultiGetAsync |
Returns a list of business card files that correspont to the specified list of item paths.
(Inherited from IAddressbookReport.) | |
QueryAsync |
Returns a list of business card files that match specified filter.
(Inherited from IAddressbookReport.) | |
UpdatePropertiesAsync |
Adds, modifies and removes properties for this item.
(Inherited from IHierarchyItem.) |
The code below is part of 'CardDAVServer.SqlStorage.AspNet' C# & VB samples provided with the SDK.
public class AddressbookFolder : DavHierarchyItem, IAddressbookFolder, ICurrentUserPrincipal, IAclHierarchyItem { public static async Task<IAddressbookFolder> 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(); } public static async Task<IEnumerable<IAddressbookFolder>> 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); } private static async Task<IEnumerable<IAddressbookFolder>> LoadAsync(DavContext context, string sql, params object[] prms) { IList<IAddressbookFolder> addressbookFolders = new List<IAddressbookFolder>(); using (SqlDataReader reader = await context.ExecuteReaderAsync(sql, prms)) { DataTable addressbooks = new DataTable(); addressbooks.Load(reader); DataTable access = new DataTable(); access.Load(reader); foreach (DataRow rowAddressbookFolder in addressbooks.Rows) { Guid addressbookFolderId = rowAddressbookFolder.Field<Guid>("AddressbookFolderId"); string filter = string.Format("AddressbookFolderId = '{0}'", addressbookFolderId); DataRow[] rowsAccess = access.Select(filter); addressbookFolders.Add(new AddressbookFolder(context, addressbookFolderId, rowAddressbookFolder, rowsAccess)); } } return addressbookFolders; } internal static async Task<IAddressbookFolder> 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 ); return await LoadByIdAsync(context, addressbookFolderId); } private readonly Guid addressbookFolderId; private readonly DataRow rowAddressbookFolder; private readonly DataRow[] rowsAccess; public override string Name { get { return rowAddressbookFolder != null ? rowAddressbookFolder.Field<string>("Name") : null; } } public override string Path { get { return string.Format("{0}{1}/", AddressbooksRootFolder.AddressbooksRootFolderPath, addressbookFolderId); } } private AddressbookFolder(DavContext context, Guid addressbookFolderId, DataRow addressbook, DataRow[] rowsAccess) : base(context) { this.addressbookFolderId = addressbookFolderId; this.rowAddressbookFolder = addressbook; this.rowsAccess = rowsAccess; } public async Task<IEnumerable<ICardFile>> MultiGetAsync(IEnumerable<string> pathList, IEnumerable<PropertyName> propNames) { // Get list of file names from path list. IEnumerable<string> fileNames = pathList.Select(a => System.IO.Path.GetFileNameWithoutExtension(a)); return await CardFile.LoadByFileNamesAsync(Context, fileNames, PropsToLoad.All); } public async Task<IEnumerable<ICardFile>> QueryAsync(string rawQuery, IEnumerable<PropertyName> propNames) { // For the sake of simplicity we just call GetChildren returning all items. // Typically you will return only items that match the query. return (await GetChildrenAsync(propNames.ToList(), null, null, null)).Page.Cast<ICardFile>(); } public string AddressbookDescription { get { return rowAddressbookFolder.Field<string>("Description"); } } public async Task<PageResults> GetChildrenAsync(IList<PropertyName> propNames, long? offset, long? nResults, IList<OrderProperty> orderProps) { // Here we enumerate all business cards contained in this address book. // You can filter children items in this implementation and // return only items that you want to be available for this // particular user. // Typically only getcontenttype and getetag properties are requested in GetChildren call by CalDAV/CardDAV clients. // The iCalendar/vCard (calendar-data/address-data) is typically requested not in GetChildren, but in a separate multiget // report, in MultiGetAsync() method call, that follows this request. // Bynari submits PROPFIND without props - Engine will request getcontentlength IList<IHierarchyItem> children = new List<IHierarchyItem>(); return new PageResults((await CardFile.LoadByAddressbookFolderIdAsync(Context, addressbookFolderId, PropsToLoad.Minimum)), null); } public async Task<IFile> CreateFileAsync(string name, Stream content, string contentType, long totalFileSize) { // The actual business card file is created in datatbase in CardFile.Write call. string fileName = System.IO.Path.GetFileNameWithoutExtension(name); return CardFile.CreateCardFile(Context, addressbookFolderId, fileName); } public async Task<IFolder> CreateFolderAsync(string name) { throw new DavException("Not allowed.", DavStatus.NOT_ALLOWED); } public override async Task MoveToAsync(IItemCollection destFolder, string destName, MultistatusException multistatus) { // Here we support only addressbooks renaming. Check that user has permissions to write. string sql = @"UPDATE [card_AddressbookFolder] SET Name=@Name WHERE [AddressbookFolderId]=@AddressbookFolderId AND [AddressbookFolderId] IN (SELECT [AddressbookFolderId] FROM [card_Access] WHERE [UserId]=@UserId AND [Write] = 1)"; if (await Context.ExecuteNonQueryAsync(sql, "@Name" , destName , "@UserId" , Context.UserId , "@AddressbookFolderId", addressbookFolderId) < 1) { throw new DavException("Item not found or you do not have enough permissions to complete this operation.", DavStatus.FORBIDDEN); } } public override async Task DeleteAsync(MultistatusException multistatus) { // Delete address book and all vCards associated with it. Check that user has permissions to delete. string sql = @"DELETE FROM [card_AddressbookFolder] WHERE [AddressbookFolderId]=@AddressbookFolderId AND [AddressbookFolderId] IN (SELECT [AddressbookFolderId] FROM [card_Access] WHERE [UserId]=@UserId AND [Owner] = 1)"; if (await Context.ExecuteNonQueryAsync(sql, "@UserId" , Context.UserId , "@AddressbookFolderId", addressbookFolderId) < 1) { throw new DavException("Item not found or you do not have enough permissions to complete this operation.", DavStatus.FORBIDDEN); } } public override async Task<IEnumerable<PropertyValue>> GetPropertiesAsync(IList<PropertyName> names, bool allprop) { IList<PropertyValue> propVals = await GetPropertyValuesAsync( "SELECT [Name], [Namespace], [PropVal] FROM [card_AddressbookFolderProperty] WHERE [AddressbookFolderId] = @AddressbookFolderId", "@AddressbookFolderId", addressbookFolderId); if (allprop) { return propVals; } else { IList<PropertyValue> requestedPropVals = new List<PropertyValue>(); foreach (PropertyValue p in propVals) { if (names.Contains(p.QualifiedName)) { requestedPropVals.Add(p); } } return requestedPropVals; } } public override async Task UpdatePropertiesAsync( IList<PropertyValue> setProps, IList<PropertyName> delProps, MultistatusException multistatus) { foreach (PropertyValue p in setProps) { await SetPropertyAsync(p); // create or update property } foreach (PropertyName p in delProps) { await RemovePropertyAsync(p.Name, p.Namespace); } } private async Task<IList<PropertyValue>> GetPropertyValuesAsync(string command, params object[] prms) { List<PropertyValue> l = new List<PropertyValue>(); using (SqlDataReader reader = await Context.ExecuteReaderAsync(command, prms)) { while (reader.Read()) { string name = reader.GetString(reader.GetOrdinal("Name")); string ns = reader.GetString(reader.GetOrdinal("Namespace")); string value = reader.GetString(reader.GetOrdinal("PropVal")); l.Add(new PropertyValue(new PropertyName(name, ns), value)); } } return l; } private async Task SetPropertyAsync(PropertyValue prop) { string selectCommand = @"SELECT Count(*) FROM [card_AddressbookFolderProperty] WHERE [AddressbookFolderId] = @AddressbookFolderId AND [Name] = @Name AND [Namespace] = @Namespace"; int count = await Context.ExecuteScalarAsync<int>( selectCommand, "@AddressbookFolderId" , addressbookFolderId, "@Name" , prop.QualifiedName.Name, "@Namespace" , prop.QualifiedName.Namespace); // insert if (count == 0) { string insertCommand = @"INSERT INTO [card_AddressbookFolderProperty] ([AddressbookFolderId], [Name], [Namespace], [PropVal]) VALUES(@AddressbookFolderId, @Name, @Namespace, @PropVal)"; await Context.ExecuteNonQueryAsync( insertCommand, "@PropVal" , prop.Value, "@AddressbookFolderId" , addressbookFolderId, "@Name" , prop.QualifiedName.Name, "@Namespace" , prop.QualifiedName.Namespace); } else { // update string command = @"UPDATE [card_AddressbookFolderProperty] SET [PropVal] = @PropVal WHERE [AddressbookFolderId] = @AddressbookFolderId AND [Name] = @Name AND [Namespace] = @Namespace"; await Context.ExecuteNonQueryAsync( command, "@PropVal" , prop.Value, "@AddressbookFolderId" , addressbookFolderId, "@Name" , prop.QualifiedName.Name, "@Namespace" , prop.QualifiedName.Namespace); } } private async Task RemovePropertyAsync(string name, string ns) { string command = @"DELETE FROM [card_AddressbookFolderProperty] WHERE [AddressbookFolderId] = @AddressbookFolderId AND [Name] = @Name AND [Namespace] = @Namespace"; await Context.ExecuteNonQueryAsync( command, "@AddressbookFolderId" , addressbookFolderId, "@Name" , name, "@Namespace" , ns); } public Task SetOwnerAsync(IPrincipal value) { throw new DavException("Not implemented.", DavStatus.NOT_IMPLEMENTED); } public async Task<IPrincipal> GetOwnerAsync() { DataRow rowOwner = rowsAccess.FirstOrDefault(x => x.Field<bool>("Owner") == true); if (rowOwner == null) return null; return await Acl.User.GetUserAsync(Context, rowOwner.Field<string>("UserId")); } public Task SetGroupAsync(IPrincipal value) { throw new DavException("Group cannot be set", DavStatus.FORBIDDEN); } public async Task<IPrincipal> GetGroupAsync() { return null; // Groups are not supported. } public async Task<IEnumerable<SupportedPrivilege>> GetSupportedPrivilegeSetAsync() { return new[] { new SupportedPrivilege { Privilege = Privilege.Read, IsAbstract = false, DescriptionLanguage = "en", Description = "Allows or denies the user the ability to read content and properties of files/folders." }, new SupportedPrivilege { Privilege = Privilege.Write, IsAbstract = false, DescriptionLanguage = "en", Description = "Allows or denies locking an item or modifying the content, properties, or membership of a collection." } }; } public async Task<IEnumerable<Privilege>> GetCurrentUserPrivilegeSetAsync() { DataRow rowAccess = rowsAccess.FirstOrDefault(x => x.Field<string>("UserId")== Context.UserId); if (rowAccess == null) return null; List<Privilege> privileges = new List<Privilege>(); if (rowAccess.Field<bool>("Read")) privileges.Add(Privilege.Read); if (rowAccess.Field<bool>("Write")) privileges.Add(Privilege.Write); return privileges; } public async Task<IEnumerable<ReadAce>> GetAclAsync(IList<PropertyName> propertyNames) { IList<ReadAce> aceList = new List<ReadAce>(); foreach (DataRow rowAccess in rowsAccess) { ReadAce ace = new ReadAce(); ace.Principal = await Acl.User.GetUserAsync(Context, rowAccess.Field<string>("UserId")); if (rowAccess.Field<bool>("Read")) ace.GrantPrivileges.Add(Privilege.Read); if (rowAccess.Field<bool>("Write")) ace.GrantPrivileges.Add(Privilege.Write); ace.IsProtected = rowAccess.Field<bool>("Owner"); aceList.Add(ace); } return aceList; } public Task SetAclAsync(IList<WriteAce> aces) { throw new DavException("Not implemented.", DavStatus.NOT_IMPLEMENTED); } public async Task<AclRestriction> GetAclRestrictionsAsync() { return new AclRestriction { NoInvert = true, GrantOnly = true }; } public async Task<IEnumerable<IHierarchyItem>> GetInheritedAclSetAsync() { return new IHierarchyItem[] { }; } public async Task<IEnumerable<IPrincipalFolder>> GetPrincipalCollectionSetAsync() { return new IPrincipalFolder[] { new Acl.UsersFolder(Context) }; } public async Task<IPrincipal> ResolveWellKnownPrincipalAsync(WellKnownPrincipal wellKnownPrincipal) { return null; } public Task<IEnumerable<IAclHierarchyItem>> GetItemsByPropertyAsync(MatchBy matchBy, IList<PropertyName> props) { throw new DavException("Not implemented.", DavStatus.NOT_IMPLEMENTED); } }