#!/usr/bin/perl -w -I/opt/ep2stable/perl_lib

######################################################################
#
#  This file is part of GNU EPrints 2.
#  
#  Copyright (c) 2000-2004 University of Southampton, UK. SO17 1BJ.
#  
#  EPrints 2 is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#  
#  EPrints 2 is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  
#  You should have received a copy of the GNU General Public License
#  along with EPrints 2; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
######################################################################

=pod

=head1 NAME

B<generate_apacheconf> - Create the apache config files needed for EPrints

=head1 SYNOPSIS

B<generate_apacheconf> [B<options>] 

=head1 DESCRIPTION

This script generates the apache config files which will be used by EPrints. In the simple case all you need to do is run this script then add a line to your main apache configuration file - often, but not always, B</usr/local/apache/conf/httpd.conf>

 Include /opt/eprints2/cfg/apache.conf

Or elsewhere if you installed EPrints somewhere other than /opt/eprints2. This file then uses the "Include" directive to include all relevant apache config files from this EPrints installation.

By default the virtualhost directives are

 VirtualHost *

But the * can be changed to something different by editing the C<virtualhost> option in SystemSettings.pm

=head1 ARGUMENTS

=over 8

=back

=head1 OPTIONS

=over 8

=item B<--help>

Print a brief help message and exit.

=item B<--man>

Print the full manual page and then exit.

=item B<--quiet>

Be vewwy vewwy quiet. This option will supress all output unless an error occurs.

=item B<--verbose>

Explain in detail what is going on.
May be repeated for greater effect.

=item B<--version>

Output version information and exit.

=back   

=head1 FILES

=over 4

=item B<EPRINTS/cfg/apache.conf>

This file is not updated if it already exists, so you can add system-wide
apache configuration directives here. By default it just includes the two other system wide files: auto-apache-includes.conf and auto-apache.conf

=item B<EPRINTS/cfg/auto-apache-includes.conf>

This file is updated with Include lines to each of the archive specific apache config files. This file should not be edited by hand,

=item B<EPRINTS/cfg/auto-apache.conf>

This file contains the system wide apache directives required by EPrints. This file should not be edited by hand.

=item B<EPRINTS/archives/ARCHIVEDIR/cfg/apache.conf>

This file is not updated if it already exists, so you can add archive-specific
apache configuration directives here. By default it just includes the automatically generated archive specific file: auto-apache.conf

=item B<EPRINTS/archives/ARCHIVEDIR/cfg/auto-apache.conf>

This file contains all the configuration directives needed for an archive. This is where the bulk of the configuration appears, the clever stuff, if you will. This file should not be edited by hand.

=item B<EPRINTS/archives/ARCHIVEDIR/cfg/apachevhost.conf>

This file is not updated if it already exists, it is included into the virutalhost in auto-apache.conf so that you can a couple of additional directives if you need to. For example, redirects or additional log directives.

=back

=head1 AUTHOR

This is part of this EPrints 2 system. EPrints 2 is developed by Christopher Gutteridge.

=head1 VERSION

EPrints Version: 2.3.7.99.1-beta

=head1 CONTACT

For more information goto B<http://www.eprints.org/> which give information on mailing lists and the like.

Chris Gutteridge may be contacted at B<support@eprints.org>

Should you need a real world address for some reason, EPrints can be contacted in the real world at

 EPrints c/o Christopher Gutteridge
 Department of Electronics and Computer Science
 University of Southampton
 SO17 1BJ
 United Kingdom

=head1 COPYRIGHT

This file is part of GNU EPrints 2.

Copyright (c) 2000-2004 University of Southampton, UK. SO17 1BJ.

EPrints 2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

EPrints 2 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with EPrints 2; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

=cut


use EPrints::Archive;
use EPrints::Config;
use strict;

use strict;
use Getopt::Long;
use Pod::Usage;

my $version = 0;
my $verbose = 0;
my $quiet = 0;
my $help = 0;
my $man = 0;

GetOptions( 
	'help|?' => \$help,
	'man' => \$man,
	'version' => \$version,
	'verbose+' => \$verbose,
	'silent' => \$quiet,
	'quiet' => \$quiet
) || pod2usage( 2 );
EPrints::Utils::cmd_version( "generate_apacheconf" ) if $version;
pod2usage( 1 ) if $help;
pod2usage( -exitstatus => 0, -verbose => 2 ) if $man;
pod2usage( 2 ) if( scalar @ARGV != 0 ); 

