/***************************************************************************
*                                                                         *
*   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.                                   *
*                                                                         *
***************************************************************************

Author: Christian Hubinger <chubinger@gmail.com>, (C) 2001-2004

*/
#include "kmyfirewall.h"

// QT includes
#include <qmessagebox.h>
#include <qtextstream.h>
#include <qpixmap.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qwidgetstack.h>
#include <qlayout.h>

// KDE includes
#include <kapplication.h>
#include <kaction.h>
#include <kaccel.h>
#include <kstdaction.h>
#include <kstandarddirs.h>
#include <kfiledialog.h>
#include <klocale.h>
#include <kmenubar.h>
#include <kprocess.h>
#include <kdebug.h>
#include <dcopclient.h>
#include <kstatusbar.h>
#include <kpopupmenu.h>
#include <kglobal.h>
#include <kmessagebox.h>
#include <kstdguiitem.h>
#include <kcmdlineargs.h>
#include <kio/netaccess.h>
#include <kfileitem.h>
#include <klibloader.h>
#include <ktextedit.h>
#include <kparts/partmanager.h>
#include <kpushbutton.h>
#include <kedittoolbar.h>

// C includes
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>

// project includes
#include "kmfapp.h"
#include "core/kmfconfig.h"
#include "core/kmferror.h"
#include "core/kmferrorhandler.h"
#include "core/kmfdoc.h"
#include "core/kmfiptdoc.h"
#include "core/kmfgenericdoc.h"
#include "core/kmfpluginfactory.h"
#include "core/kmfappstate.h"

#include "kmfwidgets/kmfprocout.h"
#include "kmfwidgets/kmfnewdocdlg.h"
#include "kmfwidgets/kmfobjectinfo.h"
#include "kmfwidgets/kmftemplatechooser.h"
#include "kmfwidgets/kmfdocumentinfo.h"
#include "kmfwidgets/kmfselectinterface.h" 
// #include "ipteditor/kmfruleedit.h"

// #include "genericinterface/kmfgenericinterface.h"

#include "kmfconfigdialog.h"

KMyFirewall::KMyFirewall( QWidget* parent, const char *name ) : KMFMainWindow( parent, name ) {
	// kdWarning() << "MyFirewall Starting up..." << endl;
	
	KCmdLineArgs * args = KCmdLineArgs::parsedArgs();
	QCString interface = args->getOption("i");
	if ( args->isSet("i") ) {
		kdDebug() << "Found interface option: " << interface << endl;
		if ( interface == "iptables" ) {
			KMFConfig::setUseGenericInterface( false );
			KMFConfig::writeConfig();
			kdDebug() << "Start using iptables interface" << endl;
		} else if ( interface == "generic" ) {
			KMFConfig::setUseGenericInterface( true );
			KMFConfig::writeConfig();
			kdDebug() << "Start using generic interface" << endl;
		} else {
			kdWarning() << "Unrecognized argument: " << interface << " for option i" <<  endl;
		}
		
	} 
	if ( ! args->isSet("i") &&  KMFConfig::showSelInterface() ) {
		slotSelectInterface();
	}
	childproc = new KProcess();
	// childproc->setUseShell( true , "/bin/sh");
	connect( childproc, SIGNAL( processExited( KProcess* ) ), this, SLOT( slotProcessExited( KProcess* ) ) ) ;
	connect( childproc, SIGNAL( receivedStdout( KProcess*, char*, int ) ), this, SLOT( slotReceivedOutput( KProcess*, char*, int ) ) );
	connect( childproc, SIGNAL( receivedStderr( KProcess*, char*, int ) ), this, SLOT( slotReceivedError( KProcess*, char*, int ) ) );

	m_configDlg = new KMFConfigDialog( this, "config" );
	connect ( m_configDlg, SIGNAL( sigConfigChanged() ),
	          this, SLOT( slotConfigChanged() ) );

	m_err = new KMFError();
	m_err_handler = new KMFErrorHandler( "KMyFirewall" );



//	kdDebug() << "kmfdoc = new KMFIPTDoc(this,kmfdoc);" << endl;
	kmfdoc = 0;
	initDoc();

	connect( kmfdoc, SIGNAL( sigEnableUndo( bool ) ),
	         this, SLOT( slotEnableUndo( bool ) ) );
	connect( kmfdoc, SIGNAL( sigEnableRedo( bool ) ),
	         this, SLOT( slotEnableRedo( bool ) ) );
	setCaption( i18n( "No File Loaded" ) );
	KMFAppState::setHasOpenDoc( false );


	set_splash_status( i18n( "Init statusbar..." ) );
	initStatusBar();
	set_splash_status( i18n( "Init menu..." ) );
	initMenu();
	set_splash_status( i18n( "Init actions..." ) );
	initActions();
	set_splash_status( i18n( "Init GUI..." ) );
	initView();
	set_splash_status( i18n( "Read configuration..." ) );
	if ( checkRoot() ) {
		if ( KMFConfig::firstRun() ) {
			closeSplash();
			slotConfigureKMF();
			slotFileNew();
		} else {
			set_splash_status( i18n( "Restoring session..." ) );
			slotRestoreSession();
		}
		setActiveWindow(); // Make sure this window gets keyboard focus
		raise(); // Make sure the window is now on top of other windows
		statusBar() ->changeItem( "Ready", 0 );
		checkStatus();
	} else {
		close(); // User indicated an abort is needed, so close the main window
	}
	emit sigHasDoc( KMFAppState::hasOpenDoc() );
	KMFAppState::setUpAndRunning( true );

	slotConfigChanged();
	slotEnableUndo( false );
	statusBar() ->changeItem( "Ready", 0 );
}

