Commit 6903f13b authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

CPaster: Revive pastebin.com

-Pass simplified type based on mimetype to paste for highlighting.
-Remove QHttp from CodePaster and pastebin.com in favour of QNetwork.
-Implement new pastebin.com protocol
-Implement listing via parsing the HTML-page for pastebin.com
parent 7a1546d4
......@@ -38,17 +38,23 @@
#include <coreplugin/messagemanager.h>
#include <coreplugin/messageoutputwindow.h>
#include <utils/qtcassert.h>
#include <QtGui/QListWidget>
#include <QtNetwork/QNetworkReply>
#include <QtCore/QDebug>
enum { debug = 0 };
using namespace CodePaster;
using namespace Core;
namespace CodePaster {
CodePasterProtocol::CodePasterProtocol()
CodePasterProtocol::CodePasterProtocol() :
m_page(new CodePaster::CodePasterSettingsPage),
m_pasteReply(0),
m_fetchReply(0),
m_listReply(0),
m_fetchId(-1)
{
m_page = new CodePaster::CodePasterSettingsPage();
connect(&http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
this, SLOT(readPostResponseHeader(const QHttpResponseHeader&)));
}
CodePasterProtocol::~CodePasterProtocol()
......@@ -68,14 +74,14 @@ unsigned CodePasterProtocol::capabilities() const
bool CodePasterProtocol::isValidHostName(const QString& hostName)
{
if (hostName.isEmpty()) {
ICore::instance()->messageManager()->printToOutputPane(
Core::ICore::instance()->messageManager()->printToOutputPane(
#ifdef Q_OS_MAC
tr("No Server defined in the CodePaster preferences."),
#else
tr("No Server defined in the CodePaster options."),
#endif
true /*error*/);
ICore::instance()->messageManager()->showOutputPane();
Core::ICore::instance()->messageManager()->showOutputPane();
return false;
}
return true;
......@@ -83,6 +89,8 @@ bool CodePasterProtocol::isValidHostName(const QString& hostName)
void CodePasterProtocol::fetch(const QString &id)
{
QTC_ASSERT(!m_fetchReply, return; )
QString hostName = m_page->hostName();
if (!isValidHostName(hostName))
return;
......@@ -93,13 +101,15 @@ void CodePasterProtocol::fetch(const QString &id)
QUrl url(link);
QNetworkRequest r(url);
reply = manager.get(r);
connect(reply, SIGNAL(finished()), this, SLOT(fetchFinished()));
fetchId = id;
m_fetchReply = m_manager.get(r);
connect(m_fetchReply, SIGNAL(finished()), this, SLOT(fetchFinished()));
m_fetchId = id;
}
void CodePasterProtocol::list()
{
QTC_ASSERT(!m_listReply, return; )
QString hostName = m_page->hostName();
if (!isValidHostName(hostName))
return;
......@@ -108,16 +118,18 @@ void CodePasterProtocol::list()
link += QLatin1String("/?command=browse&format=raw");
QUrl url(link);
QNetworkRequest r(url);
listReply = manager.get(r);
connect(listReply, SIGNAL(finished()), this, SLOT(listFinished()));
m_listReply = m_manager.get(r);
connect(m_listReply, SIGNAL(finished()), this, SLOT(listFinished()));
}
void CodePasterProtocol::paste(const QString &text,
ContentType /* ct */,
const QString &username,
const QString &comment,
const QString &description)
{
QString hostName = m_page->hostName();
QTC_ASSERT(!m_pasteReply, return; )
const QString hostName = m_page->hostName();
if (!isValidHostName(hostName))
return;
......@@ -126,12 +138,33 @@ void CodePasterProtocol::paste(const QString &text,
data += "&comment=";
data += CGI::encodeURL(comment).toLatin1();
data += "&code=";
data += CGI::encodeURL(text).toLatin1();
data += CGI::encodeURL(fixNewLines(text)).toLatin1();
data += "&poster=";
data += CGI::encodeURL(username).toLatin1();
http.setHost(hostName);
http.post(QString(QLatin1Char('/')), data);
QUrl url(QLatin1String("http://") + hostName);
QNetworkRequest r(url);
m_pasteReply = m_manager.post(r, data);
connect(m_pasteReply, SIGNAL(finished()), this, SLOT(pasteFinished()));
}
void CodePasterProtocol::pasteFinished()
{
if (m_pasteReply->error()) {
qWarning("Error pasting: %s", qPrintable(m_pasteReply->errorString()));
} else {
// Cut out the href-attribute
QString contents = QString::fromAscii(m_pasteReply->readAll());
int hrefPos = contents.indexOf(QLatin1String("href=\""));
if (hrefPos != -1) {
hrefPos += 6;
const int endPos = contents.indexOf(QLatin1Char('"'), hrefPos);
if (endPos != -1)
emit pasteDone(contents.mid(hrefPos, endPos - hrefPos));
}
}
m_pasteReply->deleteLater();
m_pasteReply = 0;
}
bool CodePasterProtocol::hasSettings() const
......@@ -148,38 +181,35 @@ void CodePasterProtocol::fetchFinished()
{
QString title;
QString content;
bool error = reply->error();
bool error = m_fetchReply->error();
if (error) {
content = reply->errorString();
content = m_fetchReply->errorString();
} else {
content = reply->readAll();
content = m_fetchReply->readAll();
if (debug)
qDebug() << content;
if (content.contains("<B>No such paste!</B>")) {
content = tr("No such paste");
error = true;
}
title = QString::fromLatin1("Codepaster: %1").arg(fetchId);
title = QString::fromLatin1("Codepaster: %1").arg(m_fetchId);
}
reply->deleteLater();
reply = 0;
m_fetchReply->deleteLater();
m_fetchReply = 0;
emit fetchDone(title, content, error);
}
void CodePasterProtocol::listFinished()
{
if (listReply->error()) {
ICore::instance()->messageManager()->printToOutputPane(listReply->errorString(), true);
if (m_listReply->error()) {
Core::ICore::instance()->messageManager()->printToOutputPane(m_listReply->errorString(), true);
} else {
const QByteArray data = listReply->readAll();
const QByteArray data = m_listReply->readAll();
const QStringList lines = QString::fromAscii(data).split(QLatin1Char('\n'));
emit listDone(name(), lines);
}
listReply->deleteLater();
listReply = 0;
m_listReply->deleteLater();
m_listReply = 0;
}
void CodePasterProtocol::readPostResponseHeader(const QHttpResponseHeader &header)
{
QString link = header.value("location");
if (!link.isEmpty())
emit pasteDone(link);
}
} // namespace CodePaster
......@@ -32,7 +32,6 @@
#include "protocol.h"
#include <QtNetwork/QHttp>
#include <QtNetwork/QNetworkAccessManager>
QT_BEGIN_NAMESPACE
......@@ -59,22 +58,23 @@ public:
void fetch(const QString &id);
void list();
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 listFinished();
void readPostResponseHeader(const QHttpResponseHeader &);
void pasteFinished();
private:
bool isValidHostName(const QString& hostName);
CodePasterSettingsPage *m_page;
QHttp http;
QNetworkAccessManager manager;
QNetworkReply *reply;
QNetworkReply *listReply;
QString fetchId;
QNetworkAccessManager m_manager;
QNetworkReply *m_pasteReply;
QNetworkReply *m_fetchReply;
QNetworkReply *m_listReply;
QString m_fetchId;
};
} // namespace CodePaster
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "columnindicatortextedit.h"
#include <QtGui/QPainter>
#include <QtGui/QScrollBar>
namespace CodePaster {
ColumnIndicatorTextEdit::ColumnIndicatorTextEdit(QWidget *parent) :
QTextEdit(parent), m_columnIndicator(0)
{
QFont font;
font.setFamily(QString::fromUtf8("Courier New"));
setFont(font);
setReadOnly(true);
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setVerticalStretch(3);
setSizePolicy(sizePolicy);
int cmx = 0, cmy = 0, cmw = 0, cmh = 0;
getContentsMargins(&cmx, &cmy, &cmw, &cmh);
m_columnIndicator = QFontMetrics(font).width('W') * 100 + cmx + 1;
m_columnIndicatorFont.setFamily(QString::fromUtf8("Times"));
m_columnIndicatorFont.setPointSizeF(7.0);
}
void ColumnIndicatorTextEdit::paintEvent(QPaintEvent *event)
{
QTextEdit::paintEvent(event);
QPainter p(viewport());
p.setFont(m_columnIndicatorFont);
p.setPen(QPen(QColor(0xa0, 0xa0, 0xa0, 0xa0)));
p.drawLine(m_columnIndicator, 0, m_columnIndicator, viewport()->height());
int yOffset = verticalScrollBar()->value();
p.drawText(m_columnIndicator + 1, m_columnIndicatorFont.pointSize() - yOffset, "100");
}
} // namespace CodePaster
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef COLUMNINDICATORTEXTEDIT_H
#define COLUMNINDICATORTEXTEDIT_H
#include <QtGui/QTextEdit>
namespace CodePaster {
// Indicate text column 100 by a vertical line.
class ColumnIndicatorTextEdit : public QTextEdit
{
public:
explicit ColumnIndicatorTextEdit(QWidget *parent);
int columnIndicator() const { return m_columnIndicator; }
protected:
virtual void paintEvent(QPaintEvent *event);
private:
int m_columnIndicator;
QFont m_columnIndicatorFont;
};
} // namespace CodePaster
#endif // COLUMNINDICATORTEXTEDIT_H
......@@ -14,7 +14,8 @@ HEADERS += cpasterplugin.h \
pastebindotcomsettings.h \
pastebindotcaprotocol.h \
settings.h \
pasteselectdialog.h
pasteselectdialog.h \
columnindicatortextedit.h
SOURCES += cpasterplugin.cpp \
settingspage.cpp \
protocol.cpp \
......@@ -25,7 +26,8 @@ SOURCES += cpasterplugin.cpp \
pastebindotcomsettings.cpp \
pastebindotcaprotocol.cpp \
settings.cpp \
pasteselectdialog.cpp
pasteselectdialog.cpp \
columnindicatortextedit.cpp
FORMS += settingspage.ui \
pasteselect.ui \
pasteview.ui \
......
......@@ -48,7 +48,7 @@
#include <coreplugin/messagemanager.h>
#include <coreplugin/uniqueidmanager.h>
#include <utils/qtcassert.h>
#include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h>
#include <QtCore/QtPlugin>
#include <QtCore/QDebug>
......@@ -145,36 +145,41 @@ void CodepasterPlugin::shutdown()
}
}
static inline void fixSpecialCharacters(QString &data)
{
QChar *uc = data.data();
QChar *e = uc + data.size();
for (; uc != e; ++uc) {
switch (uc->unicode()) {
case 0xfdd0: // QTextBeginningOfFrame
case 0xfdd1: // QTextEndOfFrame
case QChar::ParagraphSeparator:
case QChar::LineSeparator:
*uc = QLatin1Char('\n');
break;
case QChar::Nbsp:
*uc = QLatin1Char(' ');
break;
default:
break;
}
}
}
void CodepasterPlugin::post()
{
IEditor* editor = EditorManager::instance()->currentEditor();
ITextEditor* textEditor = qobject_cast<ITextEditor*>(editor);
const IEditor* editor = EditorManager::instance()->currentEditor();
const BaseTextEditorEditable *textEditor = qobject_cast<const BaseTextEditorEditable *>(editor);
if (!textEditor)
return;
QString data = textEditor->selectedText();
if (!data.isEmpty()) {
QChar *uc = data.data();
QChar *e = uc + data.size();
for (; uc != e; ++uc) {
switch (uc->unicode()) {
case 0xfdd0: // QTextBeginningOfFrame
case 0xfdd1: // QTextEndOfFrame
case QChar::ParagraphSeparator:
case QChar::LineSeparator:
*uc = QLatin1Char('\n');
break;
case QChar::Nbsp:
*uc = QLatin1Char(' ');
break;
default:
;
}
}
} else
if (data.isEmpty())
data = textEditor->contents();
if (data.isEmpty())
return;
fixSpecialCharacters(data);
FileDataList lst = splitDiffToFiles(data.toLatin1());
QString username = m_settings->username;
QString description;
......@@ -192,22 +197,13 @@ void CodepasterPlugin::post()
comment = view.comment();
data = view.content();
protocolName = view.protocol();
// Copied from cpaster. Otherwise lineendings will screw up
if (!data.contains("\r\n")) {
if (data.contains('\n'))
data.replace('\n', "\r\n");
else if (data.contains('\r'))
data.replace('\r', "\r\n");
}
foreach(Protocol *protocol, m_protocols) {
if (protocol->name() == protocolName) {
protocol->paste(data, username, comment, description);
const Protocol::ContentType ct = Protocol::contentType(textEditor->editor()->mimeType());
protocol->paste(data, ct, username, comment, description);
break;
}
}
}
void CodepasterPlugin::fetch()
......
......@@ -53,14 +53,15 @@ void PasteBinDotCaProtocol::fetch(const QString &id)
}
void PasteBinDotCaProtocol::paste(const QString &text,
const QString &username,
const QString &comment,
const QString &description)
ContentType /* ct */,
const QString &username,
const QString &comment,
const QString &description)
{
Q_UNUSED(comment);
Q_UNUSED(description);
QString data = "content=";
data += CGI::encodeURL(text);
data += CGI::encodeURL(fixNewLines(text));
data += "&description=";
data += CGI::encodeURL(description);
data += "&type=1&expiry=1%20day&name=";
......
......@@ -48,6 +48,7 @@ public:
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());
......
......@@ -29,128 +29,298 @@
#include "pastebindotcomprotocol.h"
#include "pastebindotcomsettings.h"
#include "cgi.h"
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
#include <QtNetwork/QNetworkReply>
#include <QtCore/QXmlStreamReader>
#include <QtCore/QXmlStreamAttributes>
using namespace Core;
#include <QtNetwork/QNetworkReply>
enum { debug = 0 };
static const char phpScriptpC[] = "api_public.php";
static const char pastePhpScriptpC[] = "api_public.php";
static const char fetchPhpScriptpC[] = "raw.php";
namespace CodePaster {
PasteBinDotComProtocol::PasteBinDotComProtocol()
PasteBinDotComProtocol::PasteBinDotComProtocol() :
m_settings(new PasteBinDotComSettings),
m_fetchReply(0),
m_pasteReply(0),
m_listReply(0),
m_fetchId(-1),
m_postId(-1)
{
settings = new PasteBinDotComSettings();
connect(&http, SIGNAL(requestFinished(int,bool)),
this, SLOT(postRequestFinished(int,bool)));
connect(&http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
this, SLOT(readPostResponseHeader(const QHttpResponseHeader&)));
}
QString PasteBinDotComProtocol::hostName() const
unsigned PasteBinDotComProtocol::capabilities() const
{
return ListCapability;
}
QString rc = settings->hostPrefix();
if (!rc.isEmpty())
rc.append(QLatin1Char('.'));
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;
}
void PasteBinDotComProtocol::fetch(const QString &id)
static inline QByteArray format(Protocol::ContentType ct)
{
QString link;
QTextStream(&link) << "http://" << hostName() << '/' << phpScriptpC << "?dl=" << id;
if (debug)
qDebug() << "fetch: sending " << link;
QUrl url(link);
QNetworkRequest r(url);
reply = manager.get(r);
connect(reply, SIGNAL(finished()), this, SLOT(fetchFinished()));
fetchId = id;
switch (ct) {
case Protocol::Text:
break;
case Protocol::C:
return "paste_format=cpp";
break;
case Protocol::JavaScript:
return "paste_format=javascript";
break;
case Protocol::Diff:
return "paste_format=dff";
break;
case Protocol::Xml:
return "paste_format=xml";
break;
}
return QByteArray();
}
void PasteBinDotComProtocol::paste(const QString &text,
ContentType ct,
const QString &username,
const QString & /* comment */,
const QString & /* description */)
{
QString data;
QTextStream str(&data);
str << "paste_code=" << CGI::encodeURL(text) << "&paste_name="
<< CGI::encodeURL(username);
QHttpRequestHeader header(QLatin1String("POST"), QLatin1String(phpScriptpC));