our $noise = 1;
$noise = 0 if( $quiet );
$noise = 1+$verbose if( $verbose );

#cjg Write a more simple conf if only one language involved?

# Set STDOUT to auto flush (without needing a \n)
$|=1;

my $site_sysfile = EPrints::Config::get( "sys_path" )."/auto-apache.conf";
my $site_incfile = EPrints::Config::get( "sys_path" )."/auto-apache-includes.conf";
my $site_userfile = EPrints::Config::get( "cfg_path" )."/apache.conf";

print "Creating system wide apache conf files.\n" if( $noise >= 1 );
unless( -e $site_userfile )
{
	print "Creating $site_userfile\n" if( $noise >= 2 );
	open( CONF, ">$site_userfile" ) || die "Can't write to $site_userfile";
	print CONF <<END;
#
# apache.conf include file for EPrints
#
# If this file exists then it will not be over written by
#
# Put your own extra directives for this site here
#
# Comment out the "Include" lines if you don't want to use the
# autogenerated config for this archive.
#

# Include list of 'Include's for each archive
Include $site_incfile

# Include autogenerate apache.conf elements
Include $site_sysfile




END
	close CONF;
}
else
{
	print "$site_userfile already exists.\n" if( $noise >= 2 );
}

my $virtualhost = EPrints::Config::get( "virtualhost" );
if( !EPrints::Utils::is_set( $virtualhost ) )
{
	$virtualhost = '*';
}

print "Creating $site_sysfile\n" if( $noise >= 2 );
my $startupfile = EPrints::Config::get( "bin_path" )."/startup.pl";
open( CONF, ">$site_sysfile" ) || die "Can't write to $site_sysfile";
print CONF <<END;
#
# auto-apache.conf include file for EPrints
#
# DO NOT EDIT, this file is created by bin/generate_apacheconf
# and may be overwritten. To modify, change the archive configuration
# and re-run: bin/generate_apacheconf
#

NameVirtualHost $virtualhost

# Load the perl modules & archive configurations
PerlRequire $startupfile

END

my $av =  $EPrints::SystemSettings::conf->{apache};
if( defined $av && $av eq "2" )
{
	# apache 2
	print CONF <<END;
# Makes the request object accessable for other objects
# (apache 2.0 only)
PerlOptions +GlobalRequest

END
}
close CONF;

########################################

print "Creating $site_incfile\n" if( $noise >= 2 );
open( CONF, ">$site_incfile" ) || die "Can't write to $site_incfile";
print CONF <<END;
#
# auto-apache-includes.conf include file for EPrints
#
# DO NOT EDIT, this file is created by bin/generate_apacheconf
# and may be overwritten. To modify, change the archive configuration
# and re-run: bin/generate_apacheconf
#
# List of files to include for archive specific config...

END
foreach my $archiveid ( EPrints::Config::get_archive_ids() )
{
	my $archive_config = EPrints::Config::get_archive_config( $archiveid );
	my $archive_inc = $archive_config->{archiveroot}."/cfg/apache.conf";
	print CONF <<END;
# $archiveid
Include $archive_inc

END
}
close CONF;








########################################F#N#O#R#D########
# 
#   Write apache conf files for each archive
#
########################################F#N#O#R#D########

