#!/usr/local/bin/perl
# Save binary logging configuration options

require './mysql-lib.pl';
$access{'perms'} == 1 || &error($text{'binlogs_ecannot'});
&is_mysql_local() || &error($text{'binlogs_eremote'});
&error_setup($text{'binlogs_err'});
&ReadParse();

# Get the mysqld section
foreach my $l (&get_all_mysqld_files()) {
	&lock_file($l);
	}
$conf = &get_mysql_config();
$mysqld = &get_mysqld_config_section($conf);
$mysqld || &error($text{'cnf_emysqld'});
$mems = $mysqld->{'members'};

if ($in{'enabled'}) {
	# Work out the base directive, preserving an existing or active default
	# so that merely saving this page cannot start a new binary log chain.
	# On servers that log by default the directive is also left absent, as
	# writing one would change the default base name even when stopped
	my $lbdir = &find("log_bin", $mems) || &find("log-bin", $mems);
	my $baseargs;
	if ($in{'base_def'}) {
		if ($lbdir) {
			$baseargs = [ $lbdir->{'value'} // "" ];
			}
		else {
			my ($curfile) = &get_binary_log_status();
			$baseargs = $curfile || &get_binlog_default_on() ?
					[ ] : [ "mysql-bin" ];
			}
		}
	else {
		$in{'base'} =~ /^[a-zA-Z0-9\.\-\_\/]+$/ ||
			&error($text{'binlogs_ebase'});
		$baseargs = [ $in{'base'} ];
		}
	&save_directive($conf, $mysqld, "log-bin", [ ]);
	&save_directive($conf, $mysqld, "log_bin", $baseargs);

	# Remove any directives that force binary logging off
	foreach my $s ("skip-log-bin", "skip_log_bin",
		       "disable-log-bin", "disable_log_bin") {
		&save_directive($conf, $mysqld, $s, [ ]);
		}

	# A unique server ID is required by MySQL for binary logging
	my $sid = &find_value("server_id", $mems);
	$sid = &find_value("server-id", $mems) if (!defined($sid));
	if ($in{'serverid_def'}) {
		if (!defined($sid)) {
			&save_directive($conf, $mysqld, "server_id", [ 1 ]);
			}
		}
	else {
		$in{'serverid'} =~ /^\d+$/ && $in{'serverid'} >= 1 &&
		    $in{'serverid'} <= 4294967295 ||
			&error($text{'binlogs_eserverid'});
		&save_directive($conf, $mysqld, "server-id", [ ]);
		&save_directive($conf, $mysqld, "server_id",
				[ $in{'serverid'} ]);
		}
	}
else {
	# Remove the directive under both possible names, and force logging
	# off in case the server enables it by default (as MySQL 8+ does)
	&save_directive($conf, $mysqld, "log-bin", [ ]);
	&save_directive($conf, $mysqld, "log_bin", [ ]);
	foreach my $s ("skip_log_bin", "disable-log-bin",
		       "disable_log_bin") {
		&save_directive($conf, $mysqld, $s, [ ]);
		}
	&save_directive($conf, $mysqld, "skip-log-bin", [ "" ]);
	}

# Save the binary log format
if (defined($in{'format'})) {
	$in{'format'} =~ /^(|ROW|MIXED|STATEMENT)$/ ||
		&error($text{'binlogs_eformat'});
	&save_directive($conf, $mysqld, "binlog-format", [ ]);
	&save_directive($conf, $mysqld, "binlog_format",
			$in{'format'} ? [ $in{'format'} ] : [ ]);
	}

# Save the maximum size of one log file, which the server limits to the
# range from 4 kB to 1 GB
if ($in{'maxsize_def'}) {
	&save_directive($conf, $mysqld, "max-binlog-size", [ ]);
	&save_directive($conf, $mysqld, "max_binlog_size", [ ]);
	}
else {
	$in{'maxsize'} =~ /^\d+$/ ||
		&error($text{'binlogs_emaxsize'});
	defined(&parse_binlog_max_size($in{'maxsize'},
				       $in{'maxsize_units'})) ||
		&error($text{'binlogs_emaxsizerange'});
	&save_directive($conf, $mysqld, "max-binlog-size", [ ]);
	&save_directive($conf, $mysqld, "max_binlog_size",
			[ $in{'maxsize'}.$in{'maxsize_units'} ]);
	}

# Save the retention period, preferring the seconds-based variable on
# servers that support it as it also allows fractional days
my ($ver, $variant) = &get_mysql_variant_cached();
my $newexpire = $variant eq "mysql" &&
		&compare_version_numbers($ver, "8.0") >= 0 ||
		$variant eq "mariadb" &&
		&compare_version_numbers($ver, "10.6") >= 0;
if ($in{'expire_def'}) {
	&save_directive($conf, $mysqld, "binlog_expire_logs_seconds", [ ]);
	&save_directive($conf, $mysqld, "expire_logs_days", [ ]);
	}
else {
	# Fractional days are allowed, and zero disables automatic deletion
	$in{'expire'} =~ /^\d+(\.\d+)?$/ ||
		&error($text{'binlogs_eexpire'});
	my $days = $in{'expire'} + 0;
	if ($newexpire) {
		# The seconds variable is limited to 99 days on MariaDB, and
		# to 32 bits on MySQL
		my $secs = &parse_binlog_expire_days($days);
		my $max = &get_binlog_expire_max($variant);
		$secs <= $max ||
			&error(&text('binlogs_eexpiremax',
				&format_binlog_expire_days($max)));
		&save_directive($conf, $mysqld, "expire_logs_days", [ ]);
		&save_directive($conf, $mysqld, "binlog_expire_logs_seconds",
				[ $secs ]);
		}
	else {
		# The days variable is limited to 99 whole days on servers
		# without the seconds-based variable
		$days <= 99 ||
			&error(&text('binlogs_eexpiremax', 99));
		$days == int($days) ||
			&error($text{'binlogs_eexpireint'});
		&save_directive($conf, $mysqld, "binlog_expire_logs_seconds",
				[ ]);
		&save_directive($conf, $mysqld, "expire_logs_days",
				[ $days ]);
		}
	}

# Write out file, and restart if requested
foreach my $l (&get_all_mysqld_files()) {
	&flush_file_lines($l, undef, 1);
	&unlock_file($l);
	}
if ($in{'restart'} && &is_mysql_running() > 0) {
	&stop_mysql();
	$err = &start_mysql();
	&error($err) if ($err);
	}
&webmin_log("binlogs");
&redirect("edit_binlogs.cgi");
