#include "fireflier_client.h"
#include "sourceform.h"
#include "rules_dialog.h"
#include "fireflier_indep.h"
#include "login_dialog.h"
#include "about_dialog.h"
#include "error_dialog.h"
#ifdef WITH_KDE
  #include "traywidget.h"
  #include <kwin.h>
  #include <kapplication.h>
  #include <kaboutdata.h>
  #include <kcmdlineargs.h>
#endif

#include <iostream>
#include <fstream>
#include <pthread.h>
#include <qapplication.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qlabel.h>
#include <qcombobox.h>
#include <qradiobutton.h>
#include <qtextedit.h>
#include <qthread.h>
#include <qlistbox.h>
#include <netdb.h>
#include <qlineedit.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#ifdef WITH_KDE
  #include <kstatusbar.h>
#else
  #include <qstatusbar.h>
#endif

#include "getservice.h"

#include <stdlib.h>

using namespace std;

#define FF_DEBUG 0

char *ICMP_TYPES[]={"ECHO_REPLY", "UNKNOWN", "UNKNOWN", "DEST_UNREACH", "SOURCE_QUENCH",
"REDIRECT", "UNKNOWN", "UNKNOWN", "ECHO", "UNKNOWN", "UNKNOWN",
"TIME_EXCEEDED", "PARAMETERPROB", "TIMESTAMP", "TIMESTAMP_REPLY",
"INFO_REQUEST", "INFO_REPLY", "ADDRESS", "ADDRESS_REPLY"};

void sendSourceRequest();
void sendUSRulesRequest();
void sendIPTRulesRequest();
void sendUSdelCmd(int rulenum);
void sendIPTdelCmd(int chain, int rulenum);
int sendLogin(const char *username, const char *password);
extern int authenticated;
extern int connected;

fireflier_client *cl;

#ifdef WITH_KDE
    KApplication *kApp;
#else
    QApplication *kApp;
#endif

rules_dialog *usr_rules;
rules_dialog *ipt_rules;
char *sourceText;
int cmdnum;
bool popup;
int thrfinish=0; // set to 1 to finish threads
#ifdef WITH_KDE
    traywidget *tray;
#endif

class ResolverThread : public QThread {
    char res_src[16], res_dst[16];
public:
    ResolverThread();
    void resolve(char *src, char *dest);
    void run();
};

ResolverThread::ResolverThread()
{
    res_src[0]=0;
    res_dst[0]=0;
}

void ResolverThread::resolve(char *src, char *dest)
{
    strncpy(res_src, src, 16);
    strncpy(res_dst, dest, 16);
}

void *networkThread(void *clientParameter);



void setSrcName(char *name);
void setDstName(char *name);
ResolverThread rst;

void ResolverThread::run()
{
    char src[16], dst[16];
    struct hostent *he;
    struct in_addr addr;

    while (!thrfinish)
    {
	while ((res_src[0]==0) && (!thrfinish))
	    sleep(1);
        if (thrfinish) return;
        strcpy(src, res_src);
        strcpy(dst, res_dst);
        if (FF_DEBUG)
	    cout << "Resolving: " << src << endl;;
        inet_aton(src, &addr);
	he=gethostbyaddr(&addr, sizeof(struct in_addr), AF_INET);
	if (he)
	{
	    if (!strcmp(src, res_src) && (res_src[0]))
	    {
                if (FF_DEBUG)
		    cout << "Resolved: " << he->h_name << endl;
		setSrcName(he->h_name);
                res_src[0]=0;
	    }
	    else
                setSrcName("");
	}
	else
	{
	    setSrcName("not resolvable");
	    res_src[0]=0;
	}
        if (FF_DEBUG)
	    cout << "Resolving: " << dst << endl;
        inet_aton(dst, &addr);
	he=gethostbyaddr(&addr, sizeof(struct in_addr), AF_INET);
	if (he)
	{
	    if (!strcmp(dst, res_dst) && (res_dst[0]))
	    {
		setDstName(he->h_name);
                if (FF_DEBUG)
		    cout << "Resolved: " << he->h_name << endl;
                res_dst[0]=0;
	    }
	    else
                setDstName("");
	}
	else
	{
	    setDstName("not resolvable");
	    res_dst[0]=0;
	}

    }
}

