Google: remove SyncML template, combine CalDAV/CardDAV

Google has turned off their SyncML server, so the corresponding
"Google Contacts" template became useless and needs to be removed. It
gets replaced by a "Google" template which combines the three
different URLs currently used by Google for CalDAV/CardDAV.

This new template can be used to configure a "target-config@google"
with default calendar and address book database already enabled. The
actual URL of these databases will be determined during the first
sync using them.

The template relies on the WebDAV backend's new capability to search
multiple different entries in the syncURL property for databases. To
avoid listing each calendar twice (once for the legacy URL, once with
the new one) when using basic username/password authentication, the
backend needs a special case for Google and detect that the legacy URL
does not need to be checked.
This commit is contained in:
Patrick Ohly 2014-07-25 14:02:29 +02:00
parent 74143960b9
commit 581cee897e
6 changed files with 69 additions and 58 deletions

View File

@ -967,6 +967,9 @@ bool WebDAVSource::findCollections(const boost::function<bool (const std::string
// a bit harder for it.
bool haveHomeSet = false;
// Remember whether we have results for https://apidata.googleusercontent.com:443/caldav/v2.
bool haveGoogleCalDAV2 = false;
while (true) {
bool usernameInserted = false;
Candidate next;
@ -984,6 +987,17 @@ bool WebDAVSource::findCollections(const boost::function<bool (const std::string
SE_LOG_DEBUG(NULL, "testing %s", candidate.m_uri.toURL().c_str());
Neon::URI currentURI = m_session->getURI();
Neon::URI &newURI = candidate.m_uri;
bool success = false;
bool isWellKnown = boost::starts_with(candidate.m_uri.m_path, "/.well-known/");
// Special hack Google: if we already have results for the current CalDAV
// endpoint, then don't try the legacy one.
if (newURI.m_host == "www.google.com" &&
(boost::starts_with(newURI.m_path, "/calendar/dav/") || newURI.m_path =="/calendar/dav") &&
haveGoogleCalDAV2) {
SE_LOG_DEBUG(getDisplayName(), "skipping legacy Google CalDAV");
goto next;
}
// Accessing the well-known URIs should lead to a redirect, but
// with Yahoo! Calendar all I got was a 502 "connection refused".
@ -1005,8 +1019,6 @@ bool WebDAVSource::findCollections(const boost::function<bool (const std::string
// candidates.push_back(StringPrintf("/calendar/dav/%s/user/", Neon::URI::escape(username).c_str()));
}
bool success = false;
bool isWellKnown = boost::starts_with(candidate.m_uri.m_path, "/.well-known/");
try {
if (newURI.m_scheme != currentURI.m_scheme ||
newURI.m_host != currentURI.m_host ||
@ -1292,6 +1304,10 @@ bool WebDAVSource::findCollections(const boost::function<bool (const std::string
SE_LOG_DEBUG(NULL, "found %s = %s",
name.c_str(),
uri.toURL().c_str());
if (uri.m_host == "apidata.googleusercontent.com" &&
boost::starts_with(uri.m_path, "/caldav/v2/")) {
haveGoogleCalDAV2 = true;
}
res = storeResult(name,
uri,
isReadOnly);
@ -1448,6 +1464,7 @@ bool WebDAVSource::findCollections(const boost::function<bool (const std::string
}
}
next:
if (next.empty()) {
// use next untried candidate
next = tried.getNextCandidate();

View File

@ -2527,14 +2527,17 @@ static string internalToIni(const string &config)
}
/** result of removeComments(filterRandomUUID(filterConfig())) for Google Calendar template/config */
static const std::string googlecaldav =
"syncURL = https://www.google.com/calendar/dav/%u/user/?SyncEvolution=Google\n"
static const std::string google =
"syncURL = https://apidata.googleusercontent.com/caldav/v2 https://www.googleapis.com/.well-known/carddav https://www.google.com/calendar/dav\n"
"printChanges = 0\n"
"dumpData = 0\n"
"deviceId = fixed-devid\n"
"IconURI = image://themedimage/icons/services/google-calendar\n"
"IconURI = image://themedimage/icons/services/google\n"
"ConsumerReady = 1\n"
"peerType = WebDAV\n"
"[addressbook]\n"
"sync = two-way\n"
"backend = CardDAV\n"
"[calendar]\n"
"sync = two-way\n"
"backend = CalDAV\n";
@ -3039,8 +3042,7 @@ protected:
" template name = template description\n"
" eGroupware = http://www.egroupware.org\n"
" Funambol = https://onemediahub.com\n"
" Google_Calendar = event sync via CalDAV, use for the 'target-config@google-calendar' config\n"
" Google_Contacts = contact sync via SyncML, see http://www.google.com/support/mobile/bin/topic.py?topic=22181\n"
" Google = event and contact sync via CalDAV/CardDAV, use for the 'target-config@google' config\n"
" Goosync = http://www.goosync.com/\n"
" Memotoo = http://www.memotoo.com\n"
" Mobical = https://www.everdroid.com\n"
@ -3137,9 +3139,9 @@ protected:
// note that "backend" will be take from the @default context if one
// exists, so run this before setting up Funambol below
{
TestCmdline cmdline("--print-config", "--template", "google calendar", NULL);
TestCmdline cmdline("--print-config", "--template", "google", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF(googlecaldav,
CPPUNIT_ASSERT_EQUAL_DIFF(google,
removeComments(filterRandomUUID(filterConfig(cmdline.m_out.str()))));
}
@ -3532,17 +3534,17 @@ protected:
removeComments(filterRandomUUID(filterConfig(cmdline.m_out.str()))));
}
// configure Google Calendar with template derived from config name
// configure Google Calendar/Contacts with template derived from config name
{
TestCmdline cmdline("--configure",
"target-config@google-calendar",
"target-config@google",
NULL);
cmdline.doit();
}
{
TestCmdline cmdline("--print-config", "target-config@google-calendar", NULL);
TestCmdline cmdline("--print-config", "target-config@google", NULL);
cmdline.doit();
CPPUNIT_ASSERT_EQUAL_DIFF(googlecaldav,
CPPUNIT_ASSERT_EQUAL_DIFF(google,
removeComments(filterRandomUUID(filterConfig(cmdline.m_out.str()))));
}

View File

@ -1,15 +0,0 @@
=== template.ini ===
fingerprint = Google Calendar
description = event sync via CalDAV, use for the 'target-config@google-calendar' config
=== config.ini ===
consumerReady = 1
peerType = WebDAV
syncURL = https://www.google.com/calendar/dav/%u/user/?SyncEvolution=Google
IconURI = image://themedimage/icons/services/google-calendar
dumpData = 0
printChanges = 0
=== sources/calendar/config.ini ===
sync = two-way
backend = CalDAV

View File

@ -0,0 +1,22 @@
=== template.ini ===
fingerprint = Google
description = event and contact sync via CalDAV/CardDAV, use for the 'target-config@google' config
=== config.ini ===
consumerReady = 1
peerType = WebDAV
# apidata.googleusercontent.com/caldav accepts OAuth for CalDAV,
# www.googleapis.com OAuth and basic authentication for CardDAV,
# www.google.com/calendar/dav is for CalDAV legacy basic authentication (will become obsolete at some point)
syncURL = https://apidata.googleusercontent.com/caldav/v2 https://www.googleapis.com/.well-known/carddav https://www.google.com/calendar/dav
IconURI = image://themedimage/icons/services/google
dumpData = 0
printChanges = 0
=== sources/addressbook/config.ini ===
sync = two-way
backend = CardDAV
=== sources/calendar/config.ini ===
sync = two-way
backend = CalDAV

View File

@ -1,16 +0,0 @@
=== template.ini ===
fingerprint = Google Contacts, Google
description = contact sync via SyncML, see http://www.google.com/support/mobile/bin/topic.py?topic=22181
=== config.ini ===
syncURL = https://m.google.com/syncml
WebURL = http://www.google.com
ConsumerReady = TRUE
clientAuthType = basic
IconURI = image://themedimage/icons/services/gmail
=== sources/addressbook/config.ini ===
sync = two-way
uri = contacts
syncFormat = text/x-vcard
backend = addressbook

View File

@ -1568,8 +1568,7 @@ class TestDBusServer(DBusUtil, unittest.TestCase):
configs = self.server.GetConfigs(True, utf8_strings=True)
configs.sort()
self.assertEqual(configs, ["Funambol",
"Google_Calendar",
"Google_Contacts",
"Google",
"Goosync",
"Memotoo",
"Mobical",
@ -5621,13 +5620,16 @@ def internalToIni(config):
# result of removeComments(self.removeRandomUUID(filterConfig())) for
# Google Calendar template/config
googlecaldav = '''syncURL = https://www.google.com/calendar/dav/%u/user/?SyncEvolution=Google
google = '''syncURL = https://apidata.googleusercontent.com/caldav/v2 https://www.googleapis.com/.well-known/carddav https://www.google.com/calendar/dav
printChanges = 0
dumpData = 0
deviceId = fixed-devid
IconURI = image://themedimage/icons/services/google-calendar
IconURI = image://themedimage/icons/services/google
ConsumerReady = 1
peerType = WebDAV
[addressbook]
sync = two-way
backend = CardDAV
[calendar]
sync = two-way
backend = CalDAV
@ -6494,8 +6496,7 @@ spds/sources/todo/config.txt:# evolutionpassword =
" template name = template description\n" \
" eGroupware = http://www.egroupware.org\n" \
" Funambol = https://onemediahub.com\n" \
" Google_Calendar = event sync via CalDAV, use for the 'target-config@google-calendar' config\n" \
" Google_Contacts = contact sync via SyncML, see http://www.google.com/support/mobile/bin/topic.py?topic=22181\n" \
" Google = event and contact sync via CalDAV/CardDAV, use for the 'target-config@google' config\n" \
" Goosync = http://www.goosync.com/\n" \
" Memotoo = http://www.memotoo.com\n" \
" Mobical = https://www.everdroid.com\n" \
@ -6701,9 +6702,9 @@ spds/sources/todo/config.txt:# evolutionpassword =
# note that "backend" will be taken from the @default context
# if one exists, so run this before setting up Funambol below
out, err, code = self.runCmdline(["--print-config", "--template", "google calendar"])
out, err, code = self.runCmdline(["--print-config", "--template", "google"])
self.assertNoErrors(err)
self.assertEqualDiff(googlecaldav,
self.assertEqualDiff(google,
removeComments(self.removeRandomUUID(filterConfig(out))))
out, err, code = self.runCmdline(["--print-config", "--template", "yahoo"])
@ -6928,18 +6929,18 @@ sources/xyz/config.ini:# databasePassword = """)
self.assertEqualDiff(yahoo.replace("sync = two-way", "sync = disabled"),
removeComments(self.removeRandomUUID(filterConfig(out))))
# configure Google Calendar with template derived from config name
# configure Google Calendar/Contacts with template derived from config name
out, err, code = self.runCmdline(["--configure",
"target-config@google-calendar"])
self.assertSilent(out, err, ignore=self.sourceCheckOutput('calendar'))
"target-config@google"])
self.assertSilent(out, err, ignore=self.sourceCheckOutput(['addressbook', 'calendar']))
out, err, code = self.runCmdline(["--print-config", "target-config@google-calendar"])
out, err, code = self.runCmdline(["--print-config", "target-config@google"])
self.assertNoErrors(err)
if davenabled:
self.assertEqualDiff(googlecaldav,
self.assertEqualDiff(google,
removeComments(self.removeRandomUUID(filterConfig(out))))
else:
self.assertEqualDiff(googlecaldav.replace("sync = two-way", "sync = disabled"),
self.assertEqualDiff(google.replace("sync = two-way", "sync = disabled"),
removeComments(self.removeRandomUUID(filterConfig(out))))
# test "template not found" error cases