Handle hostnames with upper-case letters
[webmin.git] / mailcap / mailcap-lib.pl
1 # Functions for editing /etc/mailcap
2
3 BEGIN { push(@INC, ".."); };
4 use WebminCore;
5 &init_config();
6
7 if ($module_info{'usermin'}) {
8         &switch_to_remote_user();
9         $mailcap_file = $userconfig{'mailcap'};
10         if ($mailcap_file !~ /^\//) {
11                 $mailcap_file = "$remote_user_info[7]/$mailcap_file";
12                 }
13         }
14 else {
15         $mailcap_file = $config{'mailcap'};
16         }
17
18 # list_mailcap()
19 # Returns a list of /etc/mailcap entries
20 sub list_mailcap
21 {
22 if (!scalar(@list_mailcap_cache)) {
23   @list_mailcap_cache = ( );
24   open(CAP, $mailcap_file);
25   local $lnum = 0;
26   while(<CAP>) {
27           local ($slnum, $elnum) = ($lnum, $lnum);
28           s/\r|\n//g;
29           while (/^(.*)\\/) {
30                 # Continuation line! Read the next one and append it
31                 local $before = $1;
32                 local $nxt = <CAP>;
33                 $nxt =~ s/\r|\n//g;
34                 $_ = $before.$nxt;
35                 $elnum++;
36                 }
37           if (/^(#*)\s*([a-z0-9\-]+)\/([a-z0-9\-\*]+);\s*([^;]*)(;(.*))?/) {
38                   # Found a line
39                   local @cmtlines = split(/\n/, $cmt);
40                   local $cap = { 'type' => $2."/".$3,
41                                  'program' => $4,
42                                  'enabled' => !$1,
43                                  'cmt' => $cmt,
44                                  'args' => { },
45                                  'line' => $slnum-scalar(@cmtlines),
46                                  'eline' => $elnum,
47                                  'index' => scalar(@list_mailcap_cache),
48                                };
49                   # Parse ; separated args after the command
50                   local $args = $6;
51                   local @args = split(/\s*;\s*/, $args);
52                   foreach my $arg (@args) {
53                         if ($arg =~ /^\s*(\S+)\s*=\s*(.*)/) {
54                                 # A name-value arg
55                                 $cap->{'args'}->{$1} = $2;
56                                 }
57                         elsif ($arg =~ /^\s*(\S+)\s*$/) {
58                                 $cap->{'args'}->{$1} = "";
59                                 }
60                         }
61                   push(@list_mailcap_cache, $cap);
62                   $cmt = undef;
63                   }
64           elsif (/^#+(.*)/) {
65                   # Found a comment before a rule
66                   if ($cmt) {
67                         $cmt .= "\n".$1;
68                         }
69                   else {
70                         $cmt = $1;
71                         }
72                   }
73           else {
74                   $cmt = undef;
75                   }
76           $lnum++;
77           }
78   close(CAP);
79   }
80 return @list_mailcap_cache;
81 }
82
83 # create_mailcap(&mailcap)
84 # Adds a mailcap entry
85 sub create_mailcap
86 {
87 local ($mailcap) = @_;
88 &list_mailcap();  # init cache
89 local $lref = &read_file_lines($mailcap_file);
90 local @lines = &mailcap_lines($mailcap);
91 $mailcap->{'line'} = scalar(@$lref);
92 $mailcap->{'eline'} = scalar(@$lref)+scalar(@lines)-1;
93 $mailcap->{'index'} = scalar(@list_mailcap_cache);
94 push(@$lref, @lines);
95 &flush_file_lines($mailcap_file);
96 push(@list_mailcap_cache, $mailcap);
97 }
98
99 # modify_mailcap(&mailcap)
100 # Updates one mailcap entry in the file
101 sub modify_mailcap
102 {
103 local ($mailcap) = @_;
104 local $lref = &read_file_lines($mailcap_file);
105 local @lines = &mailcap_lines($mailcap);
106 local $oldlen = $mailcap->{'eline'} - $mailcap->{'line'} + 1;
107 splice(@$lref, $mailcap->{'line'}, $oldlen, @lines);
108 &flush_file_lines($mailcap_file);
109 local $diff = scalar(@lines)-$oldlen;
110 foreach my $c (grep { $c ne $mailcap } @list_mailcap_cache) {
111   $c->{'line'} += $diff if ($c->{'line'} > $mailcap->{'line'});
112   $c->{'eline'} += $diff if ($c->{'eline'} > $mailcap->{'line'});
113   }
114 }
115
116 # delete_mailcap(&mailcap)
117 # Removes one mailcap entry from the file
118 sub delete_mailcap
119 {
120 local ($mailcap) = @_;
121 local $lref = &read_file_lines($mailcap_file);
122 local $len = $mailcap->{'eline'} - $mailcap->{'line'} + 1;
123 splice(@$lref, $mailcap->{'line'}, $len);
124 &flush_file_lines($mailcap_file);
125 @list_mailcap_cache = grep { $_ ne $mailcap } @list_mailcap_cache;
126 foreach my $c (@list_mailcap_cache) {
127   $c->{'line'} -= $len if ($c->{'line'} > $mailcap->{'line'});
128   $c->{'eline'} -= $len if ($c->{'eline'} > $mailcap->{'line'});
129   $c->{'index'}-- if ($c->{'index'} > $mailcap->{'index'});
130   }
131 }
132
133 # mailcap_lines(&mailcap)
134 # Returns an array of lines for a mailcap entry
135 sub mailcap_lines
136 {
137 local ($mailcap) = @_;
138 local @rv;
139 local $args;
140 foreach my $a (keys %{$mailcap->{'args'}}) {
141         local $v = $mailcap->{'args'}->{$a};
142         if ($v eq '') {
143                 $args .= "; $a";
144                 }
145         else {
146                 $args .= "; $a=$v";
147                 }
148         }
149 foreach my $l (split(/\n/, $mailcap->{'cmt'})) {
150         push(@rv, "#$l");
151         }
152 push(@rv, ($mailcap->{'enabled'} ? "" : "#").
153           "$mailcap->{'type'}; $mailcap->{'program'}".$args);
154 return @rv;
155 }
156
157 1;
158