Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add autoconfigure feature for Kolab users #232

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
8 changes: 7 additions & 1 deletion CalDavSynchronizer/CalDavSynchronizer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,8 @@
</ItemGroup>
<ItemGroup>
<Content Include="LICENSE.txt" />
<None Include="Resources\TasklistReadWrite.ico" />
<None Include="Resources\TasklistReadOnly.ico" />
<Resource Include="Resources\ProfileLogos\logo_kolab.png" />
<Resource Include="Resources\ProfileLogos\logo_swisscom.png" />
<Resource Include="Resources\ProfileLogos\logo_iCloud.png" />
Expand Down Expand Up @@ -940,6 +942,10 @@
<Resource Include="Resources\Import.png" />
<Resource Include="Resources\ClearCache.png" />
<None Include="Resources\ApplicationLogoLarge.png" />
<None Include="Resources\AddressbookReadOnly.ico" />
<None Include="Resources\AddressbookReadWrite.ico" />
<None Include="Resources\CalendarReadOnly.ico" />
<None Include="Resources\CalendarReadWrite.ico" />
<Content Include="Resources\LogoBanner.bmp" />
<Resource Include="Resources\ExpandAll.png" />
<Resource Include="Resources\ProfileLogos\logo_nextcloud.png" />
Expand Down Expand Up @@ -1090,7 +1096,7 @@
</ManifestKeyFile>
</PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>99D12A4419EA17C4DB056A34FEDAFDC1A576A921</ManifestCertificateThumbprint>
<ManifestCertificateThumbprint>1420A545B90CAFB4925D2F952464AA1F36A0AA27</ManifestCertificateThumbprint>
</PropertyGroup>
<!-- Include the build rules for a C# project. -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Expand Down
329 changes: 329 additions & 0 deletions CalDavSynchronizer/ComponentContainer.cs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions CalDavSynchronizer/Contracts/GeneralOption.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class GeneralOptions
public int ThresholdForProgressDisplay { get; set; }
public int MaxSucessiveWarnings { get; set; }
public string CultureName { get; set; }
public bool AutoconfigureKolab { get; set; }

