Commit 8c201305 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

CodePaster: Make pastebin.ca protocol work.

Replace deprecated QHttp by QNetworkReply.
Implement listing functionality, fix fetch
encoding.
parent 2a0f7098
......@@ -30,7 +30,6 @@
#include "codepasterprotocol.h"
#include "codepastersettings.h"
#include "cpasterplugin.h"
#include "cgi.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
......@@ -130,13 +129,13 @@ void CodePasterProtocol::paste(const QString &text,
return;
QByteArray data = "command=processcreate&submit=submit&highlight_type=0&description=";
data += CGI::encodeURL(description).toLatin1();
data += QUrl::toPercentEncoding(description);
data += "&comment=";
data += CGI::encodeURL(comment).toLatin1();
data += QUrl::toPercentEncoding(comment);
data += "&code=";
data += CGI::encodeURL(fixNewLines(text)).toLatin1();
data += QUrl::toPercentEncoding(fixNewLines(text));
data += "&poster=";
data += CGI::encodeURL(username).toLatin1();
data += QUrl::toPercentEncoding(username);
m_pasteReply = httpPost(QLatin1String("http://") + hostName, data);
connect(m_pasteReply, SIGNAL(finished()), this, SLOT(pasteFinished()));
......
......@@ -28,24 +28,46 @@
**************************************************************************/
#include "pastebindotcaprotocol.h"
#include "cgi.h"
#include <utils/qtcassert.h>
#include <QtNetwork/QNetworkReply>
#include <QtCore/QXmlStreamReader>
#include <QtCore/QXmlStreamAttributes>
#include <QtCore/QStringList>
static const char urlC[] = "http://pastebin.ca/";
namespace CodePaster {
PasteBinDotCaProtocol::PasteBinDotCaProtocol(const NetworkAccessManagerProxyPtr &nw) :
NetworkProtocol(nw),
m_fetchReply(0),
m_postId(-1)
m_listReply(0),
m_pasteReply(0)
{
connect(&m_http, SIGNAL(requestFinished(int,bool)),
this, SLOT(postRequestFinished(int,bool)));
}
unsigned PasteBinDotCaProtocol::capabilities() const
{
return ListCapability | PostDescriptionCapability;
}
void PasteBinDotCaProtocol::fetch(const QString &id)
{
QString link = QLatin1String("http://pastebin.ca/raw/");
link.append(id);
QTC_ASSERT(!m_fetchReply, return)
const QString url = QLatin1String(urlC);
const QString rawPostFix = QLatin1String("raw/");
// Create link as ""http://pastebin.ca/raw/[id]"
// If we get a complete URL, just insert 'raw', else build URL.
QString link = id;
if (link.startsWith(url)) {
const int lastSlashPos = link.lastIndexOf(QLatin1Char('/'));
if (lastSlashPos != -1)
link.insert(lastSlashPos + 1, rawPostFix);
} else {
link.insert(0, rawPostFix);
link.insert(0, url);
}
m_fetchReply = httpGet(link);
connect(m_fetchReply, SIGNAL(finished()), this, SLOT(fetchFinished()));
m_fetchId = id;
......@@ -54,36 +76,34 @@ void PasteBinDotCaProtocol::fetch(const QString &id)
void PasteBinDotCaProtocol::paste(const QString &text,
ContentType /* ct */,
const QString &username,
const QString &comment,
const QString & /* comment */,
const QString &description)
{
Q_UNUSED(comment);
Q_UNUSED(description);
QString data = "content=";
data += CGI::encodeURL(fixNewLines(text));
QTC_ASSERT(!m_pasteReply, return)
QByteArray data = "content=";
data += QUrl::toPercentEncoding(fixNewLines(text));
data += "&description=";
data += CGI::encodeURL(description);
data += QUrl::toPercentEncoding(description);
data += "&type=1&expiry=1%20day&name=";
data += CGI::encodeURL(username);
QHttpRequestHeader header("POST", "/quiet-paste.php");
header.setValue("host", "pastebin.ca" );
header.setContentType("application/x-www-form-urlencoded");
m_http.setHost("pastebin.ca", QHttp::ConnectionModeHttp);
header.setValue("User-Agent", "CreatorPastebin");
m_postId = m_http.request(header, data.toAscii());
data += QUrl::toPercentEncoding(username);
// fire request
const QString link = QLatin1String(urlC) + QLatin1String("quiet-paste.php");
m_pasteReply = httpPost(link, data);
connect(m_pasteReply, SIGNAL(finished()), this, SLOT(pasteFinished()));
}
void PasteBinDotCaProtocol::postRequestFinished(int id, bool error)
void PasteBinDotCaProtocol::pasteFinished()
{
QString link;
if (id == m_postId) {
if (!error) {
QByteArray data = m_http.readAll();
link = QString::fromLatin1("http://pastebin.ca/") + QString(data).remove("SUCCESS:");
} else
link = m_http.errorString();
if (m_pasteReply->error()) {
qWarning("Pastebin.ca protocol error: %s", qPrintable(m_pasteReply->errorString()));
} else {
/// returns ""SUCCESS:[id]""
const QByteArray data = m_pasteReply->readAll();
const QString link = QString::fromLatin1(urlC) + QString::fromAscii(data).remove(QLatin1String("SUCCESS:"));
emit pasteDone(link);
}
m_pasteReply->deleteLater();
m_pasteReply = 0;
}
void PasteBinDotCaProtocol::fetchFinished()
......@@ -95,10 +115,87 @@ void PasteBinDotCaProtocol::fetchFinished()
content = m_fetchReply->errorString();
} else {
title = QString::fromLatin1("Pastebin.ca: %1").arg(m_fetchId);
content = m_fetchReply->readAll();
const QByteArray data = m_fetchReply->readAll();
content = QString::fromUtf8(data);
content.remove(QLatin1Char('\r'));
}
m_fetchReply->deleteLater();
m_fetchReply = 0;
emit fetchDone(title, content, error);
}
void PasteBinDotCaProtocol::list()
{
QTC_ASSERT(!m_listReply, return);
m_listReply = httpGet(QLatin1String(urlC));
connect(m_listReply, SIGNAL(finished()), this, SLOT(listFinished()));
}
/* Quick & dirty: Parse the <div>-elements with the "Recent Posts" listing
* out of the page.
\code
<div class="menutitle"><h2>Recent Posts</h2></div>
<div class="items" id="idmenurecent-collapse">
<div class='recentlink'>
<a href="/[id]" class="rjt" rel="/preview.php?id=[id]">[nameTitle]</a>
<div class='recentdetail'>[time spec]</div>
</div>
...<h2>Create a New Pastebin Post</h2>
\endcode */
static inline QStringList parseLists(QIODevice *io)
{
enum State { OutsideRecentLink, InsideRecentLink };
QStringList rc;
const QString classAttribute = QLatin1String("class");
const QString divElement = QLatin1String("div");
const QString anchorElement = QLatin1String("a");
// Start parsing at the 'recent posts' entry as the HTML above is not well-formed
// as of 8.4.2010. This will then terminate with an error.
QByteArray data = io->readAll();
const QByteArray recentPosts("<h2>Recent Posts</h2></div>");
const int recentPostsPos = data.indexOf(recentPosts);
if (recentPostsPos == -1)
return rc;
data.remove(0, recentPostsPos + recentPosts.size());
QXmlStreamReader reader(data);
State state = OutsideRecentLink;
while (!reader.atEnd()) {
switch(reader.readNext()) {
case QXmlStreamReader::StartElement:
// Inside a <div> of an entry: Anchor or description
if (state == InsideRecentLink && reader.name() == anchorElement) { // Anchor
// Strip host from link
QString link = reader.attributes().value(QLatin1String("href")).toString();
if (link.startsWith(QLatin1Char('/')))
link.remove(0, 1);
const QString nameTitle = reader.readElementText();
rc.push_back(link + QLatin1Char(' ') + nameTitle);
} else if (state == OutsideRecentLink && reader.name() == divElement) { // "<div>" state switching
if (reader.attributes().value(classAttribute) == QLatin1String("recentlink"))
state = InsideRecentLink;
} // divElement
break;
default:
break;
} // switch reader
} // while reader.atEnd()
return rc;
}
void PasteBinDotCaProtocol::listFinished()
{
const bool error = m_listReply->error();
if (error) {
qWarning("pastebin.ca list failed: %s", qPrintable(m_listReply->errorString()));
} else {
emit listDone(name(), parseLists(m_listReply));
}
m_listReply->deleteLater();
m_listReply = 0;
}
} // namespace CodePaster
......@@ -32,8 +32,6 @@
#include "protocol.h"
#include <QtNetwork/QHttp>
namespace CodePaster {
class PasteBinDotCaProtocol : public NetworkProtocol
{
......@@ -42,26 +40,27 @@ public:
explicit PasteBinDotCaProtocol(const NetworkAccessManagerProxyPtr &nw);
QString name() const { return QLatin1String("Pastebin.Ca"); }
bool hasSettings() const { return false; }
virtual unsigned capabilities() const { return 0; }
virtual bool hasSettings() const { return false; }
virtual unsigned capabilities() const;
virtual void fetch(const QString &id);
virtual void paste(const QString &text,
ContentType ct = Text,
const QString &username = QString(),
const QString &comment = QString(),
const QString &description = QString());
virtual void list();
void fetch(const QString &id);
void paste(const QString &text,
ContentType ct = Text,
const QString &username = QString(),
const QString &comment = QString(),
const QString &description = QString());
public slots:
void fetchFinished();
void postRequestFinished(int id, bool error);
void listFinished();
void pasteFinished();
private:
QNetworkReply *m_fetchReply;
QNetworkReply *m_listReply;
QNetworkReply *m_pasteReply;
QString m_fetchId;
QHttp m_http;
int m_postId;
};
} // namespace CodePaster
......
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