commit libkgapi for openSUSE:Factory
Hello community, here is the log from the commit of package libkgapi for openSUSE:Factory checked in at 2012-12-28 22:44:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libkgapi (Old) and /work/SRC/openSUSE:Factory/.libkgapi.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "libkgapi", Maintainer is "" Changes: -------- --- /work/SRC/openSUSE:Factory/libkgapi/libkgapi.changes 2012-10-24 07:13:03.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.libkgapi.new/libkgapi.changes 2012-12-28 22:44:09.000000000 +0100 @@ -1,0 +2,9 @@ +Wed Dec 19 15:17:01 UTC 2012 - nico.kruber@gmail.com + +- Update to 0.4.4 + * fixed kde#309314 - Contacts with XML-unsafe characters not stored + * fixed kde#309318 - Support custom IM protocols + * fixed kde#310177 - Support birthday dates without year specified + * fixed kde#310851 - Handle Microsoft TZIDs + +------------------------------------------------------------------- Old: ---- libkgapi-0.4.3.tar.bz2 New: ---- libkgapi-0.4.4.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libkgapi.spec ++++++ --- /var/tmp/diff_new_pack.LsuNnI/_old 2012-12-28 22:44:10.000000000 +0100 +++ /var/tmp/diff_new_pack.LsuNnI/_new 2012-12-28 22:44:10.000000000 +0100 @@ -17,7 +17,7 @@ Name: libkgapi -Version: 0.4.3 +Version: 0.4.4 Release: 0 Summary: Extension for accessing your Google data License: GPL-2.0+ ++++++ libkgapi-0.4.3.tar.bz2 -> libkgapi-0.4.4.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkgapi-0.4.3/CMakeLists.txt new/libkgapi-0.4.4/CMakeLists.txt --- old/libkgapi-0.4.3/CMakeLists.txt 2012-10-21 18:11:23.000000000 +0200 +++ new/libkgapi-0.4.4/CMakeLists.txt 2012-12-16 19:23:52.000000000 +0100 @@ -1,8 +1,8 @@ project(libkgapi) set(KGAPI_VERSION_MAJOR 0) set(KGAPI_VERSION_MINOR 4) -set(KGAPI_VERSION_RELEASE 3) -set(KGAPI_VERSION 0.4.3) +set(KGAPI_VERSION_RELEASE 4) +set(KGAPI_VERSION 0.4.4) cmake_minimum_required(VERSION 2.8) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkgapi-0.4.3/libkgapi/objects/contact.cpp new/libkgapi-0.4.4/libkgapi/objects/contact.cpp --- old/libkgapi-0.4.3/libkgapi/objects/contact.cpp 2012-10-21 18:11:23.000000000 +0200 +++ new/libkgapi-0.4.4/libkgapi/objects/contact.cpp 2012-12-16 19:23:52.000000000 +0100 @@ -258,10 +258,10 @@ case AIM: return "AIM"; default: - return "OTHER"; + return "Other"; } - return "OTHER"; + return "Other"; } QString Contact::IMSchemeToProtocolName(const QString& scheme) @@ -274,11 +274,21 @@ QString proto; if (protocolName.toUpper() == "XMPP") { proto = "JABBER"; - } else { + } else if ((protocolName.toUpper() == QLatin1String("ICQ")) || + (protocolName.toUpper() == QLatin1String("GOOGLE_TALK")) || + (protocolName.toUpper() == QLatin1String("QQ")) || + (protocolName.toUpper() == QLatin1String("SKYPE")) || + (protocolName.toUpper() == QLatin1String("YAHOO")) || + (protocolName.toUpper() == QLatin1String("MSN")) || + (protocolName.toUpper() == QLatin1String("AIM"))) + { proto = protocolName.toUpper(); + return SCHEME_URL + proto; } - return SCHEME_URL + proto; + /* If the protocolName is not officially supported by Google, then instead + * of full scheme, Google expects just a name of the protocol. */ + return protocolName; } Contact::IMProtocol Contact::IMSchemeToProtocol(const QString& scheme) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkgapi-0.4.3/libkgapi/services/calendar.cpp new/libkgapi-0.4.4/libkgapi/services/calendar.cpp --- old/libkgapi-0.4.3/libkgapi/services/calendar.cpp 2012-10-21 18:11:23.000000000 +0200 +++ new/libkgapi-0.4.4/libkgapi/services/calendar.cpp 2012-12-16 19:23:52.000000000 +0100 @@ -63,6 +63,22 @@ static KGAPI::Object* JSONToEvent(const QVariantMap& event); static QVariantMap eventToJSON(KGAPI::Object *event); static QList<KGAPI::Object*> parseEventJSONFeed(const QVariantList& feed); + + /** + * Checks whether TZID is in Olson format and converts it to it if neccessary + * + * This is mainly to handle crazy Microsoft TZIDs like + * "(GMT) Greenwich Mean Time/Dublin/Edinburgh/London", because Google only + * accepts TZIDs in Olson format ("Europe/London"). + * + * It first tries to match the given \p tzid to all TZIDs in KTimeZones::zones(). + * If it fails, it parses the \p event, looking for X-MICROSOFT-CDO-TZID + * property and than matches it to Olson-formatted TZID using a table. + * + * When the method fails to process the TZID, it returns the original \p tzid + * in hope, that Google will cope with it. + */ + static QString checkAndConverCDOTZID(const QString &tzid, const Objects::Event *event); }; } @@ -627,7 +643,7 @@ tzStart = KTimeZone::utc().name(); } if (!tzStart.isEmpty()) { - start["timeZone"] = tzStart; + start["timeZone"] = checkAndConverCDOTZID(tzStart, object); } data["start"] = start; @@ -646,7 +662,7 @@ tzEnd = KTimeZone::utc().name(); } if (!tzEnd.isEmpty()) { - end["timeZone"] = tzEnd; + end["timeZone"] = checkAndConverCDOTZID(tzEnd, object); } data["end"] = end; @@ -794,3 +810,176 @@ return list; } + + +static QMap<int, QString> initMSCDOTZIDTable() +{ + QMap<int, QString> map; + + /* Based on "Time Zone to CdoTimeZoneId Map" + * http://msdn.microsoft.com/en-us/library/aa563018%28loband%29.aspx + * + * The mapping is not exact, since the CdoTimeZoneId usually refers to a + * region of multiple countries, so I always picked one of the countries + * in the specified region and used it's TZID. + */ + map.insert(0, QLatin1String("UTC")); + map.insert(1, QLatin1String("Europe/London")); /* GMT Greenwich Mean Time; Dublin, Edinburgh, London */ + /* Seriously? *sigh* Let's handle these two in checkAndConvertCDOTZID() */ + //map.insertMulti(2, QLatin1String("Europe/Lisbon")); /* GMT Greenwich Mean Time: Dublin, Edinburgh, Lisbon, London */ + //map.insertMulti(2, QLatin1String("Europe/Sarajevo")); /* GMT+01:00 Sarajevo, Skopje, Sofija, Vilnius, Warsaw, Zagreb */ + map.insert(3, QLatin1String("Europe/Paris")); /* GMT+01:00 Paris, Madrid, Brussels, Copenhagen */ + map.insert(4, QLatin1String("Europe/Berlin")); /* GMT+01:00 Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna */ + map.insert(5, QLatin1String("Europe/Bucharest")); /* GMT+02:00 Bucharest */ + map.insert(6, QLatin1String("Europe/Prague")); /* GMT+01:00 Prague, Central Europe */ + map.insert(7, QLatin1String("Europe/Athens")); /* GMT+02:00 Athens, Istanbul, Minsk */ + map.insert(8, QLatin1String("America/Brazil")); /* GMT-03:00 Brasilia */ + map.insert(9, QLatin1String("America/Halifax")); /* GMT-04:00 Atlantic time (Canada) */ + map.insert(10, QLatin1String("America/New_York")); /* GMT-05:00 Eastern Time (US & Canada) */ + map.insert(11, QLatin1String("America/Chicago")); /* GMT-06:00 Central Time (US & Canada) */ + map.insert(12, QLatin1String("America/Denver")); /* GMT-07:00 Mountain Time (US & Canada) */ + map.insert(13, QLatin1String("America/Los_Angeles")); /* GMT-08:00 Pacific Time (US & Canada); Tijuana */ + map.insert(14, QLatin1String("America/Anchorage")); /* GMT-09:00 Alaska */ + map.insert(15, QLatin1String("Pacific/Honolulu")); /* GMT-10:00 Hawaii */ + map.insert(16, QLatin1String("Pacific/Apia")); /* GMT-11:00 Midway Island, Samoa */ + map.insert(17, QLatin1String("Pacific/Auckland")); /* GMT+12:00 Auckland, Wellington */ + map.insert(18, QLatin1String("Australia/Brisbane")); /* GMT+10:00 Brisbane, East Australia */ + map.insert(19, QLatin1String("Australia/Adelaide")); /* GMT+09:30 Adelaide, Central Australia */ + map.insert(20, QLatin1String("Asia/Tokyo")); /* GMT+09:00 Osaka, Sapporo, Tokyo */ + map.insert(21, QLatin1String("Asia/Singapore")); /* GMT+08:00 Kuala Lumpur, Singapore */ + map.insert(22, QLatin1String("Asia/Bangkok")); /* GMT+07:00 Bangkok, Hanoi, Jakarta */ + map.insert(23, QLatin1String("Asia/Calcutta")); /* GMT+05:30 Kolkata, Chennai, Mumbai, New Delhi, India Standard Time */ + map.insert(24, QLatin1String("Asia/Dubai")); /* GMT+04:00 Abu Dhabi, Muscat */ + map.insert(25, QLatin1String("Asia/Tehran")); /* GMT+03:30 Tehran */ + map.insert(26, QLatin1String("Asia/Baghdad")); /* GMT+03:00 Baghdad */ + map.insert(27, QLatin1String("Asia/Jerusalem")); /* GMT+02:00 Israel, Jerusalem Standard Time */ + map.insert(28, QLatin1String("America/St_Johns")); /* GMT-03:30 Newfoundland */ + map.insert(29, QLatin1String("Atlantic/Portugal")); /* GMT-01:00 Azores */ + map.insert(30, QLatin1String("America/Noronha")); /* GMT-02:00 Mid-Atlantic */ + map.insert(31, QLatin1String("Africa/Monrovia")); /* GMT Casablanca, Monrovia */ + map.insert(32, QLatin1String("America/Argentina/Buenos_Aires")); /* GMT-03:00 Buenos Aires, Georgetown */ + map.insert(33, QLatin1String("America/La_Paz")); /* GMT-04:00 Caracas, La Paz */ + map.insert(34, QLatin1String("America/New_York")); /* GMT-05:00 Indiana (East) */ + map.insert(35, QLatin1String("America/Bogota")); /* GMT-05:00 Bogota, Lima, Quito */ + map.insert(36, QLatin1String("America/Winnipeg")); /* GMT-06:00 Saskatchewan */ + map.insert(37, QLatin1String("America/Mexico_City")); /* GMT-06:00 Mexico City, Tegucigalpa */ + map.insert(38, QLatin1String("America/Phoenix")); /* GMT-07:00 Arizona */ + map.insert(39, QLatin1String("Pacific/Kwajalein")); /* GMT-12:00 Eniwetok, Kwajalein, Dateline Time */ + map.insert(40, QLatin1String("Pacific/Fiji")); /* GMT+12:00 Fušál, Kamchatka, Mashall Is. */ + map.insert(41, QLatin1String("Pacific/Noumea")); /* GMT+11:00 Magadan, Solomon Is., New Caledonia */ + map.insert(42, QLatin1String("Australia/Hobart")); /* GMT+10:00 Hobart, Tasmania */ + map.insert(43, QLatin1String("Pacific/Guam")); /* GMT+10:00 Guam, Port Moresby */ + map.insert(44, QLatin1String("Australia/Darwin")); /* GMT+09:30 Darwin */ + map.insert(45, QLatin1String("Asia/Shanghai")); /* GMT+08:00 Beijing, Chongqing, Hong Kong SAR, Urumqi */ + map.insert(46, QLatin1String("Asia/Omsk")); /* GMT+06:00 Almaty, Novosibirsk, North Central Asia */ + map.insert(47, QLatin1String("Asia/Karachi")); /* GMT+05:00 Islamabad, Karachi, Tashkent */ + map.insert(48, QLatin1String("Asia/Kabul")); /* GMT+04:30 Kabul */ + map.insert(49, QLatin1String("Africa/Cairo")); /* GMT+02:00 Cairo */ + map.insert(50, QLatin1String("Africa/Harare")); /* GMT+02:00 Harare, Pretoria */ + map.insert(51, QLatin1String("Europe/Moscow")); /* GMT+03:00 Moscow, St. Petersburg, Volgograd */ + map.insert(53, QLatin1String("Atlantic/Cape_Verde")); /* GMT-01:00 Cape Verde Is. */ + map.insert(54, QLatin1String("Asia/Tbilisi")); /* GMT+04:00 Baku, Tbilisi, Yerevan */ + map.insert(55, QLatin1String("America/Tegucigalpa")); /* GMT-06:00 Central America */ + map.insert(56, QLatin1String("Africa/Nairobi")); /* GMT+03:00 East Africa, Nairobi */ + map.insert(58, QLatin1String("Asia/Yekaterinburg")); /* GMT+05:00 Ekaterinburg */ + map.insert(59, QLatin1String("Europe/Helsinki")); /* GMT+02:00 Helsinki, Riga, Tallinn */ + map.insert(60, QLatin1String("America/Greenland")); /* GMT-03:00 Greenland */ + map.insert(61, QLatin1String("Asia/Rangoon")); /* GMT+06:30 Yangon (Rangoon) */ + map.insert(62, QLatin1String("Asia/Katmandu")); /* GMT+05:45 Kathmandu, Nepal */ + map.insert(63, QLatin1String("Asia/Irkutsk")); /* GMT+08:00 Irkutsk, Ulaan Bataar */ + map.insert(64, QLatin1String("Asia/Krasnoyarsk")); /* GMT+07:00 Krasnoyarsk */ + map.insert(65, QLatin1String("America/Santiago")); /* GMT-04:00 Santiago */ + map.insert(66, QLatin1String("Asia/Colombo")); /* GMT+06:00 Sri Jayawardenepura, Sri Lanka */ + map.insert(67, QLatin1String("Pacific/Tongatapu")); /* GMT+13:00 Nuku'alofa, Tonga */ + map.insert(68, QLatin1String("Asia/Vladivostok")); /* GMT+10:00 Vladivostok */ + map.insert(69, QLatin1String("Africa/Bangui")); /* GMT+01:00 West Central Africa */ + map.insert(70, QLatin1String("Asia/Yakutsk")); /* GMT+09:00 Yakutsk */ + map.insert(71, QLatin1String("Asia/Dhaka")); /* GMT+06:00 Astana, Dhaka */ + map.insert(72, QLatin1String("Asia/Seoul")); /* GMT+09:00 Seoul, Korea Standard time */ + map.insert(73, QLatin1String("Australia/Perth")); /* GMT+08:00 Perth, Western Australia */ + map.insert(74, QLatin1String("Asia/Kuwait")); /* GMT+03:00 Arab, Kuwait, Riyadh */ + map.insert(75, QLatin1String("Asia/Taipei")); /* GMT+08:00 Taipei */ + map.insert(76, QLatin1String("Australia/Sydney")); /* GMT+10:00 Canberra, Melbourne, Sydney */ + + return map; +} + +static const QMap<int, QString> MSCDOTZIDTable = initMSCDOTZIDTable(); + +QString Services::CalendarPrivate::checkAndConverCDOTZID(const QString& tzid, const Objects::Event* event) +{ + /* Try to match the @tzid to any valid timezone we know. */ + KTimeZones timeZones; + const KTimeZones::ZoneMap zones = timeZones.zones(); + KTimeZones::ZoneMap::const_iterator iter; + for (iter = zones.constBegin(); iter != zones.constEnd(); iter++) { + if (iter.key() == tzid) { + /* Yay, @tzid is a valid TZID in Olson format */ + return tzid; + } + } + + /* Damn, no match. Parse the iCal and try to find X-MICROSOFT-CDO-TZID + * property that we can match against the MSCDOTZIDTable */ + ICalFormat format; + /* Use a copy of @event, otherwise it would be deleted when ptr is destroyed */ + Incidence::Ptr ptr(new Event(*dynamic_cast<const Event*>(event))); + const QString vcard = format.toICalString(ptr); + const QStringList properties = vcard.split(QLatin1Char('\n')); + int CDOId = -1; + Q_FOREACH(const QString &property, properties) { + if (property.startsWith(QLatin1String("X-MICROSOFT-CDO-TZID"))) { + QStringList parsed = property.split(QLatin1Char(':')); + if (parsed.length() != 2) { + /* Fail */ + return tzid; + } + + CDOId = parsed.at(1).toInt(); + break; + } + } + + /* Wheeee, we have X-MICROSOFT-CDO-TZID, try to map it to Olson format */ + if (CDOId > -1) { + + /* *sigh* Some expert in MS assigned the same ID to two two different timezones... */ + if (CDOId == 2) { + + /* GMT Greenwich Mean Time: Dublin, Edinburgh, Lisbon, London */ + if (tzid.contains(QLatin1String("Dublin")) || + tzid.contains(QLatin1String("Edinburgh")) || + tzid.contains(QLatin1String("Lisbon")) || + tzid.contains(QLatin1String("London"))) + { + return QLatin1String("Europe/London"); + } + + /* GMT+01:00 Sarajevo, Skopje, Sofija, Vilnius, Warsaw, Zagreb */ + else if (tzid.contains(QLatin1String("Sarajevo")) || + tzid.contains(QLatin1String("Skopje")) || + tzid.contains(QLatin1String("Sofija")) || + tzid.contains(QLatin1String("Vilnius")) || + tzid.contains(QLatin1String("Warsaw")) || + tzid.contains(QLatin1String("Zagreb"))) + { + return QLatin1String("Europe/Sarajevo"); + } + + /* This should never ever happen. I don't know what to do if it happens */ + else { + return tzid; + } + } + + if (MSCDOTZIDTable.contains(CDOId)) { + return MSCDOTZIDTable.value(CDOId); + } + } + + /* Fail. The event does not have a valid timezone, does not contain + * X-MICROSOFT-CDO-TZID or we failed to map the CDO-TZID to a real timezone. + * We are screwed. Just return the original TZID and hope Google will accept it + * (though we know they won't) */ + return tzid; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkgapi-0.4.3/libkgapi/services/contacts.cpp new/libkgapi-0.4.4/libkgapi/services/contacts.cpp --- old/libkgapi-0.4.3/libkgapi/services/contacts.cpp 2012-10-21 18:11:23.000000000 +0200 +++ new/libkgapi-0.4.4/libkgapi/services/contacts.cpp 2012-12-16 19:23:52.000000000 +0100 @@ -22,6 +22,9 @@ #include <kurl.h> +/* Qt::escape() */ +#include <QTextDocument> + #include <qjson/parser.h> #include <qjson/serializer.h> @@ -527,8 +530,16 @@ /* Birthday */ QVariantMap bDay = data["gContact$birthday"].toMap(); - if (!bDay.isEmpty()) - object->setBirthday(QDateTime::fromString(bDay["when"].toString(), "yyyy-MM-dd")); + if (!bDay.isEmpty()) { + QString birthday = bDay["when"].toString(); + /* Birthdays in format "--MM-DD" are valid and mean that no year has + * been specified. Since KABC does not support birthdays without year, + * we simulate that by specifying a fake year - 1900 */ + if (birthday.startsWith("--")) { + birthday = "1900" + birthday.mid(1); + } + object->setBirthday(QDateTime::fromString(birthday, "yyyy-MM-dd")); + } /* User-defined fields */ QVariantList userDefined = data["gContact$userDefinedField"].toList(); @@ -562,34 +573,34 @@ /* Name */ output.append("<gd:name>"); if (!contact->givenName().isEmpty()) - output.append("<gd:givenName>").append(contact->givenName().toUtf8()).append("</gd:givenName>"); + output.append("<gd:givenName>").append(Qt::escape(contact->givenName()).toUtf8()).append("</gd:givenName>"); if (!contact->familyName().isEmpty()) - output.append("<gd:familyName>").append(contact->familyName().toUtf8()).append("</gd:familyName>"); + output.append("<gd:familyName>").append(Qt::escape(contact->familyName()).toUtf8()).append("</gd:familyName>"); if (!contact->assembledName().isEmpty()) - output.append("<gd:fullName>").append(contact->formattedName().toUtf8()).append("</gd:fullName>"); + output.append("<gd:fullName>").append(Qt::escape(contact->formattedName()).toUtf8()).append("</gd:fullName>"); if (!contact->additionalName().isEmpty()) - output.append("<gd:additionalName>").append(contact->additionalName().toUtf8()).append("</gd:additionalName>"); + output.append("<gd:additionalName>").append(Qt::escape(contact->additionalName()).toUtf8()).append("</gd:additionalName>"); if (!contact->prefix().isEmpty()) - output.append("<gd:namePrefix>").append(contact->prefix().toUtf8()).append("</gd:namePrefix>"); + output.append("<gd:namePrefix>").append(Qt::escape(contact->prefix()).toUtf8()).append("</gd:namePrefix>"); if (!contact->suffix().isEmpty()) - output.append("<gd:nameSuffix>").append(contact->suffix().toUtf8()).append("</gd:nameSuffix>"); + output.append("<gd:nameSuffix>").append(Qt::escape(contact->suffix()).toUtf8()).append("</gd:nameSuffix>"); output.append("</gd:name>"); /* Notes */ if (!contact->note().isEmpty()) - output.append("<atom:content type='text'>").append(contact->note().toUtf8()).append("</atom:content>"); + output.append("<atom:content type='text'>").append(Qt::escape(contact->note()).toUtf8()).append("</atom:content>"); /* Organization (work) */ QByteArray org; QString office = contact->office(); if (!contact->organization().isEmpty()) - org.append("<gd:orgName>").append(contact->organization().toUtf8()).append("</gd:orgName>"); + org.append("<gd:orgName>").append(Qt::escape(contact->organization()).toUtf8()).append("</gd:orgName>"); if (!contact->department().isEmpty()) - org.append("<gd:orgDepartment>").append(contact->department().toUtf8()).append("</gd:orgDepartment>"); + org.append("<gd:orgDepartment>").append(Qt::escape(contact->department()).toUtf8()).append("</gd:orgDepartment>"); if (!contact->title().isEmpty()) - org.append("<gd:orgTitle>").append(contact->title().toUtf8()).append("</gd:orgTitle>"); + org.append("<gd:orgTitle>").append(Qt::escape(contact->title()).toUtf8()).append("</gd:orgTitle>"); if (!office.isEmpty()) { - org.append("<gd:where>").append(office.toUtf8()).append("</gd:where>"); + org.append("<gd:where>").append(Qt::escape(office).toUtf8()).append("</gd:where>"); parsedCustoms << "KADDRESSBOOK-X-Office"; } if (!org.isEmpty()) @@ -597,56 +608,56 @@ /* Nickname */ if (!contact->nickName().isEmpty()) - output.append("<gContact:nickname>").append(contact->nickName().toUtf8()).append("</gContact:nickname>"); + output.append("<gContact:nickname>").append(Qt::escape(contact->nickName()).toUtf8()).append("</gContact:nickname>"); /* Occupation */ if (!contact->profession().isEmpty()) { - output.append("<gContact:occupation>").append(contact->profession().toUtf8()).append("</gContact:occupation>"); + output.append("<gContact:occupation>").append(Qt::escape(contact->profession()).toUtf8()).append("</gContact:occupation>"); parsedCustoms << "KADDRESSBOOK-X-Profession"; } /* Spouse */ QString spouse = contact->spousesName(); if (!spouse.isEmpty()) { - output.append("<gContact:relation rel=\"spouse\">").append(spouse.toUtf8()).append("</gContact:relation>"); + output.append("<gContact:relation rel=\"spouse\">").append(Qt::escape(spouse).toUtf8()).append("</gContact:relation>"); parsedCustoms << "KADDRESSBOOK-X-SpousesName"; } /* Manager */ QString manager = contact->managersName(); if (!manager.isEmpty()) { - output.append("<gContact:relation rel=\"manager\">").append(manager.toUtf8()).append("</gContact:relation>"); + output.append("<gContact:relation rel=\"manager\">").append(Qt::escape(manager).toUtf8()).append("</gContact:relation>"); parsedCustoms << "KADDRESSBOOK-X-ManagersName"; } /* Assistant */ QString assistant = contact->assistantsName(); if (!assistant.isEmpty()) { - output.append("<gContact:relation rel=\"assistant\">").append(assistant.toUtf8()).append("</gContact:relation>"); + output.append("<gContact:relation rel=\"assistant\">").append(Qt::escape(assistant).toUtf8()).append("</gContact:relation>"); parsedCustoms << "KADDRESSBOOK-X-AssistantsName"; } /* Anniversary */ QString anniversary = contact->anniversary(); if (!anniversary.isEmpty()) { - output.append("<gContact:event rel=\"anniversary\"><gd:when startTime=\"").append(anniversary.toUtf8()).append("\" /></gContact:event>"); + output.append("<gContact:event rel=\"anniversary\"><gd:when startTime=\"").append(Qt::escape(anniversary).toUtf8()).append("\" /></gContact:event>"); parsedCustoms << "KADDRESSBOOK-X-Anniversary"; } /* Homepage */ if (!contact->url().isEmpty()) - output.append("<gContact:website rel=\"home-page\" href=\"").append(contact->url().prettyUrl().toUtf8()).append("\" />"); + output.append("<gContact:website rel=\"home-page\" href=\"").append(Qt::escape(contact->url().prettyUrl()).toUtf8()).append("\" />"); /* Blog */ QString blog = contact->blogFeed(); if (!blog.isEmpty()) { - output.append("<gContact:website rel=\"blog\" href=\"").append(blog.toUtf8()).append("\" />"); + output.append("<gContact:website rel=\"blog\" href=\"").append(Qt::escape(blog).toUtf8()).append("\" />"); parsedCustoms << "KADDRESSBOOK-BlogFeed"; } /* Emails */ Q_FOREACH(const QString &email, contact->emails()) { - output.append("<gd:email rel='http://schemas.google.com/g/2005#home' address='").append(email.toUtf8()).append("' />"); + output.append("<gd:email rel='http://schemas.google.com/g/2005#home' address='").append(Qt::escape(email).toUtf8()).append("' />"); } /* IMs */ @@ -660,6 +671,17 @@ bool primary = (contact->custom("KADDRESSBOOK", "X-IMAddress") == value); output.append(im_str.arg(value, Objects::Contact::IMProtocolNameToScheme(proto), (primary ? "true" : "false")).toUtf8()); parsedCustoms << key; + /* X-messaging is probably a new key (?) used by KAddressbook when importing + * contacts from vCard. */ + } else if (im.startsWith(QLatin1String("X-messaging"))) { + const QString key = im.left(im.indexOf(QLatin1Char(':'))); + const QString value = im.mid(im.indexOf(QLatin1Char(':')) + 1); + QString proto = key.mid(12); /* strlen("X-messaging/") */ + if (proto.endsWith(QLatin1String("-All"))) { + proto.chop(4); + } + output.append(im_str.arg(value, proto, QLatin1String("false")).toUtf8()); + parsedCustoms << key; } } parsedCustoms << "KADDRESSBOOK-X-IMAddress"; @@ -677,24 +699,33 @@ .append("'>"); if (!address.locality().isEmpty()) - output.append("<gd:city>").append(address.locality().toUtf8()).append("</gd:city>"); + output.append("<gd:city>").append(Qt::escape(address.locality()).toUtf8()).append("</gd:city>"); if (!address.street().isEmpty()) - output.append("<gd:street>").append(address.street().toUtf8()).append("</gd:street>"); + output.append("<gd:street>").append(Qt::escape(address.street()).toUtf8()).append("</gd:street>"); if (!address.region().isEmpty()) - output.append("<gd:region>").append(address.region().toUtf8()).append("</gd:region>"); + output.append("<gd:region>").append(Qt::escape(address.region()).toUtf8()).append("</gd:region>"); if (!address.postalCode().isEmpty()) - output.append("<gd:postcode>").append(address.postalCode().toUtf8()).append("</gd:postcode>"); + output.append("<gd:postcode>").append(Qt::escape(address.postalCode()).toUtf8()).append("</gd:postcode>"); if (!address.country().isEmpty()) - output.append("<gd:country>").append(address.country().toUtf8()).append("</gd:country>"); + output.append("<gd:country>").append(Qt::escape(address.country()).toUtf8()).append("</gd:country>"); if (!address.formattedAddress().isEmpty()) - output.append("<gd:formattedAddress>").append(address.formattedAddress().toUtf8()).append("</gd:formattedAddress>"); + output.append("<gd:formattedAddress>").append(Qt::escape(address.formattedAddress()).toUtf8()).append("</gd:formattedAddress>"); output.append("</gd:structuredPostalAddress>"); } /* Birthday */ QDate birthday = contact->birthday().date(); if (birthday.isValid()) { - QString birthdayStr = birthday.toString("yyyy-MM-dd"); + QString birthdayStr; + /* We use year 1900 as a fake year for birthdays without a year specified. + * Here we assume that nobody actually has a contact born in 1900 and so + * we replace 1900 by "-", so that we get "--MM-dd" date, which is a valid + * birthday date according to RFC6350 */ + if (birthday.year() == 1900) { + birthdayStr = birthday.toString("--MM-dd"); + } else { + birthdayStr = birthday.toString("yyyy-MM-dd"); + } output.append("<gContact:birthday when='").append(birthdayStr.toUtf8()).append("'/>"); } @@ -715,7 +746,7 @@ QString key = customStr.left(customStr.indexOf(':')); if (!parsedCustoms.contains(key)) { QString value = customStr.mid(customStr.indexOf(':') + 1); - output.append(defined_str.arg(key, value).toUtf8()); + output.append(defined_str.arg(Qt::escape(key), Qt::escape(value)).toUtf8()); } } @@ -730,8 +761,8 @@ output.append("<atom:category scheme=\"http://schemas.google.com/g/2005#kind\" " "term=\"http://schemas.google.com/g/2005#group\"/>"); - output.append("<atom:title type=\"text\">").append(group->title().toUtf8()).append("</atom:title>"); - output.append("<atom:content type=\"text\">").append(group->content().toUtf8()).append("</atom:content>"); + output.append("<atom:title type=\"text\">").append(Qt::escape(group->title()).toUtf8()).append("</atom:title>"); + output.append("<atom:content type=\"text\">").append(Qt::escape(group->content()).toUtf8()).append("</atom:content>"); return output; } @@ -979,7 +1010,14 @@ /* Birthday */ if (e.tagName() == "gContact:birthday") { - contact->setBirthday(QDateTime::fromString(e.attribute("when"), "yyyy-MM-dd")); + QString birthday = e.attribute("when"); + /* Birthdays in format "--MM-DD" are valid and mean that no year has + * been specified. Since KABC does not support birthdays without year, + * we simulate that by specifying a fake year - 1900 */ + if (birthday.startsWith("--")) { + birthday = "1900" + birthday.mid(1); + } + contact->setBirthday(QDateTime::fromString(birthday, "yyyy-MM-dd")); continue; } -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org
participants (1)
-
root@hilbert.suse.de