# THEME Installation # This step can use the command line arguments: # "-theme " specifies the theme to install, the script will not prompt for a theme # "-quick" the script will not prompt the user for the paths or URLs for the web server # "-nopaths, -nourls" the script will not prompt for any paths, or urls, respectively # sub step_theme_init { return 500_000; # theme installation is generally always done last } sub step_theme { my (@list, $DONE); my ($ftp, $ftpvalid, $pathvalid); my ($t, $s, @files, @deps, $cfile, $depsize, $totalsize, $total, $sum, $destroot, $dest); my $theme = $args->{theme}; # might be undef/false my $canceled = 0; my $c = copyhash($conf); # get a copy of the config my $in = $c->{install}; my $orig = $c->{theme}{source}; $wiz->wraptext($lang->{theme_start}); # If a theme wasn't specified on the command line, we need to ask the user for one to install if (!$theme) { $wiz->wraptext($lang->{theme_desc}); $theme = $orig; # default to current theme selection in config while (1) { @list = validdirs('themes'); # rebuild it each time ... unless (scalar @list) { # no themes? bail out, dude! $canceled = 1; last; } $wiz->{data}{list} = join(", ", sort @list); $wiz->wraptext($lang->{theme_list}); $theme = lc $wiz->promptfor("Choose your theme [$theme]: ", $theme); # lowercase! last if grep { /^\Q$theme\E$/ } @list or $theme eq '' or !scalar @list; # exit loop if we have a valid option $wiz->wraptext($lang->{theme_notinlist}); if ($args->{useconfonly} or $wiz->prompt_yesno(1,$lang->{yn_tryagain}) == 0) { $canceled = 1; $theme = ''; last; } $theme = $orig; # reset it to original } } else { @list = validdirs('themes'); $theme = (grep { /^\Q$theme\E$/ } @list)[0] || ''; # is the theme valid? } # If we canceled, exit now. unless ($theme and !$canceled) { $wiz->wraptext($lang->{theme_notheme}); return 0; } $c->{theme}{source} = $theme; # theme is valid, set the config value # load the theme.cfg for the selected theme, error if it can't be loaded. $cfile = catfile('themes', $theme, 'theme.cfg'); if (-e $cfile) { # load theme.cfg if its present $t = loadconfig(filename => $cfile, warning => 1); } if (!$t or !-e $cfile) { # no theme.cfg, theme is INVALID! $wiz->wraptext($lang->{theme_invalid}); return 0; # RETURN! } # gather theme related files to and show aggregates of totals, etc. @files = sort pathsort grep { !/^themes[\\\/]$theme[\\\/]dep[\\\/]/ } processpath(catfile('themes',$theme)); # get all files in the theme directory (no subdirs) @deps = sort pathsort processpath(catfile('themes',$theme,'dep')); # get dependancy files seperately $totalsize = $depsize = 0; $totalsize += -s $_ || 0 foreach @files; $depsize += -s $_ || 0 foreach @deps; $totalpages = grep { ref $t->{$_} eq 'HASH' } keys %$t; # any key thats a hash is a 'page' in the theme $wiz->{data} = { # gather basic info from theme %{$wiz->{data}}, theme => $theme, name => $lang->{unknown}, author => $lang->{unknown}, version => $lang->{unknown}, email => $lang->{unknown}, notes => "", %$t, totalfiles => scalar @files, totalsize => abbrnum($totalsize,2), totaldepfiles => scalar @deps, totaldepsize => abbrnum($depsize,2), }; print "\n", hline('- '), "\n"; $wiz->wraptext($lang->{theme_info}); if ($t->{notes}) { my $notes = $t->{notes}; $notes =~ s/\r?\n/ /g; # convert newlines into a single space $notes =~ s/\t/"\\t"/ge; # convert tab into a literal \t $wiz->wraptext($lang->{theme_notes}); $wiz->wraptext($notes, {trimtail => 1}); } print "\n", hline('- '), "\n"; $args->{theme} = $theme if $args->{useconfonly}; # if the theme was specified on the command line we FORCE the installation of it and do not ask the user for confirmation $canceled = !$args->{theme} ? !$wiz->prompt_yesno(1,$lang->{theme_yninstall}) : 0; if ($canceled) { $wiz->wraptext($lang->{theme_cancel}); return 0; # RETURN! } my $dirsep = (index($conf->{theme}{statsroot}, '/') != -1) ? '/' : '\\'; # --- NOW we finally handle the theme files ... Upload or copy them to the proper directories $in->{themedir} = $conf->{theme}{statsroot} . "themes" . $dirsep; ### unless $in->{themedir}; $in->{compiledir} = $conf->{theme}{statsroot} . "themes_compiled" . $dirsep; $in->{webhost} = 'localhost' unless $in->{webhost}; $in->{ftpuser} = ($OS eq 'MSWin32' ? $c->{ $c->{savetype} }{username} || 'unknown' : getpwuid($>) || $c->{ $c->{savetype} }{username}) unless $in->{ftpuser}; $in->{ftppass} = '' unless $in->{ftppass}; $in->{ftpport} = 21 unless $in->{ftpport}; $in->{ftppasv} = 0 unless $in->{ftppasv}; $DONE = 0; while (!$DONE) { my $proceed = 1; $wiz->get_ftp_info($in) if !defined $wiz->{ftp} and !$args->{useconfonly}; %{$conf->{install}} = ( %{$conf->{install}}, %$in ); $conf->{install}{themedir} = catfile($conf->{theme}{statsroot}, 'themes', '') unless $conf->{install}{themedir}; $conf->{install}{compiledir} = catfile($conf->{theme}{statsroot}, 'themes_compiled', '') unless $conf->{install}{compiledir}; if (lc $in->{webhost} eq 'localhost' or $in->{webhost} eq '127.0.0.1') { # WEBSITE IS LOCAL # $conf->{install}{themedir} = catfile(getcwd(), 'themes', ''); # $conf->{install}{compiledir} = catfile(getcwd(), 'themes_compiled', ''); $conf->{theme}{source} = $theme; # $wiz->wraptext($lang->{init_localtheme}, undef, { 'themedir' => $conf->{install}{themedir} }); # make sure the themes and themes_compiled directory exists. eval { mkpath($conf->{install}{themedir}) if !-d $conf->{install}{themedir} }; eval { mkpath($conf->{install}{compiledir}) if !-d $conf->{install}{compiledir} }; chmod(0777, $conf->{install}{compiledir}); # security issues! # copy theme files over to the statsroot $total = $totalsize; $sum = 0; $destroot = $c->{theme}{statsroot}; $wiz->{data}{statsroot} = $destroot; $wiz->wraptext($lang->{theme_files}); select(undef,undef,undef,1.0); # small delay foreach my $file (@files) { $sum += -s $file; $dest = catfile($destroot, $file); my $path = catfile( $destroot, (splitpath($file))[1] ); if ($path and !-d $path) { eval { mkpath($path) }; chomp($wiz->{data}{error} = $@); } $wiz->{data}{file} = $file; $wiz->{data}{filesize} = sprintf("%10s", abbrnum(-s $file,2)); $wiz->{data}{pct} = sprintf("%6s", calcpct($sum, $total)); $wiz->wraptext($lang->{copyfile}, {trimtail => 1}); my $ok = copy($file, $dest); chomp($wiz->{data}{error} = $!) if !$ok; $wiz->wraptext( $ok ? $lang->{ok} : $lang->{copyfileerr} ); } # copy dependant files over if (@deps) { $total = $depsize; $sum = 0; $destroot = $c->{theme}{statsroot}; $destroot =~ s|\\|/|g; $destroot .= '/' unless $destroot =~ m|/$|; $wiz->{data}{statsroot} = $destroot; $wiz->wraptext($lang->{theme_deps}); select(undef,undef,undef,1.0); # small delay foreach my $file (@deps) { my ($vol, $path, $filename) = splitpath($file); my (@parts, $echofile); $file =~ s|\\|/|g; # convert all \ to / $path =~ s|\\|/|g; @parts = split(/\/+/, $path); # split parts by '/' 1 while @parts and shift(@parts) ne 'dep'; # remove "themes/themename/dep" $echofile = join('/', @parts, $filename); $path = $destroot . join('/', @parts); $dest = join('/', $path, $filename); $dest =~ s|/+|/|g; $wiz->{data}{dest} = $dest; $sum += -s $file; if ($path and !-d $path) { eval { mkpath($path) }; chomp($wiz->{data}{error} = $@); } # copy the file .... $wiz->{data}{file} = $echofile; $wiz->{data}{filesize} = sprintf("%10s", abbrnum(-s $file,2)); $wiz->{data}{pct} = sprintf("%6s", calcpct($sum, $total)); $wiz->wraptext($lang->{copyfile}, {trimtail => 1}); my $ok = copy($file, $dest); chomp($wiz->{data}{error} = $!) if !$ok; $wiz->wraptext( $ok ? $lang->{ok} : $lang->{copyfileerr} ); } $wiz->wraptext($lang->{copydone}); } else { $wiz->wraptext($lang->{theme_nodeps}); } $DONE = 1; } else { # WEBSITE IS REMOTE my $havethemedir = 0; # make sure we have a valid theme directory to upload the theme to $wiz->get_dir_info($in); $conf->{install}{themedir} = $in->{themedir}; $conf->{install}{compiledir} = $in->{compiledir}; while (!$wiz->ftpconnect) { die "Error logging into FTP. Prompting disabled (-useconfonly)." if $args->{useconfonly}; last unless $wiz->prompt_yesno(1,$lang->{yn_ftpconf}); $wiz->get_ftp_info($in,undef,1); } $ftp = $wiz->{ftp} or last; $wiz->ftpcwdroot; # $proceed = $wiz->prompt_yesno(0, $lang->{yn_uploadfiles}); # verify the 'themes' directory exists within the themedir, if not, create it if possible if ($proceed) { my $isdir = 0; while (!$isdir) { # attempt to cd into the themedir, or create it if we can if (!$ftp->cwd($in->{themedir})) { $ftp->mkdir($in->{themedir}, 1); $wiz->ftpcwdroot; } # isdir logic: If the "installdir/themes" path exists already or if we create it, and then cwd into it # $isdir = ($ftp->cwd($in->{themedir}) and ($ftp->cwd('themes') or ($ftp->mkdir('themes') and $ftp->cwd('themes')))); $isdir = $ftp->cwd($in->{themedir}); $wiz->{data}{path} = $wiz->unixpath($ftp->pwd, $theme); if (!$isdir) { $wiz->wraptext($lang->{theme_baddir}); my $go = (!$args->{useconfonly} and $wiz->prompt_yesno(1,$lang->{yn_tryagaindir})) ? $wiz->get_installdir($in) : last; $havethemedir = 1; # if we get here, then we know the user had to enter a dir installation dir } else { $wiz->wraptext($lang->{theme_gooddir}); } } $proceed = $isdir; } # create / directory or confirm we want to overwrite an existing directory if it exists already if ($proceed) { my $isdir = 0; while (!$isdir) { my $themepath = $wiz->{data}{path} = $wiz->unixpath($in->{themedir}, $theme); $wiz->ftpcwdroot; $isdir = $ftp->cwd($themepath); if ($isdir) { $wiz->wraptext($lang->{theme_texists}) unless $args->{useconfonly}; $proceed = !$args->{useconfonly} ? $wiz->prompt_yesno(0, $lang->{yn_ftpoverwrite}) : 1; } else { if (!($proceed = $ftp->mkdir($themepath,1))) { chomp($wiz->{data}{error} = $ftp->message); $wiz->wraptext($lang->{theme_nothemedir}); # my $go = $wiz->prompt_yesno(1,$lang->{yn_tryagaindir}) ? $wiz->get_installdir($in) : last; } last; } } } # first, try to create the theme_compiled directory $wiz->ftpcwdroot; $ftp->mkdir($wiz->unixpath($in->{compiledir}),1); $ftp->site('chmod', 777, $wiz->unixpath($in->{compiledir})); # make it world-writable (security issues!) # print "CHMOD: ", $ftp->message,"\n"; # now we finally upload the theme if we still want to $proceed if ($proceed) { $wiz->wraptext($lang->{theme_uploadstart}); select(undef,undef,undef,1) unless $args->{useconfonly}; # small delay $wiz->ftpcwdroot; # $ftp->cwd($wiz->unixpath($in->{themedir})); # start in the themedir so files are uploaded to the correct place $wiz->ftpuploadfiles(\@files, $in->{themedir}); # upload the files $wiz->wraptext($lang->{theme_uploaddone}); } $conf->{theme}{source} = $theme; if (@deps) { my %created = (); # keep track of what directories were created already my $total = $depsize; my $sum = 0; my $destroot = $c->{theme}{statsroot}; $destroot =~ s|\\|/|g; $destroot .= '/' unless $destroot =~ m|/$|; $wiz->{data}{statsroot} = $destroot; $wiz->wraptext($lang->{theme_deps}); select(undef,undef,undef,1.0); # small delay $ftp->binary; foreach my $file (@deps) { my ($vol, $path, $filename) = splitpath($file); my (@parts, $echofile); $file =~ s|\\|/|g; # convert all \ to / $path =~ s|\\|/|g; @parts = split(/\/+/, $path); # split parts by '/' 1 while @parts and shift(@parts) ne 'dep'; # remove "themes/themename/dep" $echofile = join('/', @parts, $filename); $path = $destroot . join('/', @parts); $dest = join('/', $path, $filename); $dest =~ s|/+|/|g; $wiz->{data}{dest} = $dest; $sum += -s $file; if ($path and !$created{$path}) { $created{$path} = 1; $ftp->mkdir($path, 1); chomp($wiz->{data}{error} = $ftp->message); } # upload the file .... $wiz->{data}{file} = $echofile; $wiz->{data}{filesize} = sprintf("%10s", abbrnum(-s $file,2)); $wiz->{data}{pct} = sprintf("%6s", calcpct($sum, $total)); $wiz->wraptext($lang->{ulfile}, {trimtail => 1}); my $ok = $ftp->put($file, $dest); chomp($wiz->{data}{error} = $ftp->message) if !$ok; $wiz->wraptext( $ok ? $lang->{ok} : $lang->{ulfileerr} ); } $wiz->wraptext($lang->{uploaddone}); } else { $wiz->wraptext($lang->{theme_nodeps}); } $DONE = 1; } # if website is remote } # while !$DONE confupdate($conf, 0, 1); } 1;