You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeio-apt/src/aptcache.cpp

293 lines
7.4 KiB

/***************************************************************************
* 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 <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"