CMakeLists.txt cmake/modules COPYING src/CMakeLists.txt src/uricode.h src/uriencode.cpp src/uriencode.h src/utils.cpp tests/conversiontest.cpp tests/conversiontest.h

Christian Mollekopf mollekopf at kolabsys.com
Tue Jul 17 12:05:46 CEST 2012


 CMakeLists.txt                                  |    1 
 COPYING                                         |    1 
 cmake/modules/FindLibkolabxmlDependencies.cmake |    9 +
 src/CMakeLists.txt                              |    4 
 src/uricode.h                                   |  124 ------------------------
 src/uriencode.cpp                               |   46 ++++++++
 src/uriencode.h                                 |   29 +++++
 src/utils.cpp                                   |    6 -
 tests/conversiontest.cpp                        |   23 +++-
 tests/conversiontest.h                          |    1 
 10 files changed, 107 insertions(+), 137 deletions(-)

New commits:
commit dacb5c4bb756794788e75288e0d765f437d5d264
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Tue Jul 17 12:05:19 2012 +0200

    Replaced non-free uri encoding code with libcurl.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 495d1f2..76add63 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -173,6 +173,7 @@ include_directories(
     ${Boost_INCLUDE_DIRS}
     ${XSDCXX_INCLUDE_DIRS}
     ${XERCES_C_INCLUDE_DIRS}
+    ${CURL_INCLUDE_DIRS}
 )
 
 
