Files
webmin/cfengine/save_class.cgi
2010-11-07 12:04:59 -08:00

756 lines
20 KiB
Perl
Executable File

#!/usr/local/bin/perl
# save_class.cgi
# Create, update or delete a class in a section
require './cfengine-lib.pl';
&ReadParse();
$conf = $in{'cfd'} ? &get_cfd_config() : &get_config();
$sec = $conf->[$in{'idx'}] if ($in{'idx'} ne '');
$cls = $sec->{'cls'}->[$in{'cidx'}] if ($in{'cidx'} ne '');
if ($in{'manualmode'}) {
# Redirect back to the edit form, but in manual mode
&redirect("edit_class.cgi?cfd=$in{'cfd'}&idx=$in{'idx'}&cidx=$in{'cidx'}&new=$in{'new'}&manual=1");
}
elsif ($in{'delete'}) {
# Just delete the class, and maybe the section too
&lock_file($sec->{'file'});
if (@{$sec->{'cls'}} == 1) {
&save_directive($conf, $sec, undef);
}
else {
&save_directive($sec->{'cls'}, $cls, undef);
}
&flush_file_lines();
&unlock_file($sec->{'file'});
&webmin_log("delete", @{$sec->{'cls'}} == 1 ? "section" : "class",
$sec->{'name'});
&redirect($in{'cfd'} ? "edit_cfd.cgi" : "");
}
else {
# Validate and save inputs
$type = $in{'idx'} eq '' ? $in{'type'} : $sec->{'name'};
if (!$sec) {
$sec = { 'name' => $type,
'type' => 'section',
'cls' => [ $cls = { 'type' => 'class' } ] };
}
elsif (!$cls) {
$cls = { 'type' => 'class' };
}
&error_setup($text{'save_err'});
$in{'class_def'} || $in{'class'} =~ /^\S+$/ ||
&error($text{'save_eclass'});
$cls->{'name'} = $in{'class_def'} ? 'any' : $in{'class'};
$cls->{'implied'} = 0 if (!$in{'class_def'});
if (defined($in{'manual'})) {
# Just save manually edited text
$in{'manual'} =~ s/\r//g;
$cls->{'text'} = $in{'manual'};
}
elsif ($type eq 'links') {
# Save link creation lines
local @olinks = &parse_links($cls);
local @links;
for($i=0; defined($in{"from_$i"}); $i++) {
next if (!$in{"from_$i"} && !$in{"to_$i"});
local $link = $olinks[$i];
$in{"from_$i"} =~ /^\S+$/ ||
&error(&text('save_elinkfrom', $i+1));
$link->{'_linkfrom'} = $in{"from_$i"};
$in{"to_$i"} =~ /^\S+$/ ||
&error(&text('save_elinkto', $i+1));
$link->{'_linkto'} = $in{"to_$i"};
$link->{'_linktype'} = $in{"type_$i"} ? "+>" : "->";
$link->{'_linktype'} .= "!" if ($in{"over_$i"});
push(@links, $link);
}
&unparse_links($cls, @links);
}
elsif ($type eq 'directories') {
# Save directory creation lines
local @odirs = &parse_directories($cls);
local @dirs;
for($i=0; defined($in{"dir_$i"}); $i++) {
next if (!$in{"dir_$i"});
local $dir = $odirs[$i];
$in{"dir_$i"} =~ /^\S+$/ ||
&error(&text('save_edir', $i+1));
$dir->{'_dir'} = $in{"dir_$i"};
&sdelete($dir, 'mode');
if ($in{"mode_$i"} ne "") {
$in{"mode_$i"} =~ /^[0-9]{3,4}$/ ||
&error(&text('save_edirmode', $i+1));
$dir->{'mode'} = $in{"mode_$i"};
}
&sdelete($dir, 'owner');
if ($in{"owner_$i"} ne "") {
$in{"owner_$i"} =~ /^\S+$/ ||
&error(&text('save_edirowner', $i+1));
$dir->{'owner'} = $in{"owner_$i"};
}
&sdelete($dir, 'group');
if ($in{"group_$i"} ne "") {
$in{"group_$i"} =~ /^\S+$/ ||
&error(&text('save_edirgroup', $i+1));
$dir->{'group'} = $in{"group_$i"};
}
push(@dirs, $dir);
}
&unparse_directories($cls, @dirs);
}
elsif ($type eq "control" && !$in{'cfd'}) {
# Save actionsequence and other global definitions
local ($sp, $qu) = &split_str($in{'seq'});
push(@defs, { 'name' => 'actionsequence',
'values' => $sp,
'valuequotes' => $qu } );
for($i=0; defined($in{"def_$i"}); $i++) {
next if (!$in{"def_$i"});
$in{"def_$i"} =~ /^\S+$/ ||
&error(&text('save_econtroldef', $i+1));
local ($sp, $qu) = &split_str($in{"value_$i"});
push(@defs, { 'name' => $in{"def_$i"},
'values' => $sp,
'valuequotes' => $qu } );
}
$cls->{'defs'} = \@defs;
}
elsif ($type eq "control" && $in{'cfd'}) {
# Save cfd-specific control options
$in{'run_def'} ||
($in{'run'} =~ /^(\S+)/ && &has_command("$1")) ||
&error(&text('save_econtrolrun', "$1"));
&save_define($cls->{'defs'}, "cfrunCommand",
$in{'run_def'} ? undef : [ $in{'run'} ]);
$in{'elapsed_def'} || $in{'elapsed'} =~ /^\d+$/ ||
&error($text{'save_econtrolelapsed'});
&save_define($cls->{'defs'}, "IfElapsed",
$in{'elapsed_def'} ? undef : [ $in{'elapsed'} ]);
$in{'max_def'} || $in{'max'} =~ /^\d+$/ ||
&error($text{'save_econtrolmax'});
&save_define($cls->{'defs'}, "MaxConnections",
$in{'max_def'} ? undef : [ $in{'max'} ]);
$in{'auto_def'} ||
($in{'auto'} =~ /^(\S+)/ && &has_command("$1")) ||
&error(&text('save_econtrolauto', "$1"));
&save_define($cls->{'defs'}, "AutoExecCommand",
$in{'auto_def'} ? undef : [ $in{'auto'} ]);
$in{'interval_def'} || $in{'interval'} =~ /^\d+$/ ||
&error($text{'save_econtrolinterval'});
&save_define($cls->{'defs'}, "AutoExecInterval",
$in{'interval_def'} ? undef : [ $in{'interval'} ]);
$in{'dom_def'} || $in{'dom'} =~ /^[A-Za-z0-9\.\-]+$/ ||
&error($text{'save_econtroldomain'});
&save_define($cls->{'defs'}, "domain",
$in{'dom_def'} ? undef : [ $in{'dom'} ]);
&save_define($cls->{'defs'}, "LogAllConnections",
$in{'log'} == 1 ? [ "true" ] :
$in{'log'} == 0 ? [ "false" ] : undef);
$in{'allow_def'} || $in{'allow'} =~ /\S/ ||
&error($text{'save_econtrolallow'});
&save_define($cls->{'defs'}, "AllowConnectionsFrom",
$in{'allow_def'} ? undef :
[ split(/\s+/, $in{'allow'}) ] );
$in{'deny_def'} || $in{'deny'} =~ /\S/ ||
&error($text{'save_econtroldeny'});
&save_define($cls->{'defs'}, "DenyConnectionsFrom",
$in{'deny_def'} ? undef :
[ split(/\s+/, $in{'deny'}) ] );
$in{'skip_def'} || $in{'skip'} =~ /\S/ ||
&error($text{'save_econtrolskip'});
&save_define($cls->{'defs'}, "SkipVerify",
$in{'skip_def'} ? undef :
[ split(/\s+/, $in{'skip'}) ] );
}
elsif ($type eq "admit" || $type eq "grant" || $type eq "deny") {
# Save allowed or denied directories
local $vl = 0;
for($i=0; defined($in{"dir_$i"}); $i++) {
next if (!$in{"dir_$i"});
$in{"dir_$i"} =~ /^\S+$/ ||
&error(&text('save_egrantdir', $i+1));
push(@values, $in{"dir_$i"});
push(@valuelines, $vl++);
local @hosts = split(/\s+/, $in{"hosts_$i"});
@hosts ||
&error(&text('save_egranthosts', $in{"dir_$i"}));
foreach $h (@hosts) {
&to_ipaddress($h) ||
$h =~ /\*/ || $h =~ /=/ ||
&error(&text('save_egranthost', $h));
push(@values, $h);
push(@valuelines, $vl++);
}
$vl++;
}
$cls->{'values'} = \@values;
$cls->{'valuelines'} = \@valuelines;
}
elsif ($type eq "groups" || $type eq "classes") {
# Save group definitions
for($i=0,$j=0; defined($in{"name_$i"}); $i++) {
next if (!$in{"name_$i"});
$in{"name_$i"} =~ /^\S+$/ ||
&error(&text('save_egroupname', $i+1));
local ($st, $qu) = &split_str($in{"mems_$i"});
push(@defs, { 'name' => $in{"name_$i"},
'values' => $st,
'valuequotes' => $qu } );
$j++;
}
$cls->{'defs'} = \@defs;
}
elsif ($type eq "files") {
# Save all the files lines
local @ofiles = &parse_directories($cls);
local @files;
for($i=0; defined($d = $in{"dir_$i"}); $i++) {
next if ($in{"dir_def_$i"});
local $file = $ofiles[$i];
$file->{'_dir'} = $d;
$d =~ /\S/ || &error(&text('save_efilesdir', $i+1));
&sdelete($file, 'owner');
if (!$in{"owner_def_$i"}) {
$in{"owner_$i"} =~ /^\S+$/ ||
&error(&text('save_efilesowner', $d));
$file->{'owner'} = $in{"owner_$i"};
}
&sdelete($file, 'group');
if (!$in{"group_def_$i"}) {
$in{"group_$i"} =~ /^\S+$/ ||
&error(&text('save_efilesgroup', $d));
$file->{'group'} = $in{"group_$i"};
}
&sdelete($file, 'mode');
if (!$in{"mode_def_$i"}) {
$in{"mode_$i"} =~ /^\S+$/ ||
&error(&text('save_efilesmode', $d));
$file->{'mode'} = $in{"mode_$i"};
}
&sdelete($file, 'recurse');
if ($in{"rec_def_$i"} == 2) {
$file->{'recurse'} = 'inf';
}
elsif ($in{"rec_def_$i"} == 0) {
$in{"rec_$i"} =~ /^\d+$/ ||
&error(&text('save_efilesrec', $d));
$file->{'recurse'} = $in{"rec_$i"};
}
&sdelete($file, 'include');
if (!$in{"include_def_$i"}) {
$in{"include_$i"} =~ /^\S+$/ ||
&error(&text('save_efilesinclude', $d));
$file->{'include'} = $in{"include_$i"};
}
&sdelete($file, 'exclude');
if (!$in{"exclude_def_$i"}) {
$in{"exclude_$i"} =~ /^\S+$/ ||
&error(&text('save_efilesexclude', $d));
$file->{'exclude'} = $in{"exclude_$i"};
}
&sdelete($file, 'acl');
if (!$in{"acl_def_$i"}) {
$in{"acl_$i"} =~ /^\S+$/ ||
&error(&text('save_efileacl', $d));
$file->{'acl'} = $in{"acl_$i"};
}
&sdelete($file, 'action');
if ($in{"act_$i"}) {
$file->{'action'} = $in{"act_$i"};
}
push(@files, $file);
}
&unparse_directories($cls, @files);
}
elsif ($type eq "copy") {
# Save copy lines
local @ocopies = &parse_directories($cls);
local @copies;
for($i=0; defined($d = $in{"dir_$i"}); $i++) {
next if ($in{"dir_def_$i"});
local $copy = $ocopies[$i];
$copy->{'_dir'} = $d;
$d =~ /\S/ || &error(&text('save_ecopydir', $i+1));
&sdelete($copy, "dest");
$in{"dest_$i"} =~ /\S/ ||
&error(&text('save_ecopydest', $d));
$copy->{'dest'} = $in{"dest_$i"};
&sdelete($copy, "server");
if (!$in{"server_def_$i"}) {
&to_ipaddress($in{"server_$i"}) ||
&error(&text('save_ecopyserver', $d));
$copy->{'server'} = $in{"server_$i"};
}
&sdelete($copy, 'owner');
if (!$in{"owner_def_$i"}) {
$in{"owner_$i"} =~ /^\S+$/ ||
&error(&text('save_ecopyowner', $d));
$copy->{'owner'} = $in{"owner_$i"};
}
&sdelete($copy, 'group');
if (!$in{"group_def_$i"}) {
$in{"group_$i"} =~ /^\S+$/ ||
&error(&text('save_ecopygroup', $d));
$copy->{'group'} = $in{"group_$i"};
}
&sdelete($copy, 'mode');
if (!$in{"mode_def_$i"}) {
$in{"mode_$i"} =~ /^\S+$/ ||
&error(&text('save_ecopymode', $d));
$copy->{'mode'} = $in{"mode_$i"};
}
&sdelete($copy, 'recurse');
if ($in{"rec_def_$i"} == 2) {
$copy->{'recurse'} = 'inf';
}
elsif ($in{"rec_def_$i"} == 0) {
$in{"rec_$i"} =~ /^\d+$/ ||
&error(&text('save_ecopyrec', $d));
$copy->{'recurse'} = $in{"rec_$i"};
}
&sdelete($copy, "size");
if ($in{"size_mode_$i"} == 1) {
$in{"size1_$i"} ne '' ||
&error(&text('save_ecopysize', $d));
$copy->{'size'} = $in{"size1_$i"};
}
elsif ($in{"size_mode_$i"} == 2) {
$in{"size2_$i"} ne '' ||
&error(&text('save_ecopysize', $d));
$copy->{'size'} = "<".$in{"size2_$i"};
}
elsif ($in{"size_mode_$i"} == 3) {
$in{"size3_$i"} ne '' ||
&error(&text('save_ecopysize', $d));
$copy->{'size'} = ">".$in{"size3_$i"};
}
&sdelete($copy, "backup");
$copy->{'backup'} = 'false' if (!$in{"backup_$i"});
&sdelete($copy, "force");
$copy->{'force'} = 'true' if ($in{"force_$i"});
&sdelete($copy, "purge");
$copy->{'purge'} = 'true' if ($in{"purge_$i"});
&sdelete($copy, "action");
if ($in{"act_$i"}) {
$copy->{'action'} = $in{"act_$i"};
}
push(@copies, $copy);
}
&unparse_directories($cls, @copies);
}
elsif ($type eq "disable") {
# Save disable lines
local @odis = &parse_directories($cls);
local @dis;
for($i=0; defined($d = $in{"dir_$i"}); $i++) {
next if ($in{"dir_def_$i"});
local $dis = $odis[$i];
$dis->{'_dir'} = $d;
$d =~ /\S/ || &error(&text('save_edisfile', $i+1));
&sdelete($dis, "rotate");
if ($in{"rot_mode_$i"} == 1) {
$dis->{'rotate'} = 'empty';
}
elsif ($in{"rot_mode_$i"} == 2) {
$in{"rot_$i"} =~ /^\d+$/ ||
&error(&text('save_edisrot', $d));
$dis->{'rotate'} = $in{"rot_$i"};
}
&sdelete($dis, "type");
if ($in{"type_$i"}) {
$dis->{'type'} = $in{"type_$i"};
}
&sdelete($dis, "size");
if ($in{"size_mode_$i"} == 1) {
$in{"size1_$i"} ne '' ||
&error(&text('save_edissize', $d));
$dis->{'size'} = $in{"size1_$i"};
}
elsif ($in{"size_mode_$i"} == 2) {
$in{"size2_$i"} ne '' ||
&error(&text('save_edissize', $d));
$dis->{'size'} = "<".$in{"size2_$i"};
}
elsif ($in{"size_mode_$i"} == 3) {
$in{"size3_$i"} ne '' ||
&error(&text('save_edissize', $d));
$dis->{'size'} = ">".$in{"size3_$i"};
}
push(@dis, $dis);
}
&unparse_directories($cls, @dis);
}
elsif ($type eq "editfiles") {
# Save file-editing scripts
for($i=0; defined($d = $in{"edit_$i"}); $i++) {
local (@values, @valuelines);
next if ($in{"edit_def_$i"});
$d =~ /\S/ || &error(&text('save_eeditfile', $i+1));
push(@values, $d);
push(@valuelines, 0);
push(@valuequotes, undef);
$in{"script_$i"} =~ s/\r//g;
local @lines = split(/\n/, $in{"script_$i"});
for($j=0; $j<@lines; $j++) {
local ($st, $qu) = &split_str($lines[$j]);
push(@values, @$st);
push(@valuequotes, @$qu);
push(@valuelines, map { $j+1 } @$st);
}
@values > 1 || &error(&text('save_eeditscript', $d));
push(@lists, { 'values' => \@values,
'valuelines' => \@valuelines,
'valuequotes' => \@valuequotes } );
}
$cls->{'lists'} = \@lists;
}
elsif ($type eq "ignore") {
# Save list of ignored files
local ($st, $qu) = &split_str($in{"ignore"});
for($i=0; $i<@$st; $i++) {
push(@values, $st->[$i]);
push(@valuelines, $i);
push(@valuequotes, $qu->[$i]);
}
$cls->{'values'} = \@values;
$cls->{'valuelines'} = \@valuelines;
$cls->{'valuequotes'} = \@valuequotes;
}
elsif ($type eq "processes") {
# Save managed processes list
local $ostr;
local @oprocs = &parse_processes($cls);
local @procs;
for($i=0; defined($p = $in{"proc_$i"}) || $i<@oprocs; $i++) {
next if ($in{"proc_def_$i"});
local $proc = $oprocs[$i];
if ($proc->{'_options'}) {
push(@procs, $proc);
next;
}
$proc->{'_match'} = $p;
$p =~ /\S/ || &error(&text('save_eproc', $i+1));
&sdelete($proc, "signal");
if ($in{"sig_$i"}) {
$proc->{'signal'} = $in{"sig_$i"};
}
&sdelete($proc, "action");
if ($in{"act_$i"}) {
$proc->{'action'} = $in{"act_$i"};
}
&sdelete($proc, "matches");
if ($in{"mat_mode_$i"} == 1) {
$in{"mat1_$i"} ne '' ||
&error(&text('save_eprocmat', $d));
$proc->{'matches'} = $in{"mat1_$i"};
}
elsif ($in{"mat_mode_$i"} == 2) {
$in{"mat2_$i"} ne '' ||
&error(&text('save_eprocmat', $d));
$proc->{'matches'} = "<".$in{"mat2_$i"};
}
elsif ($in{"mat_mode_$i"} == 3) {
$in{"mat3_$i"} ne '' ||
&error(&text('save_eprocmat', $d));
$proc->{'matches'} = ">".$in{"mat3_$i"};
}
delete($proc->{'_restart'});
if (!$in{"restart_def_$i"}) {
$in{"restart_$i"} =~ /\S/ ||
&error(&text('save_eprocrestart', $p));
$proc->{'_restart'} = $in{"restart_$i"};
}
&sdelete($proc, 'owner');
if (!$in{"owner_def_$i"}) {
$in{"owner_$i"} =~ /^\S+$/ ||
&error(&text('save_eprocowner', $d));
$proc->{'owner'} = $in{"owner_$i"};
}
&sdelete($proc, 'group');
if (!$in{"group_def_$i"}) {
$in{"group_$i"} =~ /^\S+$/ ||
&error(&text('save_eprocgroup', $d));
$proc->{'group'} = $in{"group_$i"};
}
push(@procs, $proc);
}
&unparse_processes($cls, @procs);
}
elsif ($type eq "shellcommands") {
# Save commands to execute
local @ocmds = &parse_directories($cls);
local @cmds;
for($i=0; defined($in{"cmd_$i"}); $i++) {
next if (!$in{"cmd_$i"});
local $cmd = $ocmd[$i];
$in{"cmd_$i"} =~ /\S/ ||
&error(&text('save_ecmd', $i+1));
$cmd->{'_dir'} = $in{"cmd_$i"};
&sdelete($cmd, 'owner');
if ($in{"owner_$i"} ne "") {
$in{"owner_$i"} =~ /^\S+$/ ||
&error(&text('save_ecmdowner', $i+1));
$cmd->{'owner'} = $in{"owner_$i"};
}
&sdelete($cmd, 'group');
if ($in{"group_$i"} ne "") {
$in{"group_$i"} =~ /^\S+$/ ||
&error(&text('save_ecmdgroup', $i+1));
$cmd->{'group'} = $in{"group_$i"};
}
&sdelete($cmd, "timeout");
if ($in{"timeout_$i"} ne '') {
$in{"timeout_$i"} =~ /^\d+$/ ||
&error(&text('save_ecmdtimeout', $i+1));
$cmd->{'timeout'} = $in{"timeout_$i"};
}
push(@cmds, $cmd);
}
&unparse_shellcommands($cls, @cmds);
}
elsif ($type eq "tidy") {
# Save tidied directories
local @otidy = &parse_directories($cls);
local @tidy;
for($i=0; defined($d = $in{"dir_$i"}); $i++) {
next if ($in{"dir_def_$i"});
local $tidy = $otidy[$i];
$d =~ /^\S+$/ || &error(&text('save_etidy', $i+1));
$tidy->{'_dir'} = $d;
&sdelete($tidy, "pattern");
if (!$in{"pat_def_$i"}) {
$in{"pat_$i"} =~ /^\S+$/ ||
&error(&text('save_etidypat', $d));
$tidy->{'pattern'} = $in{"pat_$i"};
}
&sdelete($tidy, "size");
if ($in{"smode_$i"} == 1) {
$tidy->{'size'} = 'empty';
}
elsif ($in{"smode_$i"} == 2) {
$in{"size_$i"} =~ /^\S+$/ ||
&error(&text('save_etidysize', $d));
$tidy->{'size'} = $in{"size_$i"};
}
&sdelete($tidy, "age");
&sdelete($tidy, "type");
if ($in{"type_$i"}) {
$tidy->{'type'} = $in{"type_$i"};
}
if (!$in{"age_def_$i"}) {
$in{"age_$i"} =~ /^\d+$/ ||
&error(&text('save_etidyage', $d));
$tidy->{'age'} = $in{"age_$i"};
}
&sdelete($tidy, 'recurse');
if ($in{"rec_def_$i"} == 2) {
$tidy->{'recurse'} = 'inf';
}
elsif ($in{"rec_def_$i"} == 0) {
$in{"rec_$i"} =~ /^\d+$/ ||
&error(&text('save_etidyrec', $d));
$tidy->{'recurse'} = $in{"rec_$i"};
}
push(@tidy, $tidy);
}
&unparse_directories($cls, @tidy);
}
elsif ($type eq "miscmounts") {
# Save mounted NFS filesystems
local @omnts = &parse_miscmounts($cls);
local @mnts;
for($i=0; defined($d = $in{"src_$i"}); $i++) {
next if (!$d);
local $mnt = $omnts[$i];
$d =~ /^\S+$/ ||
&error(&text('save_emiscsrc', $i+1));
$mnt->{'_src'} = $d;
$in{"dest_$i"} =~ /^\S+$/ ||
&error(&text('save_emiscdest', $d));
$mnt->{'_dest'} = $in{"dest_$i"};
&sdelete($mnt, "mode");
$in{"mode_$i"} =~ /^\S*$/ ||
&error(&text('save_emiscmode', $d));
$mnt->{'mode'} = $in{"mode_$i"} if ($in{"mode_$i"});
push(@mnts, $mnt);
}
&unparse_miscmounts($cls, @mnts);
}
elsif ($type eq "resolve") {
# Save nameserver options
$in{'ns'} =~ s/\r//g;
local @ns = split(/\n/, $in{'ns'});
$in{'other'} =~ s/\r//g;
local @other = split(/\n/, $in{'other'});
local $vl = 0;
foreach $n (@ns) {
push(@values, $n);
push(@valuelines, $vl++);
push(@valuequotes, "");
}
foreach $n (@other) {
push(@values, $n);
push(@valuelines, $vl++);
push(@valuequotes, '"');
}
$cls->{'values'} = \@values;
$cls->{'valuelines'} = \@valuelines;
$cls->{'valuequotes'} = \@valuequotes;
}
elsif ($type eq "defaultroute") {
# Save default router options
$in{'route'} =~ /^\S+$/ || &error($text{'save_eroute'});
$cls->{'values'} = [ $in{'route'} ];
$cls->{'valuelines'} = 0;
$cls->{'valuequotes'} = [ ];
}
elsif ($type eq "required" || $type eq "disks") {
# Save filesystems to check
local @oreqs = &parse_directories($cls);
local @reqs;
for($i=0; defined($d = $in{"fs_$i"}); $i++) {
next if (!$d);
local $req = $oreqs[$i];
$d =~ /^\S+$/ || &error(&text('save_ereq', $i+1));
$req->{'_dir'} = $d;
&sdelete($req, "freespace");
if (!$in{"free_def_$i"}) {
$in{"free_$i"} =~ /^\S+$/ ||
&error(&text('save_ereqfree', $d));
$req->{'freespace'} = $in{"free_$i"};
}
push(@reqs, $req);
}
&unparse_directories($cls, @reqs);
}
# Write to the config file
if ($in{'cidx'} ne '') {
# Updating an existing class
&lock_file($sec->{'file'});
&save_directive($conf, $cls, $cls);
&flush_file_lines();
&unlock_file($sec->{'file'});
&webmin_log("modify", "class", $sec->{'name'});
}
elsif ($in{'idx'} ne '') {
# Adding a class to an existing section
&lock_file($sec->{'file'});
&save_directive($sec->{'cls'}, undef, $cls);
&flush_file_lines();
&unlock_file($sec->{'file'});
&webmin_log("create", "class", $sec->{'name'});
}
else {
# Creating a new section and class
&lock_file($conf->[0]->{'file'});
&save_directive($conf, undef, $sec);
&flush_file_lines();
&unlock_file($conf->[0]->{'file'});
&webmin_log("create", "section", $sec->{'name'});
}
&redirect($in{'cfd'} ? "edit_cfd.cgi" : "");
}
# save_define(&config, name, &values|undef)
sub save_define
{
local ($i, $old);
for($i=0; $i<@{$_[0]}; $i++) {
if ($_[0]->[$i]->{'name'} eq $_[1]) {
$old = $_[0]->[$i];
last;
}
}
if ($old && $_[2]) {
$_[0]->[$i]->{'values'} = $_[2];
}
elsif ($old) {
splice(@{$_[0]}, $i, 1);
}
elsif ($_[2]) {
push(@{$_[0]}, { 'name' => $_[1], 'values' => $_[2] } );
}
}
# sdelete(&conf, name)
sub sdelete
{
local $i;
for($i=length($_[1]); $i>0; $i--) {
local $s = substr($_[1], 0, $i);
if (defined($_[0]->{$s})) {
delete($_[0]->{$s});
last;
}
}
}