#!/usr/bin/perl -wT # --------------------------- # CGI-Script for installing modules on a server where you don't # have root access and no shell access. You have to have # tools like make and tar, though. # Tina Mueller, Dec 31th 2004 # $Id: cgipan.cgi,v 1.2 2005/02/19 20:22:01 tinita Exp $ # --------------------------- use strict; use CGI; use CGI::Carp qw(fatalsToBrowser); use vars qw($VERSION); $VERSION = 0.06; # change to your needs (e.g. path to your compiler, ...) # $ENV{PATH} = '/usr/bin:/bin'; $ENV{PATH} = '/usr/bin:/bin'; # for debugging # BEGIN {open STDERR, ">>cgipan.log"} # --------------------------- # Change variables to your needs (you probably just need # to change $root) # own root dir on server (not / though) # or leave blank, then $ENV{DOCUMENT_ROOT} will be used, # which might not be a good thing my $root = '/homepages/bla/blubb/cgipan' || $ENV{DOCUMENT_ROOT} || ''; # create before starting; must have write permissions # for webserver my $build_dir = "$root/build"; my $lib = "$root/mylib"; # path to make my $make = '/usr/bin/make'; # path to tar my $tar = '/bin/tar'; # or /usr/bin/gtar ... # url to cgi-script. $ENV{SCRIPT_NAME} should be sufficient my $self = ''; # untaint. $ENV{SCRIPT_NAME} should be safe $ENV{SCRIPT_NAME} =~ m#(/.*)# and $self = $1; # or you can define all these variables in your own cgipan.conf # ($self, $make, $tar, $build_dir, $lib) if (-f "cgipan.conf") { open D, "cgipan.conf" or die $!; local $/; my $conf = ; close D; # untaint. suppose files from the file system are safe $conf =~ m/^(.*)$/s ? ($conf = $1) : ($conf = ''); eval $conf; } $ENV{PERL5LIB} = $lib; # --------------------------- #use Data::Dumper; my $cgi = CGI->new; my $w = $cgi->param('w') || $cgi->path_info || 'start'; $w =~ s#^/##; print head($w); #print "$_ = $ENV{$_}
" for sort keys %ENV; my %map = ( start => \&start, ut => \&unpack_tar, sd => \&show_dist, pmf => \&makefile, make => \&mmake, maket => \&make_test, makei => \&make_install, tm => \&test_module, ); my $dist = $cgi->param('dist') || ''; chdir $build_dir; if (-d $dist and $dist =~ m#^([^/]+)$#) { $dist = $1; } else { # no valid path $dist = ''; } my $sub = $map{$w}; $sub->(); print foot($w); sub test_module { my $module = $cgi->param('mod') || ''; # untaint if ($module =~ m/^([a-z_:]+)$/i) { $module = $1; } else { $module = '' } unless ($module) { print <Test if Module is installed:
EOM return; } my $version; my $path; my $inc_mod = $module; $inc_mod =~ s#::#/#g; $inc_mod .= ".pm"; eval qq#use lib qw($lib); use $module; \$version = \$${module}::VERSION; \$path = \$INC{"$inc_mod"};#; print <$@)
\$${module}::VERSION = $version
\$INC{$inc_mod} = $path
EOM } sub makefile { chdir $dist; my $perl = ($^X =~ m/(.*)/) ? $1 : 'perl'; my $cmd = qq#$perl -I$lib Makefile.PL PREFIX=$lib LIB=$lib 2>&1#; my $out = command($cmd); my $missing = ''; while ($out =~ m/Warning: prerequisite ([\w:_-]+) (\d+[\d.]*) not found/g) { my $mod = $1; my $version = $2; my $mod_uri = $mod; $mod_uri =~ s/:/%3A/g; $missing .= < I didn't find $mod (version $version). You may find it here: $mod
EOM } print $out; print $missing; print qq#if everything looks okay, you may now build the module: make#; } sub mmake { chdir $dist; my $cmd = qq#$make 2>&1#; my $out = command($cmd); print $out; print qq#if everything looks okay, you may now make the tests: test#; } sub make_test { chdir $dist; my $cmd = qq#$make test 2>&1#; my $out = command($cmd); print $out; print qq#if everything looks okay, you may now install: install#; } sub make_install { chdir $dist; my $cmd = qq#$make install 2>&1#; my $out = command($cmd); print $out; print qq#Ok, if everything looks fine, you are done! You can verify if the module is installed.#; } sub command { my $cmd = shift; my $output = qx#$cmd#; return qq#
$cmd:\n$output
#; } sub unpack_tar { my $tarf = $cgi->param('tar'); chdir $build_dir or die $!; if (-f $tarf and $tarf =~ m#^([^/]+)$#) { $tarf = $1; } else { # no valid path return; } print q#Trying to unpack $tarf...
#; my $cmd = qq#$tar -xvzf $tarf 2>&1#; my $output = command($cmd); print <start EOM } sub show_dist { my $dist = $cgi->param('dist'); chdir $build_dir; opendir my $dir, $dist or die "Could not open '$dist': $!"; my @files = grep { !m/^\.\.?$/ } readdir $dir; closedir $dir; print <perl -I$lib Makefile.PL PREFIX=$lib LIB=$lib
2. make
3. make test
4.make install

