Source file: src/filter_rules.cpp
/* Copyright (C) 2004-2011 Daniel Verite
This file is part of Manitou-Mail (see http://www.manitou-mail.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "filter_rules.h"
#include "db.h"
#include "sqlstream.h"
#include "users.h"
#include "tags.h"
filter_expr::filter_expr() : m_dirty(false), m_delete(false), m_new(false)
{
m_expr_id=0;
m_apply_order=0;
m_direction='I';
}
filter_expr::~filter_expr()
{
}
filter_action::filter_action()
{
m_action_order=0;
}
filter_action::~filter_action()
{
}
QString
filter_action::ui_text() const
{
QString s;
if (m_str_atype=="tag") {
s = QObject::tr("Assign the tag: %1").arg(m_action_arg);
}
else if (m_str_atype=="redirect") {
s = QObject::tr("Redirect message to: %1").arg(m_action_arg);
}
else if (m_str_atype=="status") {
QStringList display_status;
QStringList l=m_action_arg.split('+', QString::KeepEmptyParts);
for (QStringList::Iterator it=l.begin(); it!=l.end(); ++it) {
char c=(*it).at(0).toAscii();
switch(c) {
case 'R':
display_status.append(QObject::tr("Read"));
break;
case 'T':
display_status.append(QObject::tr("Trashed")); // obsolete
break;
case 'A':
display_status.append(QObject::tr("Archived"));
break;
case 'F':
display_status.append(QObject::tr("Forwarded"));
break;
case 'D':
display_status.append(QObject::tr("Deleted")); // obsolete
break;
}
}
s = QObject::tr("Set status to %1").arg(display_status.join(","));
}
else if (m_str_atype=="priority") {
if (m_action_arg.at(0)=='=') {
s = QObject::tr("Set priority to %1").arg(m_action_arg.mid(1).toInt());
}
else if (m_action_arg.mid(0,2)=="+=") {
int p=m_action_arg.mid(2).toInt();
if (p>=0)
s = QObject::tr("Add %1 to priority").arg(p);
else
s = QObject::tr("Subtract %1 from priority").arg(-p);
}
}
else if (m_str_atype=="discard") {
if (m_action_arg=="trash")
s = QObject::tr("Move to the trash can");
else
s = QObject::tr("Delete message");
}
else if (m_str_atype=="stop") {
s = QObject::tr("Stop filters");
}
else if (m_str_atype=="set header") {
s = QObject::tr("Set header: unable to decode action");
QRegExp rx("^([^:]+):(set|prepend|append) (.*)");
int pos = rx.indexIn(m_action_arg);
if (pos>-1) {
QString op=rx.cap(2);
if (op=="set")
s = QObject::tr("Set header field %1 to %2").arg(rx.cap(1)).arg(rx.cap(3));
else if (op=="prepend")
s = QObject::tr("Prepend \"%2\" to header field %1").arg(rx.cap(1)).arg(rx.cap(3));
else if (op=="append")
s = QObject::tr("Append \"%2\" to header field %1").arg(rx.cap(1)).arg(rx.cap(3));
}
else {
QStringList list = m_action_arg.split(':');
if (list.size()==2) {
s = QObject::tr("Set header field %1 to %2").arg(list.at(0)).arg(list.at(1));
}
}
}
else if (m_str_atype=="remove header") {
s = QObject::tr("Remove header field %1").arg(m_action_arg);
}
else if (m_str_atype=="set identity") {
s = QObject::tr("Set identity to %1").arg(m_action_arg);
}
return s;
}
void
filter_action::set_action_string_from_db(const QString arg)
{
if (m_str_atype=="tag") {
m_action_arg = message_tag::convert_separator_from_ascii(arg);
}
else
m_action_arg = arg;
}
QString
filter_action::action_string_to_db()
{
if (m_str_atype=="tag") {
return message_tag::convert_separator_to_ascii(m_action_arg);
}
else
return m_action_arg;
}
expr_list::expr_list()
{
}
expr_list::~expr_list()
{
}
bool
expr_list::fetch()
{
bool result=true;
db_cnx db;
try {
filter_expr* current=NULL;
QString action_type, action_args, tmp, sdate;
int expr_id;
sql_stream s("SELECT fe.expr_id, fe.name, fe.expression, fe.direction, fe.apply_order, to_char(fe.last_hit, 'YYYYMMDDHH24MISS'), action_type,action_arg FROM filter_action fa RIGHT JOIN filter_expr fe ON fe.expr_id=fa.expr_id ORDER BY fe.apply_order,action_order", db);
while (!s.eos()) {
s >> expr_id;
if (!current || current->m_expr_id != expr_id) {
// new expr
filter_expr e;
e.m_expr_id = expr_id;
push_back(e);
current = &(back());
s >> current->m_expr_name >> current->m_expr_text >> current->m_direction >> current->m_apply_order >> sdate;
current->m_last_hit = date(sdate);
}
else {
char c;
float order;
s >> tmp >> tmp >> c >> order >> tmp;
}
s >> action_type >> action_args;
if (!action_type.isEmpty()) {
filter_action a;
a.m_str_atype = action_type;
a.set_action_string_from_db(action_args);
current->m_actions.push_back(a);
}
}
}
catch(db_excpt& p) {
DBEXCPT(p);
result=false;
}
return result;
}
bool
expr_list::needs_save()
{
std::list<filter_expr>::iterator it = begin();
for (; it != end(); ++it) {
if (!it->m_expr_id && !it->m_delete)
return true;
if (it->m_delete || it->m_dirty)
return true;
}
return false;
}
bool
expr_list::update_db()
{
bool result=true;
db_cnx db;
try {
db.begin_transaction();
sql_stream s_upd("UPDATE filter_expr SET name=:name,expression=:expr, user_lastmod=:user, last_update=now(),direction=':d',apply_order=:a WHERE expr_id=:id", db);
sql_stream s_del_expr("DELETE FROM filter_expr WHERE expr_id=:id", db);
sql_stream s_ins("INSERT INTO filter_expr(expr_id,name,expression,direction,apply_order) VALUES (:id,:name,:expr,':dir',:a)", db);
// TODO: use a sequence
sql_stream s_seq("SELECT nextval('seq_filter_expr_id')", db, false);
sql_stream s_del_act("DELETE FROM filter_action WHERE expr_id=:p1", db);
sql_stream s_add_act("INSERT INTO filter_action(expr_id,action_arg,action_type,action_order) VALUES(:p1,:p2,:p3,:p4)", db);
std::list<filter_expr>::iterator itd = begin();
for (; itd != end(); ++itd) {
if (itd->m_expr_id>0 && itd->m_delete) {
s_del_act << itd->m_expr_id;
s_del_expr << itd->m_expr_id;
}
}
std::list<filter_expr>::iterator it = begin();
for (; it != end(); ++it) {
unsigned int db_expr_id=it->m_expr_id;
if (!db_expr_id) {
if (!it->m_delete) {
s_seq.execute();
s_seq >> db_expr_id;
s_ins << db_expr_id;
if (it->m_expr_name.isEmpty())
s_ins << sql_null();
else
s_ins << it->m_expr_name;
s_ins << it->m_expr_text << it->m_direction << it->m_apply_order;
}
// else ignore the entry: it has been created then deleted.
}
if (it->m_dirty && !it->m_delete) {
if (it->m_expr_name.isEmpty())
s_upd << sql_null();
else
s_upd << it->m_expr_name;
s_upd << it->m_expr_text << user::current_user_id() << it->m_direction << it->m_apply_order << db_expr_id;
// on update, delete all old actions and insert the new ones below
s_del_act << db_expr_id;
}
// insert actions
if ((it->m_dirty || it->m_expr_id==0) && !it->m_delete) {
int aorder=1;
QList<filter_action>::iterator ait;
for (ait=it->m_actions.begin(); ait!=it->m_actions.end(); ++ait) {
s_add_act << db_expr_id << ait->action_string_to_db();
s_add_act << ait->m_str_atype << aorder++;
}
}
} // for each expr
db.commit_transaction();
}
catch(db_excpt& p) {
db.rollback_transaction();
DBEXCPT(p);
result=false;
}
return result;
}
const filter_expr*
expr_list::find_name(const QString& name) const
{
std::list<filter_expr>::const_iterator it = begin();
for (; it != end(); ++it) {
if ((*it).m_expr_name == name)
return &(*it);
}
return NULL;
}
float
expr_list::max_apply_order() const
{
float m=0;
std::list<filter_expr>::const_iterator it = begin();
for (; it != end(); ++it) {
if ((*it).m_apply_order > m)
m=(*it).m_apply_order;
}
return m;
}
HTML source code generated by GNU Source-Highlight plus some custom post-processing
List of all available source files