#! /usr/bin/perl

# This is a simple perl script for installing ogo from rpms. I use RedHat9 and it works for my
# needs. Operating systems on which this script works are noted below.
#
# It will install, update or remove OpenGroupware. It happily retrieves the latest packages,
# sets up the Apache module, and installs PostgreSQL. Requires perl and wget.
#
# Debian users: See the Debian Unofficial HowTo at : 
# http://helms-deep.cable.nu/%7erwh/howtos/OpenGroupware-Debian-HOWTO.html
#
# Be sure to check the variables in this script to match your distribution.
#
# Use at your own risk. If it breaks your system, sorry, but I'm not liable for any losses
# or damages, etc. whatsoever.

# The latest version of this script and usage instructions can always be found at:
# http://www.toasterz.com/ogo or http://www.exchangekiller.com
# This is version: //$Id: add_remove_ogo.pl 420 2005-01-17 19:48:47Z helge $

# Copyright 2003 Kelley Graham

# License: LGPL (Same as OpenGroupware)
# Find out more: http://opensource.org/licenses/lgpl-license.php

# Changelog ##############################################################
#	-Working on...
#	-Removing duplicates and getting-installing only needed packages
#04August2003
#	-Added check for opengroupware.skyrix , will add if needed.
#	-Added check for bash defaults, will add if needed
#	-Added check for ld.so.conf, will add if needed. run ldconfig.
#	-Added check for init script, will install if needed. will run chkconfig --add
#	-Cleaned up init script to set pids properly for OGo and ZideStore.
#	-Added -P option to skip PostgreSQL get-install
#29July2003
#	-Now retrieves the latest packages code.
#	-Removed -O option.
#	-Streamlined install messages. Wget is now quiet by default.
#	-Edited comments and install messages for consistency and clarity.
#28July2003
#	-Debugging
#27July2003
#	-Made default to install everything when called bare, ie with no command line options.
#	This for when script is invoked with the command
#	wget -q -O - http://www.exchangekiller.com/install | perl
#	Thanks Yeddida Klien for suggesting this feature.
#	-Added "-U" up2date option.
#26July2003
#	-Added ZideStore Apache configuration settings.
#25July2003
#	-Added working directories creation.
#	-Added mod_ngobjweb install for Apache2.
#	-Made "-n" output more consistent throughout script.
#	-Made debug "-v" output more intuitive.
#	-Misc speling corrections.
#	-Added zidestore package install (sometimes works, sometimes doesn't)
#	-Added "-h"  to display usage. Expand later to display faq.
# 23July2003
#	-Finished wget retrieve packages section, passive ftp by default, doesn't work on latest, have to fix.
#	-Added -g (get only) and -G (skip retrieval) options
#	-More comment and usage refinements
# 22July2003
#	-Added -f option to the remove code (ie --nodeps)
#	-Testing rudimentary wget for redhat9 (we need version checks, community?)
#	-Corrected misc typos and strange usage.
#	-Added latest link info to blurb, so if there's problems with mirrors etc
#	 the latest can always be found.
# 20July2003
#	-Added #'s to properly comment out comments. I have to try not to do this work in the
#	middle of the night...
#	-This script has been tested and found to work on SuSE 8.2.
# 17July2003
#	-Thanks again for Gustavo Chaves' excellent work. He added:
#	-apt-get package removal to resolve debian rpm -e problems
# 15July2003
#	-added postgresql install option
#	-added -f (force) option
#	-incorporated Gustavo Chaves' many enhancements, Thanks!
# 13July2003
#	-added comand line var and rudimentary sanity checks
# 12July2003 
#	-initial cobbling together
#	-added libical before xml
#	-removed libxmlsaxdriver line since it is included in the xml package

# Todo ###################################################################
# 
#	-add interactivity option "-N" to provide prompts for newbies or nonstandard installs.
#	-build -h (help) faq for unix newbies?, expand comments first
#	-add support for other distros (community help?)
#	-code needs to be streamlined, but not obscured.
#	-add "output debug info to file" switch.

use warnings;
use strict;
use Getopt::Std;

my $usage = <<EOF;
usage: $0 [-h] [-n] [-v] [-f] [-a] [-A] [-g] [-G] [-m] [-M] [-U] [P] [install|remove]

Call the script without any options to do a complete install. Use this command:
	wget -q -O - http://exchangekiller.com/install | perl
	
Pass the script "install" to install-upgrade Opengroupware.
Pass the script "remove" to remove OpenGroupware.
	Does not remove PostgreSQL or Apache2 module at this time.

