Plugin for regeltilvalg eller måltilvalg (kun IP-tabelgrænsefladen)

Eftersom værktøj for IP-tabelkommandoer udvikles meget hurtigt, og nye tilvalg tilføjes med nogle ugers mellemrum, er al håndtering af regeltilvalg flyttet ud til små plugin som er enkle at skrive.

Underliggende dokumentformater er konstrueret fleksibelt nok til at tillade implementering af alle kommandotilvalg som IP-tabeller kender til (eller vil kende til, hvis jeg ikke glemte noget).

Grænsefladen for at oprette regler kan udvides ved at registrere nye tilvalgs- og måltilvalgstyper definerede i små XML-filer som tolkes ved starten. Editorens grafiske grænseflade kan også indlejre de grafiske redigeringskontroller som behøves for at indstille regelvalgmulighederne.

Dele af et plugin for regeltilvalg eller måltilvalg

  • En XML-fil som for eksempel hedder kmfruleoption_mac_option.xml

  • En desktopfil, f. eks kmfruleoptionedit_mac.desktop som registrerer pluginnet i KDE's tjenesteskelet.

  • En KParts plugin eller klasse som enten afledes fra KMFRuleOptionEditInterface eller KMFRuleTargetOptionEditInterface, som f.eks. hedder KMFRuleOptionEditMAC.

  • En klasse som afledes fra QWidget som kan indlæses i editorvisningen når tilvalget redigeres.

    Mest sandsynligt bruger du Qt Designer til at oprette den grafiske grænseflade. Hvis du gør det skal du arve fra den genererede klasse.

XML-fil som beskriver regeltilvalget

XML-filen indlæses når programmet startes og registrerer det specifikke regeltilvalg i grænsefladen. Kig på nogle af de øvrige XML-filer som er installerede under $KDE-PREFIX/share/apps/kmyfirewall/ruleoptions, for nogle flere eksempler på hvordan de nødvendige valgmuligheder defineres.

<!DOCTYPE kmyfirewall-kmfruleoptiondefinition>
<ruleoptiondefinitionset>
<ruleoptiondefinition name="mac_opt"  guiName="MAC Address">
  <option guiName="" command="--match mac" />
  <option guiName="MAC:" command="--mac-source" />
</ruleoptiondefinition>
</ruleoptiondefinitionset>

Filen .desktop

Denne fil installeres i mappen services, og gør pluginnet tilgængeligt for KDE's pluginskelet.

Det vigtige her er at du angiver Type=Service og rette SeviceType. Programmet leder kun efter plugin med SeviceType=KMyFirewall/RuleOptionEdit eller SeviceType=KMyFirewall/RuleTargetOptionEdit.

Linjen X-KDE-Library=libkmfruleoptionedit_mac fortæller KDE's pluginskelet hvilket bibliotek som definerer funktionen.

[Desktop Entry]
Encoding=UTF-8
Type=Service
Name=KMyFirewall MAC option edit
Name[da]=KMyFirewall MAC redigeringstilvalg
Comment=Plugin for edition MAC address based iptables rule options
Comment[da]=Plugin ril at redigere MAC adressebaserede regeltilvalg for iptables
X-KDE-Library=libkmfruleoptionedit_mac
ServiceTypes=KMyFirewall/RuleOptionEdit

Filen Makefile.am

Sørg for at du tilføjer tilvalget -module $(KDE_PLUGIN) i <biblioteksnavn>_LDFLAGS. Ellers kan pluginnet ikke indlæses ved kørsel.

INCLUDES = -I../kmfwidgets -I../../ipteditor -I$(srcdir)/../interfaces $(all_includes)
METASOURCES = AUTO
kde_module_LTLIBRARIES =  libkmfruleoptionedit_mac.la

libkmfruleoptionedit_mac_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
libkmfruleoptionedit_mac_la_LIBADD = ../../core/libkmfcore.la ../../interfaces/libkmfinterfaces.la $(LIB_KPARTS)
noinst_HEADERS =  kmfruleoptioneditmac.h kmfruleeditmac.h

libkmfruleoptionedit_mac_la_SOURCES = kmfruleoptioneditmac.cpp kmfruleeditmac.cpp  kmyfirewallruleeditormac.ui

partdesktopdir = $(kde_servicesdir)
partdesktop_DATA = kmfruleoptionedit_mac.desktop

install-data-local:
        $(mkinstalldirs) $(DESTDIR)$(kde_datadir)/kmyfirewall/ruleoptions/
        $(INSTALL_DATA)  $(srcdir)/kmfruleoption_mac_option.xml $(DESTDIR)$(kde_datadir)/kmyfirewall/ruleoptions/kmfruleoption_mac_option.xml

