Handle hostnames with upper-case letters
[webmin.git] / software / software-lib.pl
1 # software-lib.pl
2 # A generalized system for package management on solaris, linux, etc..
3
4 BEGIN { push(@INC, ".."); };
5 use WebminCore;
6 &init_config();
7 $heiropen_file = "$module_config_directory/heiropen";
8
9 # Use the appropriate function set for whatever package management system
10 # we are using.
11 do "$config{package_system}-lib.pl";
12
13 if ($config{'update_system'} eq '*') {
14         # User specifically doesn't want any
15         $update_system = undef;
16         }
17 elsif ($config{'update_system'}) {
18         # User-specified system
19         $update_system = $config{'update_system'};
20         }
21 else {
22         # Guess which update system we are using
23         if (&has_command($config{'apt_mode'} ? "aptitude" : "apt-get")) {
24                 $update_system = "apt";
25                 }
26         elsif (&has_command("yum") && -r "/etc/yum.conf") {
27                 $update_system = "yum";
28                 }
29         elsif (&has_command("up2date") && &has_command("rhn_check")) {
30                 $update_system = "rhn";
31                 }
32         elsif (-x "/opt/csw/bin/pkg-get" || &has_command("pkg-get") ||
33                -x "/opt/csw/bin/pkgutil" || &has_command("pkgutil")) {
34                 $update_system = "csw";
35                 }
36         elsif (&has_command("urpmi")) {
37                 $update_system = "urpmi";
38                 }
39         elsif (&has_command("emerge")) {
40                 $update_system = "emerge";
41                 }
42         elsif (&has_command("cupdate")) {
43                 # not done yet!
44                 }
45         }
46 if ($update_system) {
47         do $update_system."-lib.pl";
48         $has_update_system = 1;
49         }
50
51 # uncompress_if_needed(file, disposable)
52 # If some file needs to be uncompressed or ungzipped, do it and return the
53 # new temp file path. Otherwise, return the original path.
54 sub uncompress_if_needed
55 {
56 return $_[0] if (&is_readonly_mode());  # don't even bother
57 open(PFILE, $_[0]);
58 read(PFILE, $two, 2);
59 close(PFILE);
60 if ($two eq "\037\235") {
61         if (!&has_command("uncompress")) {
62                 &unlink_file($_[0]) if ($_[1]);
63                 &error($text{'soft_euncompress'});
64                 }
65         local $temp = $_[0] =~ /\/([^\/]+)\.Z/i ? &tempname("$1")
66                                                 : &tempname();
67         local $out = `uncompress -c $_[0] 2>&1 >$temp`;
68         unlink($_[0]) if ($_[1]);
69         if ($?) {
70                 unlink($temp);
71                 &error(&text('soft_euncmsg', $out));
72                 }
73         return $temp;
74         }
75 elsif ($two eq "\037\213") {
76         if (!&has_command("gunzip")) {
77                 unlink($_[0]) if ($_[1]);
78                 &error($text{'soft_egzip'});
79                 }
80         local $temp = $_[0] =~ /\/([^\/]+)\.gz/i ? &tempname("$1")
81                                                  : &tempname();
82         local $out = `gunzip -c $_[0] 2>&1 >$temp`;
83         unlink($_[0]) if ($_[1]);
84         if ($?) {
85                 unlink($temp);
86                 &error(&text('soft_egzmsg', $out));
87                 }
88         return $temp;
89         }
90 return $_[0];
91 }
92
93 # show_package_info(package, version, [no-installed-message])
94 sub show_package_info
95 {
96 @pinfo = &package_info($_[0], $_[1]);
97 return () if (!@pinfo);
98
99 print &ui_subheading(&text('do_success', $_[0])) if (!$_[2]);
100 print &ui_table_start($text{'edit_details'}, "width=100%", 4,
101                       [ "width=20%", undef, "width=20%", undef ]);
102
103 # Package description
104 if ($pinfo[2]) {
105         $desc = &html_escape(&entities_to_ascii($pinfo[2]));
106         $desc =~ s/\r?\n/&nbsp;<br>/g;
107         print &ui_table_row($text{'edit_desc'}, "<tt>$desc</tt>", 3);
108         }
109
110 # Name
111 print &ui_table_row($text{'edit_pack'}, &html_escape($pinfo[0]));
112
113 # Class, if any
114 print &ui_table_row($text{'edit_class'},
115         $pinfo[1] ? &html_escape($pinfo[1]) : $text{'edit_none'});
116
117 # Version number
118 print &ui_table_row($text{'edit_ver'},
119         &html_escape($pinfo[4]));
120
121 # Vendor
122 print &ui_table_row($text{'edit_vend'},
123         &html_escape(&entities_to_ascii($pinfo[5])));
124
125 # Architecture
126 print &ui_table_row($text{'edit_arch'},
127         &html_escape($pinfo[3]));
128
129 # Install date
130 print &ui_table_row($text{'edit_inst'},
131         &html_escape($pinfo[6]));
132
133 print &ui_table_end();
134
135 return @pinfo;
136 }
137
138 @type_map = (   $text{'soft_reg'}, $text{'soft_dir'},  $text{'soft_spec'},
139                 $text{'soft_sym'}, $text{'soft_hard'}, $text{'soft_edit'} );
140
141 # get_heiropen()
142 # Returns an array of open categories
143 sub get_heiropen
144 {
145 open(HEIROPEN, $heiropen_file);
146 local @heiropen = <HEIROPEN>;
147 chop(@heiropen);
148 close(HEIROPEN);
149 return @heiropen;
150 }
151
152 # save_heiropen(&heir)
153 sub save_heiropen
154 {
155 &open_tempfile(HEIR, ">$heiropen_file");
156 foreach $h (@{$_[0]}) {
157         &print_tempfile(HEIR, $h,"\n");
158         }
159 &close_tempfile(HEIR);
160 }
161
162 # missing_install_link(package, description, return, return-desc)
163 # Returns HTML for installing some package that is missing, from the
164 # appropriate update system for this OS. Returns undef if automatic installation
165 # is not possible for some reason.
166 # Supported package names are :
167 #       apache
168 #       sendmail
169 #       postfix
170 #       squid
171 #       procmail
172 #       samba
173 #       mysql
174 #       postgresql
175 #       clamav
176 #       spamassassin
177 sub missing_install_link
178 {
179 local ($name, $desc, $return, $returndesc) = @_;
180 return undef if (!defined(&update_system_resolve));
181 return undef if (!&foreign_check($module_name));
182 local $pkg = &update_system_resolve($name);
183 return undef if (!$pkg);
184 local ($cpkg) = caller();
185 local $caller = eval '$'.$cpkg.'::module_name';
186 return &text('missing_link', $desc, "../$module_name/install_pack.cgi?source=3&update=".&urlize($pkg)."&return=".&urlize($return)."&returndesc=".&urlize($returndesc)."&caller=".&urlize($caller), $text{$update_system."_name"});
187 }
188
189 # update_system_button(field-name, label)
190 # Returns HTML for a button that opens the update system search window
191 sub update_system_button
192 {
193 local ($name, $label) = @_;
194 if (defined(&update_system_available) || defined(&update_system_search)) {
195         return "<input type=button onClick='window.ifield = form.$name; chooser = window.open(\"../$module_name/find.cgi\", \"chooser\", \"toolbar=no,menubar=no,scrollbars=yes,width=600,height=500\")' value=\"$label\">";
196         }
197 return undef;
198 }
199
200 # compare_versions(ver1, ver2)
201 # Returns -1 if ver1 is older than ver2, 1 if newer, 0 if same
202 sub compare_versions
203 {
204 local @sp1 = split(/[\.\-]/, $_[0]);
205 local @sp2 = split(/[\.\-]/, $_[1]);
206 for(my $i=0; $i<@sp1 || $i<@sp2; $i++) {
207         local $v1 = $sp1[$i];
208         local $v2 = $sp2[$i];
209         local $comp;
210         if ($v1 =~ /^\d+$/ && $v2 =~ /^\d+$/) {
211                 # Full numeric compare
212                 $comp = $v1 <=> $v2;
213                 }
214         elsif ($v1 =~ /^\d+\S*$/ && $v2 =~ /^\d+\S*$/) {
215                 # Numeric followed by string
216                 $v1 =~ /^(\d+)(\S*)$/;
217                 local ($v1n, $v1s) = ($1, $2);
218                 $v2 =~ /^(\d+)(\S*)$/;
219                 local ($v2n, $v2s) = ($1, $2);
220                 $comp = $v1n <=> $v2n;
221                 if (!$comp) {
222                         # X.rcN is always older than X
223                         if ($v1s =~ /^rc\d+$/i && $v2s =~ /^\d*$/) {
224                                 $comp = -1;
225                                 }
226                         elsif ($v1s =~ /^\d*$/ && $v2s =~ /^rc\d+$/i) {
227                                 $comp = 1;
228                                 }
229                         else {
230                                 $comp = $v1s cmp $v2s;
231                                 }
232                         }
233                 }
234         elsif ($v1 =~ /^\d+$/ && $v2 !~ /^\d+$/) {
235                 # Numeric compared to non-numeric - numeric is always higher
236                 $comp = 1;
237                 }
238         elsif ($v1 !~ /^\d+$/ && $v2 =~ /^\d+$/) {
239                 # Non-numeric compared to numeric - numeric is always higher
240                 $comp = -1;
241                 }
242         else {
243                 # String compare only
244                 $comp = $v1 cmp $v2;
245                 }
246         return $comp if ($comp);
247         }
248 return 0;
249 }
250
251 # check_package_system()
252 # Returns an error message if some command needed by the selected package
253 # management system is missing.
254 sub check_package_system
255 {
256 local $err;
257 if (defined(&validate_package_system)) {
258         $err = &validate_package_system();
259         }
260 if (defined(&list_package_system_commands)) {
261         foreach my $c (&list_package_system_commands()) {
262                 if (!&has_command($c)) {
263                         $err ||= &text('index_epackagecmd', &package_system(),
264                                        "<tt>$c</tt>");
265                         }
266                 }
267         }
268 return $err;
269 }
270
271 # check_update_system()
272 # Returns an error message if some command needed by the selected update
273 # system is missing.
274 sub check_update_system
275 {
276 return undef if (!$update_system);
277 local $err;
278 if (defined(&validate_update_system)) {
279         $err = &validate_update_system();
280         }
281 if (defined(&list_update_system_commands)) {
282         foreach my $c (&list_update_system_commands()) {
283                 if (!&has_command($c)) {
284                         $err ||= &text('index_eupdatecmd',
285                             $text{$update_system.'_name'} || uc($update_system),
286                             "<tt>$c</tt>");
287                         }
288                 }
289         }
290 return $err;
291 }
292
293 1;
294