summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2012-09-19 14:28:25 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-10-02 22:34:42 +0200
commit7d62f8ace542e04e3ddf92eec4fdad8d34ac9585 (patch)
tree525c7a6285cfdfd322a9ec5672b281455dfc0183 /src/corelib/io
parenta0af0fbcd4a41fb7be6abf558296682182cdffa0 (diff)
Add two compound URL invalidity cases for isValid()
These two errors can only happen if one calls setPath() explicitly. They cannot happen for parsed URLs, which is why they are only caught with isValid(). It's not possible to set the error condition in setPath() either because they depend on the presence / absence of the authority and scheme. Also update all the unit tests that set a path not starting with a slash and were just "freeloaders" on the previous behaviour. Change-Id: Ice58cd4589a850452d7573a5b19667bbab2fb43e Reviewed-by: David Faure <faure@kde.org>
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qurl.cpp65
-rw-r--r--src/corelib/io/qurl_p.h7
2 files changed, 59 insertions, 13 deletions
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 215ce32b36..9d1691010e 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -805,11 +805,6 @@ inline void QUrlPrivate::setPath(const QString &value, int from, int end)
// sectionIsPresent |= Path; // not used, save some cycles
sectionHasError &= ~Path;
path = recodeFromUser(value, decodedPathInIsolationActions, from, end);
-
- // ### FIXME?
- // check for the "path-noscheme" case
- // if the path contains a ":" before the first "/", it could be misinterpreted
- // as a scheme
}
inline void QUrlPrivate::setFragment(const QString &value, int from, int end)
@@ -1310,6 +1305,44 @@ static void removeDotsFromPath(QString *path)
path->truncate(out - path->constData());
}
+QUrlPrivate::ErrorCode QUrlPrivate::validityError() const
+{
+ if (sectionHasError)
+ return ErrorCode(errorCode);
+
+ // There are two more cases of invalid URLs that QUrl recognizes and they
+ // are only possible with constructed URLs (setXXX methods), not with
+ // parsing. Therefore, they are tested here.
+ //
+ // The two cases are a non-empty path that doesn't start with a slash and:
+ // - with an authority
+ // - without an authority, without scheme but the path with a colon before
+ // the first slash
+ // Those cases are considered invalid because toString() would produce a URL
+ // that wouldn't be parsed back to the same QUrl.
+
+ if (path.isEmpty() || path.at(0) == QLatin1Char('/'))
+ return NoError;
+ if (sectionIsPresent & QUrlPrivate::Host)
+ return AuthorityPresentAndPathIsRelative;
+ if (sectionIsPresent & QUrlPrivate::Scheme)
+ return NoError;
+
+ // check for a path of "text:text/"
+ for (int i = 0; i < path.length(); ++i) {
+ register ushort c = path.at(i).unicode();
+ if (c == '/') {
+ // found the slash before the colon
+ return NoError;
+ }
+ if (c == ':') {
+ // found the colon before the slash, it's invalid
+ return RelativeUrlPathContainsColonBeforeSlash;
+ }
+ }
+ return NoError;
+}
+
#if 0
void QUrlPrivate::validate() const
{
@@ -1519,8 +1552,11 @@ QUrl::~QUrl()
*/
bool QUrl::isValid() const
{
- if (isEmpty()) return false;
- return d->sectionHasError == 0;
+ if (isEmpty()) {
+ // also catches d == 0
+ return false;
+ }
+ return d->validityError() == QUrlPrivate::NoError;
}
/*!
@@ -3379,15 +3415,17 @@ QString QUrl::errorString() const
if (!d)
return QString();
- if (d->sectionHasError == 0)
+ QUrlPrivate::ErrorCode errorCode = d->validityError();
+ if (errorCode == QUrlPrivate::NoError)
return QString();
// check if the error code matches a section with error
- if ((d->sectionHasError & (d->errorCode >> 8)) == 0)
+ // unless it's a compound error (0x10000)
+ if ((d->sectionHasError & (errorCode >> 8)) == 0 && (errorCode & 0x10000) == 0)
return QString();
QChar c = d->errorSupplement;
- switch (QUrlPrivate::ErrorCode(d->errorCode)) {
+ switch (errorCode) {
case QUrlPrivate::NoError:
return QString();
@@ -3428,8 +3466,6 @@ QString QUrl::errorString() const
case QUrlPrivate::InvalidPathError:
return QString(QStringLiteral("Invalid path (character '%1' not permitted)"))
.arg(c);
- case QUrlPrivate::PathContainsColonBeforeSlash:
- return QStringLiteral("Path component contains ':' before any '/'");
case QUrlPrivate::InvalidQueryError:
return QString(QStringLiteral("Invalid query (character '%1' not permitted)"))
@@ -3438,6 +3474,11 @@ QString QUrl::errorString() const
case QUrlPrivate::InvalidFragmentError:
return QString(QStringLiteral("Invalid fragment (character '%1' not permitted)"))
.arg(c);
+
+ case QUrlPrivate::AuthorityPresentAndPathIsRelative:
+ return QStringLiteral("Path component is relative and authority is present");
+ case QUrlPrivate::RelativeUrlPathContainsColonBeforeSlash:
+ return QStringLiteral("Relative URL's path component contains ':' before any '/'");
}
return QStringLiteral("<unknown error>");
}
diff --git a/src/corelib/io/qurl_p.h b/src/corelib/io/qurl_p.h
index c696709c9c..8c1e307521 100644
--- a/src/corelib/io/qurl_p.h
+++ b/src/corelib/io/qurl_p.h
@@ -95,12 +95,16 @@ public:
PortEmptyError,
InvalidPathError = Path << 8,
- PathContainsColonBeforeSlash,
InvalidQueryError = Query << 8,
InvalidFragmentError = Fragment << 8,
+ // the following two cases are only possible in combination
+ // with presence/absence of the authority and scheme. See validityError().
+ AuthorityPresentAndPathIsRelative = Authority << 8 | Path << 8 | 0x10000,
+ RelativeUrlPathContainsColonBeforeSlash = Scheme << 8 | Authority << 8 | Path << 8 | 0x10000,
+
NoError = 0
};
@@ -110,6 +114,7 @@ public:
void parse(const QString &url, QUrl::ParsingMode parsingMode);
bool isEmpty() const
{ return sectionIsPresent == 0 && port == -1 && path.isEmpty(); }
+ ErrorCode validityError() const;
// no QString scheme() const;
void appendAuthority(QString &appendTo, QUrl::FormattingOptions options, Section appendingTo) const;