qtmobility/src/versit/qversitreader_p.cpp
changeset 14 6fbed849b4f4
parent 11 06b8e2af4411
equal deleted inserted replaced
11:06b8e2af4411 14:6fbed849b4f4
   469         } else {
   469         } else {
   470             property.setValue(QVariant::fromValue(subDocument));
   470             property.setValue(QVariant::fromValue(subDocument));
   471         }
   471         }
   472     } else {
   472     } else {
   473         QTextCodec* codec;
   473         QTextCodec* codec;
   474         QVariant valueVariant(decodeCharset(value, property, lineReader.codec(), &codec));
   474         bool isBinary = unencode(value, cursor, property, lineReader);
   475         bool isBinary = unencode(valueVariant, cursor, property, codec, lineReader);
   475         if (isBinary) {
   476         property.setValue(valueVariant);
   476             property.setValue(value);
   477         if (isBinary)
       
   478             property.setValueType(QVersitProperty::BinaryType);
   477             property.setValueType(QVersitProperty::BinaryType);
   479         else
   478         }
       
   479         else {
       
   480             property.setValue(decodeCharset(value, property, lineReader.codec(), &codec));
   480             splitStructuredValue(property, false);
   481             splitStructuredValue(property, false);
       
   482         }
   481     }
   483     }
   482 }
   484 }
   483 
   485 
   484 /*!
   486 /*!
   485  * Parses the property according to vCard 3.0 syntax.
   487  * Parses the property according to vCard 3.0 syntax.
   490     property.setParameters(extractVCard30PropertyParams(cursor, lineReader.codec()));
   492     property.setParameters(extractVCard30PropertyParams(cursor, lineReader.codec()));
   491 
   493 
   492     QByteArray value = extractPropertyValue(cursor);
   494     QByteArray value = extractPropertyValue(cursor);
   493 
   495 
   494     QTextCodec* codec;
   496     QTextCodec* codec;
   495     QString valueString(decodeCharset(value, property, lineReader.codec(), &codec));
       
   496 
   497 
   497     if (property.valueType() == QVersitProperty::VersitDocumentType) {
   498     if (property.valueType() == QVersitProperty::VersitDocumentType) {
       
   499         QString valueString(decodeCharset(value, property, lineReader.codec(), &codec));
   498         removeBackSlashEscaping(valueString);
   500         removeBackSlashEscaping(valueString);
   499         // Make a line reader from the value of the property.
   501         // Make a line reader from the value of the property.
   500         QByteArray subDocumentValue(codec->fromUnicode(valueString));
   502         QByteArray subDocumentValue(codec->fromUnicode(valueString));
   501         QBuffer subDocumentData(&subDocumentValue);
   503         QBuffer subDocumentData(&subDocumentValue);
   502         subDocumentData.open(QIODevice::ReadOnly);
   504         subDocumentData.open(QIODevice::ReadOnly);
   508             property = QVersitProperty();
   510             property = QVersitProperty();
   509         } else {
   511         } else {
   510             property.setValue(QVariant::fromValue(subDocument));
   512             property.setValue(QVariant::fromValue(subDocument));
   511         }
   513         }
   512     } else {
   514     } else {
   513         QVariant valueVariant(valueString);
   515         bool isBinary = unencode(value, cursor, property, lineReader);
   514         bool isBinary = unencode(valueVariant, cursor, property, codec, lineReader);
       
   515         property.setValue(valueVariant);
       
   516         if (isBinary) {
   516         if (isBinary) {
       
   517             property.setValue(value);
   517             property.setValueType(QVersitProperty::BinaryType);
   518             property.setValueType(QVersitProperty::BinaryType);
   518         } else {
   519         } else {
       
   520             property.setValue(decodeCharset(value, property, lineReader.codec(), &codec));
   519             bool isList = splitStructuredValue(property, true);
   521             bool isList = splitStructuredValue(property, true);
   520             // Do backslash unescaping
   522             // Do backslash unescaping
   521             if (isList) {
   523             if (isList) {
   522                 QStringList list = property.value<QStringList>();
   524                 QStringList list = property.value<QStringList>();
   523                 for (int i = 0; i < list.length(); i++) {
   525                 for (int i = 0; i < list.length(); i++) {
   539 bool QVersitReaderPrivate::setVersionFromProperty(QVersitDocument& document, const QVersitProperty& property) const
   541 bool QVersitReaderPrivate::setVersionFromProperty(QVersitDocument& document, const QVersitProperty& property) const
   540 {
   542 {
   541     bool valid = true;
   543     bool valid = true;
   542     if (property.name() == QLatin1String("VERSION")) {
   544     if (property.name() == QLatin1String("VERSION")) {
   543         QString value = property.value().trimmed();
   545         QString value = property.value().trimmed();
   544         if (property.parameters().contains(QLatin1String("ENCODING"),QLatin1String("BASE64"))
   546         QStringList encodingParameters = property.parameters().values(QLatin1String("ENCODING"));
   545             || property.parameters().contains(QLatin1String("TYPE"),QLatin1String("BASE64")))
   547         QStringList typeParameters = property.parameters().values(QLatin1String("TYPE"));
       
   548         if (encodingParameters.contains(QLatin1String("BASE64"), Qt::CaseInsensitive)
       
   549             || typeParameters.contains(QLatin1String("BASE64"), Qt::CaseInsensitive))
   546             value = QLatin1String(QByteArray::fromBase64(value.toAscii()));
   550             value = QLatin1String(QByteArray::fromBase64(value.toAscii()));
   547         if (value == QLatin1String("2.1")) {
   551         if (value == QLatin1String("2.1")) {
   548             document.setType(QVersitDocument::VCard21Type);
   552             document.setType(QVersitDocument::VCard21Type);
   549         } else if (value == QLatin1String("3.0")) {
   553         } else if (value == QLatin1String("3.0")) {
   550             document.setType(QVersitDocument::VCard30Type);
   554             document.setType(QVersitDocument::VCard30Type);
   554     }
   558     }
   555     return valid;
   559     return valid;
   556 }
   560 }
   557 
   561 
   558 /*!
   562 /*!
   559  * On entry, \a value should hold a QString.  On exit, it may be either a QString or a QByteArray.
   563  * On entry, \a value should be the byte array to unencode.  It is modified to be the unencoded
   560  * Returns true if and only if the property value is turned into a QByteArray.
   564  * version.  Returns true if and only if the value was base-64 encoded.  \a cursor and
   561  */
   565  * \a lineReader are supplied in case more lines need to be read (for quoted-printable).  The
   562 bool QVersitReaderPrivate::unencode(QVariant& value, VersitCursor& cursor,
   566  * \a property is supplied so we know what kind of encoding was used.
   563                                     QVersitProperty& property, QTextCodec* codec,
   567  */
       
   568 bool QVersitReaderPrivate::unencode(QByteArray& value, VersitCursor& cursor,
       
   569                                     QVersitProperty& property,
   564                                     LineReader& lineReader) const
   570                                     LineReader& lineReader) const
   565 {
   571 {
   566     Q_ASSERT(value.type() == QVariant::String);
   572     QStringList encodingParameters = property.parameters().values(QLatin1String("ENCODING"));
   567 
   573     QStringList typeParameters = property.parameters().values(QLatin1String("TYPE"));
   568     QString valueString = value.toString();
   574     if (encodingParameters.contains(QLatin1String("QUOTED-PRINTABLE"), Qt::CaseInsensitive)) {
   569 
       
   570     if (property.parameters().contains(QLatin1String("ENCODING"), QLatin1String("QUOTED-PRINTABLE"))) {
       
   571         // At this point, we need to accumulate bytes until we hit a real line break (no = before
   575         // At this point, we need to accumulate bytes until we hit a real line break (no = before
   572         // it) value already contains everything up to the character before the newline
   576         // it) value already contains everything up to the character before the newline
   573         while (valueString.endsWith(QLatin1Char('='))) {
   577         while (value.endsWith('=')) {
   574             valueString.chop(1); // Get rid of '='
   578             value.chop(1); // Get rid of '='
   575             // We add each line (minus the escaped = and newline chars)
   579             // We add each line (minus the escaped = and newline chars)
   576             cursor = lineReader.readLine();
   580             cursor = lineReader.readLine();
   577             QString line = codec->toUnicode(
   581             QByteArray line = cursor.data.mid(cursor.position, cursor.selection-cursor.position);
   578                     cursor.data.mid(cursor.position, cursor.selection-cursor.position));
   582             value.append(line);
   579             valueString.append(line);
   583         }
   580         }
   584         decodeQuotedPrintable(value);
   581         decodeQuotedPrintable(valueString);
       
   582         // Remove the encoding parameter as the value is now decoded
   585         // Remove the encoding parameter as the value is now decoded
   583         property.removeParameters(QLatin1String("ENCODING"));
   586         property.removeParameters(QLatin1String("ENCODING"));
   584         value.setValue(valueString);
       
   585         return false;
   587         return false;
   586     } else if (property.parameters().contains(QLatin1String("ENCODING"), QLatin1String("BASE64"))
   588     } else if (encodingParameters.contains(QLatin1String("BASE64"), Qt::CaseInsensitive)
   587         || property.parameters().contains(QLatin1String("ENCODING"), QLatin1String("B"))
   589         || encodingParameters.contains(QLatin1String("B"), Qt::CaseInsensitive)
   588         || property.parameters().contains(QLatin1String("TYPE"), QLatin1String("BASE64"))
   590         || typeParameters.contains(QLatin1String("BASE64"), Qt::CaseInsensitive)
   589         || property.parameters().contains(QLatin1String("TYPE"), QLatin1String("B"))) {
   591         || typeParameters.contains(QLatin1String("B"), Qt::CaseInsensitive)) {
   590         value.setValue(QByteArray::fromBase64(valueString.toAscii()));
   592         value = QByteArray::fromBase64(value);
   591         // Remove the encoding parameter as the value is now decoded
   593         // Remove the encoding parameter as the value is now decoded
   592         property.removeParameters(QLatin1String("ENCODING"));
   594         property.removeParameters(QLatin1String("ENCODING"));
   593         // Hack: add the charset parameter back in (even if there wasn't one to start with and
       
   594         // the default codec was used).  This will help later on if someone calls valueString()
       
   595         // on the property.
       
   596         property.insertParameter(QLatin1String("CHARSET"), QLatin1String(codec->name()));
       
   597         return true;
   595         return true;
   598     }
   596     }
   599     return false;
   597     return false;
   600 }
   598 }
   601 
   599 
   625 }
   623 }
   626 
   624 
   627 /*!
   625 /*!
   628  * Decodes Quoted-Printable encoded (RFC 1521) characters in /a text.
   626  * Decodes Quoted-Printable encoded (RFC 1521) characters in /a text.
   629  */
   627  */
   630 void QVersitReaderPrivate::decodeQuotedPrintable(QString& text) const
   628 void QVersitReaderPrivate::decodeQuotedPrintable(QByteArray& text) const
   631 {
   629 {
   632     for (int i=0; i < text.length(); i++) {
   630     for (int i=0; i < text.length(); i++) {
   633         QChar current = text.at(i);
   631         char current = text.at(i);
   634         if (current == QLatin1Char('=') && i+2 < text.length()) {
   632         if (current == '=' && i+2 < text.length()) {
   635             int next = text.at(i+1).unicode();
   633             char next = text.at(i+1);
   636             int nextAfterNext = text.at(i+2).unicode();
   634             char nextAfterNext = text.at(i+2);
   637             if (((next >= 'a' && next <= 'f') ||
   635             if (((next >= 'a' && next <= 'f') ||
   638                  (next >= 'A' && next <= 'F') ||
   636                  (next >= 'A' && next <= 'F') ||
   639                  (next >= '0' && next <= '9')) &&
   637                  (next >= '0' && next <= '9')) &&
   640                 ((nextAfterNext >= 'a' && nextAfterNext <= 'f') ||
   638                 ((nextAfterNext >= 'a' && nextAfterNext <= 'f') ||
   641                  (nextAfterNext >= 'A' && nextAfterNext <= 'F') ||
   639                  (nextAfterNext >= 'A' && nextAfterNext <= 'F') ||
   642                  (nextAfterNext >= '0' && nextAfterNext <= '9'))) {
   640                  (nextAfterNext >= '0' && nextAfterNext <= '9'))) {
   643                 bool ok;
   641                 bool ok;
   644                 QChar decodedChar(text.mid(i+1, 2).toInt(&ok,16));
   642                 char decodedChar(text.mid(i+1, 2).toInt(&ok,16));
   645                 if (ok)
   643                 if (ok) {
   646                     text.replace(i, 3, decodedChar);
   644                     text[i] = decodedChar;
       
   645                     text.remove(i+1, 2);
       
   646                 }
   647             } else if (next == '\r' && nextAfterNext == '\n') {
   647             } else if (next == '\r' && nextAfterNext == '\n') {
   648                 // Newlines can still be found here if they are encoded in a non-default charset.
   648                 // Newlines can still be found here if they are encoded in a non-default charset.
   649                 text.remove(i, 3);
   649                 text.remove(i, 3);
   650             }
   650             }
   651         }
   651         }