#!/usr/bin/perl
# active_table.cgi
# Show a read-only active nftables table

require './nftables-lib.pl';    ## no critic
use strict;
use warnings;
our (%in, %text);
ReadParse();
error_setup($text{'active_table_err'});
assert_acl('active');

my ($tables, $err) = get_active_nftables_save();
error(text('active_failed', $err)) if ($err);

my $table;
foreach my $t (@$tables) {
	if ($t->{'family'} eq $in{'family'} && $t->{'name'} eq $in{'name'}) {
		$table = $t;
		last;
		}
	}
$table || error($text{'active_table_notable'});
assert_table_acl($table);
my @saved_tables = get_nftables_save();
my $status_key = active_table_status($table, \@saved_tables);
my $is_saved = table_is_webmin_managed($table, \@saved_tables);

ui_print_header(undef, $text{'active_table_title'}, "");

print ui_table_start($text{'active_table_summary'}, "width=100%", 2);
print ui_table_row($text{'active_table'}, html_escape(nft_table_spec($table)));
print ui_table_row($text{'active_flags'}, html_escape($table->{'flags'} || "-"));
print ui_table_row($text{'active_status'}, $text{'active_'.$status_key});
print ui_table_end();

if (!$is_saved && check_acl('import')) {
	print ui_buttons_start();
	print ui_buttons_row(
		"import_table.cgi?family=".
		    urlize($table->{'family'}).
		    "&name=".
		    urlize($table->{'name'}),
		$text{'active_import'}, $text{'active_importdesc'}
	);
	print ui_buttons_end();
	}

my ($chains_html, $sets_html);

$chains_html .= ui_columns_start(
	[ $text{'index_chain_col'}, $text{'index_type'},
	  $text{'index_hook'}, $text{'index_priority'},
	  $text{'index_policy_col'}, $text{'index_rules'} ],
	100
);
foreach my $c (sort keys %{$table->{'chains'}}) {
	my $chain_def = $table->{'chains'}->{$c} || {};
	my $policy = $chain_def->{'policy'};
	my $policy_label =
	    $policy ? ($text{'index_policy_'.lc($policy)} || uc($policy)) : "-";
	my @rules = grep { $_->{'chain'} eq $c } @{$table->{'rules'}};
	my $rules_html = @rules
	    ? ui_tag(
		'div',
		join(
			"",
			map {
				ui_tag('div', describe_rule($_),
					{'class' => 'nftables_rule_text'})
			    } @rules
		),
		{ 'class' => 'nftables_rules_list',
		  'style' => 'display: grid; row-gap: 0.25em;' }
	    )
	    : ui_tag('i', $text{'index_rules_none'});
	$chains_html .= ui_columns_row(
		[ html_escape($c),
		  html_escape($chain_def->{'type'} || "-"),
		  html_escape($chain_def->{'hook'} || "-"),
		  defined($chain_def->{'priority'})
			? html_escape($chain_def->{'priority'})
			: "-",
		  html_escape($policy_label),
		  $rules_html ]);
	}
$chains_html .= ui_columns_end();

$sets_html .= ui_columns_start(
	[
		$text{'index_set_name'}, $text{'index_set_type'},
		$text{'index_set_flags'}, $text{'index_set_elements'}
	],
	100
);
if ($table->{'sets'} && ref($table->{'sets'}) eq 'HASH') {
	foreach my $s (sort keys %{$table->{'sets'}}) {
		my $set = $table->{'sets'}->{$s} || {};
		$sets_html .= ui_columns_row(
			[ html_escape($s),
			  html_escape($set->{'type'} || "-"),
			  html_escape($set->{'flags'} || "-"),
			  html_escape(set_elements_summary($set)),
			]
		);
		}
	}
$sets_html .= ui_columns_end();

my @tabs = (['chains', $text{'index_tab_chains'}], ['sets', $text{'index_tab_sets'}],);
my $tab = $in{'view'} && $in{'view'} eq 'sets' ? 'sets' : 'chains';
print ui_hr();
print ui_tabs_start(\@tabs, "view", $tab, 1);
print ui_tabs_start_tab("view", "chains");
print $chains_html;
print ui_tabs_end_tab();
print ui_tabs_start_tab("view", "sets");
print $sets_html;
print ui_tabs_end_tab();
print ui_tabs_end(1);

ui_print_footer("active.cgi", $text{'active_return'});
