blib/lib/WE_Frontend/Installer.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 24 | 162 | 14.8 |
branch | 0 | 64 | 0.0 |
condition | 0 | 21 | 0.0 |
subroutine | 8 | 21 | 38.1 |
pod | 6 | 9 | 66.6 |
total | 38 | 277 | 13.7 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | # -*- perl -*- | ||||||
2 | |||||||
3 | # | ||||||
4 | # $Id: Installer.pm,v 1.6 2004/06/10 13:18:02 eserte Exp $ | ||||||
5 | # Author: Slaven Rezic | ||||||
6 | # | ||||||
7 | # Copyright (C) 2001 Online Office Berlin. All rights reserved. | ||||||
8 | # Copyright (C) 2002 Slaven Rezic. | ||||||
9 | # This is free software; you can redistribute it and/or modify it under the | ||||||
10 | # terms of the GNU General Public License, see the file COPYING. | ||||||
11 | |||||||
12 | # | ||||||
13 | # Mail: slaven@rezic.de | ||||||
14 | # WWW: http://we-framework.sourceforge.net | ||||||
15 | # | ||||||
16 | |||||||
17 | package WE_Frontend::Installer; | ||||||
18 | |||||||
19 | 2 | 2 | 1651 | use strict; | |||
2 | 5 | ||||||
2 | 63 | ||||||
20 | 2 | 2 | 9 | use vars qw($VERSION $magicfile $magiccontent); | |||
2 | 3 | ||||||
2 | 167 | ||||||
21 | $VERSION = sprintf("%d.%02d", q$Revision: 1.6 $ =~ /(\d+)\.(\d+)/); | ||||||
22 | |||||||
23 | 2 | 2 | 12 | use base qw(Class::Accessor); | |||
2 | 3 | ||||||
2 | 980 | ||||||
24 | __PACKAGE__->mk_accessors(qw(Main)); | ||||||
25 | |||||||
26 | 2 | 2 | 23287 | use CGI qw(:standard); | |||
2 | 35293 | ||||||
2 | 16 | ||||||
27 | #use CGI::Carp qw(fatalsToBrowser); | ||||||
28 | 2 | 2 | 7863 | use File::Path; | |||
2 | 6 | ||||||
2 | 162 | ||||||
29 | 2 | 2 | 13 | use File::Basename; | |||
2 | 4 | ||||||
2 | 161 | ||||||
30 | 2 | 2 | 2129 | use File::stat; | |||
2 | 16837 | ||||||
2 | 43 | ||||||
31 | |||||||
32 | 2 | 2 | 776 | use WE::Util::Functions qw(_save_pwd); | |||
2 | 5 | ||||||
2 | 4539 | ||||||
33 | |||||||
34 | $magicfile = "magic"; | ||||||
35 | $magiccontent = "Elvis is alive"; | ||||||
36 | |||||||
37 | =head1 NAME | ||||||
38 | |||||||
39 | WE_Frontend::Installer - handle servicepack creation and handling | ||||||
40 | |||||||
41 | =head1 SYNOPSIS | ||||||
42 | |||||||
43 | use WE_Frontend::Installer; | ||||||
44 | WE_Frontend::Installer->create_servicepack($tarfile); | ||||||
45 | |||||||
46 | =head1 DESCRIPTION | ||||||
47 | |||||||
48 | This module handles servicepack creation and handling. | ||||||
49 | |||||||
50 | =head2 METHODS and FUNCTIONS | ||||||
51 | |||||||
52 | =over 4 | ||||||
53 | |||||||
54 | =item new | ||||||
55 | |||||||
56 | Return a new C |
||||||
57 | |||||||
58 | =cut | ||||||
59 | |||||||
60 | sub new { | ||||||
61 | 0 | 0 | 1 | bless {}, $_[0]; | |||
62 | } | ||||||
63 | |||||||
64 | =item objectify($self) | ||||||
65 | |||||||
66 | Return a new C |
||||||
67 | exist in C<$self>. Should be called as a static method. | ||||||
68 | |||||||
69 | =cut | ||||||
70 | |||||||
71 | sub objectify { | ||||||
72 | 0 | 0 | 1 | my $self = shift; | |||
73 | 0 | 0 | 0 | if (!$self || $self eq __PACKAGE__) { | |||
74 | 0 | require WE_Frontend::MainAny; | |||||
75 | 0 | $self = new WE_Frontend::Installer; | |||||
76 | 0 | my $main = WE_Frontend::MainAny->new; | |||||
77 | 0 | 0 | if (!$main) { | ||||
78 | 0 | die "Can't make \$main object"; | |||||
79 | } | ||||||
80 | |||||||
81 | 0 | $self->Main($main); | |||||
82 | } | ||||||
83 | 0 | $self; | |||||
84 | } | ||||||
85 | |||||||
86 | 0 | 0 | 0 | sub Config { shift->Main->Config(@_) } | |||
87 | |||||||
88 | =item main | ||||||
89 | |||||||
90 | Create a HTML page for uploading and installing a service pack. This | ||||||
91 | calls either upload_form or handle_tar. | ||||||
92 | |||||||
93 | =cut | ||||||
94 | |||||||
95 | sub main { | ||||||
96 | 0 | 0 | 1 | my $self = shift; | |||
97 | 0 | $self = objectify($self); | |||||
98 | |||||||
99 | 0 | print header, ""; | |||||
100 | |||||||
101 | 0 | eval { | |||||
102 | 0 | 0 | if (!param('tarfile')) { | ||||
103 | 0 | $self->upload_form; | |||||
104 | } else { | ||||||
105 | 0 | $self->handle_tar; | |||||
106 | } | ||||||
107 | }; | ||||||
108 | 0 | 0 | if ($@) { | ||||
109 | 0 | print "Folgende Fehler sind aufgetreten:", | |||||
110 | br,pre(escapeHTML($@)),p; | ||||||
111 | } | ||||||
112 | |||||||
113 | 0 | print " "; |
|||||
114 | 0 | print ' '; |
|||||
115 | 0 | print "zurück zum Site-Editor "; |
|||||
116 | } | ||||||
117 | |||||||
118 | =item upload_form | ||||||
119 | |||||||
120 | Create a HTML page for uploading a service pack. | ||||||
121 | |||||||
122 | =cut | ||||||
123 | |||||||
124 | sub upload_form { | ||||||
125 | 0 | 0 | 1 | my $self = shift; | |||
126 | 0 | my $scriptname = script_name(); | |||||
127 | 0 | print qq~ | |||||
128 | |||||||
133 | ~; |
||||||
138 | } | ||||||
139 | |||||||
140 | =item upload_form | ||||||
141 | |||||||
142 | Create a HTML page for installing a previously uploaded service pack. | ||||||
143 | |||||||
144 | =cut | ||||||
145 | |||||||
146 | sub handle_tar { | ||||||
147 | 0 | 0 | 0 | my $self = shift; | |||
148 | 0 | require Archive::Tar; | |||||
149 | 0 | my $uploadfile = param('tarfile'); | |||||
150 | 0 | my $tmpdir = tmpdir(); | |||||
151 | 0 | 0 | if (!defined $tmpdir) { | ||||
152 | 0 | die "Cannot find suitable temporary directory"; | |||||
153 | } | ||||||
154 | 0 | my $extrdir = "$tmpdir/webeditor_service"; | |||||
155 | 0 | 0 | if (-d $extrdir) { | ||||
156 | 0 | rmtree([$extrdir], 0, 1); | |||||
157 | } | ||||||
158 | 0 | mkdir $extrdir, 0775; | |||||
159 | 0 | 0 | if (!-d $extrdir) { | ||||
160 | 0 | die "Cannot create extraction directory $extrdir"; | |||||
161 | } | ||||||
162 | 0 | 0 | chdir $extrdir or die "Can't chdir to $extrdir: $!"; | ||||
163 | |||||||
164 | 0 | my $tarfilename = "$extrdir/service.tar.gz"; | |||||
165 | 0 | 0 | open(SP,">$tarfilename") or die "Can't writeopen $tarfilename: $!"; | ||||
166 | 0 | binmode SP; | |||||
167 | 0 | while (<$uploadfile>) { | |||||
168 | 0 | print SP $_; | |||||
169 | } | ||||||
170 | 0 | close SP; | |||||
171 | 0 | print "File-Upload abgeschlossen. "; |
|||||
172 | |||||||
173 | 0 | my $tar = Archive::Tar->new(); | |||||
174 | 0 | $tar->read($tarfilename); | |||||
175 | |||||||
176 | 0 | my $is_servicepack = 0; | |||||
177 | 0 | foreach my $m ($magicfile, "./$magicfile") { | |||||
178 | 0 | 0 | if ($tar->get_content($m) =~ /\Q$magiccontent/) { | ||||
179 | 0 | $is_servicepack++; | |||||
180 | 0 | last; | |||||
181 | } | ||||||
182 | } | ||||||
183 | |||||||
184 | 0 | 0 | if ($is_servicepack) { | ||||
185 | # XXX $tar->extract geht nicht?! | ||||||
186 | 0 | 0 | if (!$tar->extract_archive($tarfilename)) { | ||||
187 | 0 | print "Extrahieren von $tarfilename fehlgeschlagen: ". $tar->error(); | |||||
188 | 0 | goto CLEANUP; | |||||
189 | } else { | ||||||
190 | 0 | print "Dateien extrahiert. \n"; |
|||||
191 | }; | ||||||
192 | } else { | ||||||
193 | 0 | print "Das scheint kein gültiges Servicepack zu sein! "; |
|||||
194 | 0 | goto CLEANUP; | |||||
195 | } | ||||||
196 | |||||||
197 | 0 | unlink "$extrdir/$magicfile"; | |||||
198 | 0 | $self->install($extrdir); | |||||
199 | |||||||
200 | 0 | CLEANUP: | |||||
201 | unlink $tarfilename; | ||||||
202 | } | ||||||
203 | |||||||
204 | =item install($dir) | ||||||
205 | |||||||
206 | Install the contents of directory C<$dir> to the rootdir of the | ||||||
207 | system. | ||||||
208 | |||||||
209 | =cut | ||||||
210 | |||||||
211 | sub install { | ||||||
212 | 0 | 0 | 1 | my($self, $dir) = @_; | |||
213 | |||||||
214 | 0 | 0 | if (-e "$dir/install.pl") { | ||||
215 | 0 | 0 | if (-x "$dir/install.pl") { | ||||
216 | 0 | system("$dir/install.pl"); | |||||
217 | 0 | 0 | if ($?/256!=0) { | ||||
218 | 0 | print "Fehler beim Ausführen von install.pl! \n"; |
|||||
219 | } | ||||||
220 | } else { | ||||||
221 | 0 | print "install.pl ist nicht ausführbar. \n"; |
|||||
222 | } | ||||||
223 | } else { | ||||||
224 | 0 | print "Kopieren:\n "; |
|||||
225 | 0 | my(@f) = glob("$dir/*"); | |||||
226 | 0 | @f = grep { $_ !~ /\.tar\.gz$/ } @f; # tar.gz-Dateien ausschließen | |||||
0 | |||||||
227 | 0 | my @cmd = ('cp', '-Rf', @f, $self->Config->paths->rootdir); | |||||
228 | 0 | print join(" ",@cmd), " "; |
|||||
229 | 0 | system(@cmd); | |||||
230 | } | ||||||
231 | |||||||
232 | 0 | CLEANUP: 1; | |||||
233 | # XXX missing cleanup of $dir | ||||||
234 | } | ||||||
235 | |||||||
236 | sub tmpdir { | ||||||
237 | 0 | 0 | 0 | foreach my $d ("/tmp", "/var/tmp", "/usr/tmp", "/temp", "C:/temp", "C:/windows/temp", "D:/temp") { | |||
238 | 0 | 0 | next if !defined $d; | ||||
239 | 0 | 0 | 0 | next if !-d $d || !-w $d; | |||
240 | 0 | return $d; | |||||
241 | } | ||||||
242 | 0 | undef; | |||||
243 | } | ||||||
244 | |||||||
245 | =item WE_Frontend::Installer->create_servicepack($destfile, %args) | ||||||
246 | |||||||
247 | =item $self->create_servicepack($destfile, %args) | ||||||
248 | |||||||
249 | Create a service pack file. Ignores all WEsiteinfo*.pm files. | ||||||
250 | |||||||
251 | The %args hash may contain the following key-value pairs: | ||||||
252 | |||||||
253 | =over 4 | ||||||
254 | |||||||
255 | =item -wesiteinfo | ||||||
256 | |||||||
257 | If -wesiteinfo is specified, then use this file as the WEsiteinfo.pm | ||||||
258 | file for the target site. Most times there is a WEsiteinfo.pm file for | ||||||
259 | local development and a WEsiteinfo_customer.pm file for the customer | ||||||
260 | site. | ||||||
261 | |||||||
262 | =item -since date | ||||||
263 | |||||||
264 | Only include files newer than C |
||||||
265 | parsing the date string. | ||||||
266 | |||||||
267 | =item -v | ||||||
268 | |||||||
269 | Set to 1 to generate verbose messages. | ||||||
270 | |||||||
271 | =back | ||||||
272 | |||||||
273 | =cut | ||||||
274 | |||||||
275 | sub create_servicepack { | ||||||
276 | 0 | 0 | 1 | my($self, $destfile, %args) = @_; | |||
277 | |||||||
278 | 0 | $self = objectify($self); | |||||
279 | |||||||
280 | 0 | 0 | if (!defined $destfile) { | ||||
281 | 0 | die "Destfile not given"; | |||||
282 | } | ||||||
283 | |||||||
284 | 0 | my $since; | |||||
285 | 0 | 0 | if (defined $args{-since}) { | ||||
286 | 0 | require Date::Parse; | |||||
287 | 0 | $since = Date::Parse::str2time($args{-since}); | |||||
288 | 0 | 0 | if (!defined $since) { | ||||
289 | 0 | die "Could not parse the date $args{-since}"; | |||||
290 | } | ||||||
291 | } | ||||||
292 | 0 | my $v = $args{-verbose}; | |||||
293 | |||||||
294 | 0 | require Archive::Tar; | |||||
295 | 0 | require File::Find; | |||||
296 | |||||||
297 | 0 | require 5.006; # this perl includes a version of File::Find which can | |||||
298 | # follow symlinks | ||||||
299 | |||||||
300 | 0 | my $tar = new Archive::Tar; | |||||
301 | |||||||
302 | my $is_new = sub { | ||||||
303 | 0 | 0 | my $file = shift; | ||||
304 | 0 | 0 | return (!defined $since || stat($file)->mtime > $since); | ||||
305 | 0 | }; | |||||
306 | |||||||
307 | 0 | my @files; | |||||
308 | my $wanted = sub { | ||||||
309 | 0 | 0 | 0 | 0 | if (-d $_ && (/^(RCS|CVS|\.svn|headlines|photos)$/ || | ||
0 | |||||||
310 | $File::Find::name =~ m;(we_data/content|html/.+);)) { | ||||||
311 | 0 | $File::Find::prune = 1; | |||||
312 | 0 | return; | |||||
313 | } | ||||||
314 | 0 | 0 | 0 | if (-f $_ && (/^(\.cvsignore|WEsiteinfo.*\.pm|.*~|\.\#.*)$/ || | |||
0 | |||||||
315 | $File::Find::name =~ m;( we_data/.*\.db$ | | ||||||
316 | we_data/.*\.lock$ | ||||||
317 | );x) | ||||||
318 | ) { | ||||||
319 | 0 | return; | |||||
320 | } | ||||||
321 | 0 | 0 | if (-f $_) { | ||||
322 | 0 | 0 | return if !$is_new->($_); | ||||
323 | 0 | push @files, $File::Find::name; | |||||
324 | } | ||||||
325 | 0 | }; | |||||
326 | |||||||
327 | 0 | my $rootdir = $self->Config->paths->rootdir; | |||||
328 | 0 | my $cgidir = $self->Config->paths->cgidir; | |||||
329 | _save_pwd { | ||||||
330 | 0 | 0 | 0 | chdir $rootdir or die "Can't chdir to $rootdir: $!"; | |||
331 | |||||||
332 | 0 | File::Find::find({wanted => $wanted, follow => 1 }, "."); | |||||
333 | |||||||
334 | # Hmmm... add_files does not work?! | ||||||
335 | # But nevertheless I need resolved symbolic links, so this is the | ||||||
336 | # only possibility. | ||||||
337 | 0 | foreach my $f (@files) { | |||||
338 | 0 | 0 | warn "Add $f ...\n" if $v; | ||||
339 | 0 | _tar_add_file($tar, $f); | |||||
340 | } | ||||||
341 | 0 | }; | |||||
342 | |||||||
343 | 0 | 0 | if ($args{-wesiteinfo}) { | ||||
344 | 0 | my $as = $cgidir; | |||||
345 | 0 | $as =~ s|^$rootdir/*||; | |||||
346 | 0 | $as .= "/WEsiteinfo.pm"; | |||||
347 | 0 | 0 | if ($is_new->($args{-wesiteinfo})) { | ||||
348 | 0 | 0 | warn "Add $as ...\n" if $v; | ||||
349 | 0 | _tar_add_file($tar, $args{-wesiteinfo}, $as); | |||||
350 | } | ||||||
351 | } | ||||||
352 | |||||||
353 | 0 | $tar->add_data($magicfile, $magiccontent); | |||||
354 | |||||||
355 | 0 | 0 | $tar->write($destfile, 9) | ||||
356 | or die "Can't write to $destfile: " . $tar->error; | ||||||
357 | |||||||
358 | } | ||||||
359 | |||||||
360 | sub _tar_add_file { | ||||||
361 | 0 | 0 | my($tar, $f, $as) = @_; | ||||
362 | 0 | 0 | open(F, $f) or die "Can't open file $f: $!"; | ||||
363 | 0 | local $/ = undef; | |||||
364 | 0 | my $buf = |
|||||
365 | 0 | close F; | |||||
366 | 0 | 0 | $as = $f if !defined $as; | ||||
367 | 0 | my $s = stat $f; | |||||
368 | 0 | my %stat = (mode => $s->mode, | |||||
369 | mtime => $s->mtime); | ||||||
370 | 0 | $tar->add_data($as, $buf, \%stat); | |||||
371 | } | ||||||
372 | |||||||
373 | 1; | ||||||
374 | |||||||
375 | __END__ |