1 package Install; #assumes Install.pm
4 # Copyright 2000-2002 Katipo Communications
6 # This file is part of Koha.
8 # Koha is free software; you can redistribute it and/or modify it under the
9 # terms of the GNU General Public License as published by the Free Software
10 # Foundation; either version 2 of the License, or (at your option) any later
13 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License along with
18 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
19 # Suite 330, Boston, MA 02111-1307 USA
25 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
29 Install.pm - Perl module containing the bulk of the installation logic
33 The Install.pm module contains the bulk
34 of the code to do installation;
35 this code is used by installer.pl
36 to perform an actual installation.
38 =head2 Internal functions (not meant to be used outside of Install.pm)
44 # set the version for version checking
48 @EXPORT = qw( &checkperlmodules
52 &releasecandidatewarning
53 &getinstallationdirectories
70 $messages->{'WelcomeToKohaInstaller'
71 = heading('Welcome to the Koha Installer') . qq|...|;
73 The heading function takes one string, the text to be displayed as
74 the heading, and returns a formatted heading (currently formatted
75 in the "traditional Koha installer" style, i.e., surrounded by a
78 This reduces the likelihood of pod2man(1) etc. misinterpreting
79 a line of equal signs as POD directives.
85 my $n = length($s) + 4;
86 my $line = ('=' x $n) . "\n";
87 "\n$line= $s =\n$line\n";
91 $messages->{'continuing'}->{en}="Great! Continuing setup.\n\n";
92 $messages->{'WelcomeToKohaInstaller'}->{en} =
93 heading('Welcome to the Koha Installer') . qq|
94 Welcome to the Koha install script! This script will prompt you for some
95 basic information about your desired setup, then install Koha according to
96 your specifications. To accept the default value for any question, simply hit
99 Please be sure to read the documentation, or visit the Koha website at
100 http://www.koha.org for more information.
102 Are you ready to begin the installation? (Y/[N]): |;
103 $messages->{'ReleaseCandidateWarning'}->{en} =
104 heading('RELEASE CANDIDATE') . qq|
105 WARNING WARNING WARNING WARNING WARNING
107 You are about to install Koha version %s. This version of Koha is a
108 release candidate. It is not intended to be installed on production systems.
109 It is being released so that users can test it before we release a final
112 Are you sure you want to install Koha %s? (Y/[N]): |;
113 $messages->{'WatchForReleaseAnnouncements'}->{en}=qq|
115 Watch for announcements of Koha releases on the Koha mailing list or the Koha
116 web site (http://www.koha.org/).
120 $messages->{'NETZ3950Missing'}->{en}=qq|
122 The Net::Z3950 module is missing. This module is necessary if you want to use
123 Koha's Z39.50 client to download bibliographic records from other libraries.
124 To install this module, you will need the yaz client installed from
125 http://www.indexdata.dk/yaz/ and then you can install the perl module with the
128 perl -MCPAN -e 'install Net::Z3950'
130 Press the <ENTER> key to continue: |;
132 $messages->{'CheckingPerlModules'}->{en} = heading('PERL & MODULES') . qq|
133 Checking perl modules ...
136 $messages->{'PerlVersionFailure'}->{en}="Sorry, you need at least Perl %s\n";
138 $messages->{'MissingPerlModules'}->{en} = heading('MISSING PERL MODULES') . qq|
139 You are missing some Perl modules which are required by Koha.
140 Once these modules have been installed, rerun this installer.
141 They can be installed by running (as root) the following:
146 $messages->{'AllPerlModulesInstalled'}->{en} =
147 heading('ALL PERL MODULES INSTALLED') . qq|
148 All mandatory perl modules are installed.
150 Press <ENTER> to continue: |;
151 $messages->{'KohaVersionInstalled'}->{en}="You currently have Koha %s on your system.";
152 $messages->{'KohaUnknownVersionInstalled'}->{en}="I am not able to determine what version of Koha is installed now.";
153 $messages->{'KohaAlreadyInstalled'}->{en} =
154 heading('Koha already installed') . qq|
155 It looks like Koha is already installed on your system (%s/koha.conf exists
156 already). If you would like to upgrade your system to %s, please use
157 the koha.upgrade script in this directory.
162 $messages->{'GetOpacDir'}->{en} = heading('OPAC DIRECTORY') . qq|
163 Please supply the directory you want Koha to store its OPAC files in. This
164 directory will be auto-created for you if it doesn't exist.
166 OPAC Directory [%s]: |;
168 $messages->{'GetIntranetDir'}->{en} =
169 heading('INTRANET/LIBRARIANS DIRECTORY') . qq|
170 Please supply the directory you want Koha to store its Intranet/Librarians
171 files in. This directory will be auto-created for you if it doesn't exist.
173 Intranet Directory [%s]: |;
175 $messages->{'GetKohaLogDir'}->{en} = heading('KOHA LOG DIRECTORY') . qq|
176 Specify a log directory where any Koha daemons can create log files.
178 Koha Log Directory [%s]: |;
180 $messages->{'AuthenticationWarning'}->{en} = heading('Authentication') . qq|
181 This release of Koha has a new authentication module. If you are not already
182 using basic authentication on your intranet, you will be required to log in to
183 access some of the features of the intranet. You can log in using the userid
184 and password from the %s/koha.conf configuration file at any time. Use the
185 "Members" module to add passwords for other accounts and set their permissions.
187 Press the <ENTER> key to continue: |;
189 $messages->{'Completed'}->{en} = heading('KOHA INSTALLATION COMPLETE') . qq|
190 Congratulations ... your Koha installation is complete!
192 You will be able to connect to your Librarian interface at:
196 and the OPAC interface at :
200 Be sure to read the INSTALL, and Hints files.
202 For more information visit http://www.koha.org
204 Press <ENTER> to exit the installer: |;
206 sub releasecandidatewarning {
207 my $message=getmessage('ReleaseCandidateWarning', [$::newversion, $::newversion]);
208 my $answer=showmessage($message, 'yn', 'n');
210 if ($answer =~ /y/i) {
211 print getmessage('continuing');
213 my $message=getmessage('WatchForReleaseAnnouncements');
222 =head2 Miscellaneous utility functions
232 Does the equivalent of dirname(1). Given a path $path, return the
233 parent directory of $path (best guess), except when $path seems to
234 be the same as /, in which case $path itself is returned unchanged.
240 if ($path =~ /[^\/]/s) {
242 $path =~ s/\/+[^\/]+\/*$//s;
253 mkdir_parents $path, $mode;
255 Does the equivalent of mkdir -p, or mkdir --parents. Given a path $path,
256 create the directory $path, recursively creating any intermediate
257 directories. If $mode is given, the directory will be created with
260 WARNING: If $path already exists, mkdir_parents will just return
261 successfully (just like mkdir -p), whether the mode of $path conforms
262 to $mode or not. (This is the behaviour of the mkdir -p command.)
266 sub mkdir_parents ($;$) {
267 my($path, $mode) = @_;
268 my $ok = -d($path)? 1: defined $mode? mkdir($path, $mode): mkdir($path);
270 if (!$ok && $! == ENOENT) {
271 my $parent = dirname($path);
272 $ok = mkdir_parents($parent, $mode);
274 # retry and at the same time make sure that $! is set correctly
275 $ok = defined $mode? mkdir($path, $mode): mkdir($path);
282 =head2 Subtasks of doing an installation
288 =item checkabortedinstall
292 Assuming that Koha will be installed on a modern Unix with symlinks,
293 it is possible to code the installer so that aborted installs can be
294 detected. In case of such an event we can do our best to "roll back"
297 FIXME: The "roll back" is not complete!
301 sub checkabortedinstall () {
302 if (-l("$::etcdir/koha.conf")
303 && readlink("$::etcdir/koha.conf") =~ /\.tmp$/
306 I have detected that you tried to install Koha before, but the installation
307 was aborted. I will try to continue, but there might be problems if the
308 database is already created.
311 print "Please press <ENTER> to continue: ";
314 # Remove the symlink after the <STDIN>, so the user can back out
315 unlink "$::etcdir/koha.conf"
316 || die "Failed to remove incomplete $::etcdir/koha.conf: $!\n";
321 =item checkperlmodules
325 Test whether the version of Perl is new enough, whether Perl is
326 found at the expected location, and whether all required modules
331 sub checkperlmodules {
333 # Test for Perl and Modules
336 my $message = getmessage('CheckingPerlModules');
337 showmessage($message, 'none');
339 # FIXME: Perl 5.6 is BUGGY!!! IT SHOULD NOT BE USED in production!!!
340 unless (eval "require 5.006_000") {
341 die getmessage('PerlVersionFailure', ['5.6.0']);
345 unless (eval {require DBI}) { push @missing,"DBI" };
346 unless (eval {require Date::Manip}) { push @missing,"Date::Manip" };
347 unless (eval {require DBD::mysql}) { push @missing,"DBD::mysql" };
348 unless (eval {require HTML::Template}) { push @missing,"HTML::Template" };
349 unless (eval {require Set::Scalar}) { push @missing,"Set::Scalar" };
350 unless (eval {require Digest::MD5}) { push @missing,"Digest::MD5" };
351 unless (eval {require MARC::Record}) { push @missing,"MARC::Record" };
352 unless (eval {require Net::Z3950}) {
353 my $message = getmessage('NETZ3950Missing');
354 showmessage($message, 'PressEnter', '', 1);
356 push @missing, "Net::Z3950";
361 # Print out a list of any missing modules
366 foreach my $module (@missing) {
367 $missing.=" perl -MCPAN -e 'install \"$module\"'\n";
369 my $message=getmessage('MissingPerlModules', [$missing]);
370 showmessage($message, 'none');
373 showmessage(getmessage('AllPerlModulesInstalled'), 'PressEnter', '', 1);
377 unless (-x "/usr/bin/perl") {
378 my $realperl=`which perl`;
380 $realperl = showmessage(getmessage('NoUsrBinPerl'), 'none');
381 until (-x $realperl) {
382 $realperl=showmessage(getmessage('AskLocationOfPerlExecutable', $realperl), 'free', $realperl, 1);
384 my $response=showmessage(getmessage('ConfirmPerlExecutableSymlink', $realperl), 'yn', 'y', 1);
385 unless ($response eq 'n') {
386 system("ln -s $realperl /usr/bin/perl");
393 $messages->{'NoUsrBinPerl'}->{en} =
394 heading('Perl is not located in /usr/bin/perl') . qq|
395 The Koha perl scripts expect to find the perl executable in the /usr/bin
396 directory. It is not there on your system.
400 $messages->{'AskLocationOfPerlExecutable'}->{en}=qq|Location of Perl Executable: [%s]: |;
401 $messages->{'ConfirmPerlExecutableSymlink'}->{en}=qq|
402 The Koha scripts will _not_ work without a symlink from %s to /usr/bin/perl
404 May I create this symlink? ([Y]/N):
411 getmessage($msgid, $variables);
413 Gets a localized message (format string) with message id $msgid,
414 and, if an array reference of variables $variables is given,
415 substitutes variables in the format string with @$variables.
416 Returns the found message string, with variable substitutions
419 $msgid must be the message identifier corresponding to a defined
420 message string (a valid key to the $messages hash in the Installer
421 package). getmessage throws an exception if the message cannot be
427 my $messagename=shift;
429 my $message=$messages->{$messagename}->{$::language} || $messages->{$messagename}->{en} || "Error: No message named $messagename in Install.pm\n";
430 if (defined($variables)) {
431 $message=sprintf $message, @$variables;
438 showmessage($message, 'none');
439 showmessage($message, 'none', undef, $noclear);
441 $result = showmessage($message, 'yn');
442 $result = showmessage($message, 'yn', $defaultresponse);
443 $result = showmessage($message, 'yn', $defaultresponse, $noclear);
445 $result = showmessage($message, 'restrictchar CHARS');
446 $result = showmessage($message, 'free');
447 $result = showmessage($message, 'numerical');
448 $result = showmessage($message, 'email');
449 $result = showmessage($message, 'PressEnter');
451 Shows a message and optionally gets a response from the user.
453 The first two arguments, the message and the response type,
454 are mandatory. The message must be the actual string to
455 display. The caller is responsible for calling getmessage if
458 If a response type other than 'none' is specified, a third
459 argument, specifying the default value, is optional.
461 The screen is normally cleared before the message is displayed;
462 if a fourth argument is specified and is nonzero, this
463 screen-clearing is not done.
465 FIXME: If $noclear is not specified or specified as undef, we
466 just test it for a non-zero value without testing it for being
473 my $responsetype=shift;
474 my $defaultresponse=shift;
476 ($noclear) || (system('clear'));
477 if ($responsetype =~ /^yn$/) {
478 $responsetype='restrictchar yn';
482 if ($responsetype =~/^restrictchar (.*)/i) {
485 until ($options=~/$response/) {
486 ($defaultresponse) || ($defaultresponse=substr($options,0,1));
489 (length($response)) || ($response=$defaultresponse);
490 unless ($options=~/$response/) {
491 ($noclear) || (system('clear'));
492 print "Invalid Response. Choose from [$options].\n\n";
498 if ($responsetype =~/^free$/i) {
499 (defined($defaultresponse)) || ($defaultresponse='');
500 my $response=<STDIN>;
502 ($response) || ($response=$defaultresponse);
505 if ($responsetype =~/^numerical$/i) {
506 (defined($defaultresponse)) || ($defaultresponse='');
508 until ($response=~/^\d+$/) {
511 ($response) || ($response=$defaultresponse);
512 unless ($response=~/^\d+$/) {
513 ($noclear) || (system('clear'));
514 print "Invalid Response ($response). Response must be a number.\n\n";
520 if ($responsetype =~/^email$/i) {
521 (defined($defaultresponse)) || ($defaultresponse='');
523 until ($response=~/.*\@.*\..*/) {
526 ($response) || ($response=$defaultresponse);
527 unless ($response=~/.*\@.*\..*/) {
528 ($noclear) || (system('clear'));
529 print "Invalid Response ($response). Response must be a valid email address.\n\n";
535 if ($responsetype =~/^PressEnter$/i) {
539 if ($responsetype =~/^none$/i) {
545 sub getinstallationdirectories {
546 $::opacdir = '/usr/local/koha/opac';
547 $::intranetdir = '/usr/local/koha/intranet';
549 while ($getdirinfo) {
550 # Loop until opac directory and koha directory are different
551 my $message=getmessage('GetOpacDir', [$::opacdir]);
552 $::opacdir=showmessage($message, 'free', $::opacdir);
554 $message=getmessage('GetIntranetDir', [$::intranetdir]);
555 $::intranetdir=showmessage($message, 'free', $::intranetdir);
557 if ($::intranetdir eq $::opacdir) {
560 You must specify different directories for the OPAC and INTRANET files!
561 :: $::intranetdir :: $::opacdir ::
568 $::kohalogdir='/var/log/koha';
569 my $message=getmessage('GetKohaLogDir', [$::kohalogdir]);
570 $::kohalogdir=showmessage($message, 'free', $::kohalogdir);
573 # FIXME: Missing error handling for all mkdir calls here
574 unless ( -d $::intranetdir ) {
575 mkdir_parents (dirname($::intranetdir), 0775);
576 mkdir ($::intranetdir, 0770);
577 chown (oct(0), (getgrnam($::httpduser))[2], "$::intranetdir");
578 chmod (oct(770), "$::intranetdir");
580 mkdir_parents ("$::intranetdir/htdocs", 0750);
581 mkdir_parents ("$::intranetdir/cgi-bin", 0750);
582 mkdir_parents ("$::intranetdir/modules", 0750);
583 mkdir_parents ("$::intranetdir/scripts", 0750);
584 unless ( -d $::opacdir ) {
585 mkdir_parents (dirname($::opacdir), 0775);
586 mkdir ($::opacdir, 0770);
587 chown (oct(0), (getgrnam($::httpduser))[2], "$::opacdir");
588 chmod (oct(770), "$::opacdir");
590 mkdir_parents ("$::opacdir/htdocs", 0750);
591 mkdir_parents ("$::opacdir/cgi-bin", 0750);
594 unless ( -d $::kohalogdir ) {
595 mkdir_parents (dirname($::kohalogdir), 0775);
596 mkdir ($::kohalogdir, 0770);
597 chown (oct(0), (getgrnam($::httpduser))[2,3], "$::kohalogdir");
598 chmod (oct(770), "$::kohalogdir");
604 $messages->{'DatabaseName'}->{en} = heading('Name of MySQL database') . qq|
605 Please provide the name of the mysql database for your koha installation.
607 Database name [%s]: |;
609 $messages->{'DatabaseHost'}->{en} = heading('Database Host') . qq|
610 Please provide the hostname for mysql. Unless the database is located on
611 another machine this will be "localhost".
613 Database host [%s]: |;
615 $messages->{'DatabaseUser'}->{en} = heading('Database User') . qq|
616 Please provide the name of the user, who will have full administrative rights
617 to the %s database, when authenticating from %s.
619 This user will also be used to access Koha's INTRANET interface.
621 Database user [%s]: |;
623 $messages->{'DatabasePassword'}->{en} = heading('Database Password') . qq|
624 Please provide a good password for the user %s.
626 Database Password: |;
628 $messages->{'BlankPassword'}->{en} = heading('BLANK PASSWORD') . qq|
629 You must not use a blank password for your MySQL user!
631 Press <ENTER> to try again:
634 sub getdatabaseinfo {
637 $::hostname = 'localhost';
638 $::user = 'kohaadmin';
641 #Get the database name
643 my $message=getmessage('DatabaseName', [$::dbname]);
644 $::dbname=showmessage($message, 'free', $::dbname);
646 #Get the hostname for the database
648 $message=getmessage('DatabaseHost', [$::hostname]);
649 $::hostname=showmessage($message, 'free', $::hostname);
651 #Get the username for the database
653 $message=getmessage('DatabaseUser', [$::dbname, $::hostname, $::user]);
654 $::user=showmessage($message, 'free', $::user);
656 #Get the password for the database user
658 while ($::pass eq '') {
659 my $message=getmessage('DatabasePassword', [$::user]);
660 $::pass=showmessage($message, 'free', $::pass);
662 my $message=getmessage('BlankPassword');
663 showmessage($message,'PressEnter');
670 $messages->{'FoundMultipleApacheConfFiles'}->{en} =
671 heading('MULTIPLE APACHE CONFIG FILES') . qq|
672 I found more than one possible Apache configuration file:
676 Choose the correct file [1]: |;
678 $messages->{'NoApacheConfFiles'}->{en} =
679 heading('NO APACHE CONFIG FILE FOUND') . qq|
680 I was not able to find your Apache configuration file.
682 The file is usually called httpd.conf or apache.conf.
684 Please specify the location of your config file: |;
686 $messages->{'NotAFile'}->{en} = heading('FILE DOES NOT EXIST') . qq|
687 The file %s does not exist.
689 Please press <ENTER> to continue: |;
691 $messages->{'EnterApacheUser'}->{en} = heading('NEED APACHE USER') . qq|
692 I was not able to determine the user that Apache is running as. This
693 information is necessary in order to set the access privileges correctly on
694 %s/koha.conf. This user should be set in one of the Apache configuration
695 files using the "User" directive.
697 Enter the Apache userid: |;
699 $messages->{'InvalidUserid'}->{en} = heading('INVALID USERID') . qq|
700 The userid %s is not a valid userid on this system.
702 Press <ENTER> to continue: |;
705 my @confpossibilities;
707 foreach my $httpdconf (qw(/usr/local/apache/conf/httpd.conf
708 /usr/local/etc/apache/httpd.conf
709 /usr/local/etc/apache/apache.conf
710 /var/www/conf/httpd.conf
711 /etc/apache/conf/httpd.conf
712 /etc/apache/conf/apache.conf
713 /etc/apache-ssl/conf/apache.conf
714 /etc/apache-ssl/httpd.conf
715 /etc/httpd/conf/httpd.conf
716 /etc/httpd/httpd.conf)) {
717 if ( -f $httpdconf ) {
718 push @confpossibilities, $httpdconf;
722 if ($#confpossibilities==-1) {
723 my $message=getmessage('NoApacheConfFiles');
725 until (-f $::realhttpdconf) {
726 $choice=showmessage($message, "free", 1);
728 $::realhttpdconf=$choice;
730 showmessage(getmessage('NotAFile', [$choice]),'PressEnter', '', 1);
733 } elsif ($#confpossibilities>0) {
737 foreach (@confpossibilities) {
738 $conffiles.=" $counter: $_\n";
739 $options.="$counter";
742 my $message=getmessage('FoundMultipleApacheConfFiles', [$conffiles]);
743 my $choice=showmessage($message, "restrictchar $options", 1);
744 $::realhttpdconf=$confpossibilities[$choice-1];
746 $::realhttpdconf=$confpossibilities[0];
748 unless (open (HTTPDCONF, "<$::realhttpdconf")) {
749 warn "Insufficient privileges to open $::realhttpdconf for reading.\n";
753 while (<HTTPDCONF>) {
754 if (/^\s*User\s+"?([-\w]+)"?\s*$/) {
763 unless ($::httpduser) {
764 my $message=getmessage('EnterApacheUser', [$::etcdir]);
765 until (length($::httpduser) && getpwnam($::httpduser)) {
766 $::httpduser=showmessage($message, "free", '');
767 if (length($::httpduser)>0) {
768 unless (getpwnam($::httpduser)) {
769 my $message=getmessage('InvalidUserid', [$::httpduser]);
770 showmessage($message,'PressEnter');
775 print "AU: $::httpduser\n";
780 $messages->{'ApacheConfigIntroduction'}->{en} =
781 heading('APACHE CONFIGURATION') . qq|
782 Koha needs to setup your Apache configuration file for the
783 OPAC and LIBRARIAN virtual hosts. By default this installer
784 will do this by using one ip address and two different ports
785 for the virtual hosts. There are other ways to set this up,
786 and the installer will leave comments in httpd.conf detailing
787 what these other options are.
790 Press <ENTER> to continue: |;
792 $messages->{'GetVirtualHostEmail'}->{en} =
793 heading('WEB SERVER E-MAIL CONTACT') . qq|
794 Enter the e-mail address to be used as a contact for the virtual hosts (this
795 address is displayed if any errors are encountered).
797 E-mail contact [%s]: |;
799 $messages->{'GetServerName'}->{en} =
800 heading('WEB SERVER HOST NAME OR IP ADDRESS') . qq|
801 Please enter the domain name or ip address of your computer.
803 Host name or IP Address [%s]: |;
805 $messages->{'GetOpacPort'}->{en} = heading('OPAC VIRTUAL HOST PORT') . qq|
806 Please enter the port for your OPAC interface. This defaults to port 80, but
807 if you are already serving web content from this server, you should change it
808 to a different port (8000 might be a good choice).
810 Enter the OPAC Port [%s]: |;
812 $messages->{'GetIntranetPort'}->{en} =
813 heading('INTRANET VIRTUAL HOST PORT') . qq|
814 Please enter the port for your Intranet interface. This must be different from
817 Enter the Intranet Port [%s]: |;
820 sub getapachevhostinfo {
822 $::svr_admin = "webmaster\@$::domainname";
823 $::servername=`hostname`;
826 $::intranetport=8080;
828 showmessage(getmessage('ApacheConfigIntroduction'), 'PressEnter');
830 $::svr_admin=showmessage(getmessage('GetVirtualHostEmail', [$::svr_admin]), 'email', $::svr_admin);
831 $::servername=showmessage(getmessage('GetServerName', [$::servername]), 'free', $::servername);
834 $::opacport=showmessage(getmessage('GetOpacPort', [$::opacport]), 'numerical', $::opacport);
835 $::intranetport=showmessage(getmessage('GetIntranetPort', [$::opacport, $::intranetport]), 'numerical', $::intranetport);
839 $messages->{'StartUpdateApache'}->{en} =
840 heading('UPDATING APACHE CONFIGURATION') . qq|
841 Checking for modules that need to be loaded...
844 $messages->{'LoadingApacheModuleModEnv'}->{en}="Loading SetEnv Apache module.\n";
846 $messages->{'LoadingApacheModuleModInc'}->{en}="Loading Includes Apache module.\n";
848 $messages->{'ApacheConfigBackupFailed'}->{en} =
849 heading('APACHE CONFIGURATION BACKUP FAILED') . qq|
850 An error occurred while trying to make a backup copy of %s.
854 No changes will be made to the apache configuration file at this time.
856 Press <ENTER> to continue: |;
859 $messages->{'ApacheAlreadyConfigured'}->{en} =
860 heading('APACHE ALREADY CONFIGURED') . qq|
861 %s appears to already have an entry for Koha
862 Virtual Hosts. You may need to edit %s
863 f anything has changed since it was last set up. This
864 script will not attempt to modify an existing Koha apache
867 Press <ENTER> to continue: |;
869 sub updateapacheconf {
870 my $logfiledir=`grep ^ErrorLog "$::realhttpdconf"`;
874 $logfiledir=~m#ErrorLog (.*)/[^/]*$#
875 or die "Can't parse ErrorLog directive\n";
879 unless ($logfiledir) {
883 showmessage(getmessage('StartUpdateApache'), 'none');
887 my $includesmodule=0;
888 open HC, "<$::realhttpdconf";
890 if (/^\s*#\s*LoadModule env_module /) {
892 showmessage(getmessage('LoadingApacheModuleModEnv'));
895 if (/^\s*#\s*LoadModule includes_module /) {
897 showmessage(getmessage('LoadingApacheModuleModInc'));
899 if (/\s*LoadModule includes_module / ) {
906 $backupfailed=`cp -f $::realhttpdconf $::realhttpdconf\.prekoha`;
908 showmessage(getmessage('ApacheConfigBackupFailed', [$::realhttpdconf,$backupfailed ]), 'PressEnter');
912 if ($envmodule || $includesmodule) {
913 open HC, ">$::realhttpdconf";
920 if (`grep 'VirtualHost $::servername' "$::realhttpdconf"`) {
921 showmessage(getmessage('ApacheAlreadyConfigured', [$::realhttpdconf, $::realhttpdconf]), 'PressEnter');
924 my $includesdirectives='';
925 if ($includesmodule) {
926 $includesdirectives.="Options +Includes\n";
927 $includesdirectives.=" AddHandler server-parsed .html\n";
929 open(SITE,">>$::realhttpdconf") or warn "Insufficient priveleges to open $::realhttpdconf for writing.\n";
931 if ($::opacport != 80) {
932 $opaclisten="Listen $::opacport";
934 my $intranetlisten = '';
935 if ($::intranetport != 80) {
936 $intranetlisten="Listen $::intranetport";
940 # Ports to listen to for Koha
944 # NameVirtualHost is used by one of the optional configurations detailed below
946 #NameVirtualHost 11.22.33.44
948 # KOHA's OPAC Configuration
949 <VirtualHost $::servername\:$::opacport>
950 ServerAdmin $::svr_admin
951 DocumentRoot $::opacdir/htdocs
952 ServerName $::servername
953 ScriptAlias /cgi-bin/koha/ $::opacdir/cgi-bin/
954 ErrorLog $logfiledir/opac-error_log
955 TransferLog $logfiledir/opac-access_log
956 SetEnv PERL5LIB "$::intranetdir/modules"
960 # KOHA's INTRANET Configuration
961 <VirtualHost $::servername\:$::intranetport>
962 ServerAdmin $::svr_admin
963 DocumentRoot $::intranetdir/htdocs
964 ServerName $::servername
965 ScriptAlias /cgi-bin/koha/ "$::intranetdir/cgi-bin/"
966 ErrorLog $logfiledir/koha-error_log
967 TransferLog $logfiledir/koha-access_log
968 SetEnv PERL5LIB "$::intranetdir/modules"
972 # If you want to use name based Virtual Hosting:
973 # 1. remove the two Listen lines
974 # 2. replace $::servername\:$::opacport wih your.opac.domain.name
975 # 3. replace ServerName $::servername wih ServerName your.opac.domain.name
976 # 4. replace $::servername\:$::intranetport wih your intranet domain name
977 # 5. replace ServerName $::servername wih ServerName your.intranet.domain.name
979 # If you want to use NameVirtualHost'ing (using two names on one ip address):
980 # 1. Follow steps 1-5 above
981 # 2. Uncomment the NameVirtualHost line and set the correct ip address
989 $messages->{'IntranetAuthenticationQuestion'}->{en} =
990 heading('INTRANET AUTHENTICATION') . qq|
991 I can set it up so that the Intranet/Librarian site is password protected using
992 Apache's Basic Authorization.
994 This is going to be phased out very soon. However, setting this up can provide
995 an extra layer of security before the new authentication system is completely
998 Would you like to do this ([Y]/N): |;
1000 $messages->{'BasicAuthUsername'}->{en}="Please enter a userid for intranet access [%s]: ";
1001 $messages->{'BasicAuthPassword'}->{en}="Please enter a password for %s: ";
1002 $messages->{'BasicAuthPasswordWasBlank'}->{en}="\nYou cannot use a blank password!\n\n";
1004 sub basicauthentication {
1005 my $message=getmessage('IntranetAuthenticationQuestion');
1006 my $answer=showmessage($message, 'yn', 'y');
1008 my $apacheauthusername='librarian';
1009 my $apacheauthpassword='';
1010 if ($answer=~/^y/i) {
1011 ($apacheauthusername) = showmessage(getmessage('BasicAuthUsername', [ $apacheauthusername]), 'free', $apacheauthusername, 1);
1012 $apacheauthusername=~s/[^a-zA-Z0-9]//g;
1013 while (! $apacheauthpassword) {
1014 ($apacheauthpassword) = showmessage(getmessage('BasicAuthPassword', [ $apacheauthusername]), 'free', 1);
1015 if (!$apacheauthpassword) {
1016 ($apacheauthpassword) = showmessage(getmessage('BasicAuthPasswordWasBlank'), 'none', '', 1);
1019 open AUTH, ">$::etcdir/kohaintranet.pass";
1020 my $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
1021 my $salt=substr($chars, int(rand(length($chars))),1);
1022 $salt.=substr($chars, int(rand(length($chars))),1);
1023 print AUTH $apacheauthusername.":".crypt($apacheauthpassword, $salt)."\n";
1025 open(SITE,">>$::realhttpdconf") or warn "Insufficient priveleges to open $::realhttpdconf for writing.\n";
1028 <Directory $::intranetdir>
1029 AuthUserFile $::etcdir/kohaintranet.pass
1031 AuthName "Koha Intranet (for librarians only)"
1039 $messages->{'InstallFiles'}->{en} = heading('INSTALLING FILES') . qq|
1040 Copying files to installation directories:
1045 $messages->{'CopyingFiles'}->{en}="Copying %s to %s.\n";
1052 showmessage(getmessage('InstallFiles'),'none');
1053 print getmessage('CopyingFiles', ['intranet-html', "$::intranetdir/htdocs" ]);
1054 system("cp -R intranet-html/* $::intranetdir/htdocs/");
1055 print getmessage('CopyingFiles', ['intranet-cgi', "$::intranetdir/cgi-bin" ]);
1056 system("cp -R intranet-cgi/* $::intranetdir/cgi-bin/");
1057 print getmessage('CopyingFiles', ['stand-alone scripts', "$::intranetdir/scripts" ]);
1058 system("cp -R scripts/* $::intranetdir/scripts/");
1059 print getmessage('CopyingFiles', ['perl modules', "$::intranetdir/modules" ]);
1060 system("cp -R modules/* $::intranetdir/modules/");
1061 print getmessage('CopyingFiles', ['opac-html', "$::opacdir/htdocs" ]);
1062 system("cp -R opac-html/* $::opacdir/htdocs/");
1063 print getmessage('CopyingFiles', ['opac-cgi', "$::opacdir/cgi-bin" ]);
1064 system("cp -R opac-cgi/* $::opacdir/cgi-bin/");
1065 system("touch $::opacdir/cgi-bin/opac");
1067 system("chown -R root:$::httpduser $::opacdir");
1068 system("chown -R root:$::httpduser $::intranetdir");
1070 # Create /etc/koha.conf
1072 my $old_umask = umask(027); # make sure koha.conf is never world-readable
1073 open(SITES,">$::etcdir/koha.conf.tmp") or warn "Couldn't create file at $::etcdir. Must have write capability.\n";
1076 hostname=$::hostname
1079 includes=$::opacdir/htdocs/includes
1080 intranetdir=$::intranetdir
1082 kohalogdir=$::kohalogdir
1083 kohaversion=$::kohaversion
1084 httpduser=$::httpduser
1085 intrahtdocs=$::intranetdir/htdocs/intranet-tmpl
1086 opachtdocs=$::opacdir/htdocs/opac-tmpl
1091 chown((getpwnam($::httpduser)) [2,3], "$::etcdir/koha.conf.tmp") or warn "can't chown koha.conf: $!";
1092 chmod 0440, "$::etcdir/koha.conf.tmp";
1094 chmod 0750, "$::intranetdir/scripts/z3950daemon/z3950-daemon-launch.sh";
1095 chmod 0750, "$::intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh";
1096 chmod 0750, "$::intranetdir/scripts/z3950daemon/processz3950queue";
1097 chown(0, (getpwnam($::httpduser)) [3], "$::intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh") or warn "can't chown $::intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh: $!";
1098 chown(0, (getpwnam($::httpduser)) [3], "$::intranetdir/scripts/z3950daemon/processz3950queue") or warn "can't chown $::intranetdir/scripts/z3950daemon/processz3950queue: $!";
1102 $messages->{'MysqlRootPassword'}->{en} =
1103 heading('MYSQL ROOT USER PASSWORD') . qq|
1104 To allow us to create the koha database please supply your
1105 mysql server's root user password:
1107 Enter MySQL root user password: |;
1109 $messages->{'InvalidMysqlRootPassword'}->{en}="Invalid Password. Please try again.";
1111 $messages->{'CreatingDatabase'}->{en} = heading('CREATING DATABASE') . qq|
1112 Creating the MySQL database for Koha...
1116 $messages->{'CreatingDatabaseError'}->{en} =
1117 heading('ERROR CREATING DATABASE') . qq|
1118 Couldn't connect to the MySQL server for the reason given above.
1119 This is a serious problem, the database will not get installed.
\a
1121 Press <ENTER> to continue: |;
1123 $messages->{'SampleData'}->{en} = heading('SAMPLE DATA') . qq|
1124 If you are installing Koha for evaluation purposes, I have a batch of sample
1125 data that you can install now.
1127 If you are installing Koha with the intention of populating it with your own
1128 data, you probably don't want this sample data installed.
1130 Would you like to install the sample data? Y/[N]: |;
1132 $messages->{'SampleDataInstalled'}->{en} =
1133 heading('SAMPLE DATA INSTALLED') . qq|
1134 Sample data has been installed. For some suggestions on testing Koha, please
1135 read the file doc/HOWTO-Testing. If you find any bugs, please submit them at
1136 http://bugs.koha.org/. If you need help with testing Koha, you can post a
1137 question through the koha-devel mailing list, or you can check for a developer
1138 online at +irc.katipo.co.nz:6667 channel #koha.
1140 You can find instructions for subscribing to the Koha mailing lists at:
1145 Press <ENTER> to continue: |;
1147 $messages->{'AddBranchPrinter'}->{en} = heading('Add Branch and Printer') . qq|
1148 Would you like to install an initial branch and printer? [Y]/N: |;
1150 $messages->{'BranchName'}->{en}="Branch Name [%s]: ";
1151 $messages->{'BranchCode'}->{en}="Branch Code (4 letters or numbers) [%s]: ";
1152 $messages->{'PrinterQueue'}->{en}="Printer Queue [%s]: ";
1153 $messages->{'PrinterName'}->{en}="Printer Name [%s]: ";
1154 $messages->{'BlankMysqlPassword'}->{en} = heading('Blank MySQL Password') . qq|
1155 Do not leave your MySQL root password blank unless you know exactly what you
1156 are doing. To change your MySQL root password use the mysqladmin command:
1158 mysqladmin password NEWPASSWORDHERE
1160 Press <ENTER> to continue:
1164 $::mysqluser = 'root';
1167 foreach my $mysql (qw(/usr/local/mysql
1171 if ( -d $mysql && -f "$mysql/bin/mysqladmin") {
1176 print "I don't see mysql in the usual places.\n";
1178 print "Where have you installed mysql? ";
1179 chomp($::mysqldir = <STDIN>);
1180 last if -f "$::mysqldir/bin/mysqladmin";
1183 I can't find it there either. If you compiled mysql yourself,
1184 please give the value of --prefix when you ran configure.
1186 The file mysqladmin should be in bin/mysqladmin under the directory that you
1195 while ($needpassword) {
1196 $::mysqlpass=showmessage(getmessage('MysqlRootPassword'), 'free');
1197 $::mysqlpass_quoted = $::mysqlpass;
1198 $::mysqlpass_quoted =~ s/"/\\"/g;
1199 $::mysqlpass_quoted="-p\"$::mysqlpass_quoted\"";
1200 $::mysqlpass eq '' and $::mysqlpass_quoted='';
1201 my $result=system("$::mysqldir/bin/mysqladmin -u$::mysqluser $::mysqlpass_quoted proc > /dev/null 2>&1");
1203 print getmessage('InvalidMysqlRootPassword');
1205 if ($::mysqlpass eq '') {
1206 showmessage(getmessage('BlankMysqlPassword'), 'PressEnter');
1212 showmessage(getmessage('CreatingDatabase'),'none');
1214 my $result=system("$::mysqldir/bin/mysqladmin", "-u$::mysqluser", "-p$::mysqlpass", "create", "$::dbname");
1216 showmessage(getmessage('CreatingDatabaseError'),'PressEnter', '', 1);
1218 # Populate the Koha database
1219 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname < koha.mysql");
1220 # Set up permissions
1221 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted mysql -e \"insert into user (Host,User,Password) values ('$::hostname','$::user',password('$::pass'))\"\;");
1222 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted mysql -e \"insert into db (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv, index_priv, alter_priv) values ('%','$::dbname','$::user','Y','Y','Y','Y','Y','Y','Y','Y')\"");
1223 system("$::mysqldir/bin/mysqladmin -u$::mysqluser $::mysqlpass_quoted reload");
1233 $messages->{'UpdateMarcTables'}->{en} =
1234 heading('UPDATING MARC FIELD DEFINITION TABLES') . qq|
1235 You can import marc parameters for :
1241 Please choose which parameter you want to install. Note if you choose 3,
1242 nothing will be added, and it can be a BIG job to manually create those tables
1244 Choose MARC definition [1]: |;
1246 $messages->{'Language'}->{en} = heading('CHOOSE LANGUAGES') . qq|
1247 This version of koha supports a few languages.
1248 Enter you languages preferences : either en, fr, es or pl.
1249 Note that the en is always choosen when the system does not finds the
1250 language you choose in a specific screen.
1251 fr : opac is translated (except pictures)
1252 es : a few intranet is translated (including pictures)
1253 pl : opac is translated (UNTESTED in this release)
1256 sub updatedatabase {
1257 # At this point, $::etcdir/koha.conf must exist, for C4::Context
1258 # We must somehow temporarily enable $::etcdir/koha.conf. A symlink can
1259 # do this & at the same time facilitate detection of aborted installs.
1260 my $result=system ("perl -I $::intranetdir/modules scripts/updater/updatedatabase");
1262 print "Problem updating database...\n";
1266 my $response=showmessage(getmessage('UpdateMarcTables'), 'restrictchar 123', '1');
1268 if ($response == 1) {
1269 system("cat scripts/misc/marc_datas/marc21_en/structure_def.sql | $::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname");
1271 if ($response == 2) {
1272 system("cat scripts/misc/marc_datas/unimarc_fr/structure_def.sql | $::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname");
1273 system("cat scripts/misc/lang-datas/fr/stopwords.sql | $::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname");
1276 $result = system ("perl -I $::intranetdir/modules scripts/marc/updatedb2marc.pl");
1278 print "Problem updating database to MARC...\n";
1282 print "\n\nFinished updating of database. Press <ENTER> to continue...";
1286 sub populatedatabase {
1287 my $response=showmessage(getmessage('SampleData'), 'yn', 'n');
1288 if ($response =~/^y/i) {
1289 system("gunzip -d < sampledata-1.2.gz | $::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname");
1290 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branches (branchcode,branchname,issuing) values ('MAIN', 'Main Library', 1)\"");
1291 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'IS')\"");
1292 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'CU')\"");
1293 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into printers (printername,printqueue,printtype) values ('Circulation Desk Printer', 'lp', 'hp')\"");
1294 showmessage(getmessage('SampleDataInstalled'), 'PressEnter','',1);
1297 my $response=showmessage(getmessage('AddBranchPrinter'), 'yn', 'y');
1299 unless ($response =~/^n/i) {
1300 my $branch='Main Library';
1301 $branch=showmessage(getmessage('BranchName', [$branch]), 'free', $branch, 1);
1302 $branch=~s/[^A-Za-z0-9\s]//g;
1304 my $branchcode=$branch;
1305 $branchcode=~s/[^A-Za-z0-9]//g;
1306 $branchcode=uc($branchcode);
1307 $branchcode=substr($branchcode,0,4);
1308 $branchcode=showmessage(getmessage('BranchCode', [$branchcode]), 'free', $branchcode, 1);
1309 $branchcode=~s/[^A-Za-z0-9]//g;
1310 $branchcode=uc($branchcode);
1311 $branchcode=substr($branchcode,0,4);
1312 $branchcode or $branchcode='DEF';
1314 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branches (branchcode,branchname,issuing) values ('$branchcode', '$branch', 1)\"");
1315 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'IS')\"");
1316 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'CU')\"");
1318 my $printername='Library Printer';
1319 $printername=showmessage(getmessage('PrinterName', [$printername]), 'free', $printername, 1);
1320 $printername=~s/[^A-Za-z0-9\s]//g;
1322 my $printerqueue='lp';
1323 $printerqueue=showmessage(getmessage('PrinterQueue', [$printerqueue]), 'free', $printerqueue, 1);
1324 $printerqueue=~s/[^A-Za-z0-9]//g;
1325 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into printers (printername,printqueue,printtype) values ('$printername', '$printerqueue', '')\"");
1327 my $language=showmessage(getmessage('Language'), 'free', 'en');
1328 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"update systempreferences set value='$language' where variable='opaclanguages'\"");
1332 $messages->{'RestartApache'}->{en} = heading('RESTART APACHE') . qq|
1333 Apache needs to be restarted to load the new configuration for Koha.
1335 Would you like to restart Apache now? [Y]/N: |;
1339 my $response=showmessage(getmessage('RestartApache'), 'yn', 'y');
1343 unless ($response=~/^n/i) {
1344 # Need to support other init structures here?
1345 if (-e "/etc/rc.d/init.d/httpd") {
1346 system('/etc/rc.d/init.d/httpd restart');
1347 } elsif (-e "/etc/init.d/apache") {
1348 system('/etc//init.d/apache restart');
1349 } elsif (-e "/etc/init.d/apache-ssl") {
1350 system('/etc/init.d/apache-ssl restart');
1357 sub loadconfigfile {
1360 open (KC, "<$::etcdir/koha.conf");
1363 (next) if (/^\s*#/);
1364 if (/(.*)\s*=\s*(.*)/) {
1367 # Clean up white space at beginning and end
1368 $variable=~s/^\s*//g;
1369 $variable=~s/\s*$//g;
1372 $configfile{$variable}=$value;
1376 $::intranetdir=$configfile{'intranetdir'};
1377 $::opacdir=$configfile{'opacdir'};
1378 $::kohaversion=$configfile{'kohaversion'};
1379 $::kohalogdir=$configfile{'kohalogdir'};
1380 $::database=$configfile{'database'};
1381 $::hostname=$configfile{'hostname'};
1382 $::user=$configfile{'user'};
1383 $::pass=$configfile{'pass'};
1386 END { } # module clean-up code here (global destructor)