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