Options:

Calling script with no options is the same as add_remove_ogo.pl -a install.

Use "-h" to display these options
Use "-a" to install OGo + PostgreSQL + Apache2 module. (Default)
Use "-n" to do nothing -- see what would be done.
Use "-v" to get verbose debug output.
Use "-f" to force rpm to overwrite existing packages. (use with care) see man rpm.
	If removing packages and you receive errors, try this option.
Use "-A" to use apt-get for removing the packages.
Use "-g" to retrieve packages only. Handy when script is run from cron job.
Use "-G" to skip package retrieval. The default is to get the rpms.
Use "-U" to use up2date to install where applicable.
Use "-m" to install-upgrade Apache module only. (Default is to install)
Use "-M" to skip Apache module install.
Use "-P" to Skip PostgreSQL install.

EOF

my $action;
my %args;
if (!%args && !$action) { %args = (a => 1); }

getopts('hnvfaAgGmMUP', \%args);
die $usage if $args{h};
$action = shift;
unless ($action) { $action = "install"; }

# These arrays are used to tell the script what packages to install and in what order.
# Remove or add what you want.
my @order = qw(
	       opengroupware-gstep-make*
	       opengroupware-gstep-objc*
	       opengroupware-libfoundation*
	       opengroupware-js*
	       opengroupware-libxml2*
	       opengroupware-libical*

	       opengroupware-xml*
	       opengroupware-core*
	       opengroupware-gstep-db*
	       opengroupware-gstep-db-postgresql72*
	       opengroupware-sope*

	       opengroupware-env*
	       opengroupware-logic*
	       opengroupware-docapi*
	       opengroupware-database*
	       opengroupware-webui-libs*
	       opengroupware-webui-common*
	       opengroupware-webui-admin*
	       opengroupware-webui-app*
	       opengroupware-webui-contact*
	       opengroupware-webui-job*
	       opengroupware-webui-mailer*
	       opengroupware-webui-news*
	       opengroupware-webui-prefs*
	       opengroupware-webui-resource-en*
	       opengroupware-webui-scheduler*
	       opengroupware-webui-forms*
	       opengroupware-webui-project*
	       opengroupware-theme-default-en*
	       opengroupware-theme-ooo-en*
	       opengroupware-pilot-link*
	       opengroupware-pda*
	       opengroupware-tools*
	       opengroupware-1.0*
	       opengroupware-publisher*
	       opengroupware-zidestore*
	      );
my @pg_order = qw(
		 postgresql-libs*
		 postgresql-7*
		 postgresql-server*
		 postgresql-tcl*
		 postgresql-contrib*
		 postgresql-devel*
		 postgresql-docs*
		 postgresql-pl*
		 postgresql-python*
		 postgresql-test*
		);

# Set command line option values
my $wget_vopt = $args{v} ? "-v" : "-q";
my $pkg_ver = "latest";

# OGo package archive and command setup
my $wget_ogo_url = "ftp://ftp.opengroupware.org/packages/rpm/*$pkg_ver.rpm";
my $wget_links_cmd = "wget $wget_vopt -r -N -k -L -nH -nr --cut-dirs=2 -l 1 -w 1 --passive-ftp $wget_ogo_url";
my $wget_real_stem = "wget $wget_vopt -N --passive-ftp ftp://ftp.opengroupware.org/packages/rpm/";

# OGo init script location
my $ogo_init_url = "http://exchangekiller.com/docs/opengroupware";
my $wget_init_cmd ="wget $wget_vopt -N $ogo_init_url";

# PostgreSQL package archive amd command setup
my $wget_pgsql_url = "ftp://ftp10.us.postgresql.org/pub/postgresql/binary/v7.3.3/RPMS/redhat-9/*.i386.rpm";
my $wget_pgsql_cmd = "wget $wget_vopt -r -N -L -nH -nr --cut-dirs=6 -l 1 -w 1 --passive-ftp $wget_pgsql_url";

# Set Apache mod_ngobjweb archive, set vars, set text for ogo.conf. Make sure $version matches your version and
# copy the ogo.conf text to the appropriate place in httpd.conf if you're not using apache2.
my $wget_mod_url = "http://www.opengroupware.org/sources/opengroupware.org-mod_ngobjweb-latest.tar.gz";
my $wget_mod_cmd = "wget $wget_vopt -r -N -nH -nr -l 1 -w 1 --passive-ftp $wget_mod_url";
my $version = "2.0.40";
		