uninstall-local:
        -rm -f $(DESTDIR)$(kde_datadir)/kmyfirewall/ruleoptions/kmfruleoption_mac_option.xml

KParts pluginkomponent eller -klasse

Denne klasse definerer pluginnet som indlæses når programmet startes.

kmfruleoptioneditmac.h

/***************************************************************************
    Copyright (C) 2004 Christian Hubinger
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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) 2004
#ifndef KMFRULEOPTIONEDITMAC_H
#define KMFRULEOPTIONEDITMAC_H

#include "../../interfaces/kmfruleoptioneditinterface.h"

// KDE includes
#include <kparts/part.h>
#include <kparts/plugin.h>
#include <kparts/factory.h>
#include <kxmlgui.h>

#include <qstring.h>
#include <qptrlist.h>

class IPTRule;
class KMFRuleEditMac;
/**
@author Christian Hubinger
*/
class KMFRuleOptionEditMAC : public KMFRuleOptionEditInterface {
        Q_OBJECT
public:
        KMFRuleOptionEditMAC(QObject *parent = 0, const char *name = 0);

        ~KMFRuleOptionEditMAC();
        void loadRule( IPTRule* rule );        
        QWidget* editWidget();
        const QString& optionEditName() const;
        const QString& description() const;

private slots:
        void slotAddRuleOption(QString*, QPtrList< QString >* );
        void slotAddTargetOption(QString*, QPtrList< QString >* );
        void slotShowOverview();

private:
        KMFRuleEditMac *m_edit;
        IPTRule *m_rule;
        
};

class KInstance;

class KMFRuleOptionEditMACFactory : public KLibFactory {
        Q_OBJECT
public:
        KMFRuleOptionEditMACFactory( QObject *parent = 0, const char *name = 0 );
        virtual ~KMFRuleOptionEditMACFactory() {
        };
        virtual QObject* createObject( QObject* parent = 0, const char* pname = 0,
                                       const char* name = "QObject",
                                       const QStringList &args = QStringList() );

};

kmfruleoptioneditmac.cpp

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

// QT includes
#include <qstring.h>

// KDE includes
#include <kdebug.h>
#include <klocale.h>

// Project includes
#include "../../core/iptrule.h"
#include "../../interfaces/kmfruleeditinterface.h"
#include "kmfruleeditmac.h"

// Constructor get out plugin into a valid state
KMFRuleOptionEditMAC::KMFRuleOptionEditMAC(QObject *parent, const char *name)
                : KMFRuleOptionEditInterface(parent, name) {
        
        // Initialise the editor class
        m_edit = new KMFRuleEditMac( 0 , "Edit", 0 );
        // hide it for now
        m_edit->hide();

        // Connect the Signals for the editor class to our slots passing them to the app
        connect( m_edit,SIGNAL(sigAddRuleOpt(QString*, QPtrList< QString >* ) ), 
                this,SLOT( slotAddRuleOption(QString*, QPtrList< QString >* ) ) );
        //
        //connect( m_edit,SIGNAL(sigAddTargetOpt(QString*, QPtrList< QString >* ) ), 
        //        this,SLOT( slotAddTargetOption(QString*, QPtrList< QString >* ) ) );
        connect( m_edit,SIGNAL(sigHideMe() ), 
                this,SLOT( slotShowOverview() ) );
}

KMFRuleOptionEditMAC::~KMFRuleOptionEditMAC() {}

// Slot to pass the Signals to the app 
void KMFRuleOptionEditMAC::slotAddRuleOption(QString* name, QPtrList< QString >* values ) {
        if ( KMFRuleEditInterface* ruleedit = dynamic_cast<KMFRuleEditInterface*> ( parent() ) ) {
                ruleedit->addRuleOption( name, values );
        } else {
                kdDebug() << "KMFRuleOptionEditMAC::slotAddRuleOption(): parent() not of type KMFRuleEditInterface" << endl;
        }
}
void KMFRuleOptionEditMAC::slotAddTargetOption(QString* name, QPtrList< QString >* values ) {
        if ( KMFRuleEditInterface* ruleedit = dynamic_cast<KMFRuleEditInterface*> ( parent() ) ) {
                ruleedit->addRuleTargetOption( name, values );
        } else {
                kdDebug() << "KMFRuleOptionEditMAC::slotAddTargetOption(): parent() not of type KMFRuleEditInterface" << endl;
        }
}

