aboutsummaryrefslogtreecommitdiff
path: root/IdaliusConfig.pm
blob: 642d4089100d0447cb9082d11279e82f19ba4fb0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package IdaliusConfig;

use strict;
use warnings;
use Config::Tiny;

use ListParser;

sub config_describe {
	my ($plugin, $parm) = @_;

	# Plugin "_" is the root config
	return $parm unless $plugin ne "_";
	return "$plugin -> $parm";
}

sub assert_common {
	my ($config, $plugin, $parm, $human_type, $ref_type) = @_;
	my $ref = $config->{$parm};
	my $name = config_describe($plugin, $parm);

	die "Error: Configuration \"$name\" must be of type $human_type" unless
		defined $ref
		and ref($ref) eq $ref_type;
}

sub assert_scalar {
	my ($config, $plugin, $parm) = @_;
	assert_common($config, $plugin, $parm, "scalar", "");
}

sub assert_list {
	my ($config, $plugin, $parm) = @_;
	assert_common($config, $plugin, $parm, "list", "ARRAY");
}

sub assert_dict {
	my ($config, $plugin, $parm) = @_;
	assert_common($config, $plugin, $parm, "dictionary", "HASH");
}

# Check presence and/or sanity of config parameters for the bot's core
# I.e. it is up to each module to ensure its own config is there and sane,
# normally in sub configure.
sub check_config
{
	my ($config) = @_;

	# Lists of mandatory config variables 
	my @scalars = qw/nick username ircname server port usessl sslcert sslkey user group prefix_nick prefix log_debug/;
	my @lists   = qw/plugins channels ignore/;

	foreach my $name (@scalars) {
		assert_scalar($config->{_}, "_", $name);
	}

	foreach my $name (@lists) {
		assert_list($config->{_}, "_", $name);
	}

	# Special case: password is optional scalar
	if (defined $config->{_}->{password}) {
		assert_scalar($config->{_}, "_", "password");
	}

}

sub parse_die {
	my ($parsed, $line) = @_;
	my $pad = " " x ($parsed->{column_start} + 1);
	my $underline = "^" x ($parsed->{column_end} - $parsed->{column_start} + 1);

	die "$parsed->{error}:\n$line\n$pad$underline\n";
}

sub parse_config
{
	my $file = $_[0];
	my %built_config;
	my $config = Config::Tiny->read($file);

	foreach my $section (keys %{$config}) {
		foreach my $opt (keys %{$config->{$section}}) {
			# Detect list or hash config option
			my $c = substr $config->{$section}->{$opt}, 0, 1;
			if ($c eq "[") {
				my $parsed = ListParser::parse_list($config->{$section}->{$opt}, 0);
				parse_die($parsed, $config->{$section}->{$opt}) if $parsed->{error};
				$config->{$section}->{$opt} = $parsed->{array};
			} elsif ($c eq "{") {
				my $parsed = ListParser::parse_list($config->{$section}->{$opt}, 1);
				parse_die($parsed, $config->{$section}->{$opt}) if $parsed->{error};
				$config->{$section}->{$opt} = $parsed->{hash};
			}
		}
	}

#	my ($error, @tmp) = ListParser::parse_list($config->{_}->{plugins});
#	$config->{_}->{plugins} = \@tmp;


	# Special case
	$config->{_}->{uid} = getpwnam($config->{_}->{user})
		or die "Cannot get uid of $config->{_}->{user}: $!\n";
	$config->{_}->{gid} = getgrnam($config->{_}->{group})
		or die "Cannot get gid of $config->{_}->{group}: $!\n";

	check_config($config);

	return $config;
}
1;