3 commits - c++/lib c++/tests schemas/xCard.xsd

Christian Mollekopf mollekopf at kolabsys.com
Thu Mar 8 10:29:30 CET 2012


 c++/lib/kolabcontact.cpp     |    6 ++---
 c++/lib/kolabcontact.h       |   27 ++++++++++++++++++++++---
 c++/lib/utils.cpp            |   45 ++++++++++++++++++++++++++++++++++++++++++-
 c++/lib/utils.h              |    4 +++
 c++/lib/xcalconversions.h    |   12 +++++------
 c++/lib/xcardconversions.h   |   36 +++++++++++++++++++++++++++++-----
 c++/tests/bindingstest.cpp   |   12 ++++++++---
 c++/tests/conversiontest.cpp |   30 ++++++++++++++++++++++++++++
 c++/tests/conversiontest.h   |    3 ++
 c++/tests/serializers.h      |   22 +++++++++++++++++++++
 schemas/xCard.xsd            |   28 +++++++++++++++++++++-----
 11 files changed, 199 insertions(+), 26 deletions(-)

New commits:
commit 23ff54526debf8fba5e2d6cf59db972b75ac7c60
Merge: a8c894f e039d6d
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Thu Mar 8 10:02:35 2012 +0100

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

diff --cc c++/tests/conversiontest.cpp
index f6775f0,0752c90..218ea42
--- a/c++/tests/conversiontest.cpp
+++ b/c++/tests/conversiontest.cpp
@@@ -10,9 -10,8 +10,9 @@@
  
  Q_DECLARE_METATYPE(Kolab::Duration);
  Q_DECLARE_METATYPE(Kolab::DayPos);
- Q_DECLARE_METATYPE(Kolab::KoDateTime);
+ Q_DECLARE_METATYPE(Kolab::cDateTime);
  Q_DECLARE_METATYPE(Kolab::ErrorSeverity);
 +Q_DECLARE_METATYPE(std::string);
  
  using namespace Kolab::XCAL;
  


commit a8c894f26196638159f73e824bfa91517f52855d
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Thu Mar 8 10:02:25 2012 +0100

    x-uid and mailto handling.

diff --git a/c++/lib/kolabcontact.cpp b/c++/lib/kolabcontact.cpp
index fc99d83..ce3e0e1 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<std::string> members;
+    std::vector<Member> members;
     std::vector<CustomProperty> customProperties;
 };
     
@@ -89,12 +89,12 @@ std::string DistList::name() const
     return d->name;
 }
 
-void DistList::setMembers(const std::vector< std::string > members)
+void DistList::setMembers(const std::vector< Member > &members)
 {
     d->members = members;
 }
 
-std::vector< std::string > DistList::members() const
+std::vector< Member > DistList::members() const
 {
     return d->members;
 }
diff --git a/c++/lib/kolabcontact.h b/c++/lib/kolabcontact.h
index 5c74f7e..a449851 100644
--- a/c++/lib/kolabcontact.h
+++ b/c++/lib/kolabcontact.h
@@ -182,7 +182,28 @@ struct Crypto {
     
 };
 
-
+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:
@@ -202,8 +223,8 @@ public:
     void setName(const std::string &);
     std::string name() const;
 
-    void setMembers(const std::vector<std::string> members);
-    std::vector<std::string> members() const;
+    void setMembers(const std::vector<Member> &);
+    std::vector<Member> members() const;
 
     void setCustomProperties(const std::vector<CustomProperty> &);
     std::vector<CustomProperty> customProperties() const;
diff --git a/c++/lib/utils.cpp b/c++/lib/utils.cpp
index da9c34f..269d8ce 100644
--- a/c++/lib/utils.cpp
+++ b/c++/lib/utils.cpp
@@ -183,6 +183,49 @@ std::string uriInlineDecoding(const std::string &s, std::string &mimetype)
     return base64_decode(s.substr(pos+8, s.size()-(pos+8)));
 }
 
