#!/usr/bin/perl -w use strict; $|++; # # FILE: sptinstall / cwisinstall # # Part of the Scout Portal Toolkit # Copyright 2002-2003 Internet Scout Project # http://scout.wisc.edu # use Getopt::Std; use File::Basename; # software name and version (inserted here by SPT--BuildRelease) my($AppLongName) = "NSDL CWIS Software"; my($AppShortName) = "CWIS"; my($AppVersion) = "1.0.0"; # default installation directory and web address my($DefaultDstDir) = "/home/httpd/html/".$AppShortName; my($DefaultWebAddressDir) = "/".$AppShortName."/"; # global values (easier than passing by reference everywhere) my($DistArchiveName); my($DstDir) = ""; my($WebAddress) = ""; my($UpgradeRequested) = 0; my($SaveOldInstall) = 0; my($OldAppVersion) = ""; my($OldAppBaseVersion) = ""; my($OldAppShortName) = ""; my($NoCronTab) = 0; # SPT <--> CWIS version map # (this must match the similar maps in: # SPT--InstallComplete.php, # include/SPT--Common.php, # SPT--BuildRelease, and # sptinstall) my(%CwisVersionMap) = ( "1.1.4" => "0.9.0", "1.1.5" => "0.9.1", "1.1.6" => "0.9.2", "1.1.7" => "0.9.3", "1.1.8" => "0.9.4", "1.2.0" => "1.0.0" ); sub GetInstallInfo { # give instructions on usage print("\n" ."This program will ask you for information needed to install the\n" ."${AppLongName}. Default settings, when available, will appear after the\n" ."questions in [square brackets]. If you want to use the default setting you\n" ."can just hit Enter.\n" ."\n"); # get destination directory my($Line) = ""; if ($DstDir eq "") { $DstDir = $DefaultDstDir; print("The ${AppLongName} will be installed in the location you specify.\n" ."This installation directory should be somewhere accessible by your web server.\n"); print("Installation Directory [${DstDir}]: "); $Line = ; chomp($Line); if ($Line ne "") { $DstDir = $Line; # (strip off any trailing slash) if ($DstDir =~ /\/$/) { chomp($DstDir); } } } print("Using installation directory ${DstDir}\n"); if (! -d $DstDir) { do { print("Directory does not exist. Create directory [Y/N]? "); $Line = ; chomp($Line); } while ($Line !~ /y|n|yes|no/i); if ($Line !~ /y|yes/i) { print("\nPlease create the directory and re-run the installation.\n"); exit(1); } else { print("\nCreating directory ${DstDir}\n"); `mkdir ${DstDir}`; if (! -d $DstDir) { print("\nUnable to create installation directory ${DstDir}\n"); exit(1); } } } print("\n"); # check if destination dir is writable if ((! -w $DstDir) || (! -d $DstDir)) { print("Could not write to installation directory ${DstDir}\n"); exit(1); } # if destination dir already contains SPT or CWIS installation if ((-f $DstDir."/SPT--Home.php") && (-f $DstDir."/VERSION")) { # grab version of old installation $OldAppBaseVersion = `cat ${DstDir}/VERSION`; chomp($OldAppBaseVersion); # grab type of old installation if (`grep SPTUI--CWIS ${DstDir}/include/SPT--Config.php` ne "") { $OldAppShortName = "CWIS"; $OldAppVersion = $CwisVersionMap{$OldAppBaseVersion}; } else { $OldAppShortName = "SPT"; $OldAppVersion = $OldAppBaseVersion; } # if checksum file is not available if (! -r "${DstDir}/CHECKSUMS") { # ask if user wants to proceed without upgrading print("The directory:\n" ." ${DstDir}\n" ."appears to already contain ${OldAppShortName} version ${OldAppVersion},\n" ."however this version does not appear to be upgradable.\n" ."If you want to proceed with the install, the old installation will be moved into\n" ."a subdirectory called OLDVER-${OldAppShortName}-${OldAppVersion}, under the above directory.\n"); do { print("Do you want to proceed with the installation [Yes]? "); $Line = ; chomp($Line); } while (($Line !~ /^[YNyn]+/) && ($Line ne "")); # if user did not want to proceed if ($Line =~ /^[Nn]+/) { # tell user install is cancelled and then exit print("\nAborting installation.\n"); exit(1); } else { # set flag indicating old version must be moved aside $SaveOldInstall = 1; print("Old version will be moved to OLDVER-${OldAppShortName}-${OldAppVersion} before install.\n"); } } else { # ask if user wants to do upgrade print("The directory:\n" ." ${DstDir}\n" ."appears to already contain ${OldAppShortName} version ${OldAppVersion}.\n" ."If you decide not to upgrade, the old installation will be moved into a\n" ."subdirectory called OLDVER-${OldAppShortName}-${OldAppVersion}, under the above directory.\n"); do { print("Do you want to upgrade this installation [Yes]? "); $Line = ; chomp($Line); } while (($Line !~ /^[YNyn]+/) && ($Line ne "")); # if upgrade requested if (($Line =~ /^[Yy]+/) || ($Line eq "")) { # check to make sure that md5sum is available $Line = `md5sum --version 2>&1`; if ((! defined($Line)) || ($Line =~ /Command not found/)) { print("\nThe GNU 'md5sum' utility, which is required to upgrade a ${AppLongName}\n" ."installation, was not found. Please contact your system administrator about\n" ."getting md5sum installed on your server.\n"); exit(1); } # set flag indicating upgrade request $UpgradeRequested = 1; print("Installation will be upgraded to ${AppShortName} version ${AppVersion}.\n"); } else { # set flag indicating old version must be moved aside $SaveOldInstall = 1; print("Old version will be moved to OLDVER-${OldAppShortName}-${OldAppVersion} before install.\n"); } } } # get web server address if ($WebAddress eq "") { my($Host) = `hostname`; if ($Host !~ /[a-z0-9]+\.[a-z0-9]+/i) { $Host = `hostname --fqdn`; } chomp($Host); $WebAddress = "http://${Host}${DefaultWebAddressDir}"; print("\n" ."Now we need the URL (web address) where the portal will be found.\n"); print("Web Server Address [${WebAddress}]: "); $Line = ; chomp($Line); if ($Line ne "") { $WebAddress = $Line; } } print("Using web address ${WebAddress}\n"); print("\n"); # make sure that web server address has a trailing slash if ($WebAddress !~ /\/$/) { $WebAddress .= "/"; } # check if web server supports PHP version we need print("Checking PHP version..."); $Line = `lynx -version 2>&1 | grep -i 'lynx version'`; chomp($Line); if ($Line eq "") { print("\nThe 'lynx' utility was not found when attempting to verify the web\n" ."server and PHP version. If you are confident that the web server address\n" ."you entered is correct and the web server at that address supports the\n" ."minimum required version of PHP, you can choose to ignore the error and\n" ."continue with the installation anyway.\n" ."\n" ."Lynx is also required for the user agent search feature, so if lynx is not\n" ."available you will need to go into portal system configuration page and\n" ."turn off user agent searching.\n" ."\n" ."If you are not absolutely sure about the web server address or PHP version,\n" ."or you just want to have the installation perform the check, contact your\n" ."system administrator about making lynx available on your server.\n" ."\n"); do { print("Ignore the error and continue with installation [Y/N]? "); $Line = ; chomp($Line); } while ($Line !~ /y|n|yes|no/i); if ($Line !~ /y|yes/i) { print("\nPlease correct the error and the re-run the installation.\n"); exit(1); } # set flag to prevent installation of crontab entry $NoCronTab = 1; } else { $Line = `lynx -dump -head ${WebAddress} 2>&1 | grep '^Server:'`; chomp($Line); if ($Line eq "") { print("\nCould not connect to web server at ${WebAddress}\n"); exit(1); } $Line = `lynx -dump -head ${WebAddress} 2>&1 | grep 'PHP'`; chomp($Line); if ($Line !~ /PHP\/[4-9]/) { print("\nThe web server at:\n" ." ${WebAddress}\n" ."does not appear to support PHP 4. A web server with PHP version 4 or later\n" ."is required to run the ${AppLongName}.\n" ."\n" ."If you are SURE that your web server supports PHP 4, you can bypass this check.\n" ."\n"); do { print("Bypass this check and continue with installation [Y/N]? "); $Line = ; chomp($Line); } while ($Line !~ /y|n|yes|no/i); if ($Line !~ /y|yes/i) { print("\nPlease re-run the installation using a web server with PHP 4 installed.\n"); exit(1); } print("Bypassing check for PHP 4 support in web server.\n"); } else { print("okay.\n"); } } } sub InstallSoftware() { # if we need to move old install aside my($OurHomeDir) = `pwd`; chomp($OurHomeDir); print("\n"); if ($SaveOldInstall) { print("Saving old installation..."); # create subdirectory to hold old version (if it doesn't exist) my($OldVerDir) = "${DstDir}/OLDVER-${OldAppShortName}-${OldAppVersion}"; if (! -d $OldVerDir) { `mkdir ${OldVerDir}`; } # check that old version subdirectory is writable if ((! -d $OldVerDir) || (! -w $OldVerDir)) { print("\nCould not create ${OldVerDir}\n"); exit(1); } # move all files into subdirectory chdir($DstDir); `mv * ${OldVerDir}/. 2>&1`; # move any other old installs back up chdir($OldVerDir); `mv OLDVER-* .. 2>&1`; # copy old configuration info back up if (-f "${OldVerDir}/include/SPT--Config.php") { `mkdir ${DstDir}/include`; `cp ${OldVerDir}/include/SPT--Config.php ${DstDir}/include/.`; } print("done.\n"); } # unpack distribution archive print("Unpacking distribution archive..."); my($FullDistArchiveName) = $OurHomeDir."/".$DistArchiveName; my($WorkDir) = "/tmp/".$AppShortName."-".$AppVersion; chdir("/tmp"); if (system("cat ${FullDistArchiveName} | gunzip | tar xf -")) { print("\nCould not unpack distribution archive ${FullDistArchiveName}\nInstallation halted."); exit(1); } print("done.\n"); # if user requested upgrade if ($UpgradeRequested) { # for each file in checksum list for old install print("Checking for modified HTML files to preserve during upgrade..."); my($Line); my($FileName); my($NewFileName); my($Checksum); my($NewChecksum); chdir($DstDir); open(INPUT, "CHECKSUMS"); while ($Line = ) { # grab checksum info for old install ($Checksum, $FileName) = split(/\s+/, $Line); ($NewChecksum, $NewFileName) = split(/\s+/, `md5sum ${FileName}`); if ($NewFileName ne $FileName) { print("\n\nAn error was encountered while attempting to determine file checksums.\n"); exit(1); } # if file has changed if ($NewChecksum ne $Checksum) { # rename distribution copy of file to include version number rename($WorkDir."/".$FileName, $WorkDir."/".$FileName."--".$AppVersion); } } print("done.\n"); # for each user interface file in the new install print("Checking for vestigial user interface files..."); my(@NewInterfaces); my($NewInterface); my($InterfaceDir); my(@OldFiles); my($OldFile); @NewInterfaces = `ls -d ${WorkDir}/SPTUI--*`; foreach $NewInterface (@NewInterfaces) { # if interface is present in old install chop($NewInterface); $InterfaceDir = basename($NewInterface); if (-d $DstDir."/".$InterfaceDir) { # for each file in old install interface directory chdir($DstDir."/".$InterfaceDir); @OldFiles = `find . -type f -name "SPT--*.html"`; foreach $OldFile (@OldFiles) { # if file is not present in new install chop($OldFile); if ((! -f $WorkDir."/".$InterfaceDir."/".$OldFile) && (! -f $WorkDir."/".$InterfaceDir."/".$OldFile."--".$AppVersion)) { # rename file in old install rename($OldFile, $OldFile."--".$OldAppVersion."--V"); } } } } print("done.\n"); } # copy files from distribution to destination print("Copying files to install destination..."); chdir($WorkDir); if (system("tar cf - * | (cd ${DstDir} ; tar xpf -)")) { print("\nCould not copy archive files to ${DstDir}\nInstallation halted."); exit(1); }; system("rm -r ${WorkDir}"); print("done.\n"); # set up config file and make it writable print("Preparing for configuration file..."); chdir($DstDir); `chmod a+rwx include`; print("done.\n"); # make sure permissions are okay print("Setting file permissions..."); `find . -type f -not -name INSTALLED -not -name SPT--Config.php -not -path './ImageStorage/*' -not -path './TempStorage/*' -exec chmod a=r {} \\;`; if (-f "SPTUI--Default/include/SPT--Stylesheet.css") { `chmod a+w SPTUI--Default/include/SPT--Stylesheet.css`; } `find . -type d -exec chmod a+rx {} \\;`; `chmod u+x newinterface`; print("done.\n"); # set up link to default page print("Setting link to index.php..."); if (! -l "index.php") { `ln -s SPT--Home.php index.php`; } print("done.\n"); # set up subdirectories print("Setting up subdirectories..."); if (! -d "ImageStorage") { `mkdir ImageStorage`; `chmod a+rwx ImageStorage`; } if (! -d "ImageStorage/Previews") { `mkdir ImageStorage/Previews`; `chmod a+rwx ImageStorage/Previews`; } if (! -d "ImageStorage/Thumbnails") { `mkdir ImageStorage/Thumbnails`; `chmod a+rwx ImageStorage/Thumbnails`; } if (! -d "TempStorage") { `mkdir TempStorage`; `chmod a+rwx TempStorage`; } print("done.\n"); # set up subdirectory soft links print("Setting up links in subdirectories..."); if (! -l "MetadataTool/include") { `ln -s ../include MetadataTool`; } if (! -l "MetadataTool/images") { `ln -s ../images MetadataTool`; } if (! -l "MetadataTool/Axis--Database.php") { `ln -s ../Axis--Database.php MetadataTool`; } if (! -l "MetadataTool/Axis--StandardLibrary.php") { `ln -s ../Axis--StandardLibrary.php MetadataTool`; } if (! -l "MetadataTool/Axis--Session.php") { `ln -s ../Axis--Session.php MetadataTool`; } if (! -l "MetadataTool/Axis--User.php") { `ln -s ../Axis--User.php MetadataTool`; } if (! -l "MetadataTool/Axis--UserFactory.php") { `ln -s ../Axis--UserFactory.php MetadataTool`; } if (! -l "MetadataTool/Axis--Image.php") { `ln -s ../Axis--Image.php MetadataTool`; } # (CWIS-specific links) if ($AppShortName eq "CWIS") { if (! -l "MetadataTool/SPTUI--CWIS") { `ln -s ../SPTUI--CWIS/MetadataTool MetadataTool/SPTUI--CWIS`; } if (! -l "SPTUI--CWIS/MetadataTool/include") { `ln -s ../include SPTUI--CWIS/MetadataTool/include`; } if (! -l "SPTUI--CWIS/MetadataTool/images") { `ln -s ../images SPTUI--CWIS/MetadataTool/images`; } if (! -l "SPTUI--CWIS/MetadataTool/Themes") { `ln -s ../Themes SPTUI--CWIS/MetadataTool/Themes`; } if (! -l "CWIS--Install.php") { `ln -s SPT--Install.php CWIS--Install.php`; } } else # (SPT-specific links) { if (! -l "MetadataTool/SPTUI--Default") { `ln -s ../SPTUI--Default/MetadataTool MetadataTool/SPTUI--Default`; } if (! -l "SPTUI--Default/MetadataTool/include") { `ln -s ../include SPTUI--Default/MetadataTool/include`; } if (! -l "SPTUI--Default/MetadataTool/images") { `ln -s ../images SPTUI--Default/MetadataTool/images`; } if (! -l "MetadataTool/SPTUI--CleanOrange") { `ln -s ../SPTUI--CleanOrange/MetadataTool MetadataTool/SPTUI--CleanOrange`; } if (! -l "SPTUI--CleanOrange/MetadataTool/include") { `ln -s ../include SPTUI--CleanOrange/MetadataTool/include`; } if (! -l "SPTUI--CleanOrange/MetadataTool/images") { `ln -s ../images SPTUI--CleanOrange/MetadataTool/images`; } if (! -l "MetadataTool/SPTUI--Standards") { `ln -s ../SPTUI--Standards/MetadataTool MetadataTool/SPTUI--Standards`; } if (! -l "SPTUI--Standards/MetadataTool/include") { `ln -s ../include SPTUI--Standards/MetadataTool/include`; } if (! -l "SPTUI--Standards/MetadataTool/images") { `ln -s ../images SPTUI--Standards/MetadataTool/images`; } } print("done.\n"); # set up style sheet if not already there if ((-f "SPTUI--Default/include/SPT--Stylesheet.css.DIST") && (! -f "SPTUI--Default/include/SPT--Stylesheet.css")) { `cp SPTUI--Default/include/SPT--Stylesheet.css.DIST SPTUI--Default/include/SPT--Stylesheet.css`; `chmod a+w SPTUI--Default/include/SPT--Stylesheet.css`; } # save old version number if (length($OldAppBaseVersion) > 0) { `echo ${OldAppBaseVersion} > ${DstDir}/OLDVERSION`; } # clear install flag if present if (-f "include/INSTALLED") { `rm -f include/INSTALLED`; } } sub InstallCronEntry() { my($Line); my($AlreadyInCron) = 0; # backup current crontab `crontab -l > /tmp/crontab.backup.\${USER}.$$`; # grab current crontab my(@CronTab) = `crontab -l 2>&1`; # if crontab was empty if ($CronTab[0] =~ /^no crontab for /) { # clear error message out of crontab text undef @CronTab; } else { # see if we already have an entry in crontab foreach $Line (@CronTab) { if (($Line =~ /$WebAddress/) && ($Line =~ /HourlyMaint/)) { $AlreadyInCron = 1; } } } # if we don't already have an entry in crontab if ($AlreadyInCron == 0) { print("Adding entry to crontab file..."); # add our entry to crontab text $CronTab[$#CronTab + 1] = "#\n"; $CronTab[$#CronTab + 1] = "# SPT/CWIS - Maintenance Task\n"; $CronTab[$#CronTab + 1] = "0 * * * * lynx -dump ".$WebAddress."SPT--HourlyMaint.php > /dev/null\n"; # install new crontab text open(*OUTPUT, "| crontab - "); foreach $Line (@CronTab) { print(OUTPUT $Line); } close(*OUTPUT); print("done.\n"); } else { print("Crontab file already contains entry for this ".$AppShortName." installation.\n"); } } { # sign in print("\n"); print("${AppLongName} v${AppVersion} Installer\n"); # parse command-line arguments getopt("ud"); if ($Getopt::Std::opt_d) { $DstDir = $Getopt::Std::opt_d; } if ($Getopt::Std::opt_u) { $WebAddress = $Getopt::Std::opt_u; } # check to make sure distribution file is available $DistArchiveName = "${AppShortName}-${AppVersion}.tgz"; $DistArchiveName =~ tr/A-Z/a-z/; if (! -r $DistArchiveName) { print("Could not find ".$AppShortName." distribution archive ".$DistArchiveName."\n"); exit(1); } # ask user for settings GetInstallInfo(); # install portal toolkit InstallSoftware(); # set up cron entry (if not disabled) if ($NoCronTab == 0) { InstallCronEntry() } # tell user next steps if ($AppShortName eq "CWIS") { print("\n" ."The command-line portion of the installation has finished successfully.\n" ."To complete installation of CWIS go to:\n" ." ${WebAddress}CWIS--Install.php\n" ."with your web browser and follow the instructions given there.\n" ."\n" ."Thank you for using the NSDL Collection Workflow Integration System!\n" ); } else { print("\n" ."The command-line portion of the installation has finished successfully.\n" ."To complete installation of the Scout Portal Toolkit go to:\n" ." ${WebAddress}SPT--Install.php\n" ."with your web browser and follow the instructions given there.\n" ."\n" ."Thank you for using the Scout Portal Toolkit!\n" ); } }