void lockApplication()
{
#ifdef WITH_KDE
	kApp->lock();
#else
	qApp->lock();
#endif
}

void unlockApplication()
{
#ifdef WITH_KDE
	kApp->unlock();
#else
	qApp->unlock();
#endif
}



void setSrcName(char *name)
{
    char temp[100];
    lockApplication();

    if (strlen(name)<90)
    {
        sprintf(temp, "hostname=%s",name);
	cl->label_ip_src->setText(temp);
    }
    else
	cl->label_ip_src->setText(name);
    unlockApplication();
}

void setDstName(char *name)
{
    char temp[100];
    lockApplication();
    if (strlen(name)<90)
    {
        sprintf(temp, "hostname=%s",name);
	cl->label_ip_dst->setText(temp);
    }
    else
	cl->label_ip_dst->setText(name);
    unlockApplication();
}

class NWThread : public QThread {
public:
    unsigned char hostip[4];
    int port;
    void run();
};

void NWThread::run()
{
    unsigned char param[6];
    memcpy(param, hostip, 4);
    param[4]=port&255;
    param[5]=port>>8;
    networkThread((void*)param);
    if (FF_DEBUG)
	cout << "no connection" << endl;
    lockApplication();
    kApp->exit(1);
    unlockApplication();
}


/*
 *  Constructs a fireflier_client which is a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'
 */
#ifdef WITH_KDE
fireflier_client::fireflier_client( QWidget* parent,  const char* name, WFlags fl ) : fireflier_main( )
#else
fireflier_client::fireflier_client( QWidget* parent,  const char* name, WFlags fl ) : fireflier_main( parent, name, fl )
#endif
{
    packetAvailable=0;
}

/*
 *  Destroys the object and frees any allocated resources
 */
fireflier_client::~fireflier_client()
{
    // no need to delete child widgets, Qt does it all for us
}

#ifdef WITH_KDE
void fireflier_client::closeEvent( QCloseEvent* ce )
{
    ce->ignore();
    this->hide();
}
#endif

/*
 * public slot
 */
void fireflier_client::fileExit()
{
    exit(0);
}

void view_error(char *msg)
{
	error_dialog *errdia;
	errdia=new error_dialog();
	errdia->error_msg->setText(msg);
	errdia->exec();
}

char *HEX="0123456789ABCDEF";

char *format_source(char *src, int len)
{
    char *result=new char[len*8];
    int i, pos=0;

    if (!src) return "";

    result[0]=0;

    while (pos<len)
    {
	for (i=0;i<16;i++)
	{
	    if (i==8)
                strcat(result, "  ");
	    else if (i%4==0)
                strcat(result, " ");
	    if (i+pos<len)
	    {
		result[strlen(result)+2]=0;
		result[strlen(result)+1]=HEX[((unsigned char*)src)[i+pos]&15];
		result[strlen(result)]=HEX[((unsigned char*)src)[i+pos]>>4];
                strcat(result, " ");
	    }
	    else
                strcat(result, "   ");
	}
        strcat(result, "   ");
	for (i=0;i<16;i++)
	{
	    if (i==8)
                strcat(result, "  ");
	    else if (i%4==0)
                strcat(result, " ");

	    if ((i+pos<len) && (src[i+pos]>=32))
	    {
                result[strlen(result)+1]=0;
		result[strlen(result)]=src[i+pos];
	    }
	    else if (i+pos<len)
                strcat(result, ".");
	}
	pos+=16;
        strcat(result, "\n");
    }
    return result;
}