KMyFirewall::~KMyFirewall() {}

//############ Start Init Methods ####################
void KMyFirewall::initMenu() {
	kdDebug() << "KMyFirewall::initMenu()" << endl;
	/*	KPopupMenu * help = helpMenu();
		menuBar() ->insertItem( i18n( "&Help" ), help );*/
}


void KMyFirewall::initView() {
	kdDebug() << "KMyFirewall::initView()" << endl;
	m_widgetStack = new QWidgetStack( this, "stack" );
	setCentralWidget( m_widgetStack );
	// Load the main editor widget
	KParts::ReadWritePart* mainView = KMFPluginFactory::KMFMainView( this, m_err );
	if ( ! m_err_handler->showError( m_err ) ) {
		kapp->quit();
	}
	if ( ! mainView ) {
		KMessageBox::error( this, i18n( "KMFPluginFactory::KMFMainView( this, m_err ): returned a NULL pointer" ) );
		kapp->quit();
	}
	m_editorWidget = mainView->widget();
	m_widgetStack->addWidget( m_editorWidget );
	m_widgetStack->raiseWidget( m_editorWidget );
	createGUI( mainView );
	m_outputWidget = new QWidget( this, "output" );
	m_widgetStack->addWidget( m_outputWidget );
	emit sigEnableActions( false );
}

void KMyFirewall::initDoc() {
	if ( kmfdoc ) {
		if ( ! kmfdoc->isSaved() ) {
			slotFileClose();
		}
	}

	if ( KMFConfig::useGenericInterface() )
		kmfdoc = new KMFGenericDoc( this, "kmfdoc" );
	else
		kmfdoc = new KMFIPTDoc( this, "kmfdoc" );
}

void KMyFirewall::updateView() {
	initDoc();

	KParts::ReadWritePart* mainView = KMFPluginFactory::KMFMainView( this, m_err );
	if ( ! m_err_handler->showError( m_err ) ) {
		kapp->quit();
	}
	if ( ! mainView ) {
		KMessageBox::error( this, i18n( "KMFPluginFactory::KMFMainView( this, m_err ): returned a NULL pointer" ) );
		kapp->quit();
	}
	m_editorWidget = mainView->widget();
	QWidget* wid = m_widgetStack->widget( m_widgetStack->id( m_editorWidget ) );
	wid = m_editorWidget;

	createGUI( mainView );
	m_widgetStack->raiseWidget( m_editorWidget );
	emit sigEnableActions( false );
}

void KMyFirewall::showEditor() {
	m_widgetStack->raiseWidget( m_editorWidget );
}

void KMyFirewall::slotShowEditor() {
	showEditor();
	emit sigEnableActions( true );
}

void KMyFirewall::showOutput() {
	m_widgetStack->raiseWidget( m_outputWidget );
	emit sigEnableActions( false );
}

void KMyFirewall::setOutputWidget( QWidget* wid ) {
	m_widgetStack->removeWidget( m_outputWidget );
	QWidget* widget = new QWidget( this , "output" );
	QGridLayout *layout = new QGridLayout( widget, 1, 1 );
	wid->reparent( widget, ( unsigned int ) 0 , *( new QPoint( 0, 0 ) ) );
	layout->addWidget( wid, 0, 0 );
	kdDebug() << "Adding outputwidget: " << wid->className() << endl;
	if ( strcmp(wid->className(), "KMFObjectInfo") ) {
		KPushButton * close = new KPushButton( i18n( "Return to Editor View" ), widget );
		connect( close, SIGNAL( clicked() ),
		         this, SLOT( slotShowEditor() ) );
		layout->addWidget( close, 1, 0 );
	}
	m_outputWidget = widget;
	m_widgetStack->addWidget( widget );
}

