/***************************************************************************
  begin                : Fri Nov 1 2002
  copyright            : (C) 2002 by Christian Hubinger
  email                : chubinger@gmail.com
***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "kmfruleeditorprotocol.h"

// kde includes
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kapplication.h>

// qt includes
#include <qlayout.h>
#include <qcheckbox.h>
#include <qtabwidget.h>
#include <qstring.h>
#include <qcombobox.h>
#include <qspinbox.h>
#include <qgroupbox.h>

// project includes
#include "../../core/iptruleoption.h"
#include "../../core/iptrule.h"
#include "../../core/iptchain.h"
#include "../../core/iptable.h"
#include "../../core/kmfdoc.h"
#include "../../core/kmfiptdoc.h"

#include "../../kmfwidgets/kmfportwidget.h"
#include "../../kmfwidgets/kmfmultiportwidget.h"

KMFRuleEditorProtocol::KMFRuleEditorProtocol( QWidget *parent, const char *name, WFlags fl ) : KMyFirewallRuleEditorProtocol( parent, name, fl ) {
	use_multiport = false;
	cb_icmp_type->insertItem( "echo-request" );
	cb_icmp_type->insertItem( "echo-reply" );
	cb_icmp_type->insertItem( "source-quench" );
	cb_icmp_type->insertItem( "router-advertisement" );
	cb_icmp_type->insertItem( "router-solicitation" );
	cb_icmp_type->insertItem( "timestamp-request" );
	cb_icmp_type->insertItem( "timestamp-reply" );
	cb_icmp_type->insertItem( "address-mask-request" );
	cb_icmp_type->insertItem( "address-mask-reply" );
	cb_icmp_type->insertItem( "destination-unreachable" );
	cb_icmp_type->insertItem( "network-unreachable" );
	cb_icmp_type->insertItem( "host-unreachable" );
	cb_icmp_type->insertItem( "protocol-unreachable" );
	cb_icmp_type->insertItem( "port-unreachable" );
	cb_icmp_type->insertItem( "fragmentation-needed" );
	cb_icmp_type->insertItem( "source-route-failed" );
	cb_icmp_type->insertItem( "network-unknown" );
	cb_icmp_type->insertItem( "host-unknown" );
	cb_icmp_type->insertItem( "network-prohibited" );
	cb_icmp_type->insertItem( "host-prohibited" );
	cb_icmp_type->insertItem( "TOS-network-unreachable" );
	cb_icmp_type->insertItem( "TOS-host-unreachable" );
	cb_icmp_type->insertItem( "communication-prohibited" );
	cb_icmp_type->insertItem( "host-precedence-violation" );
	cb_icmp_type->insertItem( "precedence-cutoff" );
	cb_icmp_type->insertItem( "redirect" );
	cb_icmp_type->insertItem( "network-redirect" );
	cb_icmp_type->insertItem( "host-redirect" );
	cb_icmp_type->insertItem( "TOS-network-redirect" );
	cb_icmp_type->insertItem( "TOS-host-redirect" );
	cb_icmp_type->insertItem( "time-exceeded" );
	cb_icmp_type->insertItem( "ttl-zero-during-transit" );
	cb_icmp_type->insertItem( "ttl-zero-during-reassembly" );
	cb_icmp_type->insertItem( "parameter-problem" );
	cb_icmp_type->insertItem( "ip-header-bad" );
	cb_icmp_type->insertItem( "required-option-missing" );

	mpwid = new KMFMultiPortWidget( tab_multiport, "mpwid" );
	connect( mpwid, SIGNAL( sigMultiPortChanged( bool ) ), this, SLOT( toggleMultiPort( bool ) ) );

	pw_dest_port = new KMFPortWidget( tab_ports, "pw_dest_port" );
	pw_dest_port->setEnabled( false );
	connect( c_dest_port, SIGNAL( toggled( bool ) ) , pw_dest_port, SLOT( setEnabled( bool ) ) );

	pw_src_port = new KMFPortWidget( tab_ports, "pw_src_port" );
	pw_src_port->setEnabled( false );
	connect( c_src_port, SIGNAL( toggled( bool ) ) , pw_src_port, SLOT( setEnabled( bool ) ) );

	tab_multiportLayout->addMultiCellWidget( mpwid, 0, 0, 2, 2 );
	tab_portsLayout->addWidget( pw_src_port, 1, 1 );
	tab_portsLayout->addWidget( pw_dest_port, 2, 1 );

	connect( c_udp, SIGNAL( toggled( bool ) ), this, SLOT( toggleUdpRule( bool ) ) );
	connect( c_icmp, SIGNAL( toggled( bool ) ), this, SLOT( toggleIcmpRule( bool ) ) );
	connect( c_tcp, SIGNAL( toggled( bool ) ), this, SLOT( toggleTcpRule( bool ) ) );
	tabWidget->setTabEnabled( tab_ports, false );
	tabWidget->setTabEnabled( tab_multiport, false );
	tabWidget->setTabEnabled( tab_icmp, false );
	tabWidget->setTabEnabled( tab_special_tcp, false );

	tabWidget->setEnabled( false );
	adjustSize();
}

KMFRuleEditorProtocol::~KMFRuleEditorProtocol() {}

bool KMFRuleEditorProtocol::multiportEnabled() const {
	return use_multiport;
}

int KMFRuleEditorProtocol::getItemNum( const QString& option ) {
	kdDebug() << "int KMFRuleEditorTos::getItemNum(const QString& option)" << endl;
	int index = -1;
	for ( int i = 0; i < cb_icmp_type->count(); i++ ) {
		QString tmp_item = cb_icmp_type->text( i );
		if ( tmp_item == option ) {
			index = i;
		}
	}
	return index;
}

void KMFRuleEditorProtocol::toggleMultiPort( bool enabled ) {
	kdDebug() << "void KMFRuleEditorProtocol::toggleMultiPort(" << enabled << ")" << endl;
	if ( enabled ) {
		tabWidget->setTabEnabled( tab_ports, false );
		if ( c_tcp->isChecked() )
			tabWidget->setTabEnabled( tab_special_tcp, false );

		use_multiport = true;
	} else {
		tabWidget->setTabEnabled( tab_ports, true );
		if ( c_tcp->isChecked() )
			tabWidget->setTabEnabled( tab_special_tcp, true );

		use_multiport = false;
	}
}

void KMFRuleEditorProtocol::toggleUdpRule( bool enabled ) {
	kdDebug() << "void KMFRuleEditorProtocol::toggleMultiPort(bool)" << endl;
	if ( enabled ) {
		tabWidget->setTabEnabled( tab_ports, true );
		tabWidget->setTabEnabled( tab_multiport, true );
		tabWidget->setTabEnabled( tab_icmp, false );
		tabWidget->setTabEnabled( tab_special_tcp, false );
	} else {
		//    tabWidget->setTabEnabled(tab_ports,true);
		//		tabWidget->setTabEnabled(tab_multi_port,true);
		//		tabWidget->setTabEnabled(tab_special_tcp,true);
	}
}
void KMFRuleEditorProtocol::toggleTcpRule( bool enabled ) {
	kdDebug() << "void KMFRuleEditorProtocol::toggleTcpRule(bool)" << endl;
	if ( enabled ) {
		tabWidget->setTabEnabled( tab_ports, true );
		tabWidget->setTabEnabled( tab_multiport, true );
		tabWidget->setTabEnabled( tab_special_tcp, true );
		tabWidget->setTabEnabled( tab_icmp, false );
	} else {
		//		tabWidget->setTabEnabled(tab_icmp,true);
	}
}

void KMFRuleEditorProtocol::toggleIcmpRule( bool enabled ) {
	kdDebug() << "void KMFRuleEditorProtocol::toggleIcmpRule(bool)" << endl;
	if ( enabled ) {
		tabWidget->setTabEnabled( tab_icmp, true );
		tabWidget->setTabEnabled( tab_special_tcp, false );
		tabWidget->setTabEnabled( tab_ports, false );
		tabWidget->setTabEnabled( tab_multiport, false );
	} else {
		//		tabWidget->setTabEnabled(tab_special_tcp,true);
		//		tabWidget->setTabEnabled(tab_ports,true);
		//    tabWidget->setTabEnabled(tab_multiport,false);
	}
}

void KMFRuleEditorProtocol::loadRule( IPTRule* rule ) {
	kdDebug() << "void KMFRuleEditorProtocol::loadRule(IPTRule* rule)" << endl;
	m_rule = rule;
	toggleMultiPort( false );
	toggleTcpRule( false );
	pw_dest_port->reset();
	pw_dest_port->reset();
	mpwid->reset();
	c_all->setChecked( false );
	c_icmp->setChecked( false );
	c_udp->setChecked( false );
	c_tcp->setChecked( false );
	c_src_port->setChecked( false );
	c_dest_port->setChecked( false );
	c_icmp_type->setChecked( false );
	c_inv_icmp->setChecked( false );
	c_inv_prot->setChecked( false );
	cb_icmp_type->setCurrentItem( 0 );
	c_tcp_flags->setChecked( false );
	c_inv_flags->setChecked( false );
	c_tcp_option->setChecked( false );
	c_inv_tcp_option->setChecked( false );
	sb_tcp_option_num->setValue( 0 );
	c_all_mask->setChecked( false );
	c_none_mask->setChecked( false );
	c_syn_mask->setChecked( false );
	c_ack_mask->setChecked( false );
	c_fin_mask->setChecked( false );
	c_urg_mask->setChecked( false );
	c_rst_mask->setChecked( false );
	c_psh_mask->setChecked( false );
	c_all_comp->setChecked( false );
	c_none_comp->setChecked( false );
	c_syn_comp->setChecked( false );
	c_ack_comp->setChecked( false );
	c_fin_comp->setChecked( false );
	c_urg_comp->setChecked( false );
	c_rst_comp->setChecked( false );
	c_psh_comp->setChecked( false );

	bool finished = false;
	IPTRuleOption* option;
	QStringList vals;
	//################### start multiport options ######################
	option = rule->getOptionForName("tcp_multiport_opt");
	QString enable = "";
	QString src_port = "";
	QString dest_port = "";
	vals = option->getValues();
	enable = "";
	enable = *vals.at(0);
	if ( enable == "bool:on" ) {
		c_tcp->setChecked( true );
		c_udp->setEnabled( false );
		finished =true;
		c_all->setEnabled( false );
		c_icmp->setEnabled( false );
		tabWidget->setEnabled( true );
		toggleMultiPort( true );
		tabWidget->showPage( tab_ports );
	} else {
		option = rule->getOptionForName("udp_multiport_opt");
		vals = option->getValues();
		enable = "";
		enable = *vals.at(0);
		if ( enable == "bool:on" ) {
			c_udp->setChecked( true );
			c_tcp->setEnabled( false );
			finished =true;
			c_all->setEnabled( false );
			c_icmp->setEnabled( false );
			tabWidget->setEnabled( true );
			toggleMultiPort( true );
			tabWidget->showPage( tab_multiport );
		}
	}

	src_port = "";
	dest_port = "";
	QString equ_port = "";
	src_port = *vals.at(1);
	dest_port = *vals.at(2);
	equ_port = *vals.at(3);

	if ( !src_port.isEmpty() &&  src_port != "UNDEFINED" && src_port != "bool:off")  {
		mpwid->setType( "src" );
		mpwid->loadPortString( src_port );
		kdDebug() << "Option Value -sport: " << src_port << endl;
	}
	if ( !dest_port.isEmpty() &&  dest_port != "UNDEFINED"  && dest_port != "bool:off" ) {
		mpwid->setType( "dest" );
		mpwid->loadPortString( dest_port );
		kdDebug() << "Option Value -sport: " << dest_port << endl;
	}
	if ( !equ_port.isEmpty() &&  equ_port != "UNDEFINED"  && equ_port != "bool:off" ) {
		mpwid->setType( "equ" );
		mpwid->loadPortString( equ_port );
		kdDebug() << "Option Value -sport: " << equ_port << endl;
	}
	if (finished)
		return;


	//################# start tcp options #########################
	option = rule->getOptionForName("tcp_opt");
	vals = option->getValues();
	QString flags = "";
	QString tcp_option = "";
	enable = *vals.at(0);
	src_port = *vals.at(1);
	dest_port = *vals.at(2);
	flags = *vals.at(3);
	tcp_option = *vals.at(4);
	if ( enable  == "bool:on" ) {
		toggleMultiPort( false );
		toggleTcpRule( true );
		c_tcp->setChecked( true );
		c_all->setEnabled( false );
		c_udp->setEnabled( false );
		c_icmp->setEnabled( false );
		tabWidget->setEnabled( true );
		finished = true;
		tabWidget->showPage( tab_ports );
	}
	if ( !src_port.isEmpty() &&  src_port != "UNDEFINED" && src_port != "bool:off")  {
		kdDebug() << "Option Value -sport: " << src_port << endl;
		c_src_port->setChecked( true );
		pw_src_port->loadPortString( src_port );
	}
	if ( !dest_port.isEmpty() &&  dest_port != "UNDEFINED"  && dest_port != "bool:off" ) {
		kdDebug() << "Option Value -dport: " << dest_port << endl;
		c_dest_port->setChecked( true );
		pw_dest_port->loadPortString( dest_port );
	}
	if ( !flags.isEmpty() &&  flags != "UNDEFINED" && flags != "bool:off"  ) {
		kdDebug() << "Option Value --tcp-flags: " << flags << endl;
		gb_mask->setEnabled( true );
		gb_comp->setEnabled( true );
		c_tcp_flags->setChecked( true );
		int delim = flags.find( " " );
		if ( flags.startsWith( "! " ) ) {
			c_inv_flags->setChecked( true );
			flags = flags.right( flags.length() - 2 );
		}
		delim = flags.find( " " );
		kdDebug() << "found Whitespace at " << delim << endl;
		QString mask_lst = flags.left( delim );
		kdDebug() << "Flags for Mask: " << mask_lst << endl;
		QString comp_lst = flags.right( flags.length() - delim );
		kdDebug() << "Flags for Comp: " << comp_lst << endl;

		if ( mask_lst.contains( "SYN" ) > 0 )
			c_syn_mask->setChecked( true );
		if ( mask_lst.contains( "ACK" ) > 0 )
			c_ack_mask->setChecked( true );
		if ( mask_lst.contains( "FIN" ) > 0 )
			c_fin_mask->setChecked( true );
		if ( mask_lst.contains( "RST" ) > 0 )
			c_rst_mask->setChecked( true );
		if ( mask_lst.contains( "URG" ) > 0 )
			c_urg_mask->setChecked( true );
		if ( mask_lst.contains( "PSH" ) > 0 )
			c_psh_mask->setChecked( true );
		if ( mask_lst.contains( "NONE" ) > 0 )
			c_none_mask->setChecked( true );
		if ( mask_lst.contains( "ALL" ) > 0 )
			c_all_mask->setChecked( true );

		if ( comp_lst.contains( "SYN" ) > 0 )
			c_syn_comp->setChecked( true );
		if ( comp_lst.contains( "ACK" ) > 0 )
			c_ack_comp->setChecked( true );
		if ( comp_lst.contains( "FIN" ) > 0 )
			c_fin_comp->setChecked( true );
		if ( comp_lst.contains( "RST" ) > 0 )
			c_rst_comp->setChecked( true );
		if ( comp_lst.contains( "URG" ) > 0 )
			c_urg_comp->setChecked( true );
		if ( comp_lst.contains( "PSH" ) > 0 )
			c_psh_comp->setChecked( true );
		if ( comp_lst.contains( "NONE" ) > 0 )
			c_none_comp->setChecked( true );
		if ( comp_lst.contains( "ALL" ) > 0 )
			c_all_comp->setChecked( true );
	}
	if ( !tcp_option.isEmpty() &&  tcp_option != "UNDEFINED" && tcp_option != "bool:off"  ) {
		kdDebug() << "Option Value --tcp-options: " << tcp_option << endl;
		c_tcp_option->setChecked( true );
		sb_tcp_option_num->setEnabled( true );
		if ( tcp_option.startsWith( "! " ) ) {
			c_inv_tcp_option->setChecked( true );
			tcp_option = tcp_option.right( tcp_option.length() - 2 );
		}
		int val = tcp_option.toInt();
		sb_tcp_option_num->setValue( val );

	}

	// Return if tcp option was used
	if (finished)
		return;
	//################# start udp options #########################
	option = rule->getOptionForName("udp_opt");
	vals = option->getValues();
	enable = "";
	src_port = "";
	dest_port = "";
	enable = *vals.at(0);
	src_port = *vals.at(1);
	dest_port = *vals.at(2);

	if ( enable == "bool:on" ) {
		finished =true;
		toggleMultiPort( false );
		c_udp->setChecked( true );
		c_all->setEnabled( false );
		c_tcp->setEnabled( false );
		c_icmp->setEnabled( false );
		tabWidget->setEnabled( true );
		toggleUdpRule( true );
		tabWidget->showPage( tab_ports );
	}

	if ( !src_port.isEmpty() &&  src_port != "UNDEFINED" && src_port != "bool:off")  {
		kdDebug() << "Option Value -sport: " << src_port << endl;
		c_src_port->setChecked( true );
		pw_src_port->loadPortString( src_port );
	}
	if ( !dest_port.isEmpty() &&  dest_port != "UNDEFINED"  && dest_port != "bool:off" ) {
		kdDebug() << "Option Value -dport: " << dest_port << endl;
		c_dest_port->setChecked( true );
		pw_dest_port->loadPortString( dest_port );
	}
	if (finished)
		return;
	//################# start icmp options #########################
	option = rule->getOptionForName("icmp_opt");
	vals = option->getValues();
	enable = "";
	QString type =  "";
	enable = *vals.at(0);
	type = *vals.at(1);

	if ( enable == "bool:on" ) {
		c_icmp->animateClick();
		if ( type != "UNDEFINED" && !type.isEmpty() ) {
			if ( type.startsWith( "! " ) ) {
				c_inv_icmp->setChecked( true );
				type = type.right( type.length() - 2 );
			}
			int index = getItemNum( type );
			c_icmp_type->setChecked( true );
			if ( index > 0 ) {
				cb_icmp_type->setCurrentItem( index );
			}
			tabWidget->showPage( tab_icmp );
		}
	}

// 			if ( *opt == "all_prot" ) {
// 				c_all->animateClick();
// 			}
// 			if ( *opt == "icmp" ) {
// 				c_icmp->animateClick();
// 				for ( uint i = 0;i < options->count();i++ ) {
// 					kdDebug() << "OPTION VALUE: " << *options->at( i ) << endl;
// 					if ( i == 1 ) {
// 						QString cmd = *options->at( i );
// 						kdDebug() << "Option Value -sport: " << cmd << endl;
// 						if ( cmd.startsWith( "! " ) ) {
// 							c_inv_icmp->setChecked( true );
// 							cmd = cmd.right( cmd.length() - 2 );
// 						}
// 						c_icmp_type->setChecked( true );
// 						cb_icmp_type->setEditText( cmd );
// 					}
// 				}
// 			}
}

void KMFRuleEditorProtocol::accept() {
	kdDebug() << "void KMFRuleEditorProtocol::accept()" << endl;
	m_rule->chain()->table()->kmfDoc()->startTransaction();
	m_rule->saveState();

	///////////////////////////////////////////////////////
	// set options ++++++++++++++++++++++++++++++++++++++++
	QString* tcp_multiport_name = new QString("tcp_multiport_opt");
	QString* udp_multiport_name = new QString("udp_multiport_opt");
	QString* tcp_name = new QString("tcp_opt");
	QString* udp_name = new QString("udp_opt");
	QString* icmp_name = new QString("icmp_opt");
	QString* all_name = new QString("all_prot_opt");
	QPtrList<QString>* empty_opt = new QPtrList<QString>;
	empty_opt->append( new QString("bool:off") ); 
	emit sigAddRuleOpt( tcp_multiport_name, empty_opt );
	emit sigAddRuleOpt( udp_multiport_name, empty_opt );
	emit sigAddRuleOpt( tcp_name, empty_opt );
	emit sigAddRuleOpt( udp_name, empty_opt );
	emit sigAddRuleOpt( icmp_name, empty_opt );
	emit sigAddRuleOpt( all_name, empty_opt );

	if ( multiportEnabled() ) {
		kdDebug() << "You like a Multiport Rule" << endl;
		QPtrList<QString>* options = new QPtrList<QString>;
		QString *s = new QString( "" );
		mpwid->getPortString( s );
		QString src = *s;
		kdDebug() << "Found Multiport:" << src << endl;
		if ( !src.isEmpty() ) {
			QString type = "";
			type = mpwid->type();
			QString* opt = new QString( src );
			options->append( new QString("bool:on") );
			if ( type == "src" ) {
				options->append( new QString( src ) );
			} else if ( type == "dest" ) {
				options->append( new QString("bool:off") );
				options->append( new QString( src ) );
			} else if ( type == "equ" ) {
				options->append( new QString("bool:off") );
				options->append( new QString("bool:off") );
				options->append( new QString( src ) );
			}
			kdDebug() << "Found Option Type: " << *opt << endl;
		}
		if ( c_tcp->isChecked() ) {
			emit sigAddRuleOpt( tcp_multiport_name, options );
			options->clear();
			m_rule->chain()->table()->kmfDoc()->endTransaction();
			emit sigHideMe();

		} else if ( c_udp->isChecked() ) {
			emit sigAddRuleOpt( udp_multiport_name, options );
			options->clear();
			m_rule->chain()->table()->kmfDoc()->endTransaction();
			emit sigHideMe();
		}
	}


	if ( c_tcp->isChecked() ) {
		kdDebug() << "You like a TCP Rule" << endl;
		QPtrList<QString>* options = new QPtrList<QString>;
		options->append( new QString( "bool:on" ) );
		QString src = "";
		QString dest = "";
		QString flags = "";
		QString tcp_option = "";

		if ( c_src_port->isChecked() ) {
			QString * s = new QString( "" );
			pw_src_port->getPortString( s );
			if ( !s->isEmpty() )
				src = *s;
			if ( src.isEmpty() ) {
				m_rule->chain()->table()->kmfDoc()->endTransaction();
				return ;
			}
		}
		if ( c_dest_port->isChecked() ) {
			QString * s = new QString( "" );
			pw_dest_port->getPortString( s );
			if ( !s->isEmpty() )
				dest = *s;
			if ( dest.isEmpty() ) {
				m_rule->chain()->table()->kmfDoc()->endTransaction();
				return ;
			}
		}
		if ( c_tcp_flags->isChecked() ) {
			if ( c_inv_flags->isChecked() ) {
				flags.prepend( "! " );
			}
			QString mask = "";
			if ( ( c_all_comp->isChecked() || c_none_comp->isChecked() || c_syn_comp->isChecked() || c_fin_comp->isChecked() || c_ack_comp->isChecked() || c_rst_comp->isChecked() || c_urg_comp->isChecked() || c_psh_comp->isChecked() ) &&
					( c_all_mask->isChecked() || c_none_mask->isChecked() || c_syn_mask->isChecked() || c_fin_mask->isChecked() || c_ack_mask->isChecked() || c_rst_mask->isChecked() || c_urg_mask->isChecked() || c_psh_mask->isChecked() ) ) {
				if ( c_all_mask->isChecked() )
					mask.append( "ALL" );
				if ( c_none_mask->isChecked() )
					mask.append( "NONE" );
				if ( !c_all_mask->isChecked() && !c_none_mask->isChecked() ) {
					if ( c_syn_mask->isChecked() )
						mask.append( ",SYN" );
					if ( c_fin_mask->isChecked() )
						mask.append( ",FIN" );
					if ( c_ack_mask->isChecked() )
						mask.append( ",ACK" );
					if ( c_rst_mask->isChecked() )
						mask.append( ",RST" );
					if ( c_psh_mask->isChecked() )
						mask.append( ",PSH" );
					if ( c_urg_mask->isChecked() )
						mask.append( ",URG" );
					if ( mask.startsWith( "," ) )
						mask = mask.right( mask.length() - 1 );
				}
				QString comp = "";
				if ( c_all_comp->isChecked() )
					comp.append( "ALL" );
				if ( c_none_comp->isChecked() )
					comp.append( "NONE" );
				if ( !c_all_comp->isChecked() && !c_none_comp->isChecked() ) {
					if ( c_syn_comp->isChecked() )
						comp.append( ",SYN" );
					if ( c_fin_comp->isChecked() )
						comp.append( ",FIN" );
					if ( c_ack_comp->isChecked() )
						comp.append( ",ACK" );
					if ( c_rst_comp->isChecked() )
						comp.append( ",RST" );
					if ( c_psh_comp->isChecked() )
						comp.append( ",PSH" );
					if ( c_urg_comp->isChecked() )
						comp.append( ",URG" );
				}

				if ( comp.startsWith( "," ) )
					comp = comp.right( comp.length() - 1 );
				flags.append( mask );
				flags.append( " " );
				flags.append( comp );
			} else {
				KMessageBox::sorry( this, i18n( "<qt><p>You need to select the TCP flags you like to "
												"check and those your rule should match.</qt>" ) );

				m_rule->chain()->table()->kmfDoc()->endTransaction();
				return ;
			}
		}
		if ( c_tcp_option->isChecked() ) {
			tcp_option = sb_tcp_option_num->text();
			if ( c_inv_tcp_option->isChecked() ) {
				tcp_option.prepend( "! " );
			}
		}

//		if ( !src.isEmpty() || ! dest.isEmpty() || ! flags.isEmpty() || ! tcp_option.isEmpty() ) {
//			options->append( new QString("bool:on") );
			if ( src.isEmpty() )
				src = "bool:off";
			options->append( new QString( src )  );
			if ( dest.isEmpty()  )
				dest = "bool:off";
			options->append( new QString( dest )  );
			if ( flags.isEmpty() )
				flags = "bool:off";
			options->append( new QString( flags )  );
			if ( tcp_option.isEmpty() )
				tcp_option = "bool:off";
			options->append( new QString( tcp_option )  );
//		}
		emit sigAddRuleOpt( tcp_name, options );
	}
	//////////////////////////////////////////////////////////////////
	// start udp options
	if ( c_udp->isChecked() ) {
		kdDebug() << "You like a UDP Rule" << endl;
		QPtrList<QString>* options = new QPtrList<QString>;
		QString src = "";
		QString dest = "";
		options->append( new QString( "bool:on" ) );

		if ( c_src_port->isChecked() ) {
			QString * s = new QString( "" );
			pw_src_port->getPortString( s );
			if ( !s->isEmpty() )
				src = *s;
			if ( src.isEmpty() ) {
				m_rule->chain()->table()->kmfDoc()->endTransaction();
				return ;
			}
		}
		if ( c_dest_port->isChecked() ) {
			QString * s = new QString( "" );
			pw_dest_port->getPortString( s );
			if ( !s->isEmpty() )
				dest = *s;
			if ( dest.isEmpty() ) {
				m_rule->chain()->table()->kmfDoc()->endTransaction();
				return ;
			}
		}
		if ( !src.isEmpty() || !dest.isEmpty() ) {
//			options->append( new QString("bool:on") );
			if ( src.isEmpty() )
				src = "bool:off";
			options->append( new QString( src ) );
			if ( dest.isEmpty() )
				dest = "bool:off";
			options->append( new QString( dest ) );
		}

		emit sigAddRuleOpt( udp_name, options );
		options->clear();
	}

	if ( c_icmp->isChecked() ) {
		kdDebug() << "You like a ICMP Rule" << endl;
		QPtrList<QString>* options = new QPtrList<QString>;
		QString* opt = new QString( "" );
		if ( c_icmp_type->isChecked() ) {
			opt = new QString( cb_icmp_type->currentText() );
			if ( c_inv_icmp->isChecked() ) {
				opt->prepend( "! " );
			}
		}
		options->append( new QString("bool:on") );
		options->append( opt );
		emit sigAddRuleOpt( icmp_name, options );
		options->clear();
	}

	if ( c_all->isChecked() ) {
		kdDebug() << "You like an ALL Rule" << endl;
		QPtrList<QString>* options = new QPtrList<QString>;
		options->append( new QString("bool:on") );
		emit sigAddRuleOpt( all_name, options );
		options->clear();
	}

	m_rule->chain()->table()->kmfDoc()->endTransaction();
	emit sigHideMe();
}

void KMFRuleEditorProtocol::slotHelp() {
	kapp->invokeHelp( "protocol" );
}
void KMFRuleEditorProtocol::reject() {
	emit sigHideMe();
}

#include "kmfruleeditorprotocol.moc"
