diff -r 0ba2181d7c28 -r 76a2435edfd4 qtcontactsmobility/src/versit/versitutils.cpp --- a/qtcontactsmobility/src/versit/versitutils.cpp Fri Mar 19 09:27:18 2010 +0200 +++ b/qtcontactsmobility/src/versit/versitutils.cpp Fri Apr 16 14:53:18 2010 +0300 @@ -43,417 +43,102 @@ #include "qmobilityglobal.h" #include -#include - -QTM_BEGIN_NAMESPACE - -/*! - * Folds \a text by making all lines \a maxChars long. - */ -QByteArray VersitUtils::fold(QByteArray& text, int maxChars) -{ - char previous = 0; - int charsSinceLastLineBreak = 0; - for (int i=0; i +#include -/*! - * Unfolds \a text by removing all the CRLFs - *followed immediately by a linear whitespace (SPACE or TAB). - */ -QByteArray VersitUtils::unfold(QByteArray& text) -{ - char previous = 0; - char previousOfTheprevious = 0; - for (int i=0; i* VersitUtils::m_newlineList = 0; +QByteArray VersitUtils::m_encodingMap[256]; /*! - * Encodes special characters in /a text - * using Quoted-Printable encoding (RFC 1521). - * Returns true if at least one character was encoded. + * Performs backslash escaping for line breaks (CRLFs), semicolons, backslashes and commas according + * to RFC 2426. This is called on parameter names and values and property values. + * Colons ARE NOT escaped because the examples in RFC2426 suggest that they shouldn't be. */ -bool VersitUtils::quotedPrintableEncode(QByteArray& text) -{ - bool encoded = false; - for (int i=0; i= 'a' && next <= 'f') || - (next >= 'A' && next <= 'F') || - (next >= '0' && next <= '9')) && - ((nextAfterNext >= 'a' && nextAfterNext <= 'f') || - (nextAfterNext >= 'A' && nextAfterNext <= 'F') || - (nextAfterNext >= '0' && nextAfterNext <= '9'))) { - QByteArray hexEncodedChar(text.mid(i+1,2)); - bool decoded = false; - char decodedChar = hexEncodedChar.toInt(&decoded,16); - QByteArray decodedCharAsByteArray; - decodedCharAsByteArray.append(decodedChar); - if (decoded) { - text.replace(i,3,decodedCharAsByteArray); - } - } - } - } -} - -/*! - * Performs backslash escaping for line breaks (CRLFs), - * semicolons, backslashes and commas according to RFC 2426. - */ -bool VersitUtils::backSlashEscape(QByteArray& text) -{ - bool escaped = false; - bool withinQuotes = false; - char previous = 0; - for (int i=0; i < text.length(); i++) { - char current = text.at(i); - if (previous != '\\' && !withinQuotes) { - char next = 0; - if (i != text.length()-1) - next = text.at(i+1); - if (current == ';' || current == ',' || - (current == '\\' && - next != '\\' && next != ';' && next != ',' && next != 'n')) { - text.insert(i,'\\'); - i++; - escaped = true; - } else if (previous == '\r' && current == '\n') { - text.replace(i-1,2,"\\n"); - escaped = true; - } else { - // NOP - } - } - if (current == '"') - withinQuotes = !withinQuotes; - previous = current; - } - return escaped; -} - -/*! - * Removes backslash escaping for line breaks (CRLFs), - * semicolons, backslashes and commas according to RFC 2426. - */ -void VersitUtils::removeBackSlashEscaping(QByteArray& text) -{ - char previous = 0; - bool withinQuotes = false; - for (int i=0; i < text.length(); i++) { - char current = text.at(i); - if (previous == '\\' && !withinQuotes) { - if (current == ';' || current == ',' || current == '\\') { - text.remove(i-1,1); - } else if (current == 'n' || current == 'N') { - text.replace(i-1,2,"\r\n"); - } else { - // NOP - } - } - if (current == '"') - withinQuotes = !withinQuotes; - previous = current; - } + /* replaces ; with \; + , with \, + \ with \\ + */ + text.replace(QRegExp(QLatin1String("([;,\\\\])")), QLatin1String("\\\\1")); + // replaces any CRLFs with \n + text.replace(QRegExp(QLatin1String("\r\n|\r|\n")), QLatin1String("\\n")); } /*! - * Finds the position of the first non-soft line break - * in a Quoted-Printable encoded string. + * Removes backslash escaping for line breaks (CRLFs), colons, semicolons, backslashes and commas + * according to RFC 2426. This is called on parameter names and values and property values. + * Colons ARE unescaped because the text of RFC2426 suggests that they should be. */ -int VersitUtils::findHardLineBreakInQuotedPrintable(const QByteArray& encoded) +void VersitUtils::removeBackSlashEscaping(QString& text) { - int crlfIndex = encoded.indexOf("\r\n"); - if (crlfIndex <= 0) - return -1; - while (crlfIndex > 0 && encoded.at(crlfIndex-1) == '=') { - crlfIndex = encoded.indexOf("\r\n",crlfIndex+2); + if (!(text.startsWith(QLatin1Char('"')) && text.endsWith(QLatin1Char('"')))) { + /* replaces \; with ; + \, with , + \: with : + \\ with \ + */ + text.replace(QRegExp(QLatin1String("\\\\([;,:\\\\])")), QLatin1String("\\1")); + // replaces \n with a CRLF + text.replace(QLatin1String("\\n"), QLatin1String("\r\n"), Qt::CaseInsensitive); } - - return crlfIndex; } -/*! - * Extracts the groups and the name of the property. - */ -QPair VersitUtils::extractPropertyGroupsAndName( - const QByteArray& property) -{ - QPair groupsAndName; - int length = 0; - char previous = 0; - for (int i=0; i < property.length(); i++) { - char current = property.at(i); - if ((current == ';' && previous != '\\') || - current == ':') { - length = i; - break; - } - previous = current; - } - if (length > 0) { - QString trimmedGroupsAndName = - QString::fromAscii(property.left(length).trimmed()); - QStringList parts = trimmedGroupsAndName.split(QString::fromAscii(".")); - if (parts.count() > 1) { - groupsAndName.second = parts.takeLast(); - groupsAndName.first = parts; - } else { - groupsAndName.second = trimmedGroupsAndName; - } - } - - return groupsAndName; -} /*! - * Extracts the value of the property. - * Returns an empty string if the value was not found + * Encode \a ch with \a codec, without adding an byte-order mark */ -QByteArray VersitUtils::extractPropertyValue(const QByteArray& property) +QByteArray VersitUtils::encode(char ch, QTextCodec* codec) { - QByteArray value; - int index = property.indexOf(':') + 1; - if (index > 0 && property.length() > index) - value = property.mid(index); - return value; -} - -/*! - * Extracts the property parameters as a QMultiHash. - * The parameters without names are added as "TYPE" parameters. - */ -QMultiHash VersitUtils::extractVCard21PropertyParams( - const QByteArray& property) -{ - QMultiHash result; - QList paramList = extractParams(property); - while (!paramList.isEmpty()) { - QByteArray param = paramList.takeLast(); - QString name = QString::fromAscii(paramName(param)); - QString value = QString::fromAscii(paramValue(param)); - result.insert(name,value); + if (codec != m_previousCodec) { + changeCodec(codec); } - - return result; -} - -/*! - * Extracts the property parameters as a QMultiHash. - * The parameters without names are added as "TYPE" parameters. - */ -QMultiHash VersitUtils::extractVCard30PropertyParams( - const QByteArray& property) -{ - QMultiHash result; - QList paramList = extractParams(property); - while (!paramList.isEmpty()) { - QByteArray param = paramList.takeLast(); - QByteArray name = paramName(param); - removeBackSlashEscaping(name); - QByteArray values = paramValue(param); - QList valueList = extractParts(values,','); - while (!valueList.isEmpty()) { - QByteArray value(valueList.takeLast()); - removeBackSlashEscaping(value); - result.insert(QString::fromAscii(name),QString::fromAscii(value)); - } - } - - return result; + return m_encodingMap[(int)ch]; } /*! - * Extracts the parameters as delimited by semicolons. + * Encode \a ba with \a codec, without adding an byte-order mark. \a ba is interpreted as ASCII */ -QList VersitUtils::extractParams(const QByteArray& property) +QByteArray VersitUtils::encode(const QByteArray& ba, QTextCodec* codec) { - QList params; - int colonIndex = property.indexOf(':'); - if (colonIndex > 0) { - QByteArray nameAndParamsString = property.left(colonIndex); - params = extractParts(nameAndParamsString,';'); - if (!params.isEmpty()) - params.removeFirst(); // Remove property name - } - - return params; + QTextCodec::ConverterState state(QTextCodec::IgnoreHeader); + return codec->fromUnicode(QString::fromAscii(ba.data()).data(), ba.length(), &state); } /*! - * Extracts the parts separated by separator - * discarding the separators escaped with a backslash + * Returns the list of DOS, UNIX and Mac newline characters for \a codec. */ -QList VersitUtils::extractParts( - const QByteArray& text, - char separator) +QList* VersitUtils::newlineList(QTextCodec* codec) { - QList parts; - int partStartIndex = 0; - char previous = 0; - for (int i=0; i 0) - parts.append(part); - partStartIndex = i+1; - } - previous = current; + if (m_newlineList != 0 && codec == m_previousCodec) { + return m_newlineList; } - - // Add the last or only part - QByteArray part = extractPart(text,partStartIndex); - if (part.length() > 0) - parts.append(part); - return parts; + changeCodec(codec); + return m_newlineList; } /*! - * Extracts a substring limited by /a startPosition and /a length. - */ -QByteArray VersitUtils::extractPart( - const QByteArray& text, - int startPosition, - int length) -{ - QByteArray part; - if (startPosition >= 0) - part = text.mid(startPosition,length).trimmed(); - return part; -} - -/*! - * Extracts the name of the parameter. - * No name is interpreted as an implicit "TYPE". + * Update the cached tables of pregenerated encoded text with \a codec. */ -QByteArray VersitUtils::paramName(const QByteArray& parameter) -{ - if (parameter.trimmed().length() == 0) - return QByteArray(); - int equalsIndex = parameter.indexOf('='); - if (equalsIndex > 0) { - return parameter.left(equalsIndex).trimmed(); - } - - return QByteArray("TYPE"); -} - -/*! - * Extracts the value of the parameter - */ -QByteArray VersitUtils::paramValue(const QByteArray& parameter) -{ - QByteArray value(parameter); - int equalsIndex = parameter.indexOf('='); - if (equalsIndex > 0) { - if (equalsIndex == parameter.length()-1) { - value = QByteArray(); - } else { - int valueLength = parameter.length() - (equalsIndex + 1); - value = parameter.right(valueLength).trimmed(); - } +void VersitUtils::changeCodec(QTextCodec* codec) { + // Build m_encodingMap + QChar qch; + QTextCodec::ConverterState state(QTextCodec::IgnoreHeader); + for (int c = 0; c < 256; c++) { + qch = QLatin1Char(c); + m_encodingMap[c] = codec->fromUnicode(&qch, 1, &state); } - return value; -} + // Build m_newlineList + if (m_newlineList != 0) + delete m_newlineList; + m_newlineList = new QList; + m_newlineList->append(QByteArrayMatcher(encode("\r\n", codec))); + m_newlineList->append(QByteArrayMatcher(encode("\n", codec))); + m_newlineList->append(QByteArrayMatcher(encode("\r", codec))); -/*! - * Checks whether the \a chr should be Quoted-Printable encoded (RFC 1521). - */ -bool VersitUtils::shouldBeQuotedPrintableEncoded(char chr) -{ - return (chr < 32 || - chr == '!' || chr == '"' || chr == '#' || chr == '$' || - chr == '=' || chr == '@' || chr == '[' || chr == '\\' || - chr == ']' || chr == '^' || chr == '`' || - chr > 122 ); + m_previousCodec = codec; } - -QTM_END_NAMESPACE