void KMyFirewall::initActions() {
	kdDebug() << "Init Actions..." << endl;
	// Custom Actions

	actionEditDocInfo = new KAction( i18n( "&Edit Document Information" ), "edit", 0 , this, SLOT( slotEditDocInfo() ), actionCollection(), "edit_doc_info" );

	// KStdAction
	actionNew = KStdAction::openNew( this, SLOT( slotFileNew() ),
	                                 actionCollection(), "new" );

	actionClose = KStdAction::close( this, SLOT( slotFileClose() ),
	                                 actionCollection(), "close" );

	actionOpen = KStdAction::open( this, SLOT( slotFileOpen() ),
	                               actionCollection(), "open" );

	actionSave = KStdAction::save( this, SLOT( slotFileSave() ),
	                               actionCollection(), "save" );

	actionSaveAs = KStdAction::saveAs( this, SLOT( slotFileSaveAs() ),
	                                   actionCollection(), "save_as" );


	actionQuit = KStdAction::quit( this, SLOT( slotQuitApp() ),
	                               actionCollection(), "quit" );

	actionUndo = KStdAction::undo( this, SLOT( slotUndo() ),
	                               actionCollection(), "undo" );

	actionRedo = KStdAction::redo( this, SLOT( slotRedo() ),
	                               actionCollection(), "redo" );

	actionLoadTemplate = new KAction( i18n( "&Load Template..." ), "wizard", 0 , this, SLOT( slotLoadTemplate() ),
	                                  actionCollection(), "load_template" );
//	KStdAction::showToolbar( this, SLOT( toggleToolBar() ) , actionCollection() );
	KStdAction::showStatusbar( this, SLOT( toggleStatusBar() ), actionCollection() );
	KStdAction::preferences( this, SLOT( slotConfigureKMF() ), actionCollection() );
	KStdAction::configureToolbars( this, SLOT( slotConfigureToolbars() ), actionCollection() );
}


//############ End Init Methods ####################

/** This function copys the new doc to the member kfmdoc  */
void KMyFirewall::slotLoadDocument( KMFDoc* doc ) {
	kdDebug() << "KMyFirewall::slotLoadDocument(KMFIPTDoc& doc)" << endl;
	if ( doc == 0 ) {
		kdDebug() << "KMyFirewall::slotLoadDocument(KMFIPTDoc& doc)\n kmfdoc == 0" << endl;
		m_err->setErrType( KMFError::FATAL );
		const QString msg = i18n( "<p>KMyFirewall::slotLoadDocument(KMFIPTDoc& doc)"
		                          "<p>doc == 0<p>This is a bug." );
		m_err->setErrMsg( msg );
		m_err_handler->showError( m_err );
		return ;
	}
	kmfdoc = doc;
	toggleActions( true );
	KMFAppState::setHasOpenDoc( true );
	actionSave->setEnabled( true );
	checkStatus();
	// 	m_ruleedit->loadDoc( kmfdoc );
	kdDebug() << "exit from: KMyFirewall::slotLoadDocument( KMFIPTDoc* doc )" << endl;
}

void KMyFirewall::slotReloadDocument() {
	slotLoadDocument( kmfdoc );
}

void KMyFirewall::slotConfigureToolbars() {
	saveMainWindowSettings( KGlobal::config(), "KMyFirewall" );
	KEditToolbar dlg( factory() );
	connect( &dlg, SIGNAL( newToolbarConfig() ), this, SLOT( slotNewToolbarConfig() ) );
	dlg.exec();
}

void KMyFirewall::slotNewToolbarConfig() {
	applyMainWindowSettings( KGlobal::config(), "KMyFirewall" );
}

//check for the uid etc...
bool KMyFirewall::checkRoot() {
	// Is application started as root?
	if ( getuid() != 0 ) {
		closeSplash();
		const QString & msg = i18n( "<qt><p><b>KMyFirewall was not started as user <i>root</i>.</b><br>"
		                            "You will be prompted for the root password when you try to do something that requires root access.</p>"
		                            "<p><b>Do you still want to continue?</b></p></qt>" );
		int choise = KMessageBox::warningYesNo( NULL, msg, i18n( "Warning" ), KStdGuiItem::yes(), KStdGuiItem::no(), "not_root_warning" );
		switch ( choise ) {
		case 4:
			kdDebug() << "Clicked NO" << endl;
			return false; // Abort and prevent application continuing from here
		case 3:
			kdDebug() << "Clicked Yes" << endl;
			break;
		default:
			return false; // Any action but pressing 'yes' will abort application
		}
	}
		
	const QString& msg = i18n( "<qt><b>Compatibility Warning</b>.<p> "
"As the file format used to save the rulesets has changed, "
"rulesets created with KMyFirewall &lt; 1.0beta1 <b>WILL NOT</b> work, don't even try it!"
		"</p></qt>" );
	KConfig* _config = kapp->config();
	_config->setGroup( "Notification Messages" );
	QString warn = "";
	warn = _config->readEntry( "compatibility_warning" );
	if ( warn != "false" )
		closeSplash();
	KMessageBox::information( NULL, msg, i18n( "Warning - File format change" ), "compatibility_warning", 0 );
	return true;
}

