summaryrefslogtreecommitdiffstats
path: root/src/aptcache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/aptcache.cpp')
-rw-r--r--src/aptcache.cpp292
1 files changed, 292 insertions, 0 deletions
diff --git a/src/aptcache.cpp b/src/aptcache.cpp
new file mode 100644
index 0000000..9511760
--- /dev/null
+++ b/src/aptcache.cpp
@@ -0,0 +1,292 @@
+/***************************************************************************
+ * 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 "aptcache.h"
+#include "apt.h"
+#include "debug.h"
+
+#include "regexps.h"
+
+#include <qstringlist.h>
+#include <qregexp.h>
+
+#include <kdebug.h>
+
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+
+
+AptCache::AptCache()
+{
+ connect(&m_process, SIGNAL(receivedStderr(KProcess*, char*, int)),
+ this, SLOT(receivedStdErr(KProcess*, char*, int )));
+ connect(&m_process, SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this, SLOT(receivedStdOut(KProcess*, char*, int )));
+}
+AptCache::~AptCache() {}
+
+
+
+
+static QStringList received(QString& buffer, char* input, int input_len)
+{
+ buffer += QString::fromLatin1(input, input_len);
+ QStringList ret = QStringList::split('\n', buffer, true);
+ if (!buffer.endsWith("\n"))
+ {
+ buffer = ret.last();
+ ret.pop_back();
+ }
+ else
+ buffer = "";
+
+ return ret;
+}
+void AptCache::receivedStdErr( KProcess * /*process*/, char * buffer, int len )
+{
+ static QRegExp rx_we("(W|E):\\s+(.*)");
+
+ QStringList lines = received(m_received_err, buffer, len);
+ for (QStringList::ConstIterator i = lines.begin(); i != lines.end(); ++i)
+ {
+ if (rx_we.exactMatch(*i))
+ {
+ if (rx_we.cap(1) == "E") emit token("error", rx_we.cap(2));
+ else emit token("warning", rx_we.cap(2));
+ }
+ else
+ {
+ kdDebug() << "Unmatched error : " << *i << endl;
+ }
+ }
+}
+void AptCache::receivedStdOut( KProcess * /*process*/, char * buffer, int len )
+{
+ QStringList lines = received(m_received_out, buffer, len);
+ (this->*m_receive)(lines);
+}
+
+
+
+
+void AptCache::clear()
+{
+ m_process.clearArguments();
+ m_attribute = "";
+ m_received_err = "";
+ m_received_out = "";
+}
+
+bool AptCache::search(const QString& expression)
+{
+ clear();
+
+ m_process.setEnvironment("LANGUAGE", "C");
+ m_process << "apt-cache" << "search";
+ m_process << QStringList::split(" ", expression);
+ m_receive = &AptCache::receiveSearch;
+ return m_process.start(KProcess::Block, KProcess::Stdout );
+}
+
+void AptCache::receiveSearch(const QStringList& lines)
+{
+ static QRegExp rx_parse("([^ ]+) - (.*)");
+
+ QStringList::ConstIterator i;
+ for (i = lines.begin(); i != lines.end(); ++i)
+ {
+ if ((*i).isEmpty()) continue;
+
+ if (!rx_parse.exactMatch(*i))
+ {
+ kdDebug(DEBUG_ZONE) << "Parsing error. Line is " << *i << endl;
+ continue;
+ }
+
+ emit token("package", rx_parse.cap(1));
+ emit token("short_desc", rx_parse.cap(2));
+
+ kdDebug(DEBUG_ZONE) << "Found package : " << rx_parse.cap(1) << " - " << rx_parse.cap(2) << endl;
+ }
+}
+
+bool AptCache::show(const QString& package)
+{
+ clear();
+
+ m_process.setEnvironment("LANGUAGE", "C");
+ m_process << "apt-cache" << "show" << package;
+ m_receive = &AptCache::receiveShow;
+ return m_process.start(KProcess::Block, KProcess::Stdout );
+}
+
+void AptCache::receiveShow(const QStringList& lines)
+{
+ static bool pkgfield = false, insert_newline = false;
+ static int indent = 0;
+
+ static QRegExp rx_attribute("([\\w-]+): (.*)");
+ static const QString pkg_fields[] =
+ { "Suggests", "Replaces", "Depends", "Conflicts", QString::null };
+
+ QStringList::ConstIterator i;
+ for (i = lines.begin(); i != lines.end(); ++i)
+ {
+ QString data(*i);
+ if (data.isEmpty()) continue;
+
+ if (rx_attribute.exactMatch(*i))
+ {
+ m_attribute = rx_attribute.cap(1);
+ data = rx_attribute.cap(2);
+
+ if (m_attribute != "Package")
+ emit token("field", m_attribute);
+
+ insert_newline = pkgfield = false;
+ indent = 0;
+
+ const QString * test_field;
+ for (test_field = pkg_fields; !test_field -> isNull(); ++test_field)
+ if (*test_field == m_attribute)
+ {
+ pkgfield = true;
+ break;
+ }
+ }
+
+ if (m_attribute == "Package")
+ emit token("package", data);
+ else if (pkgfield)
+ parse_pkgfield(data);
+ else
+ {
+ int new_indent = data.find( QRegExp("[^\\s]") );
+
+ // new_indent > 0 means that we are in a multi-line
+ // field. Those lines always begin with " ", so we want
+ // to drop it.
+ if (new_indent > 0) --new_indent;
+
+ if (new_indent != indent)
+ {
+ emit token("indent", QString::number(new_indent) );
+ indent = new_indent;
+ insert_newline = false;
+ }
+
+ if (data == " .")
+ {
+ if (insert_newline)
+ emit token("data", "\n");
+ }
+ else
+ {
+ if (insert_newline)
+ emit token("data", "\n" + data);
+ else
+ emit token("data", data);
+ }
+
+ insert_newline = true;
+ }
+ }
+}
+
+void AptCache::parse_pkgfield(const QString& data)
+{
+ QStringList split(QStringList::split(",", data));
+ for (QStringList::ConstIterator i = split.begin(); i != split.end(); ++i)
+ {
+ if (i != split.begin()) emit token("data", ", ");
+
+ QStringList bar(QStringList::split("|", *i));
+ for (QStringList::ConstIterator j = bar.begin(); j != bar.end(); ++j)
+ {
+ if (j != bar.begin()) emit token("data", " | ");
+ QString pkg, remaining;
+
+ int paren = (*j).find('(');
+ if (paren != -1)
+ {
+ pkg = (*j).left(paren - 1);
+ remaining = (*j).right((*j).length() - paren + 1);
+ }
+ else
+ {
+ pkg = (*j);
+ }
+
+ pkg = pkg.stripWhiteSpace();
+ remaining = remaining.stripWhiteSpace();
+
+ emit token("package_link", pkg);
+ if (!remaining.isEmpty()) emit token("data", " " + remaining);
+ }
+ }
+}
+
+bool AptCache::policy( const QString & package )
+{
+ clear();
+
+ m_process.setEnvironment("LANGUAGE", "C");
+ m_process << "apt-cache" << "policy" << package;
+ m_receive = &AptCache::receivePolicy;
+ return m_process.start(KProcess::Block, KProcess::Stdout );
+}
+
+void AptCache::receivePolicy(const QStringList& lines)
+{
+ static QRegExp rx_pkgname("(\\w[\\w+-.]+):");
+ static QRegExp rx_location("^\\s*\\d+\\s[^\\d]");
+
+ for(QStringList::ConstIterator l = lines.begin(); l != lines.end(); ++l)
+ {
+ if ((*l).isEmpty()) continue;
+
+ QString data( (*l).stripWhiteSpace() );
+ if (rx_pkgname.exactMatch(*l))
+ emit token("package", rx_pkgname.cap(1));
+ else if (data.startsWith("Installed:", false))
+ {
+ data = data.right(data.length() - 11);
+ emit token("installed", data);
+ m_installed = data;
+ }
+ else if (data.startsWith("Candidate:", false))
+ {
+ data = data.right(data.length() - 11);
+ emit token("candidate", data);
+ m_candidate = data;
+ }
+ else if (data.startsWith("Version table:", false))
+ emit token("version_table", QString::null);
+ else if (rx_location.search(data) > -1)
+ emit token("location", data);
+ else
+ {
+ if (data.startsWith("*** "))
+ data = data.right( data.length() - 4 );
+
+ if (match_dversion(data.section(' ', 0, 0)))
+ emit token("version", data);
+ }
+ }
+}
+
+QString AptCache::policy_installed() const
+{ return m_installed; }
+QString AptCache::policy_candidate() const
+{ return m_candidate; }
+
+
+#include "aptcache.moc"
+