1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "protocol.h"
27
28 #include <utils/networkaccessmanager.h>
29
30 #include <cpptools/cpptoolsconstants.h>
31 #include <designer/designerconstants.h>
32 #include <glsleditor/glsleditorconstants.h>
33 #include <qmljstools/qmljstoolsconstants.h>
34 #include <resourceeditor/resourceeditorconstants.h>
35 #include <coreplugin/icore.h>
36 #include <coreplugin/dialogs/ioptionspage.h>
37
38 #include <QNetworkCookie>
39 #include <QNetworkCookieJar>
40 #include <QNetworkRequest>
41 #include <QNetworkReply>
42
43 #include <QUrl>
44 #include <QDebug>
45 #include <QVariant>
46
47 #include <QMessageBox>
48 #include <QApplication>
49 #include <QPushButton>
50
51 namespace CodePaster {
52
Protocol()53 Protocol::Protocol()
54 : QObject()
55 {
56 }
57
58 Protocol::~Protocol() = default;
59
hasSettings() const60 bool Protocol::hasSettings() const
61 {
62 return false;
63 }
64
checkConfiguration(QString *)65 bool Protocol::checkConfiguration(QString *)
66 {
67 return true;
68 }
69
settingsPage() const70 Core::IOptionsPage *Protocol::settingsPage() const
71 {
72 return nullptr;
73 }
74
list()75 void Protocol::list()
76 {
77 qFatal("Base Protocol list() called");
78 }
79
contentType(const QString & mt)80 Protocol::ContentType Protocol::contentType(const QString &mt)
81 {
82 if (mt == QLatin1String(CppTools::Constants::C_SOURCE_MIMETYPE)
83 || mt == QLatin1String(CppTools::Constants::C_HEADER_MIMETYPE)
84 || mt == QLatin1String(GlslEditor::Constants::GLSL_MIMETYPE)
85 || mt == QLatin1String(GlslEditor::Constants::GLSL_MIMETYPE_VERT)
86 || mt == QLatin1String(GlslEditor::Constants::GLSL_MIMETYPE_FRAG)
87 || mt == QLatin1String(GlslEditor::Constants::GLSL_MIMETYPE_VERT_ES)
88 || mt == QLatin1String(GlslEditor::Constants::GLSL_MIMETYPE_FRAG_ES))
89 return C;
90 if (mt == QLatin1String(CppTools::Constants::CPP_SOURCE_MIMETYPE)
91 || mt == QLatin1String(CppTools::Constants::CPP_HEADER_MIMETYPE)
92 || mt == QLatin1String(CppTools::Constants::OBJECTIVE_C_SOURCE_MIMETYPE)
93 || mt == QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE))
94 return Cpp;
95 if (mt == QLatin1String(QmlJSTools::Constants::QML_MIMETYPE)
96 || mt == QLatin1String(QmlJSTools::Constants::QMLUI_MIMETYPE)
97 || mt == QLatin1String(QmlJSTools::Constants::QMLPROJECT_MIMETYPE)
98 || mt == QLatin1String(QmlJSTools::Constants::QBS_MIMETYPE)
99 || mt == QLatin1String(QmlJSTools::Constants::JS_MIMETYPE)
100 || mt == QLatin1String(QmlJSTools::Constants::JSON_MIMETYPE))
101 return JavaScript;
102 if (mt == QLatin1String("text/x-patch"))
103 return Diff;
104 if (mt == QLatin1String("text/xml")
105 || mt == QLatin1String("application/xml")
106 || mt == QLatin1String(ResourceEditor::Constants::C_RESOURCE_MIMETYPE)
107 || mt == QLatin1String(Designer::Constants::FORM_MIMETYPE))
108 return Xml;
109 return Text;
110 }
111
fixNewLines(QString data)112 QString Protocol::fixNewLines(QString data)
113 {
114 // Copied from cpaster. Otherwise lineendings will screw up
115 // HTML requires "\r\n".
116 if (data.contains(QLatin1String("\r\n")))
117 return data;
118 if (data.contains(QLatin1Char('\n'))) {
119 data.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
120 return data;
121 }
122 if (data.contains(QLatin1Char('\r')))
123 data.replace(QLatin1Char('\r'), QLatin1String("\r\n"));
124 return data;
125 }
126
textFromHtml(QString data)127 QString Protocol::textFromHtml(QString data)
128 {
129 data.remove(QLatin1Char('\r'));
130 data.replace(QLatin1String("<"), QString(QLatin1Char('<')));
131 data.replace(QLatin1String(">"), QString(QLatin1Char('>')));
132 data.replace(QLatin1String("&"), QString(QLatin1Char('&')));
133 data.replace(QLatin1String("""), QString(QLatin1Char('"')));
134 return data;
135 }
136
ensureConfiguration(Protocol * p,QWidget * parent)137 bool Protocol::ensureConfiguration(Protocol *p, QWidget *parent)
138 {
139 QString errorMessage;
140 bool ok = false;
141 while (true) {
142 if (p->checkConfiguration(&errorMessage)) {
143 ok = true;
144 break;
145 }
146 // Cancel returns empty error message.
147 if (errorMessage.isEmpty() || !showConfigurationError(p, errorMessage, parent))
148 break;
149 }
150 return ok;
151 }
152
showConfigurationError(const Protocol * p,const QString & message,QWidget * parent,bool showConfig)153 bool Protocol::showConfigurationError(const Protocol *p,
154 const QString &message,
155 QWidget *parent,
156 bool showConfig)
157 {
158 if (!p->settingsPage())
159 showConfig = false;
160
161 if (!parent)
162 parent = Core::ICore::dialogParent();
163 const QString title = tr("%1 - Configuration Error").arg(p->name());
164 QMessageBox mb(QMessageBox::Warning, title, message, QMessageBox::Cancel, parent);
165 QPushButton *settingsButton = nullptr;
166 if (showConfig)
167 settingsButton = mb.addButton(Core::ICore::msgShowOptionsDialog(), QMessageBox::AcceptRole);
168 mb.exec();
169 bool rc = false;
170 if (mb.clickedButton() == settingsButton)
171 rc = Core::ICore::showOptionsDialog(p->settingsPage()->id(), parent);
172 return rc;
173 }
174
175 // --------- NetworkProtocol
176
addCookies(QNetworkRequest & request)177 static void addCookies(QNetworkRequest &request)
178 {
179 auto accessMgr = Utils::NetworkAccessManager::instance();
180 const QList<QNetworkCookie> cookies = accessMgr->cookieJar()->cookiesForUrl(request.url());
181 for (const QNetworkCookie &cookie : cookies)
182 request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookie));
183 }
184
httpGet(const QString & link,bool handleCookies)185 QNetworkReply *NetworkProtocol::httpGet(const QString &link, bool handleCookies)
186 {
187 QUrl url(link);
188 QNetworkRequest r(url);
189 if (handleCookies)
190 addCookies(r);
191 return Utils::NetworkAccessManager::instance()->get(r);
192 }
193
httpPost(const QString & link,const QByteArray & data,bool handleCookies)194 QNetworkReply *NetworkProtocol::httpPost(const QString &link, const QByteArray &data,
195 bool handleCookies)
196 {
197 QUrl url(link);
198 QNetworkRequest r(url);
199 if (handleCookies)
200 addCookies(r);
201 r.setHeader(QNetworkRequest::ContentTypeHeader,
202 QVariant(QByteArray("application/x-www-form-urlencoded")));
203 return Utils::NetworkAccessManager::instance()->post(r, data);
204 }
205
206 NetworkProtocol::~NetworkProtocol() = default;
207
httpStatus(QString url,QString * errorMessage,bool useHttps)208 bool NetworkProtocol::httpStatus(QString url, QString *errorMessage, bool useHttps)
209 {
210 // Connect to host and display a message box, using its event loop.
211 errorMessage->clear();
212 const QString httpPrefix = QLatin1String("http://");
213 const QString httpsPrefix = QLatin1String("https://");
214 if (!url.startsWith(httpPrefix) && !url.startsWith(httpsPrefix)) {
215 url.prepend(useHttps ? httpsPrefix : httpPrefix);
216 url.append(QLatin1Char('/'));
217 }
218 QScopedPointer<QNetworkReply> reply(httpGet(url));
219 QMessageBox box(QMessageBox::Information,
220 tr("Checking connection"),
221 tr("Connecting to %1...").arg(url),
222 QMessageBox::Cancel,
223 Core::ICore::dialogParent());
224 connect(reply.data(), &QNetworkReply::finished, &box, &QWidget::close);
225 QApplication::setOverrideCursor(Qt::WaitCursor);
226 box.exec();
227 QApplication::restoreOverrideCursor();
228 // User canceled, discard and be happy.
229 if (!reply->isFinished()) {
230 QNetworkReply *replyPtr = reply.take();
231 connect(replyPtr, &QNetworkReply::finished, replyPtr, &QNetworkReply::deleteLater);
232 return false;
233 }
234 // Passed
235 if (reply->error() == QNetworkReply::NoError)
236 return true;
237 // Error.
238 *errorMessage = reply->errorString();
239 return false;
240 }
241
242 } //namespace CodePaster
243