On Mon, 2013-02-04 at 13:45 +0100, Patrick Ohly wrote:
> On Sat, 2013-02-02 at 15:08 +0530, Khurshid Alam wrote:
> > [DEBUG 00:00:05] PROPFIND: Neon error code 1: XML parse error at line 55: 
> > undeclared namespace prefix, must not retry
> > [DEBUG 00:00:05] TransportStatusException: PROPFIND: Neon error code 1: XML 
> > parse error at line 55: undeclared namespace prefix
> > [INFO 00:00:05] calendar: backend failed
> > ----------------------------------------------------------------------- 
> 
> That's the same thing that I ran into. Google changed something since
> December 12th last year (I have a nightly test log which shows a
> different, correct server response) or later (I don't have newer logs).

My Google contacts confirmed the problem and promised to have at least a
workaround deployed soonish (in the order of a few weeks). Therefore for
now I decided against releasing a SyncEvolution 1.3.x update with a
workaround.

If anyone absolute needs it now, attached is the patch. Please apply to
1.3 and compile from source.

-- 
Best Regards, Patrick Ohly

The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.

>From c0c47881524fcef5375796301315480ae8630bdc Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Mon, 4 Feb 2013 13:57:16 +0100
Subject: [PATCH] CalDAV: work around Google server regression (undeclared
 namespace prefix in XML)

Google CalDAV currently sends invalid XML back when asked to include
CardDAV properties in a PROPFIND. This gets rejected in the XML
parser, which prevents syncing calendar data:
   Neon error code 1: XML parse error at line 55: undeclared namespace prefix

The incorrect XML is this:
  <D:propstat>
   <D:status>HTTP/1.1 404 Not Found</D:status>
   <D:prop>
   ...
    <caldav:max-attendees-per-instance/>
    <ns1:addressbook-home-set xmlns:ns1="urn:ietf:params:xml:ns:carddav"/>
==> <ns1:principal-address/>
    <ns1:addressbook-description/>
    <ns1:supported-address-data/>
    <ns1:max-resource-size/>
   </D:prop>
  </D:propstat>

This was introduced on the server side sometime after December 12nd
2012 (tests run at that time showed a different response) and does not
affect SyncEvolution 1.2 because it did not yet ask for CardDAV
properties.

The workaround on the client side is to ask for only the properties
which are really needed.
---
 src/backends/webdav/WebDAVSource.cpp |   32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/src/backends/webdav/WebDAVSource.cpp b/src/backends/webdav/WebDAVSource.cpp
index 4284aae..1c93fc3 100644
--- a/src/backends/webdav/WebDAVSource.cpp
+++ b/src/backends/webdav/WebDAVSource.cpp
@@ -843,6 +843,10 @@ bool WebDAVSource::findCollections(const boost::function<bool (const std::string
             m_settings->getCredentials("", user, pw);
             m_session->forceAuthorization(user, pw);
             m_davProps.clear();
+            // Avoid asking for CardDAV properties when only using CalDAV
+            // and vice versa, to avoid breaking both when the server is only
+            // broken for one of them (like Google, which (temporarily?) sent
+            // invalid CardDAV properties).
             static const ne_propname caldav[] = {
                 // WebDAV ACL
                 { "DAV:", "alternate-URI-set" },
@@ -863,6 +867,17 @@ bool WebDAVSource::findCollections(const boost::function<bool (const std::string
                 { "urn:ietf:params:xml:ns:caldav", "max-date-time" },
                 { "urn:ietf:params:xml:ns:caldav", "max-instances" },
                 { "urn:ietf:params:xml:ns:caldav", "max-attendees-per-instance" },
+                { NULL, NULL }
+            };
+            static const ne_propname carddav[] = {
+                // WebDAV ACL
+                { "DAV:", "alternate-URI-set" },
+                { "DAV:", "principal-URL" },
+                { "DAV:", "current-user-principal" },
+                { "DAV:", "group-member-set" },
+                { "DAV:", "group-membership" },
+                { "DAV:", "displayname" },
+                { "DAV:", "resourcetype" },
                 // CardDAV
                 { "urn:ietf:params:xml:ns:carddav", "addressbook-home-set" },
                 { "urn:ietf:params:xml:ns:carddav", "principal-address" },
@@ -872,7 +887,9 @@ bool WebDAVSource::findCollections(const boost::function<bool (const std::string
                 { NULL, NULL }
             };
             SE_LOG_DEBUG(NULL, NULL, "read relevant properties of %s", path.c_str());
-            m_session->propfindProp(path, 0, caldav, callback, deadline);
+            m_session->propfindProp(path, 0,
+                                    getContent() == "VCARD" ? carddav : caldav,
+                                    callback, deadline);
             success = true;
         } catch (const Neon::RedirectException &ex) {
             // follow to new location
@@ -1021,20 +1038,29 @@ bool WebDAVSource::findCollections(const boost::function<bool (const std::string
                     // Yahoo! Calendar does not return resources contained in /dav/<user>/Calendar/
                     // if <allprops> is used. Properties must be requested explicitly.
                     SE_LOG_DEBUG(NULL, NULL, "list items in %s", path.c_str());
-                    static const ne_propname props[] = {
+                    // See findCollections() for the reason why we are not mixing CalDAV and CardDAV
+                    // properties.
+                    static const ne_propname caldav[] = {
                         { "DAV:", "displayname" },
                         { "DAV:", "resourcetype" },
                         { "urn:ietf:params:xml:ns:caldav", "calendar-home-set" },
                         { "urn:ietf:params:xml:ns:caldav", "calendar-description" },
                         { "urn:ietf:params:xml:ns:caldav", "calendar-timezone" },
                         { "urn:ietf:params:xml:ns:caldav", "supported-calendar-component-set" },
+                        { NULL, NULL }
+                    };
+                    static const ne_propname carddav[] = {
+                        { "DAV:", "displayname" },
+                        { "DAV:", "resourcetype" },
                         { "urn:ietf:params:xml:ns:carddav", "addressbook-home-set" },
                         { "urn:ietf:params:xml:ns:carddav", "addressbook-description" },
                         { "urn:ietf:params:xml:ns:carddav", "supported-address-data" },
                         { NULL, NULL }
                     };
                     m_davProps.clear();
-                    m_session->propfindProp(path, 1, props, callback, finalDeadline);
+                    m_session->propfindProp(path, 1,
+                                            getContent() == "VCARD" ? carddav : caldav,
+                                            callback, finalDeadline);
                     std::set<std::string> subs;
                     BOOST_FOREACH(Props_t::value_type &entry, m_davProps) {
                         const std::string &sub = entry.first;
-- 
1.7.10.4

_______________________________________________
SyncEvolution mailing list
[email protected]
http://lists.syncevolution.org/listinfo/syncevolution

Reply via email to