void view_source_received(char *source, int len)
{
    char *formatted;
    source[len]=0;
    formatted=format_source(source, len);
    for (int i=0;formatted[i]!=0;i++)
    {
        if (FF_DEBUG)
	    cout << (int)formatted[i] << " ";
    }
    if (FF_DEBUG)
	cout << endl;
    sourceText=formatted;
}
/*
 * public slot
 */
void fireflier_client::view_source()
{
    if (packetAvailable)
    {
	Sourceform *sf=new Sourceform(this, "View source", true);
	sendSourceRequest();
	while (!sourceText) ; // FIX THIS
	lockApplication();
        sf->source->setText(sourceText);
	sf->exec();
	unlockApplication();
	delete(sourceText);
	sourceText=0;
        delete(sf);
    }
}


void view_iptables_received(char *buffer, int len)
{
    char *temp;
    char *pos, *endpos;
    char line[200];

    temp=new char[len+1];
    memcpy(temp, buffer, len);
    endpos=pos=temp;

    lockApplication();
    ipt_rules->iptables_list->clear();
    unlockApplication();

    while (endpos && (endpos<temp+strlen(temp))) {
	endpos=(char*)memchr(pos, '\n', strlen(temp)-(pos-temp));
	if (endpos && (endpos<temp+strlen(temp)))
	{
	    memcpy(line, pos, endpos-pos);
	    line[endpos-pos]=0;
            lockApplication();
	    ipt_rules->iptables_list->insertItem(line);
	    unlockApplication();
            if (FF_DEBUG)
		cout << "::" << line << endl;
	}
	pos=endpos+1;
    }
    delete(temp);
}

void fireflier_client::view_iptables()
{
    if (!ipt_rules)
    {
	ipt_rules=new rules_dialog();
	connect(ipt_rules->delete_rule , SIGNAL( clicked() ), this, SLOT( del_iptrule_clicked() ) );
	ipt_rules->show();
    }
    else if (!ipt_rules->isVisible())
    {
	lockApplication();
	ipt_rules->iptables_list->clear();
	unlockApplication();
	ipt_rules->show();
    }
    sendIPTRulesRequest();
}

void view_userspace_received(char *buffer, int len)
{
    char *temp;
    char *pos, *endpos;
    char line[200];

    temp=new char[len+1];
    memcpy(temp, buffer, len);
    endpos=pos=temp;

    lockApplication();
    usr_rules->iptables_list->clear();
    unlockApplication();

    while (endpos && (endpos<temp+strlen(temp))) {
	endpos=(char*)memchr(pos, '\n', strlen(temp)-(pos-temp));
	if (endpos && (endpos<temp+strlen(temp)))
	{
	    memcpy(line, pos, endpos-pos);
	    line[endpos-pos]=0;
            lockApplication();
	    usr_rules->iptables_list->insertItem(line);
	    unlockApplication();
            if (FF_DEBUG)
		cout << "::" << line << endl;
	}
	pos=endpos+1;
    }
    delete(temp);
}

void fireflier_client::view_userspace()
{
    if (!usr_rules)
    {
	usr_rules=new rules_dialog();
	connect(usr_rules->delete_rule , SIGNAL( clicked() ), this, SLOT( del_usrule_clicked() ) );
	usr_rules->show();
    }
    else if (!usr_rules->isVisible())
    {
	lockApplication();
        usr_rules->iptables_list->clear();
	unlockApplication();
	usr_rules->show();
    }
    sendUSRulesRequest();
}

void fireflier_client::helpAbout()
{
    about *ad=new about();
    ad->show();
}