# Check that this is truly cross platform. You may have to edit the field reference to fit your tistro.
# Make sure you season this to taste, will automate asap.
my @ogo_env= getpwnam("opengroupware");
my $ogo_user_home = $ogo_env[7];
if (!$ogo_user_home) { $ogo_user_home =  "/opt/opengroupware.org";}

#Check for skyrix group and opengroupware user. Use for broken intstalls or as
# option to check defaults. Todo: make interactive. Commands based on distribution.
print "Checking for system group: skyrix...";
unless(getgrnam("skyrix")) {
	print "...skyrix does not exist, creating...\n";
	my $sky_code = system("groupadd 'skyrix'") or print "...Warning: Couldn't create group skyrix $!\n";
	print "... Done" if (!$sky_code);
}
print "... skyrix group exists\n";

print "Checking for system user: opengroupware...";
unless(getpwnam("opengroupware")) {
	print "...opengroupware user does not exist, creating...\n";
	my $u_code = system("useradd '-g' 'skyrix' '-d' '$ogo_user_home' 'opengroupware'") or print "...Couldn't create user opengroupware. $!\n";
	print "...Done" if (!$u_code);
}
#make this work better;
print "... opengroupware user exists\n";

# Setup working dirs.
# Since we're running this script from our home dir all paths
# shoud be relative to ~.

my $ogo_dir = "ogo";
my $ogo_pkg_dir = "ogo_rpms";
my $ogo_links_dir = "$ogo_pkg_dir/links";
my $pgsql_pkg_dir = "pgsql_rpms";
my $mod_src_dir = "mod_src";

my @dirs = ($ogo_pkg_dir,$ogo_links_dir,$pgsql_pkg_dir,$mod_src_dir);

# Check for $ogo_dir and make if missing.
print "Checking working directories...";
unless(-e "$ogo_dir") {
	print "... Directories NOT found.\n";
	mkdir $ogo_dir;
	foreach my $dir(@dirs) {
		print "\n...... Creating: $ogo_dir/$dir...";
		if (!$args{n}) {
			mkdir "$ogo_dir/$dir";
			print "... Done\n";
		}
	}
}
print "Working directories OK\n";

# Install wget if needed: RedHat centric now, check and make this cross platform.
print "Checking to see if Wget is installed...";
unless(-e "/etc/wgetrc") {system("up2date 'wget'");}
print "... OK Wget's installed\n";

my $config_file = "/etc/httpd/conf.d/ogo.conf"; # todo: get this path from system call
my $conf_text = <<EOF;

#OpenGroupware Apache Module config file.

LoadModule ngobjweb_module $ogo_user_home/opengroupware/WebServer/ngobjweb_$version.so

<LocationMatch "^/OpenGroupware/*">
    SetHandler ngobjweb-adaptor
    SetAppPort 20000
#    SNSPort 127.0.0.1:20000 # User for skyrix load balancer
</LocationMatch>

<LocationMatch "^/ev*">
   SetHandler ngobjweb-adaptor
   SetAppPort 23000
</LocationMatch>

# Exchange public folders URL
<LocationMatch "^/zidestore/*">
   SetHandler ngobjweb-adaptor
   SetAppPort 23000
</LocationMatch>

Alias /OpenGroupware10a.woa/WebServerResources/ /usr/local/share/opengroupware.org-1.0a/www/
Alias /ArticleImages /var/lib/opengroupware.org/news

EOF

# Apache module -n option install message. 
# We need a check to see if it's already installed. and if there's newer source code.
# For now the message will work for -v and -n options.
my $n_msg = <<EOF;

Getting source, configure, compile and copy .so to module directory.
Creating ogo.conf in /etc/httpd/conf.d/.
Restarting Apache (and OGo).

EOF

chdir ("$ogo_dir");

# Get OGo packages latest symlinks
if (!$args{G} && !$args{m} && $action eq "install") {
	print "Retrieving Latest OpenGroupware Package List...";
	if ($args{v} || $args{n}) {print "$wget_links_cmd\n";}
	if (!$args{n}) {
		chdir("$ogo_links_dir");
		my $wget_code = system($wget_links_cmd);
		chdir("../../");
		print "... Done\n";
	}
	if ($args{g} && !$args{a}) {exit 0;}
}

