5 commits - c++/lib c++/tests schemas/kolabformat-xcard.xsd

Christian Mollekopf mollekopf at kolabsys.com
Fri Mar 16 17:04:06 CET 2012


 c++/lib/incidence_p.h            |    3 
 c++/lib/kolabcontact.cpp         |    6 -
 c++/lib/kolabcontact.h           |   64 ++++++++-----
 c++/lib/kolabcontainers.cpp      |   42 ++------
 c++/lib/kolabcontainers.h        |   52 ++++++++--
 c++/lib/kolabevent.cpp           |   14 --
 c++/lib/kolabevent.h             |    5 -
 c++/lib/kolabformat.i            |    2 
 c++/lib/kolabkcalconversion.cpp  |   17 +--
 c++/lib/kolabtodo.cpp            |   14 --
 c++/lib/kolabtodo.h              |    5 -
 c++/lib/shared_conversions.h     |   45 +++++++++
 c++/lib/xcalconversions.h        |   60 ++++++------
 c++/lib/xcardconversions.h       |  188 ++++++++++++++++++++++++++++-----------
 c++/tests/bindingstest.cpp       |   61 ++++++------
 c++/tests/conversiontest.cpp     |   19 +++
 c++/tests/conversiontest.h       |    2 
 c++/tests/kcalconversiontest.cpp |    8 -
 c++/tests/serializers.h          |   58 ++++++------
 schemas/kolabformat-xcard.xsd    |   58 +++++++++++-
 20 files changed, 468 insertions(+), 255 deletions(-)

New commits:
commit c54f228f0df55ff9be5263c5ff68af2847be20d4
Merge: dde54ba 39ddb5d
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Fri Mar 16 17:04:01 2012 +0100

    Merge branch 'master' of ssh://git.kolabsys.com/git/libkolabxml



commit dde54ba6086c1aef5a416b41d32c3d14eb552f90
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Fri Mar 16 17:00:39 2012 +0100

    organisational units

