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.
947 lines
25 KiB
947 lines
25 KiB
15 years ago
|
/***************************************************************************
|
||
|
* Copyright (C) 2003 by Sylvain Joyeux *
|
||
|
* sylvain.joyeux@m4x.org *
|
||
|
* The forms are by Willy De la Court <wdl@linux-lovers.be> *
|
||
|
* *
|
||
|
* 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 "apt.h"
|
||
|
#include "regexps.h"
|
||
|
|
||
|
#include "dpkg.h"
|
||
|
|
||
|
#include "parsers/parsers.h"
|
||
|
|
||
|
#include <qcstring.h>
|
||
|
|
||
|
#include <kapplication.h>
|
||
|
#include <kinstance.h>
|
||
|
#include <kglobal.h>
|
||
|
#include <kconfig.h>
|
||
|
#include <kstandarddirs.h>
|
||
|
#include <klocale.h>
|
||
|
#include <kurl.h>
|
||
|
#include <kio/slavebase.h>
|
||
|
#include <kmessagebox.h>
|
||
|
|
||
|
#include <kdebug.h>
|
||
|
|
||
|
#include <qregexp.h>
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include <config.h>
|
||
|
|
||
|
using namespace KIO;
|
||
|
|
||
|
/*************************************************************************
|
||
|
* Common definitions of HTML fragments
|
||
|
*/
|
||
|
|
||
|
static const QString
|
||
|
html_preamble("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Strict//EN\"\n"
|
||
|
"\t\"http://www.w3.org/TR/html4/strict.dtd\">\n"
|
||
|
"<html>\n");
|
||
|
static const QString
|
||
|
html_redirect(html_preamble +
|
||
|
QString("<head>\n"
|
||
|
"\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"
|
||
|
"\t<meta http-equiv=\"Refresh\" content=\"0 ; URL=%1\">\n"
|
||
|
"</head>\n"
|
||
|
"\n<body></body>\n"
|
||
|
"</html>"));
|
||
|
|
||
|
static const QString
|
||
|
html_head(html_preamble +
|
||
|
QString("<head>\n"
|
||
|
"\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"
|
||
|
"\t<link rel=\"stylesheet\" href=\"file:%1\">\n"
|
||
|
"\t<title>%2</title>\n"
|
||
|
"</head>\n\n"
|
||
|
"<body>\n"));
|
||
|
|
||
|
static QString close_html_head();
|
||
|
static QString open_html_head(const QString& title, bool links, AptProtocol const& config)
|
||
|
{
|
||
|
|
||
|
static const QString
|
||
|
html_head_table(
|
||
|
"<table class=\"header\" style=\"background-image: url(file:%1);\"\n"
|
||
|
"\t\tcellspacing=\"0\" cellpadding=\"0\">\n"
|
||
|
"<tr>\n"
|
||
|
"\t<td class=\"logo\" %2><img src=\"file:%3\" alt=\"%4\" style=\"border: 0px\" /></td>\n"
|
||
|
"\t<td class=\"header-title\">%4</td>\n");
|
||
|
|
||
|
QString rowspan;
|
||
|
if (links) rowspan = "rowspan=\"2\"";
|
||
|
QString ret =
|
||
|
html_head
|
||
|
.arg(config.stylesheet())
|
||
|
.arg(title)
|
||
|
+ html_head_table
|
||
|
.arg(config.header_background())
|
||
|
.arg(rowspan)
|
||
|
.arg(config.logo())
|
||
|
.arg(config.logo_alt())
|
||
|
.arg(title);
|
||
|
|
||
|
if (links)
|
||
|
{
|
||
|
return ret +
|
||
|
"</tr>\n"
|
||
|
"<tr>\n"
|
||
|
"\t<td class=\"links\">\n"
|
||
|
"\t<table class=\"links\" cellspacing=\"0\" cellpadding=\"0\">\n"
|
||
|
"\t<tr>\n";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return ret + "</tr>\n</table>\n\n";
|
||
|
}
|
||
|
}
|
||
|
static QString add_html_head_link(const QString& url, const QString& name, const QString& long_desc)
|
||
|
{
|
||
|
static const QString format("\t\t<td><a href=\"%1\" title=\"%2\">%3</a></td>\n");
|
||
|
return format.arg(url).arg(long_desc).arg(name);
|
||
|
}
|
||
|
static QString close_html_head()
|
||
|
{
|
||
|
return "\t</tr>\n"
|
||
|
"\t</table>\n"
|
||
|
"\t</td>\n"
|
||
|
"</tr>"
|
||
|
"</table>";
|
||
|
}
|
||
|
|
||
|
static const QString
|
||
|
html_tail("<div class=\"footer\">%1</div>\n"
|
||
|
"</body>\n"
|
||
|
"</html>");
|
||
|
|
||
|
|
||
|
QString AptProtocol::make_html_tail(const QString& note, bool with_form)
|
||
|
{
|
||
|
with_form = m_search && with_form;
|
||
|
|
||
|
QString ret;
|
||
|
if (with_form)
|
||
|
ret = "<hr>\n" + make_html_form();
|
||
|
|
||
|
if (!note.isEmpty())
|
||
|
ret += html_tail.arg(note + ". " + i18n("Page generated by kio_apt."));
|
||
|
else ret += html_tail.arg(i18n("Page generated by kio_apt."));
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/**********************************************************************************
|
||
|
* Search form
|
||
|
*/
|
||
|
|
||
|
static const QString
|
||
|
html_form_begin("\n<form action=\"apt:/\" method=\"GET\">\n"
|
||
|
"<table class=\"query\">\n");
|
||
|
static const QString
|
||
|
html_form_end("<tr>\n"
|
||
|
"\t<td class=\"button\" colspan=\"2\"><input type=\"submit\" value=\"%1\"></td>\n"
|
||
|
"</tr>\n"
|
||
|
"</table>\n"
|
||
|
"</form>\n");
|
||
|
|
||
|
static const QString
|
||
|
html_form_line("<tr>\n"
|
||
|
"\t<td><label for=\"%1\">%2</label></td>\n"
|
||
|
"\t<td><input type=\"text\" name=\"%3\" id=\"%4\"></td>\n"
|
||
|
"</tr>\n");
|
||
|
|
||
|
static QString make_html_form_line(const QString& type, const QString& label)
|
||
|
{ return html_form_line.arg(type).arg(label).arg(type).arg(type); }
|
||
|
|
||
|
|
||
|
static QString make_extform_cmd(bool ext_form, const KURL& query)
|
||
|
{
|
||
|
QString cmd = ext_form ? "0" : "1";
|
||
|
QString msg = ext_form ? i18n("Hide extended form") : i18n("Show extended form");
|
||
|
|
||
|
KURL url(query);
|
||
|
url.addQueryItem("extended_form", cmd);
|
||
|
url.setRef("extformcmd");
|
||
|
|
||
|
return
|
||
|
"<div class=\"command\" id=\"extformcmd\">\n"
|
||
|
"\t<a href=\"" + url.htmlURL() + "\">[" + msg + "]</a>\n"
|
||
|
"</div>\n";
|
||
|
}
|
||
|
|
||
|
/** Prints the HTML code for the query form */
|
||
|
QString AptProtocol::make_html_form() const
|
||
|
{
|
||
|
bool can_fsearch = false;
|
||
|
bool ext_form = KGlobal::config() -> readBoolEntry("extended_form", true);
|
||
|
// Only in config-file. Needed for some dpkg-based distros that are not Debian
|
||
|
can_fsearch = can_searchfile(true);
|
||
|
|
||
|
bool online = false;
|
||
|
bool online_form = KGlobal::config() -> readBoolEntry("online_form", true);
|
||
|
if (m_adept_batch)
|
||
|
online = online_form && (!m_internal) && ext_form && m_adept_batch -> capabilities(PackageManager::ONLINE);
|
||
|
|
||
|
QString ret;
|
||
|
QTextOStream stream(&ret);
|
||
|
stream << make_extform_cmd(ext_form, m_query);
|
||
|
|
||
|
if (online)
|
||
|
stream << "<table class=\"queryform\"><tr><td>\n";
|
||
|
|
||
|
stream << html_form_begin;
|
||
|
stream << "<tr><td colspan=\"2\" class=\"title\">" + i18n("Offline search") + "</td></tr>" << endl;
|
||
|
stream << make_html_form_line("search", i18n("Package search"));
|
||
|
if (ext_form)
|
||
|
{
|
||
|
if (can_fsearch)
|
||
|
stream << make_html_form_line("fsearch", i18n("File search"));
|
||
|
stream << make_html_form_line("show", i18n("Package info"));
|
||
|
}
|
||
|
stream << html_form_end.arg( i18n("Search") );
|
||
|
|
||
|
if (online)
|
||
|
{
|
||
|
stream << "\n</td><td>\n";
|
||
|
stream << m_adept_batch -> getOnlineForm();
|
||
|
stream << "\n</td></tr>\n</table>";
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************************/
|
||
|
|
||
|
AptProtocol::AptProtocol( const QCString &pool_socket, const QCString &app_socket )
|
||
|
: SlaveBase( "kio_apt", pool_socket, app_socket ),
|
||
|
m_adept_batch(0), m_parser(0)
|
||
|
|
||
|
{
|
||
|
KStandardDirs* dirs = KGlobal::dirs();
|
||
|
m_stylesheet = dirs->findResource( "data", "kio_apt/kio_apt.css" );
|
||
|
|
||
|
m_logo = dirs->findResource( "data", "kio_apt/"
|
||
|
+ KGlobal::config() -> readEntryUntranslated("logo", "kdedeb_logo.png" ) );
|
||
|
|
||
|
m_header_background = dirs->findResource( "data", "kio_apt/"
|
||
|
+ KGlobal::config() -> readEntryUntranslated("background", "headerbg.png" ) );
|
||
|
|
||
|
m_logo_alt = KGlobal::config() -> readEntryUntranslated("alt_tag", i18n("KDE on Debian") );
|
||
|
|
||
|
connect(&m_process, SIGNAL(token(const QString&, const QString&)),
|
||
|
this, SLOT(token_dispatch(const QString&, const QString&)));
|
||
|
|
||
|
m_adept_batch = new Dpkg(this);
|
||
|
|
||
|
if (m_adept_batch)
|
||
|
{
|
||
|
connect(m_adept_batch, SIGNAL(token(const QString&, const QString&)),
|
||
|
this, SLOT(token_dispatch(const QString&, const QString&)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AptProtocol::~AptProtocol() {}
|
||
|
|
||
|
QString AptProtocol::stylesheet() const { return m_stylesheet; }
|
||
|
QString AptProtocol::logo() const { return m_logo; }
|
||
|
QString AptProtocol::logo_alt() const { return m_logo_alt; }
|
||
|
QString AptProtocol::header_background() const { return m_header_background; }
|
||
|
|
||
|
void AptProtocol::token_dispatch(const QString& name, const QString& val)
|
||
|
{
|
||
|
if (m_parser.get())
|
||
|
(*m_parser)(this, name, val);
|
||
|
}
|
||
|
|
||
|
void AptProtocol::data(const QCString& string)
|
||
|
{
|
||
|
using namespace Parsers;
|
||
|
(*this) << string;
|
||
|
}
|
||
|
|
||
|
void AptProtocol::data(const QString& string)
|
||
|
{
|
||
|
using namespace Parsers;
|
||
|
(*this) << string;
|
||
|
}
|
||
|
|
||
|
void AptProtocol::data(const char* string)
|
||
|
{
|
||
|
using namespace Parsers;
|
||
|
(*this) << string;
|
||
|
}
|
||
|
|
||
|
void AptProtocol::data(const QByteArray& array)
|
||
|
{ SlaveBase::data(array); }
|
||
|
|
||
|
void AptProtocol::mimetype( const KURL & /*url*/ )
|
||
|
{
|
||
|
mimeType( "text/html" );
|
||
|
finished();
|
||
|
}
|
||
|
|
||
|
bool AptProtocol::check_validpackage(const QString& query)
|
||
|
{
|
||
|
static QRegExp rx_pkgname(rxs_pkgname);
|
||
|
if (!rx_pkgname.exactMatch(query))
|
||
|
{
|
||
|
error( ERR_SLAVE_DEFINED, i18n("\"%1\" is not a valid package name").arg(query) );
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/********************************************************************
|
||
|
* Main entry point
|
||
|
*/
|
||
|
|
||
|
static QString read_option(QMap<QString, QString>& map, const QString& name, const QString& def)
|
||
|
{
|
||
|
if (!map.contains(name)) return def;
|
||
|
QString ret = map[name];
|
||
|
map.remove(name);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void AptProtocol::get ( const KURL& url )
|
||
|
{
|
||
|
/* The queries have two possible formats :
|
||
|
|
||
|
- clean way to call a command
|
||
|
apt:/command?query&option=value&option=value&...
|
||
|
- needed to simplify forms
|
||
|
apt:/?command=query&command2=&command3=&option=value&option=value&...
|
||
|
- calls only the query form page
|
||
|
apt:/
|
||
|
*/
|
||
|
|
||
|
typedef void (AptProtocol::*Command)(const QString&, const QueryOptions&);
|
||
|
static const QString commands[] =
|
||
|
{ "search", "show", "policy",
|
||
|
"fsearch", "list", "online",
|
||
|
"get", QString::null };
|
||
|
static const Command methods[] =
|
||
|
{ &AptProtocol::search, &AptProtocol::show, &AptProtocol::policy,
|
||
|
&AptProtocol::searchfile, &AptProtocol::listfiles, &AptProtocol::online,
|
||
|
&AptProtocol::adept_batch };
|
||
|
|
||
|
QString command, query;
|
||
|
Command method = 0;
|
||
|
QueryOptions options = url.queryItems(KURL::CaseInsensitiveKeys);
|
||
|
|
||
|
// canonize the part before ? : remove the first /
|
||
|
QString path = url.path();
|
||
|
QString host = url.host();
|
||
|
|
||
|
if ( path.isEmpty() && !host.isEmpty() )
|
||
|
{
|
||
|
path = host;
|
||
|
}
|
||
|
|
||
|
if (path [0] == '/')
|
||
|
path = path.right(path.length() - 1);
|
||
|
|
||
|
for (int cmd_idx = 0; !commands[cmd_idx].isNull(); ++cmd_idx)
|
||
|
{
|
||
|
const QString cmd_it = commands[cmd_idx];
|
||
|
|
||
|
// Look if the command is in the path part
|
||
|
if (command.isEmpty() && cmd_it == path)
|
||
|
{
|
||
|
command = cmd_it;
|
||
|
method = methods[cmd_idx];
|
||
|
}
|
||
|
if (options.contains(cmd_it))
|
||
|
{
|
||
|
|
||
|
if (options[cmd_it].isEmpty() && !options[cmd_it].isNull())
|
||
|
{ // we have a &command=& format, we remove it
|
||
|
options.remove(cmd_it);
|
||
|
}
|
||
|
else if (command.isEmpty() && !options[cmd_it].isEmpty())
|
||
|
{ // the command is set in the options map
|
||
|
command = cmd_it;
|
||
|
method = methods[cmd_idx];
|
||
|
query = options[cmd_it];
|
||
|
options.remove(cmd_it);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Well, we have no query for now, let's find it
|
||
|
if (query.isEmpty())
|
||
|
{
|
||
|
for (QueryOptions::Iterator i = options.begin(); i != options.end(); ++i)
|
||
|
{
|
||
|
if ((*i).isNull())
|
||
|
{
|
||
|
query = KURL::decode_string(i.key());
|
||
|
options.remove(i);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Interpret the ioslave config options
|
||
|
// and remove them from the options map
|
||
|
QString opt = read_option(options, "extended_form", QString::null);
|
||
|
if (!opt.isNull())
|
||
|
{
|
||
|
bool ext_form = (opt != "0");
|
||
|
KGlobal::config() -> writeEntry("extended_form", ext_form);
|
||
|
}
|
||
|
|
||
|
// Enable install/remove/upgrade/...
|
||
|
opt = read_option(options, "enable_actions", "1");
|
||
|
m_act = (opt != "0");
|
||
|
|
||
|
opt = read_option(options, "enable_search", "1");
|
||
|
m_search = (opt != "0");
|
||
|
|
||
|
// Allow links outside of apt:/ hierarchy
|
||
|
opt = read_option(options, "stay_internal", "0");
|
||
|
m_internal = (opt == "1");
|
||
|
|
||
|
// Sync the config (must use kcfg sometime :p)
|
||
|
KGlobal::config() -> sync();
|
||
|
|
||
|
if (command.isEmpty() || query.isEmpty())
|
||
|
{
|
||
|
//If path isn't empty, then a package is to be installed via an apt:/ link
|
||
|
if ( !path.isEmpty())
|
||
|
{
|
||
|
query = "install";
|
||
|
options["package"] = path;
|
||
|
options["weblinkinstall"] = 1;
|
||
|
adept_batch(query, options);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// No query or no command, we go in help mode
|
||
|
m_query = buildURL(KURL("apt:/"));
|
||
|
help();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_query = buildURL(command, query);
|
||
|
m_query.setHTMLRef(url.htmlRef());
|
||
|
for (QueryOptions::ConstIterator i = options.begin(); i != options.end(); ++i)
|
||
|
m_query.addQueryItem(i.key(), i.data());
|
||
|
|
||
|
kdDebug() << "Old url " << url << ", new url " << m_query << endl;
|
||
|
|
||
|
if (m_query != url)
|
||
|
{
|
||
|
redirection(m_query);
|
||
|
data(QByteArray());
|
||
|
finished();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
(this->*method)(query, options);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************
|
||
|
*
|
||
|
* form
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
void AptProtocol::help()
|
||
|
{
|
||
|
mimeType("text/html");
|
||
|
|
||
|
QString buffer;
|
||
|
QTextOStream stream(&buffer);
|
||
|
stream
|
||
|
<< open_html_head(i18n("Search Form"), false, *this)
|
||
|
<< make_html_form()
|
||
|
<< make_html_tail(QString::null, false);
|
||
|
data(buffer);
|
||
|
data(QByteArray());
|
||
|
finished();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***********************************************************************************
|
||
|
* apt-cache search
|
||
|
*/
|
||
|
|
||
|
void AptProtocol::search( const QString& query, const QueryOptions& /*options*/ )
|
||
|
{
|
||
|
mimeType("text/html");
|
||
|
|
||
|
data(open_html_head(i18n("Package search result for \"%1\"").arg(query), false, *this));
|
||
|
|
||
|
m_parser.reset(new Parsers::Search);
|
||
|
(*m_parser)(this, "begin", query);
|
||
|
if (!m_process.search( query ))
|
||
|
{
|
||
|
error(ERR_SLAVE_DEFINED, i18n("Error launching the search").arg(query));
|
||
|
return;
|
||
|
}
|
||
|
(*m_parser)(this, "end", QString::null);
|
||
|
|
||
|
data(make_html_tail( i18n("%1 results").arg(m_parser -> result_count())) );
|
||
|
data(QByteArray());
|
||
|
finished();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***********************************************************************************
|
||
|
* apt-cache show
|
||
|
*/
|
||
|
|
||
|
static QString filelist_cmd(bool show_filelist, const KURL& query)
|
||
|
{
|
||
|
QString value = show_filelist ? "0" : "1";
|
||
|
QString msg = show_filelist ? i18n("Hide file list") : i18n("Show file list");
|
||
|
|
||
|
KURL url(query);
|
||
|
url.addQueryItem("show_filelist", value);
|
||
|
url.setRef("filelistcmd");
|
||
|
|
||
|
return
|
||
|
"<div class=\"command\" id=\"filelistcmd\">\n"
|
||
|
"\t<a href=\"" + url.htmlURL() + "\">"
|
||
|
"[" + msg + "]"
|
||
|
"</a>\n"
|
||
|
"</div>";
|
||
|
}
|
||
|
|
||
|
void AptProtocol::show(const QString& package, const QueryOptions& options)
|
||
|
{
|
||
|
if (!check_validpackage(package)) return;
|
||
|
|
||
|
if (options.contains("show_filelist"))
|
||
|
{
|
||
|
KGlobal::config() -> writeEntry("show_filelist", options["show_filelist"] != "0");
|
||
|
KGlobal::config() -> sync();
|
||
|
}
|
||
|
|
||
|
mimeType("text/html");
|
||
|
|
||
|
QString installed_version;
|
||
|
|
||
|
/** First, we parse policy
|
||
|
* We use here the fact that HTML is generated
|
||
|
* during the call of (*policy)(...,"end",...),
|
||
|
* since the header changes when the package
|
||
|
* is installed or not */
|
||
|
Parsers::Policy* policy = new Parsers::Policy(package, m_act);
|
||
|
m_parser.reset(policy);
|
||
|
(*m_parser)(this, "begin", QString::null);
|
||
|
{
|
||
|
if (!m_process.policy( package ))
|
||
|
{
|
||
|
error(ERR_SLAVE_DEFINED, i18n("Can't launch \"apt-cache policy %1\"").arg(package));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
installed_version = policy->getInstalled();
|
||
|
bool can_list = can_listfiles(!installed_version.isEmpty());
|
||
|
QString buffer;
|
||
|
QTextOStream s(&buffer);
|
||
|
if (can_list)
|
||
|
{
|
||
|
KURL url = buildURL("list", package);
|
||
|
s << open_html_head(i18n("Package description for \"%1\"").arg(package), true, *this)
|
||
|
<< add_html_head_link(url.htmlURL(), i18n("List package files"), "")
|
||
|
<< close_html_head();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s << open_html_head(i18n("Package description for \"%1\"").arg(package), false, *this);
|
||
|
}
|
||
|
data(buffer);
|
||
|
}
|
||
|
(*m_parser)(this, "end", QString::null);
|
||
|
|
||
|
|
||
|
/** Add package description section */
|
||
|
m_parser.reset(new Parsers::Show(package, installed_version, m_act));
|
||
|
(*m_parser)(this, "begin", QString::null);
|
||
|
{
|
||
|
if (!m_process.show(package))
|
||
|
{
|
||
|
error(ERR_SLAVE_DEFINED, i18n("Can't launch \"apt-cache show %1\"").arg(package));
|
||
|
return;
|
||
|
}
|
||
|
if (!m_parser -> result_count())
|
||
|
{
|
||
|
data("<div class=\"error\">" + i18n("No package found named \"%1\"").arg(package) + "</div>\n");
|
||
|
data(make_html_tail());
|
||
|
data(QByteArray());
|
||
|
finished();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
(*m_parser)(this, "end", QString::null);
|
||
|
|
||
|
|
||
|
|
||
|
/** Add file list (if enabled) */
|
||
|
bool show_filelist = KGlobal::config() -> readBoolEntry("show_filelist", false);
|
||
|
if ( show_filelist )
|
||
|
{
|
||
|
if (can_listfiles(!installed_version.isEmpty()))
|
||
|
{
|
||
|
data(
|
||
|
"<hr>\n"
|
||
|
+ filelist_cmd(show_filelist, m_query)
|
||
|
+ "<div class=\"filelist\">\n");
|
||
|
|
||
|
m_parser.reset(new Parsers::List(!m_internal));
|
||
|
(*m_parser)(this, "begin", QString::null);
|
||
|
if (!m_adept_batch -> list(package))
|
||
|
{
|
||
|
error(ERR_SLAVE_DEFINED, i18n("Error listing files of %1").arg(package));
|
||
|
return;
|
||
|
}
|
||
|
(*m_parser)(this, "end", QString::null);
|
||
|
|
||
|
data("\n</div>\n");
|
||
|
}
|
||
|
else // cannot list files
|
||
|
{
|
||
|
data(
|
||
|
"<hr>\n"
|
||
|
+ filelist_cmd(show_filelist, m_query)
|
||
|
+ "<div class=\"error\">" + i18n("Cannot list files for non-installed packages") + "</div>\n");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
data("<hr>\n" + filelist_cmd(show_filelist, m_query));
|
||
|
}
|
||
|
|
||
|
|
||
|
data(make_html_tail());
|
||
|
data(QByteArray());
|
||
|
finished();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***********************************************************************************
|
||
|
* apt-cache policy
|
||
|
*/
|
||
|
|
||
|
void AptProtocol::policy( const QString& query, const QueryOptions& /*options*/ )
|
||
|
{
|
||
|
if (!check_validpackage(query)) return;
|
||
|
|
||
|
mimeType("text/html");
|
||
|
|
||
|
data( open_html_head(i18n("Apt policy for \"%1\"").arg(query), false, *this) );
|
||
|
|
||
|
m_parser.reset(new Parsers::Policy(query, m_act));
|
||
|
(*m_parser)(this, "begin", QString::null);
|
||
|
if (!m_process.policy( query ))
|
||
|
{
|
||
|
error(ERR_SLAVE_DEFINED, i18n("Can't launch the policy for %1").arg(query));
|
||
|
return;
|
||
|
}
|
||
|
(*m_parser)(this, "end", QString::null);
|
||
|
|
||
|
data(make_html_tail());
|
||
|
data(QByteArray());
|
||
|
finished();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/***********************************************************************************
|
||
|
* Search the package which contains a specific file
|
||
|
*/
|
||
|
|
||
|
static const QString
|
||
|
html_dpkgs_begin("\n\n<table>\n"),
|
||
|
html_dpkgs_end("\n\n</table>\n");
|
||
|
|
||
|
|
||
|
bool AptProtocol::can_searchfile(bool is_installed) const
|
||
|
{
|
||
|
if (!m_adept_batch) return false;
|
||
|
int caps = m_adept_batch -> capabilities(PackageManager::SEARCH_FILE | PackageManager::OFFLINE);
|
||
|
if (!caps) return false;
|
||
|
return is_installed || !(caps & PackageManager::INSTALLED_ONLY);
|
||
|
}
|
||
|
void AptProtocol::searchfile(const QString& query, const QueryOptions& /*options*/)
|
||
|
{
|
||
|
if (!can_searchfile(true)) return;
|
||
|
|
||
|
mimeType("text/html");
|
||
|
data( open_html_head(i18n("File search for \"%1\"").arg(query), false, *this) + html_dpkgs_begin );
|
||
|
|
||
|
m_parser.reset(new Parsers::FileSearch);
|
||
|
(*m_parser)(this, "begin", QString::null);
|
||
|
if (!m_adept_batch -> search( query ))
|
||
|
{
|
||
|
error(ERR_SLAVE_DEFINED, i18n("Can't launch the package manager").arg(query));
|
||
|
return;
|
||
|
}
|
||
|
(*m_parser)(this, "end", QString::null);
|
||
|
|
||
|
data( html_dpkgs_end + make_html_tail(i18n("%1 files found").arg(m_parser -> result_count())) );
|
||
|
data(QByteArray());
|
||
|
finished();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***********************************************************************************
|
||
|
* List the files of a package
|
||
|
*/
|
||
|
|
||
|
bool AptProtocol::can_listfiles(bool is_installed) const
|
||
|
{
|
||
|
if (!m_adept_batch) return false;
|
||
|
int caps = m_adept_batch -> capabilities(PackageManager::LIST_FILES | PackageManager::OFFLINE);
|
||
|
if (!caps) return false;
|
||
|
return is_installed || !(caps & PackageManager::INSTALLED_ONLY);
|
||
|
}
|
||
|
|
||
|
void AptProtocol::listfiles(const QString& query, const QueryOptions& /*options*/)
|
||
|
{
|
||
|
if (!can_listfiles(true)) return;
|
||
|
if (!check_validpackage(query)) return;
|
||
|
|
||
|
mimeType("text/html");
|
||
|
|
||
|
KURL ret_url = buildURL("show", query);
|
||
|
|
||
|
QString buffer;
|
||
|
QTextOStream stream(&buffer);
|
||
|
stream
|
||
|
<< open_html_head(i18n("Files in \"%1\"").arg(query), true, *this)
|
||
|
<< add_html_head_link(ret_url.htmlURL(), i18n("Show package info"), "")
|
||
|
<< close_html_head()
|
||
|
<< endl;
|
||
|
data(buffer);
|
||
|
|
||
|
m_parser.reset(new Parsers::List(!m_internal));
|
||
|
(*m_parser)(this, "begin", QString::null);
|
||
|
if (!m_adept_batch -> list( query ))
|
||
|
{
|
||
|
error(ERR_SLAVE_DEFINED, i18n("Can't launch the package manager").arg(query));
|
||
|
return;
|
||
|
}
|
||
|
(*m_parser)(this, "end", QString::null);
|
||
|
|
||
|
data(make_html_tail());
|
||
|
data(QByteArray());
|
||
|
finished();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***********************************************************************************
|
||
|
* Go use online search services (like packages.debian.org for instance)
|
||
|
*/
|
||
|
|
||
|
//bool AptProtocol::can_online(int mode) const
|
||
|
//{
|
||
|
//// if (!m_adept_batch) return false;
|
||
|
//// return m_adept_batch -> capabilities(PackageManager::ONLINE | mode);
|
||
|
// return false;
|
||
|
//}
|
||
|
|
||
|
void AptProtocol::online(const QString& query, const QueryOptions& options)
|
||
|
{
|
||
|
QString url = m_adept_batch -> getOnlineURL(query, options);
|
||
|
redirection(url);
|
||
|
finished();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/***********************************************************************************
|
||
|
* Send commands for adept_batch
|
||
|
*/
|
||
|
void AptProtocol::adept_batch(const QString& query, const QueryOptions& options)
|
||
|
{
|
||
|
p=NULL;
|
||
|
|
||
|
QString command;
|
||
|
QString url;
|
||
|
QStringList plist;
|
||
|
QStringList puninst;
|
||
|
QStringList pinst;
|
||
|
int pcount;
|
||
|
int ip;
|
||
|
|
||
|
if (query == "install" || query.isEmpty()) {
|
||
|
command = "kdesu adept_batch install ";
|
||
|
} else if (query == "remove") {
|
||
|
command = "kdesu adept_batch remove ";
|
||
|
}
|
||
|
|
||
|
if (command.isEmpty())
|
||
|
{
|
||
|
error(ERR_SLAVE_DEFINED, i18n("No package manager command specified"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!options.contains("package"))
|
||
|
{
|
||
|
error(ERR_SLAVE_DEFINED, i18n("No package specified"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
plist = QStringList::split(", ", options["package"], false);
|
||
|
pcount = plist.count();
|
||
|
command += plist.join(" ");
|
||
|
|
||
|
if (pcount == 1)
|
||
|
{
|
||
|
if (query == "install")
|
||
|
ip = SlaveBase::messageBox(QuestionYesNo, i18n("Do you want to install %1 ?").arg(plist[0]), i18n("Package Installation"));
|
||
|
else
|
||
|
ip = SlaveBase::messageBox(QuestionYesNo, i18n("Do you want to remove %1 ?").arg(plist[0]), i18n("Package Removal"));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (query == "install")
|
||
|
ip = SlaveBase::messageBox(QuestionYesNo,i18n("Do you want to install the following %1 packages ?\n%2").arg(pcount).arg(options["package"]));
|
||
|
else
|
||
|
ip = SlaveBase::messageBox(QuestionYesNo,i18n("Do you want to remove the following %1 packages ?\n").arg(pcount).arg(options["package"]));
|
||
|
}
|
||
|
|
||
|
kdDebug(DEBUG_ZONE) << command << endl;
|
||
|
|
||
|
if (ip == KMessageBox::Yes)
|
||
|
{
|
||
|
p = new KShellProcess;
|
||
|
p->clearArguments();
|
||
|
*p << command;
|
||
|
p->start( KProcess::Block, KProcess::All );
|
||
|
|
||
|
for(int i = 0; i != pcount; ++i)
|
||
|
{
|
||
|
QString installed_version;
|
||
|
|
||
|
Parsers::Policy* policy = new Parsers::Policy(plist[i], m_act);
|
||
|
m_parser.reset(policy);
|
||
|
(*m_parser)(this, "begin", QString::null);
|
||
|
{
|
||
|
if (!m_process.policy( plist[i] ))
|
||
|
{
|
||
|
error(ERR_SLAVE_DEFINED, i18n("Can't launch \"apt-cache policy %1\"").arg(plist[i]));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
installed_version = policy->getInstalled();
|
||
|
if (installed_version.isEmpty())
|
||
|
{
|
||
|
puninst += plist[i];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pinst += plist[i];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (options.contains("weblinkinstall"))
|
||
|
{
|
||
|
if (puninst.count() == 0)
|
||
|
{
|
||
|
messageBox(Information,i18n("Installation successfull."));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
QString toto = puninst.join(" ");
|
||
|
messageBox(Information,i18n("There was a problem installing %1.").arg(toto));
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
url = "apt:/show?";
|
||
|
// Outside of a weblink, only one package can be installed at time
|
||
|
url += plist[0];
|
||
|
redirection(url);
|
||
|
data(QByteArray());
|
||
|
finished();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
KURL AptProtocol::buildURL( const QString & command, const QString & query ) const
|
||
|
{
|
||
|
KURL url;
|
||
|
url.setProtocol("apt");
|
||
|
if (!command.startsWith("/"))
|
||
|
url.setPath("/" + command);
|
||
|
else
|
||
|
url.setPath(command);
|
||
|
url.setQuery(query);
|
||
|
return buildURL(url);
|
||
|
}
|
||
|
|
||
|
KURL AptProtocol::buildURL( const KURL& query ) const
|
||
|
{
|
||
|
KURL url(query);
|
||
|
|
||
|
if (!m_act)
|
||
|
url.addQueryItem("enable_actions", "0");
|
||
|
if (!m_search)
|
||
|
url.addQueryItem("enable_search", "0");
|
||
|
if (m_internal)
|
||
|
url.addQueryItem("stay_internal", "1");
|
||
|
|
||
|
return url;
|
||
|
}
|
||
|
|
||
|
/***********************************************************************************
|
||
|
*
|
||
|
* kdemain
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
extern "C" {
|
||
|
int kdemain( int argc, char **argv ) {
|
||
|
KInstance instance( "kio_apt" );
|
||
|
|
||
|
if ( argc != 4 ) {
|
||
|
kdDebug( DEBUG_ZONE ) << "Usage: kio_apt protocol domain-socket1 domain-socket2" << endl;
|
||
|
exit ( -1 );
|
||
|
}
|
||
|
|
||
|
AptProtocol slave( argv[ 2 ], argv[ 3 ] );
|
||
|
slave.dispatchLoop();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#include "apt.moc"
|