EOM print qq#

#;
	print qq#$_\n# for @files;
	print qq#
#; } sub start { my %list = list_build(); print qq#Directories:
    #; foreach my $file (@{$list{dir}}) { print qq#
  • $file
  • #; } print qq#
Files:
    #; foreach my $file (@{$list{file}}) { print $file =~ m/(tgz|tar\.gz)$/i ? qq#
  • $file unpack
  • # : "
  • $file (doesn't;look like a tar archive)
  • " } print qq#
#; } sub list_build { chdir $build_dir; opendir my $dir, "." or die "Could not open '$build_dir': $!"; my @files = grep { !m/^\.\.?$/ } readdir $dir; closedir $dir; my %hash; for my $f (sort @files) { next if -l $f; if (-d $f) { push @{$hash{dir}}, $f; } elsif (-f $f) { push @{$hash{file}}, $f; } } return %hash; } sub foot { $cgi->end_html; } sub head { # do some checking my $bd_ok = 'ok'; my $l_ok = 'ok'; my $errors = ""; my $user = getpwuid($<); if (!-d $build_dir) { $errors .= qq#Your build_dir '$build_dir' does not exist. Please create it, with the correct permissions.
#; $bd_ok = 'not there'; } elsif (!-w $build_dir) { $errors .= qq#Your build_dir '$build_dir exists, but is not writeable for me (I am $user, uid $<).#; $bd_ok = 'not writeable'; } if (!-d $lib) { $errors .= qq#Your lib '$lib' does not exist. Please create it, with the correct permissions.
#; $l_ok = 'not there'; } elsif (!-w $lib) { $errors .= qq#Your lib '$lib exists, but is not writeable for me (I am $user, uid $<).#; $l_ok = 'not writeable'; } my $err = $errors ? qq#Errors:
$errors
# : ""; my $st = $cgi->header; $st .= $cgi->start_html(-title => 'CGIPAN'); $st .= <Welcome to Cgipan Config:
perl version:$]
\$root:$root
\$build_dir:$build_dir ($bd_ok)
\$lib:$lib ($l_ok)
document root:$ENV{DOCUMENT_ROOT}
$err
Start | Test Module

EOM } =pod =head1 NAME cgipan =head1 README CGI-Script for installing modules on a server where you don't have root access and no shell access. You have to have tools like make and tar, though. =head1 DESCRIPTION To use cgipan, put it in your cgi-bin directory on your server and make it executable. Then it will run. It will most likely show you the message that /homepages/bla/blubb/cgipan/build|lib don't exist. These are the directories you need for cgipan. Create them where you need them and change the variables $build_dir and $lib. They have to be writeable by the webserver, so if they aren't, cgipan will show te appropriate error messge. Note: Don't make this script accessible for others!! (yes, two exclamation marks) While this script shouldn't be public anyway, at the moment it does no sanity checks at all. Ok, I warned you. Now have fun =) =head1 OSNAMES C =head1 PREREQUISITES CGI CGI::Carp tar or gnutar make =head1 LICENSE L may be distributed under the same terms as Perl itself. =head1 SCRIPT CATEGORIES CPAN CGI =head1 BUGS not enough HTML-entities-replacing etc. =head1 CHANGES 0.05 Added Taint mode =head1 AUTHOR Tina Mueller, Dec 31th 2004 (http://search.cpan.org/~tinita/) =cut