# Craig Barratt <cbarratt@users.sourceforge.net>
#
# COPYRIGHT
-# Copyright (C) 2004 Craig Barratt
+# Copyright (C) 2005-2009 Craig Barratt
#
# 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
#
#========================================================================
#
-# Version 2.1.0beta2pl1, released 30 May 2004.
+# Version 3.2.0, released 31 Jul 2010.
#
# See http://backuppc.sourceforge.net.
#
use BackupPC::Config::Meta qw(:all);
use BackupPC::Storage;
use Data::Dumper;
+use Encode;
our %ConfigMenu = (
server => {
- text => "Server",
+ text => "CfgEdit_Title_Server",
param => [
- {text => "General Parameters"},
+ {text => "CfgEdit_Title_General_Parameters"},
{name => "ServerHost"},
{name => "BackupPCUser"},
{name => "BackupPCUserVerify"},
{name => "MaxOldLogFiles"},
{name => "TrashCleanSleepSec"},
- {text => "Wakeup Schedule"},
+ {text => "CfgEdit_Title_Wakeup_Schedule"},
{name => "WakeupSchedule"},
- {text => "Concurrent Jobs"},
+ {text => "CfgEdit_Title_Concurrent_Jobs"},
{name => "MaxBackups"},
{name => "MaxUserBackups"},
{name => "MaxPendingCmds"},
{name => "MaxBackupPCNightlyJobs"},
{name => "BackupPCNightlyPeriod"},
- {text => "Pool Filesystem Limits"},
+ {text => "CfgEdit_Title_Pool_Filesystem_Limits"},
{name => "DfCmd"},
{name => "DfMaxUsagePct"},
{name => "HardLinkMax"},
- {text => "Other Parameters"},
+ {text => "CfgEdit_Title_Other_Parameters"},
{name => "UmaskMode"},
{name => "MyPath"},
{name => "DHCPAddressRanges"},
+ {name => "CmdQueueNice"},
{name => "PerlModuleLoad"},
{name => "ServerInitdPath"},
{name => "ServerInitdStartCmd"},
- {text => "Remote Apache Settings"},
+ {text => "CfgEdit_Title_Remote_Apache_Settings"},
{name => "ServerPort"},
{name => "ServerMesgSecret"},
- {text => "Program Paths"},
+ {text => "CfgEdit_Title_Program_Paths"},
{name => "SshPath"},
{name => "NmbLookupPath"},
{name => "PingPath"},
{name => "GzipPath"},
{name => "Bzip2Path"},
- {text => "Install Paths"},
+ {text => "CfgEdit_Title_Install_Paths"},
+ #
+ # Can only edit TopDir and LogDir if we are in FHS mode.
+ # Otherwise they are hardcoded in lib/BackupPC/Lib.pm.
+ #
+ {name => "TopDir",
+ visible => sub { return $_[1]->useFHS(); } },
+ {name => "LogDir",
+ visible => sub { return $_[1]->useFHS(); } },
{name => "CgiDir"},
- {name => "InstallDir"},
+ #
+ # Cannot edit ConfDir or InstallDir, since the real value is hardcoded in
+ # lib/BackupPC/Lib.pm.
+ # {name => "ConfDir"},
+ # {name => "InstallDir"},
+ #
],
},
email => {
- text => "Email",
+ text => "CfgEdit_Title_Email",
param => [
- {text => "Email settings"},
+ {text => "CfgEdit_Title_Email_settings"},
{name => "SendmailPath"},
{name => "EMailNotifyMinDays"},
{name => "EMailFromUserName"},
{name => "EMailAdminUserName"},
{name => "EMailUserDestDomain"},
- {text => "Email User Messages"},
+ {text => "CfgEdit_Title_Email_User_Messages"},
{name => "EMailNoBackupEverSubj"},
{name => "EMailNoBackupEverMesg"},
{name => "EMailNotifyOldBackupDays"},
{name => "EMailNotifyOldOutlookDays"},
{name => "EMailOutlookBackupSubj"},
{name => "EMailOutlookBackupMesg"},
+ {name => "EMailHeaders"},
],
},
cgi => {
- text => "CGI",
+ text => "CfgEdit_Title_CGI",
param => [
- {text => "Admin Privileges"},
+ {text => "CfgEdit_Title_Admin_Privileges"},
{name => "CgiAdminUserGroup"},
{name => "CgiAdminUsers"},
- {text => "Config Editing"},
- {name => "CgiUserConfigEdit"},
-
- {text => "Page Rendering"},
+ {text => "CfgEdit_Title_Page_Rendering"},
{name => "Language"},
{name => "CgiNavBarAdminAllHosts"},
{name => "CgiSearchBoxEnable"},
{name => "CgiExt2ContentType"},
{name => "CgiCSSFile"},
- {text => "Paths"},
+ {text => "CfgEdit_Title_Paths"},
{name => "CgiURL"},
{name => "CgiImageDir"},
{name => "CgiImageDirURL"},
- {text => "User URLs"},
+ {text => "CfgEdit_Title_User_URLs"},
{name => "CgiUserHomePageCheck"},
{name => "CgiUserUrlCreate"},
+ {text => "CfgEdit_Title_User_Config_Editing"},
+ {name => "CgiUserConfigEditEnable"},
+ {name => "CgiUserConfigEdit"},
],
},
xfer => {
- text => "Xfer",
+ text => "CfgEdit_Title_Xfer",
param => [
- {text => "Xfer Settings"},
+ {text => "CfgEdit_Title_Xfer_Settings"},
{name => "XferMethod", onchangeSubmit => 1},
{name => "XferLogLevel"},
+ {name => "ClientCharset"},
+ {name => "ClientCharsetLegacy"},
- {text => "Smb Settings",
+ ### Smb Settings
+ {text => "CfgEdit_Title_Smb_Settings",
visible => sub { return $_[0]->{XferMethod} eq "smb"; } },
{name => "SmbShareName",
visible => sub { return $_[0]->{XferMethod} eq "smb"; } },
{name => "SmbSharePasswd",
visible => sub { return $_[0]->{XferMethod} eq "smb"; } },
- {text => "Tar Settings",
+ ### Tar Settings
+ {text => "CfgEdit_Title_Tar_Settings",
visible => sub { return $_[0]->{XferMethod} eq "tar"; } },
{name => "TarShareName",
visible => sub { return $_[0]->{XferMethod} eq "tar"; } },
- {text => "Rsync Settings",
+ ### Rsync Settings
+ {text => "CfgEdit_Title_Rsync_Settings",
visible => sub { return $_[0]->{XferMethod} eq "rsync"; } },
- {text => "Rsyncd Settings",
+ {text => "CfgEdit_Title_Rsyncd_Settings",
visible => sub { return $_[0]->{XferMethod} eq "rsyncd"; } },
{name => "RsyncShareName",
visible => sub { return $_[0]->{XferMethod} =~ /rsync/; } },
+ {name => "RsyncdUserName",
+ visible => sub { return $_[0]->{XferMethod} eq "rsyncd"; } },
{name => "RsyncdPasswd",
visible => sub { return $_[0]->{XferMethod} eq "rsyncd"; } },
{name => "RsyncdAuthRequired",
{name => "RsyncCsumCacheVerifyProb",
visible => sub { return $_[0]->{XferMethod} =~ /rsync/; } },
- {text => "Archive Settings",
+ ### Ftp Settings
+ {text => "CfgEdit_Title_Ftp_Settings",
+ visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
+ {name => "FtpShareName",
+ visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
+ {name => "FtpUserName",
+ visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
+ {name => "FtpPasswd",
+ visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
+ {name => "FtpPassive",
+ visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
+ {name => "FtpBlockSize",
+ visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
+ {name => "FtpPort",
+ visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
+ {name => "FtpTimeout",
+ visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
+ {name => "FtpFollowSymlinks",
+ visible => sub { return $_[0]->{XferMethod} eq "ftp"; } },
+
+
+ ### Archive Settings
+ {text => "CfgEdit_Title_Archive_Settings",
visible => sub { return $_[0]->{XferMethod} eq "archive"; } },
{name => "ArchiveDest",
visible => sub { return $_[0]->{XferMethod} eq "archive"; } },
{name => "ArchiveSplit",
visible => sub { return $_[0]->{XferMethod} eq "archive"; } },
- {text => "Include/Exclude",
+ ### Include/Exclude Settings
+ {text => "CfgEdit_Title_Include_Exclude",
visible => sub { return $_[0]->{XferMethod} ne "archive"; } },
{name => "BackupFilesOnly",
visible => sub { return $_[0]->{XferMethod} ne "archive"; } },
{name => "BackupFilesExclude",
visible => sub { return $_[0]->{XferMethod} ne "archive"; } },
- {text => "Smb Paths/Commands",
+ ### Samba paths and commands
+ {text => "CfgEdit_Title_Smb_Paths_Commands",
visible => sub { return $_[0]->{XferMethod} eq "smb"; } },
{name => "SmbClientPath",
visible => sub { return $_[0]->{XferMethod} eq "smb"; } },
{name => "SmbClientRestoreCmd",
visible => sub { return $_[0]->{XferMethod} eq "smb"; } },
- {text => "Tar Paths/Commands",
+ ### Tar paths and commands
+ {text => "CfgEdit_Title_Tar_Paths_Commands",
visible => sub { return $_[0]->{XferMethod} eq "tar"; } },
{name => "TarClientPath",
visible => sub { return $_[0]->{XferMethod} eq "tar"; } },
{name => "TarClientRestoreCmd",
visible => sub { return $_[0]->{XferMethod} eq "tar"; } },
- {text => "Rsync Paths/Commands/Args",
+ ### Rsync paths and commands
+ {text => "CfgEdit_Title_Rsync_Paths_Commands_Args",
visible => sub { return $_[0]->{XferMethod} eq "rsync"; } },
- {text => "Rsyncd Port/Args",
+ {text => "CfgEdit_Title_Rsyncd_Port_Args",
visible => sub { return $_[0]->{XferMethod} eq "rsyncd"; } },
{name => "RsyncClientPath",
visible => sub { return $_[0]->{XferMethod} eq "rsync"; } },
visible => sub { return $_[0]->{XferMethod} eq "rsyncd"; } },
{name => "RsyncArgs",
visible => sub { return $_[0]->{XferMethod} =~ /rsync/; } },
+ {name => "RsyncArgsExtra",
+ visible => sub { return $_[0]->{XferMethod} =~ /rsync/; } },
{name => "RsyncRestoreArgs",
visible => sub { return $_[0]->{XferMethod} =~ /rsync/; } },
- {text => "Archive Paths/Commands",
+ ### Archive paths and commands
+ {text => "CfgEdit_Title_Archive_Paths_Commands",
visible => sub { return $_[0]->{XferMethod} eq "archive"; } },
{name => "ArchiveClientCmd",
visible => sub { return $_[0]->{XferMethod} eq "archive"; } },
],
},
schedule => {
- text => "Schedule",
+ text => "CfgEdit_Title_Schedule",
param => [
- {text => "Full Backups"},
+ {text => "CfgEdit_Title_Full_Backups"},
{name => "FullPeriod"},
{name => "FullKeepCnt"},
{name => "FullKeepCntMin"},
{name => "FullAgeMax"},
- {text => "Incremental Backups"},
+ {text => "CfgEdit_Title_Incremental_Backups"},
{name => "IncrPeriod"},
{name => "IncrKeepCnt"},
{name => "IncrKeepCntMin"},
{name => "IncrAgeMax"},
+ {name => "IncrLevels"},
{name => "IncrFill"},
- {text => "Blackouts"},
+ {text => "CfgEdit_Title_Blackouts"},
+ {name => "BackupsDisable"},
{name => "BlackoutBadPingLimit"},
{name => "BlackoutGoodCnt"},
{name => "BlackoutPeriods"},
- {text => "Other"},
+ {text => "CfgEdit_Title_Other"},
{name => "PartialAgeMax"},
{name => "RestoreInfoKeepCnt"},
{name => "ArchiveInfoKeepCnt"},
],
},
backup => {
- text => "Backup Settings",
+ text => "CfgEdit_Title_Backup_Settings",
param => [
- {text => "Client Lookup"},
+ {text => "CfgEdit_Title_Client_Lookup"},
{name => "ClientNameAlias"},
{name => "NmbLookupCmd"},
{name => "NmbLookupFindHostCmd"},
{name => "PingCmd"},
{name => "PingMaxMsec"},
- {text => "Other"},
+ {text => "CfgEdit_Title_Other"},
{name => "ClientTimeout"},
{name => "MaxOldPerPCLogFiles"},
{name => "CompressLevel"},
- {text => "User Commands"},
+ {text => "CfgEdit_Title_User_Commands"},
{name => "DumpPreUserCmd"},
{name => "DumpPostUserCmd"},
{name => "DumpPreShareCmd"},
{name => "RestorePostUserCmd"},
{name => "ArchivePreUserCmd"},
{name => "ArchivePostUserCmd"},
+ {name => "UserCmdCheckStatus"},
],
},
+ hosts => {
+ text => "CfgEdit_Title_Hosts",
+ param => [
+ {text => "CfgEdit_Title_Hosts"},
+ {name => "Hosts",
+ comment => "CfgEdit_Hosts_Comment"},
+ ],
+ },
);
sub action
my $config_path = $host eq "" ? "$TopDir/conf/config.pl"
: "$TopDir/pc/$host/config.pl";
- my $Privileged = CheckPermission();
- my $userHost = 1 if ( $Privileged && !$PrivAdmin && defined($host) );
+ my $Privileged = CheckPermission($host)
+ && ($PrivAdmin || $Conf{CgiUserConfigEditEnable});
+ my $userHost = 1 if ( defined($host) );
+ my $debugText;
if ( !$Privileged ) {
- #ErrorExit(eval("qq{$Lang->{Only_privileged_users_can_edit_config_files}}"));
- ErrorExit("Only_privileged_users_can_edit_config_files");
+ ErrorExit(eval("qq{$Lang->{Only_privileged_users_can_edit_config_files}}"));
}
- if ( defined($In{menu}) || $In{editAction} eq "Save" ) {
+ if ( defined($In{menu}) || $In{saveAction} eq "Save" ) {
$errors = errorCheck();
if ( %$errors ) {
#
# If there are errors, then go back to the same menu
#
- $In{editAction} = "";
- $In{newMenu} = "";
+ $In{saveAction} = "";
+ #$In{newMenu} = "";
}
+ if ( (my $var = $In{overrideUncheck}) ne "" ) {
+ #
+ # a compound variable was unchecked; delete or
+ # add extra variables to make the shape the same.
+ #
+ #print STDERR Dumper(\%In);
+ foreach my $v ( keys(%In) ) {
+ if ( $v =~ /^v_zZ_(\Q$var\E(_zZ_.*|$))/ ) {
+ delete($In{$v}) if ( !defined($In{"orig_zZ_$1"}) );
+ }
+ if ( $v =~ /^orig_zZ_(\Q$var\E(_zZ_.*|$))/ ) {
+ $In{"v_zZ_$1"} = $In{$v};
+ }
+ }
+ delete($In{"vflds.$var"});
+ }
+
($newConf, $override) = inputParse($bpc, $userHost);
$override = undef if ( $host eq "" );
- #
- # Copy all the orig_ input parameters
- #
- foreach my $var ( keys(%In) ) {
- next if ( $var !~ /^orig_/ );
- $contentHidden .= <<EOF;
-<input type="hidden" name="$var" value="${EscHTML($In{$var})}">
-EOF
- }
} else {
#
# First time: pick up the current config settings
$override->{$param} = 1;
}
} else {
+ my $hostInfo = $bpc->HostInfoRead();
$hostConf = {};
+ $mainConf->{Hosts} = [map($hostInfo->{$_}, sort(keys(%$hostInfo)))];
}
$newConf = { %$mainConf, %$hostConf };
-
- #
- # Emit all the original config settings
- #
- my $doneParam = {};
- foreach my $param ( keys(%ConfigMeta) ) {
- next if ( $doneParam->{$param} );
- next if ( $userHost && !$bpc->{Conf}{CgiUserConfigEdit}{$param} );
- $contentHidden .= fieldHiddenBuild($ConfigMeta{$param},
- $param,
- $mainConf->{$param},
- "orig",
- );
- $doneParam->{$param} = 1;
- }
-
}
- if ( $In{editAction} ne "Save" && $In{newMenu} ne ""
+ if ( $In{saveAction} ne "Save" && $In{newMenu} ne ""
&& defined($ConfigMenu{$In{newMenu}}) ) {
$menu = $In{newMenu};
}
#
# For a non-admin user editing the host config, we need to
# figure out which subsets of the menu tree will be visible,
- # based on what is enabled
+ # based on what is enabled. Admin users can edit all the
+ # available per-host settings.
#
foreach my $m ( keys(%ConfigMenu) ) {
my $enabled = 0;
$text = $n;
$mask[$text] = 1;
} else {
- if ( $bpc->{Conf}{CgiUserConfigEdit}{$param} ) {
+ if ( $bpc->{Conf}{CgiUserConfigEdit}{$param}
+ || (defined($bpc->{Conf}{CgiUserConfigEdit}{$param})
+ && $PrivAdmin) ) {
$mask[$text] = 0 if ( $text >= 0 );
$mask[$n] = 0;
- $enabled = 1;
+ $enabled ||= 1;
} else {
$mask[$n] = 1;
}
my $groupText;
foreach my $m ( keys(%ConfigMenu) ) {
next if ( $menuDisable{$m}{top} );
- my $text = $ConfigMenu{$m}{text};
+ my $text = eval("qq($Lang->{$ConfigMenu{$m}{text}})");
if ( $m eq $menu ) {
$groupText .= <<EOF;
-<td bgcolor="grey"><a href="javascript:menuSubmit('$m')"><b>$text</b></a></td>
+<td class="editTabSel"><a href="javascript:menuSubmit('$m')"><b>$text</b></a></td>
EOF
} else {
$groupText .= <<EOF;
-<td><a href="javascript:menuSubmit('$m')">$text</a></td>
+<td class="editTabNoSel"><a href="javascript:menuSubmit('$m')">$text</a></td>
EOF
}
}
if ( $host eq "" ) {
- $content .= <<EOF;
-${h1("Main Configuration Editor")}
-EOF
+ $content .= eval("qq($Lang->{CfgEdit_Header_Main})");
} else {
- $content .= <<EOF;
-${h1("Host $host Configuration Editor")}
-<p>
-Note: Check Override if you want to modify a value specific to this host.
-EOF
+ $content .= eval("qq($Lang->{CfgEdit_Header_Host})");
}
- my $saveDisplay = "block";
- $saveDisplay = "none" if ( !$In{modified} );
+ my $saveStyle = "";
+ my $saveColor = "#ff0000";
+
+ if ( $In{modified} && $In{saveAction} ne "Save" && !%$errors ) {
+ $saveStyle = "style=\"color:$saveColor\"";
+ } else {
+ $In{modified} = 0;
+ }
+
+ #
+ # Add action and host to the URL so the nav bar link is
+ # highlighted
+ #
+ my $url = "$MyURL?action=editConfig";
+ $url .= "&host=$host" if ( $host ne "" );
$content .= <<EOF;
<table border="0" cellpadding="2">
<tr>$groupText</tr>
<tr>
-<form method="post" name="form1" action="$MyURL">
+<form method="post" name="editForm" action="$url">
<input type="hidden" name="host" value="$host">
<input type="hidden" name="menu" value="$menu">
<input type="hidden" name="newMenu" value="">
<input type="hidden" name="modified" value="$In{modified}">
<input type="hidden" name="deleteVar" value="">
<input type="hidden" name="insertVar" value="">
+<input type="hidden" name="overrideUncheck" value="">
<input type="hidden" name="addVar" value="">
<input type="hidden" name="action" value="editConfig">
-<input type="submit" style="display: $saveDisplay" name="editAction" value="Save">
-$contentHidden
+<input type="hidden" name="saveAction" value="">
+<input type="button" class="editSaveButton" name="editAction"
+ value="${EscHTML($Lang->{CfgEdit_Button_Save})}" $saveStyle
+ onClick="saveSubmit();">
+<p>
<script language="javascript" type="text/javascript">
<!--
+ function saveSubmit()
+ {
+ if ( document.editForm.modified.value != 0 ) {
+ document.editForm.saveAction.value = 'Save';
+ document.editForm.submit();
+ }
+ return false;
+ }
+
function deleteSubmit(varName)
{
- document.form1.deleteVar.value = varName;
- document.form1.modified.value = 1;
- document.form1.submit();
+ document.editForm.deleteVar.value = varName;
+ document.editForm.modified.value = 1;
+ document.editForm.submit();
return;
}
function insertSubmit(varName)
{
- document.form1.insertVar.value = varName;
- document.form1.modified.value = 1;
- document.form1.submit();
+ document.editForm.insertVar.value = varName;
+ document.editForm.modified.value = 1;
+ document.editForm.submit();
return;
}
function addSubmit(varName, checkKey)
{
- if ( checkKey && document.form1.addVarKey.value == "" ) {
+ if ( checkKey
+ && eval("document.editForm.addVarKey_" + varName + ".value") == "" ) {
alert("New key must be non-empty");
return;
}
- document.form1.addVar.value = varName;
- document.form1.modified.value = 1;
- document.form1.submit();
+ document.editForm.addVar.value = varName;
+ document.editForm.modified.value = 1;
+ document.editForm.submit();
return;
}
function menuSubmit(menuName)
{
- document.form1.newMenu.value = menuName;
- document.form1.submit();
+ document.editForm.newMenu.value = menuName;
+ document.editForm.submit();
}
function varChange(varName)
{
- document.form1.editAction.style.display = "block";
- document.form1.modified.value = 1;
+ document.editForm.modified.value = 1;
+ document.editForm.editAction.style.color = '$saveColor';
}
function checkboxChange(varName)
{
- document.form1.editAction.style.display = "block";
- document.form1.modified.value = 1;
+ document.editForm.modified.value = 1;
+ document.editForm.editAction.style.color = '$saveColor';
// Do nothing if the checkbox is now set
- if ( eval("document.form1.override_" + varName + ".checked") ) {
+ if ( eval("document.editForm.override_" + varName + ".checked") ) {
return false;
}
var allVars = {};
- var varRE = new RegExp("^v_(" + varName + ".*)");
- var origRE = new RegExp("^orig_(" + varName + ".*)");
- for ( var i = 0 ; i < document.form1.elements.length ; i++ ) {
- var e = document.form1.elements[i];
+ var varRE = new RegExp("^v_zZ_(" + varName + ".*)");
+ var origRE = new RegExp("^orig_zZ_(" + varName + ".*)");
+ for ( var i = 0 ; i < document.editForm.elements.length ; i++ ) {
+ var e = document.editForm.elements[i];
var re;
if ( (re = varRE.exec(e.name)) != null ) {
if ( allVars[re[1]] == null ) {
allVars[re[1]] = 0;
}
allVars[re[1]]++;
- //debugMsg("found v_ match with " + re[1]);
+ //debugMsg("found v_zZ_ match with " + re[1]);
//debugMsg("allVars[" + re[1] + "] = " + allVars[re[1]]);
} else if ( (re = origRE.exec(e.name)) != null ) {
if ( allVars[re[1]] == null ) {
if ( allVars[v] != 0 ) {
//debugMsg("Not the same shape because of " + v);
sameShape = 0;
- }
+ } else {
+ // copy the original variable values
+ //debugMsg("setting " + v);
+ eval("document.editForm.v_zZ_" + v + ".value = document.editForm.orig_zZ_" + v + ".value");
+ }
}
if ( sameShape ) {
- for ( v in allVars ) {
- //debugMsg("setting " + v);
- eval("document.form1.v_" + v + ".value = document.form1.orig_" + v + ".value");
- }
return true;
} else {
- document.form1.submit();
+ // need to rebuild the form since the compound variable
+ // has changed shape
+ document.editForm.overrideUncheck.value = varName;
+ document.editForm.submit();
return false;
}
}
function checkboxSet(varName)
{
- document.form1.editAction.style.display = "block";
- document.form1.modified.value = 1;
- eval("document.form1.override_" + varName + ".checked = 1;");
+ document.editForm.modified.value = 1;
+ document.editForm.editAction.style.color = '$saveColor';
+ eval("document.editForm.override_" + varName + ".checked = 1;");
return false;
}
//-->
</script>
-<span id="debug"></span>
+<span id="debug">$debugText</span>
EOF
EOF
my $doneParam = {};
+ my $tblContent;
#
# There is a special case of the user deleting just the field
if ( $In{deleteVar} ne "" && %$errors > 0 ) {
my $matchAll = 1;
foreach my $v ( keys(%$errors) ) {
- if ( $v ne $In{deleteVar} && $v !~ /^\Q$In{deleteVar}_/ ) {
+ if ( $v ne $In{deleteVar} && $v !~ /^\Q$In{deleteVar}_zZ_/ ) {
$matchAll = 0;
last;
}
my $isError = %$errors;
- if ( !$isError && $In{editAction} eq "Save" ) {
- my $mesg;
+ if ( !$isError && $In{saveAction} eq "Save" ) {
+ my($mesg, $err);
if ( $host ne "" ) {
$hostConf = $bpc->ConfigDataRead($host) if ( !defined($hostConf) );
- $mesg = configDiffMesg($host, $hostConf, $newConf);
- foreach my $param ( %$newConf ) {
- $hostConf->{$param} = $newConf->{$param}
- if ( $override->{param} );
+ my %hostConf2 = %$hostConf;
+ foreach my $param ( keys(%$newConf) ) {
+ if ( $override->{$param} ) {
+ $hostConf->{$param} = $newConf->{$param}
+ } else {
+ delete($hostConf->{$param});
+ }
}
- $bpc->ConfigDataWrite($host, $hostConf);
+ $mesg = configDiffMesg($host, \%hostConf2, $hostConf);
+ $err .= $bpc->ConfigDataWrite($host, $hostConf);
} else {
$mainConf = $bpc->ConfigDataRead() if ( !defined($mainConf) );
- $mesg = configDiffMesg(undef, $mainConf, $newConf);
+
+ my $hostsSave = [];
+ my($hostsNew, $allHosts, $copyConf);
+ foreach my $entry ( @{$newConf->{Hosts}} ) {
+ next if ( $entry->{host} eq "" );
+ $allHosts->{$entry->{host}} = 1;
+ $allHosts->{$1} = 1 if ( $entry->{host} =~ /(.+?)\s*=/ );
+ }
+ foreach my $entry ( @{$newConf->{Hosts}} ) {
+ next if ( $entry->{host} eq ""
+ || defined($hostsNew->{$entry->{host}}) );
+ if ( $entry->{host} =~ /(.+?)\s*=\s*(.+)/ ) {
+ if ( defined($allHosts->{$2}) ) {
+ $entry->{host} = $1;
+ $copyConf->{$1} = $2;
+ } else {
+ my $fullHost = $entry->{host};
+ my $copyHost = $2;
+ $err .= eval("qq($Lang->{CfgEdit_Error_Copy_host_does_not_exist})");
+ }
+ }
+ push(@$hostsSave, $entry);
+ $hostsNew->{$entry->{host}} = $entry;
+ }
+ ($mesg, my $hostChange) = hostsDiffMesg($hostsNew);
+ $bpc->HostInfoWrite($hostsNew) if ( $hostChange );
+ foreach my $host ( keys(%$copyConf) ) {
+ #
+ # Currently host names are forced to lc when they
+ # are read from the hosts file. Therefore we need
+ # to force the from and to hosts to lc.
+ #
+ my $confData = $bpc->ConfigDataRead(lc($copyConf->{$host}));
+ my $fromHost = $copyConf->{$host};
+ $err .= $bpc->ConfigDataWrite(lc($host), $confData);
+ $mesg .= eval("qq($Lang->{CfgEdit_Log_Copy_host_config})");
+ }
+
+ delete($newConf->{Hosts});
+ $mesg .= configDiffMesg(undef, $mainConf, $newConf);
$mainConf = { %$mainConf, %$newConf };
- $bpc->ConfigDataWrite(undef, $mainConf);
+ $err .= $bpc->ConfigDataWrite(undef, $mainConf);
+ $newConf->{Hosts} = $hostsSave;
}
+ if ( defined($err) ) {
+ $tblContent .= <<EOF;
+<tr><td colspan="2" class="border"><span class="editError">$err</span></td></tr>
+EOF
+ }
+ $bpc->ServerConnect();
if ( $mesg ne "" ) {
- $bpc->ServerConnect();
+ (my $mesgBR = $mesg) =~ s/\n/<br>\n/g;
+ # uncomment this if you want the changes to be displayed
+# $tblContent .= <<EOF;
+#<tr><td colspan="2" class="border"><span class="editComment">$mesgBR</span></td></tr>
+#EOF
foreach my $str ( split(/\n/, $mesg) ) {
- $bpc->ServerMesg($str);
+ $bpc->ServerMesg("log $str") if ( $str ne "" );
}
}
+ #
+ # Tell the server to reload, unless we only changed
+ # a client config
+ #
+ $bpc->ServerMesg("server reload") if ( $host eq "" );
}
my @mask = @{$menuDisable{$menu}{mask} || []};
next if ( $disabled || $menuDisable{$menu}{top} );
if ( ref($paramInfo->{visible}) eq "CODE"
- && !&{$paramInfo->{visible}}($newConf) ) {
+ && !&{$paramInfo->{visible}}($newConf, $bpc) ) {
next;
}
- if ( defined(my $text = $paramInfo->{text}) ) {
- $content .= <<EOF;
+ if ( defined($paramInfo->{text}) ) {
+ my $text = eval("qq($Lang->{$paramInfo->{text}})");
+ $tblContent .= <<EOF;
<tr><td colspan="2" class="editHeader">$text</td></tr>
EOF
next;
# TODO: get parameter documentation
#
my $comment = "";
- $comment =~ s/\'//g;
- $comment =~ s/\"//g;
- $comment =~ s/\n/ /g;
+ #$comment =~ s/\'//g;
+ #$comment =~ s/\"//g;
+ #$comment =~ s/\n/ /g;
$doneParam->{$param} = 1;
- $content .= fieldEditBuild($ConfigMeta{$param},
- $param,
- $newConf->{$param},
- $errors,
- 0,
- $comment,
- $isError,
- $paramInfo->{onchangeSubmit},
- defined($override) ? $param : undef,
- defined($override) ? $override->{$param} : undef
+ $tblContent .= fieldEditBuild($ConfigMeta{$param},
+ $param,
+ $newConf->{$param},
+ $errors,
+ 0,
+ $comment,
+ $isError,
+ $paramInfo->{onchangeSubmit},
+ defined($override) ? $param : undef,
+ defined($override) ? $override->{$param} : undef
);
+ if ( defined($paramInfo->{comment}) ) {
+ my $topDir = $bpc->TopDir;
+ my $text = eval("qq($Lang->{$paramInfo->{comment}})");
+ $tblContent .= <<EOF;
+<tr><td colspan="2" class="editComment">$text</td></tr>
+EOF
+ }
}
#
- # Emit any remaining errors - should not happen
+ # Emit a summary of all the errors
#
+ my $errorTxt;
+
+ if ( %$errors ) {
+ $errorTxt .= <<EOF;
+<tr><td colspan="2" class="border"><span class="editError">$Lang->{CfgEdit_Error_No_Save}</span></td></tr>
+EOF
+ }
+
foreach my $param ( sort(keys(%$errors)) ) {
- $content .= <<EOF;
-<tr><td colspan="2" class="border">$errors->{$param}</td></tr>
+ $errorTxt .= <<EOF;
+<tr><td colspan="2" class="border"><span class="editError">$errors->{$param}</span></td></tr>
EOF
- delete($errors->{$param});
}
$content .= <<EOF;
+$errorTxt
+$tblContent
</table>
EOF
#
foreach my $param ( keys(%ConfigMeta) ) {
next if ( $doneParam->{$param} );
- next if ( $userHost && !$bpc->{Conf}{CgiUserConfigEdit}{$param} );
+ next if ( $userHost
+ && (!defined($bpc->{Conf}{CgiUserConfigEdit}{$param})
+ || (!$PrivAdmin
+ && !$bpc->{Conf}{CgiUserConfigEdit}{$param})) );
$content .= fieldHiddenBuild($ConfigMeta{$param},
$param,
$newConf->{$param},
$doneParam->{$param} = 1;
}
+ if ( defined($In{menu}) || $In{saveAction} eq "Save" ) {
+ if ( $In{saveAction} eq "Save" && !$userHost ) {
+ #
+ # Emit the new settings as orig_zZ_ parameters
+ #
+ $doneParam = {};
+ foreach my $param ( keys(%ConfigMeta) ) {
+ next if ( $doneParam->{$param} );
+ next if ( $userHost
+ && (!defined($bpc->{Conf}{CgiUserConfigEdit}{$param})
+ || (!$PrivAdmin
+ && !$bpc->{Conf}{CgiUserConfigEdit}{$param})) );
+ $contentHidden .= fieldHiddenBuild($ConfigMeta{$param},
+ $param,
+ $newConf->{$param},
+ "orig",
+ );
+ $doneParam->{$param} = 1;
+ $In{modified} = 0;
+ }
+ } else {
+ #
+ # Just switching menus: copy all the orig_zZ_ input parameters
+ #
+ foreach my $var ( keys(%In) ) {
+ next if ( $var !~ /^orig_zZ_/ );
+ my $val = decode_utf8($In{$var});
+ $contentHidden .= <<EOF;
+<input type="hidden" name="$var" value="${EscHTML($val)}">
+EOF
+ }
+ }
+ } else {
+ #
+ # First time: emit all the original config settings
+ #
+ $doneParam = {};
+ foreach my $param ( keys(%ConfigMeta) ) {
+ next if ( $doneParam->{$param} );
+ next if ( $userHost
+ && (!defined($bpc->{Conf}{CgiUserConfigEdit}{$param})
+ || (!$PrivAdmin
+ && !$bpc->{Conf}{CgiUserConfigEdit}{$param})) );
+ $contentHidden .= fieldHiddenBuild($ConfigMeta{$param},
+ $param,
+ $mainConf->{$param},
+ "orig",
+ );
+ $doneParam->{$param} = 1;
+ }
+ }
+
$content .= <<EOF;
+$contentHidden
</form>
</tr>
</table>
$varValue = [$varValue] if ( ref($varValue) ne "ARRAY" );
for ( my $i = 0 ; $i < @$varValue ; $i++ ) {
- $content .= fieldHiddenBuild($type->{child}, "${varName}_$i",
+ $content .= fieldHiddenBuild($type->{child}, "${varName}_zZ_$i",
$varValue->[$i], $prefix);
}
- } elsif ( $type->{type} eq "hash" ) {
+ } elsif ( $type->{type} eq "hash" || $type->{type} eq "horizHash" ) {
$varValue = {} if ( ref($varValue) ne "HASH" );
my(@order, $childType);
- if ( defined($type->{child}) ) {
+ if ( defined($type->{order}) ) {
+ @order = @{$type->{order}};
+ } elsif ( defined($type->{child}) ) {
@order = sort(keys(%{$type->{child}}));
} else {
@order = sort(keys(%$varValue));
<input type="hidden" name="vflds.$varName" value="${EscHTML($fld)}">
EOF
}
- $content .= fieldHiddenBuild($childType, "${varName}_$fld",
+ $content .= fieldHiddenBuild($childType, "${varName}_zZ_$fld",
$varValue->{$fld}, $prefix);
}
} elsif ( $type->{type} eq "shortlist" ) {
$varValue = [$varValue] if ( ref($varValue) ne "ARRAY" );
$varValue = join(", ", @$varValue);
$content .= <<EOF;
-<input type="hidden" name="${prefix}_$varName" value="${EscHTML($varValue)}">
+<input type="hidden" name="${prefix}_zZ_$varName" value="${EscHTML($varValue)}">
EOF
} else {
$content .= <<EOF;
-<input type="hidden" name="${prefix}_$varName" value="${EscHTML($varValue)}">
+<input type="hidden" name="${prefix}_zZ_$varName" value="${EscHTML($varValue)}">
EOF
}
return $content;
my $size = 50 - 10 * $level;
$type = { type => $type } if ( ref($type) ne "HASH" );
+ $size = $type->{size} if ( defined($type->{size}) );
+
+ #
+ # These fragments allow inline content to be turned on and off
+ #
+ # <tr><td colspan="2"><span id="id_$varName" style="display: none" class="editComment">$comment</span></td></tr>
+ # <tr><td class="border"><a href="javascript: displayHelp('$varName')">$varName</a>
+ #
+
if ( $level == 0 ) {
+ my $lcVarName = lc($varName);
$content .= <<EOF;
-<tr id="id_$varName" class="optionalComment"><td colspan="2">$comment</td></tr>
-<tr><td class="border"><a href="javascript: displayHelp('$varName')">$varName</a>
+<tr><td class="border"><a href="?action=view&type=docs#_conf_${lcVarName}_">$varName</a>
EOF
if ( defined($overrideVar) ) {
my $override_checked = "";
- if ( !$isError && $In{deleteVar} =~ /^\Q${varName}_/
- || !$isError && $In{insertVar} =~ /^\Q${varName}\E(_|$)/
- || !$isError && $In{addVar} =~ /^\Q${varName}\E(_|$)/ ) {
+ if ( !$isError && $In{deleteVar} =~ /^\Q${varName}_zZ_/
+ || !$isError && $In{insertVar} =~ /^\Q${varName}\E(_zZ_|$)/
+ || !$isError && $In{addVar} =~ /^\Q${varName}\E(_zZ_|$)/ ) {
$overrideSet = 1;
}
if ( $overrideSet ) {
$override_checked = "checked";
}
$content .= <<EOF;
-<br><input type="checkbox" name="override_$varName" $override_checked value="1" onClick="checkboxChange('$varName')">\ Override
+<br><input type="checkbox" name="override_$varName" $override_checked value="1" onClick="checkboxChange('$varName')">\ ${EscHTML($Lang->{CfgEdit_Button_Override})}
EOF
}
$content .= "</td>\n";
}
- $content .= "<td class=\"border\">\n";
if ( $type->{type} eq "list" ) {
+ $content .= "<td class=\"border\">\n";
$varValue = [] if ( !defined($varValue) );
$varValue = [$varValue] if ( ref($varValue) ne "ARRAY" );
- if ( !$isError && $In{deleteVar} =~ /^\Q${varName}_\E(\d+)$/
+ if ( !$isError && $In{deleteVar} =~ /^\Q${varName}_zZ_\E(\d+)$/
&& $1 < @$varValue ) {
#
# User deleted entry in this array
splice(@$varValue, $1, 1) if ( @$varValue > 1 || $type->{emptyOk} );
$In{deleteVar} = "";
}
- if ( !$isError && $In{insertVar} =~ /^\Q${varName}_\E(\d+)$/
+ if ( !$isError && $In{insertVar} =~ /^\Q${varName}_zZ_\E(\d+)$/
&& $1 < @$varValue ) {
#
# User inserted entry in this array
$In{addVar} = "";
}
$content .= "<table border=\"1\" cellspacing=\"0\">\n";
+ my $colspan;
- for ( my $i = 0 ; $i < @$varValue ; $i++ ) {
- $content .= "<tr><td class=\"border\">\n";
- if ( @$varValue > 1 || $type->{emptyOk} ) {
- $content .= <<EOF;
-<input type="button" name="ins_${varName}_$i" value="Insert"
- onClick="insertSubmit('${varName}_$i')">
-<input type="button" name="del_${varName}_$i" value="Delete"
- onClick="deleteSubmit('${varName}_$i')">
-EOF
- }
- $content .= "</td>\n";
- $content .= fieldEditBuild($type->{child}, "${varName}_$i",
- $varValue->[$i], $errors, $level + 1, undef,
- $isError, $onchangeSubmit,
- $overrideVar, $overrideSet);
+ if ( ref($type) eq "HASH" && ref($type->{child}) eq "HASH"
+ && $type->{child}{type} eq "horizHash" ) {
+ my @order;
+ if ( defined($type->{child}{order}) ) {
+ @order = @{$type->{child}{order}};
+ } else {
+ @order = sort(keys(%{$type->{child}{child}}));
+ }
+ $content .= "<tr><td class=\"border\"></td>\n";
+ for ( my $i = 0 ; $i < @order ; $i++ ) {
+ $content .= "<td class=\"tableheader\">$order[$i]</td>\n";
+ }
+ $colspan = @order + 1;
$content .= "</tr>\n";
+ for ( my $i = 0 ; $i < @$varValue ; $i++ ) {
+ if ( @$varValue > 1 || $type->{emptyOk} ) {
+ $content .= <<EOF;
+<td class="border">
+<input type="button" name="del_${varName}_zZ_$i" value="${EscHTML($Lang->{CfgEdit_Button_Delete})}"
+ onClick="deleteSubmit('${varName}_zZ_$i')">
+</td>
+EOF
+ }
+ $content .= fieldEditBuild($type->{child}, "${varName}_zZ_$i",
+ $varValue->[$i], $errors, $level + 1, undef,
+ $isError, $onchangeSubmit,
+ $overrideVar, $overrideSet);
+ $content .= "</tr>\n";
+ }
+ } else {
+ for ( my $i = 0 ; $i < @$varValue ; $i++ ) {
+ $content .= <<EOF;
+<tr><td class="border">
+<input type="button" name="ins_${varName}_zZ_$i" value="${EscHTML($Lang->{CfgEdit_Button_Insert})}"
+ onClick="insertSubmit('${varName}_zZ_$i')">
+EOF
+ if ( @$varValue > 1 || $type->{emptyOk} ) {
+ $content .= <<EOF;
+<input type="button" name="del_${varName}_zZ_$i" value="${EscHTML($Lang->{CfgEdit_Button_Delete})}"
+ onClick="deleteSubmit('${varName}_zZ_$i')">
+EOF
+ }
+ $content .= "</td>\n";
+ $content .= fieldEditBuild($type->{child}, "${varName}_zZ_$i",
+ $varValue->[$i], $errors, $level + 1, undef,
+ $isError, $onchangeSubmit,
+ $overrideVar, $overrideSet);
+ $content .= "</tr>\n";
+ }
+ $colspan = 2;
}
$content .= <<EOF;
-<tr><td class="border"><input type="button" name="add_$varName" value="Add"
+<tr><td class="border" colspan="$colspan"><input type="button" name="add_$varName" value="${EscHTML($Lang->{CfgEdit_Button_Add})}"
onClick="addSubmit('$varName')"></td></tr>
</table>
EOF
+ $content .= "</td>\n";
} elsif ( $type->{type} eq "hash" ) {
+ $content .= "<td class=\"border\">\n";
$content .= "<table border=\"1\" cellspacing=\"0\">\n";
$varValue = {} if ( ref($varValue) ne "HASH" );
if ( !$isError && !$type->{noKeyEdit}
- && $In{deleteVar} =~ /^\Q${varName}_\E(\w+)$/ ) {
+ && $In{deleteVar} !~ /^\Q${varName}_zZ_\E.*_zZ_/
+ && $In{deleteVar} =~ /^\Q${varName}_zZ_\E(.*)$/ ) {
#
- # User deleted entry in this array
+ # User deleted entry in this hash
#
delete($varValue->{$1}) if ( keys(%$varValue) > 1
|| $type->{emptyOk} );
#
# User added entry to this array
#
- $varValue->{$In{addVarKey}} = ""
- if ( !defined($varValue->{$In{addVarKey}}) );
+ $varValue->{$In{"addVarKey_$varName"}} = ""
+ if ( !defined($varValue->{$In{"addVarKey_$varName"}}) );
$In{addVar} = "";
}
my(@order, $childType);
- if ( defined($type->{child}) ) {
+ if ( defined($type->{order}) ) {
+ @order = @{$type->{order}};
+ } elsif ( defined($type->{child}) ) {
@order = sort(keys(%{$type->{child}}));
} else {
@order = sort(keys(%$varValue));
if ( !$type->{noKeyEdit}
&& (keys(%$varValue) > 1 || $type->{emptyOk}) ) {
$content .= <<EOF;
-<input type="submit" name="del_${varName}_$fld" value="Delete"
- onClick="deleteSubmit('${varName}_$fld')">
+<input type="submit" name="del_${varName}_zZ_$fld" value="${EscHTML($Lang->{CfgEdit_Button_Delete})}"
+ onClick="deleteSubmit('${varName}_zZ_$fld')">
EOF
}
if ( defined($type->{child}) ) {
EOF
}
$content .= "</td>\n";
- $content .= fieldEditBuild($childType, "${varName}_$fld",
+ $content .= fieldEditBuild($childType, "${varName}_zZ_$fld",
$varValue->{$fld}, $errors, $level + 1, undef,
$isError, $onchangeSubmit,
$overrideVar, $overrideSet);
if ( !$type->{noKeyEdit} ) {
$content .= <<EOF;
<tr><td class="border" colspan="2">
-New key: <input type="text" name="addVarKey" size="20" maxlength="256" value="">
-<input type="button" name="add_$varName" value="Add" onClick="addSubmit('$varName', 1)">
+$Lang->{CfgEdit_Button_New_Key}: <input type="text" class="editTextInput" name="addVarKey_$varName" size="20" maxlength="256" value="">
+<input type="button" name="add_$varName" value="${EscHTML($Lang->{CfgEdit_Button_Add})}" onClick="addSubmit('$varName', 1)">
</td></tr>
EOF
}
$content .= "</table>\n";
+ $content .= "</td>\n";
+ } elsif ( $type->{type} eq "horizHash" ) {
+ $varValue = {} if ( ref($varValue) ne "HASH" );
+ my(@order, $childType);
+
+ if ( defined($type->{order}) ) {
+ @order = @{$type->{order}};
+ } elsif ( defined($type->{child}) ) {
+ @order = sort(keys(%{$type->{child}}));
+ } else {
+ @order = sort(keys(%$varValue));
+ }
+
+ foreach my $fld ( @order ) {
+ if ( defined($type->{child}) ) {
+ $childType = $type->{child}{$fld};
+ } else {
+ $childType = $type->{childType};
+ #
+ # emit list of fields since they are user-defined
+ # rather than hard-coded
+ #
+ $content .= <<EOF;
+<input type="hidden" name="vflds.$varName" value="${EscHTML($fld)}">
+EOF
+ }
+ $content .= fieldEditBuild($childType, "${varName}_zZ_$fld",
+ $varValue->{$fld}, $errors, $level + 1, undef,
+ $isError, $onchangeSubmit,
+ $overrideVar, $overrideSet);
+ }
} else {
+ $content .= "<td class=\"border\">\n";
if ( $isError ) {
#
# If there was an error, we use the original post values
# in %In, rather than the parsed values in $varValue.
# This is so that the user's erroneous input is preserved.
#
- $varValue = $In{"v_$varName"} if ( defined($In{"v_$varName"}) );
+ $varValue = $In{"v_zZ_$varName"} if ( defined($In{"v_zZ_$varName"}) );
}
if ( defined($errors->{$varName}) ) {
$content .= <<EOF;
-$errors->{$varName}<br>
+<span class="editError">$errors->{$varName}</span><br>
EOF
- delete($errors->{$varName});
}
my $onChange;
if ( defined($overrideVar) ) {
$onChange .= "checkboxSet('$overrideVar');";
} else {
- $onChange .= "varChange('$overrideVar');";
+ $onChange .= "varChange('$varName');";
}
if ( $onchangeSubmit ) {
- $onChange .= "document.form1.submit();";
+ $onChange .= "document.editForm.submit();";
}
if ( $onChange ne "" ) {
$onChange = " onChange=\"$onChange\"";
if ( $varValue !~ /\n/ &&
($type->{type} eq "integer"
|| $type->{type} eq "string"
+ || $type->{type} eq "execPath"
|| $type->{type} eq "shortlist"
|| $type->{type} eq "float") ) {
# simple input box
$varValue = [$varValue] if ( ref($varValue) ne "ARRAY" );
$varValue = join(", ", @$varValue);
}
+ my $textType = ($varName =~ /Passwd/) ? "password" : "text";
$content .= <<EOF;
-<input type="text" name="v_$varName" size="$size" maxlength="256" value="${EscHTML($varValue)}"$onChange>
+<input type="$textType" class="editTextInput" name="v_zZ_$varName" size="$size" maxlength="256" value="${EscHTML($varValue)}"$onChange>
EOF
} elsif ( $type->{type} eq "boolean" ) {
# checkbox
my $checked = "checked" if ( $varValue );
$content .= <<EOF;
-<input type="checkbox" name="v_$varName" $checked value="1">
+<input type="checkbox" name="v_zZ_$varName" $checked value="1"$onChange>
EOF
} elsif ( $type->{type} eq "select" ) {
$content .= <<EOF;
-<select name="v_$varName"$onChange>
+<select name="v_zZ_$varName"$onChange>
EOF
foreach my $option ( @{$type->{values}} ) {
my $sel = " selected" if ( $varValue eq $option );
my $rowCnt = $varValue =~ tr/\n//;
$rowCnt = 1 if ( $rowCnt < 1 );
$content .= <<EOF;
-<textarea name="v_$varName" cols="$size" rows="$rowCnt"$onChange>${EscHTML($varValue)}</textarea>
+<textarea name="v_zZ_$varName" class="editTextArea" cols="$size" rows="$rowCnt"$onChange>${EscHTML($varValue)}</textarea>
EOF
}
+ $content .= "</td>\n";
}
- $content .= "</td>\n";
return $content;
}
if ( $type->{type} eq "list" ) {
for ( my $i = 0 ; ; $i++ ) {
- last if ( fieldErrorCheck($type->{child}, "${varName}_$i", $errors) );
+ last if ( fieldErrorCheck($type->{child}, "${varName}_zZ_$i", $errors) );
}
- } elsif ( $type->{type} eq "hash" ) {
+ } elsif ( $type->{type} eq "hash" || $type->{type} eq "horizHash" ) {
my(@order, $childType);
my $ret;
- if ( defined($type->{child}) ) {
+ if ( defined($type->{order}) ) {
+ @order = @{$type->{order}};
+ } elsif ( defined($type->{child}) ) {
@order = sort(keys(%{$type->{child}}));
} else {
@order = split(/\0/, $In{"vflds.$varName"});
} else {
$childType = $type->{childType};
}
- $ret ||= fieldErrorCheck($childType, "${varName}_$fld", $errors);
+ $ret ||= fieldErrorCheck($childType, "${varName}_zZ_$fld", $errors);
}
return $ret;
} else {
- return 1 if ( !exists($In{"v_$varName"}) );
+ $In{"v_zZ_$varName"} = "0" if ( $type->{type} eq "boolean"
+ && $In{"v_zZ_$varName"} eq "" );
+
+ return 1 if ( !exists($In{"v_zZ_$varName"}) );
+
+ (my $var = $varName) =~ s/_zZ_/./g;
if ( $type->{type} eq "integer"
|| $type->{type} eq "boolean" ) {
- if ( $In{"v_$varName"} !~ /^-?\d+\s*$/s
- && $In{"v_$varName"} ne "" ) {
- $errors->{$varName} = "Error: $varName must be an integer";
+ if ( $In{"v_zZ_$varName"} !~ /^-?\d+\s*$/s
+ && $In{"v_zZ_$varName"} ne "" ) {
+ $errors->{$varName} = eval("qq{$Lang->{CfgEdit_Error__must_be_an_integer}}");
}
} elsif ( $type->{type} eq "float" ) {
- if ( $In{"v_$varName"} !~ /^-?\d*(\.\d*)?\s*$/s
- && $In{"v_$varName"} ne "" ) {
+ if ( $In{"v_zZ_$varName"} !~ /^-?\d*(\.\d*)?\s*$/s
+ && $In{"v_zZ_$varName"} ne "" ) {
$errors->{$varName}
- = "Error: $varName must be a real-valued number";
+ = eval("qq{$Lang->{CfgEdit_Error__must_be_real_valued_number}}");
}
} elsif ( $type->{type} eq "shortlist" ) {
- my @vals = split(/[,\s]+/, $In{"v_$varName"});
+ my @vals = split(/[,\s]+/, $In{"v_zZ_$varName"});
for ( my $i = 0 ; $i < @vals ; $i++ ) {
if ( $type->{child} eq "integer"
&& $vals[$i] !~ /^-?\d+\s*$/s
&& $vals[$i] ne "" ) {
my $k = $i + 1;
- $errors->{$varName} = "Error: $varName entry $k must"
- . " be an integer";
+ $errors->{$varName} = eval("qq{$Lang->{CfgEdit_Error__entry__must_be_an_integer}}");
} elsif ( $type->{child} eq "float"
&& $vals[$i] !~ /^-?\d*(\.\d*)?\s*$/s
&& $vals[$i] ne "" ) {
my $k = $i + 1;
- $errors->{$varName} = "Error: $varName entry $k must"
- . " be a real-valued number";
+ $errors->{$varName} = eval("qq{$Lang->{CfgEdit_Error__entry__must_be_real_valued_number}}");
}
}
} elsif ( $type->{type} eq "select" ) {
my $match = 0;
foreach my $option ( @{$type->{values}} ) {
- if ( $In{"v_$varName"} eq $option ) {
+ if ( $In{"v_zZ_$varName"} eq $option ) {
$match = 1;
last;
}
}
- $errors->{$varName} = "Error: $varName must be a valid option"
+ $errors->{$varName} = eval("qq{$Lang->{CfgEdit_Error__must_be_valid_option}}")
if ( !$match );
+ } elsif ( $type->{type} eq "execPath" ) {
+ if ( $In{"v_zZ_$varName"} ne "" && !-x $In{"v_zZ_$varName"} ) {
+ $errors->{$varName} = eval("qq{$Lang->{CfgEdit_Error__must_be_executable_program}}");
+ }
} else {
#
# $type->{type} eq "string": no error checking
foreach my $param ( keys(%ConfigMeta) ) {
my $value;
- next if ( $userHost && !$bpc->{Conf}{CgiUserConfigEdit}{$param} );
+ next if ( $userHost
+ && (!defined($bpc->{Conf}{CgiUserConfigEdit}{$param})
+ || (!$PrivAdmin
+ && !$bpc->{Conf}{CgiUserConfigEdit}{$param})) );
fieldInputParse($ConfigMeta{$param}, $param, \$value);
$conf->{$param} = $value;
$override->{$param} = $In{"override_$param"};
-}
+ }
return ($conf, $override);
}
$$value = [];
for ( my $i = 0 ; ; $i++ ) {
my $val;
- last if ( fieldInputParse($type->{child}, "${varName}_$i", \$val) );
+ last if ( fieldInputParse($type->{child}, "${varName}_zZ_$i", \$val) );
push(@$$value, $val);
}
$$value = undef if ( $type->{undefIfEmpty} && @$$value == 0 );
- } elsif ( $type->{type} eq "hash" ) {
+ } elsif ( $type->{type} eq "hash" || $type->{type} eq "horizHash" ) {
my(@order, $childType);
my $ret;
$$value = {};
- if ( defined($type->{child}) ) {
+ if ( defined($type->{order}) ) {
+ @order = @{$type->{order}};
+ } elsif ( defined($type->{child}) ) {
@order = sort(keys(%{$type->{child}}));
} else {
@order = split(/\0/, $In{"vflds.$varName"});
} else {
$childType = $type->{childType};
}
- $ret ||= fieldInputParse($childType, "${varName}_$fld", \$val);
+ $ret ||= fieldInputParse($childType, "${varName}_zZ_$fld", \$val);
last if ( $ret );
$$value->{$fld} = $val;
}
return $ret;
} else {
if ( $type->{type} eq "boolean" ) {
- $$value = 0 + $In{"v_$varName"};
- } elsif ( !exists($In{"v_$varName"}) ) {
+ $$value = 0 + $In{"v_zZ_$varName"};
+ } elsif ( !exists($In{"v_zZ_$varName"}) ) {
return 1;
}
+ my $v = $In{"v_zZ_$varName"};
+
if ( $type->{type} eq "integer" ) {
- $$value = 0 + $In{"v_$varName"};
+ if ( $v =~ /^-?\d+\s*$/s || $v eq "" ) {
+ $$value = 0 + $v;
+ } else {
+ # error value - keep in string form
+ $$value = $v;
+ }
} elsif ( $type->{type} eq "float" ) {
- $$value = 0 + $In{"v_$varName"};
+ if ( $v =~ /^-?\d*(\.\d*)?\s*$/s || $v eq "" ) {
+ $$value = 0 + $v;
+ } else {
+ # error value - keep in string form
+ $$value = $v;
+ }
} elsif ( $type->{type} eq "shortlist" ) {
- $$value = [split(/[,\s]+/, $In{"v_$varName"})];
- if ( $type->{child} eq "float"
- || $type->{child} eq "integer"
- || $type->{child} eq "boolean" ) {
+ $$value = [split(/[,\s]+/, $v)];
+ if ( $type->{child} eq "float" ) {
+ foreach ( @$$value ) {
+ if ( /^-?\d*(\.\d*)?\s*$/s || $v eq "" ) {
+ $_ += 0;
+ }
+ }
+ } elsif ( $type->{child} eq "integer"
+ || $type->{child} eq "boolean" ) {
foreach ( @$$value ) {
- $_ += 0;
+ if ( /^-?\d+\s*$/s || $v eq "" ) {
+ $_ += 0;
+ }
}
}
} else {
- $$value = $In{"v_$varName"};
+ $$value = decode_utf8($In{"v_zZ_$varName"});
+ $$value =~ s/\r\n/\n/g;
+ # remove leading space from exec paths
+ $$value =~ s/^\s+// if ( $type->{type} eq "execPath" );
}
$$value = undef if ( $type->{undefIfEmpty} && $$value eq "" );
}
if ( !exists($oldConf->{$p}) && !exists($newConf->{$p}) ) {
next;
} elsif ( exists($oldConf->{$p}) && !exists($newConf->{$p}) ) {
- $mesg .= "log Deleted $p from $conf\n";
+ $mesg .= eval("qq($Lang->{CfgEdit_Log_Delete_param})");
} elsif ( !exists($oldConf->{$p}) && exists($newConf->{$p}) ) {
my $dump = Data::Dumper->new([$newConf->{$p}]);
$dump->Indent(0);
$dump->Sortkeys(1);
$dump->Terse(1);
my $value = $dump->Dump;
- $mesg .= "log Added $p to $conf, set to $value\n";
+ $value =~ s/\n/\\n/g;
+ $value =~ s/\r/\\r/g;
+ if ( $p =~ /Passwd/ || $p =~ /Secret/ ) {
+ $value = "'*'";
+ }
+
+ $mesg .= eval("qq($Lang->{CfgEdit_Log_Add_param_value})");
} else {
my $dump = Data::Dumper->new([$newConf->{$p}]);
$dump->Indent(0);
$dump->Terse(1);
my $valueOld = $dump->Dump;
- $mesg .= "log Changed $p in $conf to $valueNew from $valueOld\n"
- if ( $valueOld ne $valueNew );
+ (my $valueNew2 = $valueNew) =~ s/['\n\r]//g;
+ (my $valueOld2 = $valueOld) =~ s/['\n\r]//g;
+
+ next if ( $valueOld2 eq $valueNew2 );
+
+ $valueNew =~ s/\n/\\n/g;
+ $valueOld =~ s/\n/\\n/g;
+ $valueNew =~ s/\r/\\r/g;
+ $valueOld =~ s/\r/\\r/g;
+ if ( $p =~ /Passwd/ || $p =~ /Secret/ ) {
+ $valueNew = "'*'";
+ $valueOld = "'*'";
+ }
+
+ $mesg .= eval("qq($Lang->{CfgEdit_Log_Change_param_value})");
}
}
return $mesg;
}
+sub hostsDiffMesg
+{
+ my($hostsNew) = @_;
+ my $hostsOld = $bpc->HostInfoRead();
+ my($mesg, $hostChange);
+
+ foreach my $host ( keys(%$hostsOld) ) {
+ if ( !defined($hostsNew->{$host}) ) {
+ $mesg .= eval("qq($Lang->{CfgEdit_Log_Host_Delete})");
+ $hostChange++;
+ next;
+ }
+ foreach my $key ( keys(%{$hostsNew->{$host}}) ) {
+ next if ( $hostsNew->{$host}{$key} eq $hostsOld->{$host}{$key} );
+ my $valueOld = $hostsOld->{$host}{$key};
+ my $valueNew = $hostsNew->{$host}{$key};
+ $mesg .= eval("qq($Lang->{CfgEdit_Log_Host_Change})");
+ $hostChange++;
+ }
+ }
+
+ foreach my $host ( keys(%$hostsNew) ) {
+ next if ( defined($hostsOld->{$host}) );
+ my $dump = Data::Dumper->new([$hostsNew->{$host}]);
+ $dump->Indent(0);
+ $dump->Sortkeys(1);
+ $dump->Terse(1);
+ my $value = $dump->Dump;
+ $value =~ s/\n/\\n/g;
+ $value =~ s/\r/\\r/g;
+ $mesg .= eval("qq($Lang->{CfgEdit_Log_Host_Add})");
+ $hostChange++;
+ }
+ return ($mesg, $hostChange);
+}
+
1;