diff options
Diffstat (limited to 'src/aptcache.cpp')
-rw-r--r-- | src/aptcache.cpp | 292 |
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 * + * [email protected] * + * * + * 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" + |