// Make the editor hide the plugin widget
void KMFRuleOptionEditMAC::slotShowOverview() {
        if ( KMFRuleEditInterface* ruleedit = dynamic_cast<KMFRuleEditInterface*> ( parent() ) ) {
                ruleedit->showOverview();
        } else {
                kdDebug() << "KMFRuleOptionEditMAC::slotShowOverview(): parent() not of type KMFRuleEditInterface" << endl;
        }
}


// Get info for GUI about the plugin
const QString& KMFRuleOptionEditMAC::optionEditName() const {
        return *( new QString( i18n("MAC Option") ) );
}
const QString& KMFRuleOptionEditMAC::description() const {
        return *( new QString( i18n("This plugin manages the MAC address based options of iptables.") ) );
}

// We must implement this as it is called from the underliening rule editor
void KMFRuleOptionEditMAC::loadRule( IPTRule* rule ) {
        if ( !rule ) {
                kdDebug() << "KMFRuleOptionEditMAC::loadRule( IPTRule* rule ) - rule == 0" <<endl;
                return;
        }
        m_edit->loadRule( rule );
        m_rule = rule;
}

// return a pointer to our editor widget
QWidget* KMFRuleOptionEditMAC::editWidget() {
        if ( ! m_edit ) {
                kdDebug() << "KMFRuleOptionEditMAC::editWidget() - m_edit == 0" << endl;
                return 0;
        }
        return m_edit;
}

// It's usually safe to leave the factory code alone.. with the
// notable exception of the KAboutData data
#include <kaboutdata.h>
#include <klocale.h>

// KInstance* KMFRuleOptionEditMACFactory::s_instance = 0L;
// KAboutData* KMFRuleOptionEditMACFactory::s_about = 0L;

KMFRuleOptionEditMACFactory::KMFRuleOptionEditMACFactory( QObject* parent, const char* name )
                : KLibFactory( parent, name ) {
}

QObject* KMFRuleOptionEditMACFactory::createObject( QObject* parent, const char* name,
        const char*, const QStringList & ) {
        QObject * obj = new KMFRuleOptionEditMAC( parent, name );
        emit objectCreated( obj );
        return obj;
}

extern "C" {
        void* init_libkmfruleoptionedit_mac() {
                return new KMFRuleOptionEditMACFactory;
        }
}
#include "kmfruleoptioneditmac.moc"

Den grafiske kontrolklasse for editoren

Denne klasse definerer en grafisk komponent som kan indstille det specifikke regeltilvalg.

kmfruleeditmac.h

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


#ifndef KMFRULEEDITMAC_H
#define KMFRULEEDITMAC_H

#include "kmyfirewallruleeditormac.h"

#include <qvariant.h>
#include <qdialog.h>
#include <qptrlist.h>

class IPTRule;
class KMFErrorHandler;
class KMFCheckInput;
class KMFError;