diff --git a/c++/lib/kolabcontact.h b/c++/lib/kolabcontact.h
index ea5c4c3..2402995 100644
--- a/c++/lib/kolabcontact.h
+++ b/c++/lib/kolabcontact.h
@@ -53,6 +53,7 @@ private:
 
 struct Affiliation {
     bool operator==(const Affiliation &other) const { return mOrg == other.mOrg &&
+                                                    mOrgUnits == other.mOrgUnits &&
                                                     mLogo == other.mLogo &&
                                                     mLogoMimetype == other.mLogoMimetype &&
                                                     mTitles == other.mTitles &&
@@ -63,7 +64,8 @@ struct Affiliation {
                                                     };
     void setOrganisation(const std::string &org) { mOrg = org; };
     std::string organisation() const { return mOrg; };
-//     void setOrganisationalUnits(const std::vector<std::string> &units);
+    void setOrganisationalUnits(const std::vector<std::string> &units) { mOrgUnits = units; };
+    std::vector<std::string> organisationalUnits() const { return mOrgUnits; };
     void setLogo(const std::string &l, const std::string mimetype) { mLogo = l; mLogoMimetype = mimetype; };
     std::string logo() const { return mLogo; };
     std::string logoMimetype() const { return mLogoMimetype; };
diff --git a/c++/lib/xcardconversions.h b/c++/lib/xcardconversions.h
index a2ac642..c2ea691 100644
--- a/c++/lib/xcardconversions.h
+++ b/c++/lib/xcardconversions.h
@@ -302,6 +302,9 @@ void writeCard<Kolab::Contact>(vcard_4_0::vcard &vcard, const Kolab::Contact &co
         BOOST_FOREACH(const Affiliation &a, contact.affiliations()) {
             affiliationPropType::org_type org;
             org.text().push_back(a.organisation());
+            BOOST_FOREACH(const std::string &unit, a.organisationalUnits()) {
+                org.text().push_back(unit);
+            }
             vcard::group_type group(org);
             if (!a.logo().empty()) {
                 group.logo(affiliationPropType::logo_type(uriInlineEncoding(a.logo(), a.logoMimetype())));
@@ -612,13 +615,16 @@ boost::shared_ptr<Kolab::Contact> readCard <Kolab::Contact> (const vcard_4_0::Vc
         std::vector<Kolab::Affiliation> list;
         BOOST_FOREACH (const vcard::group_type &group, vcard.group()) {
             Kolab::Affiliation aff;
-            std::string org;
             if (!group.org().text().empty()) {
-                org = *group.org().text().begin();
+                aff.setOrganisation(*group.org().text().begin());
+                std::vector<std::string> units;
+                for ( vcard_4_0::NonEmptyTextListPropertyType::text_const_iterator it = ++group.org().text().begin(); it != group.org().text().end(); it++) {
+                    units.push_back(*it);
+                }
+                aff.setOrganisationalUnits(units);
             } else {
                 WARNING("No org present");
             }
-            aff.setOrganisation(org);
             std::string mimetype;
             if (group.logo()) {
                 const std::string &logo = uriInlineDecoding((*group.logo()).uri(), mimetype);
diff --git a/c++/tests/bindingstest.cpp b/c++/tests/bindingstest.cpp
index 4c7a829..66d5f28 100644
--- a/c++/tests/bindingstest.cpp
+++ b/c++/tests/bindingstest.cpp
@@ -360,6 +360,7 @@ void BindingsTest::contactCompletness()
     std::vector<Kolab::Affiliation> list;
     Kolab::Affiliation aff;
     aff.setOrganisation("org");
+    aff.setOrganisationalUnits(stringlist);
     aff.setLogo("logo", "mime/miem");
     aff.setTitles(stringlist);
     aff.setRoles(stringlist);
diff --git a/c++/tests/serializers.h b/c++/tests/serializers.h
index b07a1b9..7d4cb70 100644
--- a/c++/tests/serializers.h
+++ b/c++/tests/serializers.h
@@ -169,9 +169,9 @@ namespace QTest {
     char *toString(const Kolab::Affiliation &a)
     {
         QByteArray ba = "Kolab::Affiliation(";
-        ba += QString::fromStdString(a.organisation()).toAscii()+ ", " + 
-        QString::fromStdString(a.logo()).toAscii()+", " +toString(a.titles()) + ", " + toString(a.roles())+  ", " + toString(a.managers()) +
-        + toString(a.assistants())  + ", " + toString(a.offices());
+        ba += QString::fromStdString(a.organisation()).toAscii()+ "\n " + 
+        QString::fromStdString(a.logo()).toAscii()+"\n " +toString(a.titles()) + "\n " + toString(a.roles())+  "\n " + toString(a.managers()) + "\n " +
+        toString(a.assistants())  + "\n " + toString(a.offices()) + "\n ";
         ba += ")";
         return qstrdup(ba.data());
     }


commit e46df10bcf9bdf9b893584ea471265e5199ebea3
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Fri Mar 16 16:43:38 2012 +0100

    Make use of ContactReference, to reference contacts using either mailto or urn.

diff --git a/c++/lib/incidence_p.h b/c++/lib/incidence_p.h
index 99f1883..5f2dc12 100644
--- a/c++/lib/incidence_p.h
+++ b/c++/lib/incidence_p.h
@@ -50,8 +50,7 @@ namespace Kolab {
         RecurrenceRule rrule;
         std::vector< cDateTime > recurrenceDates;
         std::vector< cDateTime > exceptionDates;
-        std::string organizerEmail;
-        std::string organizerName;
+        ContactReference organizer;
         Duration duration;
         
         std::vector<Attendee> attendees;
diff --git a/c++/lib/kolabcontact.cpp b/c++/lib/kolabcontact.cpp
index 8da79c4..9bd26aa 100644
--- a/c++/lib/kolabcontact.cpp
+++ b/c++/lib/kolabcontact.cpp
@@ -28,7 +28,7 @@ struct DistList::Private
     std::vector< std::string > categories;
     
     std::string name;
-    std::vector<Member> members;
+    std::vector<ContactReference> members;
     std::vector<CustomProperty> customProperties;
 };
     
@@ -89,12 +89,12 @@ std::string DistList::name() const
     return d->name;
 }
 
-void DistList::setMembers(const std::vector< Member > &members)
+void DistList::setMembers(const std::vector< ContactReference > &members)
 {
     d->members = members;
 }
 
-std::vector< Member > DistList::members() const
+std::vector< ContactReference > DistList::members() const
 {
     return d->members;
 }
diff --git a/c++/lib/kolabcontact.h b/c++/lib/kolabcontact.h
index 2f6a09b..ea5c4c3 100644
--- a/c++/lib/kolabcontact.h
+++ b/c++/lib/kolabcontact.h
@@ -218,28 +218,6 @@ private:
     CryptoPref mEncryptPref;
 };
 
-struct Member {
-    Member(){};
-    Member(const std::string &email): mEmail(email) {};
-    bool operator==(const Member &other) const { return mEmail == other.mEmail &&
-                                                mName == other.mName &&
-                                                mUid == mUid;
-    };
-    
-    void setEmail(const std::string &email) { mEmail = email; };
-    std::string email() const { return mEmail; };
-    
-    void setName(const std::string &name) { mName = name; };
-    std::string name() const { return mName; };
-    
-    void setUid(const std::string &uid) { mUid = uid; };
-    std::string uid() const { return mUid; };
-    
-private:
-    std::string mEmail;
-    std::string mName;
-    std::string mUid;
-};
 
 class DistList {
 public:
@@ -259,8 +237,8 @@ public:
     void setName(const std::string &);
     std::string name() const;
 
-    void setMembers(const std::vector<Member> &);
-    std::vector<Member> members() const;
+    void setMembers(const std::vector<ContactReference> &);
+    std::vector<ContactReference> members() const;
 
     void setCustomProperties(const std::vector<CustomProperty> &);
     std::vector<CustomProperty> customProperties() const;
diff --git a/c++/lib/kolabcontainers.cpp b/c++/lib/kolabcontainers.cpp
index 65201d0..491f9d7 100644
--- a/c++/lib/kolabcontainers.cpp
+++ b/c++/lib/kolabcontainers.cpp
@@ -399,10 +399,8 @@ struct Attendee::Private
     role(Required),
     rsvp(false){};
     
-    std::string email;
-    std::string name;
+    ContactReference contact;
     PartStatus partStat;
-    std::string uid;
     Role role;
     bool rsvp;
 };
@@ -413,10 +411,10 @@ Attendee::Attendee()
 
 }
 
-Attendee::Attendee(const std::string& email)
+Attendee::Attendee(const ContactReference& contact)
 :   d(new Attendee::Private)
 {
-   d->email = email; 
+    d->contact = contact; 
 }
 
 Attendee::Attendee(const Kolab::Attendee &other)
@@ -437,10 +435,8 @@ Attendee::~Attendee()
 
 bool Attendee::operator==(const Kolab::Attendee &other) const
 {
-    if ( d->email == other.email() &&
-        d->name == other.name() &&
+    if ( d->contact == other.contact() &&
         d->partStat == other.partStat() &&
-        d->uid == other.uid() &&
         d->role == other.role() &&
         d->rsvp== other.rsvp()) {
         return true;
@@ -450,23 +446,19 @@ bool Attendee::operator==(const Kolab::Attendee &other) const
 
 bool Attendee::isValid() const 
 { 
-    return !d->email.empty();
+    return d->contact.isValid();
 };
 
-std::string Attendee::email() const
+void Attendee::setContact(const ContactReference &c)
 {
-    return d->email;
+    d->contact = c;
 }
 
-void Attendee::setName(const std::string &name)
+ContactReference Attendee::contact() const
 {
-    d->name = name;
+    return d->contact;
 }
 
-std::string Attendee::name() const
-{
-    return d->name;
-}
 
 void Attendee::setPartStat(PartStatus partStat)
 {
@@ -478,16 +470,6 @@ PartStatus Attendee::partStat() const
     return d->partStat;
 }
 
-void Attendee::setUid(const std::string &uid)
-{
-    d->uid = uid;
-}
-
-std::string Attendee::uid() const
-{
-    return d->uid;
-}
-
 void Attendee::setRole(Role role)
 {
     d->role = role;
@@ -598,7 +580,7 @@ struct Alarm::Private
     std::string text;
     Attachment audioFile;
     std::string summary;
-    std::vector<std::string> attendees;
+    std::vector<ContactReference> attendees;
     cDateTime start;
     Duration relativeDuration;
     Relative relativeTo;
@@ -628,7 +610,7 @@ Alarm::Alarm(const Kolab::Attachment& audio)
     d->type = AudioAlarm;
 }
 
-Alarm::Alarm(const std::string& summary, const std::string& description, const std::vector< std::string > attendees)
+Alarm::Alarm(const std::string& summary, const std::string& description, const std::vector<ContactReference> attendees)
 :   d(new Alarm::Private)
 {
     d->summary = summary;
@@ -687,7 +669,7 @@ std::string Alarm::description() const
     return d->text;
 }
 
-std::vector< std::string > Alarm::attendees() const
+std::vector<ContactReference> Alarm::attendees() const
 {
     return d->attendees;
 }
diff --git a/c++/lib/kolabcontainers.h b/c++/lib/kolabcontainers.h
index 3f8d1ba..50a74d2 100644
--- a/c++/lib/kolabcontainers.h
+++ b/c++/lib/kolabcontainers.h
@@ -167,6 +167,43 @@ private:
     bool valid;
 };
 
+struct ContactReference {
+    enum ReferenceType {
+        Invalid,
+        EmailReference,
+        UrnReference
+    };
+    ContactReference(): mType(Invalid) {};
+    ContactReference(ReferenceType type, const std::string &emailOrUID, const std::string &name = std::string()): mType(type), mName(name) { 
+        if (type == EmailReference) {
+            mEmail = emailOrUID;
+        } else {
+            mUid = emailOrUID;
+        }
+    };
+    bool operator==(const ContactReference &other) const { return mType == other.mType &&
+                                                        mEmail == other.mEmail &&
+                                                        mName == other.mName &&
+                                                        mUid == mUid;
+    };
+
+    bool isValid() const { return mType != Invalid; };
+
+    void setName(const std::string &name) { mName = name; };
+
+    std::string email() const { return mEmail; };
+    std::string uid() const { return mUid; };
+    std::string name() const { return mName; };
+
+    ReferenceType type() const { return mType; };
+
+private:
+    ReferenceType mType;
+    std::string mEmail;
+    std::string mUid;
+    std::string mName;
+};
+
 class Alarm {
 public:
     enum Type {
@@ -184,10 +221,10 @@ public:
     bool operator==(const Alarm &other) const;
 
     ///EMail Alarm
-    Alarm(const std::string &summary, const std::string &description, const std::vector<std::string> attendees);
+    Alarm(const std::string &summary, const std::string &description, const std::vector<ContactReference> attendees);
     std::string summary() const;
     std::string description() const;
-    std::vector<std::string> attendees() const;
+    std::vector<ContactReference> attendees() const;
 
     ///Display Alarm
     Alarm(const std::string &text);
@@ -302,7 +339,7 @@ enum Role {
 class Attendee {
 public:
     Attendee();
-    Attendee(const std::string &email);
+    Attendee(const ContactReference &contact);
     Attendee(const Attendee &);
     ~Attendee();
 
@@ -311,17 +348,12 @@ public:
 
     bool isValid() const;
 
-    std::string email() const;
-
-    void setName(const std::string &);
-    std::string name() const;
+    void setContact(const ContactReference &);
+    ContactReference contact() const;
 
     void setPartStat(PartStatus);
     PartStatus partStat() const;
 
-    void setUid(const std::string &);
-    std::string uid() const;
-
     void setRole(Role);
     Role role() const;
 
diff --git a/c++/lib/kolabevent.cpp b/c++/lib/kolabevent.cpp
index b58f65d..07b4bb0 100644
--- a/c++/lib/kolabevent.cpp
+++ b/c++/lib/kolabevent.cpp
@@ -272,20 +272,14 @@ bool Event::transparency() const
     return d->isTransparent;
 }
 
-void Event::setOrganizer(const std::string& email, const std::string& name)
+void Event::setOrganizer(const ContactReference &organizer)
 {
-    d->organizerEmail = email;
-    d->organizerName = name;
+    d->organizer = organizer;
 }
 
-std::string Event::organizerEmail() const
+ContactReference Event::organizer() const
 {
-    return d->organizerEmail;
-}
-
-std::string Event::organizerName() const
-{
-    return d->organizerName;
+    return d->organizer;
 }
 
 void Event::setAttendees(const std::vector< Attendee > &attendees)
diff --git a/c++/lib/kolabevent.h b/c++/lib/kolabevent.h
index 4235794..415a1e9 100644
--- a/c++/lib/kolabevent.h
+++ b/c++/lib/kolabevent.h
@@ -94,9 +94,8 @@ public:
     void setLocation(const std::string &);
     std::string location() const;
     
-    void setOrganizer(const std::string &email, const std::string &name);
-    std::string organizerEmail() const;
-    std::string organizerName() const;
+    void setOrganizer(const ContactReference &);
+    ContactReference organizer() const;
     
     void setAttendees(const std::vector<Attendee> &);
     std::vector<Attendee> attendees() const;
diff --git a/c++/lib/kolabformat.i b/c++/lib/kolabformat.i
index 8315657..30726f3 100644
--- a/c++/lib/kolabformat.i
+++ b/c++/lib/kolabformat.i
@@ -27,7 +27,7 @@ namespace std {
     %template(vectoralarm) vector<Kolab::Alarm>;
     %template(vectorattachment) vector<Kolab::Attachment>;
     %template(vectorattendee) vector<Kolab::Attendee>;
-    %template(vectormember) vector<Kolab::Member>;
+    %template(vectorcontactref) vector<Kolab::ContactReference>;
     %template(vectorrelated) vector<Kolab::Related>;
     %template(vectortelephone) vector<Kolab::Telephone>;
     %template(vectordatetime) vector<Kolab::cDateTime>;
diff --git a/c++/lib/kolabkcalconversion.cpp b/c++/lib/kolabkcalconversion.cpp
index f7c8c21..bb1e0c3 100644
--- a/c++/lib/kolabkcalconversion.cpp
+++ b/c++/lib/kolabkcalconversion.cpp
@@ -334,12 +334,12 @@ void setIncidence(KCalCore::Incidence &i, const T &e)
     i.setDescription(QString::fromStdString(e.description())); //TODO detect richtext
     i.setStatus(toStatus(e.status()));
     foreach (const Kolab::Attendee a, e.attendees()) {
-        i.addAttendee(KCalCore::Attendee::Ptr(new KCalCore::Attendee(QString::fromStdString(a.name()), 
-                                                                     QString::fromStdString(a.email()), 
+        //We shouldn't rely on a uid if we're going with mail+name and not on mail+name if we're going with UID (of ical btw. and not kaddresee)
+        i.addAttendee(KCalCore::Attendee::Ptr(new KCalCore::Attendee(QString::fromStdString(a.contact().name()), 
+                                                                     QString::fromStdString(a.contact().email()),  //TODO handle uid
                                                                      a.rsvp(),
                                                                      toPartStat(a.partStat()),
-                                                                     toRole(a.role()),
-                                                                     QString::fromStdString(a.uid()) )));
+                                                                     toRole(a.role()) ))); //FIXME doesn't make sense to set both, either email or uid
     }
     foreach (const Kolab::Attachment a, e.attachments()) {
         KCalCore::Attachment::Ptr ptr;
@@ -373,12 +373,11 @@ void getIncidence(T &i, const I &e)
     i.setStatus(fromStatus(e.status()));
     std::vector<Kolab::Attendee> attendees;
     foreach (const KCalCore::Attendee::Ptr ptr, e.attendees()) {
-        Kolab::Attendee a(ptr->email().toStdString());
-        a.setName(ptr->name().toStdString());
+        Kolab::Attendee a(Kolab::ContactReference(Kolab::ContactReference::EmailReference, ptr->email().toStdString(), ptr->name().toStdString())); //TODO handle uid
         a.setRSVP(ptr->RSVP());
         a.setPartStat(fromPartStat(ptr->status()));
         a.setRole(fromRole(ptr->role()));
-        a.setUid(ptr->uid().toStdString());
+//         a.setUid(ptr->uid().toStdString()); //TODO
         attendees.push_back(a);
     }
     i.setAttendees(attendees);
@@ -649,7 +648,7 @@ void setTodoEvent(KCalCore::Incidence &i, const T &e)
 {
     i.setPriority(toPriority(e.priority()));
     i.setLocation(QString::fromStdString(e.location())); //TODO detect richtext
-    i.setOrganizer(KCalCore::Person::Ptr(new KCalCore::Person(QString::fromStdString(e.organizerName()), QString::fromStdString(e.organizerEmail()))));
+    i.setOrganizer(KCalCore::Person::Ptr(new KCalCore::Person(QString::fromStdString(e.organizer().name()), QString::fromStdString(e.organizer().email())))); //TODO handle uid too
     if (e.recurrenceID().isValid()) {
         i.setRecurrenceId(toDate(e.recurrenceID())); //TODO THISANDFUTURE
     }
@@ -661,7 +660,7 @@ void getTodoEvent(T &i, const I &e)
 {
     i.setPriority(fromPriority(e.priority()));
     i.setLocation(e.location().toStdString());
-    i.setOrganizer(e.organizer()->email().toStdString(),e.organizer()->name().toStdString());
+    i.setOrganizer(Kolab::ContactReference(Kolab::ContactReference::EmailReference, e.organizer()->email().toStdString(), e.organizer()->name().toStdString())); //TODO handle uid too
     i.setRecurrenceID(fromDate(e.recurrenceId()), false); //TODO THISANDFUTURE
     getRecurrence(i, e);
 }
diff --git a/c++/lib/kolabtodo.cpp b/c++/lib/kolabtodo.cpp
index 90b7899..97d2e03 100644
--- a/c++/lib/kolabtodo.cpp
+++ b/c++/lib/kolabtodo.cpp
@@ -274,20 +274,14 @@ std::vector< cDateTime > Todo::exceptionDates() const
     return d->exceptionDates;
 }
 
-void Todo::setOrganizer(const std::string& email, const std::string& name)
+void Todo::setOrganizer(const ContactReference &organizer)
 {
-    d->organizerEmail = email;
-    d->organizerName = name;
+    d->organizer = organizer;
 }
 
-std::string Todo::organizerEmail() const
+ContactReference Todo::organizer() const
 {
-    return d->organizerEmail;
-}
-
-std::string Todo::organizerName() const
-{
-    return d->organizerName;
+    return d->organizer;
 }
 
 void Todo::setAttendees(const std::vector< Attendee > &attendees)
diff --git a/c++/lib/kolabtodo.h b/c++/lib/kolabtodo.h
index b2cf54a..ce547e3 100644
--- a/c++/lib/kolabtodo.h
+++ b/c++/lib/kolabtodo.h
@@ -96,9 +96,8 @@ public:
     void setLocation(const std::string &);
     std::string location() const;
     
-    void setOrganizer(const std::string &email, const std::string &name);
-    std::string organizerEmail() const;
-    std::string organizerName() const;
+    void setOrganizer(const ContactReference &);
+    ContactReference organizer() const;
     
     void setAttendees(const std::vector<Attendee> &);
     std::vector<Attendee> attendees() const;
diff --git a/c++/lib/shared_conversions.h b/c++/lib/shared_conversions.h
index 253a8a8..6602e22 100644
--- a/c++/lib/shared_conversions.h
+++ b/c++/lib/shared_conversions.h
@@ -21,6 +21,7 @@
 #include <xsd/cxx/tree/date-time.hxx>
 #include "kolabcontainers.h"
 #include <boost/shared_ptr.hpp>
+#include "utils.h"
 
 namespace Kolab {
     namespace Shared {
@@ -31,6 +32,8 @@ typedef ::xsd::cxx::tree::simple_type< type > simple_type;
 typedef ::xsd::cxx::tree::date< char, simple_type > date;
 typedef ::xsd::cxx::tree::date_time< char, simple_type > date_time;
 
+using namespace Utils;
+
 cDateTimePtr toDate(const date &dt)
 {
     cDateTimePtr date(new cDateTime());
@@ -66,6 +69,48 @@ date fromDate(const cDateTime &d)
     return de;
 }
 
+std::string toURN(const std::string &uid)
+{
+    if (uid.substr(0, 9) == std::string("urn:uuid:")) {
+        return uid;
+    }
+    return std::string("urn:uuid:")+uid;
+}
+
+std::string fromURN(const std::string &uri)
+{
+    if (uri.substr(0, 9) != std::string("urn:uuid:")) {
+        WARNING("not a urn");
+        return uri;
+    }
+    return uri.substr(9);
+}
+
+Kolab::ContactReference toContactReference(const std::string &uri) {
+    std::string name;
+    if (uri.substr(0, 9) == std::string("urn:uuid:")) {
+        return Kolab::ContactReference(Kolab::ContactReference::UrnReference, fromURN(uri));
+    }
+    const std::string &email = fromMailto(uri, name);
+    return Kolab::ContactReference(Kolab::ContactReference::EmailReference, email, name);
+}
+
+std::string fromContactReference(const Kolab::ContactReference &c, bool embeddName = true) {
+    switch (c.type()) {
+        case ContactReference::UrnReference:
+            return toURN(c.uid());
+        case ContactReference::EmailReference:
+            if (embeddName) {
+                return toMailto(c.email(), c.name());
+            }
+            return toMailto(c.email());
+        case ContactReference::Invalid:
+        default:
+            WARNING("Tried serializing invalid ContactReference");
+    }
+    return std::string();
+}
+
     } //Namespace
 } //Namespace
 
diff --git a/c++/lib/xcalconversions.h b/c++/lib/xcalconversions.h
index e92acf5..1e19491 100644
--- a/c++/lib/xcalconversions.h
+++ b/c++/lib/xcalconversions.h
@@ -351,16 +351,23 @@ Kolab::Duration toDuration(const icalendar_2_0::DurationValueType &d)
 
 
 
-void setCalAddress(const icalendar_2_0::CalAddressPropertyType &cal, std::string &email, std::string &name)
+Kolab::ContactReference toContactReference(const icalendar_2_0::CalAddressPropertyType &cal)
 {
+    Kolab::ContactReference ref = Shared::toContactReference(cal.cal_address());
+    
     if (cal.parameters()) {
         for (icalendar_2_0::ArrayOfParameters::baseParameter_const_iterator it((*cal.parameters()).baseParameter().begin()); it != (*cal.parameters()).baseParameter().end(); it++) {
             if (const icalendar_2_0::CnParamType * tz = dynamic_cast<const icalendar_2_0::CnParamType*> (&*it)) {
-                name = tz->text();
+                if (!ref.name().empty()) {
+                    WARNING("name from mailto uri not empty, overwriting with cn attirbute");
+                    assert(0);
+                }
+                ref.setName(tz->text());
+                break;
             }
         }
     }
-    email = fromMailto(cal.cal_address());
+    return ref;
 }
 
 
@@ -840,12 +847,13 @@ void setIncidenceProperties(I &inc, const T &prop)
     if (prop.attendee().size()) {
         std::vector<Kolab::Attendee> attendees;
         BOOST_FOREACH(typename T::attendee_type aProp, prop.attendee()) {
-            Kolab::Attendee a(fromMailto(toString(aProp.cal_address())));
+            Kolab::Attendee a;
+            std::string name;
             if (aProp.parameters()) {
                 const icalendar_2_0::AttendeePropType::parameters_type &parameters = *aProp.parameters();
                 for (icalendar_2_0::AttendeePropType::parameters_type::baseParameter_const_iterator it(parameters.baseParameter().begin()); it != parameters.baseParameter().end(); it++) {
                     if (const icalendar_2_0::CnParamType * p = dynamic_cast<const icalendar_2_0::CnParamType*> (&*it)) {
-                        a.setName(p->text());
+                        name = p->text();
                     }
                     if (const icalendar_2_0::PartstatParamType * p = dynamic_cast<const icalendar_2_0::PartstatParamType*> (&*it)) {
                         PartStatus s = mapPartStat(p->text());
@@ -862,11 +870,11 @@ void setIncidenceProperties(I &inc, const T &prop)
                     if (const icalendar_2_0::RsvpParamType * p = dynamic_cast<const icalendar_2_0::RsvpParamType*> (&*it)) {
                         a.setRSVP(p->boolean());
                     }
-                    if (const icalendar_2_0::XuidParamType * p = dynamic_cast<const icalendar_2_0::XuidParamType*> (&*it)) {
-                        a.setUid(p->text());
-                    }
                 }
             }
+            Kolab::ContactReference ref = toContactReference(aProp.cal_address());
+            ref.setName(name);
+            a.setContact(ref);
             attendees.push_back(a);
         }
         inc.setAttendees(attendees);
@@ -937,10 +945,7 @@ void setTodoEventProperties(I &inc, const T &prop)
     }
     
     if (prop.organizer()) {
-        std::string email;
-        std::string name;
-        setCalAddress(*prop.organizer(), email, name);
-        inc.setOrganizer(email, name);
+        inc.setOrganizer(toContactReference(*prop.organizer()));
     }
     
 }
@@ -1093,11 +1098,13 @@ void getIncidenceProperties(T &prop, const I &inc)
     if (!inc.attendees().empty()) {        
         
         BOOST_FOREACH(const Kolab::Attendee &a, inc.attendees()) {
-            typename properties::attendee_type attendee(toMailto(a.email()));
+            const Kolab::ContactReference &c = a.contact();
+            
+            typename properties::attendee_type attendee(fromContactReference(c));
             
             typename properties::attendee_type::parameters_type p;
-            if (!a.name().empty()) {
-                icalendar_2_0::CnParamType name(a.name());
+            if (!c.name().empty()) {
+                icalendar_2_0::CnParamType name(c.name());
                 p.baseParameter().push_back(name);
             }
             
@@ -1114,10 +1121,6 @@ void getIncidenceProperties(T &prop, const I &inc)
             if (a.rsvp()) {
                 p.baseParameter().push_back(icalendar_2_0::RsvpParamType(true));
             }
-            
-            if (!a.uid().empty()) {
-                p.baseParameter().push_back(icalendar_2_0::XuidParamType(a.uid()));
-            }
 
             attendee.parameters(p);
             prop.attendee().push_back(attendee);
@@ -1182,11 +1185,11 @@ void getTodoEventProperties(T &prop, const I &inc)
         prop.location(typename properties::location_type(inc.location()));
     }
     
-    if (!inc.organizerEmail().empty()) { //email is required
-        typename properties::organizer_type organizer(toMailto(inc.organizerEmail()));
+    if (inc.organizer().isValid()) {
+        typename properties::organizer_type organizer(fromContactReference(inc.organizer(), false));
         
-        typename properties::organizer_type::parameters_type p; //There is maybe already a timezone set
-        icalendar_2_0::CnParamType name(inc.organizerName());
+        typename properties::organizer_type::parameters_type p;
+        icalendar_2_0::CnParamType name(inc.organizer().name());
         p.baseParameter().push_back(name);
 
         organizer.parameters(p);
@@ -1231,8 +1234,8 @@ void setAlarms(typename KolabType::components_type& components, const IncidenceT
                 p = std::auto_ptr<PropType>(new PropType(PropType::action_type(EMAILALARM), trigger));
                 p->summary(PropType::summary_type(alarm.summary()));
                 p->description(PropType::description_type(alarm.description()));
-                BOOST_FOREACH(const std::string &attendee, alarm.attendees()) {
-                    p->attendee().push_back(icalendar_2_0::ContactType(toMailto(attendee)));
+                BOOST_FOREACH(const Kolab::ContactReference &attendee, alarm.attendees()) {
+                    p->attendee().push_back(icalendar_2_0::ContactType(fromContactReference(attendee)));
                 }
                 break;
             case Kolab::Alarm::AudioAlarm:
@@ -1271,9 +1274,12 @@ void getAlarms(IncidenceType &incidence, const typename KolabType::components_ty
             }
             alarm = Kolab::Alarm((*prop.description()).text());
         } else if (prop.action().text() == EMAILALARM) {
-            std::vector<std::string> attendees;
+            std::vector<Kolab::ContactReference> attendees;
+            if (prop.attendee().empty()) {
+                WARNING("No receipents for email alarm");
+            }
             for (typename PropType::attendee_const_iterator at(prop.attendee().begin()); at != prop.attendee().end(); at++) {
-                attendees.push_back(fromMailto((*at).cal_address()));
+                attendees.push_back(toContactReference((*at).cal_address()));
             }
             if (!prop.description() || !prop.summary()) {
                 ERROR("description or summary is missing");
diff --git a/c++/lib/xcardconversions.h b/c++/lib/xcardconversions.h
index e0525f2..a2ac642 100644
--- a/c++/lib/xcardconversions.h
+++ b/c++/lib/xcardconversions.h
@@ -27,6 +27,7 @@
 #include "global_definitions.h"
 #include "utils.h"
 #include "kolabcontact.h"
+#include "shared_conversions.h"
 
 namespace Kolab {
     namespace XCARD {
@@ -528,14 +529,8 @@ void writeCard<Kolab::DistList>(vcard_4_0::vcard &vcard, const Kolab::DistList &
 {
     if (!distlist.members().empty()) {
         vcard_4_0::vcard::member_sequence members;
-        BOOST_FOREACH (const Kolab::Member &m, distlist.members()) {
-            vcard_4_0::vcard::member_type member(toMailto(m.email(), m.name()));
-            if (!m.uid().empty()) {
-                vcard_4_0::ArrayOfParameters parameters;
-                parameters.baseParameter().push_back(vcard_4_0::xuidParamType(m.uid()));
-                member.parameters(parameters);
-            }
-            members.push_back(member);
+        BOOST_FOREACH (const Kolab::ContactReference &m, distlist.members()) {
+            members.push_back(vcard_4_0::vcard::member_type(Shared::fromContactReference(m)));
         }
         vcard.member(members);
     } else {
@@ -543,22 +538,7 @@ void writeCard<Kolab::DistList>(vcard_4_0::vcard &vcard, const Kolab::DistList &
     }
 }
 
-std::string toURN(const std::string &uid)
-{
-    if (uid.substr(0, 9) == std::string("urn:uuid:")) {
-        return uid;
-    }
-    return std::string("urn:uuid:")+uid;
-}
 
-std::string fromURN(const std::string &uid)
-{
-    if (uid.substr(0, 9) != std::string("urn:uuid:")) {
-        WARNING("not a urn");
-        return uid;
-    }
-    return uid.substr(9);
-}
 
 template <typename T>
 std::string serializeCard(const T &card, const std::string prod = std::string()) {
@@ -568,8 +548,8 @@ std::string serializeCard(const T &card, const std::string prod = std::string())
     clearErrors();
 
     try {
-        vcard_4_0::vcard::uid_type uid(toURN(getUID(card.uid())));
-        setCreatedUid(fromURN(uid.uri()));
+        vcard_4_0::vcard::uid_type uid(Shared::toURN(getUID(card.uid())));
+        setCreatedUid(Shared::fromURN(uid.uri()));
         vcard_4_0::vcard::x_kolab_version_type kolab_version(KOLAB_FORMAT_VERSION);
         vcard_4_0::vcard::prodid_type prodid(prod+KOLAB_LIBNAME+KOLAB_LIB_VERSION);
         vcard_4_0::vcard::rev_type rev(fromDateTime(getCurrentTime()));
@@ -886,21 +866,10 @@ boost::shared_ptr<Kolab::DistList> readCard <Kolab::DistList> (const vcard_4_0::
     boost::shared_ptr<Kolab::DistList> distlist(new Kolab::DistList);
 
     if (!vcard.member().empty()) {
-        std::vector<Kolab::Member> members;
+        std::vector<Kolab::ContactReference> members;
 
         BOOST_FOREACH(const vcard_4_0::vcard::member_type & m, vcard.member()) {
-            std::string name;
-            std::string email = fromMailto(m.uri(), name);
-            Kolab::Member member(email);
-            member.setName(name);
-            if (m.parameters()) {
-                BOOST_FOREACH(const vcard_4_0::ArrayOfParameters::baseParameter_type &param, (*m.parameters()).baseParameter()) {
-                    if (const vcard_4_0::xuidParamType *uid = dynamic_cast<const vcard_4_0::xuidParamType*> (&param)) {
-                        member.setUid(uid->uri());
-                    } 
-                }
-            }
-            members.push_back(member);
+            members.push_back(Shared::toContactReference(m.uri()));
         }
         distlist->setMembers(members);
     } else {
@@ -933,7 +902,7 @@ boost::shared_ptr<T> deserializeCard(const std::string& s, bool isUrl)
         }
         
         boost::shared_ptr<T> card = readCard<T>(vcards->vcard());
-        card->setUid(fromURN(vcards->vcard().uid().uri()));
+        card->setUid(Shared::fromURN(vcards->vcard().uid().uri()));
         card->setName(vcards->vcard().fn().text());
         
         setProductId( vcards->vcard().prodid().text() );
diff --git a/c++/tests/bindingstest.cpp b/c++/tests/bindingstest.cpp
index a108cae..4c7a829 100644
--- a/c++/tests/bindingstest.cpp
+++ b/c++/tests/bindingstest.cpp
@@ -34,7 +34,7 @@ void BindingsTest::noteCompletness()
     note.setDescription("description");
     note.setColor("color");
     const std::string &result = Kolab::writeNote(note);
-    std::cout << result << std::endl;
+//     std::cout << result << std::endl;
     
     const Kolab::Note &re = Kolab::readNote(result, false);
     QCOMPARE(re.uid(), note.uid());
@@ -86,14 +86,12 @@ void setIncidence(T &ev)
     ev.setPriority(3);
     ev.setStatus(Kolab::StatusConfirmed);
     ev.setLocation("location");
-    ev.setOrganizer("email","organizer");
+    ev.setOrganizer(Kolab::ContactReference(Kolab::ContactReference::EmailReference, "mail", "name")); //TODO UID
     
-    Kolab::Attendee attendee("email");
-    attendee.setName("name");
+    Kolab::Attendee attendee(Kolab::ContactReference(Kolab::ContactReference::EmailReference, "mail", "name")); //TODO UID
     attendee.setPartStat(Kolab::PartDelegated);
     attendee.setRole(Kolab::Chair);
     attendee.setRSVP(true);
-    attendee.setUid("uid");
     
     ev.setAttendees(std::vector<Kolab::Attendee>() << attendee << attendee);
     
@@ -133,20 +131,20 @@ void setIncidence(T &ev)
     ev.setCustomProperties(properties);
     
     std::vector<Kolab::Alarm> alarms;
-    Kolab::Alarm dispAlarm("ident");
-    dispAlarm.setRelativeStart(Kolab::Duration(3, true), Kolab::Start);
-    alarms.push_back(dispAlarm);
-    std::vector<std::string> att;
-    att.push_back("attendee1");
-    att.push_back("attendee2");
+//     Kolab::Alarm dispAlarm("ident");
+//     dispAlarm.setRelativeStart(Kolab::Duration(3, true), Kolab::Start);
+//     alarms.push_back(dispAlarm);
+    std::vector<Kolab::ContactReference> att;
+    att.push_back(Kolab::ContactReference(Kolab::ContactReference::EmailReference, "mail", "name"));
+    att.push_back(Kolab::ContactReference(Kolab::ContactReference::EmailReference, "mail", "name")); //TODO UID
     Kolab::Alarm emailAlarm("ident", "value", att);
     emailAlarm.setStart(Kolab::cDateTime(2003,2,3,2,3,4, true));
     alarms.push_back(emailAlarm);
-    Kolab::Attachment audiofile;
-    audiofile.setUri("ksdjlksdflj", "sdkljdfl");
-    Kolab::Alarm audio(audiofile);
-    audio.setStart(Kolab::cDateTime(2003,2,3,2,3,4, true));
-    alarms.push_back(audio);
+//     Kolab::Attachment audiofile;
+//     audiofile.setUri("ksdjlksdflj", "sdkljdfl");
+//     Kolab::Alarm audio(audiofile);
+//     audio.setStart(Kolab::cDateTime(2003,2,3,2,3,4, true));
+//     alarms.push_back(audio);
     ev.setAlarms(alarms);
 }
 
@@ -191,8 +189,7 @@ void checkIncidence(const T &ev, const T &re)
     QCOMPARE(ev.priority(), re.priority());
     QCOMPARE(ev.status(), re.status());
     QCOMPARE(ev.location(), re.location());
-    QCOMPARE(ev.organizerEmail(), re.organizerEmail());
-    QCOMPARE(ev.organizerName(), re.organizerName());
+    QCOMPARE(ev.organizer(), re.organizer());
     QCOMPARE(ev.attendees(), re.attendees());
     QCOMPARE(ev.attachments(), re.attachments());
     QCOMPARE(ev.customProperties(), re.customProperties());
@@ -265,12 +262,10 @@ void BindingsTest::journalCompletness()
     ev.setClassification(Kolab::ClassConfidential);
     ev.addCategory("Category");
     ev.setStart(Kolab::cDateTime("Europe/Zurich", 2006,1,6,12,0,0));
-    Kolab::Attendee attendee("email");
-    attendee.setName("name");
+    Kolab::Attendee attendee(Kolab::ContactReference(Kolab::ContactReference::EmailReference, "mail", "name")); //TODO uid
     attendee.setPartStat(Kolab::PartDelegated);
     attendee.setRole(Kolab::Chair);
     attendee.setRSVP(true);
-    attendee.setUid("uid");
     
     ev.setAttendees(std::vector<Kolab::Attendee>() << attendee << attendee);
     
@@ -462,12 +457,9 @@ void BindingsTest::distlistCompletness()
     Kolab::DistList c;
     c.setName("name");
     c.setUid("uid");
-    std::vector<Kolab::Member> members;
-    members.push_back(Kolab::Member("email at email.com"));
-    Kolab::Member m2("email2 at email.com");
-    m2.setName("name todo");
-    m2.setUid("uid");
-    members.push_back(m2);
+    std::vector<Kolab::ContactReference> members;
+    members.push_back(Kolab::ContactReference(Kolab::ContactReference::EmailReference, "mail", "name"));
+    members.push_back(Kolab::ContactReference(Kolab::ContactReference::UrnReference, "urn"));
     c.setMembers(members);
     std::vector<Kolab::CustomProperty> properties;
     properties.push_back(Kolab::CustomProperty("ident", "value"));
diff --git a/c++/tests/conversiontest.cpp b/c++/tests/conversiontest.cpp
index 3097b35..64d6db6 100644
--- a/c++/tests/conversiontest.cpp
+++ b/c++/tests/conversiontest.cpp
@@ -200,13 +200,24 @@ void ConversionTest::mailtoUriEncodingTest()
 
 void ConversionTest::urnTest()
 {
-    QCOMPARE(Kolab::XCARD::toURN("1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000"));
-    QCOMPARE(Kolab::XCARD::toURN("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000"));
-    QCOMPARE(Kolab::XCARD::fromURN("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("1045b57d-ff7f-0000-d814-867b4d7f0000"));
-    QCOMPARE(Kolab::XCARD::fromURN("1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("1045b57d-ff7f-0000-d814-867b4d7f0000"));
+    QCOMPARE(Kolab::Shared::toURN("1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000"));
+    QCOMPARE(Kolab::Shared::toURN("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000"));
+    QCOMPARE(Kolab::Shared::fromURN("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("1045b57d-ff7f-0000-d814-867b4d7f0000"));
+    QCOMPARE(Kolab::Shared::fromURN("1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("1045b57d-ff7f-0000-d814-867b4d7f0000"));
     QCOMPARE(Kolab::Utils::getError(), Kolab::NoError);
 }
 
+void ConversionTest::contactReferenceTest()
+{
+    Kolab::ContactReference email(Kolab::ContactReference::EmailReference, "mail", "name");
+    QCOMPARE(Kolab::Shared::fromContactReference(email), std::string("mailto:name%3Cmail%3E"));
+    Kolab::ContactReference urn(Kolab::ContactReference::UrnReference, "urn");
+    QCOMPARE(Kolab::Shared::fromContactReference(urn), std::string("urn:uuid:urn"));
+    
+    QCOMPARE(Kolab::Shared::toContactReference("urn:uuid:urn"), urn);
+    QCOMPARE(Kolab::Shared::toContactReference("mailto:name%3Cmail%3E"), email);
+}
+
 
 void threadF() 
 {
diff --git a/c++/tests/conversiontest.h b/c++/tests/conversiontest.h
index 8df558f..9c2bc86 100644
--- a/c++/tests/conversiontest.h
+++ b/c++/tests/conversiontest.h
@@ -35,6 +35,8 @@ class ConversionTest : public QObject
     
     void urnTest();
     
+    void contactReferenceTest();
+    
     void threadLocalTest();
 };
 
diff --git a/c++/tests/kcalconversiontest.cpp b/c++/tests/kcalconversiontest.cpp
index 74ff3f3..ab4171d 100644
--- a/c++/tests/kcalconversiontest.cpp
+++ b/c++/tests/kcalconversiontest.cpp
@@ -309,7 +309,7 @@ void KCalConversionTest::testConversion_data()
         kcal.setStatus(KCalCore::Incidence::StatusConfirmed);
         kcal.setLocation("location");
         kcal.setOrganizer(KCalCore::Person::Ptr(new KCalCore::Person("organizer", "organizer at email")));
-        kcal.addAttendee(KCalCore::Attendee::Ptr(new KCalCore::Attendee("attendee", "attendee at email", false, KCalCore::Attendee::NeedsAction, KCalCore::Attendee::ReqParticipant, "uid")));
+        kcal.addAttendee(KCalCore::Attendee::Ptr(new KCalCore::Attendee("attendee", "attendee at email", false, KCalCore::Attendee::NeedsAction, KCalCore::Attendee::ReqParticipant)));
         //TODO KCalCore Delegate/Delegator
         kcal.addAttachment(KCalCore::Attachment::Ptr(new KCalCore::Attachment(QString("uri"), "mimetype/mime")));
         KCalCore::Alarm::Ptr alarm = KCalCore::Alarm::Ptr(new KCalCore::Alarm(&kcal));    
@@ -354,11 +354,9 @@ void KCalConversionTest::testConversion_data()
         kolab.setPriority(3);
         kolab.setStatus(Kolab::StatusConfirmed);
         kolab.setLocation("location");
-        kolab.setOrganizer("organizer at email", "organizer");
+        kolab.setOrganizer(Kolab::ContactReference(Kolab::ContactReference::EmailReference,"organizer at email", "organizer")); //TODO uid
         
-        Kolab::Attendee a("attendee at email");
-        a.setName("attendee");
-        a.setUid("uid");
+        Kolab::Attendee a(Kolab::ContactReference(Kolab::ContactReference::EmailReference,"attendee at email", "attendee"));//TODO uid
         kolab.setAttendees(std::vector<Kolab::Attendee>() << a);
         
         Kolab::Attachment attach;
diff --git a/c++/tests/serializers.h b/c++/tests/serializers.h
index de917d8..b07a1b9 100644
--- a/c++/tests/serializers.h
+++ b/c++/tests/serializers.h
@@ -32,9 +32,9 @@ namespace QTest {
     char *toString(const Kolab::Attendee &a)
     {
         QByteArray ba = "Kolab::Attendee(";
-        ba += QString::fromStdString(a.email()).toAscii() + ", " + QString::fromStdString(a.name()).toAscii()+ ", " + 
+        ba += QString::fromStdString(a.contact().email()).toAscii() + ", " + QString::fromStdString(a.contact().name()).toAscii()+ ", " + 
         QByteArray::number(a.partStat()) + ", " + QByteArray::number(a.role())  + ", " + QByteArray::number(a.rsvp())  + ", " + 
-        QString::fromStdString(a.uid()).toAscii();
+        QString::fromStdString(a.contact().uid()).toAscii();
         ba += ")";
         return qstrdup(ba.data());
     }
@@ -122,12 +122,34 @@ namespace QTest {
     }
     
     template<>
+    char *toString(const Kolab::ContactReference &a)
+    {
+        QByteArray ba = "Kolab::ContactReference(";
+        ba += QString::fromStdString(a.email()).toAscii()+ ", ";
+        ba += QString::fromStdString(a.name()).toAscii()+ ", ";
+        ba += QString::fromStdString(a.uid()).toAscii();
+        ba += ")";
+        return qstrdup(ba.data());
+    }
+    
+    template<>
+    char *toString(const std::vector<Kolab::ContactReference> &v)
+    {
+        QByteArray ba = "vector<Kolab::ContactReference>(";
+        for (int i = 0; i < v.size(); i++) {
+                ba += QByteArray(toString(v.at(i)))+ "\n";
+            }
+            ba += ")";
+            return qstrdup(ba.data());
+    }
+    
+    template<>
     char *toString(const Kolab::Alarm &a)
     {
         QByteArray ba = "Kolab::Alarm(";
-        ba += QByteArray::number(a.type()) + ", " + QString::fromStdString(a.summary()).toAscii()+ ", " + 
-        QString::fromStdString(a.text()).toAscii()+", " +toString(a.duration()) + ", " + QByteArray::number(a.numrepeat())+  ", " + toString(a.start()) +
-        + toString(a.relativeStart())  + ", " +  QByteArray::number(a.relativeTo()) + toString(a.audioFile()) +  ", " + toString(a.attendees());
+        ba += QByteArray::number(a.type()) + "\n " + QString::fromStdString(a.summary()).toAscii()+ "\n " + 
+        QString::fromStdString(a.text()).toAscii()+"\n " +toString(a.duration()) + "\n " + QByteArray::number(a.numrepeat())+  "\n " + toString(a.start()) + "\n " +
+        toString(a.relativeStart())  + "\n " +  QByteArray::number(a.relativeTo()) + "\n " + toString(a.audioFile()) +  "\n " + toString(a.attendees()) + "\n ";
         ba += ")";
         return qstrdup(ba.data());
     }
@@ -164,28 +186,6 @@ namespace QTest {
         ba += ")";
         return qstrdup(ba.data());
     }
-    
-    template<>
-    char *toString(const Kolab::Member &a)
-    {
-        QByteArray ba = "Kolab::Member(";
-        ba += QString::fromStdString(a.email()).toAscii()+ ", ";
-        ba += QString::fromStdString(a.name()).toAscii()+ ", ";
-        ba += QString::fromStdString(a.uid()).toAscii();
-        ba += ")";
-        return qstrdup(ba.data());
-    }
-    
-    template<>
-    char *toString(const std::vector<Kolab::Member> &v)
-    {
-        QByteArray ba = "vector<Kolab::Member>(";
-        for (int i = 0; i < v.size(); i++) {
-            ba += QByteArray(toString(v.at(i)))+ "\n";
-        }
-        ba += ")";
-        return qstrdup(ba.data());
-    }
 
  }
  


commit 418fe42403ced66e46f479254489a4491e6d2ce9
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Fri Mar 16 16:18:15 2012 +0100

    Implemented xCrypto

diff --git a/c++/lib/kolabcontact.h b/c++/lib/kolabcontact.h
index 6c00557..2f6a09b 100644
--- a/c++/lib/kolabcontact.h
+++ b/c++/lib/kolabcontact.h
@@ -179,7 +179,43 @@ private:
 };
 
 struct Crypto {
+    enum CryptoTypes {
+        PGPinline = 0x01,
+        PGPmime = 0x02,
+        SMIME = 0x04,
+        SMIMEopaque = 0x08
+    };
     
+    enum CryptoPref {
+        Ask,
+        Never,
+        Always,
+        IfPossible
+    };
+    Crypto(): mCryptoTypes(0), mSignPref(Ask), mEncryptPref(Ask){};
+    bool operator==(const Crypto &other) const { return mCryptoTypes == other.mCryptoTypes &&
+                                                    mPGPKey == other.mPGPKey &&
+                                                    mSMIMEKey == other.mSMIMEKey &&
+                                                    mSignPref == other.mSignPref &&
+                                                    mEncryptPref == other.mEncryptPref; };
+    bool isValid() const { return !(!mCryptoTypes && mPGPKey.empty() && mSMIMEKey.empty()); };
+
+    void setAllowed(int cryptoTypes) { mCryptoTypes = cryptoTypes; };
+    int allowed() const { return mCryptoTypes; };
+    void setPGPKey(const std::string &k) { mPGPKey = k; };
+    std::string pgpKey() const { return mPGPKey; };
+    void setSMIMEKey(const std::string &k) { mSMIMEKey = k; };
+    std::string smimeKey() const { return mSMIMEKey; };
+    void setSignPref(CryptoPref p) { mSignPref = p; };
+    CryptoPref signPref() const { return mSignPref; };
+    void setEncryptPref(CryptoPref p) { mEncryptPref = p; };
+    CryptoPref encryptPref() const { return mEncryptPref; };
+private:
+    int mCryptoTypes;
+    std::string mPGPKey;
+    std::string mSMIMEKey;
+    CryptoPref mSignPref;
+    CryptoPref mEncryptPref;
 };
 
 struct Member {
diff --git a/c++/lib/xcardconversions.h b/c++/lib/xcardconversions.h
index b2e9287..e0525f2 100644
--- a/c++/lib/xcardconversions.h
+++ b/c++/lib/xcardconversions.h
@@ -34,7 +34,9 @@ namespace Kolab {
     const char* const XCARD_NAMESPACE = "urn:ietf:params:xml:ns:vcard-4.0";
     const char* const INDIVIDUAL = "individual";
     const char* const GROUP = "group";
-    
+    const char* const MIME_PGP_KEYS = "application/pgp-keys";
+    const char* const MIME_PKCS7_MIME = "application/pkcs7-mime";
+
 using namespace Kolab::Utils;
     
 template <typename T> 
@@ -223,6 +225,40 @@ T fromDateTime(const Kolab::cDateTime &dt)
     return prop;
 }
 
+vcard_4_0::PrefTypeValueType fromCryptoPref(Kolab::Crypto::CryptoPref pref)
+{
+    switch (pref) {
+        case Kolab::Crypto::Always:
+            return vcard_4_0::CryptoType::encryptpref_type::text_type::Always;
+        case Kolab::Crypto::Ask:
+            return vcard_4_0::CryptoType::encryptpref_type::text_type::Ask;
+        case Kolab::Crypto::IfPossible:
+            return vcard_4_0::CryptoType::encryptpref_type::text_type::IfPossible;
+        case Kolab::Crypto::Never:
+            return vcard_4_0::CryptoType::encryptpref_type::text_type::Never;
+        default:
+            WARNING("unknown encrypt pref");
+    }
+    return vcard_4_0::CryptoType::encryptpref_type::text_type::Ask;
+}
+
+Kolab::Crypto::CryptoPref toCryptoPref(vcard_4_0::PrefTypeValueType pref)
+{
+    switch (pref) {
+        case vcard_4_0::CryptoType::encryptpref_type::text_type::Always:
+            return Kolab::Crypto::Always;
+        case vcard_4_0::CryptoType::encryptpref_type::text_type::Ask:
+            return Kolab::Crypto::Ask;
+        case vcard_4_0::CryptoType::encryptpref_type::text_type::IfPossible:
+            return Kolab::Crypto::IfPossible;
+        case vcard_4_0::CryptoType::encryptpref_type::text_type::Never:
+            return Kolab::Crypto::Never;
+        default:
+            WARNING("unknown encrypt pref");
+    }
+    return Kolab::Crypto::Ask;
+}
+
 template <typename T> 
 void writeCard(vcard_4_0::vcard &vcard, const T &);
 
@@ -450,9 +486,39 @@ void writeCard<Kolab::Contact>(vcard_4_0::vcard &vcard, const Kolab::Contact &co
         vcard.geo(fromList<vcard::geo_type>(contact.gpsPos()));
     }
     
-//     if (!contact.crypto().isValid()) {
-//         //TODO
-//     }
+    if (contact.crypto().isValid()) {
+        vcard::x_crypto_type crypto;
+        const Kolab::Crypto &c = contact.crypto();
+        if (c.allowed()) {
+            vcard::x_crypto_type::allowed_type::text_sequence seq;
+            if (c.allowed() & Kolab::Crypto::PGPinline) {
+                seq.push_back(vcard::x_crypto_type::allowed_type::text_type::PGP_INLINE);
+            }
+            if (c.allowed() & Kolab::Crypto::PGPmime) {
+                seq.push_back(vcard::x_crypto_type::allowed_type::text_type::PGP_MIME);
+            }
+            if (c.allowed() & Kolab::Crypto::SMIME) {
+                seq.push_back(vcard::x_crypto_type::allowed_type::text_type::S_MIME);
+            }
+            if (c.allowed() & Kolab::Crypto::SMIMEopaque) {
+                seq.push_back(vcard::x_crypto_type::allowed_type::text_type::S_MIMEOpaque);
+            }
+            vcard::x_crypto_type::allowed_type allowed;
+            allowed.text(seq);
+            crypto.allowed(allowed);
+        }
+        if (!c.pgpKey().empty()) {
+            crypto.pgpkey(vcard_4_0::CryptoType::pgpkey_type(uriInlineEncoding(c.pgpKey(), MIME_PGP_KEYS)));
+        }
+        if (!c.smimeKey().empty()) {
+            crypto.smimekey(vcard_4_0::CryptoType::smimekey_type(uriInlineEncoding(c.smimeKey(), MIME_PKCS7_MIME)));
+        }
+
+        crypto.encryptpref(fromCryptoPref(c.encryptPref()));
+        crypto.signpref(fromCryptoPref(c.signPref()));
+
+        vcard.x_crypto(crypto);
+    }
 
 
 }
@@ -766,8 +832,49 @@ boost::shared_ptr<Kolab::Contact> readCard <Kolab::Contact> (const vcard_4_0::Vc
         }
         contact->setGPSpos(list);
     }
-    if (!vcard.x_crypto().empty()) {
-        //TODO Crypto
+    if (vcard.x_crypto()) {
+        const vcard_4_0::vcard::x_crypto_type &crypto = *vcard.x_crypto();
+        Kolab::Crypto c;
+        if (crypto.allowed()) {
+            int allowed = 0;
+            BOOST_FOREACH(const vcard_4_0::vcard::x_crypto_type::allowed_type::text_type &m, crypto.allowed()->text()) {
+                if (m == vcard::x_crypto_type::allowed_type::text_type::PGP_INLINE) {
+                    allowed |= Kolab::Crypto::PGPinline;
+                } else if (m == vcard::x_crypto_type::allowed_type::text_type::PGP_MIME) {
+                    allowed |= Kolab::Crypto::PGPmime;
+                } else if (m == vcard::x_crypto_type::allowed_type::text_type::S_MIME) {
+                    allowed |= Kolab::Crypto::SMIME;
+                } else if (m == vcard::x_crypto_type::allowed_type::text_type::S_MIMEOpaque) {
+                    allowed |= Kolab::Crypto::SMIMEopaque;
+                } else {
+                    WARNING("unknown allowed property");
+                }
+            }
+            c.setAllowed(allowed);
+        }
+        if (crypto.pgpkey()) {
+            std::string mimetype;
+            const std::string &key = uriInlineDecoding(crypto.pgpkey()->uri(), mimetype);
+            if (mimetype != MIME_PGP_KEYS) {
+                WARNING("wrong mimetype on key");
+            }
+            c.setPGPKey(key);
+        }
+        if (crypto.smimekey()) {
+            std::string mimetype;
+            const std::string &key = uriInlineDecoding(crypto.smimekey()->uri(), mimetype);
+            if (mimetype != MIME_PKCS7_MIME) {
+                WARNING("wrong mimetype on key");
+            }
+            c.setSMIMEKey(key);
+        }
+        if (crypto.encryptpref()) {
+            c.setEncryptPref(toCryptoPref(crypto.encryptpref()->text()));
+        }
+        if (crypto.signpref()) {
+            c.setSignPref(toCryptoPref(crypto.signpref()->text()));
+        }
+        contact->setCrypto(c);
     }
     return contact;
 }
diff --git a/c++/tests/bindingstest.cpp b/c++/tests/bindingstest.cpp
index fbe1323..a108cae 100644
--- a/c++/tests/bindingstest.cpp
+++ b/c++/tests/bindingstest.cpp
@@ -406,6 +406,13 @@ void BindingsTest::contactCompletness()
     telephones.push_back(phone);
     c.setTelephones(telephones, 1);
     c.setGPSpos(stringlist);
+    Kolab::Crypto crypto;
+    crypto.setAllowed(Kolab::Crypto::PGPinline | Kolab::Crypto::SMIMEopaque);
+    crypto.setPGPKey("pgp");
+    crypto.setSignPref(Kolab::Crypto::IfPossible);
+    crypto.setEncryptPref(Kolab::Crypto::Never);
+    crypto.setSMIMEKey("smime");
+    c.setCrypto(crypto);
     
     std::vector<Kolab::CustomProperty> properties;
     properties.push_back(Kolab::CustomProperty("ident", "value"));
@@ -442,7 +449,7 @@ void BindingsTest::contactCompletness()
     QCOMPARE(e.emailAddresses(), c.emailAddresses());
     QCOMPARE(e.emailAddressPreferredIndex(), c.emailAddressPreferredIndex());
     QCOMPARE(e.gpsPos(), c.gpsPos());
-//     QCOMPARE(e.crypto(), c.crypto());
+    QCOMPARE(e.crypto(), c.crypto());
     QCOMPARE(e.customProperties(), c.customProperties());
 }
 
diff --git a/schemas/kolabformat-xcard.xsd b/schemas/kolabformat-xcard.xsd
index 407234c..6138231 100644
--- a/schemas/kolabformat-xcard.xsd
+++ b/schemas/kolabformat-xcard.xsd
@@ -29,8 +29,60 @@
         </xs:complexContent>
     </xs:complexType>
 
-    <xs:element name="x-kolab-custom" type="CustomType" substitutionGroup="baseProperty" />      
-    
+    <xs:element name="x-custom" type="CustomType" substitutionGroup="baseProperty" />
+
+    <xs:simpleType name="CryptoTypeValueType">
+        <xs:restriction base="xs:token">
+            <xs:enumeration value="PGP/INLINE"/>
+            <xs:enumeration value="PGP/MIME"/>
+            <xs:enumeration value="S/MIME"/>
+            <xs:enumeration value="S/MIMEOpaque"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="PrefTypeValueType">
+        <xs:restriction base="xs:token">
+            <xs:enumeration value="Never"/>
+            <xs:enumeration value="Always"/>
+            <xs:enumeration value="IfPossible"/>
+            <xs:enumeration value="Ask"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="CryptoType" >
+        <xs:complexContent mixed="false">
+            <xs:extension base="BasePropertyType">
+                <xs:sequence>
+                    <xs:element name="allowed" minOccurs="0">
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:element name="text" type="CryptoTypeValueType" maxOccurs="unbounded"/>
+                        </xs:sequence>
+                      </xs:complexType>
+                    </xs:element>
+                    <xs:element name="pgpkey" type="UriPropertyType" minOccurs="0"/>
+                    <xs:element name="smimekey" type="UriPropertyType" minOccurs="0"/>
+                    <xs:element name="signpref" minOccurs="0">
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:element name="text" type="PrefTypeValueType" />
+                        </xs:sequence>
+                      </xs:complexType>
+                    </xs:element>
+                    <xs:element name="encryptpref" minOccurs="0">
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:element name="text" type="PrefTypeValueType" />
+                        </xs:sequence>
+                      </xs:complexType>
+                    </xs:element>
+                </xs:sequence>
+           </xs:extension>
+        </xs:complexContent>
+    </xs:complexType>
+
+    <xs:element name="x-crypto" type="CryptoType" substitutionGroup="baseProperty" />
+
     <xs:complexType name="VcardsType">
         <xs:sequence>
             <xs:element name="vcard">
@@ -60,7 +112,7 @@
                         <xs:element name="impp" type="imppPropType" minOccurs="0" maxOccurs="unbounded"/>
                         <xs:element name="email" type="emailPropType" minOccurs="0" maxOccurs="unbounded"/>
                         <xs:element name="geo" type="geoPropType" minOccurs="0" maxOccurs="unbounded"/>
-                        <xs:element name="x-crypto" type="cryptoPropType" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="x-crypto" type="CryptoType" minOccurs="0"/>
                         <xs:element name="member" type="memberPropType" minOccurs="0" maxOccurs="unbounded"/>
                         <xs:element name="x-custom" type="CustomType" minOccurs="0" maxOccurs="unbounded"/>
                     </xs:sequence>


commit 65699af6182efe06aad6475b26ce745d7f8f5bba
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Thu Mar 15 09:48:11 2012 +0100

    GeoProperty, not geo uri handling yet

diff --git a/c++/lib/xcardconversions.h b/c++/lib/xcardconversions.h
index d1b9e7f..b2e9287 100644
--- a/c++/lib/xcardconversions.h
+++ b/c++/lib/xcardconversions.h
@@ -447,7 +447,7 @@ void writeCard<Kolab::Contact>(vcard_4_0::vcard &vcard, const Kolab::Contact &co
     }
     
     if (!contact.gpsPos().empty()) {
-        //TODO
+        vcard.geo(fromList<vcard::geo_type>(contact.gpsPos()));
     }
     
 //     if (!contact.crypto().isValid()) {
@@ -760,7 +760,11 @@ boost::shared_ptr<Kolab::Contact> readCard <Kolab::Contact> (const vcard_4_0::Vc
         contact->setEmailAddresses(list, preferredIndex);
     }
     if (!vcard.geo().empty()) {
-        //TODO Geo
+        std::vector<std::string> list;
+        BOOST_FOREACH(const vcard_4_0::geoPropType &s, vcard.geo()) {
+            list.push_back(s.uri());
+        }
+        contact->setGPSpos(list);
     }
     if (!vcard.x_crypto().empty()) {
         //TODO Crypto
diff --git a/c++/tests/bindingstest.cpp b/c++/tests/bindingstest.cpp
index 6d4c381..fbe1323 100644
--- a/c++/tests/bindingstest.cpp
+++ b/c++/tests/bindingstest.cpp
@@ -405,8 +405,7 @@ void BindingsTest::contactCompletness()
     telephones.push_back(phone);
     telephones.push_back(phone);
     c.setTelephones(telephones, 1);
-    
-//     c.setGPSpos(stringlist,1);
+    c.setGPSpos(stringlist);
     
     std::vector<Kolab::CustomProperty> properties;
     properties.push_back(Kolab::CustomProperty("ident", "value"));
@@ -442,7 +441,7 @@ void BindingsTest::contactCompletness()
     QCOMPARE(e.imAddressPreferredIndex(), c.imAddressPreferredIndex());
     QCOMPARE(e.emailAddresses(), c.emailAddresses());
     QCOMPARE(e.emailAddressPreferredIndex(), c.emailAddressPreferredIndex());
-//     QCOMPARE(e.gpsPos(), c.gpsPos());
+    QCOMPARE(e.gpsPos(), c.gpsPos());
 //     QCOMPARE(e.crypto(), c.crypto());
     QCOMPARE(e.customProperties(), c.customProperties());
 }





More information about the commits mailing list