void clearInterface()
{
    QString temp="not available";
    if (FF_DEBUG)
	cout << "Clearing Interface..." << endl;

    lockApplication();
    rst.resolve("", "");
    cl->cb_ip_src->setText(temp); cl->cb_ip_src->setEnabled(false); cl->cb_ip_src->setChecked(false);
    cl->cb_ip_dst->setText(temp); cl->cb_ip_dst->setEnabled(false); cl->cb_ip_dst->setChecked(false);
    cl->cb_port_src->setText(temp); cl->cb_port_src->setEnabled(false); cl->cb_port_src->setChecked(false);
    cl->cb_port_dst->setText(temp); cl->cb_port_dst->setEnabled(false); cl->cb_port_dst->setChecked(false);
    cl->cb_interface_in->setText(temp); cl->cb_interface_in->setEnabled(false); cl->cb_interface_in->setChecked(false);
    cl->cb_interface_out->setText(temp); cl->cb_interface_out->setEnabled(false); cl->cb_interface_out->setChecked(false);
    cl->cb_protocol->setText(temp); cl->cb_protocol->setEnabled(false);cl->cb_protocol->setChecked(false);
    cl->cb_conntrack->setEnabled(false); cl->cb_conntrack->setChecked(false);
    cl->cb_program->setText(temp); cl->cb_program->setEnabled(false); cl->cb_program->setChecked(false);

    cl->cb_this_packet->setEnabled(false); cl->cb_this_packet->setChecked(true);
    cl->cb_queued_packets->setEnabled(false); cl->cb_queued_packets->setChecked(false);
    cl->cb_create_rule->setEnabled(false); cl->cb_create_rule->setChecked(false);

    cl->ch_timeout->setEnabled(false);

    cl->label_mac_addr->setText(temp); cl->label_mac_addr->setEnabled(false);
    cl->label_len->setText(temp); cl->label_len->setEnabled(false);
    cl->label_tcp_flags->setText(temp); cl->label_tcp_flags->setEnabled(false);
    cl->label_icmp_type->setText(temp); cl->label_icmp_type->setEnabled(false);
    cl->label_arrived->setText(temp); cl->label_arrived->setEnabled(false);

    cl->label_ip_src->setText(temp); cl->label_ip_src->setEnabled(false);
    cl->label_ip_dst->setText(temp); cl->label_ip_dst->setEnabled(false);
    cl->label_chain->setText(temp); cl->label_chain->setEnabled(false);

	cl->statusBar()->message(QString("no packets available"));

#ifdef WITH_KDE
	tray->setPacketPending(false);
	tray->setToolTip("no packet pending");
	if (popup)
        if (!cl->isHidden())
			cl->hide();
#endif
    unlockApplication();
    if (FF_DEBUG)
	cout << "-Clearing Interface..." << endl;
}

void activateInterface()
{
    QString temp;
    lockApplication();
    if (FF_DEBUG)
	cout << "activating interface..." << endl;
    cl->cb_ip_src->setEnabled(true);
    cl->cb_ip_dst->setEnabled(true);
    cl->cb_protocol->setEnabled(true);
    cl->cb_conntrack->setEnabled(true);

    cl->cb_this_packet->setEnabled(true);
    cl->cb_queued_packets->setEnabled(true);
    cl->cb_create_rule->setEnabled(true);

    cl->ch_timeout->setEnabled(true);

    cl->label_len->setEnabled(true);
    cl->label_arrived->setEnabled(true);

    temp="resolving...";
    cl->label_ip_src->setText(temp); cl->label_ip_src->setEnabled(true);
    cl->label_ip_dst->setText(temp); cl->label_ip_dst->setEnabled(true);
    cl->label_chain->setEnabled(true);
    cl->statusBar()->clear();
#ifdef WITH_KDE
	tray->setPacketPending(true);
	if (popup)
        if (cl->isHidden())
			cl->show();
#endif
	unlockApplication();
}

