summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2019-07-23 16:15:57 +0200
committerChristian Kandeler <christian.kandeler@qt.io>2019-07-26 10:41:03 +0000
commitdf8ef72aec830d253beef32ee4d9b962afc3346e (patch)
tree24809b9298550450564688dd75bf77481f4c8971 /src
parent00bdb007ee7923f79b60c68fb891740af2f598a1 (diff)
downloadqt-creator-df8ef72aec830d253beef32ee4d9b962afc3346e.tar.gz
Wizards: Do some input validation on repository URLs
Fixes: QTCREATORBUG-18935 Change-Id: Ie2103cbe2899ea23caaedd4a6350c78b5f380ab9 Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: André Hartmann <aha_1980@gmx.de>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/coreplugin/iversioncontrol.cpp47
-rw-r--r--src/plugins/coreplugin/iversioncontrol.h13
-rw-r--r--src/plugins/git/gitclient.cpp38
-rw-r--r--src/plugins/git/gitclient.h13
-rw-r--r--src/plugins/git/gitversioncontrol.cpp5
-rw-r--r--src/plugins/git/gitversioncontrol.h2
-rw-r--r--src/plugins/vcsbase/wizard/vcsjsextension.cpp6
-rw-r--r--src/plugins/vcsbase/wizard/vcsjsextension.h1
8 files changed, 80 insertions, 45 deletions
diff --git a/src/plugins/coreplugin/iversioncontrol.cpp b/src/plugins/coreplugin/iversioncontrol.cpp
index 4a2ade10e7..b8d9582834 100644
--- a/src/plugins/coreplugin/iversioncontrol.cpp
+++ b/src/plugins/coreplugin/iversioncontrol.cpp
@@ -26,9 +26,12 @@
#include "iversioncontrol.h"
#include "vcsmanager.h"
+#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
+#include <QDir>
#include <QFileInfo>
+#include <QRegularExpression>
#include <QStringList>
/*!
@@ -90,6 +93,50 @@ ShellCommand *IVersionControl::createInitialCheckoutCommand(const QString &url,
return nullptr;
}
+IVersionControl::RepoUrl::RepoUrl(const QString &location)
+{
+ if (location.isEmpty())
+ return;
+
+ // Check for local remotes (refer to the root or relative path)
+ // On Windows, local paths typically starts with <drive>:
+ auto locationIsOnWindowsDrive = [&location] {
+ if (!Utils::HostOsInfo::isWindowsHost() || location.size() < 2)
+ return false;
+ const QChar drive = location.at(0).toLower();
+ return drive >= 'a' && drive <= 'z' && location.at(1) == ':';
+ };
+ if (location.startsWith("file://") || location.startsWith('/') || location.startsWith('.')
+ || locationIsOnWindowsDrive()) {
+ protocol = "file";
+ path = QDir::fromNativeSeparators(location.startsWith("file://")
+ ? location.mid(7) : location);
+ isValid = true;
+ return;
+ }
+
+ // TODO: Why not use QUrl?
+ static const QRegularExpression remotePattern(
+ "^(?:(?<protocol>[^:]+)://)?(?:(?<user>[^@]+)@)?(?<host>[^:/]+)"
+ "(?::(?<port>\\d+))?:?(?<path>.*)$");
+ const QRegularExpressionMatch match = remotePattern.match(location);
+ if (!match.hasMatch())
+ return;
+
+ bool ok = false;
+ protocol = match.captured("protocol");
+ userName = match.captured("user");
+ host = match.captured("host");
+ port = match.captured("port").toUShort(&ok);
+ path = match.captured("path");
+ isValid = !host.isEmpty() && (ok || match.captured("port").isEmpty());
+}
+
+IVersionControl::RepoUrl IVersionControl::getRepoUrl(const QString &location) const
+{
+ return RepoUrl(location);
+}
+
QString IVersionControl::vcsTopic(const QString &topLevel)
{
return m_topicCache ? m_topicCache->topic(topLevel) : QString();
diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h
index 338bab86d8..fb922e7d7a 100644
--- a/src/plugins/coreplugin/iversioncontrol.h
+++ b/src/plugins/coreplugin/iversioncontrol.h
@@ -217,6 +217,19 @@ public:
const QString &localName,
const QStringList &extraArgs);
+ class RepoUrl {
+ public:
+ RepoUrl(const QString &location);
+
+ QString protocol;
+ QString userName;
+ QString host;
+ QString path;
+ quint16 port = 0;
+ bool isValid = false;
+ };
+ virtual RepoUrl getRepoUrl(const QString &location) const;
+
signals:
void repositoryChanged(const QString &repository);
void filesChanged(const QStringList &files);
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 44f4d35f88..8c84c61354 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -3458,44 +3458,10 @@ void GitClient::StashInfo::end()
m_stashResult = NotStashed;
}
-// GitRemote
-
-GitRemote::GitRemote(const QString &url)
+GitRemote::GitRemote(const QString &location) : Core::IVersionControl::RepoUrl(location)
{
- static const QRegularExpression remotePattern(
- "^(?:(?<protocol>[^:]+)://)?(?:(?<user>[^@]+)@)?(?<host>[^:/]+)"
- "(?::(?<port>\\d+))?:?(?<path>.*)$");
-
- if (url.isEmpty())
- return;
-
- // Check for local remotes (refer to the root or relative path)
- // On Windows, local paths typically starts with <drive>:
- auto startsWithWindowsDrive = [](const QString &url) {
- if (!HostOsInfo::isWindowsHost() || url.size() < 2)
- return false;
- const QChar drive = url.at(0).toLower();
- return drive >= 'a' && drive <= 'z' && url.at(1) == ':';
- };
- if (url.startsWith("file://") || url.startsWith('/') || url.startsWith('.')
- || startsWithWindowsDrive(url)) {
- protocol = "file";
- path = QDir::fromNativeSeparators(url.startsWith("file://") ? url.mid(7) : url);
+ if (isValid && protocol == "file")
isValid = QDir(path).exists() || QDir(path + ".git").exists();
- return;
- }
-
- const QRegularExpressionMatch match = remotePattern.match(url);
- if (!match.hasMatch())
- return;
-
- bool ok = false;
- protocol = match.captured("protocol");
- userName = match.captured("user");
- host = match.captured("host");
- port = match.captured("port").toUShort(&ok);
- path = match.captured("path");
- isValid = ok || match.captured("port").isEmpty();
}
} // namespace Internal
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index c5e9a0df4f..32f7ac0e25 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -29,6 +29,7 @@
#include "commitdata.h"
#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/iversioncontrol.h>
#include <vcsbase/vcsbaseclient.h>
#include <utils/fileutils.h>
@@ -381,16 +382,10 @@ private:
QFutureSynchronizer<void> m_synchronizer; // for commit updates
};
-class GitRemote {
+class GitRemote : public Core::IVersionControl::RepoUrl
+{
public:
- GitRemote(const QString &url);
-
- QString protocol;
- QString userName;
- QString host;
- QString path;
- quint16 port = 0;
- bool isValid = false;
+ GitRemote(const QString &location);
};
} // namespace Internal
diff --git a/src/plugins/git/gitversioncontrol.cpp b/src/plugins/git/gitversioncontrol.cpp
index 38231527b2..8325a298b0 100644
--- a/src/plugins/git/gitversioncontrol.cpp
+++ b/src/plugins/git/gitversioncontrol.cpp
@@ -163,6 +163,11 @@ Core::ShellCommand *GitVersionControl::createInitialCheckoutCommand(const QStrin
return command;
}
+GitVersionControl::RepoUrl GitVersionControl::getRepoUrl(const QString &location) const
+{
+ return GitRemote(location);
+}
+
QStringList GitVersionControl::additionalToolsPath() const
{
QStringList res = m_client->settings().searchPathList();
diff --git a/src/plugins/git/gitversioncontrol.h b/src/plugins/git/gitversioncontrol.h
index 1e1025864d..7985040f8e 100644
--- a/src/plugins/git/gitversioncontrol.h
+++ b/src/plugins/git/gitversioncontrol.h
@@ -63,6 +63,8 @@ public:
const QString &localName,
const QStringList &extraArgs) final;
+ RepoUrl getRepoUrl(const QString &location) const override;
+
QStringList additionalToolsPath() const final;
void emitFilesChanged(const QStringList &);
diff --git a/src/plugins/vcsbase/wizard/vcsjsextension.cpp b/src/plugins/vcsbase/wizard/vcsjsextension.cpp
index bb781a32ad..35f73ae8a1 100644
--- a/src/plugins/vcsbase/wizard/vcsjsextension.cpp
+++ b/src/plugins/vcsbase/wizard/vcsjsextension.cpp
@@ -45,5 +45,11 @@ QString VcsJsExtension::displayName(const QString &vcsId) const
return vc ? vc->displayName() : QString();
}
+bool VcsJsExtension::isValidRepoUrl(const QString &vcsId, const QString &location) const
+{
+ const IVersionControl * const vc = VcsManager::versionControl(Id::fromString(vcsId));
+ return vc && vc->getRepoUrl(location).isValid;
+}
+
} // namespace Internal
} // namespace VcsBase
diff --git a/src/plugins/vcsbase/wizard/vcsjsextension.h b/src/plugins/vcsbase/wizard/vcsjsextension.h
index 4882a198d7..e1b5198cd9 100644
--- a/src/plugins/vcsbase/wizard/vcsjsextension.h
+++ b/src/plugins/vcsbase/wizard/vcsjsextension.h
@@ -37,6 +37,7 @@ class VcsJsExtension : public QObject
public:
Q_INVOKABLE bool isConfigured(const QString &vcsId) const;
Q_INVOKABLE QString displayName(const QString &vcsId) const;
+ Q_INVOKABLE bool isValidRepoUrl(const QString &vcsId, const QString &location) const;
};
} // namespace Internal