| 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__ |