# FILE: adm-accs.pl
# DESCRIPTION: Access Manager
#-------------------------------------------------------------------------------
# DISCUS COPYRIGHT NOTICE
#
# Discus is copyright (c) 2002 by DiscusWare, LLC, all rights reserved.
# The use of Discus is governed by the Discus License Agreement which is
# available from the Discus WWW site at:
#    http://www.discusware.com/discus/license
#
# Pursuant to the Discus License Agreement, this copyright notice may not be
# removed or altered in any way.
#-------------------------------------------------------------------------------

use strict;
use vars qw($GLOBAL_OPTIONS $DCONF $PARAMS);

###
### ACCESS_admin
###
### Runs the Access Manager
###

sub ACCESS_admin {
	my ($FORMref) = @_;
	my $result = check_password($FORMref->{username}, undef, { type_required => 'moderator' }, $FORMref->{'COOKIE'});
	bad_login({ username => 1}) if ! scalar(@{ $result });
	my $subst = {};
	$subst->{'general'}->{'username'} = $result->[0]->{user};
	if ($FORMref->{action} eq "access_mgr_1") {
		dreq("adm-page");
		return page_mgr_1($FORMref->{username}, 2);
	}
	if ($FORMref->{topic} =~ /^C(\d+)$/ || $FORMref->{save_cat}) {
		bad_login( { superuser_required => 1 } ) if $result->[0]->{user} ne $DCONF->{superuser};
		access_manager_cat($FORMref) if $FORMref->{action} eq "access_mgr_2";
		access_manager_cat($FORMref, access_manager_save_cat($FORMref));
	} else {
		dreq("fcn-priv");
		check_topic_authorization($FORMref->{username}, $FORMref->{topic}) or error_message("Permissions Error", "You are not permitted to set access privileges for the selected topic.", 0, 1);
	}
	access_manager($FORMref) if $FORMref->{action} eq "access_mgr_2";
	if ($FORMref->{action} eq "access_mgr_3") {
		access_manager($FORMref, access_manager_save($FORMref));
	}
	access_manager_popup($FORMref) if $FORMref->{action} eq "access_mgr_p";
}

###
### access_manager_cat
###
### Access Manager for categories
###

sub access_manager_cat {
	my ($FORMref, $success) = @_;	
	my $topic = $FORMref->{topic};
	my $subst = {};
	if ($topic =~ /^C(\d+)/) {
		$subst->{general}->{topic} = $1;
		$topic = $1;
	} else {
		$FORMref->{topic} = "C$topic";
		$subst->{general}->{topic} = $topic;
	}
	$subst->{general}->{is_category} = 1;
	$subst->{general}->{username} = $FORMref->{username};
	$subst->{general}->{topic_name} = show_topic_name($FORMref->{topic});
	$subst->{success} = $success;
	my @t = grep { $_->{type} == 1 } @{ board_topics() };
	$subst->{topic_list} = \@t;
	$subst->{checked} = {};
	dreq("fcn-usrp");
	my $p = read_topic_privilege_file();
	if ($p->{$topic}->{'cr'}->{'ip'}->{':list:'} eq "") {
		$subst->{privilege}->{'cr'} = 1;
	} elsif ($p->{$topic}->{'cr'}->{'ip'}->{':list:'} eq "x") {
		$subst->{privilege}->{'cr'} = 0;
	} else {
		$subst->{privilege}->{'cr'} = 2;
		my %ch = map { $_, 1 } split(/,/, $p->{$topic}->{'cr'}->{'ip'}->{':list:'});
		$subst->{checked} = \%ch;
	}	
	screen_out("accmgr", $subst);
}

###
### access_manager_popup
###
### Popup screens in Access Manager
###