# Get and install init script
print "Checking for init script...";
# Todo: need to figure out better command flow
if (!-e "/etc/init.d/opengroupware" && !$args{f} && !$args{m}) {
	print "... Init script not found\n";
	print "Getting latest init script...";
	system("$wget_init_cmd");
	print "... Done\n";
	print "Installing latest init script...";
	system("cp 'opengroupware' '/etc/init.d/'");
	system("chmod '+x' '/etc/init.d/opengroupware'");
	system("chkconfig '--add' 'opengroupware'");
	print "... Done\n";
	}
print "... Done\n";

# Set ld.so.conf vars
my $ldso = "/etc/ld.so.conf"; # Path to ld.so.conf. Season to taste;
my $ogo_search_string = "$ogo_user_home/Libraries/ix86/linux-gnu/gnu-fd-nil";
my $skyrix_search_string = "/opt/skyrix/system/Libraries/ix86/linux-gnu/gnu-fd-nil";
my @search_terms = ($ogo_search_string,$skyrix_search_string);
my $term;
my $search_ld_result;

# check for ld.so.conf settings
print "Checking $ldso...\n";
if (-e "$ldso" or print "\nNo $ldso file found. Is your path correct?\n") {
        foreach $term(@search_terms) {
                $search_ld_result = system("cat '$ldso' | 'grep' '$term'");       
		if($search_ld_result != "0") {
        	       print "No $term found\n";
               	print "Adding: \"$term\"\n";
               	system("echo '$term' >> '$ldso'");
		}
	}
system("ldconfig");
print "\n... Done\n";
}	

# Find and set bash vars
my $bash_name;
my $dist;
my $kernel_search_string;

if(!-e ".bash_profile") {$bash_name = ".bashrc";}
$bash_name = ".bash_profile";

# my $bash_name = "put_your_bash_initialization_filename_here"; # Use if not one of the above
my $bashrc = "$ogo_user_home/$bash_name";
my $bash_src_string = "source $ogo_user_home/OpenGroupware.org.sh";
my $bash_umask_string = "umask 0133"; # Comment out old umask would be nice
if(-e "/etc/redhat-release") {$dist = system("cat '/etc/redhat-release' | 'grep' 'Shrike'");}
if($dist == "0") {$kernel_search_string = "export LD_ASSUME_KERNEL=2.4.1";}
my @bash_search_terms = ($bash_src_string,$bash_umask_string,$kernel_search_string);
my $bash_term;
my $search_bash_result;

# Check bash settings
print "Checking $bashrc...\n";
if (-e "$bashrc" or print "No $bashrc file found. Is your path correct?\n") {
        foreach $bash_term(@bash_search_terms) {
                $search_bash_result = system("cat '$bashrc' | 'grep' '$bash_term'");
                if($search_bash_result != "0") {
                        print "\nNo $bash_term found\n";
                        print "Adding: \"$bash_term\"\n";
                        system("echo '$bash_term' >> '$bashrc'");
                }
        }
print "\n... Done\n";
}

# Build real package array.
my(@links,$symlink,@realpkgs,@realnames,$name);
opendir(LINKS, "$ogo_links_dir");
@links = grep !/^\./, readdir(LINKS);
closedir(LINKS);
chdir("$ogo_links_dir");
foreach $symlink(@links) {
	push(@realnames, readlink $symlink);
}
		
# Wget the real packages...
chdir("../");
if (!$args{G} && !$args{m} && $action eq "install") {
	print "Retrieving Latest OpenGroupware Packages...\n\n";
#	my $wget_real_cmd = join(' ',"$wget_real_stem",@realnames);
#	if ($args{n} || $args{v}) {print $wget_real_cmd;}
#	if (!$args{n}) {system("$wget_real_cmd");}
	if ($args{n}) {
		foreach $name(@realnames) {
			print "$wget_real_stem$name\n";
		}
	}
	if (!$args{n}) {
		foreach $name(@realnames) {
			print "Retrieving $name...";
			system("$wget_real_stem$name");
			print "...Done\n";
		}
	}
}

# Build OGo package array
my @packages = map(glob("$_.i386.rpm"), @order);
#my @packages = map(glob("$_"), @realnames);
my @stems = map(/(opengroupware-.*)-[.\d]+-\w+\.i386\.rpm/ ? $1 : "NOMATCH_$_", @packages);
chdir("../");