class KMFRuleEditMac : public KMyFirewallRuleEditorMac {
        Q_OBJECT

public:
        KMFRuleEditMac( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
        ~KMFRuleEditMac();

        void loadRule( IPTRule* );

public slots:
        void accept();
        void slotHelp();
        void reject();

protected:
        bool event( QEvent* );

private:
        KMFCheckInput *m_check_input;
        KMFErrorHandler *m_err_handler;
        KMFError *m_err;
        IPTRule* m_rule;

signals:
        void sigAddRuleOpt( QString*, QPtrList<QString>* );
        void sigHideMe();
};

#endif // KMFRULEEDITMAC_H

kmfruleeditmac.cpp

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

#include <qcheckbox.h>
#include <qframe.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qpushbutton.h>
#include <qlayout.h>
#include <qvariant.h>
#include <qtooltip.h>
#include <qwhatsthis.h>

#include <kdebug.h>
#include <kmessagebox.h>
#include <klocale.h>
#include <kapplication.h>

// project includes
#include "../../core/iptrule.h"
#include "../../core/iptchain.h"
#include "../../core/iptable.h"
#include "../../core/kmfdoc.h"
#include "../../core/kmfiptdoc.h"
#include "../../core/kmfcheckinput.h"
#include "../../core/kmferror.h"
#include "../../core/kmferrorhandler.h"

/*
 *  Constructs a KMFRuleEditMac which is a child of 'parent', with the
 *  name 'name' and widget flags set to 'f' 
 *
 *  The dialog will by default be modeless, unless you set 'modal' to
 *  TRUE to construct a modal dialog.
 */
KMFRuleEditMac::KMFRuleEditMac( QWidget* parent, const char* name, WFlags fl )
                : KMyFirewallRuleEditorMac( parent, name, fl ) {
        m_err_handler = new KMFErrorHandler( "KMFRuleEditMac" );
        m_check_input = new KMFCheckInput();
        m_err = new KMFError();


}

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

/*
 *  Main event handler. Reimplemented to handle application
 *  font changes
 */
bool KMFRuleEditMac::event( QEvent* ev ) {
        bool ret = QWidget::event( ev );
        if ( ev->type() == QEvent::ApplicationFontChange ) {}
        return ret;
}

void KMFRuleEditMac::loadRule( IPTRule * rule ) {
        kdDebug() << "void KMFRuleEditMac::loadRule( IPTRule * rule )" << endl,
        c_src_mac->setChecked( false );
        c_inv_src_mac->setChecked( false );
        t_src_mac1 ->clear();
        t_src_mac2 ->clear();
        t_src_mac3 ->clear();
        t_src_mac4 ->clear();
        t_src_mac5 ->clear();
        t_src_mac6 ->clear();
        m_rule = rule;
        QString line = "";

        IPTRuleOption* opt = 0;
        opt = m_rule->getOptionForName("mac_opt");
        if ( opt ) {
                QStringList args = opt->getValues();
                QString src, dest;
                line = *args.at(1);
                if ( line.isEmpty() || line == "UNDEFINED"  )
                        return;
                if ( line.startsWith( "! " ) ) {
                        line = line.right( line.length() - 2 );
                        c_inv_src_mac->setChecked( true );
                }
                int num = 1;
                QString part = "";
                c_src_mac->setChecked( true );
                while ( !line.isEmpty() ) {
                        int pos = -1;
                        pos = line.find( ":" );
                        if ( pos < 0 ) {
                                part = line;
                                line = "";
                        } else {
                                part = line.left( pos );
                                line = line.right( line.length() - ( pos + 1 ) );
                        }
                        switch ( num ) {
                                case 1:
                                        t_src_mac1 -> setText( part );
                                        break;
                                case 2:
                                        t_src_mac2 -> setText( part );
                                        break;
                                case 3:
                                        t_src_mac3 -> setText( part );
                                        break;
                                case 4:
                                        t_src_mac4 -> setText( part );
                                        break;
                                case 5:
                                        t_src_mac5 -> setText( part );
                                        break;
                                case 6:
                                        t_src_mac6 -> setText( part );
                                        break;
                        }
                        num++;
                }
        }
}


void KMFRuleEditMac::accept() {
        kdDebug() << "KMFRuleEditMac::accept()" << endl;
        m_rule->chain()->table()->kmfDoc()->startTransaction();
        m_rule->saveState();
        QString tok1 = t_src_mac1->text().upper();
        QString tok2 = t_src_mac2->text().upper();
        QString tok3 = t_src_mac3->text().upper();
        QString tok4 = t_src_mac4->text().upper();
        QString tok5 = t_src_mac5->text().upper();
        QString tok6 = t_src_mac6->text().upper();

        if ( c_src_mac->isChecked() && ( tok1.isEmpty() || tok2.isEmpty() || tok3.isEmpty() || tok4.isEmpty() || tok5.isEmpty() || tok6.isEmpty() ) ) {
                const QString & msg = i18n( "One ore more of the fields are empty. Please fill out all fields to define a valid MAC address." );
                KMessageBox::error( this, msg );
                m_rule->chain()->table()->kmfDoc()->endTransaction();
                return ;
        }

        QString mac = "";

        if ( c_src_mac->isChecked() ) {
                mac = tok1 + ":" + tok2 + ":" + tok3 + ":" + tok4 + ":" + tok5 + ":" + tok6;
                m_check_input->checkInput( mac, "MAC", m_err );
                if ( ! m_err_handler->showError( m_err ) ) {
                        m_rule->chain()->table()->kmfDoc()->endTransaction();
                        return ;
                }
        }

        QPtrList<QString
>* values = new QPtrList<QString>;
        QString* op = new QString( "mac_opt" );
        if ( c_src_mac->isChecked() && !mac.isEmpty() ) {
                kdDebug() << "Add new mac option" << endl;
                QString* src_mac = new QString( mac );
                if ( c_inv_src_mac->isChecked() ) {
                        src_mac->prepend( "! " );
                }
                values->append( new QString( "bool:on" ) );
                values->append( src_mac );
        }
        emit sigAddRuleOpt( op, values );
        m_rule->chain()->table()->kmfDoc()->endTransaction();
        emit sigHideMe();
}

void KMFRuleEditMac::slotHelp() {
        kdDebug() << "void KMFRuleEditMac::slotHelp()" << endl;
        kapp->invokeHelp( "src_mac" );
}
void KMFRuleEditMac::reject() {
        kdDebug() << "void KMFRuleEditMac::reject()" << endl;
        emit sigHideMe();
}
#include "kmfruleeditmac.moc"