bool KMyFirewall::saveQuit() {
	if ( !kmfdoc->isSaved() && !kmfdoc->isEmpty() && KMFAppState::hasOpenDoc() ) {
		const QString & msg = i18n( "<p>Do you want to save the changes before you quit?" );
		const QString& title = i18n( "Quit" );
		int doit = KMessageBox::questionYesNoCancel ( this , msg, title );
		kdDebug() << "Message Box returned: " << doit << endl;
		if ( doit == 3 ) { // OK clicked
			slotFileSave();
			KMFAppState::setHasOpenDoc( false );
			return true;
		}
		if ( doit == 2 ) { // Cancel clicked
			return false;
		}
		if ( doit == 4 ) { // No clicked
			KMFAppState::setHasOpenDoc( false );
			return true;
		}
		return false;
	}
	return true;
}

void KMyFirewall::slotQuitApp() {
	bool quit = saveQuit();
	if ( quit ) {
		KMFAppState::setHasOpenDoc( false );
		KMFConfig::self() ->writeConfig();
		kapp->quit();
	}
}

KMFDoc* KMyFirewall::doc() {
	return kmfdoc;
}

void KMyFirewall::closeEvent( QCloseEvent* ) {
	slotQuitApp();
}

void KMyFirewall::toggleToolBar() {
	if ( toolBar() ->isVisible() )
		toolBar() ->hide();
	else
		toolBar() ->show();
}
void KMyFirewall::toggleStatusBar() {
	if ( statusBar() ->isVisible() )
		statusBar() ->hide();
	else
		statusBar() ->show();
}

void KMyFirewall::initStatusBar() {
	kdDebug() << "KMyFirewall::initStatusBar()" << endl;
	statusBar() ->insertItem( i18n( "Starting Up" ), 0, true );
	statusBar() ->insertItem( "", 1, true );
}

void KMyFirewall::slotConfigChanged() {
	kdDebug() << "KMyFirewall::slotConfigChanged()" << endl;
	KMFDoc::setMaxUndo( KMFConfig::maxUndo() );
	// FIXME: enable dynamicly interface changeing
	//updateView();
	emit sigUpdateView();
}

void KMyFirewall::slotEnableSave() {
	actionSave->setEnabled( true );
}

// void KMyFirewall::slotCreateFirewallScript() {
// 	if ( KMFIPTDoc * doc = dynamic_cast<KMFIPTDoc*> ( kmfdoc ) ) {
// 		doc -> createFirewallScript();
// 	}
// }

void KMyFirewall::slotEditDocInfo() {
	KMFDocumentInfo * dlg = new KMFDocumentInfo( this, "KMFObjectInfo", true );
	dlg->loadDoc( kmfdoc );
	connect( dlg,SIGNAL( sigSaveAsTemplate() ) , this, SLOT( slotFileSaveAsTemplate() )  );
	dlg->exec();
}

void KMyFirewall::slotSelectInterface() {
	KMFSelectInterface * m_sel = new KMFSelectInterface( 0, "KMFSelectInterface", true, QWidget::WDestructiveClose | QWidget::WStyle_Customize | QWidget::WStyle_NoBorder );
	closeSplash();
	if ( m_sel->exec() == QDialog::Rejected ) {
		kdDebug() << "Wante to exit now..." << endl;
		kapp->quit();
		; // FIXME: Doe not work - kapp->quit();
	}
	showSplash();
}

void KMyFirewall::slotUndo() {
	kdDebug() << "KMyFirewall::slotUndo()" << endl;
	kmfdoc->undo();
	emit sigUpdateView();
}

void KMyFirewall::slotRedo() {
	kdDebug() << "KMyFirewall::slotRedo()" << endl;
	kmfdoc->redo();
	emit sigUpdateView();
}

void KMyFirewall::slotFileOpen() {
	kdDebug() << "KMyFirewall::slotFileOpen()" << endl;
	KURL url;
	if ( KMFConfig::useGenericInterface() )
		url = KFileDialog::getOpenURL( ":", "*.kmfgrs|KMyFirewall Ruleset(*.kmfgrs)" );
	else
		url = KFileDialog::getOpenURL( ":", "*.kmfrs|KMyFirewall IPTables Ruleset(*.kmfrs)" );

	QString xmlfile = url.path();
	if ( url.path().isEmpty() ) {
		return ;
	} else {
		slotFileClose();
		statusBar() ->message( i18n( "Open file: " ) + url.path() , 5000 );
		m_err = parseDocument( url );
		m_err_handler->showError( m_err );
		emit sigUpdateView();
	}
}

