]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - html/cgi-bin/base.cgi
SMP-Config angepasst.. CGIs usw. wurden im Windoof-Format gespeichert... muss noch...
[people/pmueller/ipfire-2.x.git] / html / cgi-bin / base.cgi
index cc11800f3c6ef6a9128e02707a2ef1bc162f2701..b98e991d489c82bc3ba5db592417fb29bf9de4e7 100644 (file)
-#!/usr/bin/perl\r
-#\r
-# IPCop CGI's - base.cgi\r
-#\r
-# This code is distributed under the terms of the GPL\r
-#\r
-# (c) place a name here\r
-#\r
-# $Id: base.cgi,v 1.1.2.10 2005/11/03 19:20:50 franck78 Exp $\r
-#\r
-#\r
-\r
-\r
-# This file is a starting base for writting a new GUI screen using the three box model\r
-#      Box 1 : global settings for the application\r
-#      Box 2 : line editor for multiple data line\r
-#      Box 3 : the list of data line, with edit/remove buttons\r
-#\r
-#      This example do the following\r
-#      Read global settings:\r
-#              a NAME and an interface (IT)\r
-#      Lines of data composed of:\r
-#              an ipaddress (IP), an enabled/disabled options (CB), a comment (CO)\r
-#\r
-#\r
-# All you need to do is\r
-#      replace 'XY' with your app name\r
-#      define your global $settings{'var name'}\r
-#      define your strings\r
-#      write validation code for Settings1 and Settings2\r
-#      write HTML box Settings1 and Settings2\r
-#      adapt the sort function\r
-#      write the correct configuration file\r
-#\r
-#\r
-# to fully troubleshot your code, uncomment diagnostics, Carp and cluck lines\r
-# use diagnostics; # need to add the file /usr/lib/perl5/5.8.x/pods/perldiag.pod before to work\r
-# next look at /var/log/httpd/error_log , http://www.perl.com/pub/a/2002/05/07/mod_perl.html may help\r
-#use warnings;\r
-use strict;\r
-#use Carp ();\r
-#local $SIG{__WARN__} = \&Carp::cluck;\r
-\r
-require '/var/ipcop/general-functions.pl';     # Replace all occurences of </var/ipcop> with CONFIG_ROOT\r
-                                               # before updating cvs IPCop file.\r
-require "${General::swroot}/lang.pl";\r
-require "${General::swroot}/header.pl";\r
-\r
-# Files used\r
-our $setting  = "${General::swroot}/XY/settings";              # particular settings\r
-my  $datafile = "${General::swroot}/XY/data";                  # repeted settings (multilines)\r
-our $conffile = "${General::swroot}/XY/XY.conf";               # Config file for application XY\r
-\r
-# strings to add to languages databases or in addon language file\r
-$Lang::tr{'XY title'}     = 'XY service';\r
-$Lang::tr{'XY settings'}  = 'XY setup';\r
-$Lang::tr{'XY add data'}  = 'add data';\r
-$Lang::tr{'XY edit data'} = 'edit data';\r
-$Lang::tr{'XY data'}      = 'XY data';\r
-\r
-# informationnal & log strings, no translation required\r
-my  $msg_added           = 'XY added';\r
-my  $msg_modified        = 'XY modified';\r
-my  $msg_deleted         = 'XY removed';\r
-my  $msg_datafileerror   = 'XY data file error';\r
-our $msg_configfileerror = 'XY configuration file error';\r
-\r
-my %settings=();\r
-\r
-# Settings1\r
-$settings{'NAME'} = '';                # a string field than must be 'GOOD' or 'good'\r
-$settings{'IT'} = '';          # a 'choose' field for color interface\r
-$settings{'TURBO'} = 'off';    # a checkbox field to enable something\r
-\r
-# Settings2 for editing the multi-line list\r
-# Must not be saved by writehash !\r
-$settings{'IP'} = '';                  # datalines are: IPaddress,enable,comment \r
-$settings{'CB'} = 'off';               # Every check box must be set to off\r
-$settings{'COMMENT'} = '';\r
-my @nosaved=('IP','CB','COMMENT');        # List here ALL setting2 fields. Mandatory\r
-\r
-$settings{'ACTION'} = '';              # add/edit/remove....\r
-$settings{'KEY1'} = '';                        # point record for ACTION\r
-\r
-# Define each field that can be used to sort columns\r
-my $sortstring='^IP|^COMMENT';\r
-my $errormessage = '';\r
-my $warnmessage = '';\r
-\r
-&Header::showhttpheaders();\r
-\r
-# Read needed Ipcop settings (exemple)\r
-my %mainsettings=();\r
-&General::readhash("${General::swroot}/main/settings", \%mainsettings);\r
-\r
-# Get GUI values\r
-&Header::getcgihash(\%settings);\r
-\r
-# Load multiline data. Do it before use in save action\r
-our $f = new Multilines (filename => $datafile,\r
-                        fields   => ['IP','CB','COMMENT'],\r
-                        comment  => 1\r
-                       );\r
-\r
-##\r
-## SAVE Settings1 \r
-##\r
-# Remove if no Settings1 needed\r
-if ($settings{'ACTION'} eq $Lang::tr{'save'}) {\r
-\r
-    #\r
-    #Validate static Settings1 here\r
-    #\r
-    if (($settings{"NAME"} ne "GOOD") &&\r
-       ($settings{"NAME"} ne "good"))    {\r
-       $errormessage = 'Enter good or GOOD in Name field';\r
-    }\r
-\r
-    unless ($errormessage) {                                   # Everything is ok, save settings\r
-       map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));# Must never be saved\r
-       &General::writehash($setting, \%settings);              # Save good settings\r
-       $settings{'ACTION'} = $Lang::tr{'save'};                # Recreate  'ACTION'\r
-       map ($settings{$_}= '',(@nosaved,'KEY1'));              # and reinit var to empty\r
-\r
-       # Rebuild configuration file if needed\r
-       &BuildConfiguration;\r
-    }\r
-\r
-    ERROR:                                             # Leave the faulty field untouched\r
-} else {\r
-    &General::readhash($setting, \%settings);                  # Get saved settings and reset to good if needed\r
-}\r
-\r
-##\r
-## Now manipulate the multiline list with Settings2\r
-##\r
-\r
-# Basic actions are:\r
-#      toggle the check box\r
-#      add/update a new line\r
-#      begin editing a line\r
-#      remove a line\r
-# $KEY1 contains the index of the line manipulated\r
-\r
-##\r
-## Toggle CB field.\r
-##\r
-if ($settings{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {\r
-\r
-    $f->togglebyfields($settings{'KEY1'},'CB');                # toggle checkbox\r
-    $settings{'KEY1'} = '';                            # End edit mode\r
-\r
-    &General::log($msg_modified);\r
-\r
-    # save changes\r
-    $f->savedata || die "$msg_datafileerror";\r
-\r
-    # Rebuild configuration file\r
-    &BuildConfiguration;\r
-}\r
-\r
-##\r
-## ADD/UPDATE a line of configuration from Settings2\r
-##\r
-if ($settings{'ACTION'} eq $Lang::tr{'add'}) {\r
-    # Validate inputs\r
-    if (! &General::validip($settings{'IP'})) {$errormessage = "Specify an IP value !"};\r
-    if (! $settings{'COMMENT'} ) {$warnmessage = "no comment specified"};\r
-\r
-    unless ($errormessage) {\r
-       if ($settings{'KEY1'} eq '') { #add or edit ?\r
-           # insert new data line\r
-           $f->writedata(-1, $settings{'IP'},$settings{'CB'},$settings{'COMMENT'});\r
-           &General::log($msg_added);\r
-       } else {\r
-           # modify data line\r
-           $f->writedata($settings{'KEY1'}, $settings{'IP'},$settings{'CB'},$settings{'COMMENT'});\r
-           $settings{'KEY1'} = '';       # End edit mode\r
-           &General::log($msg_modified);\r
-       }\r
-       # save changes\r
-       $f->savedata || die "$msg_datafileerror";\r
-\r
-       # Rebuild configuration file\r
-       &BuildConfiguration;\r
-\r
-       # if entering data line is a repetitive task, choose here to not erase fields between each addition\r
-       map ($settings{$_}='' ,@nosaved);\r
-    }\r
-}\r
-\r
-##\r
-## begin EDIT: move data fields to Settings2 controls\r
-##\r
-if ($settings{'ACTION'} eq $Lang::tr{'edit'}) {\r
-    $f->readdata ($settings{'KEY1'},\r
-                 $settings{'IP'},\r
-                 $settings{'CB'},\r
-                 $settings{'COMMENT'});\r
-}\r
-##\r
-## REMOVE: remove selected line\r
-##\r
-if ($settings{'ACTION'} eq $Lang::tr{'remove'}) {\r
-    $f->deleteline ($settings{'KEY1'});\r
-    $settings{'KEY1'} = '';                            # End remove mode\r
-    &General::log($msg_deleted);\r
-\r
-    # save changes\r
-    $f->savedata || die "$msg_datafileerror";\r
-\r
-    # Rebuild configuration file\r
-    &BuildConfiguration;\r
-}\r
-\r
-\r
-##\r
-## Check if sorting is asked\r
-##\r
-if ($ENV{'QUERY_STRING'} =~ /$sortstring/ ) {\r
-    my $newsort=$ENV{'QUERY_STRING'};\r
-    my $actual=$settings{'SORT_XY'};\r
-\r
-    # Reverse actual sort or choose new column ?\r
-    if ($actual =~ $newsort) {\r
-       $f->setsortorder ($newsort ,rindex($actual,'Rev'));\r
-       $newsort .= rindex($actual,'Rev')==-1 ? 'Rev' : '';\r
-    } else {\r
-       $f->setsortorder ($newsort ,1);\r
-    }\r
-    $f->savedata;                                              # Synchronise file & display\r
-    $settings{'SORT_XY'} = $newsort;\r
-    map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));  # Must never be saved\r
-    &General::writehash($setting, \%settings);\r
-    $settings{'ACTION'} = 'SORT';                              # Recreate an 'ACTION'\r
-    map ($settings{$_}= '',(@nosaved,,'KEY1'));                        # and reinit var to empty\r
-}\r
-\r
-##\r
-## Remove if no Setting1 needed\r
-##\r
-if ($settings{'ACTION'} eq '' ) { # First launch from GUI\r
-    # Place here default value when nothing is initialized\r
-\r
-}\r
-\r
-&Header::openpage($Lang::tr{'XY title'}, 1, '');\r
-&Header::openbigbox('100%', 'left', '', $errormessage);\r
-my %checked =();     # Checkbox manipulations\r
-\r
-if ($errormessage) {\r
-    &Header::openbox('100%', 'left', $Lang::tr{'error messages'});\r
-    print "<font class='base'>$errormessage&nbsp;</font>";\r
-    &Header::closebox();\r
-}\r
-\r
-##\r
-## First box Settings1. Remove if not needed\r
-##\r
-$warnmessage = "<font color=${Header::colourred}><b>$Lang::tr{'capswarning'}</b></font>: $warnmessage" if ($warnmessage);\r
-\r
-&Header::openbox('100%', 'left', $Lang::tr{'XY settings'});\r
-print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>";\r
-$checked{'IT'}{'RED'} = '';\r
-$checked{'IT'}{'GREEN'} = '';\r
-$checked{'IT'}{'ORANGE'} = '';\r
-$checked{'IT'}{'BLUE'} = '';\r
-$checked{'IT'}{$settings{'IT'}} = "checked='checked'";\r
-$checked{'TURBO'} = ($settings{'TURBO'} eq 'on') ? "checked='checked'" : '';\r
-\r
-print<<END\r
-<table width='100%'>\r
-<tr>\r
-    <td class='base'>Name:</td>\r
-    <td><input type='text' name='NAME' value='$settings{'NAME'}' /></td>\r
-    <td align='right'>INTERFACE</td>\r
-    <td align='right'>red<input type='radio' name='IT' value='RED' $checked{'IT'}{'RED'} /></td>\r
-</tr><tr>\r
-    <td>Turbo:</td>\r
-    <td><input type='checkbox' name='TURBO' $checked{'TURBO'}' /></td>\r
-    <td></td>\r
-    <td align='right'>green<input type='radio' name='IT' value='GREEN' $checked{'IT'}{'GREEN'} /></td>\r
-</tr><tr>\r
-    <td></td>\r
-    <td></td>\r
-    <td></td>\r
-    <td align='right'>blue<input type='radio' name='IT' value='BLUE' $checked{'IT'}{'BLUE'} /></td>\r
-</tr><tr>\r
-    <td></td>\r
-    <td></td>\r
-    <td></td>\r
-    <td align='right'>orange<input type='radio' name='IT' value='ORANGE' $checked{'IT'}{'ORANGE'} /></td>\r
-</tr>\r
-</table>\r
-<br />\r
-END\r
-;\r
-\r
-print<<END\r
-<table width='100%'>\r
-<hr />\r
-<tr>\r
-    <td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' />&nbsp;$Lang::tr{'this field may be blank'}</td>\r
-    <td class='base' width='25%'>$warnmessage</td>\r
-    <td width='50%' align='center'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>\r
-</tr>\r
-</table>\r
-</form>\r
-END\r
-;\r
-&Header::closebox();   # end of Settings1\r
-\r
-##\r
-## Second box is for editing the an item of the list\r
-##\r
-$checked{'CB'} = ($settings{'CB'} eq 'on') ? "checked='checked'" : '';\r
-\r
-my $buttontext = $Lang::tr{'add'};\r
-if ($settings{'KEY1'} ne '') {\r
-    $buttontext = $Lang::tr{'update'};\r
-    &Header::openbox('100%', 'left', $Lang::tr{'XY edit data'});\r
-} else {\r
-    &Header::openbox('100%', 'left', $Lang::tr{'XY add data'});\r
-}\r
-\r
-# Edited line number (KEY1) passed until cleared by 'save' or 'remove' or 'new sort order'\r
-print <<END\r
-<form method='post' action='$ENV{'SCRIPT_NAME'}'>\r
-<input type='hidden' name='KEY1' value='$settings{'KEY1'}' />\r
-<table width='100%'>\r
-<tr>\r
-    <td class='base'>$Lang::tr{'ip address'}:</td>\r
-    <td><input type='text' name='IP' value='$settings{'IP'}' /></td>\r
-    <td class='base'>$Lang::tr{'enabled'}</td>\r
-    <td><input type='checkbox' name='CB' $checked{'CB'} /></td>\r
-    <td class='base'>$Lang::tr{'remark'}:&nbsp;<img src='/blob.gif' alt='*' /></td>\r
-    <td><input type 'text' name='COMMENT' value='$settings{'COMMENT'}' /></td>\r
-</tr>\r
-</table>\r
-<hr />\r
-<table width='100%'>\r
-<tr>\r
-    <td class='base' width='50%'><img src='/blob.gif' align='top' alt='*' />&nbsp;$Lang::tr{'this field may be blank'}</td>\r
-    <td width='50%' align='center'><input type='hidden' name='ACTION' value='$Lang::tr{'add'}' /><input type='submit' name='SUBMIT' value='$buttontext' /></td>\r
-</tr>\r
-</table>\r
-</form>\r
-END\r
-;\r
-&Header::closebox();\r
-\r
-##\r
-## Third box shows the list\r
-##\r
-\r
-# Columns headers may be a sort link. In this case it must be named in $sortstring\r
-&Header::openbox('100%', 'left', $Lang::tr{'XY data'});\r
-print <<END\r
-<table width='100%'>\r
-<tr>\r
-    <td width='20%' align='center'><a href='$ENV{'SCRIPT_NAME'}?IP'><b>$Lang::tr{'ip address'}</b></a></td>\r
-    <td width='70%' align='center'><a href='$ENV{'SCRIPT_NAME'}?COMMENT'><b>$Lang::tr{'remark'}</b></a></td>\r
-    <td width='10%' colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></td>\r
-</tr>\r
-END\r
-;\r
-\r
-##\r
-## Print each line of @current list\r
-##\r
-my $key = 0;\r
-$f->readreset; # beginning of data\r
-for ($key=0; $key<$f->getnumberofline; $key++) {\r
-\r
-    my($cb,$comment,$ip) = $f->readbyfieldsseq($key,'CB','COMMENT','IP');\r
-\r
-    #Choose icon for checkbox\r
-    my $gif = '';\r
-    my $gdesc = '';\r
-    if ($cb eq "on") {\r
-       $gif = 'on.gif';\r
-       $gdesc = $Lang::tr{'click to disable'};\r
-    } else {\r
-       $gif = 'off.gif';\r
-       $gdesc = $Lang::tr{'click to enable'};\r
-    }\r
-\r
-    #Colorize each line\r
-    if ($settings{'KEY1'} eq $key) {\r
-       print "<tr bgcolor='${Header::colouryellow}'>";\r
-    } elsif ($key % 2) {\r
-       print "<tr bgcolor='${Header::table2colour}'>";\r
-    } else {\r
-       print "<tr bgcolor='${Header::table1colour}'>"; \r
-    }\r
-\r
-    print <<END\r
-<td align='center'>$ip</td>\r
-<td align='center'>$comment</td>\r
-\r
-<td align='center'>\r
-<form method='post' action='$ENV{'SCRIPT_NAME'}'>\r
-<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />\r
-<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />\r
-<input type='hidden' name='KEY1' value='$key' />\r
-</form>\r
-</td>\r
-\r
-<td align='center'>\r
-<form method='post' action='$ENV{'SCRIPT_NAME'}'>\r
-<input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />\r
-<input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />\r
-<input type='hidden' name='KEY1' value='$key' />\r
-</form>\r
-</td>\r
-\r
-<td align='center'>\r
-<form method='post' action='$ENV{'SCRIPT_NAME'}'>\r
-<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />\r
-<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />\r
-<input type='hidden' name='KEY1' value='$key' />\r
-</form>\r
-</td>\r
-</tr>\r
-END\r
-;\r
-} print "</table>";\r
-\r
-# If table contains entries, print 'Key to action icons'\r
-if ($key) {\r
-print <<END\r
-<table>\r
-<tr>\r
-    <td class='boldbase'>&nbsp;<b>$Lang::tr{'legend'}:&nbsp;</b></td>\r
-    <td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>\r
-    <td class='base'>$Lang::tr{'click to disable'}</td>\r
-    <td>&nbsp;&nbsp;</td>\r
-    <td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>\r
-    <td class='base'>$Lang::tr{'click to enable'}</td>\r
-    <td>&nbsp;&nbsp;</td>\r
-    <td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>\r
-    <td class='base'>$Lang::tr{'edit'}</td>\r
-    <td>&nbsp;&nbsp;</td>\r
-    <td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>\r
-    <td class='base'>$Lang::tr{'remove'}</td>\r
-</tr>\r
-</table>\r
-END\r
-;\r
-}\r
-\r
-&Header::closebox();\r
-&Header::closebigbox();\r
-&Header::closepage();\r
-\r
-## Ouf it's the end !\r
-\r
-##\r
-## Build the configuration file for application XY\r
-##\r
-sub BuildConfiguration {\r
-    open(FILE, ">/$conffile") or die "$msg_configfileerror";\r
-    flock(FILE, 2);\r
-\r
-    #Global settings\r
-    print FILE "#\n#  Configuration file for application XY\n#\n\n";\r
-    print FILE "#     do not edit manually\n";\r
-    print FILE "#     build for Ipcop:$mainsettings{'HOSTNAME'}\n\n\n";\r
-    print FILE "service=$settings{'NAME'}\n";\r
-    print FILE "activate-turbo\n" if $settings{'TURBO'} eq 'on';\r
-    print FILE "interface=$settings{'IT'}\n\n\n";\r
-    #write data line\r
-    {\r
-       my ($IP,$CB,$COMMENT);\r
-       $f->readreset;\r
-       while (defined ($f->readdataseq($IP,$CB,$COMMENT))) {\r
-           if ($CB eq "on") {\r
-               print FILE "$IP\t\t\t\t\t#$COMMENT\n";\r
-           } else {\r
-               print FILE "#DISABLED $IP\t\t\t\t#$COMMENT\n";\r
-           }\r
-       }\r
-    }\r
-    close FILE;\r
-\r
-    # Restart service\r
-    #system '/usr/local/bin/restartyourhelper';\r
-}\r
+#!/usr/bin/perl
+#
+# IPCop CGI's - base.cgi
+#
+# This code is distributed under the terms of the GPL
+#
+# (c) place a name here
+#
+# $Id: base.cgi,v 1.1.2.10 2005/11/03 19:20:50 franck78 Exp $
+#
+#
+
+
+# This file is a starting base for writting a new GUI screen using the three box model
+#      Box 1 : global settings for the application
+#      Box 2 : line editor for multiple data line
+#      Box 3 : the list of data line, with edit/remove buttons
+#
+#      This example do the following
+#      Read global settings:
+#              a NAME and an interface (IT)
+#      Lines of data composed of:
+#              an ipaddress (IP), an enabled/disabled options (CB), a comment (CO)
+#
+#
+# All you need to do is
+#      replace 'XY' with your app name
+#      define your global $settings{'var name'}
+#      define your strings
+#      write validation code for Settings1 and Settings2
+#      write HTML box Settings1 and Settings2
+#      adapt the sort function
+#      write the correct configuration file
+#
+#
+# to fully troubleshot your code, uncomment diagnostics, Carp and cluck lines
+# use diagnostics; # need to add the file /usr/lib/perl5/5.8.x/pods/perldiag.pod before to work
+# next look at /var/log/httpd/error_log , http://www.perl.com/pub/a/2002/05/07/mod_perl.html may help
+#use warnings;
+use strict;
+#use Carp ();
+#local $SIG{__WARN__} = \&Carp::cluck;
+
+require '/var/ipcop/general-functions.pl';     # Replace all occurences of </var/ipcop> with CONFIG_ROOT
+                                               # before updating cvs IPCop file.
+require "${General::swroot}/lang.pl";
+require "${General::swroot}/header.pl";
+
+# Files used
+our $setting  = "${General::swroot}/XY/settings";              # particular settings
+my  $datafile = "${General::swroot}/XY/data";                  # repeted settings (multilines)
+our $conffile = "${General::swroot}/XY/XY.conf";               # Config file for application XY
+
+# strings to add to languages databases or in addon language file
+$Lang::tr{'XY title'}     = 'XY service';
+$Lang::tr{'XY settings'}  = 'XY setup';
+$Lang::tr{'XY add data'}  = 'add data';
+$Lang::tr{'XY edit data'} = 'edit data';
+$Lang::tr{'XY data'}      = 'XY data';
+
+# informationnal & log strings, no translation required
+my  $msg_added           = 'XY added';
+my  $msg_modified        = 'XY modified';
+my  $msg_deleted         = 'XY removed';
+my  $msg_datafileerror   = 'XY data file error';
+our $msg_configfileerror = 'XY configuration file error';
+
+my %settings=();
+
+# Settings1
+$settings{'NAME'} = '';                # a string field than must be 'GOOD' or 'good'
+$settings{'IT'} = '';          # a 'choose' field for color interface
+$settings{'TURBO'} = 'off';    # a checkbox field to enable something
+
+# Settings2 for editing the multi-line list
+# Must not be saved by writehash !
+$settings{'IP'} = '';                  # datalines are: IPaddress,enable,comment 
+$settings{'CB'} = 'off';               # Every check box must be set to off
+$settings{'COMMENT'} = '';
+my @nosaved=('IP','CB','COMMENT');        # List here ALL setting2 fields. Mandatory
+
+$settings{'ACTION'} = '';              # add/edit/remove....
+$settings{'KEY1'} = '';                        # point record for ACTION
+
+# Define each field that can be used to sort columns
+my $sortstring='^IP|^COMMENT';
+my $errormessage = '';
+my $warnmessage = '';
+
+&Header::showhttpheaders();
+
+# Read needed Ipcop settings (exemple)
+my %mainsettings=();
+&General::readhash("${General::swroot}/main/settings", \%mainsettings);
+
+# Get GUI values
+&Header::getcgihash(\%settings);
+
+# Load multiline data. Do it before use in save action
+our $f = new Multilines (filename => $datafile,
+                        fields   => ['IP','CB','COMMENT'],
+                        comment  => 1
+                       );
+
+##
+## SAVE Settings1 
+##
+# Remove if no Settings1 needed
+if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
+
+    #
+    #Validate static Settings1 here
+    #
+    if (($settings{"NAME"} ne "GOOD") &&
+       ($settings{"NAME"} ne "good"))    {
+       $errormessage = 'Enter good or GOOD in Name field';
+    }
+
+    unless ($errormessage) {                                   # Everything is ok, save settings
+       map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));# Must never be saved
+       &General::writehash($setting, \%settings);              # Save good settings
+       $settings{'ACTION'} = $Lang::tr{'save'};                # Recreate  'ACTION'
+       map ($settings{$_}= '',(@nosaved,'KEY1'));              # and reinit var to empty
+
+       # Rebuild configuration file if needed
+       &BuildConfiguration;
+    }
+
+    ERROR:                                             # Leave the faulty field untouched
+} else {
+    &General::readhash($setting, \%settings);                  # Get saved settings and reset to good if needed
+}
+
+##
+## Now manipulate the multiline list with Settings2
+##
+
+# Basic actions are:
+#      toggle the check box
+#      add/update a new line
+#      begin editing a line
+#      remove a line
+# $KEY1 contains the index of the line manipulated
+
+##
+## Toggle CB field.
+##
+if ($settings{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {
+
+    $f->togglebyfields($settings{'KEY1'},'CB');                # toggle checkbox
+    $settings{'KEY1'} = '';                            # End edit mode
+
+    &General::log($msg_modified);
+
+    # save changes
+    $f->savedata || die "$msg_datafileerror";
+
+    # Rebuild configuration file
+    &BuildConfiguration;
+}
+
+##
+## ADD/UPDATE a line of configuration from Settings2
+##
+if ($settings{'ACTION'} eq $Lang::tr{'add'}) {
+    # Validate inputs
+    if (! &General::validip($settings{'IP'})) {$errormessage = "Specify an IP value !"};
+    if (! $settings{'COMMENT'} ) {$warnmessage = "no comment specified"};
+
+    unless ($errormessage) {
+       if ($settings{'KEY1'} eq '') { #add or edit ?
+           # insert new data line
+           $f->writedata(-1, $settings{'IP'},$settings{'CB'},$settings{'COMMENT'});
+           &General::log($msg_added);
+       } else {
+           # modify data line
+           $f->writedata($settings{'KEY1'}, $settings{'IP'},$settings{'CB'},$settings{'COMMENT'});
+           $settings{'KEY1'} = '';       # End edit mode
+           &General::log($msg_modified);
+       }
+       # save changes
+       $f->savedata || die "$msg_datafileerror";
+
+       # Rebuild configuration file
+       &BuildConfiguration;
+
+       # if entering data line is a repetitive task, choose here to not erase fields between each addition
+       map ($settings{$_}='' ,@nosaved);
+    }
+}
+
+##
+## begin EDIT: move data fields to Settings2 controls
+##
+if ($settings{'ACTION'} eq $Lang::tr{'edit'}) {
+    $f->readdata ($settings{'KEY1'},
+                 $settings{'IP'},
+                 $settings{'CB'},
+                 $settings{'COMMENT'});
+}
+##
+## REMOVE: remove selected line
+##
+if ($settings{'ACTION'} eq $Lang::tr{'remove'}) {
+    $f->deleteline ($settings{'KEY1'});
+    $settings{'KEY1'} = '';                            # End remove mode
+    &General::log($msg_deleted);
+
+    # save changes
+    $f->savedata || die "$msg_datafileerror";
+
+    # Rebuild configuration file
+    &BuildConfiguration;
+}
+
+
+##
+## Check if sorting is asked
+##
+if ($ENV{'QUERY_STRING'} =~ /$sortstring/ ) {
+    my $newsort=$ENV{'QUERY_STRING'};
+    my $actual=$settings{'SORT_XY'};
+
+    # Reverse actual sort or choose new column ?
+    if ($actual =~ $newsort) {
+       $f->setsortorder ($newsort ,rindex($actual,'Rev'));
+       $newsort .= rindex($actual,'Rev')==-1 ? 'Rev' : '';
+    } else {
+       $f->setsortorder ($newsort ,1);
+    }
+    $f->savedata;                                              # Synchronise file & display
+    $settings{'SORT_XY'} = $newsort;
+    map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));  # Must never be saved
+    &General::writehash($setting, \%settings);
+    $settings{'ACTION'} = 'SORT';                              # Recreate an 'ACTION'
+    map ($settings{$_}= '',(@nosaved,,'KEY1'));                        # and reinit var to empty
+}
+
+##
+## Remove if no Setting1 needed
+##
+if ($settings{'ACTION'} eq '' ) { # First launch from GUI
+    # Place here default value when nothing is initialized
+
+}
+
+&Header::openpage($Lang::tr{'XY title'}, 1, '');
+&Header::openbigbox('100%', 'left', '', $errormessage);
+my %checked =();     # Checkbox manipulations
+
+if ($errormessage) {
+    &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
+    print "<font class='base'>$errormessage&nbsp;</font>";
+    &Header::closebox();
+}
+
+##
+## First box Settings1. Remove if not needed
+##
+$warnmessage = "<font color=${Header::colourred}><b>$Lang::tr{'capswarning'}</b></font>: $warnmessage" if ($warnmessage);
+
+&Header::openbox('100%', 'left', $Lang::tr{'XY settings'});
+print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>";
+$checked{'IT'}{'RED'} = '';
+$checked{'IT'}{'GREEN'} = '';
+$checked{'IT'}{'ORANGE'} = '';
+$checked{'IT'}{'BLUE'} = '';
+$checked{'IT'}{$settings{'IT'}} = "checked='checked'";
+$checked{'TURBO'} = ($settings{'TURBO'} eq 'on') ? "checked='checked'" : '';
+
+print<<END
+<table width='100%'>
+<tr>
+    <td class='base'>Name:</td>
+    <td><input type='text' name='NAME' value='$settings{'NAME'}' /></td>
+    <td align='right'>INTERFACE</td>
+    <td align='right'>red<input type='radio' name='IT' value='RED' $checked{'IT'}{'RED'} /></td>
+</tr><tr>
+    <td>Turbo:</td>
+    <td><input type='checkbox' name='TURBO' $checked{'TURBO'}' /></td>
+    <td></td>
+    <td align='right'>green<input type='radio' name='IT' value='GREEN' $checked{'IT'}{'GREEN'} /></td>
+</tr><tr>
+    <td></td>
+    <td></td>
+    <td></td>
+    <td align='right'>blue<input type='radio' name='IT' value='BLUE' $checked{'IT'}{'BLUE'} /></td>
+</tr><tr>
+    <td></td>
+    <td></td>
+    <td></td>
+    <td align='right'>orange<input type='radio' name='IT' value='ORANGE' $checked{'IT'}{'ORANGE'} /></td>
+</tr>
+</table>
+<br />
+END
+;
+
+print<<END
+<table width='100%'>
+<hr />
+<tr>
+    <td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' />&nbsp;$Lang::tr{'this field may be blank'}</td>
+    <td class='base' width='25%'>$warnmessage</td>
+    <td width='50%' align='center'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>
+</tr>
+</table>
+</form>
+END
+;
+&Header::closebox();   # end of Settings1
+
+##
+## Second box is for editing the an item of the list
+##
+$checked{'CB'} = ($settings{'CB'} eq 'on') ? "checked='checked'" : '';
+
+my $buttontext = $Lang::tr{'add'};
+if ($settings{'KEY1'} ne '') {
+    $buttontext = $Lang::tr{'update'};
+    &Header::openbox('100%', 'left', $Lang::tr{'XY edit data'});
+} else {
+    &Header::openbox('100%', 'left', $Lang::tr{'XY add data'});
+}
+
+# Edited line number (KEY1) passed until cleared by 'save' or 'remove' or 'new sort order'
+print <<END
+<form method='post' action='$ENV{'SCRIPT_NAME'}'>
+<input type='hidden' name='KEY1' value='$settings{'KEY1'}' />
+<table width='100%'>
+<tr>
+    <td class='base'>$Lang::tr{'ip address'}:</td>
+    <td><input type='text' name='IP' value='$settings{'IP'}' /></td>
+    <td class='base'>$Lang::tr{'enabled'}</td>
+    <td><input type='checkbox' name='CB' $checked{'CB'} /></td>
+    <td class='base'>$Lang::tr{'remark'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
+    <td><input type 'text' name='COMMENT' value='$settings{'COMMENT'}' /></td>
+</tr>
+</table>
+<hr />
+<table width='100%'>
+<tr>
+    <td class='base' width='50%'><img src='/blob.gif' align='top' alt='*' />&nbsp;$Lang::tr{'this field may be blank'}</td>
+    <td width='50%' align='center'><input type='hidden' name='ACTION' value='$Lang::tr{'add'}' /><input type='submit' name='SUBMIT' value='$buttontext' /></td>
+</tr>
+</table>
+</form>
+END
+;
+&Header::closebox();
+
+##
+## Third box shows the list
+##
+
+# Columns headers may be a sort link. In this case it must be named in $sortstring
+&Header::openbox('100%', 'left', $Lang::tr{'XY data'});
+print <<END
+<table width='100%'>
+<tr>
+    <td width='20%' align='center'><a href='$ENV{'SCRIPT_NAME'}?IP'><b>$Lang::tr{'ip address'}</b></a></td>
+    <td width='70%' align='center'><a href='$ENV{'SCRIPT_NAME'}?COMMENT'><b>$Lang::tr{'remark'}</b></a></td>
+    <td width='10%' colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></td>
+</tr>
+END
+;
+
+##
+## Print each line of @current list
+##
+my $key = 0;
+$f->readreset; # beginning of data
+for ($key=0; $key<$f->getnumberofline; $key++) {
+
+    my($cb,$comment,$ip) = $f->readbyfieldsseq($key,'CB','COMMENT','IP');
+
+    #Choose icon for checkbox
+    my $gif = '';
+    my $gdesc = '';
+    if ($cb eq "on") {
+       $gif = 'on.gif';
+       $gdesc = $Lang::tr{'click to disable'};
+    } else {
+       $gif = 'off.gif';
+       $gdesc = $Lang::tr{'click to enable'};
+    }
+
+    #Colorize each line
+    if ($settings{'KEY1'} eq $key) {
+       print "<tr bgcolor='${Header::colouryellow}'>";
+    } elsif ($key % 2) {
+       print "<tr bgcolor='${Header::table2colour}'>";
+    } else {
+       print "<tr bgcolor='${Header::table1colour}'>"; 
+    }
+
+    print <<END
+<td align='center'>$ip</td>
+<td align='center'>$comment</td>
+
+<td align='center'>
+<form method='post' action='$ENV{'SCRIPT_NAME'}'>
+<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
+<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
+<input type='hidden' name='KEY1' value='$key' />
+</form>
+</td>
+
+<td align='center'>
+<form method='post' action='$ENV{'SCRIPT_NAME'}'>
+<input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
+<input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
+<input type='hidden' name='KEY1' value='$key' />
+</form>
+</td>
+
+<td align='center'>
+<form method='post' action='$ENV{'SCRIPT_NAME'}'>
+<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
+<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
+<input type='hidden' name='KEY1' value='$key' />
+</form>
+</td>
+</tr>
+END
+;
+} print "</table>";
+
+# If table contains entries, print 'Key to action icons'
+if ($key) {
+print <<END
+<table>
+<tr>
+    <td class='boldbase'>&nbsp;<b>$Lang::tr{'legend'}:&nbsp;</b></td>
+    <td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
+    <td class='base'>$Lang::tr{'click to disable'}</td>
+    <td>&nbsp;&nbsp;</td>
+    <td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
+    <td class='base'>$Lang::tr{'click to enable'}</td>
+    <td>&nbsp;&nbsp;</td>
+    <td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
+    <td class='base'>$Lang::tr{'edit'}</td>
+    <td>&nbsp;&nbsp;</td>
+    <td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
+    <td class='base'>$Lang::tr{'remove'}</td>
+</tr>
+</table>
+END
+;
+}
+
+&Header::closebox();
+&Header::closebigbox();
+&Header::closepage();
+
+## Ouf it's the end !
+
+##
+## Build the configuration file for application XY
+##
+sub BuildConfiguration {
+    open(FILE, ">/$conffile") or die "$msg_configfileerror";
+    flock(FILE, 2);
+
+    #Global settings
+    print FILE "#\n#  Configuration file for application XY\n#\n\n";
+    print FILE "#     do not edit manually\n";
+    print FILE "#     build for Ipcop:$mainsettings{'HOSTNAME'}\n\n\n";
+    print FILE "service=$settings{'NAME'}\n";
+    print FILE "activate-turbo\n" if $settings{'TURBO'} eq 'on';
+    print FILE "interface=$settings{'IT'}\n\n\n";
+    #write data line
+    {
+       my ($IP,$CB,$COMMENT);
+       $f->readreset;
+       while (defined ($f->readdataseq($IP,$CB,$COMMENT))) {
+           if ($CB eq "on") {
+               print FILE "$IP\t\t\t\t\t#$COMMENT\n";
+           } else {
+               print FILE "#DISABLED $IP\t\t\t\t#$COMMENT\n";
+           }
+       }
+    }
+    close FILE;
+
+    # Restart service
+    #system '/usr/local/bin/restartyourhelper';
+}