Handle hostnames with upper-case letters
[webmin.git] / tcpwrappers / tcpwrappers-lib.pl
1 # tcpwrappers-lib.pl
2 # Library for TCP Wrappers
3
4 BEGIN { push(@INC, ".."); };
5 use WebminCore;
6 &init_config();
7
8 # list_rules($filename)
9 # Parse rules from /etc/hosts.*
10 # File format described in "man 5 hosts_access"
11 sub list_rules {
12     my $file = shift;
13     my @ret;
14     my $id = 0;
15
16     open(HOSTS, $file) || return ();
17     my $line;
18     my $last_line = '';
19     my $lnum = 0;
20     while ($line = <HOSTS>) {
21         my ($slnum, $elnum) = ($lnum, $lnum);
22         s/\r|\n//g;
23
24         while ($line =~ /^(.*)\\/) {
25             # Continuation line! Read the next one and append it
26             local $before = $1;
27             local $nxt = <HOSTS>;
28             $nxt =~ s/\r|\n//g;
29             $line = $before.$nxt;
30             $elnum++; $lnum++;
31         }
32
33         if ($line =~ /^\#(.*)/) {
34             # Comment
35             $cmt = $cmt ? $cmt."\n".$1 : $1;
36         } elsif ($line =~ /^\s*$/) {
37             $cmt = undef;
38         } else {
39             my @cmtlines = split(/\n/, $cmt);
40             $cmt = undef;
41             my ($service, $host, $cmd) = split /:/, $line, 3;
42             $service =~ s/^\s*//; $service =~ s/\s*$//;
43             $host =~ s/^\s*//; $host =~ s/\s*$//;
44             
45             push @ret, { 'id' => $id++,
46                          'service' => $service,
47                          'host' => $host,
48                          'cmd' => $cmd,
49                          'line' => $slnum-scalar(@cmtlines),
50                          'eline' => $elnum
51                          };
52         }
53         $lnum++;
54     }
55     close FILE;
56
57     return @ret;
58 }
59
60 # list_services()
61 # List system services from (x)inetd or return ()
62 sub list_services {
63     my @ret;
64
65     if (&foreign_installed("xinetd")) {
66         &foreign_require("xinetd", "xinetd-lib.pl");
67         my @conf = &foreign_call('xinetd', 'get_xinetd_config');
68         foreach $x (@conf) {
69             next if ($x->{'quick'}{'server'}[0] !~ /\/([^\/]+)$/);
70             push @ret, $1;
71         }
72     } elsif (&foreign_installed("inetd")) {
73         &foreign_require("inetd", "inetd-lib.pl");
74         my @conf = &foreign_call('inetd', 'list_inets');
75         foreach $x (@conf) {
76             next unless ($x->[9] =~ /^(\S+)/);
77             push @ret, $1;
78         }
79     }
80
81     return &unique(@ret);
82 }
83
84 # delete_rule($filename, &rule)
85 # Removes one rule entry from the file
86 sub delete_rule {
87     my ($filename, $rule) = @_;
88
89     my $lref = &read_file_lines($filename);
90     my $len = $rule->{'eline'} - $rule->{'line'} + 1;
91     splice(@$lref, $rule->{'line'}, $len);
92     &flush_file_lines($filename);
93 }
94
95 # create_rule($filename, &rule)
96 # Adds new rule
97 sub create_rule {
98     my ($file, $rule) = @_;
99
100     my $lref = &read_file_lines($file);
101     my $newline = $rule->{'service'}.' : '.$rule->{'host'}.($rule->{'cmd'} ? ' : '.$rule->{'cmd'} : '');
102     push(@$lref, $newline);
103     &flush_file_lines($file);
104 }
105
106 # modify_rule($filename, &old_rule, &new_rule)
107 # Updates rule
108 sub modify_rule {
109     my ($filename, $oldrule, $newrule) = @_;
110
111     my @newline = ($newrule->{'service'}.' : '.$newrule->{'host'}.($newrule->{'cmd'} ? ' : '.$newrule->{'cmd'} : ''));
112
113     my $lref = &read_file_lines($filename);
114     my $len = $oldrule->{'eline'} - $oldrule->{'line'} + 1;
115     splice(@$lref, $oldrule->{'line'}, $len, @newline);
116     &flush_file_lines($filename);
117 }
118
119 1;