diff --git a/COPYING b/COPYING
index 8f75ae9..724d8fe 100644
--- a/COPYING
+++ b/COPYING
@@ -2,5 +2,4 @@ schemas/*: Apache v2 (see http://www.calconnect.org/artifacts/ical-art.shtml)
 compiled/xsdbin.cxx: not copyrighted - public domain
 compiled/grammar-input-stream.*: not copyrighted - public domain
 src/base64.*: Copyright (C) 2004-2008 René Nyffenegger
-src/uricode.h: Copyright (C) Jin Qing
 everything else: LGPLv3 or later
\ No newline at end of file
diff --git a/cmake/modules/FindLibkolabxmlDependencies.cmake b/cmake/modules/FindLibkolabxmlDependencies.cmake
index 84c2de6..66eefd6 100644
--- a/cmake/modules/FindLibkolabxmlDependencies.cmake
+++ b/cmake/modules/FindLibkolabxmlDependencies.cmake
@@ -30,6 +30,13 @@ endif()
 find_package_handle_standard_args(Xerces  DEFAULT_MSG
                                   XERCES_C XERCES_C_INCLUDE_DIRS)
 
+find_library(CURL NAMES curl)
+if (CURL)
+    find_path(CURL_INCLUDE_DIRS NAMES curl/curl.h)
+endif()
+find_package_handle_standard_args(Curl  DEFAULT_MSG
+                                  CURL CURL_INCLUDE_DIRS)
+
 find_program(SWIG swig /usr/bin/)
 if(SWIG)
     set(SWIG_FOUND ON)
@@ -44,4 +51,4 @@ endif()
 
 #abort if any of the requireds are missing
 find_package_handle_standard_args(LibkolabxmlDependencies  DEFAULT_MSG
-                                  UUID_LIBRARY_FOUND XSDCXX XERCES_C)
+                                  UUID_LIBRARY_FOUND XSDCXX XERCES_C CURL)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dfb2721..94a3de0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -15,13 +15,13 @@ add_library(kolabxml SHARED
     containers/kolabcontact.cpp
     containers/kolabconfiguration.cpp
     containers/kolabfreebusy.cpp
-    utils.cpp base64.cpp
+    utils.cpp base64.cpp uriencode.cpp
     ../compiled/XMLParserWrapper.cpp
     ../compiled/grammar-input-stream.cxx
     ${SCHEMA_SOURCEFILES}
 )
 add_dependencies(kolabxml generate_bindings)
-target_link_libraries(kolabxml ${XERCES_C} ${Boost_LIBRARIES} ${UUID})
+target_link_libraries(kolabxml ${XERCES_C} ${Boost_LIBRARIES} ${UUID} ${CURL})
 
 # For the core library we can be stricter when compiling. This doesn't work with the auto generated code though.
 if (${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.42)
diff --git a/src/uricode.h b/src/uricode.h
deleted file mode 100644
index 86c5f8d..0000000
--- a/src/uricode.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Uri encode and decode.
-// RFC1630, RFC1738, RFC2396
-//
-// Copyright 2006 Jin Qing
-
-#include <string>
-#include <assert.h>
-
-const char HEX2DEC[256] = 
-{
-    /*       0  1  2  3   4  5  6  7   8  9  A  B   C  D  E  F */
-    /* 0 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* 1 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* 2 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* 3 */  0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1,
-    
-    /* 4 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* 5 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* 6 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* 7 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    
-    /* 8 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* 9 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* A */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* B */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    
-    /* C */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* D */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* E */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-    /* F */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
-};
-
-std::string UriDecode(const std::string & sSrc)
-{
-    // Note from RFC1630:  "Sequences which start with a percent sign
-    // but are not followed by two hexadecimal characters (0-9, A-F) are reserved
-    // for future extension"
-    
-    const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
-    const std::string::size_type SRC_LEN = sSrc.length();
-    const unsigned char * const SRC_END = pSrc + SRC_LEN;
-    const unsigned char * const SRC_LAST_DEC = SRC_END - 2;   // last decodable '%' 
-    
-    char * const pStart = new char[SRC_LEN];
-    char * pEnd = pStart;
-    
-    while (pSrc < SRC_LAST_DEC)
-    {
-        if (*pSrc == '%')
-        {
-            char dec1, dec2;
-            if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)])
-                && -1 != (dec2 = HEX2DEC[*(pSrc + 2)]))
-            {
-                *pEnd++ = static_cast<char>((dec1 << 4) + dec2);
-                pSrc += 3;
-                continue;
-            }
-        }
-        
-        *pEnd++ = *pSrc++;
-    }
-    
-    // the last 2- chars
-    while (pSrc < SRC_END)
-        *pEnd++ = *pSrc++;
-    
-    std::string sResult(pStart, pEnd);
-    delete [] pStart;
-    return sResult;
-}
-
-// Only alphanum is safe.
-const char SAFE[256] =
-{
-    /*      0 1 2 3  4 5 6 7  8 9 A B  C D E F */
-    /* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
-    /* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
-    /* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
-    /* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0,
-    
-    /* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
-    /* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
-    /* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
-    /* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
-    
-    /* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
-    /* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
-    /* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
-    /* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
-    
-    /* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
-    /* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
-    /* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
-    /* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
-};
-
-std::string UriEncode(const std::string & sSrc)
-{
-    const char DEC2HEX[16 + 1] = "0123456789ABCDEF";
-    const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
-    const std::string::size_type SRC_LEN = sSrc.length();
-    unsigned char * const pStart = new unsigned char[SRC_LEN * 3];
-    unsigned char * pEnd = pStart;
-    const unsigned char * const SRC_END = pSrc + SRC_LEN;
-    
-    for (; pSrc < SRC_END; ++pSrc)
-    {
-        if (SAFE[*pSrc]) 
-            *pEnd++ = *pSrc;
-        else
-        {
-            // escape this char
-            *pEnd++ = '%';
-            *pEnd++ = DEC2HEX[*pSrc >> 4];
-            *pEnd++ = DEC2HEX[*pSrc & 0x0F];
-        }
-    }
-    
-    std::string sResult((char *)pStart, (char *)pEnd);
-    delete [] pStart;
-    return sResult;
-}
-
diff --git a/src/uriencode.cpp b/src/uriencode.cpp
new file mode 100644
index 0000000..363f98e
--- /dev/null
+++ b/src/uriencode.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012  Christian Mollekopf <mollekopf at kolabsys.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <curl/curl.h>
+#include <string>
+
+std::string uriEncode(const std::string &s)
+{
+    CURL *easyhandle = curl_easy_init();
+    const char *result = curl_easy_escape(easyhandle, s.c_str(), s.length());
+    curl_easy_cleanup(easyhandle);
+    if (!result) {
+        return std::string();
+    }
+    const std::string r(result);
+    curl_free(result);
+    return r;
+}
+
+std::string uriDecode(const std::string &s)
+{
+    CURL *easyhandle = curl_easy_init();
+    int length = 0;
+    const char *result = curl_easy_unescape(easyhandle, s.c_str(), s.length(), &length);
+    curl_easy_cleanup(easyhandle);
+    if (!length) {
+        return std::string();
+    }
+    const std::string r(result, length);
+    curl_free(result);
+    return r;
+}
diff --git a/src/uriencode.h b/src/uriencode.h
new file mode 100644
index 0000000..c704351
--- /dev/null
+++ b/src/uriencode.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012  Christian Mollekopf <mollekopf at kolabsys.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef URIENCODE_H
+#define URIENCODE_H
+
+#include <string>
+
+/**
+ * Url encoding according to RFC 3986 (used for mailto encoding)
+ */
+std::string uriEncode(const std::string &s);
+std::string uriDecode(const std::string &s);
+
+#endif
\ No newline at end of file
diff --git a/src/utils.cpp b/src/utils.cpp
index 5e0bcb0..db0e254 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -33,7 +33,7 @@
 #include <boost/thread.hpp>
 #include <time.h>
 #include "base64.h"
-#include "uricode.h"
+#include "uriencode.h"
 #include "libkolabxml-version.h"
 
 namespace Kolab {
@@ -251,12 +251,12 @@ std::string toMailto(const std::string &email, const std::string &name)
     mailto.append("<");
     mailto.append(email);
     mailto.append(">");
-    return std::string("mailto:")+UriEncode(mailto);
+    return std::string("mailto:")+uriEncode(mailto);
 }
 
 std::string fromMailto(const std::string &mailtoUri, std::string &name)
 {
-    const std::string &decoded = UriDecode(mailtoUri);
+    const std::string &decoded = uriDecode(mailtoUri);
     if (decoded.substr(0, 7).compare("mailto:")) {
         WARNING("no mailto address");
         std::cout << decoded << std::endl;
diff --git a/tests/conversiontest.cpp b/tests/conversiontest.cpp
index 7144fb4..8ead31d 100644
--- a/tests/conversiontest.cpp
+++ b/tests/conversiontest.cpp
@@ -174,10 +174,10 @@ 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";
+    QTest::newRow("1") << "email_1 at email.com" << "John Doe" << "mailto:John%20Doe%3Cemail_1%40email.com%3E";
+    QTest::newRow("Reserved characters") << "!*'();:@&=+$,/?#[]@email.com" << "John Doe" << "mailto:John%20Doe%3C%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D%40email.com%3E";
+    QTest::newRow("Unreserved characters") << "Aa0-_.~@email.com" << "John Doe" << "mailto:John%20Doe%3CAa0-_.~%40email.com%3E";
     
     Kolab::Utils::clearErrors();
 }
@@ -186,18 +186,29 @@ 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;
+//     std::cout << mailto << std::endl;
     QCOMPARE(QString::fromStdString(mailto), resultEncoded);
     std::string n;
-    const std::string &e = Kolab::XCARD::fromMailto(mailto, n);
+    const std::string &e = Kolab::XCARD::fromMailto(resultEncoded.toStdString(), n);
     QCOMPARE(QString::fromStdString(n), name);
     QCOMPARE(QString::fromStdString(e), email);
     
 }
 
+void ConversionTest::mailtoUriDecodingTest()
+{
+    QString name("John Doe");
+    QString email("email_1 at email.com");
+    //While we shouldn't encode '_' and '.' according to RFC 3986, we should still understand it for backwards compatiblity
+    const std::string resultEncoded = "mailto:John%20Doe%3Cemail%5F1%40email%2Ecom%3E";
+    std::string n;
+    const std::string &e = Kolab::XCARD::fromMailto(resultEncoded, n);
+    QCOMPARE(QString::fromStdString(n), name);
+    QCOMPARE(QString::fromStdString(e), email);
+}
+
 void ConversionTest::urnTest()
 {
     QCOMPARE(Kolab::Shared::toURN("1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000"));
diff --git a/tests/conversiontest.h b/tests/conversiontest.h
index 7ccd110..1ae4094 100644
--- a/tests/conversiontest.h
+++ b/tests/conversiontest.h
@@ -32,6 +32,7 @@ class ConversionTest : public QObject
     
     void mailtoUriEncodingTest_data();
     void mailtoUriEncodingTest();
+    void mailtoUriDecodingTest();
     
     void urnTest();
     





More information about the commits mailing list