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.
kftpgrabber/kftpgrabber/src/misc/filter.cpp

422 lines
12 KiB

/*
* This file is part of the KFTPGrabber project
*
* Copyright (C) 2003-2006 by the KFTPGrabber developers
* Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.net>
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
* NON-INFRINGEMENT. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
*
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
#include "filter.h"
#include <ntqregexp.h>
#include <tdeapplication.h>
#include <tdelocale.h>
#include <kstaticdeleter.h>
#include <tdeconfig.h>
namespace KFTPCore {
namespace Filter {
Condition::Condition(Field field, Type type, const TQVariant &value)
: m_field(field),
m_type(type),
m_value(value)
{
}
bool Condition::matches(const KFTPEngine::DirectoryEntry &entry) const
{
bool result = false;
TQString check;
switch (m_field) {
default:
case Filename: check = entry.filename(); break;
case EntryType: check = entry.type(); break;
case Size: check = TQString::number(entry.size()); break;
}
switch (m_type) {
case None: result = false; break;
case Contains: result = (check.contains(m_value.toString()) > 0); break;
case ContainsNot: result = (check.contains(m_value.toString()) == 0); break;
case Is: result = (check == m_value.toString()); break;
case IsNot: result = (check != m_value.toString()); break;
case Matches: {
TQRegExp r(m_value.toString());
result = (r.search(check) > -1);
break;
}
case MatchesNot: {
TQRegExp r(m_value.toString());
result = (r.search(check) == -1);
break;
}
case Greater: result = (check.toULongLong() > m_value.toULongLong()); break;
case Smaller: result = (check.toULongLong() < m_value.toULongLong()); break;
}
return result;
}
ConditionChain::ConditionChain()
: TQPtrList<Condition>(),
m_type(All)
{
setAutoDelete(true);
}
ConditionChain::ConditionChain(Type type)
: TQPtrList<Condition>(),
m_type(type)
{
setAutoDelete(true);
}
bool ConditionChain::matches(const KFTPEngine::DirectoryEntry &entry) const
{
if (isEmpty())
return false;
TQPtrList<Condition>::ConstIterator le = end();
for (TQPtrList<Condition>::ConstIterator i = begin(); i != le; ++i) {
bool match = (*i)->matches(entry);
if (match && m_type == Any)
return true;
else if (!match && m_type == All)
return false;
}
if (m_type == Any)
return false;
return true;
}
Action::Action()
: m_valid(false)
{
}
Action::Action(Type type, const TQVariant &value)
: m_valid(true),
m_type(type),
m_value(value)
{
}
ActionChain::ActionChain()
: TQPtrList<Action>()
{
setAutoDelete(true);
}
const Action *ActionChain::getAction(Action::Type type) const
{
ActionChain::ConstIterator le = end();
for (ActionChain::ConstIterator i = begin(); i != le; ++i)
if ((*i)->type() == type)
return (*i);
return 0;
}
Rule::Rule()
: m_name(TQString::null),
m_enabled(false)
{
}
Rule::Rule(const Rule *rule)
: m_name(rule->name()),
m_enabled(rule->isEnabled())
{
// Copy conditions
const ConditionChain *conditionList = rule->conditions();
m_conditionChain.setType(conditionList->type());
ConditionChain::ConstIterator cle = conditionList->end();
for (ConditionChain::ConstIterator i = conditionList->begin(); i != cle; ++i) {
const Condition *c = (*i);
m_conditionChain.append(new Condition(c->field(), c->type(), c->value()));
}
// Copy actions
const ActionChain *actionList = rule->actions();
ActionChain::ConstIterator ale = actionList->end();
for (ActionChain::ConstIterator i = actionList->begin(); i != ale; ++i) {
const Action *a = (*i);
m_actionChain.append(new Action(a->type(), a->value()));
}
}
Rule::Rule(const TQString &name)
: m_name(name),
m_enabled(true)
{
// Add a simple condition and a simple action
m_conditionChain.append(new Condition(Filename, Condition::Contains, TQVariant("")));
m_actionChain.append(new Action(Action::None, TQVariant()));
}
Filters *Filters::m_self = 0;
static KStaticDeleter<Filters> staticFiltersDeleter;
Filters *Filters::self()
{
if (!m_self) {
staticFiltersDeleter.setObject(m_self, new Filters());
}
return m_self;
}
Filters::Filters()
: TQPtrList<Rule>(),
m_enabled(true)
{
setAutoDelete(true);
// Generate human readable strings
m_fieldNames << i18n("Filename");
m_fieldNames << i18n("Entry Type");
m_fieldNames << i18n("Size");
m_actionNames << " ";
m_actionNames << i18n("Change priority");
m_actionNames << i18n("Skip when queuing");
m_actionNames << i18n("Colorize in list view");
m_actionNames << i18n("Hide from list view");
m_actionNames << i18n("Lowercase destination");
// Load the filters
load();
}
Filters::~Filters()
{
if (m_self == this)
staticFiltersDeleter.setObject(m_self, 0, false);
}
void Filters::save()
{
int num = 0;
TDEConfig *config = kapp->config();
config->setGroup("Filters");
config->writeEntry("count", count());
// Remove any existing sections
for (int i = 0; ; i++) {
TQString groupName = TQString("Filter #%1").arg(i);
if (config->hasGroup(groupName))
config->deleteGroup(groupName);
else
break;
}
Filters::ConstIterator le = end();
for (Filters::ConstIterator i = begin(); i != le; ++i, num++) {
const Rule *rule = (*i);
config->setGroup(TQString("Filter #%1").arg(num));
config->writeEntry("name", rule->name());
config->writeEntry("enabled", rule->isEnabled());
// Write conditions
int cnum = 0;
const ConditionChain *conditions = rule->conditions();
config->writeEntry("conditions", conditions->count());
config->writeEntry("conditions-type", (int) conditions->type());
ConditionChain::ConstIterator cle = conditions->end();
for (ConditionChain::ConstIterator j = conditions->begin(); j != cle; ++j, cnum++) {
const Condition *c = (*j);
TQString prefix = TQString("condition%1-").arg(cnum);
config->writeEntry(prefix + "field", (int) c->field());
config->writeEntry(prefix + "type", (int) c->type());
config->writeEntry(prefix + "value", c->value());
config->writeEntry(prefix + "valueType", (int) c->value().type());
}
// Write actions
int anum = 0;
const ActionChain *actions = rule->actions();
config->writeEntry("actions", actions->count());
ActionChain::ConstIterator ale = actions->end();
for (ActionChain::ConstIterator j = actions->begin(); j != ale; ++j, anum++) {
const Action *a = (*j);
TQString prefix = TQString("action%1-").arg(anum);
config->writeEntry(prefix + "type", (int) a->type());
config->writeEntry(prefix + "value", a->value());
config->writeEntry(prefix + "valueType", (int) a->value().type());
}
}
}
void Filters::load()
{
int num = 0;
TDEConfig *config = kapp->config();
config->setGroup("Filters");
num = config->readNumEntry("count");
for (int i = 0; i < num; i++) {
Rule *rule = new Rule();
config->setGroup(TQString("Filter #%1").arg(i));
rule->setName(config->readEntry("name", i18n("Unnamed Rule")));
rule->setEnabled(config->readBoolEntry("enabled", true));
// Read conditions
ConditionChain *conditions = const_cast<ConditionChain*>(rule->conditions());
int cnum = config->readNumEntry("conditions");
conditions->setType((ConditionChain::Type) config->readNumEntry("conditions-type"));
for (int j = 0; j < cnum; j++) {
TQString prefix = TQString("condition%1-").arg(j);
conditions->append(new Condition((Field) config->readNumEntry(prefix + "field"),
(Condition::Type) config->readNumEntry(prefix + "type"),
config->readPropertyEntry(prefix + "value",
(TQVariant::Type) config->readNumEntry(prefix + "valueType"))));
}
// Read actions
ActionChain *actions = const_cast<ActionChain*>(rule->actions());
int anum = config->readNumEntry("actions");
for (int j = 0; j < anum; j++) {
TQString prefix = TQString("action%1-").arg(j);
actions->append(new Action((Action::Type) config->readNumEntry(prefix + "type"),
config->readPropertyEntry(prefix + "value",
(TQVariant::Type) config->readNumEntry(prefix + "valueType"))));
}
append(rule);
}
}
const ActionChain *Filters::process(const KFTPEngine::DirectoryEntry &entry) const
{
if (m_enabled) {
TQPtrList<Rule>::ConstIterator le = end();
for (TQPtrList<Rule>::ConstIterator i = begin(); i != le; ++i) {
const Rule *rule = (*i);
if (rule->isEnabled() && rule->conditions()->matches(entry))
return rule->actions();
}
}
// Nothing has matched
return 0;
}
const Action *Filters::process(const KFTPEngine::DirectoryEntry &entry, TQValueList<Action::Type> types) const
{
const ActionChain *chain = process(entry);
if (!chain || chain->isEmpty())
return 0;
// Find an action that matches the filter
ActionChain::ConstIterator le = chain->end();
for (ActionChain::ConstIterator i = chain->begin(); i != le; ++i) {
if (types.contains((*i)->type()))
return (*i);
}
return 0;
}
const Action *Filters::process(const KFTPEngine::DirectoryEntry &entry, Action::Type filter) const
{
const ActionChain *chain = process(entry);
if (!chain || chain->isEmpty())
return 0;
// Find an action that matches the filter
ActionChain::ConstIterator le = chain->end();
for (ActionChain::ConstIterator i = chain->begin(); i != le; ++i) {
if ((*i)->type() == filter)
return (*i);
}
return 0;
}
const Action *Filters::process(const KURL &url, filesize_t size, bool directory, Action::Type filter) const
{
KFTPEngine::DirectoryEntry entry;
entry.setFilename(url.filename());
entry.setSize(size);
entry.setType(directory ? 'd' : 'f');
return process(entry, filter);
}
const ActionChain *Filters::process(const KURL &url, filesize_t size, bool directory) const
{
KFTPEngine::DirectoryEntry entry;
entry.setFilename(url.filename());
entry.setSize(size);
entry.setType(directory ? 'd' : 'f');
return process(entry);
}
const Action *Filters::process(const KURL &url, Action::Type filter) const
{
return process(url, 0, false, filter);
}
}
}