public GeneralOptions Clone()
{
Expand Down
4 changes: 3 additions & 1 deletion CalDavSynchronizer/DataAccess/AddressBookData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ public class AddressBookData
{
public Uri Uri { get; }
public string Name { get; }
public bool ReadOnly { get; }

public AddressBookData (Uri uri, string name)
public AddressBookData (Uri uri, string name, bool readOnly = false)
{
Uri = uri;
Name = name;
ReadOnly = readOnly;
}
}
}
14 changes: 12 additions & 2 deletions CalDavSynchronizer/DataAccess/CalDavDataAccess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ public async Task<CalDavResources> GetUserResourcesNoThrow (bool useWellKnownUrl
XmlNode homeSetNode = calendarHomeSetProperties.XmlDocument.SelectSingleNode ("/D:multistatus/D:response/D:propstat/D:prop/C:calendar-home-set", calendarHomeSetProperties.XmlNamespaceManager);
if (homeSetNode != null && homeSetNode.HasChildNodes)
{
// https://tools.ietf.org/html/rfc6638#section-9.2
XmlNode scheduleDefaultCalendarNode = calendarHomeSetProperties.XmlDocument.SelectSingleNode("/D:multistatus/D:response/D:propstat/D:prop/C:schedule-default-calendar-URL", calendarHomeSetProperties.XmlNamespaceManager);
String scheduleDefaultCalendarPath = scheduleDefaultCalendarNode == null ? "" :
scheduleDefaultCalendarNode.InnerText.EndsWith("/") ? scheduleDefaultCalendarNode.InnerText : scheduleDefaultCalendarNode.InnerText + "/";
bool isFirstCalendar = true;
foreach (XmlNode homeSetNodeHref in homeSetNode.ChildNodes)
{
if (!string.IsNullOrEmpty (homeSetNodeHref.InnerText))
Expand Down Expand Up @@ -182,16 +187,20 @@ public async Task<CalDavResources> GetUserResourcesNoThrow (bool useWellKnownUrl
if (supportedComponentsNode != null)
{
var path = urlNode.InnerText.EndsWith ("/") ? urlNode.InnerText : urlNode.InnerText + "/";
var uri = new Uri(calendarDocument.DocumentUri, path);
bool ro = await IsReadOnly(uri);

if (supportedComponentsNode.InnerXml.Contains ("VEVENT"))
{
bool isDefault = (scheduleDefaultCalendarNode != null && scheduleDefaultCalendarPath == path || scheduleDefaultCalendarNode == null && isFirstCalendar);
isFirstCalendar = false;
var displayName = string.IsNullOrEmpty (displayNameNode.InnerText) ? "Default Calendar" : displayNameNode.InnerText;
calendars.Add (new CalendarData (new Uri (calendarDocument.DocumentUri, path), displayName, calendarColor));
calendars.Add (new CalendarData (uri, displayName, calendarColor, ro, isDefault));
}
if (supportedComponentsNode.InnerXml.Contains ("VTODO"))
{
var displayName = string.IsNullOrEmpty (displayNameNode.InnerText) ? "Default Tasks" : displayNameNode.InnerText;
taskLists.Add (new TaskListData (new Uri (calendarDocument.DocumentUri, path).ToString(), displayName));
taskLists.Add (new TaskListData (uri.ToString(), displayName, ro));
}
}
}
Expand Down Expand Up @@ -233,6 +242,7 @@ private Task<XmlDocumentWithNamespaceManager> GetCalendarHomeSet (Uri url)
<D:propfind xmlns:D=""DAV:"" xmlns:C=""urn:ietf:params:xml:ns:caldav"">
<D:prop>
<C:calendar-home-set/>
<C:schedule-default-calendar-URL/>
</D:prop>
</D:propfind>
"
Expand Down
6 changes: 5 additions & 1 deletion CalDavSynchronizer/DataAccess/CalendarData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ public class CalendarData
public Uri Uri { get; }
public string Name { get; }
public ArgbColor? Color { get; }
public bool ReadOnly { get; }
public bool IsDefault { get; }

public CalendarData (Uri uri, string name, ArgbColor? color)
public CalendarData (Uri uri, string name, ArgbColor? color, bool readOnly = false, bool isDefault = false)
{
Uri = uri;
Name = name;
Color = color;
ReadOnly = readOnly;
IsDefault = isDefault;
}
}
}
4 changes: 3 additions & 1 deletion CalDavSynchronizer/DataAccess/CardDavDataAccess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ public async Task<IReadOnlyList<AddressBookData>> GetUserAddressBooksNoThrow (bo
{
var path = urlNode.InnerText.EndsWith ("/") ? urlNode.InnerText : urlNode.InnerText + "/";
var displayName = string.IsNullOrEmpty (displayNameNode.InnerText) ? "Default Addressbook" : displayNameNode.InnerText;
addressbooks.Add (new AddressBookData (new Uri (addressBookDocument.DocumentUri, path), displayName));
var uri = new Uri(addressBookDocument.DocumentUri, path);
bool ro = await IsReadOnly(uri);
addressbooks.Add (new AddressBookData (uri, displayName, ro));
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion CalDavSynchronizer/DataAccess/GeneralOptionsDataAccess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public class GeneralOptionsDataAccess : IGeneralOptionsDataAccess
private const string ValueNameMaxSucessiveWarnings = "MaxSucessiveWarnings";

private const string ValueNameCultureName = "CultureName";
private const string ValueNameAutoconfigureKolab = "AutoconfigureKolab";

public GeneralOptions LoadOptions ()
{
Expand Down Expand Up @@ -102,7 +103,8 @@ public GeneralOptions LoadOptions ()
ShowProgressBar = (int) (key.GetValue (ValueNameShowProgressBar) ?? Convert.ToInt32 (Boolean.Parse (ConfigurationManager.AppSettings["showProgressBar"] ?? bool.TrueString))) != 0,
ThresholdForProgressDisplay = (int) (key.GetValue (ValueNameThresholdForProgressDisplay) ?? int.Parse(ConfigurationManager.AppSettings["loadOperationThresholdForProgressDisplay"] ?? "50")),
MaxSucessiveWarnings = (int) (key.GetValue (ValueNameMaxSucessiveWarnings) ?? 2),
CultureName = GetCultureName(key)
CultureName = GetCultureName(key),
AutoconfigureKolab = (int)(key.GetValue(ValueNameAutoconfigureKolab) ?? 0) != 0
};
}
}
Expand Down
4 changes: 3 additions & 1 deletion CalDavSynchronizer/DataAccess/TaskListData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ public class TaskListData
{
public string Id { get; }
public string Name { get; }
public bool ReadOnly { get; }

public TaskListData (string id, string name)
public TaskListData (string id, string name, bool readOnly = false)
{
Id = id;
Name = name;
ReadOnly = readOnly;
}
}
}
42 changes: 42 additions & 0 deletions CalDavSynchronizer/DataAccess/WebDavDataAccess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,48 @@ public async Task<AccessPrivileges> GetPrivileges ()
return privileges;
}

