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("&lt;"), QString(QLatin1Char('<')));
131     data.replace(QLatin1String("&gt;"), QString(QLatin1Char('>')));
132     data.replace(QLatin1String("&amp;"), QString(QLatin1Char('&')));
133     data.replace(QLatin1String("&quot;"), 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