# $Id: Makefile.PL,v 1.51 2003/08/28 19:19:33 andreychek Exp $ use lib "./inc"; use strict; use File::Copy; use File::Path; use File::NCopy qw(); use ExtUtils::MakeMaker qw( prompt ); use ExtUtils::AutoInstall qw(); # Perl version 5.005_03 is our minimum eval "use 5.005_03"; if( $@ ) { print <new(); my @plugin_dependencies = $op->get_install_list; my @optional_modules; if ( $] >= 5.006 ) { @optional_modules = qw( Attribute::Handlers 0 ); } ExtUtils::AutoInstall->import ( -version => '0.30', -config => { force => 0, }, -core => [ 'Class::Factory' => '1.0', 'Digest::MD5' => '2.16', 'MD5' => '', 'Test::Harness' => '2.0', 'Test::More' => '0.47', 'Error' => '', 'Storable' => '1.011', 'Devel::StackTrace' => '', 'Time::HiRes' => '1.20', 'Archive::Tar' => '0.23', @optional_modules, 'Params::Validate' => '', 'XML::DOM' => '1.29', 'Log::Dispatch' => '2.00', 'Log::Log4perl' => '0.25', 'HTML::Template' => '', 'CGI::Application' => '2.6', @plugin_dependencies, ], ); config_openplugin(); WriteMakefile( NAME => 'OpenPlugin', VERSION_FROM => './OpenPlugin.pm', test => { TESTS => $op->get_core_tests . $op->get_plugin_tests }, ($] >= 5.005 ? (ABSTRACT_FROM => 'OpenPlugin.pm', AUTHOR => 'Eric Andreychek ') : ()), ); sub config_openplugin { unless (prompt("\nCan I install your data files now?", 'Y/n') =~ /^y/i) { print "Warning: skipping data file installation.\n"; print "Normal OpenPlugin operation requires these data files!\n\n"; return; } my $data_file = prompt("\n\nWhere would you like to put the OpenPlugin\n" . "configuration files?\n", "/usr/local/etc"); chomp $data_file; unless ( -d $data_file ) { mkdir $data_file, 0777 or die "Cannot create $data_file: $!"; } if( -f "$data_file/OpenPlugin.conf" ) { File::Copy::copy("$data_file/OpenPlugin.conf", "$data_file/OpenPlugin.conf.orig") or die "Cannot backup config file: $!"; print "\nFound existing [OpenPlugin.conf] file. Backing up to [OpenPlugin.conf.orig].\n"; } if( -f "$data_file/OpenPlugin-drivermap.conf" ) { File::Copy::copy("$data_file/OpenPlugin-drivermap.conf", "$data_file/OpenPlugin-drivermap.conf.orig") or die "Cannot backup config file: $!"; print "Found existing [OpenPlugin-drivermap.conf] file. Backing up to [OpenPlugin-drivermap.conf.orig].\n\n"; } my $file = File::NCopy->new(recursive => 1); $file->copy("conf/*", "$data_file") or die "Cannot copy conf directory to $data_file: $!"; print "OpenPlugin config files are now in $data_file\n"; return {}; } package OpenPlugin::Installer; use strict; use ExtUtils::MakeMaker qw(prompt); ################### # Data Format # # deps # A reference to an array containing a list of all a particular # driver's dependencies, in the format: # 'Module' => 'Version' # # meta # Meta information for a particular driver. The following meta information is # recognized: # -install -- Means this driver will be installed by default # -force -- Forces installation of a particular driver (driver is required) # -test -- Name of test to run if installing this driver sub new { my $class = shift; my $self = { 'Request' => { Apache2 => { deps => [ 'Apache2' => '' ], meta => { -install => 0, -test => 't/request_apache2.t' }, }, Apache => { deps => [ 'Apache::Request' => '0.30' ], meta => { -install => 0, -test => 't/request_apache.t' }, }, CGI => { deps => [ 'CGI' => '', ], meta => { -install => 1, -test => 't/request_cgi.t' }, }, }, Authenticate => { #DBI => { # deps => [ DBI => '', ], # meta => { -install => 1, }, #}, PAM => { deps => [ 'Authen::PAM' => '', ], meta => {}, }, SMB => { deps => [ 'Authen::Smb' => '', ], meta => {}, }, }, Cache => { File => { deps => [ 'Digest::SHA1' => '2.02', 'Cache::Cache' => '', ], meta => { -install => 1, -test => 't/cache_file.t' }, }, }, Config => { Conf => { deps => [ 'Config::General' => '', ], meta => { -install => 1, -force => 1, }, }, Ini => { deps => [], meta => { -install => 1, -force => 1, }, }, Perl => { deps => [ 'Data::Dumper' => '', ], meta => {}, }, XML => { deps => [ 'OpenThought::XML2Hash' => '0.56', ], meta => {}, }, }, Datasource => { DBI => { deps => [ DBI => '', ], meta => { -install => 1, }, }, LDAP => { deps => [ 'Net::LDAP' => '', ], meta => {}, }, }, Log => { ApacheLog => { deps => [ 'Apache::Log' => '', ], meta => {}, }, DBI => { deps => [ 'DBI' => '', 'Log::Dispatch::DBI' => '', ], meta => {}, }, Email => { deps => [ 'Mail::Sendmail' => '', ], meta => {}, }, Jabber => { deps => [ 'Unicode::String' => '', 'Net::SSLeay' => '', 'IO::Socket::SSL' => '0.81', 'XML::Stream' => '', 'Net::Jabber' => '', ], meta => {}, }, Syslog => { deps => [ 'Sys::Syslog' => '', ], meta => {}, }, }, Session => { ApacheSession => { deps => [ 'MIME::Base64' => '', 'DB_File' => '', 'Apache::Session' => '1.54', ], meta => { -install => 1, -test => 't/session_apachesession.t' }, }, }, }; bless( $self, $class ); return $self; } sub get_core_tests { my $self = shift; # Leave a trailing space my $tests = "t/01_require.t t/02_config.t t/03_log.t t/04_exception.t "; return $tests; } # Get a hash (name, version) of modules to be installed sub get_install_list { my $self = shift; $self->check_deps; $self->handle_input; my @install_list = $self->get_scheduled_driver_deps; if( @install_list ) { return @install_list; } else { return (); } } sub get_scheduled_driver_deps { my $self = shift; my @deps_list; foreach my $plugin ( $self->get_plugins ) { foreach my $driver ( $self->get_scheduled_drivers( $plugin )) { foreach my $dep ( $self->_get_driver_deps( $plugin, $driver )) { push @deps_list, $dep; } } } return @deps_list; } sub get_plugin_tests { my $self = shift; my $test_list; foreach my $plugin ( $self->get_plugins ) { foreach my $driver ( $self->get_installed_drivers( $plugin ) ){ foreach my $test ( $self->_get_driver_test( $plugin, $driver )) { $test_list .= " $test"; } } foreach my $driver ( $self->get_scheduled_drivers( $plugin ) ){ foreach my $test ( $self->_get_driver_test( $plugin, $driver )) { $test_list .= " $test"; } } } $test_list =~ s/\s+/ /g; return $test_list; } # The main look for the installation screen sub handle_input { my $self = shift; my $action; while ( $action ne "d" ) { $action = ""; $self->display_installation_screen; while ($action !~ m/^[ardAR]/) { $action = (prompt("\n[a]dd, [r]emove, [A]dd All, [R]emove All, [d]one:", "d")); } if( $action eq "a") { $self->add_driver; } elsif( $action eq "r") { $self->remove_driver; } elsif( $action eq "A") { $self->add_all_drivers; } elsif( $action eq "R") { $self->remove_all_drivers; } } print "\nDone.\n\n"; } # Return a list of all plugins sub get_plugins { my $self = shift; return sort keys %{ $self }; } # Return a list of all drivers for a given plugin sub get_drivers { my ( $self, $plugin ) = @_; return sort keys %{ $self->{ $plugin } }; } # List drivers which currently are not scheduled to be installed sub get_available_drivers { my ( $self, $plugin ) = @_; my @all_drivers = sort keys %{ $self->{ $plugin } }; my @available_drivers; foreach my $driver ( @all_drivers ) { # If it's already installed, or scheduled to be installed, it's not # considered available unless(( $self->_to_be_installed( $plugin, $driver )) || ( $self->_already_installed( $plugin, $driver))) { push @available_drivers, $driver; } } return @available_drivers; } # List drivers which are currently scheduled to be installed sub get_scheduled_drivers { my ( $self, $plugin ) = @_; my @all_drivers = sort keys %{ $self->{ $plugin } }; my @drivers_to_install; foreach my $driver ( @all_drivers ) { if( $self->_to_be_installed( $plugin, $driver )) { push @drivers_to_install, $driver; } } return @drivers_to_install; } # List drivers which are already installed sub get_installed_drivers { my ( $self, $plugin ) = @_; my @all_drivers = sort keys %{ $self->{ $plugin } }; my @installed_drivers; foreach my $driver ( @all_drivers ) { if( $self->_already_installed( $plugin, $driver )) { push @installed_drivers, $driver; } } return @installed_drivers; } # List drivers which are currently scheduled to be installed sub get_scheduled_drivers { my ( $self, $plugin ) = @_; my @all_drivers = sort keys %{ $self->{ $plugin } }; my @drivers_to_install; foreach my $driver ( @all_drivers ) { if( $self->_to_be_installed( $plugin, $driver )) { push @drivers_to_install, $driver; } } return @drivers_to_install; } # See which drivers we already have all the dependencies installed for sub check_deps { my $self = shift; foreach my $plugin ( $self->get_plugins ) { foreach my $driver ( $self->get_drivers( $plugin ) ) { my $driver_test = 1; my %deps = $self->_get_driver_deps( $plugin, $driver ); foreach my $module ( keys %deps ){ unless (defined (ExtUtils::AutoInstall::_version_check( ExtUtils::AutoInstall::_load($module), $deps{$module} ||= 0 ))) { $driver_test = 0; } } if( $driver_test ) { $self->_set_driver_installed( $plugin, $driver ); } } } } # Remove a scheduled driver sub remove_driver { my $self = shift; my @plugins = $self->get_plugins; $self->display_ordered_list( @plugins ); my $msg = "Remove driver from which plugin?"; my $plugin_num = $self->get_number_input( 1, scalar @plugins, $msg ); return unless defined $plugin_num; my $plugin = $self->get_plugin_by_number( $plugin_num ); my @drivers = $self->get_scheduled_drivers( $plugin ); my $driver_num; if ( @drivers > 1 ) { $self->display_ordered_list( @drivers ); my $msg = "Remove which driver?"; my $driver_num = $self->get_number_input( 1, scalar @drivers, $msg ); return unless defined $driver_num; } elsif ( @drivers == 1 ) { $driver_num = 0; } else { prompt("\n * No drivers from $plugin to remove: ", "whoops"); return; } my $driver = $self->get_scheduled_drivers_by_number( $plugin, $driver_num ); if ( $self->_unschedule_driver( $plugin, $driver ) ) { prompt("\n * Removed the $driver driver from $plugin: ", "okay"); } else { prompt("\n * $driver is either already installed on your system, or required: ", "okay"); } } # Schedule a driver to be installed sub add_driver { my $self = shift; my @plugins = $self->get_plugins; $self->display_ordered_list( @plugins ); my $msg = "Add driver from which plugin?"; my $plugin_num = $self->get_number_input( 1, scalar @plugins, $msg ); return unless defined $plugin_num; my $plugin = $self->get_plugin_by_number( $plugin_num ); my @drivers = $self->get_available_drivers( $plugin ); my $driver_num; if ( @drivers > 1 ) { $self->display_ordered_list( @drivers ); my $msg = "Add which driver?"; $driver_num = $self->get_number_input( 1, scalar @drivers, $msg ); return unless defined $driver_num; } elsif ( @drivers == 1 ) { $driver_num = 0; } else { prompt("\n * No more drivers from $plugin to install: ", "bummer"); return; } my $driver = $self->get_available_drivers_by_number( $plugin, $driver_num ); $self->_schedule_driver( $plugin, $driver ); prompt("\n * Scheduled the $driver driver from $plugin to be installed: ", "okay"); } sub add_all_drivers { my $self = shift; foreach my $plugin ( $self->get_plugins ) { foreach my $driver ( $self->get_available_drivers( $plugin )) { print "P: $plugin, $driver\n"; $self->_schedule_driver( $plugin, $driver ); } } } sub remove_all_drivers { my $self = shift; foreach my $plugin ( $self->get_plugins ) { foreach my $driver ( $self->get_scheduled_drivers( $plugin )) { $self->_unschedule_driver( $plugin, $driver ); } } } sub get_plugin_by_number { my ( $self, $number ) = @_; return (sort $self->get_plugins)[$number-1]; } sub get_available_drivers_by_number { my ( $self, $plugin, $number ) = @_; return (sort $self->get_available_drivers( $plugin ))[$number-1]; } sub get_scheduled_drivers_by_number { my ( $self, $plugin, $number ) = @_; return (sort $self->get_scheduled_drivers( $plugin ))[$number]; } # Given a min and max number, a prompt and error message, this function gets a # number as input from the user. It keeps trying until they give a number # within the limit sub get_number_input { my ( $self, $min, $max, $prompt ) = @_; my $num = $min - 1; while(( $num < $min ) || ( $num > $max )) { $num = prompt( $prompt . ": [$min-$max]" ); return undef if $num =~ m/^\s*$/g; if(( $num < $min ) || ( $num > $max )) { prompt( "\n * Is '$num' one of the choices?", "nope" ); print "\n"; } } return $num; } # Given a list of items, displays it line by line with prefixed numbers sub display_ordered_list { my ( $self, @list ) = @_; print "\n"; for( my $i = 1; $i <= $#list+1; $i++ ) { print "[$i] $list[$i-1]\n"; } print "\n"; } sub display_installation_screen { my $self = shift; my $i; foreach my $plugin ( $self->get_plugins ){ $i += scalar $self->get_installed_drivers( $plugin ); } print qq{ \n\n\n\n\n\n\n\n\n\n\n OpenPlugin Driver Installation Screen I detected dependencies for ($i) drivers already installed on your system. You may now choose additional drivers to install. ------------------------------------------------------------------------------ Plugin | Available Drivers | Install ------------------------------------------------------------------------------ }; foreach my $plugin ( $self->get_plugins ) { my $available_drivers; foreach my $driver ( $self->get_available_drivers( $plugin ) ){ $available_drivers .= "$driver "; } my $drivers_to_install; foreach my $driver ( $self->get_scheduled_drivers( $plugin ) ){ $drivers_to_install .= "$driver "; } #my $installed_drivers; #foreach my $driver ( $self->get_installed_drivers( $plugin ) ){ # $installed_drivers .= "$driver "; #} format STDOUT = @<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $plugin $available_drivers $drivers_to_install . write; } } sub display_installed_drivers_screen { my $self = shift; my $i; foreach my $plugin ( $self->get_plugins ){ $i += scalar $self->get_installed_drivers( $plugin ); } foreach my $plugin ( $self->get_plugins ){ $i += scalar $self->get_scheduled_drivers( $plugin ); } print qq{ \n\n\n\n\n\n\n\n\n\n\n When the installation is complete, the following $i drivers will be available to you: ------------------------------------------------------------------------------ Plugin | Drivers ------------------------------------------------------------------------------ }; foreach my $plugin ( $self->get_plugins ) { my $driver_list; foreach my $driver ( $self->get_installed_drivers( $plugin ) ){ $driver_list .= "$driver "; } foreach my $driver ( $self->get_scheduled_drivers( $plugin ) ){ $driver_list .= "$driver "; } format STDOUT1 = @<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $plugin $driver_list . write STDOUT1; } ; } ################### # Private Functions # Determine whether or not a driver is already installed sub _already_installed { my ( $self, $plugin, $driver ) = @_; if( $self->{ $plugin }{ $driver }{'meta'}{'-installed'} ) { return 1; } else { return 0; } } # Set a driver as already being installed sub _set_driver_installed { my ( $self, $plugin, $driver ) = @_; $self->{ $plugin }{ $driver }{'meta'}{ '-installed' } = 1; $self->{ $plugin }{ $driver }{'meta'}{ '-install' } = 0; } # Schedule a driver to be installed sub _schedule_driver { my ( $self, $plugin, $driver ) = @_; return $self->{ $plugin }{ $driver }{'meta'}{ '-install' } = 1; } # Unschedule a driver from installtion sub _unschedule_driver { my ( $self, $plugin, $driver ) = @_; if( $self->{ $plugin }{ $driver }{'meta'}{ '-force' } ) { return 0; } else { $self->{ $plugin }{ $driver }{'meta'}{ '-install' } = 0; return 1; } } # Determine whether or not a driver is scheduled for installation sub _to_be_installed { my ( $self, $plugin, $driver ) = @_; if( $self->{ $plugin }{ $driver }{'meta'}{'-install'} ) { return 1; } else { return 0; } } # Get a list of dependencies for a given driver sub _get_driver_deps { my ( $self, $plugin, $driver ) = @_; return @{ $self->{ $plugin }{ $driver }{'deps'} }; } # Get a list of dependencies for a given driver sub _get_driver_test { my ( $self, $plugin, $driver ) = @_; return $self->{ $plugin }{ $driver }{'meta'}{'-test'}; } 1;