/* * This file is part of the KFTPGrabber project * * Copyright (C) 2003-2006 by the KFTPGrabber developers * Copyright (C) 2003-2006 Jernej Kos * * 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 #include #include #include #include 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(), m_type(All) { setAutoDelete(true); } ConditionChain::ConditionChain(Type type) : TQPtrList(), m_type(type) { setAutoDelete(true); } bool ConditionChain::matches(const KFTPEngine::DirectoryEntry &entry) const { if (isEmpty()) return false; TQPtrList::ConstIterator le = end(); for (TQPtrList::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() { 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 staticFiltersDeleter; Filters *Filters::self() { if (!m_self) { staticFiltersDeleter.setObject(m_self, new Filters()); } return m_self; } Filters::Filters() : TQPtrList(), 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(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(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::ConstIterator le = end(); for (TQPtrList::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 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); } } }