my $secureconfigs = {};
foreach my $archiveid ( EPrints::Config::get_archive_ids() )
{


my $archive = EPrints::Archive->new_archive_by_id( $archiveid, 1 );
exit( 1 ) unless( defined $archive );

my $sysfile = $archive->get_conf( "config_path" )."/auto-apache.conf";
my $userfile = $archive->get_conf( "config_path" )."/apache.conf";
my $vhostfile = $archive->get_conf( "config_path" )."/apachevhost.conf";

my $id = $archive->get_id();

print "Creating apache conf files for archive $archiveid\n" if( $noise >= 1 );
unless( -e $userfile )
{
	print "Creating $userfile\n" if( $noise >= 2 );
	open( CONF, ">$userfile" ) || die "Can't write to $userfile";
	print CONF <<END;
#
# apache.conf include file for $id
#
# If this file exists then it will not be over written by
# the generate_apacheconf command.
#
# Put your own extra directives for this site here
#
# Comment out the "Include" line if you don't want to use the
# autogenerated config for this archive.
#

Include $sysfile
END
}
else
{
	print "$userfile already exists.\n" if( $noise >= 2 );
}


unless( -e $vhostfile )
{
	print "Creating $vhostfile\n" if( $noise >= 2 );
	open( CONF, ">$vhostfile" ) || die "Can't write to $vhostfile";
	print CONF <<END;
#
# apachevhost.conf include file for $id
#
# If this file exists then it will not be over written by
# the generate_apacheconf command.
#
# Directives in this file are interpreted inside the virtualhost 
# configuration for this archive.
#


END
}
else
{
	print "$vhostfile already exists.\n" if( $noise >= 2 );
}


my $cgidir = EPrints::Config::get( "cgi_path" );
my $adminemail = $archive->get_conf( "adminemail" );
my $htdocs_path = $archive->get_conf( "htdocs_path" );
my $htdocs_secure_path = $archive->get_conf( "htdocs_secure_path" );
my $host = $archive->get_conf( "host" );
my $urlpath = $archive->get_conf( "urlpath" );
my $userhome = $archive->get_conf( "userhome" );
my $securehost = $archive->get_conf( "securehost" );
my $securepath = '';
if( EPrints::Utils::is_set( $securehost ) )
{
	$securepath = $archive->get_conf( "securepath" );
}


print "Creating $sysfile\n" if( $noise >= 2 );
open( CONF, ">$sysfile" ) || die "Can't write to $sysfile";
print CONF <<END;
#
# auto-apache.conf include file for $id
#
# DO NOT EDIT, this file is created by bin/generate_apacheconf
# and may be overwritten. To modify, change the archive configuration
# and re-run: bin/generate_apacheconf $id
#

END
my $aliasinfo;
my $aliases = "";
foreach $aliasinfo ( @{$archive->get_conf( "aliases" )} )
{
	if( $aliasinfo->{redirect} )
	{
		my $vname = $aliasinfo->{name};
		print CONF <<END;

# Redirect to the correct hostname
<VirtualHost $virtualhost>
  ServerName $vname
  Redirect / http://$host/
</VirtualHost>
END
	}
	else
	{
		$aliases.="  ServerAlias ".$aliasinfo->{name}."\n";
	}
}
print CONF <<END;

# The main virtual host for this archive
<VirtualHost $virtualhost>
  ServerName $host
$aliases
  ServerAdmin $adminemail

  # Include this here, so that it's rules come first.
  Include $vhostfile

END

# If we want to use the non-perl CGI script mimetex.cgi we need to 
# insert the script alias here.
if( $archive->get_conf( "use_mimetex" ) ) 
{
	if( !defined $EPrints::SystemSettings::conf->{executables}->{mimetex} )
	{
		EPrints::Config::abort( "use_mimetex is set to true but\n\$EPrints::SystemSettings::conf->{executables}->{mimetex}\nis not set." );
	}
	if( !-e $EPrints::SystemSettings::conf->{executables}->{mimetex} )
	{
		EPrints::Config::abort( "use_mimetex is set to true but\n\$EPrints::SystemSettings::conf->{executables}->{mimetex}\nis set to a non existant file." );
	}
	     
	print CONF '  ScriptAlias '.$urlpath.'/cgi/mimetex.cgi '.$EPrints::SystemSettings::conf->{executables}->{mimetex}."\n\n";
}

print CONF <<END;
  Alias $urlpath/perl $cgidir
  Alias $urlpath/ $htdocs_path/

  <Location "$urlpath">
    ErrorDocument 401 $urlpath/error401.html
    ErrorDocument 404 $urlpath/perl/handle_404
    PerlSetVar EPrints_ArchiveID $archiveid
  </Location>

  # Note that PerlTransHandler can't go inside
  # a "Location" block as it occurs before the
  # Location is known.
  PerlTransHandler EPrints::Rewrite
END

my @langs = @{$archive->get_conf( "languages" )};

#my $defaultlang = $archive->get_conf( "defaultlanguage" );
# cjg remove this stuff later.
#
#foreach my $langid ( @langs )
#{
	#next if( $langid eq $defaultlang );
		#print CONF <<END;
  #RewriteCond %{HTTP_COOKIE}   lang=$langid
  #RewriteRule ^/(.*)\$         /$langid/\$1   [L]
#
#END
#}
#
#print CONF <<END;
  ## Default Language
  #RewriteRule ^/(.*)\$         /$defaultlang/\$1   [L]
#
#END


if( $archive->get_conf( "vlit" )->{enable} )
{
	foreach my $langid ( @langs )
	{
		print CONF <<END;
  <Directory "$htdocs_path/$langid/archive">
    SetHandler perl-script
    PerlHandler EPrints::VLit::handler
  </Directory>

END
	}
}

my $registry_module;
if( $av eq "1" ) 
{
	$registry_module = "Apache::Registry";
}
else # apache 2
{
	$registry_module = "ModPerl::Registry";
}

print CONF <<END;
  <Directory "$htdocs_path">
    AddType 'text/html; charset=UTF-8' .html
  </Directory>

  <Directory "$cgidir">
    SetHandler perl-script
    PerlHandler $registry_module
    PerlSendHeader Off
    Options ExecCGI FollowSymLinks
  </Directory>

END

my $secureconfig = <<END;
  <Directory "$cgidir/users">
    AuthName "User Area"
    AuthType "Basic"
    PerlAuthenHandler EPrints::Auth::authen
    PerlAuthzHandler EPrints::Auth::authz
    PerlSetVar EPrints_Security_Area User
    require valid-user

    SetHandler perl-script
    PerlHandler $registry_module
    PerlSendHeader Off
    Options ExecCGI FollowSymLinks
  </Directory>
  <Directory "$cgidir/users/awstats">
    PerlSendHeader On
  </Directory>

  <Directory "$htdocs_secure_path">
    AuthName "Secure Document Area"
    AuthType "Basic"
    PerlAuthenHandler EPrints::Auth::authen
    PerlAuthzHandler EPrints::Auth::authz
    PerlSetVar EPrints_Security_Area Documents
    require valid-user
  </Directory>

  # This sets up the change_user URL, which does
  # not have a REAL file associated with it, it
  # forces the browser to fail to register the
  # current user as a valid user, and thus ask
  # for re-validation.
  <Location "$securepath/change_user">
    AuthName "User Area"
    AuthType "Basic"
    PerlAuthenHandler EPrints::Auth::authen
    PerlAuthzHandler EPrints::Auth::authz
    PerlSetVar EPrints_Security_Area ChangeUser
    require valid-user
    Redirect $securepath/change_user $userhome
  </Location>

END

if( EPrints::Utils::is_set( $securehost ) )
{
#cjg MUST BE HTTPS!
	my $securebase = "http://".$securehost.$securepath;
	print CONF <<END;
  Redirect /secure/ $securebase/secure/
  Redirect /perl/users/ $securebase/perl/users/
  Redirect /change_user $securebase/change_user

END
	# cjg =- 404 & 401 handlers?
	$secureconfigs->{$securehost} .= <<END;
##### CONFIG FOR $archiveid

$secureconfig

  Alias $securepath/secure/ $htdocs_secure_path/
  Alias $securepath/perl/users/ $cgidir/users/

  #RewriteRule ^$securepath/secure/([0-9]+)([0-9][0-9])([0-9][0-9])([0-9][0-9])/(.*)\$ $securepath/secure/\$1/\$2/\$3/\$4/\$5 [L]

##### END OF CONFIG FOR $archiveid

END
}
else
{
	print CONF $secureconfig;
}

print CONF <<END;

</VirtualHost>

END

close CONF;
}

foreach( keys %{$secureconfigs} )
{
	my $secfile = EPrints::Config::get( "sys_path" )."/auto-".$_.".conf";
	print "Making include block for $_\n" if( $noise >= 1 );

	open( CONF, ">$secfile" ) || die "Can't write $secfile";
	print CONF $secureconfigs->{$_};
	close CONF;
}

print "\nDo not forget to stop and restart apache to cause changes to take effect!\n" if( $noise >= 1 );

print "Exiting normally.\n" if( $noise >= 2 );
exit;

