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