void fireflier_client::accept_clicked()
{
    if (packetAvailable)
    {
        if (FF_DEBUG)
	    cout << "accepting" << endl;
	int id=0;
	int timeout=0;
        int ipsrc, ipdst, portsrc, portdst, intin, intout, prot, conn, prog;
	lockApplication();

	if (cb_this_packet->isChecked()) id=1;
	if (cb_queued_packets->isChecked()) id=2;
	if (cb_create_rule->isChecked()) id=3;

	if (ch_timeout->currentItem()==1)
	    timeout=5*60;
	else if (ch_timeout->currentItem()==2)
            timeout=60*60;
	else if (ch_timeout->currentItem()==3)
            timeout=24*60*60;

	ipsrc=cb_ip_src->isChecked();
	ipdst=cb_ip_dst->isChecked();
	portsrc=cb_port_src->isChecked();
	portdst=cb_port_dst->isChecked();
	intin=cb_interface_in->isChecked();
	intout=cb_interface_out->isChecked();
	prot=cb_protocol->isChecked();
	conn=cb_conntrack->isChecked();
        prog=cb_program->isChecked();
	unlockApplication();

        clearInterface();
	packetAvailable=0;
	sendCmd(id, ipsrc, ipdst, portsrc, portdst, intin, intout,
		0, // reserved for mac address filtering
		prot, conn, prog, timeout,
		1 // accept
	       );
	if (ipt_rules && ipt_rules->isVisible())
            sendIPTRulesRequest();
	if (usr_rules && usr_rules->isVisible())
            sendUSRulesRequest();
    }
}

void fireflier_client::deny_clicked()
{
    if (packetAvailable)
    {
        if (FF_DEBUG)
	    cout << "denying" << endl;
	int id=0;
	int timeout=0;
        int ipsrc, ipdst, portsrc, portdst, intin, intout, prot, conn, prog;
	lockApplication();
	if (cb_this_packet->isChecked()) id=1;
	if (cb_queued_packets->isChecked()) id=2;
	if (cb_create_rule->isChecked()) id=3;

	if (ch_timeout->currentItem()==1)
	    timeout=5*60;
	else if (ch_timeout->currentItem()==2)
            timeout=60*60;
	else if (ch_timeout->currentItem()==3)
            timeout=24*60*60;

	ipsrc=cb_ip_src->isChecked();
	ipdst=cb_ip_dst->isChecked();
	portsrc=cb_port_src->isChecked();
	portdst=cb_port_dst->isChecked();
	intin=cb_interface_in->isChecked();
	intout=cb_interface_out->isChecked();
	prot=cb_protocol->isChecked();
	conn=cb_conntrack->isChecked();
        prog=cb_program->isChecked();
	unlockApplication();

        clearInterface();
	packetAvailable=0;
	sendCmd(id, ipsrc, ipdst, portsrc, portdst, intin, intout,
		0, // reserved for mac address filtering
		prot, conn, prog, timeout,
		0 // accept
	       );
	if (ipt_rules && ipt_rules->isVisible())
            sendIPTRulesRequest();
	if (usr_rules && usr_rules->isVisible())
            sendUSRulesRequest();
	}
}

