3 # Download and install usermin module or theme on multiple hosts
5 require './cluster-usermin-lib.pl';
6 if ($ENV{REQUEST_METHOD} eq "POST") { &ReadParseMime(); }
7 else { &ReadParse(); $no_upload = 1; }
8 &error_setup($text{'install_err'});
10 if ($in{source} == 2) {
11 &ui_print_unbuffered_header(undef, $text{'install_title'}, "");
14 &ui_print_header(undef, $text{'install_title'}, "");
17 if ($in{source} == 0) {
18 # installing from local file (or maybe directory)
20 { &download_error($text{'install_elocal'}); }
22 { &download_error(&text('install_elocal2', $in{'local'})); }
23 $source = $in{'local'};
24 $pfile = $in{'local'};
27 elsif ($in{source} == 1) {
28 # installing from upload .. store file in temp location
30 &download_error($text{'install_eupload'});
32 $in{'upload_filename'} =~ /([^\/\\]+$)/;
33 $pfile = &tempname("$1");
34 &open_tempfile(PFILE, "> $pfile");
35 &print_tempfile(PFILE, $in{'upload'});
36 &close_tempfile(PFILE);
37 $source = $in{'upload_filename'};
40 elsif ($in{source} == 2) {
41 # installing from URL.. store downloaded file in temp location
42 $in{'url'} =~ /\/([^\/]+)\/*$/;
43 $pfile = &tempname("$1");
44 $progress_callback_url = $in{'url'};
45 if ($in{'url'} =~ /^(http|https):\/\/([^\/]+)(\/.*)$/) {
48 $host = $2; $page = $3; $port = $ssl ? 443 : 80;
49 if ($host =~ /^(.*):(\d+)$/) { $host = $1; $port = $2; }
50 &http_download($host, $port, $page, $pfile, \$error,
51 \&progress_callback, $ssl);
53 elsif ($in{'url'} =~ /^ftp:\/\/([^\/]+)(:21)?(\/.*)$/) {
54 $host = $1; $file = $3;
55 &ftp_download($host, $file, $pfile, \$error,
58 else { &download_error(&text('install_eurl', $in{'url'})); }
59 &download_error($error) if ($error);
63 $grant = $in{'grant'} ? undef : [ split(/\s+/, $in{'grantto'}) ];
69 if ($two eq "\037\235") {
71 &has_command("uncompress") ||
72 &download_error(&text('install_ecomp', "<tt>uncompress</tt>"));
73 $cmd = "uncompress -c '$pfile' | tar tf -";
75 elsif ($two eq "\037\213") {
77 &has_command("gunzip") ||
78 &download_error(&text('install_egzip', "<tt>gunzip</tt>"));
79 $cmd = "gunzip -c '$pfile' | tar tf -";
83 $cmd = "tar tf '$pfile'";
86 $? && &download_error(&text('install_ecmd', "<tt>$tar</tt>"));
87 foreach $f (split(/\n/, $tar)) {
88 if ($f =~ /^\.\/([^\/]+)\/(.*)$/ || $f =~ /^([^\/]+)\/(.*)$/) {
93 foreach $m (keys %mods) {
94 $hasfile{$m,"module.info"} || $hasfile{$m,"theme.info"} ||
95 &download_error(&text('install_einfo', "<tt>$m</tt>"));
98 &download_error($text{'install_enone'});
101 # Get the version numbers
102 $tempdir = &transname();
103 mkdir($tempdir, 0755);
104 foreach $m (keys %mods) {
107 system("cd $tempdir ; $xcmd $m/module.info ./$m/module.info >/dev/null 2>&1");
109 &read_file("$tempdir/$m/module.info", \%minfo);
110 $modver{$m} = $minfo{'version'};
113 # Setup error handler for down hosts
116 $inst_error_msg = join("", @_);
118 &remote_error_setup(\&inst_error);
120 # Work out which hosts have the module, and which to install on
121 @hosts = &list_usermin_hosts();
122 @servers = &list_servers();
123 foreach $h (@hosts) {
125 foreach $m (keys %mods) {
126 local ($alr) = grep { $_->{'dir'} eq $m }
127 (@{$h->{'modules'}}, @{$h->{'themes'}});
128 $gotall = 0 if (!$alr ||
129 (defined($modver{$m}) &&
130 $modver{$m} > $alr->{'version'}));
132 push(@gothosts, $h) if ($gotall);
134 @hosts = &create_on_parse("install_header", \@gothosts,
135 join(" ", keys %mods));
139 foreach $h (@hosts) {
140 local ($s) = grep { $_->{'id'} == $h->{'id'} } @servers;
142 local ($rh = "READ$p", $wh = "WRITE$p");
144 select($wh); $| = 1; select(STDOUT);
146 # Do the install in a subprocess
149 &remote_foreign_require($s->{'host'}, "usermin",
151 if ($inst_error_msg) {
152 # Failed to contact host ..
153 print $wh &serialise_variable($inst_error_msg);
156 &remote_foreign_require($s->{'host'}, "acl", "acl-lib.pl");
158 local $host_need_unlink = 1;
160 # This host, so we already have the file
162 $host_need_unlink = 0;
164 elsif ($in{'source'} == 0) {
165 # Is the file the same on remote? (like if we have NFS)
166 local @st = stat($pfile);
167 local $rst = &remote_eval($s->{'host'}, "usermin",
168 "[ stat('$pfile') ]");
170 if (@st && @rst && $st[7] == $rst[7] &&
172 # File is the same! No need to download
174 $host_need_unlink = 0;
177 # Need to copy the file across :(
178 $rfile = &remote_write(
179 $s->{'host'}, $pfile);
182 elsif ($in{'source'} == 2 && $in{'down'}) {
183 # Ask the remote server to download the file
184 $rfile = &remote_foreign_call($s->{'host'}, "usermin",
186 if ($in{'url'} =~ /^ftp/) {
187 &remote_foreign_call($s->{'host'}, "usermin",
188 "ftp_download", $host, $file,
192 &remote_foreign_call($s->{'host'}, "usermin",
193 "http_download", $host, $port,
194 $page, $rfile, undef, undef, $ssl);
198 # Need to copy the file across :(
199 $rfile = &remote_write($s->{'host'}, $pfile);
203 local $rv = &remote_foreign_call($s->{'host'},
204 "usermin", "install_usermin_module", $rfile,
205 $host_need_unlink, $in{'nodeps'});
207 # It worked .. get all the module infos
209 foreach $m (@{$rv->[1]}) {
211 local %info = &remote_foreign_call(
212 $s->{'host'}, "usermin",
213 "get_usermin_module_info", $m);
215 # Must have been a theme
216 %info = &remote_foreign_call(
217 $s->{'host'}, "usermin",
218 "get_usermin_theme_info", $m);
223 print $wh &serialise_variable(\@mods);
225 # Re-request all modules and themes from the server
226 $h->{'modules'} = [ grep { !$_->{'clone'} }
227 &remote_foreign_call($s->{'host'},
228 "usermin", "list_modules") ];
229 $h->{'themes'} = [ &remote_foreign_call($s->{'host'},
230 "usermin", "list_themes") ];
231 &save_usermin_host($h);
234 print $wh &serialise_variable($rv);
243 # Get back all the results
245 foreach $h (@hosts) {
246 local $rh = "READ$p";
249 local $rv = &unserialise_variable($line);
251 local ($s) = grep { $_->{'id'} == $h->{'id'} } @servers;
252 local $d = &server_name($s);
255 print &text('do_failed', $d, "Unknown reason"),"<br>\n";
258 print &text('do_failed', $d, $rv),"<br>\n";
261 # List the modules installed, and add to lists
264 print &text('do_success_theme', $d, "<b>$m->{'desc'}</b>"), "<br>\n";
267 print &text('do_success_mod', $d, "<b>$m->{'desc'}</b>"), "<br>\n";
273 unlink($pfile) if ($need_unlink);
274 print "<p><b>$text{'do_done'}</b><p>\n";
277 &ui_print_footer("", $text{'index_return'});
281 unlink($pfile) if ($need_unlink);
282 print "<br><b>$whatfailed : $_[0]</b> <p>\n";
283 &ui_print_footer("", $text{'index_return'});