+std::string toMailto(const std::string &email, const std::string &name)
+{
+    std::string mailto;
+    if (!name.empty()) {
+        mailto.append(name);
+    }
+    mailto.append("<");
+    mailto.append(email);
+    mailto.append(">");
+    return std::string("mailto:")+mailto;
+}
+
+std::string fromMailto(const std::string &mailtoUri, std::string &name)
+{
+    const std::string &decoded = mailtoUri;
+    if (decoded.substr(0, 7).compare("mailto:")) {
+        WARNING("no mailto address");
+        std::cout << decoded << std::endl;
+        return mailtoUri;
+    }
+    std::size_t begin = decoded.find('<',7);
+    if (begin == std::string::npos) {
+        WARNING("no mailto address");
+        std::cout << decoded << std::endl;
+        return mailtoUri;
+    }
+    std::size_t end = decoded.find('>', begin);
+    if (end == std::string::npos) {
+        WARNING("no mailto address");
+        std::cout << decoded << std::endl;
+        return mailtoUri;
+    }
+    name = decoded.substr(7, begin-7);
+    const std::string &email = decoded.substr(begin+1, end-begin-1);
+    return email;
+}
+
+std::string fromMailto(const std::string &mailtoUri)
+{
+    std::string n;
+    return fromMailto(mailtoUri, n);
+}
+
 } //Namespace
 
 } //Namespace
\ No newline at end of file
diff --git a/c++/lib/utils.h b/c++/lib/utils.h
index b7b69ea..55ed292 100644
--- a/c++/lib/utils.h
+++ b/c++/lib/utils.h
@@ -110,6 +110,10 @@ T fromInt(int integer)
 std::string uriInlineEncoding(const std::string &, const std::string &mime);
 std::string uriInlineDecoding(const std::string &s, std::string &mimetype);
 
+std::string toMailto(const std::string &email, const std::string &name = std::string());
+std::string fromMailto(const std::string &mailtoUri, std::string &name);
+std::string fromMailto(const std::string &mailtoUri);
+
     } //Namespace
 
 } //Namespace
diff --git a/c++/lib/xcalconversions.h b/c++/lib/xcalconversions.h
index 932b000..ca54642 100644
--- a/c++/lib/xcalconversions.h
+++ b/c++/lib/xcalconversions.h
@@ -358,7 +358,7 @@ void setCalAddress(const icalendar_2_0::CalAddressPropertyType &cal, std::string
             }
         }
     }
-    email = cal.cal_address();
+    email = fromMailto(cal.cal_address());
 }
 
 