sub access_manager_popup {
	my ($FORMref) = @_;
	undef my $subst;
	$subst->{general}->{letter} = $FORMref->{letter};
	dreq("fcn-usrp");
	my $privs = read_topic_privilege_file();
	if ($FORMref->{subaction} eq "modselect") {
		$subst->{general}->{popup} = 1;
		dreq("fcn-priv");
		my $mod = read_account_file("passwd", undef, { returnformat => 'single_array' });
		my @mod = ();
		foreach my $x (@{ $mod }) {
			undef my $i;
			$i->{user} = $x->{user};
			$i->{fullname} = $x->{fullname};
			$i->{checked} = ($privs->{$FORMref->{topic}}->{$FORMref->{letter}}->{moderator}->{$x->{user}} == 1 ? 1 : 0);
			push (@mod, $i);
		}
		@mod = sort { $a->{user} cmp $b->{user} } @mod;
		$subst->{moderators} = \@mod;
	}
	if ($FORMref->{subaction} eq "usrselect") {
		$subst->{general}->{popup} = 2;
		dreq("fcn-grp");
		my $group_file = read_group_file();
		my @grp = ();
		foreach my $g (@{ $group_file->{group_list} }) {
			undef my $i;
			$i->{group} = $g;
			$i->{checked} = ($privs->{$FORMref->{topic}}->{$FORMref->{letter}}->{user}->{$i->{group}} == 1 ? 1 : 0);
			push (@grp, $i);
		}
		@grp = sort { $a->{group} cmp $b->{group} } @grp;
		$subst->{groups} = \@grp;
	}
	if ($FORMref->{subaction} eq "ipselect") {
		$subst->{general}->{popup} = 3;
		my @ips = split(/,/, $privs->{$FORMref->{topic}}->{$FORMref->{letter}}->{ip}->{':list:'});
		my @ip_pass = ();
		my $c = -1;
		foreach my $ip (@ips) {
			$c += 1;
			if ($c == $#ips && $ip =~ m|^[\!\*]+$|) {
				$subst->{general}->{ipseldef} = ($ip eq "!*" ? 2 : 1);
			} else {
				undef my $i;
				$i->{ipval} = $ip;
				$i->{ipval} = $' if $ip =~ m|^!|;
				$i->{ipsel} = ($ip eq "" ? 0 : ( $ip =~ m|^!| ? 2 : 1 ));
				push (@ip_pass, $i);
			}
		}
		for (my $i = 1; $i <= 7; $i++) {
			undef my $f;
			$f->{ipval} = "";
			$f->{ipsel} = 0;
			push (@ip_pass, $f);
		}
		$subst->{ips} = \@ip_pass;
	}
	if ($FORMref->{subaction} eq "specselect") {
		$subst->{general}->{popup} = 4;
		if ($privs->{$FORMref->{topic}}->{$FORMref->{letter}}->{special} ne "") {
			$subst->{general}->{special_exists} = 1;
		}
	}
	screen_out("accmgr", $subst);
}

###
### access_manager_save_cat
###
### Saving of access to category options
###

sub access_manager_save_cat {
	my ($FORMref) = @_;
	my @actions = ();
	my $topic = $FORMref->{topic}; $topic =~ s/\D//g; return -1 if $topic == 0;
	dreq("fcn-usrp");
	my $i = {};
	$i->{topic} = $topic;
	$i->{action} = "set_equal";
	$i->{type} = "cr";
	my $letter = "cr";
	if ($FORMref->{"main$letter"} == 0) {
		$i->{ip} = "x";
		$i->{user} = undef;
		$i->{moderator} = undef;
		$i->{special} = undef;
	} elsif ($FORMref->{"main$letter"} == 1) {
		$i->{ip} = "";
		$i->{user} = undef;
		$i->{moderator} = undef;
		$i->{special} = undef;
	} else {
		$i->{ip} = join(",", grep { /^\d+$/ } split(/,/, $FORMref->{ta}));
		$i->{user} = undef;
		$i->{moderator} = undef;
		$i->{special} = undef;
	}
	push (@actions, $i);
	my $m1 = read_topic_privilege_file(1);
	write_topic_privilege_file(\@actions);
	my $m2 = read_topic_privilege_file(1);
	return { saved => 1 };
}

###
### access_manager_save
###
### Save settings for a topic (return -1 failed, 1 succeeded)
###

