summaryrefslogtreecommitdiffstats
path: root/src/parsers
diff options
context:
space:
mode:
Diffstat (limited to 'src/parsers')
-rw-r--r--src/parsers/Makefile.am7
-rw-r--r--src/parsers/filesearch.cpp52
-rw-r--r--src/parsers/list.cpp69
-rw-r--r--src/parsers/parsers.cpp64
-rw-r--r--src/parsers/parsers.h91
-rw-r--r--src/parsers/policy.cpp202
-rw-r--r--src/parsers/qhtmlstream.h286
-rw-r--r--src/parsers/search.cpp76
-rw-r--r--src/parsers/show.cpp194
9 files changed, 1041 insertions, 0 deletions
diff --git a/src/parsers/Makefile.am b/src/parsers/Makefile.am
new file mode 100644
index 0000000..9893dd4
--- /dev/null
+++ b/src/parsers/Makefile.am
@@ -0,0 +1,7 @@
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+libparsers_la_LDFLAGS = -avoid-version $(all_libraries)
+noinst_LTLIBRARIES = libparsers.la
+noinst_HEADERS = parsers.h qhtmlstream.h
+libparsers_la_SOURCES = list.cpp search.cpp policy.cpp show.cpp parsers.cpp filesearch.cpp
+libparsers_la_LIBADD = $(LIB_KIO)
diff --git a/src/parsers/filesearch.cpp b/src/parsers/filesearch.cpp
new file mode 100644
index 0000000..c0a7a36
--- /dev/null
+++ b/src/parsers/filesearch.cpp
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * Copyright (C) 2003 by Sylvain Joyeux *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "parsers.h"
+#include "../apt.h"
+
+static QString
+ html_dpkgs_line_begin("<tr><td class=\"file\">%1</td><td>\n\t"),
+ html_dpkgs_line_end("\n</td></tr>\n");
+
+namespace Parsers
+{
+
+void FileSearch::operator() (AptProtocol* slave, const QString & tag, const QString & value )
+{
+ static QString buffer;
+ if (tag == "begin")
+ {
+ m_result_count = 0;
+ }
+ else if (tag == "error")
+ {
+ *slave << "<div class=\"error\">" + value + "</div>";
+ }
+ else if (tag == "file")
+ {
+ if (m_result_count)
+ *slave << buffer + html_dpkgs_line_end;
+
+ *slave << html_dpkgs_line_begin.arg(value);
+ ++m_result_count;
+ buffer = "";
+ }
+ else if (tag == "package")
+ {
+ if (!buffer.isEmpty()) buffer = buffer + ", ";
+ buffer += "<a href=\"apt:/show?" + value + "\">" + value + "</a>";
+ }
+ else if (tag == "end")
+ {
+ *slave << buffer + html_dpkgs_line_end;
+ buffer="";
+ }
+}
+
+}
diff --git a/src/parsers/list.cpp b/src/parsers/list.cpp
new file mode 100644
index 0000000..afaac7f
--- /dev/null
+++ b/src/parsers/list.cpp
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * Copyright (C) 2003 by Sylvain Joyeux *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "parsers.h"
+#include "../apt.h"
+
+#include <kio/slavebase.h>
+#include <klocale.h>
+#include <qregexp.h>
+#include <kurl.h>
+
+namespace Parsers
+{
+ List::List(bool links)
+ : m_links(links) {}
+
+ /** Parses the tokens sent by PackageManager::list */
+ void List::operator() (AptProtocol* slave, const QString& tag, const QString& value )
+ {
+ static QRegExp rx_manpage("/man/.*\\.\\d[^/]*$");
+
+ static QStringList files;
+
+ if (tag == "begin")
+ {
+ m_result_count = 0;
+ }
+ else if (tag == "error")
+ {
+ *slave << "<div class=\"error\">" + value + "</div>";
+ }
+ else if (tag == "file" && value != "/.")
+ {
+ if (m_links)
+ {
+ KURL url;
+ if (rx_manpage.search(value) >= 0)
+ url.setProtocol("man");
+ else
+ url.setProtocol("file");
+
+ url.setPath(value);
+
+ files += "<a href=\"" + url.htmlURL() + "\">" + value + "</a>";
+ }
+ else
+ {
+ files += value;
+ }
+
+ ++m_result_count;
+ }
+ else if (tag == "end")
+ {
+ files.sort();
+ *slave <<
+ "<div class=\"filelist\">\n" + files.join("\n<br>") + "\n</div>\n"
+ "<div class=\"footer\">" + i18n("%1 files in the package").arg(result_count()) + "</div>\n";
+ files.clear();
+ }
+ }
+}
diff --git a/src/parsers/parsers.cpp b/src/parsers/parsers.cpp
new file mode 100644
index 0000000..2f959ce
--- /dev/null
+++ b/src/parsers/parsers.cpp
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * Copyright (C) 2003 by Sylvain Joyeux *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "parsers.h"
+
+#include <kuserprofile.h>
+
+#include <kio/slavebase.h>
+#include <qhtmlstream.h>
+#include <qregexp.h>
+
+#include <stdlib.h>
+
+namespace Parsers
+{
+ static void print_czstring(KIO::SlaveBase& slave, const char* data, int len)
+ {
+ QByteArray nonull;
+ nonull.setRawData(data, len);
+ slave.data(nonull);
+ nonull.resetRawData(data, len);
+ }
+ void operator << (KIO::SlaveBase& slave, const QCString& string)
+ { print_czstring(slave, string.data(), string.size() - 1); }
+ void operator << (KIO::SlaveBase& slave, const QString& string)
+ { slave << string.utf8(); }
+ void operator << (KIO::SlaveBase& slave, const char* string)
+ { print_czstring(slave, string, strlen(string)); }
+
+
+
+ Parser::Parser( ) {}
+ Parser::~Parser( ) {}
+
+ void Parser::attribute_begin(QHtmlStream& stream, const QString& text)
+ {
+ stream
+ << block("tr") << endl
+ << block("td") << param("class") << "attname" << data()
+ << text
+ << close() << endl
+ << block("td");
+ }
+ void Parser::attribute_end(QHtmlStream& stream)
+ { stream << close() << endl << close(); }
+
+// void Parser::operator ( )( KIO::SlaveBase * /*slave*/,
+// const QString & /*tag*/, const QString & /*value*/ )
+// {}
+
+ QString mangle_version(QString version)
+ { return "version_" + version.replace(QRegExp("[-:\\.\\+]"), QString("_")); }
+
+}
+
+
+
diff --git a/src/parsers/parsers.h b/src/parsers/parsers.h
new file mode 100644
index 0000000..26e0113
--- /dev/null
+++ b/src/parsers/parsers.h
@@ -0,0 +1,91 @@
+/***************************************************************************
+ * Copyright (C) 2003 by Sylvain Joyeux *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef PARSERS_H
+#define PARSERS_H
+
+#include <qstring.h>
+
+namespace KIO
+{
+ class SlaveBase;
+}
+class QHtmlStream;
+class AptProtocol;
+
+/** Here are defined the functional objects that takes the tokens
+ * sent by AptCache and PackageManager objects, and produces HTML */
+namespace Parsers
+{
+ class Parser
+ {
+ protected:
+ int m_result_count;
+
+ static void attribute_begin(QHtmlStream& stream, const QString& text);
+ static void attribute_end(QHtmlStream& stream);
+
+ public:
+ Parser();
+ virtual ~Parser();
+ int result_count() const { return m_result_count; }
+ virtual void operator () (AptProtocol* slave, const QString& tag, const QString& value) = 0;
+ };
+
+ class Search : public Parser
+ {
+ public:
+ void operator () (AptProtocol* slave, const QString& tag, const QString& value);
+ };
+
+ class List : public Parser
+ {
+ bool m_links;
+ public:
+ List(bool show_links);
+ void operator () (AptProtocol* slave, const QString& tag, const QString& value);
+ };
+
+ class FileSearch : public Parser
+ {
+ public:
+ void operator () (AptProtocol* slave, const QString& tag, const QString& value);
+ };
+
+ class Show : public Parser
+ {
+ QString m_package, m_installed;
+ bool m_act;
+
+ public:
+ Show(const QString& package, const QString& installed, bool act);
+ void operator () (AptProtocol* slave, const QString& tag, const QString& value);
+ };
+
+ class Policy : public Parser
+ {
+ QString m_package, m_installed;
+ bool m_has_adept_batch;
+ bool m_act;
+
+ public:
+ Policy(const QString& package, bool act);
+ QString getInstalled() const { return m_installed; }
+ void operator () (AptProtocol* slave, const QString& tag, const QString& value);
+ };
+
+ void operator << (KIO::SlaveBase& slave, const QCString& string);
+ void operator << (KIO::SlaveBase& slave, const QString& string);
+ void operator << (KIO::SlaveBase& slave, const char* string);
+
+ QString mangle_version(QString version);
+}
+
+#endif
diff --git a/src/parsers/policy.cpp b/src/parsers/policy.cpp
new file mode 100644
index 0000000..ad31b7f
--- /dev/null
+++ b/src/parsers/policy.cpp
@@ -0,0 +1,202 @@
+/***************************************************************************
+ * Copyright (C) 2003 by Sylvain Joyeux *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "parsers.h"
+#include "../apt.h"
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <qhtmlstream.h>
+#include <qregexp.h>
+
+static void policy_begin(QHtmlStream& stream)
+{
+ stream
+ << block("div") << endl
+ << block("table", "policy") << endl
+ << block("tr") << block("td") << endl
+ << block("table", "curver") << endl
+ << block("tbody");
+}
+
+static void add_button(QHtmlStream& stream, const QString& mode, const QString& text, const QString& package)
+{
+ stream
+ << block("form")
+ << param("action") << "apt:/"
+ << param("method") << "get" << endl
+ << block("p") << endl
+ << tag("input")
+ << param("type") << "hidden"
+ << param("name") << "get"
+ << param("value") << mode << endl
+ << tag("input")
+ << param("type") << "hidden"
+ << param("name") << "package"
+ << param("value") << package << endl
+ << tag("input")
+ << param("type") << "submit"
+ << param("value") << text << endl
+ << close()
+ << close() << endl;
+}
+
+static void add_version_link(QHtmlStream& stream, AptProtocol* slave, const QString& package, const QString& version)
+{
+ KURL url(slave->buildURL("show", package));
+ url.setHTMLRef(Parsers::mangle_version(version));
+
+ stream
+ << block("a", "vtable-version")
+ << param("href") << url.htmlURL()
+ << data() << version
+ << close();
+}
+
+namespace Parsers
+{
+
+Policy::Policy(const QString& package, bool act)
+ : m_package(package), m_act(false)
+{
+ m_act = act;
+}
+
+void Policy::operator() (AptProtocol* slave, const QString& type, const QString& value)
+{
+ static bool first_version = false, received_sth = false;
+ static QString buffer;
+ static QHtmlStream* stream;
+
+ static QRegExp rx_notinstalled("(none)");
+
+ kdDebug() << "policy : " << type << " " << value << endl;
+
+ if (type == "begin")
+ {
+ stream = new QHtmlStream(&buffer);
+ policy_begin(*stream);
+ }
+ else if (type == "installed")
+ {
+ received_sth = true;
+
+ attribute_begin(*stream, i18n("Installed"));
+ if (rx_notinstalled.match(value) >= 0)
+ {
+ m_installed = QString::null;
+ *stream << i18n("no");
+ }
+ else
+ {
+ m_installed = value.stripWhiteSpace();
+ add_version_link(*stream, slave, m_package, m_installed);
+ }
+ attribute_end(*stream);
+ }
+ else if (type == "candidate")
+ {
+ received_sth = true;
+
+ bool has_candidate = (rx_notinstalled.match(value) == -1);
+
+ if (m_act && has_candidate)
+ {
+ *stream
+ << block("tr") << endl
+ << block("td") << param("colspan") << 2 << endl;
+
+ if (m_installed.isEmpty())
+ add_button(*stream, "install", i18n("Install"), m_package);
+ else
+ add_button(*stream, "remove", i18n("Remove"), m_package);
+ *stream << close() << close() << endl;
+ }
+
+ attribute_begin(*stream, i18n("Candidate"));
+ if (has_candidate)
+ add_version_link(*stream, slave, m_package, value);
+ else
+ *stream << i18n("none");
+ attribute_end(*stream);
+
+ if (m_act && has_candidate
+ && !m_installed.isEmpty() && m_installed != value)
+ {
+ *stream
+ << block("tr") << endl
+ << block("td") << param("colspan") << 2 << endl;
+ add_button(*stream, "install", i18n("Upgrade"), m_package);
+ *stream << close() << close() << endl;
+ }
+ }
+ else if (type == "version_table")
+ {
+ received_sth = true;
+
+ *stream
+ << close() << close() << endl // tbody, table, form
+ << close() << endl; // td
+
+ first_version = true;
+ }
+ else if (type == "version")
+ {
+ QString version = value.section(' ', 0, 0);
+ QString pin = value.section(' ', 1, 1);
+
+ if (first_version)
+ {
+ *stream
+ << block("td") << endl
+ << block("div", "vtable") << endl
+ << block("div", "header") << i18n("Version Table") << close() << endl
+ << block("div", "versions") << endl;
+ } /*else {
+ *stream << close() << close();
+ }*/
+
+ QString version_link;
+ version_link = "<a href=\"apt:/show?" + m_package + "#" + mangle_version(version) + "\">"
+ + version + "</a>";
+
+ *stream << tag("br") << endl;
+ add_version_link(*stream, slave, m_package, version);
+ *stream << "[Pin " << block("span", "version-pin") << pin << close() << "]";
+
+ first_version = false;
+ }
+ else if (type == "location")
+ {
+ QStringList sections = QStringList::split(' ', value);
+ QString pin = sections.first();
+ sections.pop_front();
+ // remove the "Packages" field if it is here
+ if (sections.last() == "Packages")
+ sections.pop_back();
+
+ *stream << tag("br") << endl;
+ *stream << block("span", "location-pin") << pin << close() << sections.join(" ") << endl;
+ }
+ else if (type == "end")
+ {
+ if (received_sth)
+ {
+ *stream << close_all() << endl;
+ *slave << buffer;
+ }
+
+ buffer = QString::null;
+ received_sth = false;
+ delete stream;
+ }
+}
+
+}
diff --git a/src/parsers/qhtmlstream.h b/src/parsers/qhtmlstream.h
new file mode 100644
index 0000000..330f9d5
--- /dev/null
+++ b/src/parsers/qhtmlstream.h
@@ -0,0 +1,286 @@
+/***************************************************************************
+ * Copyright (C) 2003 by Sylvain Joyeux *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef QHtmlStream_H
+#define QHtmlStream_H
+
+#include <qtextstream.h>
+#include <qstringlist.h>
+
+class QHtmlStream;
+class QHtmlStreamManip;
+
+/**
+@author Sylvain Joyeux
+*/
+
+class QHtmlStreamManip
+{
+protected:
+ virtual void apply(QHtmlStream& stream) const = 0;
+
+public:
+ virtual ~QHtmlStreamManip() {};
+ void operator () (QHtmlStream& stream) const
+ { apply(stream); }
+};
+
+class QHtmlStream
+{
+ QTextOStream m_stream;
+
+ enum States
+ {
+ NORMAL_FLOW,
+ TAG,
+ BLOCK,
+ PARAM
+ };
+ int m_state, m_enclosing_state;
+
+ bool m_newline;
+ QString m_indent;
+ QStringList m_blockstack;
+
+ void finalize_open()
+ {
+ if (m_state == PARAM)
+ m_state = m_enclosing_state;
+
+ if (m_state == BLOCK)
+ m_stream << ">";
+ else if (m_state == TAG)
+ m_stream << " />";
+
+ m_state = NORMAL_FLOW;
+ }
+
+ void indent()
+ {
+ if (m_newline)
+ {
+ m_stream << m_indent;
+ m_newline = false;
+ }
+ }
+
+ template<class T>
+ QHtmlStream& output(const T& o)
+ {
+ indent();
+
+ if (m_state == PARAM)
+ {
+ m_stream << "=\"" << o << "\"";
+ m_state = m_enclosing_state;
+ return *this;
+ }
+
+ if (m_state == BLOCK)
+ {
+ m_stream << ">";
+ m_state = NORMAL_FLOW;
+ }
+ else if (m_state == TAG)
+ {
+ m_stream << "/>";
+ m_state = NORMAL_FLOW;
+ }
+ m_stream << o;
+
+ return *this;
+ }
+
+public:
+ QHtmlStream(QString* buffer)
+ : m_stream(buffer), m_state(NORMAL_FLOW), m_newline(true) {}
+ ~QHtmlStream() {}
+
+ void tag(const QString& name, const QString& cl, const QString& id)
+ {
+ finalize_open();
+ indent();
+
+ m_stream << '<' << name;
+ m_state = TAG;
+
+ if (!cl.isEmpty())
+ m_stream << " class=\"" << cl << "\"";
+ if (!id.isEmpty())
+ m_stream << " id=\"" << id << "\"";
+ }
+
+ void block(const QString& name, const QString& cl, const QString& id)
+ {
+ finalize_open();
+ indent();
+
+ m_stream << '<' << name;
+ m_indent += '\t';
+ m_blockstack.push_front(name);
+ m_state = BLOCK;
+
+ if (!cl.isEmpty())
+ m_stream << " class=\"" << cl << "\"";
+ if (!id.isEmpty())
+ m_stream << " id=\"" << id << "\"";
+ }
+
+ void parameter(const QString& param_name)
+ {
+ if (m_state == NORMAL_FLOW) return;
+
+ m_stream << " " << param_name;
+ m_enclosing_state = m_state;
+ m_state = PARAM;
+ }
+
+ void close()
+ {
+ finalize_open();
+
+ m_indent.truncate(m_indent.length() - 1);
+ indent();
+ m_stream << "</" << m_blockstack.first() << ">";
+ m_blockstack.pop_front();
+ }
+ void close_all(bool indent)
+ {
+ while( ! m_blockstack.empty() )
+ {
+ if (indent)
+ (*this) << endl;
+ close();
+ }
+ }
+
+ void data()
+ {
+ finalize_open();
+ }
+
+ QHtmlStream & operator<< ( QChar c ) { return output(c); }
+ QHtmlStream & operator<< ( char c ) { return output(c); }
+ QHtmlStream & operator<< ( signed short i ) { return output(i); }
+ QHtmlStream & operator<< ( unsigned short i ) { return output(i); }
+ QHtmlStream & operator<< ( signed int i ) { return output(i); }
+ QHtmlStream & operator<< ( unsigned int i ) { return output(i); }
+ QHtmlStream & operator<< ( signed long i ) { return output(i); }
+ QHtmlStream & operator<< ( unsigned long i ) { return output(i); }
+ QHtmlStream & operator<< ( float f ) { return output(f); }
+ QHtmlStream & operator<< ( double f ) { return output(f); }
+ QHtmlStream & operator<< ( const char * s ) { return output(s); }
+ QHtmlStream & operator<< ( const QString & s ) { return output(s); }
+ QHtmlStream & operator<< ( const QCString & s ) { return output(s); }
+
+ QHtmlStream & operator<< ( const QHtmlStreamManip& op )
+ {
+ op(*this);
+ return *this;
+ }
+
+ QHtmlStream & operator<< (QTSManip m)
+ {
+ finalize_open();
+ m_stream << m;
+ return (*this);
+ }
+
+ QHtmlStream & operator<< (QTSFUNC f)
+ {
+ finalize_open();
+ int old_flags = m_stream.flags();
+ m_stream << f;
+ if (old_flags == m_stream.flags())
+ m_newline = true;
+ return (*this);
+ }
+};
+
+/***************************************************************************************
+* Stream manipulators
+*/
+
+class QHtmlStreamManip0 : public QHtmlStreamManip
+{
+public:
+ typedef void (QHtmlStream::*Method)();
+
+private:
+ Method m_method;
+
+ void apply (QHtmlStream& stream) const
+ { (stream.*m_method)(); }
+
+public:
+ QHtmlStreamManip0(Method m)
+ : m_method(m) {}
+};
+
+class QHtmlStreamManip1 : public QHtmlStreamManip
+{
+public:
+ typedef void (QHtmlStream::*Method)(const QString& param);
+
+private:
+ Method m_method;
+ QString m_param;
+
+ void apply(QHtmlStream& stream) const
+ { (stream.*m_method)(m_param); }
+
+public:
+ QHtmlStreamManip1(Method m, const QString& param)
+ : m_method(m), m_param(param) {}
+};
+
+class QHtmlStreamManip3 : public QHtmlStreamManip
+{
+public:
+ typedef void (QHtmlStream::*Method)(const QString& param0, const QString& param1, const QString& param2);
+
+private:
+ Method m_method;
+ QString m_param0, m_param1, m_param2;
+
+ void apply(QHtmlStream& stream) const
+ { (stream.*m_method)(m_param0, m_param1, m_param2); }
+
+public:
+ QHtmlStreamManip3(Method m, const QString& param0, const QString& param1, const QString& param2)
+ : m_method(m),
+ m_param0(param0), m_param1(param1), m_param2(param2) {}
+};
+
+class CloseAll : public QHtmlStreamManip
+{
+private:
+ bool m_indent;
+ void apply(QHtmlStream& stream) const
+ { stream.close_all(m_indent); }
+public:
+ CloseAll(bool indent) : m_indent(indent) {}
+};
+
+inline QHtmlStreamManip3 tag(const QString& name, const QString& cl = QString::null, const QString& id = QString::null)
+{ return QHtmlStreamManip3(&QHtmlStream::tag, name, cl, id); }
+inline QHtmlStreamManip3 block(const QString& name, const QString& cl = QString::null, const QString& id = QString::null)
+{ return QHtmlStreamManip3(&QHtmlStream::block, name, cl, id); }
+
+inline QHtmlStreamManip1 param(const QString& name)
+{ return QHtmlStreamManip1(&QHtmlStream::parameter, name); }
+
+inline QHtmlStreamManip0 close()
+{ return QHtmlStreamManip0(&QHtmlStream::close); }
+inline QHtmlStreamManip0 data()
+{ return QHtmlStreamManip0(&QHtmlStream::data); }
+inline CloseAll close_all(bool indent = true)
+{ return CloseAll(indent); }
+
+#endif
diff --git a/src/parsers/search.cpp b/src/parsers/search.cpp
new file mode 100644
index 0000000..0d0a952
--- /dev/null
+++ b/src/parsers/search.cpp
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * Copyright (C) 2003 by Sylvain Joyeux *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "parsers.h"
+#include "../apt.h"
+
+#include "qhtmlstream.h"
+
+#include <kio/slavebase.h>
+
+namespace Parsers
+{
+/** Parses the output of apt-cache search */
+void Search::operator() (AptProtocol* slave, const QString& tag, const QString& value)
+{
+ static QMap<QString, QString> results;
+ static QString cur_package;
+ static QString query;
+
+ if (tag == "begin")
+ {
+ query = value;
+ m_result_count = 0;
+ }
+ else if (tag == "package")
+ {
+ ++m_result_count;
+ cur_package = value;
+ }
+ else if (tag == "short_desc")
+ {
+ results[cur_package] = value;
+ }
+ else if (tag == "end")
+ {
+ // We separate results whose package name matches the query
+ // and those who matches only with the description
+ QString normal, special;
+ QHtmlStream sstream(&special), nstream(&normal);
+
+ // QMap iteration sorts wrt the key < operator
+ // with QStrings, it means case insensitive sort
+ QMap<QString, QString>::ConstIterator i;
+ for (i = results.begin(); i != results.end(); ++i)
+ {
+ const QString key = i.key();
+ QHtmlStream* stream = &nstream;
+ if (key == query)
+ stream = &sstream;
+
+ (*stream)
+ << block("tr")
+ << block("td")
+ << block("a") << param("href") << "apt:/show?" + key
+ << key
+ << close()
+ << close() << block("td") << *i << close() << endl
+ << close() << endl;
+ }
+
+ if (!special.isEmpty())
+ *slave << QString("<table>") + special + QString("</table>\n<hr>\n");
+ *slave << QString("<table>") + normal + QString("</table>");
+
+ results.clear();
+ }
+}
+}
+
diff --git a/src/parsers/show.cpp b/src/parsers/show.cpp
new file mode 100644
index 0000000..0a1c503
--- /dev/null
+++ b/src/parsers/show.cpp
@@ -0,0 +1,194 @@
+/***************************************************************************
+ * Copyright (C) 2003 by Sylvain Joyeux *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "parsers.h"
+#include "../apt.h"
+
+#include <klocale.h>
+#include <qregexp.h>
+
+static const QString
+ html_attribute_begin("<tr><td class=\"attname\">%1</td>\n\t<td>\n\t\t"),
+ html_attribute_classed("<tr class=\"%1\"><td class=\"attname\">%2</td>\n\t<td>\n\t\t"),
+ html_attribute_end("\n\t</td>\n</tr>\n");
+
+// Converts the special chars in orig into its HTML equivalents
+static QString text2html(const QString& orig)
+{ QString ret(orig);
+ ret = ret.replace("<(?!a href)", "&lt;");
+ //ret = ret.replace( QRegExp("\n"), "<br />\n");
+ return ret;
+}
+
+static void close_indent(int indent, QString& buffer)
+{
+ if (buffer.isEmpty()) return;
+ if (indent)
+ buffer += "\n\t\t</div>";
+}
+static void close_item(int indent, QString& buffer)
+{
+ if (buffer.isEmpty()) return;
+ close_indent(indent, buffer);
+ buffer += html_attribute_end;
+}
+
+static void close_table(const QString& version, int indent, QString& buffer)
+{
+ if (buffer.isEmpty()) return;
+ close_item(indent, buffer);
+ buffer = version + "<table class=\"version\">\n" + buffer + "</table>\n";
+}
+
+static QString version_header_link(const KURL& url, const QString& name)
+{ return QString("\t<a class=\"links\" href=\"" + url.htmlURL() + "\">" + name + "</a>\n"); }
+
+namespace Parsers
+{
+
+Show::Show(const QString& package, const QString& installed_version, bool act)
+ : m_package(package), m_installed(installed_version), m_act(false)
+{
+ m_act = act;
+}
+
+void Show::operator() (AptProtocol* slave, const QString& tag, const QString& value)
+{
+ // Since we want to show the version first, we should wait for it
+ // before sending anything
+ static QString version;
+ static QString buffer;
+ static QString attribute;
+ static int indent;
+ static bool multiline = false;
+ static bool first_line = false, new_paragraph = true;
+
+ if (tag == "begin" || tag == "package" || tag == "end")
+ {
+ if (multiline && !new_paragraph)
+ buffer += "</p>";
+
+ if (tag == "begin")
+ m_result_count = 0;
+ else
+ {
+ m_result_count += (tag == "package");
+
+ close_table(version, indent, buffer);
+ if (!buffer.isEmpty()) *slave << buffer;
+ }
+
+ // init the state variables for the next package
+ buffer = "";
+ indent = 0;
+ first_line = false;
+ new_paragraph = true;
+ }
+ else if (tag == "field")
+ {
+ if (multiline && !new_paragraph)
+ buffer += "</p>";
+
+ attribute = value;
+ if (value == "Depends" || value == "Description")
+ {
+ close_item(indent, buffer);
+ buffer +=
+ html_attribute_begin.arg(value)
+ + "&nbsp;";
+
+ close_item(indent, buffer);
+ buffer += html_attribute_begin.arg("&nbsp;");
+ }
+ else if (value != "Version" && value != "Package")
+ {
+ close_item(indent, buffer);
+ buffer += html_attribute_begin.arg(value);
+ }
+
+ if (value == "Description")
+ {
+ multiline = true;
+ new_paragraph = true;
+ first_line = true;
+ }
+ else
+ {
+ multiline = false;
+ }
+ }
+ else if (tag == "indent")
+ {
+ close_indent(indent, buffer);
+
+ int new_indent = value.toInt();
+ if (new_indent)
+ buffer += "\n\t<div style=\"margin-left: " + value + "em\">";
+ indent = new_indent;
+ }
+ else if (tag == "data" && attribute == "Version")
+ {
+ KURL action ("apt:/get");
+
+ QString item_id = mangle_version(value);
+ if (value == m_installed)
+ {
+ action.setQuery("remove");
+ version = QString("<div class=\"version-header-installed\" id=\"%1\">").arg(item_id)
+ + i18n("Installed version %1").arg(value);
+ }
+ else
+ {
+ action.setQuery("install");
+ version = QString("<div class=\"version-header\" id=\"%1\">").arg(item_id)
+ + i18n("Version %1").arg(value);
+ }
+
+ action.addQueryItem("package", m_package);
+ action.addQueryItem("version", value);
+
+ if (m_act)
+ {
+ if (value == m_installed)
+ version += version_header_link(action, i18n("Remove"));
+ else
+ version += version_header_link(action, i18n("Install"));
+ }
+ version += "</div>\n";
+
+ }
+ else if (tag == "data")
+ {
+ if (multiline)
+ {
+ static const QRegExp rx_empty("^\\s*$");
+ if (rx_empty.exactMatch(value))
+ {
+ buffer += "</p>";
+ new_paragraph = true;
+ }
+ else if (first_line)
+ {
+ new_paragraph = true;
+ first_line = false;
+ }
+ else if (new_paragraph)
+ {
+ buffer += "<p>";
+ new_paragraph = false;
+ }
+ }
+ buffer += text2html(QString(value).replace(QRegExp("(http://\\S+)"),QString("<a href=\"\\1\">\\1</a>")));
+ }
+ else if (tag == "package_link")
+ buffer += "<a href=\"" + slave->buildURL("show", value).htmlURL() + "\">" + value + "</a>";
+}
+
+}