From c107cfbbc54da2902f45ef91991cd7d963f7fd56 Mon Sep 17 00:00:00 2001 From: Szabo Bogdan Date: Sun, 19 Apr 2015 23:52:45 +0300 Subject: [PATCH] Added CalDav collection plugin --- source/vibedav/acldav.d | 40 +------- source/vibedav/base.d | 55 ++++++++++- source/vibedav/caldav.d | 153 ++++++++++++++-------------- source/vibedav/davresource.d | 187 +++++++++++++++++------------------ source/vibedav/filedav.d | 3 +- 5 files changed, 230 insertions(+), 208 deletions(-) diff --git a/source/vibedav/acldav.d b/source/vibedav/acldav.d index 23f9da9..093c042 100644 --- a/source/vibedav/acldav.d +++ b/source/vibedav/acldav.d @@ -130,56 +130,24 @@ class ACLDavResourcePlugin : ACLDavProperties, IDavResourcePlugin { } } -class ACLDavPlugin : IDavPlugin { +class ACLDavPlugin : BaseDavPlugin { private IDav _dav; this(IDav dav) { - _dav = dav; + super(dav); } - bool exists(URL url, string username) { - return false; - } - - bool canCreateCollection(URL url, string username) { - return false; - } - - bool canCreateResource(URL url, string username) { - return false; - } - - void removeResource(URL url, string username) { - throw new DavException(HTTPStatus.internalServerError, "Can't remove resource."); - } - - DavResource getResource(URL url, string username) { - throw new DavException(HTTPStatus.internalServerError, "Can't get resource."); - } - - DavResource createCollection(URL url, string username) { - throw new DavException(HTTPStatus.internalServerError, "Can't create collection."); - } - - DavResource createResource(URL url, string username) { - throw new DavException(HTTPStatus.internalServerError, "Can't create resource."); - } - - void bindResourcePlugins(ref DavResource resource) { + override void bindResourcePlugins(DavResource resource) { resource.registerPlugin(new ACLDavResourcePlugin); } @property { - IDav dav() { - return _dav; - } - string name() { return "ACLDavPlugin"; } - string[] support(URL url, string username) { + override string[] support(URL url, string username) { if(matchPluginUrl(url)) return [ "access-control" ]; diff --git a/source/vibedav/base.d b/source/vibedav/base.d index de525f2..1771d52 100644 --- a/source/vibedav/base.d +++ b/source/vibedav/base.d @@ -67,7 +67,7 @@ interface IDavResourceAccess { DavResource createCollection(URL url, string username); DavResource createResource(URL url, string username); - void bindResourcePlugins(ref DavResource resource); + void bindResourcePlugins(DavResource resource); } interface IDavPlugin : IDavResourceAccess { @@ -84,6 +84,55 @@ interface IDavPluginHub { bool hasPlugin(string name); } + +abstract class BaseDavPlugin : IDavPlugin { + private IDav _dav; + + this(IDav dav) { + _dav = dav; + } + + bool exists(URL url, string username) { + return false; + } + + bool canCreateCollection(URL url, string username) { + return false; + } + + bool canCreateResource(URL url, string username) { + return false; + } + + void removeResource(URL url, string username) { + throw new DavException(HTTPStatus.internalServerError, "Can't remove resource."); + } + + DavResource getResource(URL url, string username) { + throw new DavException(HTTPStatus.internalServerError, "Can't get resource."); + } + + DavResource createCollection(URL url, string username) { + throw new DavException(HTTPStatus.internalServerError, "Can't create collection."); + } + + DavResource createResource(URL url, string username) { + throw new DavException(HTTPStatus.internalServerError, "Can't create resource."); + } + + void bindResourcePlugins(DavResource resource) { } + + @property { + IDav dav() { + return _dav; + } + + string[] support(URL url, string username) { + return []; + } + } +} + interface IDav : IDavResourceAccess, IDavPluginHub { void options(DavRequest request, DavResponse response); void propfind(DavRequest request, DavResponse response); @@ -235,6 +284,8 @@ class Dav : IDav { depth--; } + list ~= tmpList; + return list; } @@ -263,7 +314,7 @@ class Dav : IDav { } - void bindResourcePlugins(ref DavResource resource) { + void bindResourcePlugins(DavResource resource) { foreach(plugin; plugins) plugin.bindResourcePlugins(resource); } diff --git a/source/vibedav/caldav.d b/source/vibedav/caldav.d index acdd590..88612a7 100644 --- a/source/vibedav/caldav.d +++ b/source/vibedav/caldav.d @@ -415,7 +415,7 @@ private bool matchPluginUrl(URL url, string username) { return false; } -class CalDavResourcePlugin : IDavResourcePlugin, ICalDavProperties, IDavReportSetProperties { +class CalDavResourcePlugin : BaseDavResourcePlugin, ICalDavProperties, IDavReportSetProperties { string[] calendarHomeSet(DavResource resource) { if(matchPluginUrl(resource.url, resource.username)) @@ -452,70 +452,100 @@ class CalDavResourcePlugin : IDavResourcePlugin, ICalDavProperties, IDavReportSe return []; } - bool canSetContent(DavResource resource) { - return false; + override { + bool canGetProperty(DavResource resource, string name) { + if(matchPluginUrl(resource.url, resource.username) && hasDavInterfaceProperty!ICalDavProperties(name)) + return true; + + if(matchPluginUrl(resource.url, resource.username) && hasDavInterfaceProperty!IDavReportSetProperties(name)) + return true; + + return false; + } + + DavProp property(DavResource resource, string name) { + if(!matchPluginUrl(resource.url, resource.username)) + throw new DavException(HTTPStatus.internalServerError, "Can't get property."); + + if(hasDavInterfaceProperty!ICalDavProperties(name)) + return getDavInterfaceProperty!ICalDavProperties(name, this, resource); + + if(hasDavInterfaceProperty!IDavReportSetProperties(name)) + return getDavInterfaceProperty!IDavReportSetProperties(name, this, resource); + + throw new DavException(HTTPStatus.internalServerError, "Can't get property."); + } } - bool canGetStream(DavResource resource) { - return false; + @property { + string name() { + return "ResourceBasicProperties"; + } } +} - bool canSetProperty(DavResource resource, string name) { - return false; + +class CalDavCollectionPlugin : BaseDavResourcePlugin, ICalDavCollectionProperties { + + string calendarDescription(DavResource resource) { + return resource.name; } - bool canRemoveProperty(DavResource resource, string name) { - return false; + TimeZone calendarTimezone(DavResource resource) { + TimeZone t; + return t; } - bool canGetProperty(DavResource resource, string name) { - if(matchPluginUrl(resource.url, resource.username) && hasDavInterfaceProperty!ICalDavProperties(name)) - return true; + string[] supportedCalendarComponentSet(DavResource resource) { + return ["VEVENT", "VTODO", "VJOURNAL", "VFREEBUSY", "VTIMEZONE", "VALARM"]; + } - if(matchPluginUrl(resource.url, resource.username) && hasDavInterfaceProperty!IDavReportSetProperties(name)) - return true; + string[string][] supportedCalendarData(DavResource resource) { + string[string][] list; - return false; - } + list ~= [["content-type": "text/calendar", "version": "2.0"]]; - bool[string] getChildren(DavResource resource) { - bool[string] list; return list; } - void setContent(DavResource resource, const ubyte[] content) { - throw new DavException(HTTPStatus.internalServerError, "Can't set content."); + ulong maxResourceSize(DavResource resource) { + return ulong.max; } - void setContent(DavResource resource, InputStream content, ulong size) { - throw new DavException(HTTPStatus.internalServerError, "Can't set content."); + SysTime minDateTime(DavResource resource) { + return SysTime.min; } - InputStream stream(DavResource resource) { - throw new DavException(HTTPStatus.internalServerError, "Can't get stream."); + SysTime maxDateTime(DavResource resource) { + return SysTime.max; } - void copyPropertiesTo(URL source, URL destination) { } + ulong maxInstances(DavResource resource) { + return ulong.max; + } - DavProp property(DavResource resource, string name) { - if(!matchPluginUrl(resource.url, resource.username)) - throw new DavException(HTTPStatus.internalServerError, "Can't get property."); + ulong maxAttendeesPerInstance(DavResource resource) { + return ulong.max; + } - if(hasDavInterfaceProperty!ICalDavProperties(name)) - return getDavInterfaceProperty!ICalDavProperties(name, this, resource); + override { - if(hasDavInterfaceProperty!IDavReportSetProperties(name)) - return getDavInterfaceProperty!IDavReportSetProperties(name, this, resource); + bool canGetProperty(DavResource resource, string name) { + if(matchPluginUrl(resource.url, resource.username) && hasDavInterfaceProperty!ICalDavCollectionProperties(name)) + return true; - throw new DavException(HTTPStatus.internalServerError, "Can't get property."); - } + return false; + } - HTTPStatus setProperty(DavResource resource, string name, DavProp prop) { - throw new DavException(HTTPStatus.internalServerError, "Can't set property."); - } + DavProp property(DavResource resource, string name) { + if(!matchPluginUrl(resource.url, resource.username)) + throw new DavException(HTTPStatus.internalServerError, "Can't get property."); + + if(hasDavInterfaceProperty!ICalDavCollectionProperties(name)) + return getDavInterfaceProperty!ICalDavCollectionProperties(name, this, resource); - HTTPStatus removeProperty(DavResource resource, string name) { - throw new DavException(HTTPStatus.internalServerError, "Can't remove property."); + throw new DavException(HTTPStatus.internalServerError, "Can't get property."); + } } @property { @@ -525,56 +555,33 @@ class CalDavResourcePlugin : IDavResourcePlugin, ICalDavProperties, IDavReportSe } } -class CalDavPlugin : IDavPlugin { - - private IDav _dav; +class CalDavPlugin : BaseDavPlugin { this(IDav dav) { - _dav = dav; + super(dav); } - bool exists(URL url, string username) { - return false; - } - bool canCreateCollection(URL url, string username) { - return false; - } + override void bindResourcePlugins(DavResource resource) { - bool canCreateResource(URL url, string username) { - return false; - } - - void removeResource(URL url, string username) { - throw new DavException(HTTPStatus.internalServerError, "Can't remove resource."); - } - - DavResource getResource(URL url, string username) { - throw new DavException(HTTPStatus.internalServerError, "Can't get resource."); - } - - DavResource createCollection(URL url, string username) { - throw new DavException(HTTPStatus.internalServerError, "Can't create collection."); - } - - DavResource createResource(URL url, string username) { - throw new DavException(HTTPStatus.internalServerError, "Can't create resource."); - } + if(!matchPluginUrl(resource.url, resource.username)) + return; - void bindResourcePlugins(ref DavResource resource) { resource.registerPlugin(new CalDavResourcePlugin); + + if(resource.isCollection && resource.url.path.toString.stripSlashes != "principals/" ~ resource.username ~ "/calendars") { + resource.resourceType ~= "calendar:urn:ietf:params:xml:ns:caldav"; + resource.registerPlugin(new CalDavCollectionPlugin); + } } @property { - IDav dav() { - return _dav; - } string name() { return "CalDavPlugin"; } - string[] support(URL url, string username) { + override string[] support(URL url, string username) { if(matchPluginUrl(url, username)) return [ "calendar-access" ]; diff --git a/source/vibedav/davresource.d b/source/vibedav/davresource.d index a1170b0..9aba6f7 100644 --- a/source/vibedav/davresource.d +++ b/source/vibedav/davresource.d @@ -288,6 +288,9 @@ interface IDavResourceProperties { @ResourceProperty("resourcetype", "DAV:") @ResourcePropertyTagName() string[] resourceType(DavResource resource); + + @ResourceProperty("displayname", "DAV:") + string displayName(DavResource resource); } interface IDavResourceExtendedProperties { @@ -324,37 +327,8 @@ interface IDavResourcePlugin { } } -interface IDavResourcePluginHub { - void registerPlugin(IDavResourcePlugin plugin); - bool hasPlugin(string name); -} - - -class ResourceBasicProperties : IDavResourcePlugin, IDavResourceProperties { - - SysTime creationDate(DavResource resource) { - return resource.creationDate; - } - - SysTime lastModified(DavResource resource) { - return resource.lastModified; - } - - string eTag(DavResource resource) { - return resource.eTag; - } - - string contentType(DavResource resource) { - return resource.contentType; - } - ulong contentLength(DavResource resource) { - return resource.contentLength; - } - - string[] resourceType(DavResource resource) { - return resource.resourceType; - } +abstract class BaseDavResourcePlugin : IDavResourcePlugin { bool canSetContent(DavResource resource) { return false; @@ -373,9 +347,6 @@ class ResourceBasicProperties : IDavResourcePlugin, IDavResourceProperties { } bool canGetProperty(DavResource resource, string name) { - if(hasDavInterfaceProperty!IDavResourceProperties(name)) - return true; - return false; } @@ -396,14 +367,9 @@ class ResourceBasicProperties : IDavResourcePlugin, IDavResourceProperties { throw new DavException(HTTPStatus.internalServerError, "Can't get stream."); } - void copyPropertiesTo(URL source, URL destination) { - - } + void copyPropertiesTo(URL source, URL destination) { } DavProp property(DavResource resource, string name) { - if(canGetProperty(resource, name)) - return getDavInterfaceProperty!IDavResourceProperties(name, this, resource); - throw new DavException(HTTPStatus.internalServerError, "Can't get property."); } @@ -414,91 +380,122 @@ class ResourceBasicProperties : IDavResourcePlugin, IDavResourceProperties { HTTPStatus removeProperty(DavResource resource, string name) { throw new DavException(HTTPStatus.internalServerError, "Can't remove property."); } +} - @property { - string name() { - return "ResourceBasicProperties"; - } - } +interface IDavResourcePluginHub { + void registerPlugin(IDavResourcePlugin plugin); + bool hasPlugin(string name); } -class ResourceCustomProperties : IDavResourcePlugin { - private static DavProp[string][string] properties; +class ResourceBasicProperties : BaseDavResourcePlugin, IDavResourceProperties { - bool canSetContent(DavResource resource) { - return false; + SysTime creationDate(DavResource resource) { + return resource.creationDate; } - bool canGetStream(DavResource resource) { - return false; + SysTime lastModified(DavResource resource) { + return resource.lastModified; } - bool canGetProperty(DavResource resource, string name) { - string u = resource.url.toString; - - if(u !in properties) - return false; - - if(name !in properties[u]) - return false; - - return true; + string eTag(DavResource resource) { + return resource.eTag; } - bool canSetProperty(DavResource resource, string name) { - return true; + string contentType(DavResource resource) { + return resource.contentType; } - bool canRemoveProperty(DavResource resource, string name) { - return canGetProperty(resource, name); + ulong contentLength(DavResource resource) { + return resource.contentLength; } - bool[string] getChildren(DavResource resource) { - bool[string] list; - return list; + string[] resourceType(DavResource resource) { + return resource.resourceType; } - void setContent(DavResource resource, const(ubyte[]) content) { - throw new DavException(HTTPStatus.internalServerError, "Can't set content."); + string displayName(DavResource resource) { + return resource.name; } - void setContent(DavResource resource, InputStream content, ulong size) { - throw new DavException(HTTPStatus.internalServerError, "Can't set content."); - } - InputStream stream(DavResource resource) { - throw new DavException(HTTPStatus.internalServerError, "Can't get stream."); + override { + bool canGetProperty(DavResource resource, string name) { + if(hasDavInterfaceProperty!IDavResourceProperties(name)) + return true; + + return false; + } + + DavProp property(DavResource resource, string name) { + if(canGetProperty(resource, name)) + return getDavInterfaceProperty!IDavResourceProperties(name, this, resource); + + throw new DavException(HTTPStatus.internalServerError, "Can't get property."); + } } - void copyPropertiesTo(URL source, URL destination) { - if(source.toString in properties) - properties[destination.toString] = properties[source.toString]; + @property { + string name() { + return "ResourceBasicProperties"; + } } +} - DavProp property(DavResource resource, string name) { - if(canGetProperty(resource, name)) - return properties[resource.url.toString][name]; +class ResourceCustomProperties : BaseDavResourcePlugin { - throw new DavException(HTTPStatus.internalServerError, "Can't get property."); - } + private static DavProp[string][string] properties; - HTTPStatus setProperty(DavResource resource, string name, DavProp prop) { - if(resource.url.toString !in properties) { - DavProp[string] list; - properties[resource.url.toString] = list; + override { + bool canGetProperty(DavResource resource, string name) { + string u = resource.url.toString; + + if(u !in properties) + return false; + + if(name !in properties[u]) + return false; + + return true; } - properties[resource.url.toString][name] = prop; + bool canSetProperty(DavResource resource, string name) { + return true; + } - return HTTPStatus.ok; - } + bool canRemoveProperty(DavResource resource, string name) { + return canGetProperty(resource, name); + } - HTTPStatus removeProperty(DavResource resource, string name) { - if(canGetProperty(resource, name)) - properties[resource.url.toString].remove(name); + void copyPropertiesTo(URL source, URL destination) { + if(source.toString in properties) + properties[destination.toString] = properties[source.toString]; + } + + DavProp property(DavResource resource, string name) { + if(canGetProperty(resource, name)) + return properties[resource.url.toString][name]; + + throw new DavException(HTTPStatus.internalServerError, "Can't get property."); + } + + HTTPStatus setProperty(DavResource resource, string name, DavProp prop) { + if(resource.url.toString !in properties) { + DavProp[string] list; + properties[resource.url.toString] = list; + } + + properties[resource.url.toString][name] = prop; - return HTTPStatus.notFound; + return HTTPStatus.ok; + } + + HTTPStatus removeProperty(DavResource resource, string name) { + if(canGetProperty(resource, name)) + properties[resource.url.toString].remove(name); + + return HTTPStatus.notFound; + } } @property { @@ -520,6 +517,7 @@ class DavResource : IDavResourcePluginHub { string contentType; ulong contentLength; string[] resourceType; + string name; protected { IDavResourcePlugin[] plugins; @@ -581,9 +579,6 @@ class DavResource : IDavResourcePluginHub { } @property { - string name() { - return href.baseName; - } string fullURL() { return url.toString; diff --git a/source/vibedav/filedav.d b/source/vibedav/filedav.d index 5a82721..6520a92 100644 --- a/source/vibedav/filedav.d +++ b/source/vibedav/filedav.d @@ -338,6 +338,7 @@ class FileDav : IDavPlugin { resource.eTag = eTag(path); resource.contentType = getMimeTypeForFile(path); resource.contentLength = contentLength(path); + resource.name = baseName(path); if(path.isDir) resource.resourceType ~= "collection:DAV:"; @@ -407,7 +408,7 @@ class FileDav : IDavPlugin { return getResource(url, username); } - void bindResourcePlugins(ref DavResource resource) { + void bindResourcePlugins(DavResource resource) { if(resource.isCollection) resource.registerPlugin(new DirectoryResourcePlugin(baseUrlPath, basePath)); else