sub access_manager_save {
	my ($FORMref) = @_;
	if ($FORMref->{save_cat} == 1) {
		return access_manager_save_cat($FORMref);
	}
	dreq("fcn-usrp", "fcn-priv");
	my $topic = $FORMref->{topic}; $topic =~ s/\D//g; return -1 if $topic == 0;
	my @actions = ();
	{ # Post Options
		my $u = $FORMref->{postoption}; $u =~ s/\W//g;
		undef my $i;
		$i->{topic} = $topic;
		$i->{type} = "o";
		$i->{define} = $u;
		my $k1 = (($FORMref->{ip_on_post} + 0) % 3); $i->{define} .= "i$k1";
		my $k2 = (($FORMref->{ip_on_post_anon} + 0) % 3); $i->{define} .= "j$k2";
		push (@actions, $i);
	}
	{ # Queued Messages
		my $u = $FORMref->{postqueue}; $u =~ s/\W//g;
		undef my $i;
		$i->{topic} = $topic;
		$i->{type} = "q";
		$i->{define} = $u;
		push (@actions, $i);
	}
	{ # Posting & Reading
		foreach my $letter ('p', 'r') {
			next if $letter eq "r" && ! $DCONF->{pro};
			undef my $i;
			$i->{topic} = $topic;
			$i->{action} = "set_equal";
			$i->{type} = $letter;
			if ($FORMref->{"main$letter"} == 0) {
				$i->{ip} = undef;
				$i->{user} = undef;
				$i->{moderator} = undef;
				$i->{special} = undef;
			} elsif ($FORMref->{"main$letter"} == 1) {
				$i->{ip} = "*";
				$i->{user} = undef;
				$i->{moderator} = undef;
				$i->{special} = undef;
			} else {
				$i->{ip} = ( $FORMref->{"ip$letter"} == 0 ? undef : $FORMref->{"ipselect$letter"} );
				$i->{special} = (
					$FORMref->{"spec$letter"} == 0 ? undef :
					($FORMref->{"specselect$letter"} =~ m|^\*| ? crypt(prepare_userpass_p($'), "ab" ) :
					$FORMref->{"specselect$letter"}));
				$i->{moderator} = ( $FORMref->{"mod$letter"} == 0 ? undef :
					( $FORMref->{"modc$letter"} == 0 ? "**" :
					( $FORMref->{"modc$letter"} == 1 ? "*" : $FORMref->{"modselect$letter"} )));
				$i->{user} = ( $FORMref->{"usr$letter"} == 0 ? undef :
					( $FORMref->{"usrc$letter"} == 0 ? "*" : $FORMref->{"usrselect$letter"} ));
				foreach my $x ('ip', 'special', 'moderator', 'user') {
					$i->{$x} =~ s/://g; $i->{$x} =~ s/,,//g; $i->{$x} =~ s/^,+//; $i->{$x} =~ s/,+$//;
				}
			}
			push (@actions, $i);
		}
	}
	{ # Save Settings
		my $m1 = read_topic_privilege_file(1);
		write_topic_privilege_file(\@actions);
		my $m2 = read_topic_privilege_file(1);
		if ($DCONF->{pro}) {
			dreq("fcn-sec-PRO");
			topic_security($topic, $m2);
		}
		my $r1p = determine_addmessage($topic, $m1, "p");
		my $r2p = determine_addmessage($topic, $m2, "p");
		my $r1c = ($r1p->{disabled} + 2*$r1p->{public} + 4*$r1p->{anonymous_posting});
		my $r2c = ($r2p->{disabled} + 2*$r2p->{public} + 4*$r2p->{anonymous_posting});
		if ($r1c != $r2c) {
			dreq("fcn-regn"); regenerate_board({ hold => "topic=$topic", topic => $topic, username => $FORMref->{username}, action => "regen1" });
		}
	}
	return { saved => 1 };
}

###
### access_manager
###
### Main interface of the Access Manager
###

sub access_manager {
	my ($FORMref, $success) = @_;
	my $topic = $FORMref->{topic};
	my $subst = {};
	if ($topic =~ /^C/ || $FORMref->{save_cat}) {
		$subst->{general}->{topic} = $1;
		$subst->{general}->{is_category} = 1;
	} else {
		$subst->{general}->{topic} = $topic;
		$subst->{general}->{is_category} = 0;
	}
	$subst->{general}->{username} = $FORMref->{username};
	$subst->{general}->{topic_name} = show_topic_name($FORMref->{topic});
	$subst->{success} = $success;
	dreq("fcn-usrp");
	my @u = ('p'); push (@u, 'r') if $DCONF->{pro};
	my $p = read_topic_privilege_file();
	foreach my $i (@u) {
		my $x = $p->{$FORMref->{topic}}->{$i};
		$subst->{privilege}->{$i} = (
			($x->{ip}->{':list:'} eq "" && $x->{user}->{':list:'} eq "" && $x->{moderator}->{':list:'} eq "" && $x->{special} eq "") ? 0 :
			( $x->{ip}->{':list:'} eq "*" ? 1 : 2 ));
		$subst->{modcheck}->{$i} = ( $x->{moderator}->{':list:'} eq "" ? 0 : 1 );
		$subst->{modtype}->{$i} = ( $x->{moderator}->{':list:'} eq "**" ? 0 : ( $x->{moderator}->{':list:'} eq "*" ? 1 : 2 ));
		$subst->{usrcheck}->{$i} = ( $x->{user}->{':list:'} eq "" ? 0 : 1 );
		$subst->{usrtype}->{$i} = ( $x->{user}->{':list:'} eq "*" ? 0 : 1 );
		$subst->{ipcheck}->{$i} = ( $x->{ip}->{':list:'} eq "" ? 0 : 1 );
		$subst->{speccheck}->{$i} = ( $x->{special} eq "" ? 0 : 1 );
		$subst->{general}->{"modselect$i"} = $x->{moderator}->{':list:'};
		$subst->{general}->{"usrselect$i"} = $x->{user}->{':list:'};
		$subst->{general}->{"ipselect$i"} = $x->{ip}->{':list:'};
		$subst->{general}->{"specselect$i"} = $x->{special};
	}
	if ($DCONF->{pro}) {
		$subst->{general}->{problem} = 1 if (
			($subst->{privilege}->{'r'} == 1 && -e "$DCONF->{secdir}/$topic") ||
			($subst->{privilege}->{'r'} != 1 && -e "$DCONF->{message_dir}/$topic"));
	}
	$subst->{queuecheck} = $p->{$topic}->{'q'};
	$subst->{postcheck} = $p->{$topic}->{'o'};
	screen_out("accmgr", $subst);
}

###
### show_topic_name
###
### Returns the topic name, given a topic number
###

sub show_topic_name {
	my ($topic_num) = @_;
	if ($topic_num =~ /^C(\d+)$/) {
		my $l = $1;
		my $x = board_topics();
		foreach my $z (@{ $x }) {
			return $z->{text} if $z->{number} == $l;
		}
		return "";
	}	
	return undef if $topic_num !~ m|^\d+$|;
	my $tree = read_tree($topic_num);
	return $tree->[0]->{name};
}

1;