void KMyFirewall::slotLoadTemplate() {
	KMFTemplateChooser * dlg = new KMFTemplateChooser( 0 , "KMyFirewall - Load Template", true, QWidget::WDestructiveClose | QWidget::WStyle_Customize | QWidget::WStyle_NoBorder );

	connect( dlg, SIGNAL( sigLoadTemplate( const QString& ) ),
	         this, SLOT( slotLoadFile( const QString& ) ) );

	dlg->exec();
}

void KMyFirewall::slotFileClose() {
	bool choose_save = false;
	if ( !kmfdoc->isSaved() && !kmfdoc->isEmpty() && KMFAppState::hasOpenDoc() ) {
		switch ( QMessageBox::warning( this, i18n( "Save Changed Data?" ),
		                               i18n( "This firewall configuration has been changed since it was last saved.\n\n"
		                                     "What do you want to do with these changes?\n" ),
		                               i18n( "&Cancel" ), i18n( "&Discard" ), i18n( "&Save" ),
		                               2, 3 ) ) {

		case 0:
			kdDebug() << "Clicked Cancel" << endl;
			return ;
		case 1:
			kdDebug() << "Clicked Discard" << endl;
			break;
		case 2:
			kdDebug() << "Clicked Save" << endl;
			choose_save = true;
			slotFileSave();
			break;
		}
	}
	if ( ! choose_save ) {
		kmfdoc->clear();
		if (  KMFConfig::useGenericInterface() ) {
			KMFConfig::setCurrentGenericConfiguration( "" );
		} else {
			KMFConfig::setCurrentIPTConfiguration( "" );
		}
		actionSave->setEnabled( false );
		setCaption( i18n( "No File Loaded" ) );
		toggleActions( false );
		emit sigUpdateView();
		KMFAppState::setHasOpenDoc( false );
		emit sigHasDoc( false );
	}
}

void KMyFirewall::slotLoadFile( const QString& file ) {
	kdDebug() << "void KMyFirewall::slotLoadFile( const QString& " << file << " )" << endl;

	slotFileClose();
	KURL url( file );
	statusBar() ->message( i18n( "Open file: " ) + url.path() , 5000 );
	m_err = parseDocument( url );
	m_err_handler->showError( m_err );

	kmfdoc->setFileName( i18n( "Untitled" ) );
	setCaption( i18n( "Untitled" ) );
	kmfdoc->changed();
}


KMFError* KMyFirewall::parseDocument( const KURL& url ) {
	kdDebug() << "void KMyFirewall::parseDocument(QString& file)" << endl;
	KIO::UDSEntry f_props;
	
	if ( ! KIO::NetAccess::stat( url , f_props, 0 ) ) {
		closeSplash();
		const QString msg = i18n( "<qt><p>The file <b>%1</b> could not be loaded.</p>"
		                          "<p>If you are working with files stored on remote computers "
		                          "make sure that the network is up and the fileserver running.</qt>" ).arg( url.url() );
		m_err->setErrType( KMFError::NORMAL );
		m_err->setErrMsg( msg );
		return m_err;
	}
	KFileItem *props = new KFileItem( f_props, url );
	kdDebug() << "Found file permissions: " << props->permissionsString() << endl;
	if ( !props->isReadable() ) {
		const QString msg = i18n( "<qt><p>You don't have the permissions to read file: <b>%1</b></p></qt>" ).arg( url.url() );
		m_err->setErrType( KMFError::NORMAL );
		m_err->setErrMsg( msg );
		return m_err;
	}

	kmfdoc = kmfdoc->parseXMLRuleset( url );
	slotEnableUndo( false );
	slotEnableRedo( false );
	if ( kmfdoc == 0 ) {
		kdDebug() << "void KMyFirewall::parseDocument(QString& file)\nkmfdoc == 0" << endl;
		if (  KMFConfig::useGenericInterface() ) {
			KMFConfig::setCurrentGenericConfiguration( "" );
		}	 else {
			KMFConfig::setCurrentIPTConfiguration( "" );
		}
		
		kmfdoc->clear();
		m_err->setErrType( KMFError::NORMAL );
		const QString msg = i18n( "<p>Unable to load file %1" ).arg( url.url() );
		m_err->setErrMsg( msg );
		return m_err;
	}
	if ( kmfdoc->url().fileName() == i18n( "Untitled" ) ) {
		m_err->setErrType( KMFError::NORMAL );
		m_err->setErrMsg( i18n( "<qt><p><b>Loading <i>%1</i> Failed.</b></p>"
		                        "<p>Please make sure that you have the permissions to read to this file.<br>"
		                        "If you are working with remotely stored files "
		                        "make sure that the target host and the directory is reachable. "
		                        "</p></qt>" ).arg( url.url() ) );
		closeSplash();
		return m_err;
	}

	const QString filename = url.fileName();
	slotLoadDocument( kmfdoc );
	setCaption( filename );
	kmfdoc->saved();

	if ( url.fileName() != "workstation_template.kmfrs"
	        && url.fileName() != "nat_router_template.kmfrs"
	        && url.fileName() != "router_template.kmfrs" ) {
		if (  KMFConfig::useGenericInterface() ) {
			KMFConfig::setCurrentGenericConfiguration( url.url() );
		}	 else {
			KMFConfig::setCurrentIPTConfiguration( url.url() );
		}
		kdDebug() << "\nWrote URL: " << url.url() << "\n" << endl;
	} else {
		kmfdoc->setFileName( i18n( "Untitled" ) );
		setCaption( i18n( "Untitled" ) );
		if (  KMFConfig::useGenericInterface() ) {
			KMFConfig::setCurrentGenericConfiguration( url.url() );
		}	 else {
			KMFConfig::setCurrentIPTConfiguration( url.url() );
		}
	}
	m_err->setErrType( KMFError::OK );
	const QString msg = "";
	m_err->setErrMsg( msg );
	return m_err;
}


