diff options
author | Kevin Wu Won <kevin.wuwon@nokia.com> | 2011-01-14 16:57:08 +1000 |
---|---|---|
committer | Kevin Wu Won <kevin.wuwon@nokia.com> | 2011-01-14 17:27:36 +1000 |
commit | 0d2aad9c04a7f2327ac8ae83cb7565a532a3811a (patch) | |
tree | d6c98c627dfe185f2c61a60b7aa803cd0682ab38 | |
parent | 4d59e71d6d385b7e18bdf2ca0d8f9a1a3118f7d3 (diff) |
QVCard21Writer: Use Quoted-Printable soft-line breaks for wrapping
This is necessary because Symbian devices don't support vCard-style folding
on Quoted-Printable properties.
Task-number: MOBILITY-2353
Reviewed-by: Michael Goddard
Change-Id: I59fdd6a448c64e4b94b2840596120f0869a435f1
-rw-r--r-- | src/versit/qvcard21writer.cpp | 8 | ||||
-rw-r--r-- | src/versit/qversitdocumentwriter_p.cpp | 34 | ||||
-rw-r--r-- | src/versit/qversitdocumentwriter_p.h | 1 | ||||
-rw-r--r-- | tests/auto/qvcard21writer/qvcard21writer.pro | 1 | ||||
-rw-r--r-- | tests/auto/qvcard21writer/tst_qvcard21writer.cpp | 31 |
5 files changed, 68 insertions, 7 deletions
diff --git a/src/versit/qvcard21writer.cpp b/src/versit/qvcard21writer.cpp index b9acf7de74..9055cbfb2a 100644 --- a/src/versit/qvcard21writer.cpp +++ b/src/versit/qvcard21writer.cpp @@ -129,7 +129,13 @@ void QVCard21Writer::encodeVersitProperty(const QVersitProperty& property) QVersitDocument embeddedDocument = variant.value<QVersitDocument>(); encodeVersitDocument(embeddedDocument); } else if (variant.type() == QVariant::String || variant.type() == QVariant::StringList) { - writeString(renderedValue); + // Some devices don't support vCard-style line folding if the property is + // quoted-printable-encoded. Therefore, we use QP soft linebreaks if the property is being + // QP-encoded, and normal vCard folding otherwise. + if (parameters.contains("ENCODING", QLatin1String("QUOTED-PRINTABLE"))) + writeStringQp(renderedValue); + else + writeString(renderedValue); } else if (variant.type() == QVariant::ByteArray) { // One extra folding before the value and // one extra line break after the value are needed in vCard 2.1 diff --git a/src/versit/qversitdocumentwriter_p.cpp b/src/versit/qversitdocumentwriter_p.cpp index f81cfdb006..e8f5093aea 100644 --- a/src/versit/qversitdocumentwriter_p.cpp +++ b/src/versit/qversitdocumentwriter_p.cpp @@ -237,6 +237,40 @@ void QVersitDocumentWriter::writeString(const QString &value) } /*! + Writes \a value to the device. + + This function tracks how many characters have been written to the line and wraps the line + according to RFC2045 (a Quoted-Printable soft line break is an EQUALS-CR-LF sequence) + */ +void QVersitDocumentWriter::writeStringQp(const QString &value) +{ + int spaceRemaining = MAX_LINE_LENGTH - mCurrentLineLength - 1; + // minus 1 for the equals required at the end + int charsWritten = 0; + QString softBreak(QLatin1String("=\r\n")); + while (spaceRemaining < value.length() - charsWritten) { + // Write the first "spaceRemaining" characters + if (value[charsWritten + spaceRemaining - 2] == QLatin1Char('=')) { + spaceRemaining -= 2; + } else if (value[charsWritten + spaceRemaining - 1] == QLatin1Char('=')) { + spaceRemaining -= 1; + } + QStringRef line(&value, charsWritten, spaceRemaining); + + charsWritten += spaceRemaining; + if (mDevice->write(mEncoder->fromUnicode(line.constData(), line.length())) < 0 + || mDevice->write(mEncoder->fromUnicode(softBreak)) < 0) + mSuccessful = false; + spaceRemaining = MAX_LINE_LENGTH - 1; // minus 1 for the equals required at the end + mCurrentLineLength = 0; + } + + if (mDevice->write(mEncoder->fromUnicode(value.mid(charsWritten))) < 0) + mSuccessful = false; + mCurrentLineLength += value.length() - charsWritten; +} + +/*! Writes a CRLF to the device. By using this function, rather than writeString("\\r\\n"), you will allow the writer to know where a line starts, for folding purposes. */ diff --git a/src/versit/qversitdocumentwriter_p.h b/src/versit/qversitdocumentwriter_p.h index f3c86dd18d..9e1f119d04 100644 --- a/src/versit/qversitdocumentwriter_p.h +++ b/src/versit/qversitdocumentwriter_p.h @@ -82,6 +82,7 @@ public: void writeBytes(const QByteArray& value); void writeString(const QString& value); + void writeStringQp(const QString& value); void writeCrlf(); protected: diff --git a/tests/auto/qvcard21writer/qvcard21writer.pro b/tests/auto/qvcard21writer/qvcard21writer.pro index dc44c81ef4..67974cf696 100644 --- a/tests/auto/qvcard21writer/qvcard21writer.pro +++ b/tests/auto/qvcard21writer/qvcard21writer.pro @@ -4,7 +4,6 @@ TARGET=tst_qvcard21writer CONFIG+=testcase include(../../../common.pri) -DEFINES += QT_ASCII_CAST_WARNINGS DEPENDPATH += . INCLUDEPATH += \ diff --git a/tests/auto/qvcard21writer/tst_qvcard21writer.cpp b/tests/auto/qvcard21writer/tst_qvcard21writer.cpp index df6a5fc431..35701f8af8 100644 --- a/tests/auto/qvcard21writer/tst_qvcard21writer.cpp +++ b/tests/auto/qvcard21writer/tst_qvcard21writer.cpp @@ -86,7 +86,11 @@ void tst_QVCard21Writer::testEncodeVersitProperty() buffer.open(QIODevice::WriteOnly); mWriter->encodeVersitProperty(property); - QCOMPARE(encodedProperty, expectedResult); + if (encodedProperty != expectedResult) { + qDebug() << "Encoded: " << encodedProperty; + qDebug() << "Expected: " << expectedResult; + QVERIFY(false); + } } void tst_QVCard21Writer::testEncodeVersitProperty_data() @@ -176,13 +180,30 @@ END:VCARD\r\n\ // Characters other than ASCII: // Note: KATAKANA_NOKIA is defined as: QString::fromUtf8("\xe3\x83\x8e\xe3\x82\xad\xe3\x82\xa2") - // The expected behaviour is to convert to UTF8, then encode with quoted-printable - expectedResult = "ORG;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E3=83=8E=E3=82=AD=E3=82=A2\r\n"; + // The expected behaviour is to convert to UTF8, then encode with quoted-printable. + // Because the result overflows one line, it should be split onto two lines using a + // quoted-printable soft line break (EQUALS-CR-LF). (Note: Versit soft line breaks + // (CR-LF-SPACE) are not supported by the native Symbian vCard importers). + expectedResult = "ORG;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E3=83=8E=E3=82=AD=E3=82=A2=E3=\r\n" + "=83=8E=E3=82=AD=E3=82=A2\r\n"; + property = QVersitProperty(); + property.setName(QLatin1String("ORG")); + property.setValue(KATAKANA_NOKIA + KATAKANA_NOKIA); + QTest::newRow("non-ASCII 1") << property << expectedResult << codec; + expectedResult = "ORG;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:a=E3=83=8E=E3=82=AD=E3=82=A2=E3=\r\n" + "=83=8E=E3=82=AD=E3=82=A2\r\n"; property = QVersitProperty(); property.setName(QLatin1String("ORG")); - property.setValue(KATAKANA_NOKIA); - QTest::newRow("non-ASCII") << property << expectedResult << codec; + property.setValue("a" + KATAKANA_NOKIA + KATAKANA_NOKIA); + QTest::newRow("non-ASCII 2") << property << expectedResult << codec; + + expectedResult = "ORG;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:aa=E3=83=8E=E3=82=AD=E3=82=A2=\r\n" + "=E3=83=8E=E3=82=AD=E3=82=A2\r\n"; + property = QVersitProperty(); + property.setName(QLatin1String("ORG")); + property.setValue("aa" + KATAKANA_NOKIA + KATAKANA_NOKIA); + QTest::newRow("non-ASCII 3") << property << expectedResult << codec; // In Shift-JIS codec. QTextCodec* jisCodec = QTextCodec::codecForName("Shift-JIS"); |