if ($action eq "install") {
	my $vopts = $args{v} ? "vv" : "vh";
	my $fopt = $args{f} ? "--force" : "";
	my $pg_vopts = $args{v} ? "vv" : "vh";
	my $pg_fopt = $args{f} ? "--force" : "";
	chdir $pgsql_pkg_dir;
	my @pg_pkgs = map(glob("$_.i386.rpm"), @pg_order);
	my @pg_stems = map(/(postgresql-.*)-[.\d]+-\w+\.i386\.rpm/ ? $1 : "NOMATCH_$_", @pg_pkgs);
	chdir("../");
					
	if ($args{a} || $args{m}) {
		if(!$args{P}) {
			# Get PostgreSQL packages
			if (!$args{G} && !$args{m} && !$args{U} && !$args{P}) {print "\nRetrieving PostgreSQL Packages...";
				if ($args{n}) {print "$wget_pgsql_cmd\n";}
				if (!$args{U} && !$args{n}) {
					chdir("$pgsql_pkg_dir");
					if ($args{v}) {print "$wget_pgsql_cmd\n";}
					my $wget_pgsql_code = system($wget_pgsql_cmd);
					chdir("../");
 					if ($args{g}) {exit $wget_pgsql_code;}
 					print "...Done\n";	
				}	
			}
			my $pg_u2d_cmd = join(' ', "up2date", @pg_pkgs);
			# Need to check for dist. here. reduce possible confusing newbie errors
			# Currently need make new @pg_pkgs so up2date works.
			if ($args{U}) {
				print "Using up2date to install all PostgreSQL packages.\n\n";
				if ($args{v} || $args{n}) {print "$pg_u2d_cmd\n";}
				my $pg_u2d_code = system($pg_u2d_cmd);
			}

			if (@pg_pkgs && !$args{m} && !$args{g} && !$args{P}) {
				print "Installing PostgreSQL...\n\n";
				chdir("$pgsql_pkg_dir");
				my $pg_cmd = join(' ', "rpm -U$pg_vopts $pg_fopt", @pg_pkgs);
				if ($args{v} || $args{n}) {print "$pg_cmd\n";}
				if (!$args{n}) {system($pg_cmd);}
				chdir("../");
			}
	}
		if ($args{m} || !$args{M}) {
			if (!$args{g} && !$args{G}) {print "\nInstalling Apache2 module...\n";}
			if ($args{n} && !$args{g}) {print"$n_msg";}
			if (!$args{n} && !$args{g} && !$args{G}) {
				if ($args{n} || $args{v}) {print "$n_msg\n";}
				if ($args{n}) {exit 0;}
				chdir("$mod_src_dir");
				system("$wget_mod_cmd");
				chdir("sources");
				system("tar '-xzvf' 'opengroupware.org-mod_ngobjweb-latest.tar.gz'");
				chdir("opengroupware.org-mod_ngobjweb");
				system("make");
				mkdir("$ogo_user_home/opengroupware");
				mkdir("$ogo_user_home/documents");
				system("chown 'opengroupware.skyrix' '/opt/opengroupware.org/documents'");
				mkdir("$ogo_user_home/opengroupware/WebServer");
				system("cp 'ngobjweb_$version.so' $ogo_user_home'/opengroupware/WebServer'");
				system("chown '-R' 'opengroupware.skyrix' $ogo_user_home'/opengroupware/WebServer'");
				system("echo '$conf_text' > '$config_file'");
				chdir("../../../");
				system("service 'httpd' 'restart'");
				if (-e "/etc/init.d/opengroupware") {system("/etc/init.d/opengroupware 'restart'");}
				if ($args{m}) {exit 0;}
			}
		}
	}

	if (!$args{m} && !$args{g}) {
		print "Installing OpenGroupware...\n\n";
		my $cmd = join(' ', "rpm -U$vopts $fopt", @packages);
		if ($args{v} || $args{n}) {print "$cmd\n";}
		exit 0 if $args{n};
		chdir("$ogo_pkg_dir");
		my $code = system($cmd);
		chdir("../");
		if (-e "/etc/init.d/opengroupware") {system("/etc/init.d/opengroupware 'restart'");}
		exit $code;
	}
	if ($args{g}) {exit 0;}
}

if ($action eq "remove") {
	print "Removing OpenGroupware...\n\n";
	my $vopts = $args{v} ? "vv" : "v";
	my $rm_fopts = $args{f} ? " --nodeps" : "";
	my $rm  = $args{A} ? "apt-get remove" : "rpm -e$vopts$rm_fopts";
	my $cmd = join(' ', $rm, reverse @stems);
	if ($args{v} || $args{n}) {print "$cmd\n";}
	exit 0 if $args{n};
	exec($cmd);
}

# If we get here then there's an improper command line var. Echo Usage and exit.
print $usage;
exit 0;
