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 Checks whether a previous installation process has been abnormally
293 aborted, by checking whether $::etcidr/koha.conf is a symlink or not.
294 If an aborted installation is detected, gives the user a chance to
295 abort, before trying to recover the aborted installation.
297 Assuming that Koha will be installed on a modern Unix with symlinks,
298 it is possible to code the installer so that aborted installs can be
299 detected. In case of such an event we can do our best to "roll back"
302 FIXME: The "roll back" is not complete!
306 sub checkabortedinstall () {
307 if (-l("$::etcdir/koha.conf")
308 && readlink("$::etcdir/koha.conf") =~ /\.tmp$/
311 I have detected that you tried to install Koha before, but the installation
312 was aborted. I will try to continue, but there might be problems if the
313 database is already created.
316 print "Please press <ENTER> to continue: ";
319 # Remove the symlink after the <STDIN>, so the user can back out
320 unlink "$::etcdir/koha.conf"
321 || die "Failed to remove incomplete $::etcdir/koha.conf: $!\n";
326 =item checkperlmodules
330 Test whether the version of Perl is new enough, whether Perl is
331 found at the expected location, and whether all required modules
336 sub checkperlmodules {
338 # Test for Perl and Modules
341 my $message = getmessage('CheckingPerlModules');
342 showmessage($message, 'none');
344 # FIXME: Perl 5.6 is BUGGY!!! IT SHOULD NOT BE USED in production!!!
345 unless (eval "require 5.006_000") {
346 die getmessage('PerlVersionFailure', ['5.6.0']);
350 unless (eval {require DBI}) { push @missing,"DBI" };
351 unless (eval {require Date::Manip}) { push @missing,"Date::Manip" };
352 unless (eval {require DBD::mysql}) { push @missing,"DBD::mysql" };
353 unless (eval {require HTML::Template}) { push @missing,"HTML::Template" };
354 unless (eval {require Set::Scalar}) { push @missing,"Set::Scalar" };
355 unless (eval {require Digest::MD5}) { push @missing,"Digest::MD5" };
356 unless (eval {require MARC::Record}) { push @missing,"MARC::Record" };
357 unless (eval {require Net::Z3950}) {
358 my $message = getmessage('NETZ3950Missing');
359 showmessage($message, 'PressEnter', '', 1);
361 push @missing, "Net::Z3950";
366 # Print out a list of any missing modules
371 foreach my $module (@missing) {
372 $missing.=" perl -MCPAN -e 'install \"$module\"'\n";
374 my $message=getmessage('MissingPerlModules', [$missing]);
375 showmessage($message, 'none');
378 showmessage(getmessage('AllPerlModulesInstalled'), 'PressEnter', '', 1);
382 unless (-x "/usr/bin/perl") {
383 my $realperl=`which perl`;
385 $realperl = showmessage(getmessage('NoUsrBinPerl'), 'none');
386 until (-x $realperl) {
387 $realperl=showmessage(getmessage('AskLocationOfPerlExecutable', $realperl), 'free', $realperl, 1);
389 my $response=showmessage(getmessage('ConfirmPerlExecutableSymlink', $realperl), 'yn', 'y', 1);
390 unless ($response eq 'n') {
391 system("ln -s $realperl /usr/bin/perl");
398 $messages->{'NoUsrBinPerl'}->{en} =
399 heading('Perl is not located in /usr/bin/perl') . qq|
400 The Koha perl scripts expect to find the perl executable in the /usr/bin
401 directory. It is not there on your system.
405 $messages->{'AskLocationOfPerlExecutable'}->{en}=qq|Location of Perl Executable: [%s]: |;
406 $messages->{'ConfirmPerlExecutableSymlink'}->{en}=qq|
407 The Koha scripts will _not_ work without a symlink from %s to /usr/bin/perl
409 May I create this symlink? ([Y]/N):
416 getmessage($msgid, $variables);
418 Gets a localized message (format string) with message id $msgid,
419 and, if an array reference of variables $variables is given,
420 substitutes variables in the format string with @$variables.
421 Returns the found message string, with variable substitutions
424 $msgid must be the message identifier corresponding to a defined
425 message string (a valid key to the $messages hash in the Installer
426 package). getmessage throws an exception if the message cannot be
432 my $messagename=shift;
434 my $message=$messages->{$messagename}->{$::language} || $messages->{$messagename}->{en} || "Error: No message named $messagename in Install.pm\n";
435 if (defined($variables)) {
436 $message=sprintf $message, @$variables;
444 showmessage($message, 'none');
445 showmessage($message, 'none', undef, $noclear);
447 $result = showmessage($message, 'yn');
448 $result = showmessage($message, 'yn', $defaultresponse);
449 $result = showmessage($message, 'yn', $defaultresponse, $noclear);
451 $result = showmessage($message, 'restrictchar CHARS');
452 $result = showmessage($message, 'free');
453 $result = showmessage($message, 'numerical');
454 $result = showmessage($message, 'email');
455 $result = showmessage($message, 'PressEnter');
457 Shows a message and optionally gets a response from the user.
459 The first two arguments, the message and the response type,
460 are mandatory. The message must be the actual string to
461 display. The caller is responsible for calling getmessage if
464 If a response type other than 'none' is specified, a third
465 argument, specifying the default value, is optional.
467 The screen is normally cleared before the message is displayed;
468 if a fourth argument is specified and is nonzero, this
469 screen-clearing is not done.
471 FIXME: If $noclear is not specified or specified as undef, we
472 just test it for a non-zero value without testing it for being
479 my $responsetype=shift;
480 my $defaultresponse=shift;
482 ($noclear) || (system('clear'));
483 if ($responsetype =~ /^yn$/) {
484 $responsetype='restrictchar yn';
488 if ($responsetype =~/^restrictchar (.*)/i) {
491 until ($options=~/$response/) {
492 ($defaultresponse) || ($defaultresponse=substr($options,0,1));
495 (length($response)) || ($response=$defaultresponse);
496 unless ($options=~/$response/) {
497 ($noclear) || (system('clear'));
498 print "Invalid Response. Choose from [$options].\n\n";
504 if ($responsetype =~/^free$/i) {
505 (defined($defaultresponse)) || ($defaultresponse='');
506 my $response=<STDIN>;
508 ($response) || ($response=$defaultresponse);
511 if ($responsetype =~/^numerical$/i) {
512 (defined($defaultresponse)) || ($defaultresponse='');
514 until ($response=~/^\d+$/) {
517 ($response) || ($response=$defaultresponse);
518 unless ($response=~/^\d+$/) {
519 ($noclear) || (system('clear'));
520 print "Invalid Response ($response). Response must be a number.\n\n";
526 if ($responsetype =~/^email$/i) {
527 (defined($defaultresponse)) || ($defaultresponse='');
529 until ($response=~/.*\@.*\..*/) {
532 ($response) || ($response=$defaultresponse);
533 unless ($response=~/.*\@.*\..*/) {
534 ($noclear) || (system('clear'));
535 print "Invalid Response ($response). Response must be a valid email address.\n\n";
541 if ($responsetype =~/^PressEnter$/i) {
545 if ($responsetype =~/^none$/i) {
552 =item getinstallationdirectories
554 getinstallationdirectories;
556 Get the various installation directories from the user, and then
557 create those directories (if they do not already exist).
559 These pieces of information are saved to global variables; the
560 function does not return any values.
564 sub getinstallationdirectories {
565 $::opacdir = '/usr/local/koha/opac';
566 $::intranetdir = '/usr/local/koha/intranet';
568 while ($getdirinfo) {
569 # Loop until opac directory and koha directory are different
570 my $message=getmessage('GetOpacDir', [$::opacdir]);
571 $::opacdir=showmessage($message, 'free', $::opacdir);
573 $message=getmessage('GetIntranetDir', [$::intranetdir]);
574 $::intranetdir=showmessage($message, 'free', $::intranetdir);
576 if ($::intranetdir eq $::opacdir) {
579 You must specify different directories for the OPAC and INTRANET files!
580 :: $::intranetdir :: $::opacdir ::
587 $::kohalogdir='/var/log/koha';
588 my $message=getmessage('GetKohaLogDir', [$::kohalogdir]);
589 $::kohalogdir=showmessage($message, 'free', $::kohalogdir);
592 # FIXME: Missing error handling for all mkdir calls here
593 unless ( -d $::intranetdir ) {
594 mkdir_parents (dirname($::intranetdir), 0775);
595 mkdir ($::intranetdir, 0770);
596 chown (oct(0), (getgrnam($::httpduser))[2], "$::intranetdir");
597 chmod (oct(770), "$::intranetdir");
599 mkdir_parents ("$::intranetdir/htdocs", 0750);
600 mkdir_parents ("$::intranetdir/cgi-bin", 0750);
601 mkdir_parents ("$::intranetdir/modules", 0750);
602 mkdir_parents ("$::intranetdir/scripts", 0750);
603 unless ( -d $::opacdir ) {
604 mkdir_parents (dirname($::opacdir), 0775);
605 mkdir ($::opacdir, 0770);
606 chown (oct(0), (getgrnam($::httpduser))[2], "$::opacdir");
607 chmod (oct(770), "$::opacdir");
609 mkdir_parents ("$::opacdir/htdocs", 0750);
610 mkdir_parents ("$::opacdir/cgi-bin", 0750);
613 unless ( -d $::kohalogdir ) {
614 mkdir_parents (dirname($::kohalogdir), 0775);
615 mkdir ($::kohalogdir, 0770);
616 chown (oct(0), (getgrnam($::httpduser))[2,3], "$::kohalogdir");
617 chmod (oct(770), "$::kohalogdir");
623 =item getdatabaseinfo
627 Get various pieces of information related to the Koha database:
628 the name of the database, the host on which the SQL server is
629 running, and the database user name.
631 These pieces of information are saved to global variables; the
632 function does not return any values.
636 $messages->{'DatabaseName'}->{en} = heading('Name of MySQL database') . qq|
637 Please provide the name of the mysql database for your koha installation.
639 Database name [%s]: |;
641 $messages->{'DatabaseHost'}->{en} = heading('Database Host') . qq|
642 Please provide the hostname for mysql. Unless the database is located on
643 another machine this will be "localhost".
645 Database host [%s]: |;
647 $messages->{'DatabaseUser'}->{en} = heading('Database User') . qq|
648 Please provide the name of the user, who will have full administrative rights
649 to the %s database, when authenticating from %s.
651 This user will also be used to access Koha's INTRANET interface.
653 Database user [%s]: |;
655 $messages->{'DatabasePassword'}->{en} = heading('Database Password') . qq|
656 Please provide a good password for the user %s.
658 Database Password: |;
660 $messages->{'BlankPassword'}->{en} = heading('BLANK PASSWORD') . qq|
661 You must not use a blank password for your MySQL user!
663 Press <ENTER> to try again:
666 sub getdatabaseinfo {
669 $::hostname = 'localhost';
670 $::user = 'kohaadmin';
673 #Get the database name
675 my $message=getmessage('DatabaseName', [$::dbname]);
676 $::dbname=showmessage($message, 'free', $::dbname);
678 #Get the hostname for the database
680 $message=getmessage('DatabaseHost', [$::hostname]);
681 $::hostname=showmessage($message, 'free', $::hostname);
683 #Get the username for the database
685 $message=getmessage('DatabaseUser', [$::dbname, $::hostname, $::user]);
686 $::user=showmessage($message, 'free', $::user);
688 #Get the password for the database user
690 while ($::pass eq '') {
691 my $message=getmessage('DatabasePassword', [$::user]);
692 $::pass=showmessage($message, 'free', $::pass);
694 my $message=getmessage('BlankPassword');
695 showmessage($message,'PressEnter');
706 Get various pieces of information related to the Apache server:
707 the location of the configuration file and, if needed, the Unix
708 user that the Koha CGI will be run under.
710 These pieces of information are saved to global variables; the
711 function does not return any values.
715 $messages->{'FoundMultipleApacheConfFiles'}->{en} =
716 heading('MULTIPLE APACHE CONFIG FILES') . qq|
717 I found more than one possible Apache configuration file:
721 Choose the correct file [1]: |;
723 $messages->{'NoApacheConfFiles'}->{en} =
724 heading('NO APACHE CONFIG FILE FOUND') . qq|
725 I was not able to find your Apache configuration file.
727 The file is usually called httpd.conf or apache.conf.
729 Please specify the location of your config file: |;
731 $messages->{'NotAFile'}->{en} = heading('FILE DOES NOT EXIST') . qq|
732 The file %s does not exist.
734 Please press <ENTER> to continue: |;
736 $messages->{'EnterApacheUser'}->{en} = heading('NEED APACHE USER') . qq|
737 I was not able to determine the user that Apache is running as. This
738 information is necessary in order to set the access privileges correctly on
739 %s/koha.conf. This user should be set in one of the Apache configuration
740 files using the "User" directive.
742 Enter the Apache userid: |;
744 $messages->{'InvalidUserid'}->{en} = heading('INVALID USERID') . qq|
745 The userid %s is not a valid userid on this system.
747 Press <ENTER> to continue: |;
750 my @confpossibilities;
752 foreach my $httpdconf (qw(/usr/local/apache/conf/httpd.conf
753 /usr/local/etc/apache/httpd.conf
754 /usr/local/etc/apache/apache.conf
755 /var/www/conf/httpd.conf
756 /etc/apache/conf/httpd.conf
757 /etc/apache/conf/apache.conf
758 /etc/apache-ssl/conf/apache.conf
759 /etc/apache-ssl/httpd.conf
760 /etc/httpd/conf/httpd.conf
761 /etc/httpd/httpd.conf)) {
762 if ( -f $httpdconf ) {
763 push @confpossibilities, $httpdconf;
767 if ($#confpossibilities==-1) {
768 my $message=getmessage('NoApacheConfFiles');
770 until (-f $::realhttpdconf) {
771 $choice=showmessage($message, "free", 1);
773 $::realhttpdconf=$choice;
775 showmessage(getmessage('NotAFile', [$choice]),'PressEnter', '', 1);
778 } elsif ($#confpossibilities>0) {
782 foreach (@confpossibilities) {
783 $conffiles.=" $counter: $_\n";
784 $options.="$counter";
787 my $message=getmessage('FoundMultipleApacheConfFiles', [$conffiles]);
788 my $choice=showmessage($message, "restrictchar $options", 1);
789 $::realhttpdconf=$confpossibilities[$choice-1];
791 $::realhttpdconf=$confpossibilities[0];
793 unless (open (HTTPDCONF, "<$::realhttpdconf")) {
794 warn "Insufficient privileges to open $::realhttpdconf for reading.\n";
798 while (<HTTPDCONF>) {
799 if (/^\s*User\s+"?([-\w]+)"?\s*$/) {
808 unless ($::httpduser) {
809 my $message=getmessage('EnterApacheUser', [$::etcdir]);
810 until (length($::httpduser) && getpwnam($::httpduser)) {
811 $::httpduser=showmessage($message, "free", '');
812 if (length($::httpduser)>0) {
813 unless (getpwnam($::httpduser)) {
814 my $message=getmessage('InvalidUserid', [$::httpduser]);
815 showmessage($message,'PressEnter');
820 print "AU: $::httpduser\n";
825 $messages->{'ApacheConfigIntroduction'}->{en} =
826 heading('APACHE CONFIGURATION') . qq|
827 Koha needs to setup your Apache configuration file for the
828 OPAC and LIBRARIAN virtual hosts. By default this installer
829 will do this by using one ip address and two different ports
830 for the virtual hosts. There are other ways to set this up,
831 and the installer will leave comments in httpd.conf detailing
832 what these other options are.
835 Press <ENTER> to continue: |;
837 $messages->{'GetVirtualHostEmail'}->{en} =
838 heading('WEB SERVER E-MAIL CONTACT') . qq|
839 Enter the e-mail address to be used as a contact for the virtual hosts (this
840 address is displayed if any errors are encountered).
842 E-mail contact [%s]: |;
844 $messages->{'GetServerName'}->{en} =
845 heading('WEB SERVER HOST NAME OR IP ADDRESS') . qq|
846 Please enter the domain name or ip address of your computer.
848 Host name or IP Address [%s]: |;
850 $messages->{'GetOpacPort'}->{en} = heading('OPAC VIRTUAL HOST PORT') . qq|
851 Please enter the port for your OPAC interface. This defaults to port 80, but
852 if you are already serving web content from this server, you should change it
853 to a different port (8000 might be a good choice).
855 Enter the OPAC Port [%s]: |;
857 $messages->{'GetIntranetPort'}->{en} =
858 heading('INTRANET VIRTUAL HOST PORT') . qq|
859 Please enter the port for your Intranet interface. This must be different from
862 Enter the Intranet Port [%s]: |;
865 sub getapachevhostinfo {
867 $::svr_admin = "webmaster\@$::domainname";
868 $::servername=`hostname`;
871 $::intranetport=8080;
873 showmessage(getmessage('ApacheConfigIntroduction'), 'PressEnter');
875 $::svr_admin=showmessage(getmessage('GetVirtualHostEmail', [$::svr_admin]), 'email', $::svr_admin);
876 $::servername=showmessage(getmessage('GetServerName', [$::servername]), 'free', $::servername);
879 $::opacport=showmessage(getmessage('GetOpacPort', [$::opacport]), 'numerical', $::opacport);
880 $::intranetport=showmessage(getmessage('GetIntranetPort', [$::opacport, $::intranetport]), 'numerical', $::intranetport);
884 $messages->{'StartUpdateApache'}->{en} =
885 heading('UPDATING APACHE CONFIGURATION') . qq|
886 Checking for modules that need to be loaded...
889 $messages->{'LoadingApacheModuleModEnv'}->{en}="Loading SetEnv Apache module.\n";
891 $messages->{'LoadingApacheModuleModInc'}->{en}="Loading Includes Apache module.\n";
893 $messages->{'ApacheConfigBackupFailed'}->{en} =
894 heading('APACHE CONFIGURATION BACKUP FAILED') . qq|
895 An error occurred while trying to make a backup copy of %s.
899 No changes will be made to the apache configuration file at this time.
901 Press <ENTER> to continue: |;
904 $messages->{'ApacheAlreadyConfigured'}->{en} =
905 heading('APACHE ALREADY CONFIGURED') . qq|
906 %s appears to already have an entry for Koha
907 Virtual Hosts. You may need to edit %s
908 f anything has changed since it was last set up. This
909 script will not attempt to modify an existing Koha apache
912 Press <ENTER> to continue: |;
914 sub updateapacheconf {
915 my $logfiledir=`grep ^ErrorLog "$::realhttpdconf"`;
919 $logfiledir=~m#ErrorLog (.*)/[^/]*$#
920 or die "Can't parse ErrorLog directive\n";
924 unless ($logfiledir) {
928 showmessage(getmessage('StartUpdateApache'), 'none');
932 my $includesmodule=0;
933 open HC, "<$::realhttpdconf";
935 if (/^\s*#\s*LoadModule env_module /) {
937 showmessage(getmessage('LoadingApacheModuleModEnv'));
940 if (/^\s*#\s*LoadModule includes_module /) {
942 showmessage(getmessage('LoadingApacheModuleModInc'));
944 if (/\s*LoadModule includes_module / ) {
951 $backupfailed=`cp -f $::realhttpdconf $::realhttpdconf\.prekoha`;
953 showmessage(getmessage('ApacheConfigBackupFailed', [$::realhttpdconf,$backupfailed ]), 'PressEnter');
957 if ($envmodule || $includesmodule) {
958 open HC, ">$::realhttpdconf";
965 if (`grep 'VirtualHost $::servername' "$::realhttpdconf"`) {
966 showmessage(getmessage('ApacheAlreadyConfigured', [$::realhttpdconf, $::realhttpdconf]), 'PressEnter');
969 my $includesdirectives='';
970 if ($includesmodule) {
971 $includesdirectives.="Options +Includes\n";
972 $includesdirectives.=" AddHandler server-parsed .html\n";
974 open(SITE,">>$::realhttpdconf") or warn "Insufficient priveleges to open $::realhttpdconf for writing.\n";
976 if ($::opacport != 80) {
977 $opaclisten="Listen $::opacport";
979 my $intranetlisten = '';
980 if ($::intranetport != 80) {
981 $intranetlisten="Listen $::intranetport";
985 # Ports to listen to for Koha
989 # NameVirtualHost is used by one of the optional configurations detailed below
991 #NameVirtualHost 11.22.33.44
993 # KOHA's OPAC Configuration
994 <VirtualHost $::servername\:$::opacport>
995 ServerAdmin $::svr_admin
996 DocumentRoot $::opacdir/htdocs
997 ServerName $::servername
998 ScriptAlias /cgi-bin/koha/ $::opacdir/cgi-bin/
999 ErrorLog $logfiledir/opac-error_log
1000 TransferLog $logfiledir/opac-access_log
1001 SetEnv PERL5LIB "$::intranetdir/modules"
1005 # KOHA's INTRANET Configuration
1006 <VirtualHost $::servername\:$::intranetport>
1007 ServerAdmin $::svr_admin
1008 DocumentRoot $::intranetdir/htdocs
1009 ServerName $::servername
1010 ScriptAlias /cgi-bin/koha/ "$::intranetdir/cgi-bin/"
1011 ErrorLog $logfiledir/koha-error_log
1012 TransferLog $logfiledir/koha-access_log
1013 SetEnv PERL5LIB "$::intranetdir/modules"
1017 # If you want to use name based Virtual Hosting:
1018 # 1. remove the two Listen lines
1019 # 2. replace $::servername\:$::opacport wih your.opac.domain.name
1020 # 3. replace ServerName $::servername wih ServerName your.opac.domain.name
1021 # 4. replace $::servername\:$::intranetport wih your intranet domain name
1022 # 5. replace ServerName $::servername wih ServerName your.intranet.domain.name
1024 # If you want to use NameVirtualHost'ing (using two names on one ip address):
1025 # 1. Follow steps 1-5 above
1026 # 2. Uncomment the NameVirtualHost line and set the correct ip address
1034 $messages->{'IntranetAuthenticationQuestion'}->{en} =
1035 heading('INTRANET AUTHENTICATION') . qq|
1036 I can set it up so that the Intranet/Librarian site is password protected using
1037 Apache's Basic Authorization.
1039 This is going to be phased out very soon. However, setting this up can provide
1040 an extra layer of security before the new authentication system is completely
1043 Would you like to do this ([Y]/N): |;
1045 $messages->{'BasicAuthUsername'}->{en}="Please enter a userid for intranet access [%s]: ";
1046 $messages->{'BasicAuthPassword'}->{en}="Please enter a password for %s: ";
1047 $messages->{'BasicAuthPasswordWasBlank'}->{en}="\nYou cannot use a blank password!\n\n";
1049 sub basicauthentication {
1050 my $message=getmessage('IntranetAuthenticationQuestion');
1051 my $answer=showmessage($message, 'yn', 'y');
1053 my $apacheauthusername='librarian';
1054 my $apacheauthpassword='';
1055 if ($answer=~/^y/i) {
1056 ($apacheauthusername) = showmessage(getmessage('BasicAuthUsername', [ $apacheauthusername]), 'free', $apacheauthusername, 1);
1057 $apacheauthusername=~s/[^a-zA-Z0-9]//g;
1058 while (! $apacheauthpassword) {
1059 ($apacheauthpassword) = showmessage(getmessage('BasicAuthPassword', [ $apacheauthusername]), 'free', 1);
1060 if (!$apacheauthpassword) {
1061 ($apacheauthpassword) = showmessage(getmessage('BasicAuthPasswordWasBlank'), 'none', '', 1);
1064 open AUTH, ">$::etcdir/kohaintranet.pass";
1065 my $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
1066 my $salt=substr($chars, int(rand(length($chars))),1);
1067 $salt.=substr($chars, int(rand(length($chars))),1);
1068 print AUTH $apacheauthusername.":".crypt($apacheauthpassword, $salt)."\n";
1070 open(SITE,">>$::realhttpdconf") or warn "Insufficient priveleges to open $::realhttpdconf for writing.\n";
1073 <Directory $::intranetdir>
1074 AuthUserFile $::etcdir/kohaintranet.pass
1076 AuthName "Koha Intranet (for librarians only)"
1084 $messages->{'InstallFiles'}->{en} = heading('INSTALLING FILES') . qq|
1085 Copying files to installation directories:
1090 $messages->{'CopyingFiles'}->{en}="Copying %s to %s.\n";
1097 showmessage(getmessage('InstallFiles'),'none');
1098 print getmessage('CopyingFiles', ['intranet-html', "$::intranetdir/htdocs" ]);
1099 system("cp -R intranet-html/* $::intranetdir/htdocs/");
1100 print getmessage('CopyingFiles', ['intranet-cgi', "$::intranetdir/cgi-bin" ]);
1101 system("cp -R intranet-cgi/* $::intranetdir/cgi-bin/");
1102 print getmessage('CopyingFiles', ['stand-alone scripts', "$::intranetdir/scripts" ]);
1103 system("cp -R scripts/* $::intranetdir/scripts/");
1104 print getmessage('CopyingFiles', ['perl modules', "$::intranetdir/modules" ]);
1105 system("cp -R modules/* $::intranetdir/modules/");
1106 print getmessage('CopyingFiles', ['opac-html', "$::opacdir/htdocs" ]);
1107 system("cp -R opac-html/* $::opacdir/htdocs/");
1108 print getmessage('CopyingFiles', ['opac-cgi', "$::opacdir/cgi-bin" ]);
1109 system("cp -R opac-cgi/* $::opacdir/cgi-bin/");
1110 system("touch $::opacdir/cgi-bin/opac");
1112 system("chown -R root:$::httpduser $::opacdir");
1113 system("chown -R root:$::httpduser $::intranetdir");
1115 # Create /etc/koha.conf
1117 my $old_umask = umask(027); # make sure koha.conf is never world-readable
1118 open(SITES,">$::etcdir/koha.conf.tmp") or warn "Couldn't create file at $::etcdir. Must have write capability.\n";
1121 hostname=$::hostname
1124 includes=$::opacdir/htdocs/includes
1125 intranetdir=$::intranetdir
1127 kohalogdir=$::kohalogdir
1128 kohaversion=$::kohaversion
1129 httpduser=$::httpduser
1130 intrahtdocs=$::intranetdir/htdocs/intranet-tmpl
1131 opachtdocs=$::opacdir/htdocs/opac-tmpl
1136 chown((getpwnam($::httpduser)) [2,3], "$::etcdir/koha.conf.tmp") or warn "can't chown koha.conf: $!";
1137 chmod 0440, "$::etcdir/koha.conf.tmp";
1139 chmod 0750, "$::intranetdir/scripts/z3950daemon/z3950-daemon-launch.sh";
1140 chmod 0750, "$::intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh";
1141 chmod 0750, "$::intranetdir/scripts/z3950daemon/processz3950queue";
1142 chown(0, (getpwnam($::httpduser)) [3], "$::intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh") or warn "can't chown $::intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh: $!";
1143 chown(0, (getpwnam($::httpduser)) [3], "$::intranetdir/scripts/z3950daemon/processz3950queue") or warn "can't chown $::intranetdir/scripts/z3950daemon/processz3950queue: $!";
1147 $messages->{'MysqlRootPassword'}->{en} =
1148 heading('MYSQL ROOT USER PASSWORD') . qq|
1149 To allow us to create the koha database please supply your
1150 mysql server's root user password:
1152 Enter MySQL root user password: |;
1154 $messages->{'InvalidMysqlRootPassword'}->{en}="Invalid Password. Please try again.";
1156 $messages->{'CreatingDatabase'}->{en} = heading('CREATING DATABASE') . qq|
1157 Creating the MySQL database for Koha...
1161 $messages->{'CreatingDatabaseError'}->{en} =
1162 heading('ERROR CREATING DATABASE') . qq|
1163 Couldn't connect to the MySQL server for the reason given above.
1164 This is a serious problem, the database will not get installed.
\a
1166 Press <ENTER> to continue: |;
1168 $messages->{'SampleData'}->{en} = heading('SAMPLE DATA') . qq|
1169 If you are installing Koha for evaluation purposes, I have a batch of sample
1170 data that you can install now.
1172 If you are installing Koha with the intention of populating it with your own
1173 data, you probably don't want this sample data installed.
1175 Would you like to install the sample data? Y/[N]: |;
1177 $messages->{'SampleDataInstalled'}->{en} =
1178 heading('SAMPLE DATA INSTALLED') . qq|
1179 Sample data has been installed. For some suggestions on testing Koha, please
1180 read the file doc/HOWTO-Testing. If you find any bugs, please submit them at
1181 http://bugs.koha.org/. If you need help with testing Koha, you can post a
1182 question through the koha-devel mailing list, or you can check for a developer
1183 online at +irc.katipo.co.nz:6667 channel #koha.
1185 You can find instructions for subscribing to the Koha mailing lists at:
1190 Press <ENTER> to continue: |;
1192 $messages->{'AddBranchPrinter'}->{en} = heading('Add Branch and Printer') . qq|
1193 Would you like to install an initial branch and printer? [Y]/N: |;
1195 $messages->{'BranchName'}->{en}="Branch Name [%s]: ";
1196 $messages->{'BranchCode'}->{en}="Branch Code (4 letters or numbers) [%s]: ";
1197 $messages->{'PrinterQueue'}->{en}="Printer Queue [%s]: ";
1198 $messages->{'PrinterName'}->{en}="Printer Name [%s]: ";
1199 $messages->{'BlankMysqlPassword'}->{en} = heading('Blank MySQL Password') . qq|
1200 Do not leave your MySQL root password blank unless you know exactly what you
1201 are doing. To change your MySQL root password use the mysqladmin command:
1203 mysqladmin password NEWPASSWORDHERE
1205 Press <ENTER> to continue:
1209 $::mysqluser = 'root';
1212 foreach my $mysql (qw(/usr/local/mysql
1216 if ( -d $mysql && -f "$mysql/bin/mysqladmin") {
1221 print "I don't see mysql in the usual places.\n";
1223 print "Where have you installed mysql? ";
1224 chomp($::mysqldir = <STDIN>);
1225 last if -f "$::mysqldir/bin/mysqladmin";
1228 I can't find it there either. If you compiled mysql yourself,
1229 please give the value of --prefix when you ran configure.
1231 The file mysqladmin should be in bin/mysqladmin under the directory that you
1240 while ($needpassword) {
1241 $::mysqlpass=showmessage(getmessage('MysqlRootPassword'), 'free');
1242 $::mysqlpass_quoted = $::mysqlpass;
1243 $::mysqlpass_quoted =~ s/"/\\"/g;
1244 $::mysqlpass_quoted="-p\"$::mysqlpass_quoted\"";
1245 $::mysqlpass eq '' and $::mysqlpass_quoted='';
1246 my $result=system("$::mysqldir/bin/mysqladmin -u$::mysqluser $::mysqlpass_quoted proc > /dev/null 2>&1");
1248 print getmessage('InvalidMysqlRootPassword');
1250 if ($::mysqlpass eq '') {
1251 showmessage(getmessage('BlankMysqlPassword'), 'PressEnter');
1257 showmessage(getmessage('CreatingDatabase'),'none');
1259 my $result=system("$::mysqldir/bin/mysqladmin", "-u$::mysqluser", "-p$::mysqlpass", "create", "$::dbname");
1261 showmessage(getmessage('CreatingDatabaseError'),'PressEnter', '', 1);
1263 # Populate the Koha database
1264 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname < koha.mysql");
1265 # Set up permissions
1266 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted mysql -e \"insert into user (Host,User,Password) values ('$::hostname','$::user',password('$::pass'))\"\;");
1267 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')\"");
1268 system("$::mysqldir/bin/mysqladmin -u$::mysqluser $::mysqlpass_quoted reload");
1278 $messages->{'UpdateMarcTables'}->{en} =
1279 heading('UPDATING MARC FIELD DEFINITION TABLES') . qq|
1280 You can import marc parameters for :
1286 Please choose which parameter you want to install. Note if you choose 3,
1287 nothing will be added, and it can be a BIG job to manually create those tables
1289 Choose MARC definition [1]: |;
1291 $messages->{'Language'}->{en} = heading('CHOOSE LANGUAGES') . qq|
1292 This version of koha supports a few languages.
1293 Enter you languages preferences : either en, fr, es or pl.
1294 Note that the en is always choosen when the system does not finds the
1295 language you choose in a specific screen.
1296 fr : opac is translated (except pictures)
1297 es : a few intranet is translated (including pictures)
1298 pl : opac is translated (UNTESTED in this release)
1301 sub updatedatabase {
1302 # At this point, $::etcdir/koha.conf must exist, for C4::Context
1303 # We must somehow temporarily enable $::etcdir/koha.conf. A symlink can
1304 # do this & at the same time facilitate detection of aborted installs.
1305 my $result=system ("perl -I $::intranetdir/modules scripts/updater/updatedatabase");
1307 print "Problem updating database...\n";
1311 my $response=showmessage(getmessage('UpdateMarcTables'), 'restrictchar 123', '1');
1313 if ($response == 1) {
1314 system("cat scripts/misc/marc_datas/marc21_en/structure_def.sql | $::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname");
1316 if ($response == 2) {
1317 system("cat scripts/misc/marc_datas/unimarc_fr/structure_def.sql | $::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname");
1318 system("cat scripts/misc/lang-datas/fr/stopwords.sql | $::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname");
1321 $result = system ("perl -I $::intranetdir/modules scripts/marc/updatedb2marc.pl");
1323 print "Problem updating database to MARC...\n";
1327 print "\n\nFinished updating of database. Press <ENTER> to continue...";
1331 sub populatedatabase {
1332 my $response=showmessage(getmessage('SampleData'), 'yn', 'n');
1333 if ($response =~/^y/i) {
1334 system("gunzip -d < sampledata-1.2.gz | $::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname");
1335 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branches (branchcode,branchname,issuing) values ('MAIN', 'Main Library', 1)\"");
1336 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'IS')\"");
1337 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'CU')\"");
1338 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into printers (printername,printqueue,printtype) values ('Circulation Desk Printer', 'lp', 'hp')\"");
1339 showmessage(getmessage('SampleDataInstalled'), 'PressEnter','',1);
1342 my $response=showmessage(getmessage('AddBranchPrinter'), 'yn', 'y');
1344 unless ($response =~/^n/i) {
1345 my $branch='Main Library';
1346 $branch=showmessage(getmessage('BranchName', [$branch]), 'free', $branch, 1);
1347 $branch=~s/[^A-Za-z0-9\s]//g;
1349 my $branchcode=$branch;
1350 $branchcode=~s/[^A-Za-z0-9]//g;
1351 $branchcode=uc($branchcode);
1352 $branchcode=substr($branchcode,0,4);
1353 $branchcode=showmessage(getmessage('BranchCode', [$branchcode]), 'free', $branchcode, 1);
1354 $branchcode=~s/[^A-Za-z0-9]//g;
1355 $branchcode=uc($branchcode);
1356 $branchcode=substr($branchcode,0,4);
1357 $branchcode or $branchcode='DEF';
1359 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branches (branchcode,branchname,issuing) values ('$branchcode', '$branch', 1)\"");
1360 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'IS')\"");
1361 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'CU')\"");
1363 my $printername='Library Printer';
1364 $printername=showmessage(getmessage('PrinterName', [$printername]), 'free', $printername, 1);
1365 $printername=~s/[^A-Za-z0-9\s]//g;
1367 my $printerqueue='lp';
1368 $printerqueue=showmessage(getmessage('PrinterQueue', [$printerqueue]), 'free', $printerqueue, 1);
1369 $printerqueue=~s/[^A-Za-z0-9]//g;
1370 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"insert into printers (printername,printqueue,printtype) values ('$printername', '$printerqueue', '')\"");
1372 my $language=showmessage(getmessage('Language'), 'free', 'en');
1373 system("$::mysqldir/bin/mysql -u$::mysqluser $::mysqlpass_quoted $::dbname -e \"update systempreferences set value='$language' where variable='opaclanguages'\"");
1377 $messages->{'RestartApache'}->{en} = heading('RESTART APACHE') . qq|
1378 Apache needs to be restarted to load the new configuration for Koha.
1380 Would you like to restart Apache now? [Y]/N: |;
1384 my $response=showmessage(getmessage('RestartApache'), 'yn', 'y');
1388 unless ($response=~/^n/i) {
1389 # Need to support other init structures here?
1390 if (-e "/etc/rc.d/init.d/httpd") {
1391 system('/etc/rc.d/init.d/httpd restart');
1392 } elsif (-e "/etc/init.d/apache") {
1393 system('/etc//init.d/apache restart');
1394 } elsif (-e "/etc/init.d/apache-ssl") {
1395 system('/etc/init.d/apache-ssl restart');
1402 sub loadconfigfile {
1405 open (KC, "<$::etcdir/koha.conf");
1408 (next) if (/^\s*#/);
1409 if (/(.*)\s*=\s*(.*)/) {
1412 # Clean up white space at beginning and end
1413 $variable=~s/^\s*//g;
1414 $variable=~s/\s*$//g;
1417 $configfile{$variable}=$value;
1421 $::intranetdir=$configfile{'intranetdir'};
1422 $::opacdir=$configfile{'opacdir'};
1423 $::kohaversion=$configfile{'kohaversion'};
1424 $::kohalogdir=$configfile{'kohalogdir'};
1425 $::database=$configfile{'database'};
1426 $::hostname=$configfile{'hostname'};
1427 $::user=$configfile{'user'};
1428 $::pass=$configfile{'pass'};
1431 END { } # module clean-up code here (global destructor)
1437 A lot of variables like $::opacdir. Because Perl does not check
1438 for strictness when a package name is explicitly specified,
1439 using such variables defeats the purpose of "use strict".