Page MenuHomePhorge

libkolab fails to read valid current-user-privilege-set from Radicale
Closed, ResolvedPublic

Description

To determine if a calendar is writable, libkolab issues a PROPFIND for various properties and processes them in kolab_dav_client.php getFolderPropertiesFromResponse()

In that code, it makes the assumption that tag names will be prefixed. But Radicale doesn't write privileges like <D:privilege><D:write/></D:privilege>. Instead it declares its top level element like <multistatus xmlns="DAV:"> and all the child tags inherit that default namespace. <privilege><write/></privilege> is thus valid, but libkolab fails to accept it.

Example:

<multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:CS="http://calendarserver.org/ns/" xmlns:ICAL="http://apple.com/ns/ical/" xmlns:ns4="Kolab:">
  <response>
    <href>/calendar/.../.../</href>
    <propstat>
      <prop>
<ICAL:calendar-color>#ff0000ff</ICAL:calendar-color>
        <C:supported-calendar-component-set>
          <C:comp name="VEVENT"/>
          <C:comp name="VJOURNAL"/>
          <C:comp name="VTODO"/>
        </C:supported-calendar-component-set>
        <CS:getctag>"..."</CS:getctag>
        <current-user-privilege-set>
          <privilege>
            <read/>
          </privilege>
          <privilege>
            <all/>
          </privilege>
          <privilege>
            <write/>
          </privilege>
...

This is a fix for the issue:

--- plugins/libkolab/lib/kolab_dav_client.php.orig      2025-10-14 12:34:56.0 +0000
+++ plugins/libkolab/lib/kolab_dav_client.php   2025-10-14 12:34:56.0 +0000
@@ -1046,16 +1046,16 @@

                 if ($grant_element = $ace->getElementsByTagName('grant')->item(0)) {
                     foreach ($grant_element->childNodes as $privilege) {
-                        if (strpos($privilege->nodeName, ':privilege') !== false && $privilege->firstChild) {
-                            $grant[] = preg_replace('/^[^:]+:/', '', $privilege->firstChild->nodeName);
+                        if ($privilege->localName == 'privilege' && $privilege->firstChild) {
+                            $grant[] = $privilege->firstChild->localName;
                         }
                     }
                 }

                 if ($deny_element = $ace->getElementsByTagName('deny')->item(0)) {
                     foreach ($deny_element->childNodes as $privilege) {
-                        if (strpos($privilege->nodeName, ':privilege') !== false && $privilege->firstChild) {
-                            $deny[] = preg_replace('/^[^:]+:/', '', $privilege->firstChild->nodeName);
+                        if ($privilege->localName == 'privilege' && $privilege->firstChild) {
+                            $deny[] = $privilege->firstChild->localName;
                         }
                     }
                 }
@@ -1075,8 +1075,8 @@
             $rights = [];

             foreach ($set_element->childNodes as $privilege) {
-                if (strpos($privilege->nodeName, ':privilege') !== false && $privilege->firstChild) {
-                    $rights[] = preg_replace('/^[^:]+:/', '', $privilege->firstChild->nodeName);
+                if ($privilege->localName == 'privilege' && $privilege->firstChild) {
+                    $rights[] = $privilege->firstChild->localName;
                 }
             }

Details

Ticket Type
Task