/*************************************************************************** * Copyright (C) 2003 by Sylvain Joyeux * * sylvain.joyeux@m4x.org * * * * 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 #include #include #include #include #include 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"