void setLabels(packet *p)
{
    char buffer[50];
    char buffer2[50];
    if (FF_DEBUG)
	cout << "Setting labels..." << endl;

    activateInterface();
    lockApplication();
    char temp[50];
    cl->packetAvailable=1;

    sprintf(buffer, "%i.%i.%i.%i",
            ((unsigned char*)&p->ip_src)[0],
	    ((unsigned char*)(&p->ip_src))[1],
	    ((unsigned char*)(&p->ip_src))[2],
	    ((unsigned char*)(&p->ip_src))[3]);
    strcpy(temp, "&IP=");
    strcat(temp, buffer);
    cl->cb_ip_src->setText(temp);
    cl->cb_ip_src->setAccel(QKeySequence(QString("ALT+I")));
    sprintf(buffer2, "%i.%i.%i.%i",
	    ((unsigned char*)(&p->ip_dst))[0],
	    ((unsigned char*)(&p->ip_dst))[1],
	    ((unsigned char*)(&p->ip_dst))[2],
	    ((unsigned char*)(&p->ip_dst))[3]);
    unlockApplication();

    strcpy(temp, "I&P=");
    strcat(temp, buffer2);
    rst.resolve(buffer, buffer2);

    lockApplication();
    cl->cb_ip_dst->setText(temp);
    cl->cb_ip_dst->setAccel(QKeySequence(QString("ALT+P")));

    if (p->port_src)
    {
	cl->cb_port_src->setEnabled(true);
	sprintf(buffer, "P&ort=%i (%s)", p->port_src, getService(p->port_src, p->protocol, true).c_str());
	strcpy(temp, buffer);
	cl->cb_port_src->setText(temp);
        cl->cb_port_src->setAccel(QKeySequence(QString("ALT+O")));
    }

    if (p->port_dst)
    {
	cl->cb_port_dst->setEnabled(true);
	sprintf(buffer, "Po&rt=%i (%s)", p->port_dst, getService(p->port_dst, p->protocol, true).c_str());
	strcpy(temp, buffer);
	cl->cb_port_dst->setText(temp);
	cl->cb_port_dst->setAccel(QKeySequence(QString("ALT+R")));

    }

    strcpy(buffer, "");
    switch (p->protocol)
    {
    case 1:
	strcpy(buffer, "Protoco&l=ICMP");
        break;
    case 6:
	strcpy(buffer, "Protoco&l=TCP");
        break;
    case 17:
	strcpy(buffer, "Protoco&l=UDP");
        break;
    case 47:
	strcpy(buffer, "Protoco&l=GRE");
	break;
    case 0:
	sprintf(buffer, "Protoco&l=UNKNOWN(%d)", p->protocol);
	break;

    }
    strcpy(temp, buffer);
    cl->cb_protocol->setText(temp);
    cl->cb_protocol->setAccel(QKeySequence(QString("ALT+L")));

    if (p->programname && strcmp((char*)p->programname, ""))
    {
        sprintf(temp, "pro&gram=%s", p->programname);
	cl->cb_program->setEnabled(true);
	cl->cb_program->setText(temp);
	cl->cb_program->setAccel(QKeySequence(QString("ALT+G")));
    }
    else
    {
        sprintf(temp, "not available", p->programname);
	cl->cb_program->setEnabled(false);
	cl->cb_program->setText(temp);
    }

    if (strcmp((char*)p->interface_in, ""))
    {
	cl->cb_interface_in->setEnabled(true);
	strcpy(temp, (char*)p->interface_in);
	strcpy(buffer, "i&nterface=");
        strcat(buffer, temp);
	cl->cb_interface_in->setText(buffer);
	cl->cb_interface_in->setAccel(QKeySequence(QString("ALT+N")));

    }

    if (strcmp((char*)p->interface_out, ""))
    {
	cl->cb_interface_out->setEnabled(true);
	strcpy(temp, (char*)p->interface_out);
	strcpy(buffer, "interfac&e=");
        strcat(buffer, temp);
	cl->cb_interface_out->setText(buffer);
	cl->cb_interface_out->setAccel(QKeySequence(QString("ALT+C")));

    }

    switch (p->hook)
    {
    case 1:
	strcpy(temp,"Chain=INPUT");
	break;
    case 2:
	strcpy(temp,"Chain=FORWARD");
	break;
    case 3:
	strcpy(temp,"Chain=OUTPUT");
	break;
    default:
	strcpy(temp,"Chain=not available");
        break;
    }
    cl->label_chain->setText(temp);

    sprintf(buffer, "length=%d", p->len);
    strcpy(temp, buffer);
    cl->label_len->setText(temp);
    cl->label_len->setEnabled(temp);

    if (p->mac_addrlen>0)
    {
	sprintf(buffer, "mac=%2x:%2x:%2x:%2x:%2x:%2x", p->mac_addr[0],p->mac_addr[1],
		p->mac_addr[2],p->mac_addr[3],
		p->mac_addr[4],p->mac_addr[5]);
	strcpy(temp, buffer);
	cl->label_mac_addr->setText(temp);
	cl->label_mac_addr->setEnabled(true);
    }
    strcpy(buffer, "TCP Flags=");
    if (p->tcp_flags&1)
        strcat(buffer, "FIN ");
    if (p->tcp_flags&2)
        strcat(buffer, "SYN ");
    if (p->tcp_flags&4)
        strcat(buffer, "ACK ");
    if (p->tcp_flags&8)
	strcat(buffer, "RST ");
    if (strcmp(buffer, "TCP Flags=") && (p->protocol==6))
    {
	strcpy(temp, buffer);
	cl->label_tcp_flags->setText(temp);
	cl->label_tcp_flags->setEnabled(true);
    }
    if (p->protocol==1)
    {
	strcpy(temp, "ICMP Type=");
	strcat(temp, ICMP_TYPES[p->icmp_type]);
	cl->label_icmp_type->setText(temp);
	cl->label_icmp_type->setEnabled(true);
    }

    strcpy(buffer, "Packet arrived at ");
    strcat(buffer, ctime((long*)&(p->arrived)));
    buffer[strlen(buffer)-1]=0;

    cl->label_arrived->setText(buffer);
	unlockApplication();

#ifdef WITH_KDE
    if (p->programname && strcmp((char*)p->programname, ""))
    {
		tray->setToolTip(p->programname);
	}
	else
		tray->setToolTip("Unknown");
#endif

	if (FF_DEBUG)
	cout << "-Setting labels..." << endl;
}

