diff --git a/src/plugins/cpaster/pastebindotcomprotocol.cpp b/src/plugins/cpaster/pastebindotcomprotocol.cpp
index 5615a273ab0..111f6a4a07c 100644
--- a/src/plugins/cpaster/pastebindotcomprotocol.cpp
+++ b/src/plugins/cpaster/pastebindotcomprotocol.cpp
@@ -230,10 +230,11 @@ void PasteBinDotComProtocol::list()
QTC_ASSERT(!m_listReply, return;)
// fire request
- m_listReply = httpGet(QLatin1String("http://") + hostName(true));
+ const QString url = QLatin1String("http://") + hostName(true) + QLatin1String("/archive");
+ m_listReply = httpGet(url);
connect(m_listReply, SIGNAL(finished()), this, SLOT(listFinished()));
if (debug)
- qDebug() << "list: sending " << m_listReply;
+ qDebug() << "list: sending " << url << m_listReply;
}
static inline void padString(QString *s, int len)
@@ -243,85 +244,186 @@ static inline void padString(QString *s, int len)
s->append(QString(missing, QLatin1Char(' ')));
}
-/* Quick & dirty: Parse the
-elements with the "Recent Posts" listing
- * out of the page.
+/* Quick & dirty: Parse out the 'archive' table as of 16.3.2011:
\code
-
Recent Posts
-
-
-
Title
+
+
+ | Name / Title |
+ Posted |
+ Expires |
+ Size |
+ Syntax |
+ User |
+
+
+ | Untitled |
+ 2 sec ago |
+ Never |
+ 9.41 KB |
+ None |
+ a guest |
+
+
\endcode */
+enum ParseState
+{
+ OutSideTable, WithinTable, WithinTableRow, WithinTableHeaderElement,
+ WithinTableElement, WithinTableElementAnchor, ParseError
+};
+
+static inline ParseState nextOpeningState(ParseState current, const QStringRef &element)
+{
+ switch (current) {
+ case OutSideTable:
+ if (element == QLatin1String("table"))
+ return WithinTable;
+ return OutSideTable;
+ case WithinTable:
+ if (element == QLatin1String("tr"))
+ return WithinTableRow;
+ break;
+ case WithinTableRow:
+ if (element == QLatin1String("td"))
+ return WithinTableElement;
+ if (element == QLatin1String("th"))
+ return WithinTableHeaderElement;
+ break;
+ case WithinTableElement:
+ if (element == QLatin1String("a"))
+ return WithinTableElementAnchor;
+ break;
+ case WithinTableHeaderElement:
+ case WithinTableElementAnchor:
+ case ParseError:
+ break;
+ }
+ return ParseError;
+}
+
+static inline ParseState nextClosingState(ParseState current, const QStringRef &element)
+{
+ switch (current) {
+ case OutSideTable:
+ return OutSideTable;
+ case WithinTable:
+ if (element == QLatin1String("table"))
+ return OutSideTable;
+ break;
+ case WithinTableRow:
+ if (element == QLatin1String("tr"))
+ return WithinTable;
+ break;
+ case WithinTableElement:
+ if (element == QLatin1String("td"))
+ return WithinTableRow;
+ break;
+ case WithinTableHeaderElement:
+ if (element == QLatin1String("th"))
+ return WithinTableRow;
+ break;
+ case WithinTableElementAnchor:
+ if (element == QLatin1String("a"))
+ return WithinTableElement;
+ break;
+ case ParseError:
+ break;
+ }
+ return ParseError;
+}
+
static inline QStringList parseLists(QIODevice *io)
{
- enum State { OutsideRecentPostList, InsideRecentPostList,
- InsideRecentPostBox, InsideRecentPost };
+ enum { maxEntries = 200 }; // Limit the archive, which can grow quite large.
QStringList rc;
QXmlStreamReader reader(io);
+ ParseState state = OutSideTable;
+ int tableRow = 0;
+ int tableColumn = 0;
+
+ const QString hrefAttribute = QLatin1String("href");
+
+ QString link;
+ QString user;
+ QString description;
- const QString classAttribute = QLatin1String("class");
- const QString divElement = QLatin1String("div");
- const QString anchorElement = QLatin1String("a");
- const QString spanElement = QLatin1String("span");
- State state = OutsideRecentPostList;
while (!reader.atEnd()) {
switch(reader.readNext()) {
case QXmlStreamReader::StartElement:
- // Inside a of an entry: Anchor or description
- if (state == InsideRecentPost) {
- if (reader.name() == anchorElement) { // Anchor
- // Strip host from link
- QString link = reader.attributes().value(QLatin1String("href")).toString();
- const int slashPos = link.lastIndexOf(QLatin1Char('/'));
- if (slashPos != -1)
- link.remove(0, slashPos + 1);
- const QString user = reader.readElementText();
- rc.push_back(link + QLatin1Char(' ') + user);
- } else if (reader.name() == spanElement) { //
with description
- const QString description = reader.readElementText();
- QTC_ASSERT(!rc.isEmpty(), return rc; )
- padString(&rc.back(), 25);
- rc.back() += QLatin1Char(' ');
- rc.back() += description;
+ state = nextOpeningState(state, reader.name());
+ switch (state) {
+ case WithinTableRow:
+ tableColumn = 0;
+ break;
+ case OutSideTable:
+ case WithinTable:
+ case WithinTableHeaderElement:
+ case WithinTableElement:
+ break;
+ case WithinTableElementAnchor: // 'href="/svb5K8wS"'
+ if (tableColumn == 0) {
+ link = reader.attributes().value(hrefAttribute).toString();
+ if (link.startsWith(QLatin1Char('/')))
+ link.remove(0, 1);
}
- } else if (reader.name() == divElement) { // "" state switching
- switch (state) {
- // Check on the contents as there are several lists.
- case OutsideRecentPostList:
- if (reader.attributes().value(classAttribute) == QLatin1String("content_left_title")
- && reader.readElementText() == QLatin1String("Recent Posts"))
- state = InsideRecentPostList;
- break;
- case InsideRecentPostList:
- if (reader.attributes().value(classAttribute) == QLatin1String("content_left_box"))
- state = InsideRecentPostBox;
- break;
- case InsideRecentPostBox:
- state = InsideRecentPost;
- break;
- default:
- break;
- }
- } // divElement
+ break;
+ case ParseError:
+ return rc;
+ } // switch startelement state
break;
case QXmlStreamReader::EndElement:
- if (reader.name() == divElement) {
- switch (state) {
- case InsideRecentPost:
- state = InsideRecentPostBox;
- break;
- case InsideRecentPostBox: // Stop parsing when leaving the box.
+ state = nextClosingState(state, reader.name());
+ switch (state) {
+ case OutSideTable:
+ if (tableRow) // Seen the table, bye.
return rc;
- break;
- default:
- break;
+ break;
+ case WithinTable:
+ if (tableRow && !user.isEmpty() && !link.isEmpty() && !description.isEmpty()) {
+ QString entry = link;
+ entry += QLatin1Char(' ');
+ entry += user;
+ entry += QLatin1Char(' ');
+ entry += description;
+ rc.push_back(entry);
+ if (rc.size() >= maxEntries)
+ return rc;
}
- }
+ tableRow++;
+ user.clear();
+ link.clear();
+ description.clear();
+ break;
+ case WithinTableRow:
+ tableColumn++;
+ break;
+ case WithinTableHeaderElement:
+ case WithinTableElement:
+ case WithinTableElementAnchor:
+ break;
+ case ParseError:
+ return rc;
+ } // switch endelement state
+ break;
+ case QXmlStreamReader::Characters:
+ switch (state) {
+ break;
+ case WithinTableElement:
+ if (tableColumn == 5)
+ user = reader.text().toString();
+ break;
+ case WithinTableElementAnchor:
+ if (tableColumn == 0)
+ description = reader.text().toString();
+ break;
+ default:
+ break;
+ } // switch characters read state
break;
default:
break;
- }
+ } // switch reader state
}
return rc;
}