|
|
|
/***************************************************************************
|
|
|
|
* 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 <tqstringlist.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
|
|
AptCache::AptCache()
|
|
|
|
{
|
|
|
|
connect(&m_process, TQT_SIGNAL(receivedStderr(KProcess*, char*, int)),
|
|
|
|
this, TQT_SLOT(receivedStdErr(KProcess*, char*, int )));
|
|
|
|
connect(&m_process, TQT_SIGNAL(receivedStdout(KProcess*, char*, int)),
|
|
|
|
this, TQT_SLOT(receivedStdOut(KProcess*, char*, int )));
|
|
|
|
}
|
|
|
|
AptCache::~AptCache() {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static TQStringList received(TQString& buffer, char* input, int input_len)
|
|
|
|
{
|
|
|
|
buffer += TQString::fromLatin1(input, input_len);
|
|
|
|
TQStringList ret = TQStringList::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 TQRegExp rx_we("(W|E):\\s+(.*)");
|
|
|
|
|
|
|
|
TQStringList lines = received(m_received_err, buffer, len);
|
|
|
|
for (TQStringList::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 )
|
|
|
|
{
|
|
|
|
TQStringList 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 TQString& expression)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
|
|
|
|
m_process.setEnvironment("LANGUAGE", "C");
|
|
|
|
m_process << "apt-cache" << "search";
|
|
|
|
m_process << TQStringList::split(" ", expression);
|
|
|
|
m_receive = &AptCache::receiveSearch;
|
|
|
|
return m_process.start(KProcess::Block, KProcess::Stdout );
|
|
|
|
}
|
|
|
|
|
|
|
|
void AptCache::receiveSearch(const TQStringList& lines)
|
|
|
|
{
|
|
|
|
static TQRegExp rx_parse("([^ ]+) - (.*)");
|
|
|
|
|
|
|
|
TQStringList::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 TQString& 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 TQStringList& lines)
|
|
|
|
{
|
|
|
|
static bool pkgfield = false, insert_newline = false;
|
|
|
|
static int indent = 0;
|
|
|
|
|
|
|
|
static TQRegExp rx_attribute("([\\w-]+): (.*)");
|
|
|
|
static const TQString pkg_fields[] =
|
|
|
|
{ "Suggests", "Replaces", "Depends", "Conflicts", TQString() };
|
|
|
|
|
|
|
|
TQStringList::ConstIterator i;
|
|
|
|
for (i = lines.begin(); i != lines.end(); ++i)
|
|
|
|
{
|
|
|
|
TQString 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 TQString * 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( TQRegExp("[^\\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", TQString::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 TQString& data)
|
|
|
|
{
|
|
|
|
TQStringList split(TQStringList::split(",", data));
|
|
|
|
for (TQStringList::ConstIterator i = split.begin(); i != split.end(); ++i)
|
|
|
|
{
|
|
|
|
if (i != split.begin()) emit token("data", ", ");
|
|
|
|
|
|
|
|
TQStringList bar(TQStringList::split("|", *i));
|
|
|
|
for (TQStringList::ConstIterator j = bar.begin(); j != bar.end(); ++j)
|
|
|
|
{
|
|
|
|
if (j != bar.begin()) emit token("data", " | ");
|
|
|
|
TQString 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 TQString & 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 TQStringList& lines)
|
|
|
|
{
|
|
|
|
static TQRegExp rx_pkgname("(\\w[\\w+-.]+):");
|
|
|
|
static TQRegExp rx_location("^\\s*\\d+\\s[^\\d]");
|
|
|
|
|
|
|
|
for(TQStringList::ConstIterator l = lines.begin(); l != lines.end(); ++l)
|
|
|
|
{
|
|
|
|
if ((*l).isEmpty()) continue;
|
|
|
|
|
|
|
|
TQString 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", TQString());
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString AptCache::policy_installed() const
|
|
|
|
{ return m_installed; }
|
|
|
|
TQString AptCache::policy_candidate() const
|
|
|
|
{ return m_candidate; }
|
|
|
|
|
|
|
|
|
|
|
|
#include "aptcache.moc"
|
|
|
|
|