void KMyFirewall::slotRestoreSession() {
	KCmdLineArgs * args = KCmdLineArgs::parsedArgs();
	bool worked = true;
	QString curr = "";
	if ( args->count() == 1 ) {
		curr = args->arg( 0 );
	} else {
		if (  KMFConfig::useGenericInterface() ) {
			curr = KMFConfig::currentGenericConfiguration();
		} else {
			curr = KMFConfig::currentIPTConfiguration();
		}
	}

	

	// Check for right documant type
	if ( ( KMFConfig::useGenericInterface() && curr.endsWith( ".kmfrs" ) ) ||
	        ( ! KMFConfig::useGenericInterface() && curr.endsWith( ".kmfgrs" ) ) ) {
		worked = false;
		curr = "";
	}


	args->clear();
	if ( worked ) {
		KURL url( curr );
		if ( url.fileName().isEmpty() ) {
			worked = false;
			toggleActions( false );
		} else {
			const QString file = curr;
			m_err = parseDocument( url );
			slotEnableUndo( false );
			slotEnableUndo( false );
			if ( ! m_err_handler->showError( m_err ) ) {
				worked = false;
			}
		}
	}

	if ( worked ) {
		checkStatus();
		KMFAppState::setHasOpenDoc( true );
		emit sigHasDoc( KMFAppState::hasOpenDoc() );
	} else {
		checkStatus();
		if (  KMFConfig::useGenericInterface() ) {
			KMFConfig::setCurrentGenericConfiguration( "" );
		}	 else {
			KMFConfig::setCurrentIPTConfiguration( "" );
		}		
		toggleActions( false );
		actionSave->setEnabled( false );
		KMFAppState::setHasOpenDoc( false );
		emit sigHasDoc( KMFAppState::hasOpenDoc() );
		toggleActions( false );
	}
}


void KMyFirewall::slotFileNew() {
	kdDebug() << "KMyFirewall::slotFileNew()" << endl;
	if ( hasOpenDoc() )
		slotFileClose();

	KMFNewDocDlg *dlg = new KMFNewDocDlg( 0, "KMyFirewall - New Document", QWidget::WDestructiveClose | QWidget::WStyle_Customize | QWidget::WStyle_NoBorder );
	dlg->show();
	dlg->raise();
	connect( dlg, SIGNAL( sigNewDocLoadTemplate() ), this, SLOT( slotLoadTemplate() ) );
	connect( dlg, SIGNAL( sigNewDocLoadEmpty() ), this, SLOT( slotLoadEmptyRuleset() ) );
	connect( dlg, SIGNAL( sigNewDocLoadSaved() ), this, SLOT( slotFileOpen() ) );
}

void KMyFirewall::slotLoadEmptyRuleset() {
	kdDebug() << "slotLoadEmptyRuleset()" << endl;
	kmfdoc->clear();
	setCaption( i18n( "Untitled" ) );
	slotLoadDocument( kmfdoc );
	toggleActions( true );
	KMFAppState::setHasOpenDoc( true );
	emit sigHasDoc( KMFAppState::hasOpenDoc() );
	//	slotEditDocOptions();
}


//############# Save Stuff #################//

void KMyFirewall::slotFileSaveAs() {
	kdDebug() << "KMyFirewallMainView::slotFileSaveAs()" << endl;
	saveDocument( false );
}

void KMyFirewall::slotFileSaveAsTemplate() {
	kdDebug() << "KMyFirewallMainView::slotFileSaveAsTemplate()" << endl;
	saveDocument( true );
}