void fireflier_client::del_usrule_clicked()
{
    int rulenum;

    lockApplication();
    rulenum=usr_rules->iptables_list->currentItem();
    unlockApplication();
    if (rulenum>=0)
    {
        sendUSdelCmd(rulenum);
    }
}

void fireflier_client::del_iptrule_clicked()
{
    int rulenum;
    int chain=-1;

    lockApplication();
    rulenum=ipt_rules->iptables_list->currentItem();
    unlockApplication();
    if (rulenum>=0)
    {
	if (strncmp(ipt_rules->iptables_list->currentText(), "Chain ", 6))
	{
	    int i=0;
	    while (i<rulenum)
	    {
		i++;
		if (!strncmp("Chain INPUT", ipt_rules->iptables_list->item(rulenum-i)->text(),11))
		{
		    chain=1;
                    break;
		}
		if (!strncmp("Chain OUTPUT", ipt_rules->iptables_list->item(rulenum-i)->text(),12))
		{
		    chain=3;
                    break;
		}
		if (!strncmp("Chain FORWARD", ipt_rules->iptables_list->item(rulenum-i)->text(),13))
		{
		    chain=2;
                    break;
		}
	    }
            rulenum=i-1;
	}
	if (chain>=1)
	    sendIPTdelCmd(chain, rulenum);
    }
}

void usage()
{
    cout << "Usage: fireflier-client-qt -s SERVER_IP -p SERVER_PORT -r -a filename" << endl;
    cout << "  Default: fireflier-client-qt -s 127.0.0.1 -p 1133" << endl;
    cout << "  -s ... connect to this ip" << endl;
    cout << "  -p ... connect to this port" << endl;
    cout << "  -r ... auto popup (only used with kde client)" << endl;
    cout << "  -a ... get username/password from this file instead of asking (security risk - see AUTOLOGIN)" << endl;
}

void deinit()
{
    thrfinish=1;
    sleep(1);
}

