Commit b1683641 authored by Tobias Hunger's avatar Tobias Hunger

CPaster: Fix pastebin.com

* Update to new API
* remove unnecessary settings page (pastebin no longer offers subdomains)
* Set post expiration to one month

Change-Id: Ic9947e7227858b87e5dab15c3ce15366004a10c7
Reviewed-by: default avatarTobias Hunger <tobias.hunger@nokia.com>
parent 501346c3
......@@ -12,7 +12,6 @@ HEADERS += cpasterplugin.h \
cpasterconstants.h \
codepastersettings.h \
pastebindotcomprotocol.h \
pastebindotcomsettings.h \
pastebindotcaprotocol.h \
settings.h \
pasteselectdialog.h \
......@@ -28,7 +27,6 @@ SOURCES += cpasterplugin.cpp \
pasteview.cpp \
codepastersettings.cpp \
pastebindotcomprotocol.cpp \
pastebindotcomsettings.cpp \
pastebindotcaprotocol.cpp \
settings.cpp \
pasteselectdialog.cpp \
......
......@@ -31,13 +31,13 @@
**************************************************************************/
#include "pastebindotcomprotocol.h"
#include "pastebindotcomsettings.h"
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
#include <QDebug>
#include <QStringList>
#include <QTextStream>
#include <QXmlStreamReader>
#include <QXmlStreamAttributes>
......@@ -47,13 +47,16 @@
enum { debug = 0 };
static const char pastePhpScriptpC[] = "api_public.php";
static const char fetchPhpScriptpC[] = "raw.php";
static const char PASTEBIN_BASE[]="http://pastebin.com/";
static const char PASTEBIN_API[]="api/api_post.php";
static const char PASTEBIN_RAW[]="raw.php";
static const char PASTEBIN_ARCHIVE[]="archive";
static const char API_KEY[]="api_dev_key=516686fc461fb7f9341fd7cf2af6f829&"; // user: qtcreator_apikey
namespace CodePaster {
PasteBinDotComProtocol::PasteBinDotComProtocol(const NetworkAccessManagerProxyPtr &nw) :
NetworkProtocol(nw),
m_settings(new PasteBinDotComSettings),
m_fetchReply(0),
m_pasteReply(0),
m_listReply(0),
......@@ -73,83 +76,59 @@ unsigned PasteBinDotComProtocol::capabilities() const
return ListCapability;
}
bool PasteBinDotComProtocol::checkConfiguration(QString *errorMessage)
{
if (m_hostChecked) // Check the host once.
return true;
const bool ok = httpStatus(hostName(false), errorMessage);
if (ok)
m_hostChecked = true;
return ok;
}
QString PasteBinDotComProtocol::hostName(bool withSubDomain) const
{
QString rc;
if (withSubDomain) {
rc = m_settings->hostPrefix();
if (!rc.isEmpty())
rc.append(QLatin1Char('.'));
}
rc.append(QLatin1String("pastebin.com"));
return rc;
}
static inline QByteArray format(Protocol::ContentType ct)
{
QByteArray format = "api_paste_format=";
switch (ct) {
case Protocol::Text:
break;
case Protocol::C:
case Protocol::Cpp:
return "paste_format=cpp";
format += 'c';
break;
case Protocol::Cpp:
format += "cpp-qt";
case Protocol::JavaScript:
return "paste_format=javascript";
format += "javascript";
break;
case Protocol::Diff:
return "paste_format=diff"; // v3.X 'dff' -> 'diff'
format += "diff";
break;
case Protocol::Xml:
return "paste_format=xml";
format += "xml";
break;
case Protocol::Text:
// fallthrough!
default:
format += "text";
}
return QByteArray();
format += '&';
return format;
}
void PasteBinDotComProtocol::paste(const QString &text,
ContentType ct,
const QString &username,
const QString & /* comment */,
const QString & /* description */)
const QString &comment,
const QString &description)
{
QTC_ASSERT(!m_pasteReply, return;)
Q_UNUSED(comment);
Q_UNUSED(description);
QTC_ASSERT(!m_pasteReply, return);
// Format body
QByteArray pasteData = format(ct);
if (!pasteData.isEmpty())
pasteData.append('&');
pasteData += "paste_name=";
QByteArray pasteData = API_KEY;
pasteData += "api_option=paste&";
pasteData += "api_paste_expire_date=1M&";
pasteData += format(ct);
pasteData += "api_paste_name=";
pasteData += QUrl::toPercentEncoding(username);
const QString subDomain = m_settings->hostPrefix();
if (!subDomain.isEmpty()) {
pasteData += "&paste_subdomain=";
pasteData += QUrl::toPercentEncoding(subDomain);
}
pasteData += "&paste_code=";
pasteData += "&api_paste_code=";
pasteData += QUrl::toPercentEncoding(fixNewLines(text));
// fire request
QString link;
QTextStream(&link) << "http://" << hostName(false) << '/' << pastePhpScriptpC;
m_pasteReply = httpPost(link, pasteData);
m_pasteReply = httpPost(QLatin1String(PASTEBIN_BASE) + QLatin1String(PASTEBIN_API), pasteData);
connect(m_pasteReply, SIGNAL(finished()), this, SLOT(pasteFinished()));
if (debug)
qDebug() << "paste: sending " << m_pasteReply << link << pasteData;
qDebug() << "paste: sending " << m_pasteReply << pasteData;
}
void PasteBinDotComProtocol::pasteFinished()
......@@ -166,21 +145,14 @@ void PasteBinDotComProtocol::pasteFinished()
void PasteBinDotComProtocol::fetch(const QString &id)
{
const QString httpProtocolPrefix = QLatin1String("http://");
QTC_ASSERT(!m_fetchReply, return;)
// Did we get a complete URL or just an id. Insert a call to the php-script
QString link;
if (id.startsWith(httpProtocolPrefix)) {
// Change "http://host/id" -> "http://host/script?i=id".
const int lastSlashPos = id.lastIndexOf(QLatin1Char('/'));
link = id.mid(0, lastSlashPos);
QTextStream(&link) << '/' << fetchPhpScriptpC<< "?i=" << id.mid(lastSlashPos + 1);
} else {
// format "http://host/script?i=id".
QTextStream(&link) << "http://" << hostName(true) << '/' << fetchPhpScriptpC<< "?i=" << id;
}
QString link = QLatin1String(PASTEBIN_BASE) + QLatin1String(PASTEBIN_RAW);
link.append(QLatin1String("?i="));
if (id.startsWith(QLatin1String("http://")))
link.append(id.mid(id.lastIndexOf(QLatin1Char('/')) + 1));
else
link.append(id);
if (debug)
qDebug() << "fetch: sending " << link;
......@@ -227,10 +199,9 @@ void PasteBinDotComProtocol::fetchFinished()
void PasteBinDotComProtocol::list()
{
QTC_ASSERT(!m_listReply, return;)
QTC_ASSERT(!m_listReply, return);
// fire request
const QString url = QLatin1String("http://") + hostName(true) + QLatin1String("/archive");
const QString url = QLatin1String(PASTEBIN_BASE) + QLatin1String(PASTEBIN_ARCHIVE);
m_listReply = httpGet(url);
connect(m_listReply, SIGNAL(finished()), this, SLOT(listFinished()));
if (debug)
......@@ -245,27 +216,20 @@ static inline void padString(QString *s, int len)
}
/* Quick & dirty: Parse out the 'archive' table as of 16.3.2011:
\code
<table class="maintable" cellspacing="0">
<tr class="top">
<th scope="col" align="left">Name / Title</th>
<th scope="col" align="left">Posted</th>
<th scope="col" align="left">Expires</th>
<th scope="col" align="left">Size</th>
<th scope="col" align="left">Syntax</th>
<th scope="col" align="left">User</th>
</tr>
<tr class="g">
<td class="icon"><a href="/8ZRqkcaP">Untitled</a></td>
<td>2 sec ago</td>
<td>Never</td>
<td>9.41 KB</td>
<td><a href="/archive/text">None</a></td>
<td>a guest</td>
</tr>
<tr>
\endcode */
\code
<table class="maintable" cellspacing="0">
<tr class="top">
<th scope="col" align="left">Name / Title</th>
<th scope="col" align="left">Posted</th>
<th scope="col" align="right">Syntax</th>
</tr>
<tr>
<td><img src="/i/t.gif" class="i_p0" alt="" border="0" /><a href="/cvWciF4S">Vector 1</a></td>
<td>2 sec ago</td>
<td align="right"><a href="/archive/cpp">C++</a></td>
</tr>
...
-\endcode */
enum ParseState
{
OutSideTable, WithinTable, WithinTableRow, WithinTableHeaderElement,
......@@ -282,7 +246,7 @@ QDebug operator<<(QDebug d, const QXmlStreamAttributes &al)
static inline ParseState nextOpeningState(ParseState current, const QXmlStreamReader &reader)
{
const QStringRef element = reader.name();
const QStringRef &element = reader.name();
switch (current) {
case OutSideTable:
// Trigger on main table only.
......@@ -301,6 +265,8 @@ static inline ParseState nextOpeningState(ParseState current, const QXmlStreamRe
return WithinTableHeaderElement;
break;
case WithinTableElement:
if (element == QLatin1String("img"))
return WithinTableElement;
if (element == QLatin1String("a"))
return WithinTableElementAnchor;
break;
......@@ -328,6 +294,8 @@ static inline ParseState nextClosingState(ParseState current, const QStringRef &
case WithinTableElement:
if (element == QLatin1String("td"))
return WithinTableRow;
if (element == QLatin1String("img"))
return WithinTableElement;
break;
case WithinTableHeaderElement:
if (element == QLatin1String("th"))
......@@ -337,10 +305,10 @@ static inline ParseState nextClosingState(ParseState current, const QStringRef &
if (element == QLatin1String("a"))
return WithinTableElement;
break;
case ParseError:
case ParseError:
break;
}
return ParseError;
}
return ParseError;
}
static inline QStringList parseLists(QIODevice *io)
......@@ -355,10 +323,9 @@ static inline QStringList parseLists(QIODevice *io)
const QString hrefAttribute = QLatin1String("href");
//: Unknown user of paste.
const QString unknownUser = PasteBinDotComProtocol::tr("<Unknown>");
QString link;
QString user;
QString description;
QString title;
QString age;
while (!reader.atEnd()) {
switch(reader.readNext()) {
......@@ -393,20 +360,21 @@ static inline QStringList parseLists(QIODevice *io)
break;
case WithinTable:
// User can occasionally be empty.
if (tableRow && !link.isEmpty() && !description.isEmpty()) {
if (tableRow && !link.isEmpty() && !title.isEmpty() && !age.isEmpty()) {
QString entry = link;
entry += QLatin1Char(' ');
entry += user.isEmpty() ? unknownUser : user;
entry += QLatin1Char(' ');
entry += description;
entry += title;
entry += QLatin1String(" (");
entry += age;
entry += QLatin1Char(')');
rc.push_back(entry);
if (rc.size() >= maxEntries)
return rc;
}
tableRow++;
user.clear();
age.clear();
link.clear();
description.clear();
title.clear();
break;
case WithinTableRow:
tableColumn++;
......@@ -421,14 +389,13 @@ static inline QStringList parseLists(QIODevice *io)
break;
case QXmlStreamReader::Characters:
switch (state) {
break;
case WithinTableElement:
if (tableColumn == 5)
user = reader.text().toString();
if (tableColumn == 1)
age = reader.text().toString();
break;
case WithinTableElementAnchor:
if (tableColumn == 0)
description = reader.text().toString();
title = reader.text().toString();
break;
default:
break;
......@@ -457,8 +424,4 @@ void PasteBinDotComProtocol::listFinished()
m_listReply = 0;
}
Core::IOptionsPage *PasteBinDotComProtocol::settingsPage() const
{
return m_settings;
}
} // namespace CodePaster
......@@ -36,7 +36,6 @@
#include "protocol.h"
namespace CodePaster {
class PasteBinDotComSettings;
class PasteBinDotComProtocol : public NetworkProtocol
{
......@@ -48,8 +47,6 @@ public:
QString name() const { return protocolName(); }
virtual unsigned capabilities() const;
bool hasSettings() const { return true; }
Core::IOptionsPage *settingsPage() const;
virtual void fetch(const QString &id);
virtual void paste(const QString &text,
......@@ -64,13 +61,7 @@ public slots:
void pasteFinished();
void listFinished();
protected:
virtual bool checkConfiguration(QString *errorMessage = 0);
private:
QString hostName(bool withSubDomain) const;
PasteBinDotComSettings *m_settings;
QNetworkReply *m_fetchReply;
QNetworkReply *m_pasteReply;
QNetworkReply *m_listReply;
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "pastebindotcomsettings.h"
#include "cpasterconstants.h"
#include "ui_pastebindotcomsettings.h"
#include <coreplugin/icore.h>
#include <QSettings>
#include <QCoreApplication>
static const char groupC[] = "PasteBinDotComSettings";
static const char prefixKeyC[] = "Prefix";
namespace CodePaster {
PasteBinDotComSettings::PasteBinDotComSettings()
{
m_settings = Core::ICore::settings();
if (m_settings) {
const QString rootKey = QLatin1String(groupC) + QLatin1Char('/');
m_hostPrefix = m_settings->value(rootKey + QLatin1String(prefixKeyC), QString()).toString();
}
}
QString PasteBinDotComSettings::id() const
{
return QLatin1String("B.Pastebin.com");
}
QString PasteBinDotComSettings::displayName() const
{
return tr("Pastebin.com");
}
QString PasteBinDotComSettings::category() const
{
return QLatin1String(CodePaster::Constants::CPASTER_SETTINGS_CATEGORY);
}
QString PasteBinDotComSettings::displayCategory() const
{
return QCoreApplication::translate("CodePaster", CodePaster::Constants::CPASTER_SETTINGS_TR_CATEGORY);
}
QIcon PasteBinDotComSettings::categoryIcon() const
{
return QIcon(); // TODO: Icon for CodePaster
}
QWidget *PasteBinDotComSettings::createPage(QWidget *parent)
{
Internal::Ui::PasteBinComSettingsWidget ui;
QWidget *w = new QWidget(parent);
ui.setupUi(w);
ui.lineEdit->setText(hostPrefix());
connect(ui.lineEdit, SIGNAL(textChanged(QString)), this, SLOT(serverChanged(QString)));
return w;
}
void PasteBinDotComSettings::apply()
{
if (!m_settings)
return;
m_settings->beginGroup(QLatin1String(groupC));
m_settings->setValue(QLatin1String(prefixKeyC), m_hostPrefix);
m_settings->endGroup();
}
void PasteBinDotComSettings::serverChanged(const QString &prefix)
{
m_hostPrefix = prefix;
}
QString PasteBinDotComSettings::hostPrefix() const
{
return m_hostPrefix;
}
} //namespace CodePaster
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#ifndef PASTEBINDOTCOMSETTINGS_H
#define PASTEBINDOTCOMSETTINGS_H
#include <coreplugin/dialogs/ioptionspage.h>
#include <QStringList>
#include <QUrl>
#include <QWidget>
QT_BEGIN_NAMESPACE
class QSettings;
QT_END_NAMESPACE
namespace CodePaster {
class PasteBinDotComSettings : public Core::IOptionsPage
{
Q_OBJECT
public:
PasteBinDotComSettings();
QString id() const;
QString displayName() const;
QString category() const;
QString displayCategory() const;
QIcon categoryIcon() const;
QWidget *createPage(QWidget *parent);
void apply();
void finish() { }
QString hostPrefix() const;
public slots:
void serverChanged(const QString &host);
private:
QSettings *m_settings;
QString m_hostPrefix;
};
} // namespace CodePaster
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment