summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2012-08-16 15:31:06 +0200
committerQt by Nokia <qt-info@nokia.com>2012-08-20 21:59:32 +0200
commitce9b010ec619aa6e5f19b6ae208b76a4e398b20b (patch)
tree7eccc6c7a4a5654dae1956df4a3f262dd8c0f109 /src
parent60818231d82ca34f1d33ccb9ba7500b5470a3d0d (diff)
Fix decoding of QByteArray in the deprecated "encoded" setters in QUrl
The asymmetry is intentional: the getters can use toLatin1() because the called functions, with a QUrl::FullyEncoded parameter, return ASCII only. This gives a small performance improvement over the need to run the UTF-8 encoder. However, the data passed to setters could contain non-ASCII binary data, in addition to the percent-encoded data. We can't use fromUtf8 because it's binary and we can't use toPercentEncoded because it already encoded. Change-Id: I5ecdb49be5af51ac86fd9764eb3a6aa96385f512 Reviewed-by: David Faure <faure@kde.org>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qurl.cpp11
-rw-r--r--src/corelib/io/qurl.h16
-rw-r--r--src/corelib/io/qurl_p.h1
-rw-r--r--src/corelib/io/qurlquery.h14
-rw-r--r--src/corelib/io/qurlrecode.cpp50
5 files changed, 78 insertions, 14 deletions
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 3b49b82637..cc326566c8 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -2979,6 +2979,17 @@ QByteArray QUrl::toPercentEncoding(const QString &input, const QByteArray &exclu
}
/*!
+ \internal
+ \since 5.0
+ Used in the setEncodedXXX compatibility functions. Converts \a ba to
+ QString form.
+*/
+QString QUrl::fromEncodedComponent_helper(const QByteArray &ba)
+{
+ return qt_urlRecodeByteArray(ba);
+}
+
+/*!
\fn QByteArray QUrl::toPunycode(const QString &uc)
\obsolete
Returns a \a uc in Punycode encoding.
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index 8055129e4b..2a651b92f6 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -274,37 +274,37 @@ public:
QT_DEPRECATED inline void removeAllEncodedQueryItems(const QByteArray &key);
QT_DEPRECATED void setEncodedUrl(const QByteArray &u, ParsingMode mode = TolerantMode)
- { setUrl(QString::fromUtf8(u.constData(), u.size()), mode); }
+ { setUrl(fromEncodedComponent_helper(u), mode); }
QT_DEPRECATED QByteArray encodedUserName() const
{ return userName(FullyEncoded).toLatin1(); }
QT_DEPRECATED void setEncodedUserName(const QByteArray &value)
- { setUserName(QString::fromLatin1(value)); }
+ { setUserName(fromEncodedComponent_helper(value)); }
QT_DEPRECATED QByteArray encodedPassword() const
{ return password(FullyEncoded).toLatin1(); }
QT_DEPRECATED void setEncodedPassword(const QByteArray &value)
- { setPassword(QString::fromLatin1(value)); }
+ { setPassword(fromEncodedComponent_helper(value)); }
QT_DEPRECATED QByteArray encodedHost() const
{ return host(FullyEncoded).toLatin1(); }
QT_DEPRECATED void setEncodedHost(const QByteArray &value)
- { setHost(QString::fromLatin1(value)); }
+ { setHost(fromEncodedComponent_helper(value)); }
QT_DEPRECATED QByteArray encodedPath() const
{ return path(FullyEncoded).toLatin1(); }
QT_DEPRECATED void setEncodedPath(const QByteArray &value)
- { setPath(QString::fromLatin1(value)); }
+ { setPath(fromEncodedComponent_helper(value)); }
QT_DEPRECATED QByteArray encodedQuery() const
{ return toLatin1_helper(query(FullyEncoded)); }
QT_DEPRECATED void setEncodedQuery(const QByteArray &value)
- { setQuery(value.isNull() ? QString() : QString::fromLatin1(value)); }
+ { setQuery(fromEncodedComponent_helper(value)); }
QT_DEPRECATED QByteArray encodedFragment() const
{ return toLatin1_helper(fragment(FullyEncoded)); }
QT_DEPRECATED void setEncodedFragment(const QByteArray &value)
- { setFragment(value.isNull() ? QString() : QString::fromLatin1(value)); }
+ { setFragment(fromEncodedComponent_helper(value)); }
private:
// helper function for the encodedQuery and encodedFragment functions
@@ -315,6 +315,8 @@ private:
return string.toLatin1();
}
#endif
+private:
+ static QString fromEncodedComponent_helper(const QByteArray &ba);
public:
static QString fromAce(const QByteArray &);
diff --git a/src/corelib/io/qurl_p.h b/src/corelib/io/qurl_p.h
index e55ba4a52a..7c4beccb02 100644
--- a/src/corelib/io/qurl_p.h
+++ b/src/corelib/io/qurl_p.h
@@ -182,6 +182,7 @@ extern Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from);
extern Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len);
extern Q_AUTOTEST_EXPORT void qt_punycodeEncoder(const QChar *s, int ucLength, QString *output);
extern Q_AUTOTEST_EXPORT QString qt_punycodeDecoder(const QString &pc);
+extern Q_AUTOTEST_EXPORT QString qt_urlRecodeByteArray(const QByteArray &ba);
QT_END_NAMESPACE
diff --git a/src/corelib/io/qurlquery.h b/src/corelib/io/qurlquery.h
index 5eac44f327..c4bb359f3b 100644
--- a/src/corelib/io/qurlquery.h
+++ b/src/corelib/io/qurlquery.h
@@ -132,22 +132,22 @@ inline void QUrl::removeAllQueryItems(const QString &key)
{ QUrlQuery q(*this); q.removeAllQueryItems(key); }
inline void QUrl::addEncodedQueryItem(const QByteArray &key, const QByteArray &value)
-{ QUrlQuery q(*this); q.addQueryItem(QString::fromUtf8(key), QString::fromUtf8(value)); setQuery(q); }
+{ QUrlQuery q(*this); q.addQueryItem(fromEncodedComponent_helper(key), fromEncodedComponent_helper(value)); setQuery(q); }
inline bool QUrl::hasEncodedQueryItem(const QByteArray &key) const
-{ return QUrlQuery(*this).hasQueryItem(QString::fromUtf8(key)); }
+{ return QUrlQuery(*this).hasQueryItem(fromEncodedComponent_helper(key)); }
inline QByteArray QUrl::encodedQueryItemValue(const QByteArray &key) const
-{ return QUrlQuery(*this).queryItemValue(QString::fromUtf8(key), QUrl::FullyEncoded).toLatin1(); }
+{ return QUrlQuery(*this).queryItemValue(fromEncodedComponent_helper(key), QUrl::FullyEncoded).toLatin1(); }
inline void QUrl::removeEncodedQueryItem(const QByteArray &key)
-{ QUrlQuery q(*this); q.removeQueryItem(QString::fromUtf8(key)); setQuery(q); }
+{ QUrlQuery q(*this); q.removeQueryItem(fromEncodedComponent_helper(key)); setQuery(q); }
inline void QUrl::removeAllEncodedQueryItems(const QByteArray &key)
-{ QUrlQuery q(*this); q.removeAllQueryItems(QString::fromUtf8(key)); }
+{ QUrlQuery q(*this); q.removeAllQueryItems(fromEncodedComponent_helper(key)); }
inline void QUrl::setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &qry)
{
QUrlQuery q;
QList<QPair<QByteArray, QByteArray> >::ConstIterator it = qry.constBegin();
for ( ; it != qry.constEnd(); ++it)
- q.addQueryItem(QString::fromUtf8(it->first), QString::fromUtf8(it->second));
+ q.addQueryItem(fromEncodedComponent_helper(it->first), fromEncodedComponent_helper(it->second));
setQuery(q);
}
inline QList<QPair<QByteArray, QByteArray> > QUrl::encodedQueryItems() const
@@ -162,7 +162,7 @@ inline QList<QPair<QByteArray, QByteArray> > QUrl::encodedQueryItems() const
}
inline QList<QByteArray> QUrl::allEncodedQueryItemValues(const QByteArray &key) const
{
- QStringList items = QUrlQuery(*this).allQueryItemValues(QString::fromUtf8(key), QUrl::FullyEncoded);
+ QStringList items = QUrlQuery(*this).allQueryItemValues(fromEncodedComponent_helper(key), QUrl::FullyEncoded);
QList<QByteArray> result;
result.reserve(items.size());
Q_FOREACH (const QString &item, items)
diff --git a/src/corelib/io/qurlrecode.cpp b/src/corelib/io/qurlrecode.cpp
index 12d23e9450..4399f38286 100644
--- a/src/corelib/io/qurlrecode.cpp
+++ b/src/corelib/io/qurlrecode.cpp
@@ -674,4 +674,54 @@ qt_urlRecode(QString &appendTo, const QChar *begin, const QChar *end,
encoding, actionTable, false);
}
+/*!
+ \internal
+ \since 5.0
+
+ \a ba contains an 8-bit form of the component and it might be
+ percent-encoded already. We can't use QString::fromUtf8 because it might
+ contain non-UTF8 sequences. We can't use QByteArray::toPercentEncoding
+ because it might already contain percent-encoded sequences. We can't use
+ qt_urlRecode because it needs UTF-16 input.
+*/
+Q_AUTOTEST_EXPORT
+QString qt_urlRecodeByteArray(const QByteArray &ba)
+{
+ if (ba.isNull())
+ return QString();
+
+ // scan ba for anything above or equal to 0x80
+ // control points below 0x20 are fine in QString
+ const char *in = ba.constData();
+ const char *const end = ba.constEnd();
+ for ( ; in < end; ++in) {
+ if (*in & 0x80)
+ break;
+ }
+
+ if (in == end) {
+ // no non-ASCII found, we're safe to convert to QString
+ return QString::fromLatin1(ba, ba.size());
+ }
+
+ // we found something that we need to encode
+ QByteArray intermediate = ba;
+ intermediate.resize(ba.size() * 3 - (in - ba.constData()));
+ uchar *out = reinterpret_cast<uchar *>(intermediate.data() + (in - ba.constData()));
+ for ( ; in < end; ++in) {
+ if (*in & 0x80) {
+ // encode
+ *out++ = '%';
+ *out++ = encodeNibble(uchar(*in) >> 4);
+ *out++ = encodeNibble(uchar(*in) & 0xf);
+ } else {
+ // keep
+ *out++ = uchar(*in);
+ }
+ }
+
+ // now it's safe to call fromLatin1
+ return QString::fromLatin1(intermediate, out - reinterpret_cast<uchar *>(intermediate.data()));
+}
+
QT_END_NAMESPACE