int main(int argc, char **argv)
{
	NWThread qt;

	string serverip="";
	string serverport="";
    string autologin="";
	int needusage=0;
    char option=0;
	while ((option=getopt(argc, argv, "s:p:a:r"))!=-1) // using this the first time, hope it works this way :)
	{
		switch (option)
		{
		case 's':
            serverip=argv[optind-1];
			break;
		case 'p':
            serverport=argv[optind-1];
			break;
		case 'a':
            autologin=argv[optind-1];
			break;
		case 'r':
            popup=true;
            break;
		default:
			needusage=1;
			break;
		}
	}

#ifdef WITH_KDE
	KAboutData aboutData( "fireflier-client-kde", I18N_NOOP("fireflier-client-kde"),
						 "1.1.4", "FireFlier Client", KAboutData::License_GPL,
						 "(c) 2002, Martin Maurer");
	aboutData.addAuthor("Martin Maurer",0, "fireflier@gibraltar.at");

	static KCmdLineOptions options[] = {
		{ "s <argument>", I18N_NOOP("Server where this client should connect to"), "127.0.0.1" },
		{ "p <argument>", I18N_NOOP("Port this client should connect to"), "1133" },
		{ "a <argument>", I18N_NOOP("get username/password from this file instead of asking (security risk - see AUTOLOGIN)"), "" },
		{ "r", I18N_NOOP("Autoraise window on new packet"), "false" },
		{ 0, 0, 0}
	};
	KCmdLineArgs::init(argc, argv, &aboutData );
    KCmdLineArgs::addCmdLineOptions(options);

	kApp=new KApplication;

	tray=new traywidget();
	KWin::setSystemTrayWindowFor(tray->winId(),0);
	tray->show();

	kApp->setTopWidget(tray);
#else
	qApp=new QApplication( argc, argv );
#endif

	if (serverip!="")
    {
		if (sscanf(serverip.c_str(), "%u.%u.%u.%u", qt.hostip, qt.hostip+1, qt.hostip+2, qt.hostip+3)!=4)
		{
            needusage=1;
		}
    }
    else
    {
        qt.hostip[0]=127;
        qt.hostip[1]=0;
        qt.hostip[2]=0;
        qt.hostip[3]=1;
    }

    if (serverport!="")
    {
		qt.port=atoi(serverport.c_str());
		if ((qt.port<=0) || (qt.port>65535))
		{
            needusage=1;
		}
    }
    else
        qt.port=1133;

	if (needusage)
	{
		usage();
        exit(1);
	}

    sourceText=0;
    ipt_rules=0;
    usr_rules=0;
	cl=new fireflier_client();
	cl->adjustSize(); // auto-calculate optimal size
    cl->setMinimumWidth(600); // but the width should be more than minimum needed

#ifdef WITH_KDE
	kApp->setMainWidget(cl);
#else
	qApp->setMainWidget(cl);
#endif

    rst.start();

    qt.start();
    atexit(deinit);

	string autouser="";
    string autopass="";
	if (autologin!="")
	{
        char temp[50];
		ifstream in(autologin.c_str());
		if (in.is_open())
		{
			in.getline(temp, 49);
			temp[49]=0;
            autouser=temp;
			in.getline(temp, 49);
			temp[49]=0;
            autopass=temp;
		}
	}

	if (autopass=="")
		cl->show();
    login_dialog ld;
	char *username=getlogin();
    if (username)
		ld.input_username->setText(username);
    authenticated=0;
    bool loginagain=false;
    do {
        if (!loginagain)
			cl->statusBar()->message("logging in to server");
        else
			cl->statusBar()->message("login error - try again");

		if ((autopass=="") || (loginagain))
		{
			ld.exec();
			if (ld.result()==QDialog::Rejected)
				exit(1);
		}
  		cl->statusBar()->message("sending login and password");
		kApp->processEvents();
        // authenticated is set to -1
		// as soon as login result is received, authenticated is set again
		if ((autopass!="") && !loginagain)
			sendLogin(autouser.c_str(), autopass.c_str());
        else
			sendLogin(ld.input_username->text(), ld.input_password->text());
		while (((authenticated==-1) || (authenticated==2)) && (connected))
		{
			kApp->processEvents();
            sleep(1);
		}
//			sleep(1);
		if (!authenticated)
		{
			loginagain=true;
			if (!cl->isVisible())
				cl->show();
		}
	} while ((authenticated!=1) && (connected));
	cl->statusBar()->message("logged in successfully");
    if (popup)
        cl->hide();

	if (!connected)
        return 1;

#ifdef WITH_KDE
//  deprecated
//	KWin::appStarted();
	kApp->exec();
#else
	qApp->exec();
#endif
    return 0;
}