@@ -877,7 +877,7 @@ 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(toString(aProp.cal_address()));
+            Kolab::Attendee a(fromMailto(toString(aProp.cal_address())));
             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++) {
@@ -1130,7 +1130,7 @@ void getIncidenceProperties(T &prop, const I &inc)
     if (!inc.attendees().empty()) {        
         
         BOOST_FOREACH(const Kolab::Attendee &a, inc.attendees()) {
-            typename properties::attendee_type attendee(a.email());
+            typename properties::attendee_type attendee(toMailto(a.email()));
             
             typename properties::attendee_type::parameters_type p;
             if (!a.name().empty()) {
@@ -1220,7 +1220,7 @@ void getTodoEventProperties(T &prop, const I &inc)
     }
     
     if (!inc.organizerEmail().empty()) { //email is required
-        typename properties::organizer_type organizer(inc.organizerEmail());
+        typename properties::organizer_type organizer(toMailto(inc.organizerEmail()));
         
         typename properties::organizer_type::parameters_type p; //There is maybe already a timezone set
         icalendar_2_0::CnParamType name(inc.organizerName());
@@ -1269,7 +1269,7 @@ void setAlarms(typename KolabType::components_type& components, const IncidenceT
                 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(attendee));
+                    p->attendee().push_back(icalendar_2_0::ContactType(toMailto(attendee)));
                 }
                 break;
             case Kolab::Alarm::AudioAlarm:
@@ -1310,7 +1310,7 @@ void getAlarms(IncidenceType &incidence, const typename KolabType::components_ty
         } else if (prop.action().text() == EMAILALARM) {
             std::vector<std::string> attendees;
             for (typename PropType::attendee_const_iterator at(prop.attendee().begin()); at != prop.attendee().end(); at++) {
-                attendees.push_back((*at).cal_address());
+                attendees.push_back(fromMailto((*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 f406105..d8d7ba4 100644
--- a/c++/lib/xcardconversions.h
+++ b/c++/lib/xcardconversions.h
@@ -461,7 +461,17 @@ template <>
 void writeCard<Kolab::DistList>(vcard_4_0::vcard &vcard, const Kolab::DistList &distlist)
 {
     if (!distlist.members().empty()) {
-        vcard.member(fromList<vcard_4_0::vcard::member_type>(distlist.members()));
+        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);
+        }
+        vcard.member(members);
     } else {
         WARNING("empty distlist");
     }
@@ -748,9 +758,25 @@ boost::shared_ptr<Kolab::DistList> readCard <Kolab::DistList> (const vcard_4_0::
 {
     using namespace vcard_4_0;
     boost::shared_ptr<Kolab::DistList> distlist(new Kolab::DistList);
-    
+
     if (!vcard.member().empty()) {
-        distlist->setMembers(toUriList<vcard_4_0::vcard::member_type>(vcard.member()));
+        std::vector<Kolab::Member> 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);
+        }
+        distlist->setMembers(members);
     } else {
         WARNING("empty distlist");
     }
diff --git a/c++/tests/bindingstest.cpp b/c++/tests/bindingstest.cpp
index 2ed8882..486c250 100644
--- a/c++/tests/bindingstest.cpp
+++ b/c++/tests/bindingstest.cpp
@@ -316,7 +316,7 @@ void BindingsTest::contactCompletness()
     stringlist.push_back("sdf");
 
     Kolab::Contact c;
-    c.setUid("uid");
+    c.setUid("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000");
     c.setCategories(stringlist);
     c.setName("name");
     Kolab::NameComponents nc;
@@ -431,7 +431,13 @@ void BindingsTest::distlistCompletness()
     Kolab::DistList c;
     c.setName("name");
     c.setUid("uid");
-    c.setMembers(stringlist);
+    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);
+    c.setMembers(members);
     std::vector<Kolab::CustomProperty> properties;
     properties.push_back(Kolab::CustomProperty("ident", "value"));
     properties.push_back(Kolab::CustomProperty("ident", "value"));
@@ -439,7 +445,7 @@ void BindingsTest::distlistCompletness()
     
     const std::string result = Kolab::writeDistlist(c);
     QVERIFY(Kolab::error() == Kolab::NoError);
-//     std::cout << result << endl;
+    std::cout << result << endl;
     Kolab::DistList e = Kolab::readDistlist(result, false);
     QVERIFY(Kolab::error() == Kolab::NoError);
     QCOMPARE(e.uid(), c.uid());
diff --git a/c++/tests/conversiontest.cpp b/c++/tests/conversiontest.cpp
index bc2ebcc..f6775f0 100644
--- a/c++/tests/conversiontest.cpp
+++ b/c++/tests/conversiontest.cpp
@@ -12,6 +12,7 @@ Q_DECLARE_METATYPE(Kolab::Duration);
 Q_DECLARE_METATYPE(Kolab::DayPos);
 Q_DECLARE_METATYPE(Kolab::KoDateTime);
 Q_DECLARE_METATYPE(Kolab::ErrorSeverity);
+Q_DECLARE_METATYPE(std::string);
 
 using namespace Kolab::XCAL;
 
@@ -169,6 +170,35 @@ void ConversionTest::uriInlineEncodingTest()
     QCOMPARE(Kolab::Utils::getError(), Kolab::NoError);
 }
 
+void ConversionTest::mailtoUriEncodingTest_data()
+{
+    QTest::addColumn<QString>("email");
+    QTest::addColumn<QString>("name");
+    QTest::addColumn<QString>("result");
+    QTest::addColumn<QString>("resultEncoded");
+    
+    QTest::newRow("1") << "email_1 at email.com" << "John Doe" << "mailto:John Doe<email_1 at email.com>" << "mailto:John%20Doe%3Cemail%5F1%40email%2Ecom%3E";
+    
+    Kolab::Utils::clearErrors();
+}
+
+void ConversionTest::mailtoUriEncodingTest()
+{
+    QFETCH(QString, email);
+    QFETCH(QString, name);
+    QFETCH(QString, result);
+    QFETCH(QString, resultEncoded);
+    const std::string &mailto = Kolab::XCARD::toMailto(email.toStdString(), name.toStdString());
+    std::cout << mailto << std::endl;
+    QCOMPARE(QString::fromStdString(mailto), resultEncoded);
+    std::string n;
+    const std::string &e = Kolab::XCARD::fromMailto(mailto, n);
+    QCOMPARE(QString::fromStdString(n), name);
+    QCOMPARE(QString::fromStdString(e), email);
+    
+}
+
+
 void threadF() 
 {
     for (int i = 0; i < 5; ++i)
diff --git a/c++/tests/conversiontest.h b/c++/tests/conversiontest.h
index e99bf0c..3ccdd1c 100644
--- a/c++/tests/conversiontest.h
+++ b/c++/tests/conversiontest.h
@@ -30,6 +30,9 @@ class ConversionTest : public QObject
     
     void uriInlineEncodingTest();
     
+    void mailtoUriEncodingTest_data();
+    void mailtoUriEncodingTest();
+    
     void threadLocalTest();
 };
 
diff --git a/c++/tests/serializers.h b/c++/tests/serializers.h
index c92f577..6a0af74 100644
--- a/c++/tests/serializers.h
+++ b/c++/tests/serializers.h
@@ -164,6 +164,28 @@ 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());
+    }
 
  }
  
diff --git a/schemas/xCard.xsd b/schemas/xCard.xsd
index 89d7481..429e4bf 100644
--- a/schemas/xCard.xsd
+++ b/schemas/xCard.xsd
@@ -50,11 +50,17 @@
           </xs:extension>
       </xs:complexContent>
   </xs:complexType>
+
+  <xs:complexType name="UriParameterType" mixed="false">
+      <xs:complexContent>
+          <xs:extension base="xcard:BaseParameterType">
+              <xs:sequence>
+                 <xs:element ref="xcard:uri"/>
+              </xs:sequence>
+          </xs:extension>
+      </xs:complexContent>
+  </xs:complexType>
   
-    <!-- WARNING: don't forget to add those, otherwise the serialization code will not be built and you're up for a long debugging session       -->
-    <xs:element name="type" type="xcard:typeParamType" substitutionGroup="xcard:baseParameter"/>
-    <xs:element name="label" type="xcard:labelParamType" substitutionGroup="xcard:baseParameter"/>
-    <xs:element name="pref" type="xcard:prefParamType" substitutionGroup="xcard:baseParameter"/>
   
     <xs:simpleType name="TypeValueType">
         <xs:restriction base="xs:token">
@@ -96,7 +102,19 @@
         </xs:extension>
       </xs:complexContent>    
     </xs:complexType>
+    
+    <xs:complexType name="xuidParamType" mixed="false">
+        <xs:complexContent>
+            <xs:extension base="xcard:UriParameterType"/>
+        </xs:complexContent>
+    </xs:complexType>
 
+    <!-- WARNING: don't forget to add those, otherwise the serialization code will not be built and you're up for a long debugging session       -->
+    <xs:element name="type" type="xcard:typeParamType" substitutionGroup="xcard:baseParameter"/>
+    <xs:element name="label" type="xcard:labelParamType" substitutionGroup="xcard:baseParameter"/>
+    <xs:element name="pref" type="xcard:prefParamType" substitutionGroup="xcard:baseParameter"/>
+    <xs:element name="x-uid" type="xcard:xuidParamType" substitutionGroup="xcard:baseParameter"/>
+    
 <!-- Properties -->
   <xs:complexType name="BasePropertyType" abstract="true" >
     <xs:sequence>


commit 039c548357d435350958569d5e32be0a96d4759b
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Wed Mar 7 18:08:55 2012 +0100

    xcard uid is a uri.

diff --git a/c++/lib/utils.cpp b/c++/lib/utils.cpp
index d476dfd..da9c34f 100644
--- a/c++/lib/utils.cpp
+++ b/c++/lib/utils.cpp
@@ -93,7 +93,7 @@ std::string getUID(const std::string &s)
 {
     if (s.empty()) {
         boost::uuids::uuid u; // initialize uuid
-        return boost::uuids::to_string(u);
+        return std::string("urn:uuid:")+boost::uuids::to_string(u);
     }
     return s;
 }
diff --git a/c++/lib/xcardconversions.h b/c++/lib/xcardconversions.h
index 5f7bbe8..f406105 100644
--- a/c++/lib/xcardconversions.h
+++ b/c++/lib/xcardconversions.h
@@ -478,7 +478,7 @@ std::string serializeCard(const T &card, const std::string prod = std::string())
 
     try {
         vcard_4_0::vcard::uid_type uid(getUID(card.uid()));
-        setCreatedUid(uid.text());
+        setCreatedUid(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()));
@@ -781,7 +781,7 @@ boost::shared_ptr<T> deserializeCard(const std::string& s, bool isUrl)
         }
         
         boost::shared_ptr<T> card = readCard<T>(vcards->vcard());
-        card->setUid(vcards->vcard().uid().text());
+        card->setUid(vcards->vcard().uid().uri());
         card->setName(vcards->vcard().fn().text());
         
         setProductId( vcards->vcard().prodid().text() );
diff --git a/schemas/xCard.xsd b/schemas/xCard.xsd
index 1d23de6..89d7481 100644
--- a/schemas/xCard.xsd
+++ b/schemas/xCard.xsd
@@ -225,7 +225,7 @@
   
   <xs:complexType name="uidPropType">
     <xs:complexContent mixed="false">
-      <xs:extension base="xcard:TextPropertyType"/>
+      <xs:extension base="xcard:UriPropertyType"/>
     </xs:complexContent>
   </xs:complexType>
   





More information about the commits mailing list