Fixed bug #175.
[koha.git] / misc / Install.pm
1 package Install; #assumes Install.pm
2
3
4 # Copyright 2000-2002 Katipo Communications
5 #
6 # This file is part of Koha.
7 #
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
11 # version.
12 #
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.
16 #
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
20
21 use strict;
22 use POSIX;
23 require Exporter;
24
25 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
26
27 =head1 NAME
28
29 Install.pm - Perl module containing the bulk of the installation logic
30
31 =head1 DESCRIPTION
32
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.
37
38 =head2 Internal functions (not meant to be used outside of Install.pm)
39
40 =over 4
41
42 =cut
43
44 # set the version for version checking
45 $VERSION = 0.01;
46
47 @ISA = qw(Exporter);
48 @EXPORT = qw(   &checkperlmodules
49                 &checkabortedinstall
50                 &getmessage
51                 &showmessage
52                 &releasecandidatewarning
53                 &getinstallationdirectories
54                 &getdatabaseinfo
55                 &getapacheinfo
56                 &getapachevhostinfo
57                 &updateapacheconf
58                 &basicauthentication
59                 &installfiles
60                 &databasesetup
61                 &updatedatabase
62                 &populatedatabase
63                 &restartapache
64                 &finalizeconfigfile
65                 &loadconfigfile
66                 );
67
68 use vars qw( $kohaversion );                    # set in installer.pl
69 use vars qw( $language );                       # set in installer.pl
70 use vars qw( $domainname );                     # set in installer.pl
71
72 use vars qw( $etcdir );                         # set in installer.pl, usu. /etc
73 use vars qw( $intranetdir $opacdir $kohalogdir );
74 use vars qw( $realhttpdconf $httpduser );
75 use vars qw( $servername $svr_admin $opacport $intranetport );
76 use vars qw( $mysqldir );
77 use vars qw( $database $mysqluser );
78 use vars qw( $mysqlpass );                      # normally should not be used
79 use vars qw( $mysqlpass_quoted );               # quoted, contains -p as needed
80 use vars qw( $dbname $hostname $user $pass );   # virtual hosting
81
82 use vars qw( $newversion );                     # XXX this seems to be unused
83
84 =item heading
85
86     $messages->{'WelcomeToKohaInstaller'
87         = heading('Welcome to the Koha Installer') . qq|...|;
88
89 The heading function takes one string, the text to be displayed as
90 the heading, and returns a formatted heading (currently formatted
91 in the "traditional Koha installer" style, i.e., surrounded by a
92 box of equal signs).
93
94 This reduces the likelihood of pod2man(1) etc. misinterpreting
95 a line of equal signs as illegal POD directives.
96
97 =cut
98
99 sub heading ($) {
100    my($s) = @_;
101    my $n = length($s) + 4;
102    my $line = ('=' x $n) . "\n";
103    "\n$line= $s =\n$line\n";
104 }
105
106 my $messages;
107 $messages->{'continuing'}->{en}="Great!  Continuing setup.\n\n";
108 $messages->{'WelcomeToKohaInstaller'}->{en} =
109    heading('Welcome to the Koha Installer') . qq|
110 Welcome to the Koha install script!  This script will prompt you for some
111 basic information about your desired setup, then install Koha according to
112 your specifications.  To accept the default value for any question, simply hit
113 Enter at the prompt.
114
115 Please be sure to read the documentation, or visit the Koha website at
116 http://www.koha.org for more information.
117
118 Are you ready to begin the installation? (Y/[N]): |;
119 $messages->{'ReleaseCandidateWarning'}->{en} =
120    heading('RELEASE CANDIDATE') . qq|
121 WARNING WARNING WARNING WARNING WARNING
122
123 You are about to install Koha version %s.  This version of Koha is a
124 release candidate.  It is not intended to be installed on production systems.
125 It is being released so that users can test it before we release a final
126 version.
127
128 Are you sure you want to install Koha %s? (Y/[N]): |;
129 $messages->{'WatchForReleaseAnnouncements'}->{en}=qq|
130
131 Watch for announcements of Koha releases on the Koha mailing list or the Koha
132 web site (http://www.koha.org/).
133
134 |;
135
136 $messages->{'NETZ3950Missing'}->{en}=qq|
137
138 The Net::Z3950 module is missing.  This module is necessary if you want to use
139 Koha's Z39.50 client to download bibliographic records from other libraries.
140
141 To install this module, you will need the yaz client installed from
142 http://www.indexdata.dk/yaz/ and then you can install the perl module with the
143 command:
144
145 perl -MCPAN -e 'install Net::Z3950'
146
147 IMPORTANT NOTE : If you use PERL5.8.0 (RedHat 8.0 or Mandrake 9.x), you MUST install 
148 manually the Net::Z3950 and edit Makefile.PL and yazwrap/Makefile.PL to include:
149     'DEFINES' => '-D_GNU_SOURCE',
150
151
152 Press the <ENTER> key to continue: |;   #'
153
154 $messages->{'CheckingPerlModules'}->{en} = heading('PERL & MODULES') . qq|
155 Checking perl modules ...
156 |;
157
158 $messages->{'PerlVersionFailure'}->{en}="Sorry, you need at least Perl %s\n";
159
160 $messages->{'MissingPerlModules'}->{en} = heading('MISSING PERL MODULES') . qq|
161 You are missing some Perl modules which are required by Koha.
162 Once these modules have been installed, rerun this installer.
163 They can be installed by running (as root) the following:
164
165 %s
166 |;
167
168 $messages->{'AllPerlModulesInstalled'}->{en} =
169    heading('ALL PERL MODULES INSTALLED') . qq|
170 All mandatory perl modules are installed.
171
172 Press <ENTER> to continue: |;
173 $messages->{'KohaVersionInstalled'}->{en}="You currently have Koha %s on your system.";
174 $messages->{'KohaUnknownVersionInstalled'}->{en}="I am not able to determine what version of Koha is installed now.";
175 $messages->{'KohaAlreadyInstalled'}->{en} =
176    heading('Koha already installed') . qq|
177 It looks like Koha is already installed on your system (%s/koha.conf exists
178 already).  If you would like to upgrade your system to %s, please use
179 the koha.upgrade script in this directory.
180
181 %s
182
183 |;
184 $messages->{'GetOpacDir'}->{en} = heading('OPAC DIRECTORY') . qq|
185 Please supply the directory you want Koha to store its OPAC files in.  This
186 directory will be auto-created for you if it doesn't exist.
187
188 OPAC Directory [%s]: |; #'
189
190 $messages->{'GetIntranetDir'}->{en} =
191    heading('INTRANET/LIBRARIANS DIRECTORY') . qq|
192 Please supply the directory you want Koha to store its Intranet/Librarians
193 files in.  This directory will be auto-created for you if it doesn't exist.
194
195 Intranet Directory [%s]: |;     #'
196
197 $messages->{'GetKohaLogDir'}->{en} = heading('KOHA LOG DIRECTORY') . qq|
198 Specify a log directory where any Koha daemons can create log files.
199
200 Koha Log Directory [%s]: |;
201
202 $messages->{'AuthenticationWarning'}->{en} = heading('Authentication') . qq|
203 This release of Koha has a new authentication module.  If you are not already
204 using basic authentication on your intranet, you will be required to log in to
205 access some of the features of the intranet.  You can log in using the userid
206 and password from the %s/koha.conf configuration file at any time.  Use the
207 "Members" module to add passwords for other accounts and set their permissions.
208
209 Press the <ENTER> key to continue: |;
210
211 $messages->{'Completed'}->{en} = heading('KOHA INSTALLATION COMPLETE') . qq|
212 Congratulations ... your Koha installation is complete!
213
214 You will be able to connect to your Librarian interface at:
215
216    http://%s\:%s/
217
218 and the OPAC interface at :
219
220    http://%s\:%s/
221
222 Be sure to read the Hints file.
223
224 For more information visit http://www.koha.org
225
226 Press <ENTER> to exit the installer: |;
227
228 sub releasecandidatewarning {
229     my $message=getmessage('ReleaseCandidateWarning', [$newversion, $newversion]);
230     my $answer=showmessage($message, 'yn', 'n');
231
232     if ($answer =~ /y/i) {
233         print getmessage('continuing');
234     } else {
235         my $message=getmessage('WatchForReleaseAnnouncements');
236         print $message;
237         exit;
238     };
239 }
240
241
242 =back
243
244 =head2 Accessor functions (for installer.pl)
245
246 =over 4
247
248 =cut
249
250 =item setlanguage
251
252     setlanguage('en');
253
254 Sets the installation language, normally "en" (English).
255 In fact, only "en" is supported.
256
257 =cut
258
259 sub setlanguage ($) {
260     ($language) = @_;
261 }
262
263 =item setdomainname
264
265     setdomainname('example.org');
266
267 Sets the domain name of the host.
268
269 The domain name should not contain a leading dot;
270 otherwise, the results are undefined.
271
272 =cut
273
274 sub setdomainname ($) {
275     ($domainname) = @_;
276 }
277
278 =item setetcdir
279
280     setetcdir('/etc');
281
282 Sets the sysconfdir, normally /etc.
283 This should be an absolute path; a trailing / is not required.
284
285 =cut
286
287 sub setetcdir ($) {
288     ($etcdir) = @_;
289 }
290
291 =item setkohaversion
292
293     setkohaversion('1.3.3RC26');
294
295 Sets the Koha version as known by the installer.
296
297 =cut
298
299 sub setkohaversion ($) {
300     ($kohaversion) = @_;
301 }
302
303 =item getservername
304
305     my $servername = getservername;
306
307 Gets the name of the Koha virtual server as specified by the user.
308
309 =cut
310
311 sub getservername () {
312     $servername;
313 }
314
315 =item getopacport
316
317     $port = getopacport;
318
319 Gets the port that will run the Koha OPAC virtual server,
320 as specified by the user.
321
322 =cut
323
324 sub getopacport () {
325     $opacport;
326 }
327
328 =item getintranetport
329
330     $port = getintranetport;
331
332 Gets the port that will run the Koha INTRANET virtual server,
333 as specified by the user.
334
335 =cut
336
337 sub getintranetport () {
338     $intranetport;
339 }
340
341 =back
342
343 =head2 Miscellaneous utility functions
344
345 =over 4
346
347 =cut
348
349 =item dirname
350
351     dirname $path;
352
353 Does the equivalent of dirname(1). Given a path $path, return the
354 parent directory of $path (best guess), except when $path seems to
355 be the same as /, in which case $path itself is returned unchanged.
356
357 =cut
358
359 sub dirname ($;$) {
360     my($path) = @_;
361     if ($path =~ /[^\/]/s) {
362         if ($path =~ /\//) {
363             $path =~ s/\/+[^\/]+\/*$//s;
364         } else {
365             $path = '.';
366         }
367     }
368     return $path;
369 }
370
371 =item mkdir_parents
372
373     mkdir_parents $path;
374     mkdir_parents $path, $mode;
375
376 Does the equivalent of mkdir -p, or mkdir --parents. Given a path $path,
377 create the directory $path, recursively creating any intermediate
378 directories. If $mode is given, the directory will be created with
379 mode $mode.
380
381 WARNING: If $path already exists, mkdir_parents will just return
382 successfully (just like mkdir -p), whether the mode of $path conforms
383 to $mode or not. (This is the behaviour of the mkdir -p command.)
384
385 =cut
386
387 sub mkdir_parents ($;$) {
388     my($path, $mode) = @_;
389     my $ok = -d($path)? 1: defined $mode? mkdir($path, $mode): mkdir($path);
390
391     if (!$ok && $! == ENOENT) {
392         my $parent = dirname($path);
393         $ok = mkdir_parents($parent, $mode);
394
395         # retry and at the same time make sure that $! is set correctly
396         $ok = defined $mode? mkdir($path, $mode): mkdir($path);
397     }
398     return $ok;
399 }
400
401
402 =item getmessage
403
404     getmessage($msgid);
405     getmessage($msgid, $variables);
406
407 Gets a localized message (format string) with message id $msgid,
408 and, if an array reference of variables $variables is given,
409 substitutes variables in the format string with @$variables.
410 Returns the found message string, with variable substitutions
411 if specified.
412
413 $msgid must be the message identifier corresponding to a defined
414 message string (a valid key to the $messages hash in the Installer
415 package). getmessage throws an exception if the message cannot be
416 found.
417
418 =cut
419
420 sub getmessage {
421     my $messagename=shift;
422     my $variables=shift;
423     my $message=$messages->{$messagename}->{$language} || $messages->{$messagename}->{en} || "Error: No message named $messagename in Install.pm\n";
424     if (defined($variables)) {
425         $message=sprintf $message, @$variables;
426     }
427     return $message;
428 }
429
430
431 =item showmessage
432
433     showmessage($message, 'none');
434     showmessage($message, 'none', undef, $noclear);
435
436     $result = showmessage($message, 'yn');
437     $result = showmessage($message, 'yn', $defaultresponse);
438     $result = showmessage($message, 'yn', $defaultresponse, $noclear);
439
440     $result = showmessage($message, 'restrictchar CHARS');
441     $result = showmessage($message, 'free');
442     $result = showmessage($message, 'numerical');
443     $result = showmessage($message, 'email');
444     $result = showmessage($message, 'PressEnter');
445
446 Shows a message and optionally gets a response from the user.
447
448 The first two arguments, the message and the response type,
449 are mandatory.  The message must be the actual string to
450 display; the caller is responsible for calling getmessage if
451 required.
452
453 The response type must be one of "none", "yn", "free",
454 "numerical", "email", "PressEnter", or a string consisting
455 of "restrictchar " followed by a list of allowed characters
456 (space can be specified). (Case is not significant, but case is
457 significant in the list of allowed characters.) If a response
458 type other than the above-listed is specified, the result is
459 undefined.
460
461 Note that the response type "yn" is equivalent to "restrictchar yn".
462 Because "restrictchar" is case-sensitive, the user is expected
463 to enter "y" or "n" in lowercase only.
464
465 Note that the response type of "email" does not actually
466 guarantee that the returned value is a well-formed RFC-822
467 email address, nor does it accept all well-formed RFC-822 email
468 addresses. What it does is to restrict the returned value to a
469 string that is looks reasonably likely to be an email address
470 in the "real world", given the premise that the user is trying
471 to enter a real email address.
472
473 If a response type other than "none" or "PressEnter" is
474 specified, a third argument, specifying the default value, can
475 be specified:  If this default response is not specified, the
476 default response is the first allowed character if the response
477 type is "restrictchar", otherwise the default response is the
478 empty string. This default response is used when the user does
479 not specify a value (i.e., presses Enter without typing in
480 anything), showmessage will assume that the default response is
481 the user's response.
482
483 Note that because the response type "yn" is equivalent to
484 "restrictchar yn", the default value for response type "yn",
485 if unspecified, is "y".
486
487 The screen is normally cleared before the message is displayed;
488 if a fourth argument is specified and is nonzero, this
489 screen-clearing is not done.
490
491 =cut
492 #'
493
494 sub showmessage {
495     my $message=shift;
496     my $responsetype=shift;
497     my $defaultresponse=shift;
498     my $noclear=shift;
499     $noclear = 0 unless defined $noclear; # defaults to "clear"
500     ($noclear) || (system('clear'));
501     if ($responsetype =~ /^yn$/) {
502         $responsetype='restrictchar yn';
503     }
504     print $message;
505     if ($responsetype =~/^restrictchar (.*)/i) {
506         my $response='\0';
507         my $options=$1;
508         until ($options=~/$response/) {
509             ($defaultresponse) || ($defaultresponse=substr($options,0,1));
510             $response=<STDIN>;
511             chomp $response;
512             (length($response)) || ($response=$defaultresponse);
513             if ( $response=~/.*[\:\(\)\^\$\*\!\\].*/ ) {
514                 ($noclear) || (system('clear'));
515                 print "Response contains invalid characters.  Choose from [$options].\n\n";
516                 print $message;
517                 $response='\0';
518             } else {
519                 unless ($options=~/$response/) {
520                     ($noclear) || (system('clear'));
521                     print "Invalid Response.  Choose from [$options].\n\n";
522                     print $message;
523                 }
524             }
525         }
526         return $response;
527     } elsif ($responsetype =~/^free$/i) {
528         (defined($defaultresponse)) || ($defaultresponse='');
529         my $response=<STDIN>;
530         chomp $response;
531         ($response) || ($response=$defaultresponse);
532         return $response;
533     } elsif ($responsetype =~/^numerical$/i) {
534         (defined($defaultresponse)) || ($defaultresponse='');
535         my $response='';
536         until ($response=~/^\d+$/) {
537             $response=<STDIN>;
538             chomp $response;
539             ($response) || ($response=$defaultresponse);
540             unless ($response=~/^\d+$/) {
541                 ($noclear) || (system('clear'));
542                 print "Invalid Response ($response).  Response must be a number.\n\n";
543                 print $message;
544             }
545         }
546         return $response;
547     } elsif ($responsetype =~/^email$/i) {
548         (defined($defaultresponse)) || ($defaultresponse='');
549         my $response='';
550         until ($response=~/.*\@.*\..*/) {
551             $response=<STDIN>;
552             chomp $response;
553             ($response) || ($response=$defaultresponse);
554             unless ($response=~/.*\@.*\..*/) {
555                 ($noclear) || (system('clear'));
556                 print "Invalid Response ($response).  Response must be a valid email address.\n\n";
557                 print $message;
558             }
559         }
560         return $response;
561     } elsif ($responsetype =~/^PressEnter$/i) {
562         <STDIN>;
563         return;
564     } elsif ($responsetype =~/^none$/i) {
565         return;
566     } else {
567         # FIXME: There are a few places where we will get an undef as the
568         # response type. Should we thrown an exception here, or should we
569         # legitimize this usage and say "none" is the default if not specified?
570         #die "Illegal response type \"$responsetype\"";
571     }
572 }
573
574
575 =back
576
577 =head2 Subtasks of doing an installation
578
579 =over 4
580
581 =cut
582
583 =item checkabortedinstall
584
585     checkabortedinstall;
586
587 Checks whether a previous installation process has been abnormally
588 aborted, by checking whether $etcidr/koha.conf is a symlink matching
589 a particular pattern.  If an aborted installation is detected, give
590 the user a chance to abort, before trying to recover the aborted
591 installation.
592
593 FIXME: The recovery is not complete; it only partially rolls back
594 some changes.
595
596 =cut
597
598 sub checkabortedinstall () {
599     if (-l("$etcdir/koha.conf")
600         && readlink("$etcdir/koha.conf") =~ /\.tmp$/
601     ) {
602         print qq|
603 I have detected that you tried to install Koha before, but the installation
604 was aborted.  I will try to continue, but there might be problems if the
605 database is already created.
606
607 |;
608         print "Please press <ENTER> to continue: ";
609         <STDIN>;
610
611         # Remove the symlink after the <STDIN>, so the user can back out
612         unlink "$etcdir/koha.conf"
613             || die "Failed to remove incomplete $etcdir/koha.conf: $!\n";
614     }
615 }
616
617
618 =item checkperlmodules
619
620     checkperlmodules;
621
622 Test whether the version of Perl is new enough, whether Perl is
623 found at the expected location, and whether all required modules
624 have been installed.
625
626 =cut
627
628 sub checkperlmodules {
629 #
630 # Test for Perl and Modules
631 #
632
633     my $message = getmessage('CheckingPerlModules');
634     showmessage($message, 'none');
635
636     unless ($] >= 5.006001) {                   # Bug 179
637         die getmessage('PerlVersionFailure', ['5.6.1']);
638     }
639
640     my @missing = ();
641     unless (eval {require DBI})              { push @missing,"DBI" };
642     unless (eval {require Date::Manip})      { push @missing,"Date::Manip" };
643     unless (eval {require DBD::mysql})       { push @missing,"DBD::mysql" };
644     unless (eval {require HTML::Template})   { push @missing,"HTML::Template" };
645 #    unless (eval {require Set::Scalar})      { push @missing,"Set::Scalar" };
646     unless (eval {require Digest::MD5})      { push @missing,"Digest::MD5" };
647     unless (eval {require MARC::Record})     { push @missing,"MARC::Record" };
648     unless (eval {require Mail::Sendmail})   { push @missing,"Mail::Sendmail" };
649     unless (eval {require Net::Z3950})       {
650         showmessage(getmessage('NETZ3950Missing'), 'PressEnter', '', 1);
651         if ($#missing>=0) { # XXX why only when $#missing >= 0?
652             push @missing, "Net::Z3950";
653         }
654     }
655
656 #
657 # Print out a list of any missing modules
658 #
659
660     if (@missing > 0) {
661         my $missing='';
662         foreach my $module (@missing) {
663             $missing.="   perl -MCPAN -e 'install \"$module\"'\n";
664         }
665         my $message=getmessage('MissingPerlModules', [$missing]);
666         showmessage($message, 'none');
667         exit;
668     } else {
669         showmessage(getmessage('AllPerlModulesInstalled'), 'PressEnter', '', 1);
670     }
671
672
673     unless (-x "/usr/bin/perl") {
674         my $realperl=`which perl`;
675         chomp $realperl;
676         $realperl = showmessage(getmessage('NoUsrBinPerl'), 'none');
677         until (-x $realperl) {
678             $realperl=showmessage(getmessage('AskLocationOfPerlExecutable', $realperl), 'free', $realperl, 1);
679         }
680         my $response=showmessage(getmessage('ConfirmPerlExecutableSymlink', $realperl), 'yn', 'y', 1);
681         unless ($response eq 'n') {
682             system("ln -s $realperl /usr/bin/perl");
683         }
684     }
685
686
687 }
688
689 $messages->{'NoUsrBinPerl'}->{en} =
690    heading('Perl is not located in /usr/bin/perl') . qq|
691 The Koha perl scripts expect to find the perl executable in the /usr/bin
692 directory.  It is not there on your system.
693
694 |;
695
696 $messages->{'AskLocationOfPerlExecutable'}->{en}=qq|Location of Perl Executable: [%s]: |;
697 $messages->{'ConfirmPerlExecutableSymlink'}->{en}=qq|
698 The Koha scripts will _not_ work without a symlink from %s to /usr/bin/perl
699
700 May I create this symlink? ([Y]/N):
701 : |;
702
703
704 =item getinstallationdirectories
705
706     getinstallationdirectories;
707
708 Get the various installation directories from the user, and then
709 create those directories (if they do not already exist).
710
711 These pieces of information are saved to global variables; the
712 function does not return any values.
713
714 =cut
715
716 sub getinstallationdirectories {
717     $opacdir = '/usr/local/koha/opac';
718     $intranetdir = '/usr/local/koha/intranet';
719     my $getdirinfo=1;
720     while ($getdirinfo) {
721         # Loop until opac directory and koha directory are different
722         my $message=getmessage('GetOpacDir', [$opacdir]);
723         $opacdir=showmessage($message, 'free', $opacdir);
724
725         $message=getmessage('GetIntranetDir', [$intranetdir]);
726         $intranetdir=showmessage($message, 'free', $intranetdir);
727
728         if ($intranetdir eq $opacdir) {
729             print qq|
730
731 You must specify different directories for the OPAC and INTRANET files!
732  :: $intranetdir :: $opacdir ::
733 |;
734 <STDIN>
735         } else {
736             $getdirinfo=0;
737         }
738     }
739     $kohalogdir='/var/log/koha';
740     my $message=getmessage('GetKohaLogDir', [$kohalogdir]);
741     $kohalogdir=showmessage($message, 'free', $kohalogdir);
742
743
744     # FIXME: Missing error handling for all mkdir calls here
745     unless ( -d $intranetdir ) {
746        mkdir_parents (dirname($intranetdir), 0775);
747        mkdir ($intranetdir,                  0770);
748        chown (oct(0), (getgrnam($httpduser))[2], "$intranetdir");
749        chmod (oct(770), "$intranetdir");
750     }
751     mkdir_parents ("$intranetdir/htdocs",    0750);
752     mkdir_parents ("$intranetdir/cgi-bin",   0750);
753     mkdir_parents ("$intranetdir/modules",   0750);
754     mkdir_parents ("$intranetdir/scripts",   0750);
755     unless ( -d $opacdir ) {
756        mkdir_parents (dirname($opacdir),     0775);
757        mkdir ($opacdir,                      0770);
758        chown (oct(0), (getgrnam($httpduser))[2], "$opacdir");
759        chmod (oct(770), "$opacdir");
760     }
761     mkdir_parents ("$opacdir/htdocs",        0750);
762     mkdir_parents ("$opacdir/cgi-bin",       0750);
763
764
765     unless ( -d $kohalogdir ) {
766        mkdir_parents (dirname($kohalogdir),  0775);
767        mkdir ($kohalogdir,                   0770);
768        chown (oct(0), (getgrnam($httpduser))[2,3], "$kohalogdir");
769        chmod (oct(770), "$kohalogdir");
770     }
771 }
772
773
774
775 =item getdatabaseinfo
776
777     getdatabaseinfo;
778
779 Get various pieces of information related to the Koha database:
780 the name of the database, the host on which the SQL server is
781 running, and the database user name.
782
783 These pieces of information are saved to global variables; the
784 function does not return any values.
785
786 =cut
787
788 $messages->{'DatabaseName'}->{en} = heading('Name of MySQL database') . qq|
789 Please provide the name of the mysql database for your koha installation.
790
791 Database name [%s]: |;
792
793 $messages->{'DatabaseHost'}->{en} = heading('Database Host') . qq|
794 Please provide the hostname for mysql.  Unless the database is located on
795 another machine this will be "localhost".
796
797 Database host [%s]: |;
798
799 $messages->{'DatabaseUser'}->{en} = heading('Database User') . qq|
800 Please provide the name of the user, who will have full administrative rights
801 to the %s database, when authenticating from %s.
802
803 This user will also be used to access Koha's INTRANET interface.
804
805 Database user [%s]: |;
806
807 $messages->{'DatabasePassword'}->{en} = heading('Database Password') . qq|
808 Please provide a good password for the user %s.
809
810 This password will also be used to access Koha's INTRANET interface.
811
812 Password for database user %s: |;
813
814 $messages->{'BlankPassword'}->{en} = heading('BLANK PASSWORD') . qq|
815 You must not use a blank password for your MySQL user!
816
817 Press <ENTER> to try again: 
818 |;
819
820 sub getdatabaseinfo {
821
822     $dbname = 'Koha';
823     $hostname = 'localhost';
824     $user = 'kohaadmin';
825     $pass = '';
826
827 #Get the database name
828
829     my $message=getmessage('DatabaseName', [$dbname]);
830     $dbname=showmessage($message, 'free', $dbname);
831
832 #Get the hostname for the database
833     
834     $message=getmessage('DatabaseHost', [$hostname]);
835     $hostname=showmessage($message, 'free', $hostname);
836
837 #Get the username for the database
838
839     $message=getmessage('DatabaseUser', [$dbname, $hostname, $user]);
840     $user=showmessage($message, 'free', $user);
841
842 #Get the password for the database user
843
844     while ($pass eq '') {
845         my $message=getmessage('DatabasePassword', [$user, $user]);
846         $pass=showmessage($message, 'free', $pass);
847         if ($pass eq '') {
848             my $message=getmessage('BlankPassword');
849             showmessage($message,'PressEnter');
850         }
851     }
852 }
853
854
855
856 =item getapacheinfo
857
858     getapacheinfo;
859
860 Get various pieces of information related to the Apache server:
861 the location of the configuration file and, if needed, the Unix
862 user that the Koha CGI will be run under.
863
864 These pieces of information are saved to global variables; the
865 function does not return any values.
866
867 =cut
868
869 $messages->{'FoundMultipleApacheConfFiles'}->{en} = 
870    heading('MULTIPLE APACHE CONFIG FILES') . qq|
871 I found more than one possible Apache configuration file:
872
873 %s
874
875 Choose the correct file [1]: |;
876
877 $messages->{'NoApacheConfFiles'}->{en} =
878    heading('NO APACHE CONFIG FILE FOUND') . qq|
879 I was not able to find your Apache configuration file.
880
881 The file is usually called httpd.conf or apache.conf.
882
883 Please specify the location of your config file: |;
884
885 $messages->{'NotAFile'}->{en} = heading('FILE DOES NOT EXIST') . qq|
886 The file %s does not exist.
887
888 Please press <ENTER> to continue: |;
889
890 $messages->{'EnterApacheUser'}->{en} = heading('NEED APACHE USER') . qq|
891 I was not able to determine the user that Apache is running as.  This
892 information is necessary in order to set the access privileges correctly on
893 %s/koha.conf.  This user should be set in one of the Apache configuration
894 files using the "User" directive.
895
896 Enter the Apache userid: |;
897
898 $messages->{'InvalidUserid'}->{en} = heading('INVALID USERID') . qq|
899 The userid %s is not a valid userid on this system.
900
901 Press <ENTER> to continue: |;
902
903 sub getapacheinfo {
904     my @confpossibilities;
905
906     foreach my $httpdconf (qw(/usr/local/apache/conf/httpd.conf
907                           /usr/local/etc/apache/httpd.conf
908                           /usr/local/etc/apache/apache.conf
909                           /var/www/conf/httpd.conf
910                           /etc/apache/conf/httpd.conf
911                           /etc/apache/conf/apache.conf
912                           /etc/apache-ssl/conf/apache.conf
913                           /etc/apache-ssl/httpd.conf
914                           /etc/httpd/conf/httpd.conf
915                           /etc/httpd/httpd.conf)) {
916         if ( -f $httpdconf ) {
917             push @confpossibilities, $httpdconf;
918         }
919     }
920
921     if ($#confpossibilities==-1) {
922         my $message=getmessage('NoApacheConfFiles');
923         my $choice='';
924         until (-f $realhttpdconf) {
925             $choice=showmessage($message, "free", 1);
926             if (-f $choice) {
927                 $realhttpdconf=$choice;
928             } else {
929                 showmessage(getmessage('NotAFile', [$choice]),'PressEnter', '', 1);
930             }
931         }
932     } elsif ($#confpossibilities>0) {
933         my $conffiles='';
934         my $counter=1;
935         my $options='';
936         foreach (@confpossibilities) {
937             $conffiles.="   $counter: $_\n";
938             $options.="$counter";
939             $counter++;
940         }
941         my $message=getmessage('FoundMultipleApacheConfFiles', [$conffiles]);
942         my $choice=showmessage($message, "restrictchar $options", 1);
943         $realhttpdconf=$confpossibilities[$choice-1];
944     } else {
945         $realhttpdconf=$confpossibilities[0];
946     }
947     unless (open (HTTPDCONF, "<$realhttpdconf")) {
948         warn "Insufficient privileges to open $realhttpdconf for reading.\n";
949         sleep 4;
950     }
951
952     while (<HTTPDCONF>) {
953         if (/^\s*User\s+"?([-\w]+)"?\s*$/) {
954             $httpduser = $1;
955         }
956     }
957     close(HTTPDCONF);
958
959
960
961
962     unless ($httpduser) {
963         my $message=getmessage('EnterApacheUser', [$etcdir]);
964         until (length($httpduser) && getpwnam($httpduser)) {
965             $httpduser=showmessage($message, "free", '');
966             if (length($httpduser)>0) {
967                 unless (getpwnam($httpduser)) {
968                     my $message=getmessage('InvalidUserid', [$httpduser]);
969                     showmessage($message,'PressEnter');
970                 }
971             } else {
972             }
973         }
974         print "AU: $httpduser\n";
975     }
976 }
977
978
979 =item getapachevhostinfo
980
981     getapachevhostinfo;
982
983 Gets various pieces of information related to virtual hosting:
984 the webmaster email address, virtual hostname, and the ports
985 that the OPAC and INTRANET modules run on.
986
987 These pieces of information are saved to global variables; the
988 function does not return any values.
989
990 =cut
991
992 $messages->{'ApacheConfigIntroduction'}->{en} =
993    heading('APACHE CONFIGURATION') . qq|
994 Koha needs to setup your Apache configuration file for the
995 OPAC and LIBRARIAN virtual hosts.  By default this installer
996 will do this by using one ip address and two different ports
997 for the virtual hosts.  There are other ways to set this up,
998 and the installer will leave comments in httpd.conf detailing
999 what these other options are.
1000
1001
1002 Press <ENTER> to continue: |;
1003
1004 $messages->{'GetVirtualHostEmail'}->{en} =
1005    heading('WEB SERVER E-MAIL CONTACT') . qq|
1006 Enter the e-mail address to be used as a contact for the virtual hosts (this
1007 address is displayed if any errors are encountered).
1008
1009 E-mail contact [%s]: |;
1010
1011 $messages->{'GetServerName'}->{en} =
1012    heading('WEB SERVER HOST NAME OR IP ADDRESS') . qq|
1013 Please enter the domain name or ip address of your computer.
1014
1015 Host name or IP Address [%s]: |;
1016
1017 $messages->{'GetOpacPort'}->{en} = heading('OPAC VIRTUAL HOST PORT') . qq|
1018 Please enter the port for your OPAC interface.  This defaults to port 80, but
1019 if you are already serving web content from this server, you should change it
1020 to a different port (8000 might be a good choice).
1021
1022 Enter the OPAC Port [%s]: |;
1023
1024 $messages->{'GetIntranetPort'}->{en} =
1025    heading('INTRANET VIRTUAL HOST PORT') . qq|
1026 Please enter the port for your Intranet interface.  This must be different from
1027 the OPAC port (%s).
1028
1029 Enter the Intranet Port [%s]: |;
1030
1031
1032 sub getapachevhostinfo {
1033
1034     $svr_admin = "webmaster\@$domainname";
1035     $servername=`hostname`;
1036     chomp $servername;
1037     $opacport=80;
1038     $intranetport=8080;
1039
1040     showmessage(getmessage('ApacheConfigIntroduction'), 'PressEnter');
1041
1042     $svr_admin=showmessage(getmessage('GetVirtualHostEmail', [$svr_admin]), 'email', $svr_admin);
1043     $servername=showmessage(getmessage('GetServerName', [$servername]), 'free', $servername);
1044
1045
1046     $opacport=showmessage(getmessage('GetOpacPort', [$opacport]), 'numerical', $opacport);
1047     $intranetport=showmessage(getmessage('GetIntranetPort', [$opacport, $intranetport]), 'numerical', $intranetport);
1048
1049 }
1050
1051
1052 =item updateapacheconf
1053
1054     updateapacheconf;
1055
1056 Updates the Apache config file according to parameters previously
1057 specified by the user.
1058
1059 It will append fully-commented directives at the end of the original
1060 Apache config file.  The old config file is renamed with an extension
1061 of .prekoha.
1062
1063 If you need to uninstall Koha for any reason, the lines between
1064
1065     # Ports to listen to for Koha
1066
1067 and the block of comments beginning with
1068
1069     # If you want to use name based Virtual Hosting:
1070
1071 must be removed.
1072
1073 =cut
1074
1075 $messages->{'StartUpdateApache'}->{en} =
1076    heading('UPDATING APACHE CONFIGURATION') . qq|
1077 Checking for modules that need to be loaded...
1078 |;
1079
1080 $messages->{'LoadingApacheModuleModEnv'}->{en}="Loading SetEnv Apache module.\n";
1081
1082 $messages->{'LoadingApacheModuleModInc'}->{en}="Loading Includes Apache module.\n";
1083
1084 $messages->{'ApacheConfigBackupFailed'}->{en} =
1085    heading('APACHE CONFIGURATION BACKUP FAILED') . qq|
1086 An error occurred while trying to make a backup copy of %s.
1087
1088   %s
1089
1090 No changes will be made to the apache configuration file at this time.
1091
1092 Press <ENTER> to continue: |;
1093
1094
1095 $messages->{'ApacheAlreadyConfigured'}->{en} =
1096    heading('APACHE ALREADY CONFIGURED') . qq|
1097 %s appears to already have an entry for Koha
1098 Virtual Hosts.  You may need to edit %s
1099 f anything has changed since it was last set up.  This
1100 script will not attempt to modify an existing Koha apache
1101 configuration.
1102
1103 Press <ENTER> to continue: |;
1104
1105 sub updateapacheconf {
1106     my $logfiledir=`grep ^ErrorLog "$realhttpdconf"`;
1107     chomp $logfiledir;
1108
1109     if ($logfiledir) {
1110         $logfiledir=~m#ErrorLog (.*)/[^/]*$#
1111             or die "Can't parse ErrorLog directive\n";
1112         $logfiledir=$1;
1113     }
1114
1115     unless ($logfiledir) {
1116         $logfiledir='logs';
1117     }
1118
1119     showmessage(getmessage('StartUpdateApache'), 'none');
1120
1121     my $httpdconf;
1122     my $envmodule=0;
1123     my $includesmodule=0;
1124     open HC, "<$realhttpdconf";
1125     while (<HC>) {
1126         if (/^\s*#\s*LoadModule env_module /) {
1127             s/^\s*#\s*//;
1128             showmessage(getmessage('LoadingApacheModuleModEnv'));
1129             $envmodule=1;
1130         }
1131         if (/^\s*#\s*LoadModule includes_module /) {
1132             s/^\s*#\s*//;
1133             showmessage(getmessage('LoadingApacheModuleModInc'));
1134         }
1135         if (/\s*LoadModule includes_module / ) {
1136             $includesmodule=1;
1137         }
1138         $httpdconf.=$_;
1139     }
1140
1141     my $backupfailed=0;
1142     $backupfailed=`cp -f $realhttpdconf $realhttpdconf\.prekoha`;
1143     if ($backupfailed) {
1144         showmessage(getmessage('ApacheConfigBackupFailed', [$realhttpdconf,$backupfailed ]), 'PressEnter');
1145         return;
1146     }
1147
1148     if ($envmodule || $includesmodule) {
1149         open HC, ">$realhttpdconf";
1150         print HC $httpdconf;
1151         close HC;
1152     }
1153
1154
1155     
1156     if (`grep 'VirtualHost $servername' "$realhttpdconf"`) {
1157         showmessage(getmessage('ApacheAlreadyConfigured', [$realhttpdconf, $realhttpdconf]), 'PressEnter');
1158         return;
1159     } else {
1160         my $includesdirectives='';
1161         if ($includesmodule) {
1162             $includesdirectives.="Options +Includes\n";
1163             $includesdirectives.="   AddHandler server-parsed .html\n";
1164         }
1165         open(SITE,">>$realhttpdconf") or warn "Insufficient priveleges to open $realhttpdconf for writing.\n";
1166         my $opaclisten = '';
1167         if ($opacport != 80) {
1168             $opaclisten="Listen $opacport";
1169         }
1170         my $intranetlisten = '';
1171         if ($intranetport != 80) {
1172             $intranetlisten="Listen $intranetport";
1173         }
1174         print SITE <<EOP
1175
1176 # Ports to listen to for Koha
1177 $opaclisten
1178 $intranetlisten
1179
1180 # NameVirtualHost is used by one of the optional configurations detailed below
1181
1182 #NameVirtualHost 11.22.33.44
1183
1184 # KOHA's OPAC Configuration
1185 <VirtualHost $servername\:$opacport>
1186    ServerAdmin $svr_admin
1187    DocumentRoot $opacdir/htdocs
1188    ServerName $servername
1189    ScriptAlias /cgi-bin/koha/ $opacdir/cgi-bin/
1190    ErrorLog $logfiledir/opac-error_log
1191    TransferLog $logfiledir/opac-access_log
1192    SetEnv PERL5LIB "$intranetdir/modules"
1193    $includesdirectives
1194 </VirtualHost>
1195
1196 # KOHA's INTRANET Configuration
1197 <VirtualHost $servername\:$intranetport>
1198    ServerAdmin $svr_admin
1199    DocumentRoot $intranetdir/htdocs
1200    ServerName $servername
1201    ScriptAlias /cgi-bin/koha/ "$intranetdir/cgi-bin/"
1202    ErrorLog $logfiledir/koha-error_log
1203    TransferLog $logfiledir/koha-access_log
1204    SetEnv PERL5LIB "$intranetdir/modules"
1205    $includesdirectives
1206 </VirtualHost>
1207
1208 # If you want to use name based Virtual Hosting:
1209 #   1. remove the two Listen lines
1210 #   2. replace $servername\:$opacport wih your.opac.domain.name
1211 #   3. replace ServerName $servername wih ServerName your.opac.domain.name
1212 #   4. replace $servername\:$intranetport wih your intranet domain name
1213 #   5. replace ServerName $servername wih ServerName your.intranet.domain.name
1214 #
1215 # If you want to use NameVirtualHost'ing (using two names on one ip address):
1216 #   1.  Follow steps 1-5 above
1217 #   2.  Uncomment the NameVirtualHost line and set the correct ip address
1218
1219 EOP
1220
1221
1222     }
1223 }
1224
1225
1226 =item basicauthentication
1227
1228     basicauthentication;
1229
1230 Asks the user whether HTTP basic authentication is wanted, and,
1231 if so, the user name and password for the basic authentication.
1232
1233 These pieces of information are saved to global variables; the
1234 function does not return any values.
1235
1236 =cut
1237
1238 $messages->{'IntranetAuthenticationQuestion'}->{en} =
1239    heading('INTRANET AUTHENTICATION') . qq|
1240 I can set it up so that the Intranet/Librarian site is password protected using
1241 Apache's Basic Authorization.
1242
1243 This is going to be phased out very soon. However, setting this up can provide
1244 an extra layer of security before the new authentication system is completely
1245 in place.
1246
1247 Would you like to do this ([Y]/N): |;   #'
1248
1249 $messages->{'BasicAuthUsername'}->{en}="Please enter a userid for intranet access [%s]: ";
1250 $messages->{'BasicAuthPassword'}->{en}="Please enter a password for %s: ";
1251 $messages->{'BasicAuthPasswordWasBlank'}->{en}="\nYou cannot use a blank password!\n\n";
1252
1253 sub basicauthentication {
1254     my $message=getmessage('IntranetAuthenticationQuestion');
1255     my $answer=showmessage($message, 'yn', 'y');
1256
1257     my $apacheauthusername='librarian';
1258     my $apacheauthpassword='';
1259     if ($answer=~/^y/i) {
1260         ($apacheauthusername) = showmessage(getmessage('BasicAuthUsername', [ $apacheauthusername]), 'free', $apacheauthusername, 1);
1261         $apacheauthusername=~s/[^a-zA-Z0-9]//g;
1262         while (! $apacheauthpassword) {
1263             ($apacheauthpassword) = showmessage(getmessage('BasicAuthPassword', [ $apacheauthusername]), 'free', 1);
1264             if (!$apacheauthpassword) {
1265                 ($apacheauthpassword) = showmessage(getmessage('BasicAuthPasswordWasBlank'), 'none', '', 1);
1266             }
1267         }
1268         open AUTH, ">$etcdir/kohaintranet.pass";
1269         my $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
1270         my $salt=substr($chars, int(rand(length($chars))),1);
1271         $salt.=substr($chars, int(rand(length($chars))),1);
1272         print AUTH $apacheauthusername.":".crypt($apacheauthpassword, $salt)."\n";
1273         close AUTH;
1274         open(SITE,">>$realhttpdconf") or warn "Insufficient priveleges to open $realhttpdconf for writing.\n";
1275         print SITE <<EOP
1276
1277 <Directory $intranetdir>
1278     AuthUserFile $etcdir/kohaintranet.pass
1279     AuthType Basic
1280     AuthName "Koha Intranet (for librarians only)"
1281     Require  valid-user
1282 </Directory>
1283 EOP
1284     }
1285     close(SITE);
1286 }
1287
1288
1289 =item installfiles
1290
1291     installfiles
1292
1293 Install the Koha files to the specified OPAC and INTRANET
1294 directories (usually in /usr/local/koha).
1295
1296 The koha.conf file is created, but as koha.conf.tmp. The
1297 caller is responsible for calling finalizeconfigfile when
1298 installation is completed, to rename it back to koha.conf.
1299
1300 =cut
1301
1302 $messages->{'InstallFiles'}->{en} = heading('INSTALLING FILES') . qq|
1303 Copying files to installation directories:
1304
1305 |;
1306
1307
1308 $messages->{'CopyingFiles'}->{en}="Copying %s to %s.\n";
1309
1310
1311
1312 sub installfiles {
1313
1314
1315     showmessage(getmessage('InstallFiles'),'none');
1316     print getmessage('CopyingFiles', ['intranet-html', "$intranetdir/htdocs" ]);
1317     system("cp -R intranet-html/* $intranetdir/htdocs/");
1318     print getmessage('CopyingFiles', ['intranet-cgi', "$intranetdir/cgi-bin" ]);
1319     system("cp -R intranet-cgi/* $intranetdir/cgi-bin/");
1320     print getmessage('CopyingFiles', ['stand-alone scripts', "$intranetdir/scripts" ]);
1321     system("cp -R scripts/* $intranetdir/scripts/");
1322     print getmessage('CopyingFiles', ['perl modules', "$intranetdir/modules" ]);
1323     system("cp -R modules/* $intranetdir/modules/");
1324     print getmessage('CopyingFiles', ['opac-html', "$opacdir/htdocs" ]);
1325     system("cp -R opac-html/* $opacdir/htdocs/");
1326     print getmessage('CopyingFiles', ['opac-cgi', "$opacdir/cgi-bin" ]);
1327     system("cp -R opac-cgi/* $opacdir/cgi-bin/");
1328     system("touch $opacdir/cgi-bin/opac");
1329
1330     system("chown -R $httpduser:$httpduser $opacdir");
1331     system("chown -R $httpduser:$httpduser $intranetdir");
1332
1333     # Create /etc/koha.conf
1334
1335     my $old_umask = umask(027); # make sure koha.conf is never world-readable
1336     open(SITES,">$etcdir/koha.conf.tmp") or warn "Couldn't create file at $etcdir. Must have write capability.\n";
1337     print SITES qq|
1338 database=$dbname
1339 hostname=$hostname
1340 user=$user
1341 pass=$pass
1342 includes=$opacdir/htdocs/includes
1343 intranetdir=$intranetdir
1344 opacdir=$opacdir
1345 kohalogdir=$kohalogdir
1346 kohaversion=$kohaversion
1347 httpduser=$httpduser
1348 intrahtdocs=$intranetdir/htdocs/intranet-tmpl
1349 opachtdocs=$opacdir/htdocs/opac-tmpl
1350 |;
1351     close(SITES);
1352     umask($old_umask);
1353
1354     chown((getpwnam($httpduser)) [2,3], "$etcdir/koha.conf.tmp") or warn "can't chown koha.conf: $!";
1355     chmod 0440, "$etcdir/koha.conf.tmp";
1356
1357     chmod 0750, "$intranetdir/scripts/z3950daemon/z3950-daemon-launch.sh";
1358     chmod 0750, "$intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh";
1359     chmod 0750, "$intranetdir/scripts/z3950daemon/processz3950queue";
1360     chown(0, (getpwnam($httpduser)) [3], "$intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh") or warn "can't chown $intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh: $!";
1361     chown(0, (getpwnam($httpduser)) [3], "$intranetdir/scripts/z3950daemon/processz3950queue") or warn "can't chown $intranetdir/scripts/z3950daemon/processz3950queue: $!";
1362
1363 }
1364
1365
1366 =item databasesetup
1367
1368     databasesetup;
1369
1370 Finds out where the MySQL utitlities are located in the system,
1371 then create the Koha database structure and MySQL permissions.
1372
1373 =cut
1374
1375 $messages->{'MysqlRootPassword'}->{en} =
1376    heading('MYSQL ROOT USER PASSWORD') . qq|
1377 To allow us to create the koha database please supply your
1378 mysql server's root user password:
1379
1380 Enter MySQL root user password: |;      #'
1381
1382 $messages->{'InvalidMysqlRootPassword'}->{en}="Invalid Password.  Please try again.";
1383
1384 $messages->{'CreatingDatabase'}->{en} = heading('CREATING DATABASE') . qq|
1385 Creating the MySQL database for Koha...
1386
1387 |;
1388
1389 $messages->{'CreatingDatabaseError'}->{en} =
1390    heading('ERROR CREATING DATABASE') . qq|
1391 Couldn't connect to the MySQL server for the reason given above.
1392 This is a serious problem, the database will not get installed.\a
1393
1394 Press <ENTER> to continue: |;   #'
1395
1396 $messages->{'SampleData'}->{en} = heading('SAMPLE DATA') . qq|
1397 If you are installing Koha for evaluation purposes,  I have a batch of sample
1398 data that you can install now.
1399
1400 If you are installing Koha with the intention of populating it with your own
1401 data, you probably don't want this sample data installed.
1402
1403 Would you like to install the sample data? Y/[N]: |;    #'
1404
1405 $messages->{'SampleDataInstalled'}->{en} =
1406    heading('SAMPLE DATA INSTALLED') . qq|
1407 Sample data has been installed.  For some suggestions on testing Koha, please
1408 read the file doc/HOWTO-Testing.  If you find any bugs, please submit them at
1409 http://bugs.koha.org/.  If you need help with testing Koha, you can post a
1410 question through the koha-devel mailing list, or you can check for a developer
1411 online at +irc.katipo.co.nz:6667 channel #koha.
1412
1413 You can find instructions for subscribing to the Koha mailing lists at:
1414
1415     http://www.koha.org
1416
1417
1418 Press <ENTER> to continue: |;
1419
1420 $messages->{'AddBranchPrinter'}->{en} = heading('Add Branch and Printer') . qq|
1421 Would you like to install an initial branch and printer? [Y]/N: |;
1422
1423 $messages->{'BranchName'}->{en}="Branch Name [%s]: ";
1424 $messages->{'BranchCode'}->{en}="Branch Code (4 letters or numbers) [%s]: ";
1425 $messages->{'PrinterQueue'}->{en}="Printer Queue [%s]: ";
1426 $messages->{'PrinterName'}->{en}="Printer Name [%s]: ";
1427 $messages->{'BlankMysqlPassword'}->{en} = heading('Blank MySQL Password') . qq|
1428 Do not leave your MySQL root password blank unless you know exactly what you
1429 are doing.  To change your MySQL root password use the mysqladmin command:
1430
1431 mysqladmin password NEWPASSWORDHERE
1432
1433 Press <ENTER> to continue:
1434 |;
1435
1436 sub databasesetup {
1437     $mysqluser = 'root';
1438     $mysqlpass = '';
1439
1440     foreach my $mysql (qw(/usr/local/mysql
1441                           /opt/mysql
1442                           /usr
1443                           )) {
1444        if ( -d $mysql  && -f "$mysql/bin/mysqladmin") {
1445             $mysqldir=$mysql;
1446        }
1447     }
1448     if (!$mysqldir){
1449         print "I don't see mysql in the usual places.\n";
1450         for (;;) {
1451             print "Where have you installed mysql? ";
1452             chomp($mysqldir = <STDIN>);
1453             last if -f "$mysqldir/bin/mysqladmin";
1454         print <<EOP;
1455
1456 I can't find it there either. If you compiled mysql yourself,
1457 please give the value of --prefix when you ran configure.
1458
1459 The file mysqladmin should be in bin/mysqladmin under the directory that you
1460 provide here.
1461
1462 EOP
1463 #'
1464         }
1465     }
1466
1467
1468     my $needpassword=1;
1469     while ($needpassword) {
1470         $mysqlpass=showmessage(getmessage('MysqlRootPassword'), 'free');
1471         $mysqlpass_quoted = $mysqlpass;
1472         $mysqlpass_quoted =~ s/"/\\"/g;
1473         $mysqlpass_quoted="-p\"$mysqlpass_quoted\"";
1474         $mysqlpass eq '' and $mysqlpass_quoted='';
1475         my $result=system("$mysqldir/bin/mysqladmin -u$mysqluser $mysqlpass_quoted proc > /dev/null 2>&1");
1476         if ($result) {
1477             print getmessage('InvalidMysqlRootPassword');
1478         } else {
1479             if ($mysqlpass eq '') {
1480                 showmessage(getmessage('BlankMysqlPassword'), 'PressEnter');
1481             }
1482             $needpassword=0;
1483         }
1484     }
1485
1486     showmessage(getmessage('CreatingDatabase'),'none');
1487
1488     my $result=system("$mysqldir/bin/mysqladmin", "-u$mysqluser", "-p$mysqlpass", "create", "$dbname");
1489     if ($result) {
1490         showmessage(getmessage('CreatingDatabaseError'),'PressEnter', '', 1);
1491     } else {
1492         # Create the database structure
1493         system("$mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname < koha.mysql");
1494         # Set up permissions
1495         system("$mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted mysql -e \"insert into user (Host,User,Password) values ('$hostname','$user',password('$pass'))\"\;");
1496         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')\"");
1497         system("$mysqldir/bin/mysqladmin -u$mysqluser $mysqlpass_quoted reload");
1498
1499
1500
1501
1502
1503     }
1504
1505 }
1506
1507
1508 =item updatedatabase
1509
1510     updatedatabase;
1511
1512 Updates the Koha database structure, including the addition of
1513 MARC tables.
1514
1515 The MARC tables are also populated in addition to being created.
1516
1517 Because updatedatabase calls scripts/updater/updatedatabase to
1518 do the actual update, and that script uses C4::Context,
1519 $etcdir/koha.conf must exist at this point. We use a symlink to
1520 do this and to also at the same time faciliate detection of
1521 ahorted installs. (See checkabortedinstall.)
1522
1523 =cut
1524
1525 $messages->{'UpdateMarcTables'}->{en} =
1526    heading('UPDATING MARC FIELD DEFINITION TABLES') . qq|
1527 You can import marc parameters for :
1528
1529   1 MARC21
1530   2 UNIMARC
1531   N none
1532
1533 Please choose which parameter you want to install. Note if you choose 3,
1534 nothing will be added, and it can be a BIG job to manually create those tables
1535
1536 Choose MARC definition [1]: |;
1537
1538 $messages->{'Language'}->{en} = heading('CHOOSE LANGUAGES') . qq|
1539 This version of koha supports a few languages.
1540 Enter your language preference : either en, fr, es, pl or zh_TW
1541
1542 Note that the en is always choosen when the system does not finds the
1543 language you choose in a specific screen.
1544
1545 fr : all is translated (except pictures)
1546 es : a few intranet is translated (including pictures)
1547 pl : OPAC and a few intranet is translated
1548 zh_TW : partial translation
1549
1550 Whether you specify a language here, you can always go to the
1551 intranet interface and change it from the system preferences.
1552
1553 Which language do you choose? |;
1554
1555 sub updatedatabase {
1556     # At this point, $etcdir/koha.conf must exist, for C4::Context
1557         my $result=system ("perl -I $intranetdir/modules scripts/updater/updatedatabase");
1558         if ($result) {
1559                 print "Problem updating database...\n";
1560                 exit;
1561         }
1562
1563         my $response=showmessage(getmessage('UpdateMarcTables'), 'restrictchar 12N', '1');
1564
1565         if ($response eq '1') {
1566                 system("cat scripts/misc/marc_datas/marc21_en/structure_def.sql | $mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname");
1567         }
1568         if ($response eq '2') {
1569                 system("cat scripts/misc/marc_datas/unimarc_fr/structure_def.sql | $mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname");
1570                 system("cat scripts/misc/lang-datas/fr/stopwords.sql | $mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname");
1571         }
1572
1573         $result = system ("perl -I $intranetdir/modules scripts/marc/updatedb2marc.pl");
1574         if ($result) {
1575                 print "Problem updating database to MARC...\n";
1576                 exit;
1577         }
1578
1579         print "\n\nFinished updating of database. Press <ENTER> to continue...";
1580         <STDIN>;
1581 }
1582
1583
1584 =item populatedatabase
1585
1586     populatedatabase;
1587
1588 Populate the non-MARC tables. If the user wants to install the
1589 sample data, install them.
1590
1591 =cut
1592
1593 sub populatedatabase {
1594         my $response=showmessage(getmessage('SampleData'), 'yn', 'n');
1595         if ($response =~/^y/i) {
1596                 system("gunzip -d < sampledata-1.2.gz | $mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname");
1597                 system("$mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname -e \"insert into branches (branchcode,branchname,issuing) values ('MAIN', 'Main Library', 1)\"");
1598                 system("$mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'IS')\"");
1599                 system("$mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'CU')\"");
1600                 system("$mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname -e \"insert into printers (printername,printqueue,printtype) values ('Circulation Desk Printer', 'lp', 'hp')\"");
1601                 showmessage(getmessage('SampleDataInstalled'), 'PressEnter','',1);
1602         } else {
1603                 my $input;
1604                 my $response=showmessage(getmessage('AddBranchPrinter'), 'yn', 'y');
1605
1606                 unless ($response =~/^n/i) {
1607                 my $branch='Main Library';
1608                 $branch=showmessage(getmessage('BranchName', [$branch]), 'free', $branch, 1);
1609                 $branch=~s/[^A-Za-z0-9\s]//g;
1610
1611                 my $branchcode=$branch;
1612                 $branchcode=~s/[^A-Za-z0-9]//g;
1613                 $branchcode=uc($branchcode);
1614                 $branchcode=substr($branchcode,0,4);
1615                 $branchcode=showmessage(getmessage('BranchCode', [$branchcode]), 'free', $branchcode, 1);
1616                 $branchcode=~s/[^A-Za-z0-9]//g;
1617                 $branchcode=uc($branchcode);
1618                 $branchcode=substr($branchcode,0,4);
1619                 $branchcode or $branchcode='DEF';
1620
1621                 system("$mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname -e \"insert into branches (branchcode,branchname,issuing) values ('$branchcode', '$branch', 1)\"");
1622                 system("$mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'IS')\"");
1623                 system("$mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'CU')\"");
1624
1625                 my $printername='Library Printer';
1626                 $printername=showmessage(getmessage('PrinterName', [$printername]), 'free', $printername, 1);
1627                 $printername=~s/[^A-Za-z0-9\s]//g;
1628
1629                 my $printerqueue='lp';
1630                 $printerqueue=showmessage(getmessage('PrinterQueue', [$printerqueue]), 'free', $printerqueue, 1);
1631                 $printerqueue=~s/[^A-Za-z0-9]//g;
1632                 system("$mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname -e \"insert into printers (printername,printqueue,printtype) values ('$printername', '$printerqueue', '')\"");
1633                 }
1634         my $language=showmessage(getmessage('Language'), 'free', 'en');
1635         system("$mysqldir/bin/mysql -u$mysqluser $mysqlpass_quoted $dbname -e \"update systempreferences set value='$language' where variable='opaclanguages'\"");
1636         }
1637 }
1638
1639
1640 =item restartapache
1641
1642     restartapache;
1643
1644 Asks the user whether to restart Apache, and restart it if the user
1645 wants so.
1646
1647 FIXME: If the installer does not know how to restart the Apache
1648 server (e.g., if the user is not actually using Apache), it still
1649 asks the question.
1650
1651 =cut
1652
1653 $messages->{'RestartApache'}->{en} = heading('RESTART APACHE') . qq|
1654 Apache needs to be restarted to load the new configuration for Koha.
1655
1656 Would you like to restart Apache now?  [Y]/N: |;
1657
1658 sub restartapache {
1659
1660     my $response=showmessage(getmessage('RestartApache'), 'yn', 'y');
1661
1662
1663
1664     unless ($response=~/^n/i) {
1665         # Need to support other init structures here?
1666         if (-e "/etc/rc.d/init.d/httpd") {
1667             system('/etc/rc.d/init.d/httpd restart');
1668         } elsif (-e "/etc/init.d/apache") {
1669             system('/etc//init.d/apache restart');
1670         } elsif (-e "/etc/init.d/apache-ssl") {
1671             system('/etc/init.d/apache-ssl restart');
1672         }
1673     }
1674
1675 }
1676
1677
1678 =item finalizeconfigfile
1679
1680    finalizeconfigfile;
1681
1682 This function must be called when the installation is complete,
1683 to rename the koha.conf.tmp file to koha.conf.
1684
1685 Currently, failure to rename the file results only in a warning.
1686
1687 =cut
1688
1689 sub finalizeconfigfile {
1690    rename "$etcdir/koha.conf.tmp", "$etcdir/koha.conf"
1691       || showmessage(<<EOF, 'PressEnter', undef, 1);
1692 An unexpected error, $!, occurred
1693 while the Koha config file is being saved to its final location,
1694 $etcdir/koha.conf.
1695
1696 Couldn't rename file at $etcdir. Must have write capability.
1697
1698 Press Enter to continue.
1699 EOF
1700 #'
1701 }
1702
1703
1704 =item loadconfigfile
1705
1706    loadconfigfile
1707
1708 Open the existing koha.conf file and get its values,
1709 saving the values to some global variables.
1710
1711 If the existing koha.conf file cannot be opened for any reason,
1712 the file is silently ignored.
1713
1714 =cut
1715
1716 sub loadconfigfile {
1717     my %configfile;
1718
1719     open (KC, "<$etcdir/koha.conf");
1720     while (<KC>) {
1721      chomp;
1722      (next) if (/^\s*#/);
1723      if (/(.*)\s*=\s*(.*)/) {
1724        my $variable=$1;
1725        my $value=$2;
1726        # Clean up white space at beginning and end
1727        $variable=~s/^\s*//g;
1728        $variable=~s/\s*$//g;
1729        $value=~s/^\s*//g;
1730        $value=~s/\s*$//g;
1731        $configfile{$variable}=$value;
1732      }
1733     }
1734
1735     $intranetdir=$configfile{'intranetdir'};
1736     $opacdir=$configfile{'opacdir'};
1737     $kohaversion=$configfile{'kohaversion'};
1738     $kohalogdir=$configfile{'kohalogdir'};
1739     $database=$configfile{'database'};
1740     $hostname=$configfile{'hostname'};
1741     $user=$configfile{'user'};
1742     $pass=$configfile{'pass'};
1743 }
1744
1745 END { }       # module clean-up code here (global destructor)
1746
1747 =back
1748
1749 =head1 SEE ALSO
1750
1751 buildrelease.pl,
1752 installer.pl
1753
1754 =cut
1755
1756 1;