void KMyFirewall::slotFileSave() {
	// FIXME: reenable after ngeneric doc works
	/*	if ( kmfdoc->isSaved() ) {
			statusBar() ->message( i18n( "No changes to save." ) , 5000 );
			// 		actionSave->setEnabled( false );
			return ;
		}*/
	const KURL & url = kmfdoc->url();
	if ( url.fileName() != i18n( "Untitled" ) && ! isTemplate() ) {
		m_err = saveDocument( url );
		kdDebug() <<  "m_err" + m_err->errNum() << endl;
		if ( m_err_handler->showError( m_err ) ) {
			kdDebug() << "Wrote file: " << url.path() << endl;
			kmfdoc->saved();
			// 			actionSave->setEnabled( false );
			statusBar() ->message( i18n( "Wrote file: " ) + url.fileName(), 5000 );
		} else {
			statusBar() ->message( i18n( "Sorry could not write file: " ) + url.fileName(), 5000 );
			kdDebug() << "Sorry couldn't write File: " << url.fileName() << endl;
		}
	} else {
		slotFileSaveAs();
	}
}

KMFError* KMyFirewall::saveDocument( const KURL& url ) {
	kdDebug() << "void KMyFirewall::saveDocument( const KURL& url )" << endl;
	kdDebug() << "Writing File: " << url.fileName() << endl;

	m_err = kmfdoc->exportXMLRuleset( url );
	if ( m_err->errType() != KMFError::OK ) {
		return m_err;
	}
		
	kmfdoc->setUrl( url );
	if (  KMFConfig::useGenericInterface() ) {
		KMFConfig::setCurrentGenericConfiguration( url.url() );
	}	 else {
		KMFConfig::setCurrentIPTConfiguration( url.url() );
	}
	
	kdDebug() << "\nWrote URL: " << url.url() << "\n" << endl;
	QString filename = kmfdoc->url().fileName();
	setCaption( filename );
	m_err -> setErrType( KMFError::OK );
	m_err -> setErrMsg( "" );
	return m_err;
}

void KMyFirewall::saveDocument( bool asTemplate ) {
	QString xmlfile;
	KURL url;
	// bool chooseTemlate = false;
	QString path = ":";
	QString filter = "*.kmfrs|KMyFirewall IPTables Ruleset (*.kmfrs)";
	QString desc = i18n("|KMyFirewall IPTables Ruleset (*.kmfrs)");
	QString tdesc = i18n("KMyFirewall IPTables Ruleset Template (*.tkmfrs)");
	QString gdesc = i18n("|KMyFirewall Generic Ruleset (*.kmfgrs)");
	QString tgdesc = i18n("KMyFirewall Generic Ruleset Template (*.tkmfgrs)");
	
	KStandardDirs std_dir;
	QString tmp_dir = std_dir.findResourceDir( "data", "kmyfirewall/templates/" );
	QDir dir( tmp_dir + "/kmyfirewall/templates/" );
	
	if ( KMFConfig::useGenericInterface() ) {
		if ( asTemplate ) {
			filter = "*.tkmfgrs|" + tgdesc;
			path = dir.path();
		} else {
			filter = QString("*.kmfgrs|" + gdesc );
		}
	
	} else {
		if ( asTemplate ) {
			filter = QString("*.tkmfrs| " + tdesc );
			path = dir.path();
		} else {
			filter = QString("*.kmfrs|" +  desc );
		}
	}
	
	url = KFileDialog::getSaveURL( path, filter );
	QString filename = url.fileName();
	if ( url.fileName().isEmpty() )
		return ;
	int answer = 0;
	while ( answer != 3 ) {
		if ( KIO::NetAccess::exists( url, false, 0 ) ) {
			if ( answer == 4 ) {
				slotFileSaveAs();
				return ;
			} else {
				answer = KMessageBox::questionYesNo( this, i18n( "<qt>File <b>%1</b> already exists!</p>"
				                                     "<p><b>Overwrite the existing file?</b></p></qt>" ).arg( url.url() ) );
			}
		} else {
			answer = 3;
		}
	}
/*	if ( KMFConfig::useGenericInterface() ) {
		QString extention = filename.right( 7 );
		if ( extention != ".kmfgrs" ) {
			filename.append( ".kmfgrs" );
			url.setFileName( filename );
		}
	} else {
		QString extention = filename.right( 6 );
		if ( extention != ".kmfrs" ) {
			filename.append( ".kmfrs" );
			url.setFileName( filename );
		}
	}*/
	m_err = saveDocument( url );
	if ( m_err_handler->showError( m_err ) ) {
		kmfdoc->saved();
		// 		actionSave->setEnabled( false );
		statusBar() ->message( i18n( "Wrote File: " ) + url.fileName() , 5000 );
	} else {
		statusBar() ->message( i18n( "Sorry could not write file: " ) + url.fileName() , 5000 );
		kdDebug() << "Sorry couldn't write File: " << url.path() << endl;
	}
	kdDebug() << "Finished Saving" << endl;


}

//#############################################//

void KMyFirewall::slotConfigureKMF() {
	closeSplash();
	m_configDlg->slotReadConfig();
	m_configDlg->exec();
}

//################ Check Status #############//
// FIXME: Implement iptables active check