// Only consider resource as read-only if we are sure. That is:
// - we can query ACL property
// - we see a READ privilage, but no WRITE privilege
public async Task<bool> IsReadOnly(Uri resourceUrl)
{
try
{
var document = await _webDavClient.ExecuteWebDavRequestAndReadResponse(
resourceUrl,
"PROPFIND",
0,
null,
null,
"application/xml",
@"<?xml version='1.0'?>
<D:propfind xmlns:D=""DAV:"" xmlns:C=""urn:ietf:params:xml:ns:caldav"" xmlns:E=""http://apple.com/ns/ical/"">
<D:prop>
<D:acl />
</D:prop>
</D:propfind>
"
);

if (
document.XmlDocument.SelectSingleNode("/D:multistatus/D:response/D:propstat/D:prop/D:acl/D:ace/D:grant/D:privilege/D:read", document.XmlNamespaceManager) != null
&& document.XmlDocument.SelectSingleNode("/D:multistatus/D:response/D:propstat/D:prop/D:acl/D:ace/D:grant/D:privilege/D:write", document.XmlNamespaceManager) == null
)
{
return true;
}
else
{
return false;
}
}
catch (Exception x)
{
s_logger.Error(null, x);
return false;
}
}

protected async Task<string> GetEtag (Uri absoluteEntityUrl)
{
var headers = await _webDavClient.ExecuteWebDavRequestAndReturnResponseHeaders (absoluteEntityUrl, "GET", null, null, null, null, null);
Expand Down
27 changes: 27 additions & 0 deletions CalDavSynchronizer/Globalization/StringResources.de-DE.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1404,4 +1404,31 @@ Andere Protokolle können mittels protocol: address hinzugefügt werden</value>
<data name="Map Outlook Public flag to default instead of PUBLIC" xml:space="preserve">
<value>Synchronisiere öffentliche Outlook Termine auf Standard Sichtbarkeit anstelle von PUBLIC</value>
</data>
<data name="Deleted" xml:space="preserve">
<value>Gelöscht</value>
</data>
<data name="local changes made in Outlook and remote changes from the server are merged." xml:space="preserve">
<value>Änderungen in Outlook und Änderungen vom Server werden zusammengeführt.</value>
</data>
<data name="local changes made in Outlook are discarded and replaced by data from the server." xml:space="preserve">
<value>Änderungen in Outlook werden verworfen und durch Daten vom Server ersetzt.</value>
</data>
<data name="Read-only address book" xml:space="preserve">
<value>Adressbuch mit Nur-Lese-Zugriff</value>
</data>
<data name="Read-only calendar" xml:space="preserve">
<value>Kalender mit Nur-Lese-Zugriff</value>
</data>
<data name="Read-only task list" xml:space="preserve">
<value>Aufgabenliste mit Nur-Lese-Zugriff</value>
</data>
<data name="Read-write address book" xml:space="preserve">
<value>Adressbuch mit Lese- und Schreibzugriff</value>
</data>
<data name="Read-write calendar" xml:space="preserve">
<value>Kalender mit Lese- und Schreibzugriff</value>
</data>
<data name="Read-write task list" xml:space="preserve">
<value>Aufgabenliste mit Lese- und Schreibzugriff</value>
</data>
</root>
3 changes: 3 additions & 0 deletions CalDavSynchronizer/Globalization/StringResources.ru-RU.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1342,4 +1342,7 @@
<data name="Map Outlook Public flag to default instead of PUBLIC" xml:space="preserve">
<value>Установите флаг общедоступный MS Outlook по умолчанию вместо PUBLIC</value>
</data>
<data name="Deleted" xml:space="preserve">
<value>удаленный</value>
</data>
</root>
62 changes: 61 additions & 1 deletion CalDavSynchronizer/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions CalDavSynchronizer/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,22 @@
<data name="ApplicationLogoLarge" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ApplicationLogoLarge.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="AddressbookReadOnly" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\AddressbookReadOnly.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="AddressbookReadWrite" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\AddressbookReadWrite.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="CalendarReadOnly" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\CalendarReadOnly.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="CalendarReadWrite" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\CalendarReadWrite.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="TasklistReadOnly" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\TasklistReadOnly.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="TasklistReadWrite" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\TasklistReadWrite.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading