Hello community,

here is the log from the commit of package kcontacts for openSUSE:Factory 
checked in at 2017-05-22 10:39:39
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kcontacts (Old)
 and      /work/SRC/openSUSE:Factory/.kcontacts.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kcontacts"

Mon May 22 10:39:39 2017 rev:20 rq:495919 version:17.04.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/kcontacts/kcontacts.changes      2017-05-08 
18:49:15.552726797 +0200
+++ /work/SRC/openSUSE:Factory/.kcontacts.new/kcontacts.changes 2017-05-22 
10:39:41.810780238 +0200
@@ -1,0 +2,14 @@
+Wed May 17 20:36:00 CEST 2017 - lbeltr...@kde.org
+
+- Update to 17.04.1
+  * New bugfix release
+  * For more details please see:
+  * https://www.kde.org/announcements/announce-applications-17.04.1.php
+- Changes since 17.04.0:
+  * VCardParser: gain 1% of performance by using indexOf+mid instead of 
split('\n')
+  * Add missing include (make it happy jenkins)
+  * VCardParser: rewrite parser to use a state machine instead of split()
+  * VCardParser: extract class for parsing the current line
+  * Revert 1760aca (which commented out some unittests...).
+
+-------------------------------------------------------------------

Old:
----
  kcontacts-17.04.0.tar.xz

New:
----
  kcontacts-17.04.1.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kcontacts.spec ++++++
--- /var/tmp/diff_new_pack.IyEDR7/_old  2017-05-22 10:39:43.458547905 +0200
+++ /var/tmp/diff_new_pack.IyEDR7/_new  2017-05-22 10:39:43.458547905 +0200
@@ -20,7 +20,7 @@
 
 %define kf5_version 5.5.0
 Name:           kcontacts
-Version:        17.04.0
+Version:        17.04.1
 Release:        0
 %define kf5_version 5.26.0
 # Latest stable Applications (e.g. 16.08 in KA, but 16.11.80 in KUA)

++++++ kcontacts-17.04.0.tar.xz -> kcontacts-17.04.1.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcontacts-17.04.0/CMakeLists.txt 
new/kcontacts-17.04.1/CMakeLists.txt
--- old/kcontacts-17.04.0/CMakeLists.txt        2017-04-14 02:21:53.000000000 
+0200
+++ new/kcontacts-17.04.1/CMakeLists.txt        2017-05-09 02:26:31.000000000 
+0200
@@ -1,5 +1,5 @@
 cmake_minimum_required(VERSION 3.0)
-set(PIM_VERSION "5.5.0")
+set(PIM_VERSION "5.5.1")
 
 project(KContacts VERSION ${PIM_VERSION})
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcontacts-17.04.0/autotests/data/vcard10.vcf.ref 
new/kcontacts-17.04.1/autotests/data/vcard10.vcf.ref
--- old/kcontacts-17.04.0/autotests/data/vcard10.vcf.ref        2017-04-08 
06:47:01.000000000 +0200
+++ new/kcontacts-17.04.1/autotests/data/vcard10.vcf.ref        2017-04-26 
06:55:00.000000000 +0200
@@ -35,7 +35,8 @@
 N:Name;Surname;;Dr. med.;
 NOTE:Sprechzeiten:\nMo   8–12\, 15–18\nDi     8–12\nMi    8–12\, 14
  –15\nDo 14–19\nFr     8–12
-TITLE:Facharzt für Allgemeinmedizin
+TITLE;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=46acharzt f=C3=BCr Allgemein
+ medizin
 UID:b4fc4930-043f-446a-9a76-cf0b548368d8
 END:VCARD
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kcontacts-17.04.0/autotests/importexportvcardtest.cpp 
new/kcontacts-17.04.1/autotests/importexportvcardtest.cpp
--- old/kcontacts-17.04.0/autotests/importexportvcardtest.cpp   2017-04-08 
06:47:01.000000000 +0200
+++ new/kcontacts-17.04.1/autotests/importexportvcardtest.cpp   2017-04-26 
06:55:00.000000000 +0200
@@ -21,6 +21,7 @@
 #include "importexportvcardtest.h"
 #include <QTest>
 #include "vcardtool.h"
+#include <QDebug>
 
 ImportExportVCardTest::ImportExportVCardTest(QObject *parent)
     : QObject(parent)
@@ -33,6 +34,27 @@
 
 }
 
+static void compareBuffers(const QByteArray &outputData, const QByteArray 
&expected)
+{
+    if (outputData != expected) {
+        qDebug() << " outputData " << outputData;
+        qDebug() << " expected " << expected;
+    }
+    const QList<QByteArray> outputLines = outputData.split('\n');
+    const QList<QByteArray> outputRefLines = expected.split('\n');
+    for (int i = 0; i < qMin(outputLines.count(), outputRefLines.count()); 
++i) {
+        const QByteArray actual = outputLines.at(i);
+        const QByteArray expect = outputRefLines.at(i);
+        if (actual != expect) {
+            qCritical() << "Mismatch at output line" << (i + 1);
+            QCOMPARE(actual, expect);
+            QCOMPARE(actual.count(), expect.count());
+        }
+    }
+    QCOMPARE(outputLines.count(), outputRefLines.count());
+    QCOMPARE(outputData.size(), expected.size());
+}
+
 void ImportExportVCardTest::shouldExportFullTestVcard4()
 {
     QByteArray vcarddata("BEGIN:VCARD\r\n"
@@ -71,8 +93,9 @@
                          "END:VCARD\r\n\r\n");
     QByteArray vcardexpected("BEGIN:VCARD\r\n"
                              "VERSION:4.0\r\n"
-                             "ADR;GEO=\"geo:51.523701,0.158500\";LABEL=\"Mr 
Sherlock Holmes\";TYPE:;;221B Bak\r\n"
-                             " er Street;London;;NW1;United Kingdom\r\n"
+                             "ADR;GEO=\"geo:51.523701,0.158500\";LABEL=\"Mr 
Sherlock Holmes, 221B Baker Stre\r\n"
+                             " et, London NW1, England, United 
Kingdom\";TYPE:;;221B Baker Street;London;;\r\n"
+                             " NW1;United Kingdom\r\n"
                              "ANNIVERSARY:19960415\r\n"
                              "BDAY:19531015T231000Z\r\n"
                              
"CALADRURI;PREF=1:mailto:detect...@sherlockholmes.com\r\n";
@@ -93,7 +116,7 @@
                              "PRODID:-//KADDRESSBOOK//NONSGML Version 
1//EN\r\n"
                              "REV:20140722T222710Z\r\n"
                              "ROLE:Detective\r\n"
-                             "TEL;PREF=1;VALUE=uri:ext=5555\r\n"
+                             
"TEL;TYPE=\"home,voice\";PREF=1;VALUE=uri:tel:+44-555-555-5555;ext=5555\r\n"
                              
"TEL;TYPE=\"cell,voice\";VALUE=uri:tel:+44-555-555-6666\r\n"
                              
"TEL;TYPE=\"voice,work\";VALUE=uri:tel:+44-555-555-7777\r\n"
                              "TITLE;ALTID=1;LANGUAGE=fr:Patron\r\n"
@@ -107,8 +130,7 @@
     const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
 
     const QByteArray result = vcard.exportVCards(lst, KContacts::VCard::v4_0);
-    //qDebug() << " result " << result;
-    QCOMPARE(result, vcardexpected);
+    compareBuffers(result, vcardexpected);
 }
 
 void ImportExportVCardTest::shouldExportMiscElementVcard4()
@@ -140,9 +162,7 @@
     const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
 
     const QByteArray result = vcard.exportVCards(lst, KContacts::VCard::v4_0);
-    //qDebug() << " result " << result;
-    QCOMPARE(result, vcardexpected);
-
+    compareBuffers(result, vcardexpected);
 }
 
 void ImportExportVCardTest::shouldExportMemberElementVcard4()
@@ -174,8 +194,9 @@
     const KContacts::AddresseeList lst = vcard.parseVCards(vcarddata);
 
     const QByteArray result = vcard.exportVCards(lst, KContacts::VCard::v4_0);
-    //qDebug() << " result " << result;
-    QCOMPARE(result, vcardexpected);
+    compareBuffers(result, vcardexpected);
 }
 
+// TODO please make this data driven before copy/pasting more methods here...
+
 QTEST_MAIN(ImportExportVCardTest)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcontacts-17.04.0/autotests/testroundtrip.cpp 
new/kcontacts-17.04.1/autotests/testroundtrip.cpp
--- old/kcontacts-17.04.0/autotests/testroundtrip.cpp   2017-04-08 
06:47:01.000000000 +0200
+++ new/kcontacts-17.04.1/autotests/testroundtrip.cpp   2017-04-26 
06:55:00.000000000 +0200
@@ -99,6 +99,27 @@
     }
 }
 
+static void compareBuffers(const char *version, const QByteArray &outputData, 
const QByteArray &outputRefData)
+{
+    if (outputData != outputRefData) {
+        qDebug() << " outputData " << outputData;
+        qDebug() << " outputRefData " << outputRefData;
+    }
+    const QList<QByteArray> outputLines = outputData.split('\n');
+    const QList<QByteArray> outputRefLines = outputRefData.split('\n');
+    for (int i = 0; i < qMin(outputLines.count(), outputRefLines.count()); 
++i) {
+        const QByteArray actual = outputLines.at(i);
+        const QByteArray expect = outputRefLines.at(i);
+        if (actual != expect) {
+            qCritical() << "Mismatch in" << version << "output line" << (i + 
1);
+            QCOMPARE(actual, expect);
+            QCOMPARE(actual.count(), expect.count());
+        }
+    }
+    QCOMPARE(outputLines.count(), outputRefLines.count());
+    QCOMPARE(outputData.size(), outputRefData.size());
+}
+
 void RoundtripTest::testVCardRoundtrip()
 {
     QFETCH(QString, inputFile);
@@ -128,23 +149,7 @@
         QVERIFY(outputFile.open(QIODevice::ReadOnly));
 
         const QByteArray outputRefData = outputFile.readAll();
-        QCOMPARE(outputData.size(), outputRefData.size());
-
-        const QList<QByteArray> outputLines = outputData.split('\n');
-        const QList<QByteArray> outputRefLines = outputRefData.split('\n');
-        QCOMPARE(outputLines.count(), outputRefLines.count());
-        for (int i = 0; i < outputLines.count(); ++i) {
-            const QByteArray actual = outputLines[i];
-            const QByteArray expect = outputRefLines[i];
-
-            if (actual != expect) {
-                qCritical() << "Mismatch in v2.1 output line" << (i + 1);
-                QCOMPARE(actual.count(), expect.count());
-
-                qCritical() << "\nActual:" << actual << "\nExpect:" << expect;
-                QCOMPARE(actual, expect);
-            }
-        }
+        compareBuffers("v2.1", outputData, outputRefData);
     }
 
     if (!output3_0File.isEmpty()) {
@@ -154,26 +159,7 @@
         QVERIFY(outputFile.open(QIODevice::ReadOnly));
 
         const QByteArray outputRefData = outputFile.readAll();
-        if (outputData.size() != outputRefData.size()) {
-            qDebug() << " outputRefData " << outputRefData << endl;
-            qDebug() << " outputData " << outputData;
-        }
-        QCOMPARE(outputData.size(), outputRefData.size());
-        const QList<QByteArray> outputLines = outputData.split('\n');
-        const QList<QByteArray> outputRefLines = outputRefData.split('\n');
-        QCOMPARE(outputLines.count(), outputRefLines.count());
-        for (int i = 0; i < outputLines.count(); ++i) {
-            const QByteArray actual = outputLines[i];
-            const QByteArray expect = outputRefLines[i];
-
-            if (actual != expect) {
-                qCritical() << "Mismatch in v3.0 output line" << (i + 1);
-
-                qCritical() << "\nActual:" << actual << "\nExpect:" << expect;
-                QCOMPARE(actual.count(), expect.count());
-                QCOMPARE(actual, expect);
-            }
-        }
+        compareBuffers("v3.0", outputData, outputRefData);
     }
 #if 0
     if (!output4_0File.isEmpty()) {
@@ -183,28 +169,7 @@
         QVERIFY(outputFile.open(QIODevice::ReadOnly));
 
         const QByteArray outputRefData = outputFile.readAll();
-        if (outputData.size() != outputRefData.size()) {
-            qDebug() << " outputRefData " << outputRefData << endl;
-            qDebug() << " outputData " << outputData;
-        }
-        //QCOMPARE( outputData.size(), outputRefData.size() );
-
-        const QList<QByteArray> outputLines = outputData.split('\n');
-        const QList<QByteArray> outputRefLines = outputRefData.split('\n');
-        //QCOMPARE(outputLines.count(), outputRefLines.count());
-
-        for (int i = 0; i < outputLines.count(); ++i) {
-            const QByteArray actual = outputLines[i];
-            const QByteArray expect = outputRefLines[i];
-
-            if (actual != expect) {
-                qCritical() << "Mismatch in v4.0 output line" << (i + 1);
-
-                qCritical() << "\nActual:" << actual << "\nExpect:" << expect;
-                QCOMPARE(actual.count(), expect.count());
-                QCOMPARE(actual, expect);
-            }
-        }
+        compareBuffers("v4.0", outputData, outputRefData);
     }
 #endif
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcontacts-17.04.0/autotests/testroundtrip.qrc 
new/kcontacts-17.04.1/autotests/testroundtrip.qrc
--- old/kcontacts-17.04.0/autotests/testroundtrip.qrc   2017-04-08 
06:47:01.000000000 +0200
+++ new/kcontacts-17.04.1/autotests/testroundtrip.qrc   2017-04-26 
06:55:00.000000000 +0200
@@ -3,14 +3,14 @@
   <qresource prefix="/input">
     <file>data/vcard1.vcf</file>
     <file>data/vcard2.vcf</file>
-    <!-- <file>data/vcard3.vcf</file> 
-    <file>data/vcard4.vcf</file> -->
+    <file>data/vcard3.vcf</file>
+    <file>data/vcard4.vcf</file>
     <file>data/vcard5.vcf</file>
     <file>data/vcard6.vcf</file>
     <file>data/vcard7.vcf</file>
     <file>data/vcard8.vcf</file>
     <file>data/vcard9.vcf</file>
-    <!-- <file>data/vcard10.vcf</file> -->
+    <file>data/vcard10.vcf</file>
     <file>data/vcard11.vcf</file>
     <file>data/vcard12.vcf</file>
     <file>data/vcard13.vcf</file>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kcontacts-17.04.0/src/vcardparser/vcardparser.cpp 
new/kcontacts-17.04.1/src/vcardparser/vcardparser.cpp
--- old/kcontacts-17.04.0/src/vcardparser/vcardparser.cpp       2017-04-08 
06:47:01.000000000 +0200
+++ new/kcontacts-17.04.1/src/vcardparser/vcardparser.cpp       2017-04-26 
06:55:00.000000000 +0200
@@ -22,6 +22,7 @@
 #include <kcodecs.h>
 #include "kcontacts_debug.h"
 #include <QtCore/QTextCodec>
+#include <functional>
 
 // This cache for QString::fromLatin1() isn't about improving speed, but about 
reducing memory usage by sharing common strings
 class StringCache
@@ -72,6 +73,185 @@
     str.replace("\\\\", "\\");
 }
 
+class VCardLineParser
+{
+public:
+    VCardLineParser(StringCache &cache, std::function<QByteArray()> 
fetchAnotherLine)
+      : m_cache(cache), m_fetchAnotherLine(fetchAnotherLine)
+    {
+    }
+
+    void parseLine(const QByteArray &currentLine, VCardLine *vCardLine);
+
+private:
+    void addParameter(const QByteArray &paramKey, const QByteArray 
&paramValue);
+
+private:
+    StringCache &m_cache;
+    std::function<QByteArray()> m_fetchAnotherLine;
+
+    VCardLine *m_vCardLine;
+    QByteArray m_encoding;
+    QByteArray m_charset;
+};
+
+void VCardLineParser::addParameter(const QByteArray& paramKey, const 
QByteArray& paramValue)
+{
+    if (paramKey == "encoding") {
+        m_encoding = paramValue.toLower();
+    } else if (paramKey == "charset") {
+        m_charset = paramValue.toLower();
+    }
+    //qDebug() << "  add parameter" << paramKey << "    =    " << paramValue;
+    m_vCardLine->addParameter(m_cache.fromLatin1(paramKey), 
m_cache.fromLatin1(paramValue));
+}
+
+void VCardLineParser::parseLine(const QByteArray& currentLine, 
KContacts::VCardLine* vCardLine)
+{
+    //qDebug() << currentLine;
+    m_vCardLine = vCardLine;
+    // The syntax is key:value, but the key can contain semicolon-separated 
parameters, which can contain a ':', so indexOf(':') is wrong.
+    // EXAMPLE: ADR;GEO="geo:22.500000,45.099998";LABEL="My 
Label";TYPE=home:P.O. Box 101;;;Any Town;CA;91921-1234;
+    // Therefore we need a small state machine, just the way I like it.
+    enum State { StateInitial, StateParamKey, StateParamValue, 
StateQuotedValue, StateAfterParamValue, StateValue };
+    State state = StateInitial;
+    const int lineLength = currentLine.length();
+    const char *lineData = currentLine.constData(); // to skip length checks 
from at() in debug mode
+    QByteArray paramKey;
+    QByteArray paramValue;
+    int start = 0;
+    int pos = 0;
+    for (; pos < lineLength; ++pos) {
+        const char ch = lineData[pos];
+        const bool colonOrSemicolon = (ch == ';' || ch == ':');
+        switch (state) {
+        case StateInitial:
+            if (colonOrSemicolon) {
+                const QByteArray identifier = currentLine.mid(start, pos - 
start);
+                //qDebug() << " identifier" << identifier;
+                vCardLine->setIdentifier(m_cache.fromLatin1(identifier));
+                start = pos + 1;
+            }
+            if (ch == ';') {
+                state = StateParamKey;
+            } else if (ch == ':') {
+                state = StateValue;
+            } else if (ch == '.') {
+                vCardLine->setGroup(m_cache.fromLatin1(currentLine.mid(start, 
pos - start)));
+                start = pos + 1;
+            }
+            break;
+        case StateParamKey:
+            if (colonOrSemicolon || ch == '=') {
+                paramKey = currentLine.mid(start, pos - start);
+                start = pos + 1;
+            }
+            if (colonOrSemicolon) {
+                // correct the so-called 2.1 'standard'
+                paramValue = paramKey;
+                const QByteArray lowerKey = paramKey.toLower();
+                if (lowerKey == "quoted-printable" || lowerKey == "base64") {
+                    paramKey = "encoding";
+                } else {
+                    paramKey = "type";
+                }
+                addParameter(paramKey, paramValue);
+            }
+            if (ch == ';') {
+                state = StateParamKey;
+            } else if (ch == ':') {
+                state = StateValue;
+            } else if (ch == '=') {
+                state = StateParamValue;
+            }
+            break;
+        case StateQuotedValue:
+            if (ch == '"' || (ch == ',' && paramKey.toLower() == "type")) {
+                // TODO the hack above is for TEL;TYPE=\"voice,home\":... 
without breaking GEO.... TODO: check spec
+                paramValue = currentLine.mid(start, pos - start);
+                addParameter(paramKey.toLower(), paramValue);
+                start = pos + 1;
+                if (ch == '"') {
+                    state = StateAfterParamValue; // to avoid duplicating code 
with StateParamValue, we use this intermediate state for one char
+                }
+            }
+            break;
+        case StateParamValue:
+            if (colonOrSemicolon || ch == ',') {
+                paramValue = currentLine.mid(start, pos - start);
+                addParameter(paramKey.toLower(), paramValue);
+                start = pos + 1;
+            }
+            // fall-through intended
+        case StateAfterParamValue:
+            if (ch == ';') {
+                state = StateParamKey;
+                start = pos + 1;
+            } else if (ch == ':') {
+                state = StateValue;
+            } else if (pos == start && ch == '"') { // don't treat foo"bar" as 
quoted - TODO check the vCard 3.0 spec.
+                state = StateQuotedValue;
+                start = pos + 1;
+            }
+            break;
+        case StateValue:
+            Q_UNREACHABLE();
+            break;
+        }
+
+        if (state == StateValue) {
+            break;
+        }
+    }
+
+    if (state != StateValue) {   // invalid line, no ':'
+        return;
+    }
+
+    QByteArray value = currentLine.mid(pos + 1);
+    removeEscapes(value);
+
+    QByteArray output;
+    bool wasBase64Encoded = false;
+
+    if (!m_encoding.isEmpty()) {
+        // have to decode the data
+        if (m_encoding == "b" || m_encoding == "base64") {
+            output = QByteArray::fromBase64(value);
+            wasBase64Encoded = true;
+        } else if (m_encoding == "quoted-printable") {
+            // join any qp-folded lines
+            while (value.endsWith('=')) {
+                value.chop(1);   // remove the '='
+                value.append(m_fetchAnotherLine());
+            }
+            KCodecs::quotedPrintableDecode(value, output);
+        } else if (m_encoding == "8bit") {
+            output = value;
+        } else {
+            qDebug("Unknown vcard encoding type!");
+        }
+    } else {
+        output = value;
+    }
+
+    if (!m_charset.isEmpty()) {
+        // have to convert the data
+        QTextCodec *codec = QTextCodec::codecForName(m_charset);
+        if (codec) {
+            vCardLine->setValue(codec->toUnicode(output));
+        } else {
+            vCardLine->setValue(QString::fromUtf8(output));
+        }
+    } else if (wasBase64Encoded) {
+        vCardLine->setValue(output);
+    } else {
+        vCardLine->setValue(QString::fromUtf8(output));
+    }
+}
+
+////
+
 VCardParser::VCardParser()
     : d(nullptr)
 {
@@ -87,15 +267,14 @@
     VCard::List vCardList;
     QByteArray currentLine;
 
-    const QList<QByteArray> lines = text.split('\n');
+    int lineStart = 0;
+    int lineEnd = text.indexOf('\n');
 
     bool inVCard = false;
-    const QList<QByteArray>::const_iterator linesEnd(lines.end());
 
     StringCache cache;
-
-    for (auto it = lines.begin(); it != linesEnd; ++it) {
-        QByteArray cur = *it;
+    for (; lineEnd != -1; lineStart = lineEnd + 1, lineEnd = 
text.indexOf('\n', lineStart)) {
+        QByteArray cur = text.mid(lineStart, lineEnd - lineStart);
         // remove the trailing \r, left from \r\n
         if (cur.endsWith('\r')) {
             cur.chop(1);
@@ -110,164 +289,26 @@
                 continue;
             }
             if (inVCard && !currentLine.isEmpty()) {   // now parse the line
-                int colon = currentLine.indexOf(':');
-                if (colon == -1) {   // invalid line
-                    currentLine = cur;
-                    continue;
-                }
-                bool keyFound = false;
-                QByteArray key;
-                QList<QByteArray> params;
-                const int currentLineLength(currentLine.length());
-                for (int i = 0; i < currentLineLength; ++i) {
-                    char character = currentLine.at(i);
-                    if (keyFound) {
-                        const QList<QByteArray> tmpParams = 
currentLine.mid(i).split(';');
-                        QByteArray tmpParameter;
-                        bool valueAdded = false;
-                        for (const QByteArray &parameter : tmpParams) {
-                            if (parameter.contains('=')) {
-                                if (tmpParameter.isEmpty()) {
-                                    tmpParameter = parameter;
-                                } else {
-                                    params << tmpParameter;
-                                    tmpParameter = parameter;
-                                }
-                            } else {
-                                if (tmpParameter.isEmpty() && !valueAdded) {
-                                    tmpParameter = parameter;
-                                    valueAdded = true;
-                                } else {
-                                    tmpParameter += ';' + parameter;
-                                }
-                            }
-                        }
-                        if (!tmpParameter.isEmpty()) {
-                            params << tmpParameter;
-                        }
-                        break;
-                    } else {
-                        if ((character == ';' || character == ':') && 
!keyFound) {
-                            keyFound = true;
-                        } else {
-                            key += character;
-                        }
-                    }
-                }
                 VCardLine vCardLine;
-                QByteArray value;
-                if (!params.isEmpty()) {
-                    value = params.takeLast();
-                    if (value.contains('=')) {
-                        colon = value.indexOf(':');
-                        const QByteArray lastParam = 
value.left(colon).trimmed();
-                        if ((lastParam != "geo")) {
-                            params.append(lastParam);
-                            value = value.mid(colon + 1);
-                        } else {
-                            params.append(value);
-                        }
-                    }
-                }
-                params.prepend(key);
-                // check for group
-                const QByteArray firstParam = params.at(0);
-                const int groupPos = firstParam.indexOf('.');
-                if (groupPos != -1) {
-                    
vCardLine.setGroup(cache.fromLatin1(firstParam.left(groupPos)));
-                    
vCardLine.setIdentifier(cache.fromLatin1(firstParam.mid(groupPos + 1)));
-                } else {
-                    vCardLine.setIdentifier(cache.fromLatin1(firstParam));
-                }
 
-                if (params.count() > 1) {   // find all parameters
-                    QList<QByteArray>::ConstIterator 
paramIt(params.constBegin());
-                    for (++paramIt; paramIt != params.constEnd(); ++paramIt) {
-                        QList<QByteArray> pair = (*paramIt).split('=');
-                        QByteArray first = pair.at(0).toLower();
-                        if (pair.count() == 1) {
-                            // correct the fucking 2.1 'standard'
-                            if (first == "quoted-printable") {
-                                pair[ 0 ] = "encoding";
-                                pair.append("quoted-printable");
-                            } else if (first == "base64") {
-                                pair[ 0 ] = "encoding";
-                                pair.append("base64");
-                            } else {
-                                pair.prepend("type");
-                            }
-                            first = pair.at(0);
-                        }
-                        const QByteArray second = pair.at(1);
-                        if (second.contains(':')) {
-                            vCardLine.addParameter(cache.fromLatin1(first),
-                                                   cache.fromLatin1(second));
-                        } else if (second.contains(',')) {     // parameter in 
type=x,y,z format
-                            const QList<QByteArray> args = second.split(',');
-                            for (QByteArray tmpArg : args) {
-                                if (tmpArg.startsWith('"')) {
-                                    tmpArg = tmpArg.mid(1);
-                                }
-                                if (tmpArg.endsWith('"')) {
-                                    tmpArg.chop(1);
-                                }
-                                vCardLine.addParameter(cache.fromLatin1(first),
-                                                       
cache.fromLatin1(tmpArg));
-                            }
-                        } else {
-                            vCardLine.addParameter(cache.fromLatin1(first),
-                                                   cache.fromLatin1(second));
+                // Provide a way for the parseVCardLine function to read more 
lines (for quoted-printable support)
+                auto fetchAnotherLine = [&text, &lineStart, &lineEnd, &cur]() 
-> QByteArray {
+                    const QByteArray ret = cur;
+                    lineStart = lineEnd + 1;
+                    lineEnd = text.indexOf('\n', lineStart);
+                    if (lineEnd != -1) {
+                        cur = text.mid(lineStart, lineEnd - lineStart);
+                        // remove the trailing \r, left from \r\n
+                        if (cur.endsWith('\r')) {
+                            cur.chop(1);
                         }
                     }
-                }
-
-                removeEscapes(value);
+                    return ret;
+                };
 
-                QByteArray output;
-                bool wasBase64Encoded = false;
+                VCardLineParser lineParser(cache, fetchAnotherLine);
 
-                const QString encoding = 
vCardLine.parameter(QStringLiteral("encoding")).toLower();
-                if (!encoding.isEmpty()) {
-
-                    // have to decode the data
-                    if (encoding == QLatin1String("b") || encoding == 
QLatin1String("base64")) {
-                        output = QByteArray::fromBase64(value);
-                        wasBase64Encoded = true;
-                    } else if (encoding == QLatin1String("quoted-printable")) {
-                        // join any qp-folded lines
-                        while (value.endsWith('=') && it != linesEnd) {
-                            value.chop(1);   // remove the '='
-                            value.append(cur);
-                            cur = *(++it);
-                            // remove the trailing \r, left from \r\n
-                            if (cur.endsWith('\r')) {
-                                cur.chop(1);
-                            }
-                        }
-                        KCodecs::quotedPrintableDecode(value, output);
-                    } else if (encoding == QLatin1String("8bit")) {
-                        output = value;
-                    } else {
-                        qDebug("Unknown vcard encoding type!");
-                    }
-                } else {
-                    output = value;
-                }
-
-                const QString charset = 
vCardLine.parameter(QStringLiteral("charset"));
-                if (!charset.isEmpty()) {
-                    // have to convert the data
-                    QTextCodec *codec = 
QTextCodec::codecForName(charset.toLatin1());
-                    if (codec) {
-                        vCardLine.setValue(codec->toUnicode(output));
-                    } else {
-                        vCardLine.setValue(QString::fromUtf8(output));
-                    }
-                } else if (wasBase64Encoded) {
-                    vCardLine.setValue(output);
-                } else {
-                    vCardLine.setValue(QString::fromUtf8(output));
-                }
+                lineParser.parseLine(currentLine, &vCardLine);
 
                 currentVCard.addLine(vCardLine);
             }


Reply via email to