void KMyFirewall::checkStatus() {
	kdDebug() << "checkStatus()" << endl;
	m_iptables_saveOutput = new KTempFile();
//	statusBar() ->changeItem( i18n( "Not implement yet" ), 1 );
	FILE *sbin1;
	sbin1 = fopen( "/etc/kmyfirewall", "r" );

	if ( sbin1 != NULL ) {
		statusBar() ->changeItem( i18n( "Firewall is installed" ), 1 );
		fclose( sbin1 );
	} else {
		statusBar() ->changeItem( i18n( "Firewall is not installed" ), 1 );
	}
}

// FIXME: Implement iptables active check
void KMyFirewall::slotProcessExited( KProcess* p ) {
	kdDebug() << "void KMyFirewall::slotProcessExited(KProcess*)" << endl;
	kdDebug() << "ProcessName: " << p->name() << endl;
	// QTextStream *s = m_iptables_saveOutput->textStream();
	/*	QString str;
		while ( ! s->atEnd() ) { 
			str += s->readLine();
		}
		kdDebug() << "Tempfile content: " << str << endl;
		if ( m_processName == "iptables-save" ) {
			if ( str.stripWhiteSpace().isEmpty() ) {
				kdDebug() << "Firewall is not running" << endl;
				statusBar() ->changeItem( i18n("Firewall is not running"), 0 );
			} else {
				kdDebug() << "Firewall is running" << endl;
				statusBar() ->changeItem( i18n("Firewall is running"), 0 );
			}
		}*/
	m_iptables_saveOutput->close();
	m_iptables_saveOutput->unlink();
}

// FIXME: Implement iptables active check
void KMyFirewall::slotReceivedError( KProcess *, char *buffer, int buflen ) {
	kdDebug() << "void KMyFirewall::slotReceivedError(KProcess *, char *buffer, int buflen)" << endl;
	kdDebug() << "received string: " << QString::fromLatin1( buffer, buflen ) << endl;
}
// FIXME: Implement iptables active check
void KMyFirewall::slotReceivedOutput( KProcess *, char *buffer, int buflen ) {
	kdDebug() << "void KMyFirewall::slotReceivedOutput(KProcess *, char *buffer, int buflen) " << endl;
	kdDebug() << "Buffer: \n" << buffer << endl;
	if ( m_processName == "iptables-save" ) {
		QString tmp = QString::fromLatin1( buffer, buflen );
		if ( tmp.stripWhiteSpace().isEmpty() ) {
			statusBar() ->changeItem( i18n( "Firewall is not running" ), 0 );
		} else {
			statusBar() ->changeItem( i18n( "Firewall is running" ), 0 );
		}
	}
}

//############# UNDO ###################// 
void KMyFirewall::slotEnableUndo( bool onoff ) {
	kdDebug() << "void KMyFirewall::slotEnableUndo( bool " << onoff << " )" << endl;
	if ( ! KMFIPTDoc::maxUndo() ) {
		actionUndo->setEnabled( false );
		return ;
	}
	actionUndo->setEnabled( onoff );
}

void KMyFirewall::slotEnableRedo( bool onoff ) {
	kdDebug() << "void KMyFirewall::slotEnableUndo( bool " << onoff << " )" << endl;
	if ( ! KMFIPTDoc::maxUndo() ) {
		actionRedo->setEnabled( false );
		return ;
	}
	actionRedo->setEnabled( onoff );
}

//########### ACTION TOGGLES ################//
/** toggle the available actions  */
void KMyFirewall::toggleActions( bool on ) {
	if ( on ) {
		actionClose->setEnabled( true );
		actionSave->setEnabled( true );
		actionSaveAs->setEnabled( true );
		actionEditDocInfo->setEnabled( true );

		// diable new and open file
		actionNew->setEnabled( false );
		actionOpen->setEnabled( false );
		actionUndo->setEnabled( false );
		actionRedo->setEnabled( false );
		emit sigHasDoc( true );
		emit sigEnableActions( true );
	} else {
		actionClose->setEnabled( false );
		actionSave->setEnabled( false );
		actionSaveAs->setEnabled( false );
		actionEditDocInfo->setEnabled( false );
		actionUndo->setEnabled( false );
		actionRedo->setEnabled( false );

		// enable new and open file
		actionNew->setEnabled( true );
		actionOpen->setEnabled( true );
		emit sigHasDoc( false );
		emit sigEnableActions( false );
	}
}

bool KMyFirewall::hasOpenDoc() {
	return KMFAppState::hasOpenDoc();
}

bool KMyFirewall::isTemplate() {
	if ( ( kmfdoc->url().fileName().endsWith( "tkmfrs" ) || kmfdoc->url().fileName().endsWith( "tkmfgrs" ) ) ) {
		return true;
	}
	return false;
}

#include "kmyfirewall.moc"
