From f5dfb1faa646f3705a5789f7bdf3ece561697596 Mon Sep 17 00:00:00 2001 From: tpearson Date: Tue, 22 Jun 2010 21:54:39 +0000 Subject: [PATCH] Added new hidden vCard URI parameter for certain CardDAV systems (such as Zimbra) that do not handle UID properly git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1141499 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kabc/scripts/addressee.src.cpp | 19 +++++++ kabc/scripts/addressee.src.h | 13 +++++ kabc/vcard/Enum.cpp | 96 +++++++++++++++++--------------- kabc/vcard/include/VCardEnum.h | 5 +- kabc/vcardformatimpl.cpp | 5 ++ kabc/vcardparser/vcardparser.cpp | 86 +++++++++++++++------------- kabc/vcardtool.cpp | 7 +++ 7 files changed, 147 insertions(+), 84 deletions(-) diff --git a/kabc/scripts/addressee.src.cpp b/kabc/scripts/addressee.src.cpp index 887290c8f..1735da995 100644 --- a/kabc/scripts/addressee.src.cpp +++ b/kabc/scripts/addressee.src.cpp @@ -47,6 +47,7 @@ KABC::SortMode *Addressee::mSortMode = 0; struct Addressee::AddresseeData : public KShared { QString uid; + QString uri; --VARIABLES-- PhoneNumber::List phoneNumbers; @@ -180,6 +181,24 @@ QString Addressee::uidLabel() return i18n("Unique Identifier"); } +void Addressee::setUri( const QString &id ) +{ + if ( id == mData->uri ) return; + detach(); + mData->empty = false; + mData->uri = id; +} + +QString Addressee::uri() const +{ + return mData->uri; +} + +QString Addressee::uriLabel() +{ + return i18n("Unique Resource Identifier"); +} + --DEFINITIONS-- void Addressee::setNameFromString( const QString &s ) diff --git a/kabc/scripts/addressee.src.h b/kabc/scripts/addressee.src.h index abceb052a..edb63ae60 100644 --- a/kabc/scripts/addressee.src.h +++ b/kabc/scripts/addressee.src.h @@ -110,6 +110,19 @@ class KABC_EXPORT Addressee */ static QString uidLabel(); + /** + Set unique resource identifier. + */ + void setUri( const QString &uid ); + /** + Return unique resource identifier. + */ + QString uri() const; + /** + Return translated label for uri field. + */ + static QString uriLabel(); + --DECLARATIONS-- /** Set name fields by parsing the given string and trying to associate the diff --git a/kabc/vcard/Enum.cpp b/kabc/vcard/Enum.cpp index cc48b5a57..c2a0eeab3 100644 --- a/kabc/vcard/Enum.cpp +++ b/kabc/vcard/Enum.cpp @@ -2,7 +2,7 @@ libvcard - vCard parsing library for vCard version 3.0 Copyright (C) 1998 Rik Hemsley rik@kde.org - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the @@ -29,6 +29,8 @@ using namespace VCARD; // There are 31 possible types, not including extensions. +// URI is a custom field designed to store the upstream URI for each contact +// in order to handle certain limited CardDAV systems such as Zimbra const QCString VCARD::paramNames [] = { @@ -62,7 +64,8 @@ VCARD::paramNames [] = "URL", "VERSION", "CLASS", - "KEY" + "KEY", + "URI" }; const ParamType @@ -99,6 +102,7 @@ VCARD::paramTypesTable[] = { ParamNone, // CLASS ParamTextBin, // KEY ParamTextNS // X + ParamNone, // URI }; ParamType @@ -107,31 +111,31 @@ VCARD::EntityTypeToParamType(EntityType e) ParamType t(ParamUnknown); switch (e) { - - //---------------------------------------------------------------// + + //---------------------------------------------------------------// case EntityAgent: t = ParamAgent; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntitySound: t = ParamSound; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntitySource: t = ParamSource; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityTelephone: t = ParamTel; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityEmail: t = ParamEmail; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityKey: t = ParamTextBin; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityExtension: t = ParamTextNS; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityAddress: case EntityLabel: t = ParamAddrText; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityBirthday: case EntityRevision: t = ParamDate; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityPhoto: case EntityLogo: t = ParamImage; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityOrganisation: case EntityTitle: case EntityRole: @@ -142,7 +146,7 @@ VCARD::EntityTypeToParamType(EntityType e) case EntityNickname: case EntityCategories: case EntityNote: t = ParamText; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityProductID: case EntityTimeZone: case EntityUID: @@ -152,11 +156,12 @@ VCARD::EntityTypeToParamType(EntityType e) case EntityName: case EntityVersion: case EntityProfile: + case EntityURI: default: t = ParamNone; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// } - + return t; } @@ -166,40 +171,40 @@ VCARD::EntityTypeToValueType(EntityType e) ValueType t(ValueUnknown); switch (e) { - - //---------------------------------------------------------------// + + //---------------------------------------------------------------// case EntitySound: t = ValueSound; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityAgent: t = ValueAgent; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityAddress: t = ValueAddress; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityTelephone: t = ValueTel; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityKey: t = ValueTextBin; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityOrganisation: t = ValueOrg; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityN: t = ValueN; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityTimeZone: t = ValueUTC; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityClass: t = ValueClass; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityGeo: t = ValueGeo; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntitySource: case EntityURL: t = ValueURI; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityPhoto: case EntityLogo: t = ValueImage; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityBirthday: case EntityRevision: t = ValueDate; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityCategories: case EntityNickname: t = ValueTextList; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// case EntityLabel: case EntityExtension: case EntityEmail: @@ -214,11 +219,12 @@ VCARD::EntityTypeToValueType(EntityType e) case EntityProfile: case EntityUID: case EntityNote: + case EntityURI: default: t = ValueText; break; - //---------------------------------------------------------------// + //---------------------------------------------------------------// } - + return t; } @@ -233,9 +239,9 @@ VCARD::EntityTypeToParamName(EntityType e) VCARD::EntityNameToEntityType(const QCString & s) { if (s.isEmpty()) return EntityUnknown; - + EntityType t(EntityUnknown); - + switch (s[0]) { case 'A': @@ -288,7 +294,7 @@ VCARD::EntityNameToEntityType(const QCString & s) if (s == "MAILER") t = EntityMailer; break; - + case 'N': if (s == "N") t = EntityN; @@ -313,14 +319,14 @@ VCARD::EntityNameToEntityType(const QCString & s) else if (s == "PROFILE") t = EntityProfile; break; - + case 'R': if (s == "REV") t = EntityRevision; else if (s == "ROLE") t = EntityRole; break; - + case 'S': if (s == "SORT-STRING") t = EntitySortString; @@ -344,6 +350,8 @@ VCARD::EntityNameToEntityType(const QCString & s) t = EntityUID; else if (s == "URL") t = EntityURL; + else if (s == "URI") + t = EntityURI; case 'V': if (s == "VERSION") t = EntityVersion; @@ -353,12 +361,12 @@ VCARD::EntityNameToEntityType(const QCString & s) if (s.left(2) == "X-") t = EntityExtension; break; - + default: - + t = EntityUnknown; } - + return t; } @@ -389,7 +397,7 @@ VCARD::EntityNameToEntityType(const QCString & s) * */ -static char B64[] = +static char B64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // the mime base64 disctionary used for decoding diff --git a/kabc/vcard/include/VCardEnum.h b/kabc/vcard/include/VCardEnum.h index 485a13e16..cd55632f6 100644 --- a/kabc/vcard/include/VCardEnum.h +++ b/kabc/vcard/include/VCardEnum.h @@ -1,8 +1,8 @@ /* libvcard - vCard parsing library for vCard version 3.0 - + Copyright (C) 1999 Rik Hemsley rik@kde.org - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the @@ -61,6 +61,7 @@ enum EntityType { EntitySortString, EntitySound, EntityUID, + EntityURI, EntityURL, EntityVersion, EntityClass, diff --git a/kabc/vcardformatimpl.cpp b/kabc/vcardformatimpl.cpp index cfaccd056..51e6f2eb5 100644 --- a/kabc/vcardformatimpl.cpp +++ b/kabc/vcardformatimpl.cpp @@ -137,6 +137,10 @@ bool VCardFormatImpl::loadAddressee( Addressee& addressee, VCARD::VCard &v ) addressee.setUid( readTextValue( cl ) ); break; + case EntityURI: + addressee.setUri( readTextValue( cl ) ); + break; + case EntityEmail: addressee.insertEmail( readTextValue( cl ) ); break; @@ -278,6 +282,7 @@ void VCardFormatImpl::saveAddressee( const Addressee &addressee, VCARD::VCard *v addTextValue( v, EntityName, addressee.name() ); addTextValue( v, EntityUID, addressee.uid() ); + addTextValue( v, EntityURI, addressee.uri() ); addTextValue( v, EntityFullName, addressee.formattedName() ); QStringList emails = addressee.emails(); diff --git a/kabc/vcardparser/vcardparser.cpp b/kabc/vcardparser/vcardparser.cpp index 34c13c68a..df622b22f 100644 --- a/kabc/vcardparser/vcardparser.cpp +++ b/kabc/vcardparser/vcardparser.cpp @@ -227,54 +227,64 @@ QString VCardParser::createVCards( const VCard::List& list ) // iterate over the lines for ( lineIt = lines.constBegin(); lineIt != lines.constEnd(); ++lineIt ) { if ( !(*lineIt).value().asString().isEmpty() ) { - if ( (*lineIt).hasGroup() ) - textLine = (*lineIt).group() + "." + (*lineIt).identifier(); - else - textLine = (*lineIt).identifier(); - - params = (*lineIt).parameterList(); - hasEncoding = false; - if ( params.count() > 0 ) { // we have parameters - for ( paramIt = params.begin(); paramIt != params.end(); ++paramIt ) { - if ( (*paramIt) == "encoding" ) { - hasEncoding = true; - encodingType = (*lineIt).parameter( "encoding" ).lower(); + if ((*lineIt).identifier() != QString("URI")) { + if ( (*lineIt).hasGroup() ) + textLine = (*lineIt).group() + "." + (*lineIt).identifier(); + else + textLine = (*lineIt).identifier(); + + params = (*lineIt).parameterList(); + hasEncoding = false; + if ( params.count() > 0 ) { // we have parameters + for ( paramIt = params.begin(); paramIt != params.end(); ++paramIt ) { + if ( (*paramIt) == "encoding" ) { + hasEncoding = true; + encodingType = (*lineIt).parameter( "encoding" ).lower(); + } + + values = (*lineIt).parameters( *paramIt ); + for ( valueIt = values.constBegin(); valueIt != values.constEnd(); ++valueIt ) { + textLine.append( ";" + (*paramIt).upper() ); + if ( !(*valueIt).isEmpty() ) + textLine.append( "=" + (*valueIt) ); + } } + } - values = (*lineIt).parameters( *paramIt ); - for ( valueIt = values.constBegin(); valueIt != values.constEnd(); ++valueIt ) { - textLine.append( ";" + (*paramIt).upper() ); - if ( !(*valueIt).isEmpty() ) - textLine.append( "=" + (*valueIt) ); + if ( hasEncoding ) { // have to encode the data + QByteArray input, output; + if ( encodingType == "b" ) { + input = (*lineIt).value().toByteArray(); + KCodecs::base64Encode( input, output ); + } else if ( encodingType == "quoted-printable" ) { + input = (*lineIt).value().toString().utf8(); + input.resize( input.size() - 1 ); // strip \0 + KCodecs::quotedPrintableEncode( input, output, false ); } - } - } - if ( hasEncoding ) { // have to encode the data - QByteArray input, output; - if ( encodingType == "b" ) { - input = (*lineIt).value().toByteArray(); - KCodecs::base64Encode( input, output ); - } else if ( encodingType == "quoted-printable" ) { - input = (*lineIt).value().toString().utf8(); - input.resize( input.size() - 1 ); // strip \0 - KCodecs::quotedPrintableEncode( input, output, false ); + QString value( output ); + addEscapes( value ); + textLine.append( ":" + value ); + } else { + QString value( (*lineIt).value().asString() ); + addEscapes( value ); + textLine.append( ":" + value ); } - QString value( output ); - addEscapes( value ); - textLine.append( ":" + value ); - } else { + if ( textLine.length() > FOLD_WIDTH ) { // we have to fold the line + for ( uint i = 0; i <= ( textLine.length() / FOLD_WIDTH ); ++i ) + text.append( ( i == 0 ? "" : " " ) + textLine.mid( i * FOLD_WIDTH, FOLD_WIDTH ) + "\r\n" ); + } else + text.append( textLine + "\r\n" ); + } + else { + // URIs can be full of weird symbols, etc. so bypass all checks + textLine = (*lineIt).identifier(); QString value( (*lineIt).value().asString() ); addEscapes( value ); textLine.append( ":" + value ); - } - - if ( textLine.length() > FOLD_WIDTH ) { // we have to fold the line - for ( uint i = 0; i <= ( textLine.length() / FOLD_WIDTH ); ++i ) - text.append( ( i == 0 ? "" : " " ) + textLine.mid( i * FOLD_WIDTH, FOLD_WIDTH ) + "\r\n" ); - } else text.append( textLine + "\r\n" ); + } } } } diff --git a/kabc/vcardtool.cpp b/kabc/vcardtool.cpp index d9fdd03a8..566b5968d 100644 --- a/kabc/vcardtool.cpp +++ b/kabc/vcardtool.cpp @@ -320,6 +320,9 @@ QString VCardTool::createVCards( Addressee::List list, VCard::Version version ) // UID card.addLine( VCardLine( "UID", (*addrIt).uid() ) ); + // UID + card.addLine( VCardLine( "URI", (*addrIt).uri() ) ); + // URL card.addLine( VCardLine( "URL", (*addrIt).url().url() ) ); @@ -580,6 +583,10 @@ Addressee::List VCardTool::parseVCards( const QString& vcard ) else if ( identifier == "uid" ) addr.setUid( (*lineIt).value().asString() ); + // URI + else if ( identifier == "uri" ) + addr.setUri( (*lineIt).value().asString() ); + // URL else if ( identifier == "url" ) addr.setUrl( KURL( (*lineIt).value().asString() ) );