fixing permissions on scripts
[koha.git] / misc / Install.pm
1 package Install; #assumes Install.pm
2
3
4 # Copyright 2000-2002 Katipo Communications
5 # Contains parts Copyright 2003-4 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 # Current maintainer MJR slef at users.sourceforge.net
23
24 use strict;
25 use POSIX;
26 #MJR: everyone will have these modules, right?
27 # They look like part of perl core to me
28 use Term::ANSIColor qw(:constants);
29 use Text::Wrap;
30 use File::Temp qw/ :mktemp /;
31 require Exporter;
32
33 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
34
35 =head1 NAME
36
37 Install.pm - Perl module containing the bulk of the installation logic
38
39 =head1 DESCRIPTION
40
41 The Install.pm module contains the bulk
42 of the code to do installation;
43 this code is used by installer.pl
44 to perform an actual installation.
45
46 =head2 Internal variables
47
48 =over 4
49
50 =item $VERSION, @ISA, @EXPORT
51
52 Defines the version and structure of the module interface
53
54 =cut
55
56 # set the version for version checking
57 # set the version for version checking
58 $VERSION = do { my @v = '$Revision$' =~ /\d+/g; shift(@v) . "." . join( "_", map { sprintf "%03d", $_ } @v ); };
59
60 @ISA = qw(Exporter);
61 @EXPORT = qw(
62                 &read_autoinstall_file
63                 &checkperlmodules
64                 &checkabortedinstall
65                 &getmessage
66                 &showmessage
67                 &completeupgrade
68                 &releasecandidatewarning
69                 &getinstallationdirectories
70                 &getdatabaseinfo
71                 &getapacheinfo
72                 &getapachevhostinfo
73                 &updateapacheconf
74                 &basicauthentication
75                 &installfiles
76                 &databasesetup
77                 &updatedatabase
78                 &populatedatabase
79                 &restartapache
80                 &backupkoha
81                 &finalizeconfigfile
82                 &loadconfigfile
83                 &backupmycnf
84                 &restoremycnf
85                 );
86
87 =item $kohaversion, $newversion, $language, $clear_string
88
89 Installer setting details
90
91 =item $etcdir, $intranetdir, $opacdir, $kohalogdir
92
93 Directories to use for installation (configuration, intranet, opac, logs)
94
95 =item $domainname, $realhttpdconf, $httpduser, $httpdgroup, $servername, $svr_admin, $opacport, $intranetport, $hostname, $user, $pass
96
97 Apache configuration settings
98
99 =item $mysqldir, $database, $mysqluser, $mysqlpass, $mycnf, $mytmpcnf
100
101 MySQL configuration settings
102
103 =cut
104
105 use vars qw( $kohaversion $newversion $language
106   $etcdir $intranetdir $opacdir $kohalogdir
107   $domainname $realhttpdconf $httpduser $httpdgroup
108   $servername $svr_admin $opacport $intranetport
109   $hostname $user $pass
110   $mysqldir $database $mysqluser $mysqlpass );
111
112 my $clear_string = "\n\n"; #MJR: was $terminal->Tputs('cl');
113
114 my $mycnf = $ENV{HOME}."/.my.cnf";
115 my $mytmpcnf = mktemp("my.cnf.koha.XXXXXX");
116 chomp($mytmpcnf);
117
118 =back
119
120 =head2 Internal functions (not meant to be used outside of Install.pm)
121
122 =over 4
123
124 =item C<heading($)>
125
126 Takes: a string to be displayed as the heading
127
128 Returns: a formatted heading (currently with ANSI colours).
129
130 This reduces the likelihood of pod2man(1) etc. misinterpreting
131 a line of equal signs as illegal POD directives.
132
133 =cut
134
135 sub heading ($) {
136   my $title = shift;
137   my $bal = 5;
138   return($clear_string.ON_BLUE.WHITE.BOLD." "x$bal.uc($title)." "x$bal.RESET."\n\n");
139 }
140
141 my $messages;
142 $messages->{'continuing'}->{en}="Great!  Continuing...\n\n";
143 $messages->{'WelcomeToKohaInstaller'}->{en} =
144    heading('Welcome to the Koha Installer') . qq|
145 This program will ask some questions and try to install koha for you.
146 You need to know: where most koha files should be stored (you can set
147 the prefix environment variable for this); the username and password of
148 a mysql superuser; and details of your library setup.  You may also need
149 to know details of your Apache setup.
150
151 If you want to install the Koha configuration files somewhere other than
152 /etc (for installing not as root, or to have many Kohas on one system, for example), you should
153 set the etcdir environment variable.  Please look at your manuals for
154 details of how to set that.
155
156 Recommended answers are given in brackets after each question.  To accept
157 the default value for any question (indicated by []), simply hit Enter
158 at the prompt.
159
160 Note that you also can define an auto_install_file, that will answer every question automatically.
161 To use this feature, run ./installer.pl -i /path/to/auto_install_file 
162
163 Are you ready to begin the installation? ([Y]/N): |;
164
165 $messages->{'WelcomeToUpgrader'}->{en} =
166    heading('Welcome to the Koha Upgrader') . qq|
167 You are attempting to upgrade from Koha %s to Koha %s.
168
169 We recommend that you do a complete backup of all your files before upgrading.
170 This upgrade script will make a backup copy of your files for you.
171
172 Would you like to proceed?  (Y/[N]):|;
173
174 $messages->{'AbortingInstall'}->{en} =
175    heading('ABORTING') . qq|
176 Aborting as requested.  Please rerun when you are ready.
177 |;
178
179 $messages->{'ReleaseCandidateWarning'}->{en} =
180    heading('RELEASE CANDIDATE') . qq|
181 WARNING: You are about to install Koha version %s.  This is a
182 release candidate, It is NOT bugfree.
183 However, it works, and has been declared stable enough to
184 be released.
185
186 Most people should answer Yes here.
187
188 Are you sure you want to install Koha %s? (Y/[N]): |;
189 $messages->{'WatchForReleaseAnnouncements'}->{en}=qq|
190
191 Watch for announcements of Koha releases on the Koha mailing list or the Koha
192 web site (http://www.koha.org/).
193
194 |;
195
196 $messages->{'NETZ3950Missing'}->{en}=qq|
197
198 The Net::Z3950 module is missing.  This module is necessary if you want to use
199 Koha's Z39.50 client to download bibliographic records from other libraries.
200
201 To install this module, you will need the yaz client installed from
202 http://www.indexdata.dk/yaz/ and then you can install the perl module with the
203 command:
204
205 perl -MCPAN -e 'install Net::Z3950'
206
207 ...or by installing packages for your distribution, if available.
208
209 IMPORTANT NOTE : If you use Perl 5.8.0, you might need to 
210 edit NET::Z3950's Makefile.PL and yazwrap/Makefile.PL to include:
211
212     'DEFINE' => '-D_GNU_SOURCE',
213
214 Also note that some installations of Perl on Red Hat will generate a lot of
215 "'my_perl' undeclared" errors when running make in Net-Z3950.  This is fixed by
216 inserting in yazwrap/ywpriv.h a line saying #include "XSUB.h"
217
218 Press the <ENTER> key to continue: |;   #'
219
220 $messages->{'CheckingPerlModules'}->{en} = heading('PERL MODULES') . qq|
221 Checking perl modules ...
222 |;
223
224 $messages->{'PerlVersionFailure'}->{en}="Sorry, you need at least Perl %s\n";
225
226 $messages->{'MissingPerlModules'}->{en} = heading('MISSING PERL MODULES') . qq|
227 You are missing some Perl modules required by Koha.
228 Please run this again after installing them.
229 They may be installed by finding packages from your operating system supplier, or running (as root) the following commands:
230
231 %s
232 |;
233
234 $messages->{'AllPerlModulesInstalled'}->{en} =
235    heading('PERL MODULES AVAILABLE') . qq|
236 All required perl modules are installed.
237
238 Press <ENTER> to continue: |;
239 $messages->{'KohaVersionInstalled'}->{en}="You currently have Koha %s on your system.";
240 $messages->{'KohaUnknownVersionInstalled'}->{en}="I am not able to determine what version of Koha is installed now.";
241 $messages->{'KohaAlreadyInstalled'}->{en} =
242    heading('Koha already installed') . qq|
243 It looks like Koha is already installed on your system (%s/koha.conf exists).
244 If you would like to upgrade your system to %s, please use
245 the koha.upgrade script in this directory.
246
247 %s
248
249 |;
250 $messages->{'GetOpacDir'}->{en} = heading('OPAC DIRECTORY') . qq|
251 Please supply the directory you want Koha to store its OPAC files in.  This
252 directory will be auto-created for you if it doesn't exist.
253
254 OPAC Directory [%s]: |; #'
255
256 $messages->{'GetIntranetDir'}->{en} =
257    heading('LIBRARIAN DIRECTORY') . qq|
258 Please supply the directory you want Koha to store its Librarian interface
259 files in.  This directory will be auto-created for you if it doesn't exist.
260
261 Intranet Directory [%s]: |;     #'
262
263 $messages->{'GetKohaLogDir'}->{en} = heading('LOG DIRECTORY') . qq|
264 Specify a directory where log files will be written.
265
266 Koha Log Directory [%s]: |;
267
268 $messages->{'AuthenticationWarning'}->{en} = heading('Authentication') . qq|
269 This release of Koha has a new authentication module.
270 You will be required to log in to
271 access some features.
272
273 IMPORTANT: You can log in using the userid and password from the %s/koha.conf configuration file at any time.
274 Use the "Members" screen to add passwords for other accounts and set their flags.
275
276 Press the <ENTER> key to continue: |;
277
278 $messages->{'Completed'}->{en} = heading('INSTALLATION COMPLETE') . qq|
279 Congratulations ... your Koha installation is complete!
280
281 You will be able to connect to your Librarian interface at:
282
283    http://%s\:%s/
284
285    use the koha admin mysql login and password to connect to this interface.
286 and the OPAC interface at:
287
288    http://%s\:%s/
289    
290 NOTE: You need to add lines to your main httpd.conf to include
291 /etc/koha-httpd.conf and to make sure it is listening on the right ports
292 (using the Listen directive). Then, restart Apache.
293
294 Please read the Hints file and visit http://www.koha.org (in english) or www.koha-fr.org (in french)
295 Press <ENTER> to exit the installer: |;
296
297 $messages->{'UpgradeCompleted'}->{en} = heading('UPGRADE COMPLETE') . qq|
298 Congratulations ... your Koha upgrade is finished!
299
300 Please report any problems you encounter through http://bugs.koha.org/
301
302 Press <ENTER> to exit the installer: |;
303
304 #'
305
306 =item C<completeupgrade()>
307
308 Display a message describing what may need changing in httpd.conf
309 and any other instructions for just before exit.
310
311 =cut
312
313 sub completeupgrade {
314         showmessage(getmessage('UpgradeCompleted',[$intranetdir,$intranetdir,$intranetdir,$opacdir,$opacdir,$intranetdir]),'PressEnter');
315 }
316
317 =item C<releasecandidatewarning()>
318
319 Display a warning about upgrading to a public test release.
320
321 =cut
322
323 sub releasecandidatewarning {
324     my $message=getmessage('ReleaseCandidateWarning', [$newversion, $newversion]);
325     my $answer=showmessage($message, 'yn', 'n');
326
327     if ($answer =~ /y/i) {
328         print getmessage('continuing');
329     } else {
330         my $message=getmessage('WatchForReleaseAnnouncements');
331         print $message."\n";
332         exit;
333     };
334 }
335
336 =item C<read_autoinstall_file($)>
337
338 Takes: a configuration file describing the installation
339
340 Returns: a hashref of the configuration
341
342 =cut
343
344 sub read_autoinstall_file
345 {
346         my $fname = shift;      # Config file to read
347         my $retval = {};        # Return value: ref-to-hash holding the
348                                 # configuration
349
350         open (CONF, $fname) or return undef;
351
352         while (<CONF>)
353         {
354                 my $var;                # Variable name
355                 my $value;              # Variable value
356
357                 chomp;
358                 s/#.*//;                # Strip comments
359                 next if /^\s*$/;        # Ignore blank lines
360
361                 # Look for a line of the form
362                 #       var = value
363                 if (!/^\s*(\w+)\s*=\s*(.*?)\s*$/)
364                 {
365                         next;
366                 }
367
368                 # Found a variable assignment
369                 # variable that was already set.
370                 $var = $1;
371                 $value = $2;
372                 $retval->{$var} = $value;
373         }
374         close CONF;
375         if ($retval->{MysqlRootPassword} eq "XXX") {
376                 print "ERROR : the root password is XXX. It is NOT valid. Edit your auto_install_file\n";
377         }
378         return $retval;
379 }
380
381 =back
382
383 =head2 Accessor functions (for installer.pl)
384
385 =over 4
386
387 =item C<setlanguage($)>
388
389 Sets the installation language code, normally "en" (English).
390 Only "en" is supported so far.
391
392 =cut
393
394 sub setlanguage ($) {
395     ($language) = @_;
396 }
397
398 =item C<setdomainname($)>
399
400 Sets the domain name of the host.
401
402 The domain name should not contain a leading dot;
403 otherwise, the results are undefined.
404
405 =cut
406
407 sub setdomainname ($) {
408     ($domainname) = @_;
409 }
410
411 =item C<setetcdir($)>
412
413 Sets the sysconfdir, normally /etc.
414 This should be an absolute path; a trailing / is not required.
415 Must be writeable, else we die.
416
417 =cut
418
419 sub setetcdir ($) {
420     ($etcdir) = @_;
421     if (! ((-d $etcdir) && (-w $etcdir))) { die("Cannot write to $etcdir! Please set the etcdir environment variable to a writeable directory.\nFailed"); }
422 }
423
424 =item C<getkohaversion()>
425
426 Returns: the Koha version as known by the previous config file..
427
428 =cut
429
430 sub getkohaversion () {
431     return($kohaversion);
432 }
433
434 =item C<setkohaversion($)>
435
436 Sets the Koha version as known by the installer.
437
438 Note: function is now misnamed, setting $newversion not $kohaversion
439
440 =cut
441
442 sub setkohaversion ($) {
443     ($newversion) = @_;
444 }
445
446 =item C<getservername()>
447
448 Returns: the name of the Koha virtual server as specified by the user.
449
450 =cut
451
452 sub getservername () {
453     $servername;
454 }
455
456 =item C<getopacport()>
457
458 Returns the port that will run the Koha OPAC virtual server, as
459 specified by the user.
460
461 =cut
462
463 sub getopacport () {
464     $opacport;
465 }
466
467 =item C<getintranetport()>
468
469 Returns the port that will run the Koha INTRANET virtual server, as
470 specified by the user.
471
472 =cut
473
474 sub getintranetport () {
475     $intranetport;
476 }
477
478 =back
479
480 =head2 Miscellaneous utility functions
481
482 =over 4
483
484 =item C<dirname($)>
485
486 Does the equivalent of dirname(1).
487
488 Takes: a path
489
490 Returns: parent directory of path (best guess), except when the path
491 seems to be the same as /, in which case it is returned unchanged.
492
493 =cut
494
495 sub dirname ($;$) {
496     my($path) = @_;
497     if ($path =~ /[^\/]/s) {
498         if ($path =~ /\//) {
499             $path =~ s/\/+[^\/]+\/*$//s;
500         } else {
501             $path = '.';
502         }
503     }
504     return $path;
505 }
506
507 =item C<mkdir_parents($;$)>
508
509 Does the equivalent of mkdir -p, or mkdir --parents.
510
511 Takes: a path and an optional mode.
512
513 Create the directory path, recursively creating any intermediate
514 directories, with the access mode if given.
515
516 WARNING: If the path already exists, mkdir_parents will just return
517 successfully (just like mkdir -p), whether the mode of path conforms
518 to the mode or not. (This is the behaviour of the mkdir -p command.)
519
520 =cut
521
522 sub mkdir_parents ($;$) {
523     my($path, $mode) = @_;
524     my $ok = -d($path)? 1: defined $mode? mkdir($path, $mode): mkdir($path);
525
526     if (!$ok && $! == ENOENT) {
527         my $parent = dirname($path);
528         $ok = &mkdir_parents($parent, $mode);
529
530         # retry and at the same time make sure that $! is set correctly
531         $ok = defined $mode? mkdir($path, $mode): mkdir($path);
532     }
533     return $ok;
534 }
535
536 =item C<getmessage($;$)>
537
538 Takes: a message identifier, an array reference
539
540 Returns: a localized message (format string)
541
542 The first message must be the message identifier corresponding to a
543 defined message string (a valid key to the $Installer::messages hash).
544 The second parameter may be an array reference of variables,
545 to be substituted into the format string.
546
547 getmessage throws an exception if the message cannot be found.
548
549 =cut
550
551 sub getmessage {
552     my $messagename=shift;
553     my $variables=shift;
554     my $message=$messages->{$messagename}->{$language} || $messages->{$messagename}->{en} || RED.BOLD."Error: No message named $messagename in Install.pm\n";
555     if (defined($variables)) {
556         $message=sprintf $message, @$variables;
557     }
558     return $message;
559 }
560
561
562 =item C<showmessage($$;$$)>
563
564 Shows a message and optionally gets a response from the user.
565
566 Takes:
567 message string, question type, default response, noclear
568
569 Returns: response string
570
571 The message must be the actual string to display; the caller is
572 responsible for calling getmessage if required.
573
574 Question type must be 'none' for no response, 'yn' for a yes/no
575 question, 'restrictchar CHARS' for one letter from CHARS (Case is not
576 significant, but case is significant in the list of allowed
577 characters), 'free' for any string, 'silentfree' for any string
578 entered without on-screen display, 'numerical', 'email' or
579 'PressEnter'.  If a response type other than the above-listed is
580 specified, the result is undefined.
581
582 Note that the response type of "email" does not actually
583 guarantee that the returned value is a well-formed RFC-822
584 email address, nor does it accept all well-formed RFC-822 email
585 addresses. What it does is to restrict the returned value to a
586 string that is looks reasonably likely to be an email address
587 in the "real world", given the premise that the user is trying
588 to enter a real email address.
589
590 If a response type other than "none" or "PressEnter" is specified, a
591 third argument, specifying the default value, can be specified: If
592 this default response is not specified, the default response is the
593 first allowed character if the response type is "restrictchar",
594 otherwise the default response is the empty string. This default
595 response is used when the user does not specify a value (i.e., presses
596 Enter without typing in anything), showmessage will assume that the
597 default response is the user's response.
598
599 Note that because the response type "yn" is equivalent to
600 "restrictchar yn", the default value for response type "yn", if
601 unspecified, is "y".
602
603 The screen is normally cleared before the message is displayed; if a
604 fourth argument is specified and is nonzero, this screen-clearing is
605 not done.
606
607 =cut
608 #'
609
610 sub showmessage ($$;$$) {
611     #MJR: Maybe refactor to use anonymous functions that
612     # check the responses instead of RnP branching.
613     my $message=join('',fill('','',(shift)));
614     my $responsetype=shift;
615     my $defaultresponse=shift;
616     my $noclear=shift;
617     $noclear = 0 unless defined $noclear; # defaults to "clear"
618     ($noclear) || (print $clear_string);
619     if ($responsetype =~ /^yn$/) {
620         $responsetype='restrictchar ynYN';
621     }
622     print RESET.$message;
623     if ($responsetype =~/^restrictchar (.*)/i) {
624         my $response='\0';
625         my $options=$1;
626         until ($options=~/$response/) {
627             (defined($defaultresponse)) || ($defaultresponse=substr($options,0,1));
628             $response=<STDIN>;
629             chomp $response;
630             (length($response)) || ($response=$defaultresponse);
631             if ( $response=~/.*[\:\(\)\^\$\*\!\\].*/ ) {
632                 ($noclear) || (print $clear_string);
633                 print RED."Response contains invalid characters.  Choose from [$options].\n\n";
634                 print RESET.$message;
635                 $response='\0';
636             } else {
637                 unless ($options=~/$response/) {
638                     ($noclear) || (print $clear_string);
639                     print RED."Invalid Response.  Choose from [$options].\n\n";
640                     print RESET.$message;
641                 }
642             }
643         }
644         return $response;
645     } elsif ($responsetype =~/^(silent)?free$/i) {
646         (defined($defaultresponse)) || ($defaultresponse='');
647         if ($responsetype =~/^(silent)/i) { setecho(0) }; 
648         my $response=<STDIN>;
649         if ($responsetype =~/^(silent)/i) { setecho(1) }; 
650         chomp $response;
651         ($response) || ($response=$defaultresponse);
652         return $response;
653     } elsif ($responsetype =~/^numerical$/i) {
654         (defined($defaultresponse)) || ($defaultresponse='');
655         my $response='';
656         until ($response=~/^\d+$/) {
657             $response=<STDIN>;
658             chomp $response;
659             ($response) || ($response=$defaultresponse);
660             unless ($response=~/^\d+$/) {
661                 ($noclear) || (print $clear_string);
662                 print RED."Invalid Response ($response).  Response must be a number.\n\n";
663                 print RESET.$message;
664             }
665         }
666         return $response;
667     } elsif ($responsetype =~/^email$/i) {
668         (defined($defaultresponse)) || ($defaultresponse='');
669         my $response='';
670         until ($response=~/.*\@.*\..*/) {
671             $response=<STDIN>;
672             chomp $response;
673             ($response) || ($response=$defaultresponse);
674             if ($response!~/.*\@.*\..*/) {
675                         ($noclear) || (print $clear_string);
676                         print RED."Invalid Response ($response).  Response must be a valid email address.\n\n";
677                         print RESET.$message;
678             }
679         }
680         return $response;
681     } elsif ($responsetype =~/^PressEnter$/i) {
682         <STDIN>;
683         return;
684     } elsif ($responsetype =~/^none$/i) {
685         return;
686     } else {
687         # FIXME: There are a few places where we will get an undef as the
688         # response type. Should we thrown an exception here, or should we
689         # legitimize this usage and say "none" is the default if not specified?
690         #die "Illegal response type \"$responsetype\"";
691     }
692 }
693
694
695 =item C<startsysout()>
696
697 Changes the display to show system output until the next showmessage call.
698 At the time of writing, this means using red text.
699
700 =cut
701
702 sub startsysout {
703         print RED."\n";
704 }
705
706 =back
707
708 =head2 Subtasks of doing an installation
709
710 =over 4
711
712 =item C<checkabortedinstall()>
713
714 Checks whether a previous installation process has been abnormally
715 aborted, by checking whether $etcidr/koha.conf is a symlink matching
716 a particular pattern.  If an aborted installation is detected, give
717 the user a chance to abort, before trying to recover the aborted
718 installation.
719
720 FIXME: The recovery is not complete; it only partially rolls back
721 some changes.
722
723 =cut
724
725 sub checkabortedinstall () {
726     if (-l("$etcdir/koha.conf")
727         && readlink("$etcdir/koha.conf") =~ /\.tmp$/
728     ) {
729         print qq|
730 I have detected that you tried to install Koha before, but the installation
731 was aborted.  I will try to continue, but there might be problems if the
732 database is already created.
733
734 |;
735         print "Please press <ENTER> to continue: ";
736         <STDIN>;
737
738         # Remove the symlink after the <STDIN>, so the user can back out
739         unlink "$etcdir/koha.conf"
740             || die "Failed to remove incomplete $etcdir/koha.conf: $!\n";
741     }
742 }
743
744 =item C<checkpaths()>
745
746 Make sure that we loaded the right dirs from an old koha.conf
747
748 FIXME: needs update to use Install.pm
749
750 =cut
751
752 sub checkpaths {
753 if ($opacdir && $intranetdir) {
754     print qq|
755
756 I believe that your old files are located in:
757
758   OPAC:      $opacdir
759   LIBRARIAN: $intranetdir
760
761
762 Does this look right?  ([Y]/N):
763 |;
764     my $answer = <STDIN>;
765     chomp $answer;
766
767     if ($answer =~/n/i) {
768         $intranetdir='';
769         $opacdir='';
770     } else {
771         print "Great! continuing upgrade... \n";
772     }
773 }
774
775 if (!$opacdir || !$intranetdir) {
776     $intranetdir='';
777     $opacdir='';
778     while (!$intranetdir) {
779         print "Please specify the location of your LIBRARIAN files: ";
780
781         my $answer = <STDIN>;
782         chomp $answer;
783
784         if ($answer) {
785             $intranetdir=$answer;
786         }
787         if (! -e "$intranetdir/htdocs") {
788             print "\nCouldn't find the htdocs directory here.  That doesn't look right.\nPlease enter another location.\n\n";
789             $intranetdir='';
790         }
791     }
792     while (!$opacdir) {
793         print "Please specify the location of your OPAC files: ";  
794
795         my $answer = <STDIN>;
796         chomp $answer;
797
798         if ($answer) {
799             $opacdir=$answer;
800         }
801         if (! -e "$opacdir/htdocs") {
802             print "\nCouldn't find the htdocs directory here.  That doesn't look right.\nPlease enter another location.\n\n";
803             $opacdir='';
804         }
805     }
806 }
807
808 }
809
810 =item C<checkperlmodules(;$)>
811
812 Test whether the version of Perl is new enough, whether Perl is found
813 at the expected location, and whether all required modules have been
814 installed.
815
816 =cut
817
818 sub checkperlmodules(;$) {
819 #
820 # Test for Perl and Modules
821 #
822         my ($auto_install) = @_;
823         my $message = getmessage('CheckingPerlModules');
824         showmessage($message, 'none');
825
826         unless ($] >= 5.006001) {                       # Bug 179
827                 die getmessage('PerlVersionFailure', ['5.6.1']);
828         }
829         startsysout();
830
831         my @missing = ();
832         unless (eval {require DBI})              { push @missing,"DBI" };
833         unless (eval {require Date::Manip})      { push @missing,"Date::Manip" };
834         unless (eval {require DBD::mysql})       { push @missing,"DBD::mysql" };
835         unless (eval {require HTML::Template})   { push @missing,"HTML::Template" };
836         unless (eval {require Digest::MD5})      { push @missing,"Digest::MD5" };
837         unless (eval {require MARC::Record})     { push @missing,"MARC::Record" };
838         unless (eval {require Mail::Sendmail})   { push @missing,"Mail::Sendmail" };
839 # The following modules are not mandatory, depends on how the library want to use Koha
840         unless (eval {require PDF::API2})   { 
841                         if ($#missing>=0) { # only when $#missing >= 0 so this isn't fatal
842                                 push @missing,"You will need PDF::API2 for barcode generator";
843                         }
844         }
845         unless (eval {require GD::Barcorde})   { 
846                                     if ($#missing>=0) { # only when $#missing >= 0 so this isn't fatal
847                                 push @missing,"You will need GD::Barcode for the new barcode generator";
848                                     }
849                     }
850         unless (eval {require GD::Barcorde})   { 
851                         if ($#missing>=0) { # only when $#missing >= 0 so this isn't fatal
852                                 push @missing,"You will need GD::Barcode for the new barcode generator";
853                         }
854         }
855         unless (eval {require Data::Random})   { 
856                                     if ($#missing>=0) { # only when $#missing >= 0 so this isn't fatal
857                                 push @missing,"You will need Data::Random for the new barcode generator";
858                                     }
859                     }
860                 unless (eval {require PDF::Reuse::Barcode})   {
861                                     if ($#missing>=0) { # only when $#missing >= 0 so this isn't fatal
862                                 push @missing,"You will need PDF::Reuse::Barcode for the new barcode generator";
863                                     }
864                     }
865                 unless (eval {require PDF::Report})   {
866                                     if ($#missing>=0) { # only when $#missing >= 0 so this isn't fatal
867                                             push @missing,"You will need PDF::Report for spine and barcode printing"
868                                     }
869                     }
870
871                 unless (eval {require GD::Barcode})   {
872                                     if ($#missing>=0) { # only when $#missing >= 0 so this isn't fatal
873                                             push @missing,"You will need GD::Barcode for spine and barcode printing"
874                                     }
875                     }
876
877                 unless (eval {require GD::Barcode::UPCE})   {
878                                     if ($#missing>=0) { # only when $#missing >= 0 so this isn't fatal
879                                             push @missing,"You will need GD::Barcode::UPCE for spine and barcode printing"
880                                     }
881                     }
882
883         unless (eval {require Net::LDAP})       {
884                 if ($#missing>=0) { # only when $#missing >= 0 so this isn't fatal
885                                 push @missing, "Net::LDAP";
886                         }
887     }
888         unless (eval {require Event})       {
889                 if ($#missing>=0) { # only when $#missing >= 0 so this isn't fatal
890                                 push @missing, "Event";
891                         }
892     }
893     unless (eval {require Net::Z3950})       {
894                 showmessage(getmessage('NETZ3950Missing'), 'PressEnter', '', 1);
895                 if ($#missing>=0) { # see above note
896                         push @missing, "Net::Z3950";
897                 }
898     }
899     unless (eval {require LWP::Simple})       {
900                 showmessage(getmessage('LWP::Simple'), 'PressEnter', '', 1);
901                 if ($#missing>=0) { # see above note
902                         push @missing, "LWP::Simple";
903                 }
904     }
905     unless (eval {require XML::Simple})       {
906                 showmessage(getmessage('XML::Simple'), 'PressEnter', '', 1);
907                 if ($#missing>=0) { # see above note
908                         push @missing, "XML::Simple";
909                 }
910     }
911
912 #
913 # Print out a list of any missing modules
914 #
915
916     if (@missing > 0) {
917         my $missing='';
918         if (POSIX::setlocale(LC_ALL) ne "C") {
919                 $missing.="   export LC_ALL=C\n";  
920         }
921         foreach my $module (@missing) {
922             $missing.="   perl -MCPAN -e 'install \"$module\"'\n";
923         }
924         my $message=getmessage('MissingPerlModules', [$missing]);
925         showmessage($message, 'none');
926         print "\n";
927         exit;
928     } else {
929         showmessage(getmessage('AllPerlModulesInstalled'), 'PressEnter', '', 1) unless $auto_install->{NoPressEnter};
930     }
931
932
933         startsysout();
934     unless (-x "/usr/bin/perl") {
935         my $realperl=`which perl`;
936         chomp $realperl;
937         $realperl = showmessage(getmessage('NoUsrBinPerl'), 'none');
938         until (-x $realperl) {
939             $realperl=showmessage(getmessage('AskLocationOfPerlExecutable', $realperl), 'free', $realperl, 1);
940         }
941         my $response=showmessage(getmessage('ConfirmPerlExecutableSymlink', $realperl), 'yn', 'y', 1);
942         unless ($response eq 'n') {
943                 startsysout();
944             system("ln -s $realperl /usr/bin/perl");
945         }
946     }
947
948
949 }
950
951 $messages->{'NoUsrBinPerl'}->{en} =
952    heading('No /usr/bin/perl') . qq|
953 Koha expects to find the perl executable in the /usr/bin
954 directory.  It is not there on your system.
955
956 |;
957
958 $messages->{'AskLocationOfPerlExecutable'}->{en}=qq|Location of Perl Executable [%s]: |;
959 $messages->{'ConfirmPerlExecutableSymlink'}->{en}=qq|
960 Some Koha scripts will _not_ work without a symlink from %s to /usr/bin/perl
961
962 Most users should answer Y here.
963
964 May I try to create this symlink? ([Y]/N):|;
965
966 $messages->{'DirFailed'}->{en} = RED.qq|
967 We could not create %s, but continuing anyway...
968
969 |;
970
971
972
973 =item C<getinstallationdirectories(;$)>
974
975 Asks the user for the various installation directories, and then
976 creates those directories (if they do not already exist).
977
978 These pieces of information are saved to variables; the function does
979 not return any values.
980
981 =cut
982
983 sub getinstallationdirectories(;$) {
984         my ($auto_install) = @_;
985         if (!$ENV{prefix}) { $ENV{prefix} = "/usr/local"; }
986     $opacdir = $ENV{prefix}.'/koha/opac';
987     $intranetdir = $ENV{prefix}.'/koha/intranet';
988     my $getdirinfo=1;
989     while ($getdirinfo) {
990         # Loop until opac directory and koha directory are different
991         my $message;
992         if ($auto_install->{GetOpacDir}) {
993                 $opacdir=$auto_install->{GetOpacDir};
994                 print ON_YELLOW.BLACK."auto-setting OpacDir to : $opacdir".RESET."\n";
995         } else {
996                 $message=getmessage('GetOpacDir', [$opacdir]);
997                 $opacdir=showmessage($message, 'free', $opacdir);
998         }
999         if ($auto_install->{GetIntranetDir}) {
1000                 $intranetdir=$auto_install->{GetIntranetDir};
1001                 print ON_YELLOW.BLACK."auto-setting IntranetDir to : $intranetdir".RESET."\n";
1002         } else {
1003                 $message=getmessage('GetIntranetDir', [$intranetdir]);
1004                 $intranetdir=showmessage($message, 'free', $intranetdir);
1005         }
1006         if ($intranetdir eq $opacdir) {
1007             print qq|
1008
1009 You must specify different directories for the OPAC and INTRANET files!
1010  :: $intranetdir :: $opacdir ::
1011 |;
1012 <STDIN>
1013         } else {
1014             $getdirinfo=0;
1015         }
1016     }
1017     $kohalogdir=$ENV{prefix}.'/koha/log';
1018         if ($auto_install->{GetOpacDir}) {
1019                 $kohalogdir=$auto_install->{KohaLogDir};
1020                 print ON_YELLOW.BLACK."auto-setting log dir to : $kohalogdir".RESET."\n";
1021         } else {
1022             my $message=getmessage('GetKohaLogDir', [$kohalogdir]);
1023         $kohalogdir=showmessage($message, 'free', $kohalogdir);
1024         }
1025
1026
1027     # FIXME: Need better error handling for all mkdir calls here
1028     unless ( -d $intranetdir ) {
1029        mkdir_parents (dirname($intranetdir), 0775) || print getmessage('DirFailed',['parents of '.$intranetdir]);
1030        mkdir ($intranetdir,                  0770) || print getmessage('DirFailed',[$intranetdir]);
1031        if ($>==0) { chown (oct(0), (getgrnam($httpduser))[2], "$intranetdir"); }
1032        chmod 0770, "$intranetdir";
1033     }
1034     mkdir_parents ("$intranetdir/htdocs",    0750);
1035     mkdir_parents ("$intranetdir/cgi-bin",   0750);
1036     mkdir_parents ("$intranetdir/modules",   0750);
1037     mkdir_parents ("$intranetdir/scripts",   0750);
1038     unless ( -d $opacdir ) {
1039        mkdir_parents (dirname($opacdir),     0775) || print getmessage('DirFailed',['parents of '.$opacdir]);
1040        mkdir ($opacdir,                      0770) || print getmessage('DirFailed',[$opacdir]);
1041        if ($>==0) { chown (oct(0), (getgrnam($httpduser))[2], "$opacdir"); }
1042        chmod (oct(770), "$opacdir");
1043     }
1044     mkdir_parents ("$opacdir/htdocs",        0750);
1045     mkdir_parents ("$opacdir/cgi-bin",       0750);
1046
1047
1048     unless ( -d $kohalogdir ) {
1049        mkdir_parents (dirname($kohalogdir),  0775) || print getmessage('DirFailed',['parents of '.$kohalogdir]);
1050        mkdir ($kohalogdir,                   0770) || print getmessage('DirFailed',[$kohalogdir]);
1051        if ($>==0) { chown (oct(0), (getgrnam($httpduser))[2,3], "$kohalogdir"); }
1052        chmod (oct(770), "$kohalogdir");
1053     }
1054 }
1055
1056 =item C<getmysqldir()>
1057
1058 Returns: the MySQL database server installation directory,
1059 automatically if possible and from the user otherwise.
1060
1061 =cut
1062
1063 $messages->{'WhereIsMySQL'}->{en} = heading('MYSQL LOCATION').qq|
1064 Koha can't find the MySQL command-line tools. If you installed a MySQL package, you may need to install an additional package containing mysqladmin.
1065 If you compiled mysql yourself,
1066 please give the value of --prefix when you ran configure.
1067 The file mysqladmin should be in bin/mysqladmin under the directory that you give here.
1068
1069 MySQL installation directory: |;
1070 #'
1071 sub getmysqldir () {
1072     foreach my $mysql (qw(/usr/local/mysql
1073                           /opt/mysql
1074                           /usr/local
1075                           /usr
1076                           )) {
1077        if ( -d $mysql  && -f "$mysql/bin/mysqladmin") {
1078             $mysqldir=$mysql;
1079        }
1080     }
1081     if (!$mysqldir){
1082         for (;;) {
1083             $mysqldir = showmessage(getmessage('WhereIsMySQL'),'free');
1084             last if -f "$mysqldir/bin/mysqladmin";
1085         }
1086     }
1087     return($mysqldir);
1088 }
1089
1090 =item C<getdatabaseinfo(;$)>
1091
1092 Asks for various pieces of information related to the Koha database:
1093 the name of the database, the host on which the SQL server is running,
1094 and the database user name.
1095
1096 These pieces of information are saved to global variables; the
1097 function does not return any values.
1098
1099 =cut
1100
1101 $messages->{'DatabaseName'}->{en} = heading('Database Name') . qq|
1102 Please provide the name that you wish to give your koha database.
1103 It must not exist already on the database server.
1104
1105 Most users give a short single-word name for their library here.
1106
1107 Database name [%s]: |;
1108
1109 $messages->{'DatabaseHost'}->{en} = heading('Database Host') . qq|
1110 Please provide the mysql server name.  Unless the database is stored on
1111 another machine, this should be "localhost".
1112
1113 Database host [%s]: |;
1114
1115 $messages->{'DatabaseUser'}->{en} = heading('Database User') . qq|
1116 We are going to create a new mysql user for Koha. This user will have full administrative rights
1117 to the database called %s when they connect from %s.
1118 This is also the name of the Koha librarian superuser.
1119
1120 Most users give a single-word name here.
1121
1122 Database user [%s]: |;
1123
1124 $messages->{'DatabasePassword'}->{en} = heading('Database Password') . qq|
1125 Please provide a good password for the user %s.
1126
1127 IMPORTANT: You can log in using this user and password at any time.
1128
1129 Password for database user %s: |;
1130
1131 $messages->{'BlankPassword'}->{en} = heading('BLANK PASSWORD') . qq|
1132 You must not use a blank password for your MySQL user.
1133
1134 Press <ENTER> to try again: 
1135 |;
1136
1137 sub getdatabaseinfo(;$) {
1138         my ($auto_install) = @_;
1139     $database = 'Koha';
1140     $hostname = 'localhost';
1141     $user = 'kohaadmin';
1142     $pass = '';
1143
1144 #Get the database name
1145         my $message;
1146         
1147         if ($auto_install->{database}) {
1148                 $database=$auto_install->{database};
1149                 print ON_YELLOW.BLACK."auto-setting database to : $database".RESET."\n";
1150         } else {
1151                 $message=getmessage('DatabaseName', [$database]);
1152                 $database=showmessage($message, 'free', $database);
1153         }
1154 #Get the hostname for the database
1155     
1156         if ($auto_install->{DatabaseHost}) {
1157                 $hostname=$auto_install->{DatabaseHost};
1158                 print ON_YELLOW.BLACK."auto-setting database host to : $hostname".RESET."\n";
1159         } else {
1160                 $message=getmessage('DatabaseHost', [$hostname]);
1161                 $hostname=showmessage($message, 'free', $hostname);
1162         }
1163 #Get the username for the database
1164
1165         if ($auto_install->{DatabaseUser}) {
1166                 $user=$auto_install->{DatabaseUser};
1167                 print ON_YELLOW.BLACK."auto-setting DB user to : $user".RESET."\n";
1168         } else {
1169                 $message=getmessage('DatabaseUser', [$database, $hostname, $user]);
1170                 $user=showmessage($message, 'free', $user);
1171         }
1172 #Get the password for the database user
1173
1174     while ($pass eq '') {
1175                 my $message=getmessage('DatabasePassword', [$user, $user]);
1176                 if ($auto_install->{DatabasePassword}) {
1177                         $pass=$auto_install->{DatabasePassword};
1178                         print ON_YELLOW.BLACK."auto-setting database password to : $pass".RESET."\n";
1179                 } else {
1180                                 $pass=showmessage($message, 'free', $pass);
1181                 }
1182                 if ($pass eq '') {
1183                         my $message=getmessage('BlankPassword');
1184                         showmessage($message,'PressEnter');
1185                 }
1186     }
1187 }
1188
1189
1190
1191 =item C<getapacheinfo(;$)>
1192
1193 Detects or asks for various pieces of information related to the
1194 Apache server: the location of the configuration file and, if needed,
1195 the Unix user that the Koha CGI will be run under.
1196
1197 These pieces of information are saved to global variables; the
1198 function does not return any values.
1199
1200 =cut
1201
1202 $messages->{'FoundMultipleApacheConfFiles'}->{en} = 
1203    heading('MULTIPLE APACHE CONFIG FILES FOUND') . qq|
1204 I found more than one possible Apache configuration file:
1205
1206 %s
1207
1208 Enter number of the file to read [1]: |;
1209
1210 $messages->{'NoApacheConfFiles'}->{en} =
1211    heading('NO APACHE CONFIG FILE FOUND') . qq|
1212 I was not able to find your Apache configuration file.
1213
1214 The file is usually called httpd.conf, apache.conf or similar.
1215
1216 Please enter the full name, starting with /: |;
1217
1218 $messages->{'NotAFile'}->{en} = heading('FILE DOES NOT EXIST') . qq|
1219 The file %s does not exist.
1220
1221 Please press <ENTER> to continue: |;
1222
1223 $messages->{'EnterApacheUser'}->{en} = heading('NEED APACHE USER') . qq\
1224 The installer could not find the User setting in the Apache configuration file.
1225 This is used to set up access permissions for
1226 %s/koha.conf.  This user should be set in one of the Apache configuration.
1227 Please try to find it and enter the user name below.  You might find
1228 that "ps u|grep apache" will tell you.  It probably is NOT "root".
1229
1230 Enter the Apache userid: \;
1231
1232 $messages->{'InvalidUserid'}->{en} = heading('INVALID USER') . qq|
1233 The userid %s is not a valid userid on this system.
1234
1235 Press <ENTER> to continue: |;
1236
1237 sub getapacheinfo (;$) {
1238         my ($auto_install) = @_;
1239     my @confpossibilities;
1240
1241     foreach my $httpdconf (qw(/usr/local/apache/conf/httpd.conf
1242                           /usr/local/etc/apache/httpd.conf
1243                           /usr/local/etc/apache/apache.conf
1244                           /var/www/conf/httpd.conf
1245                           /etc/apache2/httpd.conf
1246                           /etc/apache2/apache2.conf
1247                           /etc/apache/conf/httpd.conf
1248                           /etc/apache/conf/apache.conf
1249                           /etc/apache/httpd.conf
1250                           /etc/apache-ssl/conf/apache.conf
1251                           /etc/apache-ssl/httpd.conf
1252                           /etc/httpd/conf/httpd.conf
1253                           /etc/httpd/httpd.conf
1254                           /etc/httpd/2.0/conf/httpd2.conf
1255                           )) {
1256                 if ( -f $httpdconf ) {
1257                         push @confpossibilities, $httpdconf;
1258                 }
1259     }
1260
1261     if ($#confpossibilities==-1) {
1262                 my $message=getmessage('NoApacheConfFiles');
1263                 my $choice='';
1264                 $realhttpdconf='';
1265                 until (-f $realhttpdconf) {
1266                         $choice=showmessage($message, "free", 1);
1267                         if (-f $choice) {
1268                         $realhttpdconf=$choice;
1269                         } else {
1270                         showmessage(getmessage('NotAFile', [$choice]),'PressEnter', '', 1);
1271                         }
1272                 }
1273     } elsif ($#confpossibilities>0) {
1274                 my $conffiles='';
1275                 my $counter=1;
1276                 my $options='';
1277                 foreach (@confpossibilities) {
1278                         $conffiles.="   $counter: $_\n";
1279                         $options.="$counter";
1280                         $counter++;
1281                 }
1282                 my $message=getmessage('FoundMultipleApacheConfFiles', [$conffiles]);
1283                 my $choice=showmessage($message, "restrictchar $options", 1);
1284                 $realhttpdconf=$confpossibilities[$choice-1];
1285     } else {
1286                 $realhttpdconf=$confpossibilities[0];
1287     }
1288     unless (open (HTTPDCONF, "<$realhttpdconf")) {
1289         warn RED."Insufficient privileges to open $realhttpdconf for reading.\n";
1290         sleep 4;
1291     }
1292
1293     while (<HTTPDCONF>) {
1294                 if (/^\s*User\s+"?([-\w]+)"?\s*$/) {
1295                         $httpduser = $1;
1296                 }
1297     }
1298     close(HTTPDCONF);
1299
1300     unless (defined($httpduser)) {
1301                 my $message;
1302                 if ($auto_install->{EnterApacheUser}) {
1303                         $message = $auto_install->{EnterApacheUser};
1304                         print ON_YELLOW.BLACK."auto-setting Apache User to : $message".RESET."\n";
1305                 } else {
1306                         $message=getmessage('EnterApacheUser', [$etcdir]);
1307                 }
1308                 until (defined($httpduser) && length($httpduser) && getpwnam($httpduser)) {
1309                         if ($auto_install->{EnterApacheUser}) {
1310                                 $httpduser = $auto_install->{EnterApacheUser};
1311                         } else {
1312                                 $httpduser=showmessage($message, "free", '');
1313                         }
1314                         if (length($httpduser)>0) {
1315                                 unless (getpwnam($httpduser)) {
1316                                         my $message=getmessage('InvalidUserid', [$httpduser]);
1317                                         showmessage($message,'PressEnter');
1318                                 }
1319                         } else {
1320                         }
1321                 }
1322         }
1323 }
1324
1325
1326 =item C<getapachevhostinfo(;$)>
1327
1328 Asks for various pieces of information related to virtual hosting: the
1329 webmaster email address, virtual hostname, and the ports that the OPAC
1330 and INTRANET modules run on.
1331
1332 These pieces of information are saved to global variables; the
1333 function does not return any values.
1334
1335 =cut
1336
1337 $messages->{'ApacheConfigIntroduction'}->{en} =
1338    heading('APACHE CONFIGURATION') . qq|
1339 Koha needs to write an Apache configuration file for the
1340 OPAC and Librarian sites.  By default this installer
1341 will do this by using one name and two different ports
1342 for the virtual hosts.  There are other ways to set this up,
1343 and the installer will leave comments in
1344 %s/koha-httpd.conf about them.
1345
1346 NOTE: You will need to add lines to your main httpd.conf to
1347 include %s/koha-httpd.conf
1348 (using the Include directive)
1349 and to make sure it is listening on the right ports
1350 and host names
1351 (using the Listen directive).
1352
1353 Press <ENTER> to continue: |;
1354
1355 $messages->{'GetVirtualHostEmail'}->{en} =
1356    heading('WEB E-MAIL CONTACT') . qq|
1357 Enter the e-mail address to be used as a contact for Koha.  This
1358 address is displayed if fatal errors are encountered.
1359
1360 E-mail contact [%s]: |;
1361
1362 $messages->{'GetServerName'}->{en} =
1363    heading('WEB HOST NAME OR IP ADDRESS') . qq|
1364 Please enter the host name or IP address that you wish to use for koha.
1365 Normally, this should be a name or IP that belongs to this machine.
1366
1367 Host name or IP Address [%s]: |;
1368
1369 $messages->{'GetOpacPort'}->{en} = heading('OPAC PORT') . qq|
1370 Please enter the port for your OPAC interface.  This defaults to port 80, but
1371 if you are already serving web content with this hostname, you should change it
1372 to a different port (8000 might be a good choice, but check any firewalls).
1373
1374 Enter the OPAC Port [%s]: |;
1375
1376 $messages->{'GetIntranetPort'}->{en} =
1377    heading('LIBRARIAN PORT') . qq|
1378 Please enter the port for your Librarian interface.  This must be different from
1379 the OPAC port (%s).
1380
1381 Enter the Intranet Port [%s]: |;
1382
1383
1384 sub getapachevhostinfo (;$) {
1385         my ($auto_install) = @_;
1386     $svr_admin = "webmaster\@$domainname";
1387     $servername=`hostname`;
1388     chomp $servername;
1389     $opacport=80;
1390     $intranetport=8080;
1391
1392         if ($auto_install->{GetVirtualHostEmail}) {
1393                 $svr_admin=$auto_install->{GetVirtualHostEmail};
1394                 print ON_YELLOW.BLACK."auto-setting VirtualHostEmail to : $svr_admin".RESET."\n";
1395         } else {
1396                 showmessage(getmessage('ApacheConfigIntroduction',[$etcdir,$etcdir]), 'PressEnter');
1397                 $svr_admin=showmessage(getmessage('GetVirtualHostEmail', [$svr_admin]), 'email', $svr_admin);
1398         }
1399         if ($auto_install->{servername}) {
1400                 $servername=$auto_install->{servername};
1401                 print ON_YELLOW.BLACK."auto-setting server name to : $servername".RESET."\n";
1402         } else {
1403         $servername=showmessage(getmessage('GetServerName', [$servername]), 'free', $servername);
1404         }
1405         if ($auto_install->{opacport}) {
1406                 $opacport=$auto_install->{opacport};
1407                 print ON_YELLOW.BLACK."auto-setting opac port to : $opacport".RESET."\n";
1408         } else {
1409             $opacport=showmessage(getmessage('GetOpacPort', [$opacport]), 'numerical', $opacport);
1410         }
1411         if ($auto_install->{intranetport}) {
1412                 $intranetport=$auto_install->{intranetport};
1413                 print ON_YELLOW.BLACK."auto-setting intranet port to : $intranetport".RESET."\n";
1414         } else {
1415             $intranetport=showmessage(getmessage('GetIntranetPort', [$opacport, $intranetport]), 'numerical', $intranetport);
1416         }
1417
1418 }
1419
1420
1421 =item C<updateapacheconf(;$)>
1422
1423 Creates the Apache config file according to parameters previously
1424 specified by the user as F<$etcdir/koha-httpd.conf>.
1425
1426 If you need to uninstall Koha for any reason, the lines between
1427
1428     # Ports to listen to for Koha
1429
1430 and the block of comments beginning with
1431
1432     # If you want to use name based Virtual Hosting:
1433
1434 must be removed.
1435
1436 =cut
1437
1438 $messages->{'StartUpdateApache'}->{en} =
1439    heading('UPDATING APACHE CONFIGURATION') . qq|
1440 Checking for modules that need to be loaded...
1441 |;
1442
1443 $messages->{'ApacheConfigMissingModules'}->{en} =
1444    heading('APACHE CONFIGURATION NEEDS UPDATE') . qq|
1445 Koha uses the mod_env and mod_include apache features, but the
1446 installer did not find them in your config.  Please
1447 make sure that they are enabled for your Koha site.
1448
1449 Press <ENTER> to continue: |;
1450
1451
1452 $messages->{'ApacheAlreadyConfigured'}->{en} =
1453    heading('APACHE ALREADY CONFIGURED') . qq|
1454 %s appears to already have an entry for Koha.  You may need to edit %s
1455 if anything has changed since it was last set up.  This
1456 script will not attempt to modify an existing Koha apache
1457 configuration.
1458
1459 Press <ENTER> to continue: |;
1460
1461 sub updateapacheconf (;$) {
1462         my ($auto_install)=@_;
1463     my $logfiledir=$kohalogdir;
1464     my $httpdconf = $etcdir."/koha-httpd.conf";
1465    
1466     showmessage(getmessage('StartUpdateApache'), 'none') unless $auto_install->{NoPressEnter};
1467         # to be polite about it: I don't think this should touch the main httpd.conf
1468
1469         # QUESTION: Should we warn for includes_module too?
1470     my $envmodule=0;
1471     my $includesmodule=0;
1472     open HC, "<$realhttpdconf";
1473     while (<HC>) {
1474         if (/^\s*#\s*LoadModule env_module /) {
1475             showmessage(getmessage('ApacheConfigMissingModules'),'none');
1476             $envmodule=1;
1477         }
1478         if (/\s*LoadModule includes_module / ) {
1479             $includesmodule=1;
1480         }
1481     }
1482
1483         startsysout;
1484     if (`grep -q 'VirtualHost $servername' "$httpdconf" 2>/dev/null`) {
1485         showmessage(getmessage('ApacheAlreadyConfigured', [$httpdconf, $httpdconf]), 'PressEnter');
1486         return;
1487     } else {
1488         my $includesdirectives='';
1489         if ($includesmodule) {
1490             $includesdirectives.="Options +Includes\n";
1491             $includesdirectives.="   AddHandler server-parsed .html\n";
1492         }
1493         open(SITE,">$httpdconf") or warn "Insufficient priveleges to open $httpdconf for writing.\n";
1494         my $opaclisten = '';
1495         if ($opacport != 80) {
1496             $opaclisten="Listen $opacport";
1497         }
1498         my $intranetlisten = '';
1499         if ($intranetport != 80) {
1500             $intranetlisten="Listen $intranetport";
1501         }
1502         print SITE <<EOP
1503
1504 # Koha 2.2 Apache Virtual Host Config File
1505 #
1506 # Please include this file in your apache configuration.
1507 # The best way to do that depends on your site setup.
1508 # Some like an Include adding to /etc/apache/httpd.conf
1509 # and some prefer a symlink to this file from some dir.
1510 # Please refer to your system manuals.
1511
1512 # Ports to listen to for Koha
1513 # uncomment these if they aren't already in main httpd.conf
1514 #$opaclisten
1515 #$intranetlisten
1516
1517 # NameVirtualHost is used by one of the optional configurations detailed below
1518 # Please make sure this line is correct before uncommenting.
1519 # See http://httpd.apache.org/docs/vhosts/ for some guides.
1520
1521 #NameVirtualHost 11.22.33.44
1522
1523 # KOHA's OPAC Configuration
1524 <VirtualHost $servername\:$opacport>
1525    ServerAdmin $svr_admin
1526    DocumentRoot $opacdir/htdocs
1527    ServerName $servername
1528    ScriptAlias /cgi-bin/koha/ $opacdir/cgi-bin/
1529    Redirect permanent index.html http://$servername\:$opacport/cgi-bin/koha/opac-main.pl
1530    ErrorLog $logfiledir/opac-error_log
1531    TransferLog $logfiledir/opac-access_log
1532    SetEnv PERL5LIB "$intranetdir/modules"
1533    SetEnv KOHA_CONF "$etcdir/koha.conf"
1534    $includesdirectives
1535 </VirtualHost>
1536
1537 # KOHA's INTRANET Configuration
1538 <VirtualHost $servername\:$intranetport>
1539    ServerAdmin $svr_admin
1540    DocumentRoot $intranetdir/htdocs
1541    ServerName $servername
1542    ScriptAlias /cgi-bin/koha/ "$intranetdir/cgi-bin/"
1543    Redirect permanent index.html http://$servername\:$intranetport/cgi-bin/koha/mainpage.pl
1544    ErrorLog $logfiledir/koha-error_log
1545    TransferLog $logfiledir/koha-access_log
1546    SetEnv PERL5LIB "$intranetdir/modules"
1547    SetEnv KOHA_CONF "$etcdir/koha.conf"
1548    $includesdirectives
1549 </VirtualHost>
1550
1551 # If you want to use name based Virtual Hosting:
1552 #   1. remove the two Listen lines
1553 #   2. replace $servername\:$opacport wih your.opac.domain.name
1554 #   3. replace ServerName $servername wih ServerName your.opac.domain.name
1555 #   4. replace $servername\:$intranetport wih your intranet domain name
1556 #   5. replace ServerName $servername wih ServerName your.intranet.domain.name
1557 #
1558 # If you want to use NameVirtualHost'ing (using two names on one ip address):
1559 #   1.  Follow steps 1-5 above
1560 #   2.  Uncomment the NameVirtualHost line and set the correct ip address
1561
1562 EOP
1563
1564
1565     }
1566 }
1567
1568
1569 # =item C<basicauthentication(;$)>
1570
1571 # Asks the user whether HTTP basic authentication is wanted, and,
1572 # if so, the user name and password for the basic authentication.
1573
1574 # These pieces of information are saved to global variables; the
1575 # function does not return any values.
1576
1577 # =cut
1578
1579 # $messages->{'IntranetAuthenticationQuestion'}->{en} =
1580 #    heading('LIBRARIAN AUTHENTICATION') . qq|
1581 # The Librarian site can be password protected using
1582 # Apache's Basic Authorization instead of Koha user details.
1583
1584 # This method going to be phased out very soon.  Most users should answer N here.
1585
1586 # Would you like to do this (Y/[N]): |; #'
1587
1588 # $messages->{'BasicAuthUsername'}->{en}="Please enter a username for librarian access [%s]: ";
1589 # $messages->{'BasicAuthPassword'}->{en}="Please enter a password for %s: ";
1590 # $messages->{'BasicAuthPasswordWasBlank'}->{en}="\nYou cannot use a blank password!\n\n";
1591
1592 # sub basicauthentication {
1593 #     my $message=getmessage('IntranetAuthenticationQuestion');
1594 #     my $answer=showmessage($message, 'yn', 'n');
1595 #     my $httpdconf = $etcdir."/koha-httpd.conf";
1596
1597 #     my $apacheauthusername='librarian';
1598 #     my $apacheauthpassword='';
1599 #     if ($answer=~/^y/i) {
1600 #       ($apacheauthusername) = showmessage(getmessage('BasicAuthUsername', [ $apacheauthusername]), 'free', $apacheauthusername, 1);
1601 #       $apacheauthusername=~s/[^a-zA-Z0-9]//g;
1602 #       while (! $apacheauthpassword) {
1603 #           ($apacheauthpassword) = showmessage(getmessage('BasicAuthPassword', [ $apacheauthusername]), 'free', 1);
1604 #           if (!$apacheauthpassword) {
1605 #               ($apacheauthpassword) = showmessage(getmessage('BasicAuthPasswordWasBlank'), 'none', '', 1);
1606 #           }
1607 #       }
1608 #       open AUTH, ">$etcdir/kohaintranet.pass";
1609 #       my $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
1610 #       my $salt=substr($chars, int(rand(length($chars))),1);
1611 #       $salt.=substr($chars, int(rand(length($chars))),1);
1612 #       print AUTH $apacheauthusername.":".crypt($apacheauthpassword, $salt)."\n";
1613 #       close AUTH;
1614 #       open(SITE,">>$httpdconf") or warn "Insufficient priveleges to open $realhttpdconf for writing.\n";
1615 #       print SITE <<EOP
1616
1617 # <Directory $intranetdir>
1618 #     AuthUserFile $etcdir/kohaintranet.pass
1619 #     AuthType Basic
1620 #     AuthName "Koha Intranet (for librarians only)"
1621 #     Require  valid-user
1622 # </Directory>
1623 # EOP
1624 #     }
1625 #     close(SITE);
1626 # }
1627
1628
1629 =item C<installfiles(;$$)>
1630
1631 Copy the Koha files to the specified OPAC and INTRANET
1632 directories (usually in /usr/local/koha).
1633
1634 Creates the koha.conf file, but as koha.conf.tmp. The caller is
1635 responsible for calling C<finalizeconfigfile(;$)> when installation is
1636 completed, to rename it back to koha.conf.
1637
1638 The first parameter may be a marker to say this is a new installation,
1639 rather than an upgrade.
1640
1641 =cut
1642
1643 $messages->{'InstallFiles'}->{en} = heading('INSTALLING FILES') . qq|
1644 Copying files to installation directories:
1645
1646 |;
1647
1648 $messages->{'OldFiles'}->{en} = heading('OLD FILES') . qq|
1649 Any files from the previous edition of Koha have been
1650 copied to a dated backup directory alongside the new
1651 installation. You should move any custom files that you
1652 want to keep (such as your site templates) into the new
1653 directories and then move the backup off of the live
1654 server.
1655
1656 Press ENTER to continue:|;
1657
1658
1659 $messages->{'CopyingFiles'}->{en}="Copying %s to %s.\n";
1660
1661
1662
1663 sub installfiles (;$$) {
1664
1665         my ($is_first_install,$auto_install) = @_;
1666         # $is_install is set if it's a fresh install and not an upgrade. If it's an upgrade, copy old files.
1667         
1668         sub neatcopy {
1669                 my $desc = shift;
1670                 my $src = shift;
1671                 my $tgt = shift;
1672                 my $auto_install = shift;
1673                 my $is_first_install = shift;
1674                 if (!$is_first_install && -e $tgt) {
1675                 print getmessage('CopyingFiles', ["old ".$desc,$tgt.strftime("%Y%m%d%H%M",localtime())]) unless ($auto_install->{NoPressEnter});
1676                         system("mv ".$tgt." ".$tgt.strftime("%Y%m%d%H%M",localtime()));
1677                         system("mkdir ".$tgt);   ##New line 
1678                 }
1679                 print getmessage('CopyingFiles', [$desc,$tgt]) unless ($auto_install->{NoPressEnter});
1680                 system("cp -R ".$src."/* ".$tgt);
1681         }
1682
1683 #       my ($auto_install) = @_;
1684         showmessage(getmessage('InstallFiles'),'none') unless ($auto_install->{NoPressEnter});
1685
1686         neatcopy("admin templates", 'intranet-html', "$intranetdir/htdocs",$auto_install,$is_first_install);
1687         neatcopy("admin interface", 'intranet-cgi', "$intranetdir/cgi-bin",$auto_install,$is_first_install);
1688         neatcopy("main scripts", 'scripts', "$intranetdir/scripts",$auto_install,$is_first_install);
1689         neatcopy("perl modules", 'modules', "$intranetdir/modules",$auto_install,$is_first_install);
1690         neatcopy("OPAC templates", 'opac-html', "$opacdir/htdocs",$auto_install,$is_first_install);
1691         neatcopy("OPAC interface", 'opac-cgi', "$opacdir/cgi-bin",$auto_install,$is_first_install);
1692         startsysout();
1693         system("touch $opacdir/cgi-bin/opac");
1694
1695         #MJR: is this necessary?
1696         if ($> == 0) {
1697                 my $httpdgrp = getgrnam($httpduser);
1698                 system("chown -R $httpduser:$httpdgrp $opacdir $intranetdir");
1699         }
1700         system("chmod -R a+rx $opacdir $intranetdir");
1701
1702         # Create /etc/koha.conf
1703
1704         my $old_umask = umask(027); # make sure koha.conf is never world-readable
1705         open(SITES,">$etcdir/koha.conf.tmp") or warn "Couldn't create file at $etcdir. Must have write capability.\n";
1706         print SITES qq|
1707 database=$database
1708 hostname=$hostname
1709 user=$user
1710 pass=$pass
1711 intranetdir=$intranetdir
1712 opacdir=$opacdir
1713 kohalogdir=$kohalogdir
1714 kohaversion=$newversion
1715 httpduser=$httpduser
1716 intrahtdocs=$intranetdir/htdocs/intranet-tmpl
1717 opachtdocs=$opacdir/htdocs/opac-tmpl
1718 |;
1719         close(SITES);
1720         umask($old_umask);
1721
1722         startsysout();
1723         #MJR: can't help but this be broken, can we?
1724         chmod 0440, "$etcdir/koha.conf.tmp";
1725         
1726         #MJR: does this contain any passwords?
1727         chmod 0755, "$intranetdir/scripts/z3950daemon/z3950-daemon-launch.sh", "$intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh", "$intranetdir/scripts/z3950daemon/processz3950queue";
1728
1729         open(FILE,">$intranetdir/scripts/z3950daemon/z3950-daemon-options");
1730         print FILE "RunAsUser=$httpduser\nKohaZ3950Dir=$intranetdir/scripts/z3950daemon\nKohaModuleDir=$intranetdir/modules\nLogDir=$kohalogdir\nKohaConf=$etcdir/koha.conf";
1731         close(FILE);
1732
1733         if ($> == 0) {
1734             chown((getpwnam($httpduser)) [2,3], "$etcdir/koha.conf.tmp") or warn "can't chown koha.conf: $!";
1735                 chown(0, (getpwnam($httpduser)) [3], "$intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh") or warn "can't chown $intranetdir/scripts/z3950daemon/z3950-daemon-shell.sh: $!";
1736                 chown(0, (getpwnam($httpduser)) [3], "$intranetdir/scripts/z3950daemon/processz3950queue") or warn "can't chown $intranetdir/scripts/z3950daemon/processz3950queue: $!";
1737         } #MJR: report that we haven't chown()d.
1738         else {
1739                 print "Please check permissions in $intranetdir/scripts/z3950daemon\n";
1740         }
1741         showmessage(getmessage('OldFiles'),'PressEnter') unless ($auto_install->{NoPressEnter} or $is_first_install);
1742 }
1743
1744
1745 =item C<databasesetup(;$)>
1746
1747 Finds out where the MySQL utitlities are located in the system,
1748 then create the Koha database structure and MySQL permissions.
1749
1750 =cut
1751
1752 $messages->{'MysqlRootPassword'}->{en} =
1753    heading('MYSQL ROOT USER PASSWORD') . qq|
1754 To create the koha database, please enter your
1755 mysql server's root user password:
1756
1757 Password: |;
1758
1759 $messages->{'CreatingDatabase'}->{en} = heading('CREATING DATABASE') . qq|
1760 Creating the MySQL database for Koha...
1761
1762 |;
1763
1764 $messages->{'CreatingDatabaseError'}->{en} =
1765    heading('ERROR CREATING DATABASE') . qq|
1766 Couldn't connect to the MySQL server for the reason given above.
1767 This is a serious problem, the database will not get installed.
1768
1769 Press <ENTER> to continue: |;   #'
1770
1771 $messages->{'SampleData'}->{en} = heading('SAMPLE DATA') . qq|
1772 If you are installing Koha for evaluation purposes,
1773 you can install some sample data now.
1774
1775 If you are installing Koha to use your own
1776 data, you probably don't want this sample data installed.
1777
1778 Would you like to install the sample data? Y/[N]: |;    #'
1779
1780 $messages->{'SampleDataInstalled'}->{en} =
1781    heading('SAMPLE DATA INSTALLED') . qq|
1782 Sample data has been installed.  For some suggestions on testing Koha, please
1783 read the file doc/HOWTO-Testing.  If you find any bugs, please submit them at
1784 http://bugs.koha.org/.  If you need help with testing Koha, you can post a
1785 question through the koha-devel mailing list, or you can check for a developer
1786 online at irc.katipo.co.nz:6667 channel #koha.
1787
1788 You can find instructions for subscribing to the Koha mailing lists at:
1789
1790     http://www.koha.org
1791
1792
1793 Press <ENTER> to continue: |;
1794
1795 $messages->{'AddBranchPrinter'}->{en} = heading('Add Branch and Printer') . qq|
1796 Would you like to describe an initial branch and printer? [Y]/N: |;
1797
1798 $messages->{'BranchName'}->{en}="Branch Name [%s]: ";
1799 $messages->{'BranchCode'}->{en}="Branch Code (4 letters or numbers) [%s]: ";
1800 $messages->{'PrinterQueue'}->{en}="Printer Queue [%s]: ";
1801 $messages->{'PrinterName'}->{en}="Printer Name [%s]: ";
1802
1803 sub databasesetup (;$) {
1804         my ($auto_install) = @_;
1805     $mysqluser = 'root';
1806     $mysqlpass = '';
1807         my $mysqldir = getmysqldir();
1808
1809         if ($auto_install->{MysqlRootPassword}) {
1810                 $mysqlpass=$auto_install->{MysqlRootPassword};
1811         } else {
1812         # we must not put the mysql root password on the command line
1813                 $mysqlpass=     showmessage(getmessage('MysqlRootPassword'),'silentfree');
1814         }
1815         
1816         showmessage(getmessage('CreatingDatabase'),'none') unless ($auto_install->{NoPressEnter});
1817         # set the login up
1818         setmysqlclipass($mysqlpass);
1819         # Set up permissions
1820         startsysout();
1821        print system("$mysqldir/bin/mysql -u$mysqluser -e \"insert into user (Host,User,Password) values ('$hostname','$user',password('$pass'))\" -h$hostname mysql\;");
1822        system("$mysqldir/bin/mysql -u$mysqluser -e \"insert into db (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv, index_priv, alter_priv) values ('%','$database','$user','Y','Y','Y','Y','Y','Y','Y','Y')\" -h$hostname mysql");
1823        system("$mysqldir/bin/mysqladmin -u$mysqluser -h$hostname reload");
1824
1825         my $result=system("$mysqldir/bin/mysqladmin", "-u$mysqluser", "create", "$database");
1826         system("$mysqldir/bin/mysql '-u$mysqluser' -e \"GRANT ALL PRIVILEGES on ".$database.".* to '$user' IDENTIFIED BY '$pass' \" mysql");
1827         # Change to admin user login
1828         setmysqlclipass($pass);
1829         if ($result) {
1830                 showmessage(getmessage('CreatingDatabaseError'),'PressEnter', '', 1);
1831         } else {
1832                 # Create the database structure
1833                 startsysout();
1834                 system("$mysqldir/bin/mysql '-u$user' '$database' < koha.mysql");
1835         }
1836
1837 }
1838
1839
1840 =item C<updatedatabase(;$)>
1841
1842 Updates the Koha database structure, including the addition of
1843 MARC tables.
1844
1845 The MARC tables are also populated in addition to being created.
1846
1847 Because updatedatabase calls scripts/updater/updatedatabase to
1848 do the actual update, and that script uses C4::Context,
1849 $etcdir/koha.conf must exist at this point. We use the KOHA_CONF
1850 environment variable to do this.
1851
1852 FIXME: (See checkabortedinstall as it depends on old symlink way.)
1853
1854 =cut
1855
1856 $messages->{'UpdateMarcTables'}->{en} =
1857    heading('MARC FIELD DEFINITIONS') . qq|
1858 You can import MARC settings for:
1859
1860   1 MARC21 in english
1861   2 UNIMARC in french
1862   3 UNIMARC in english
1863   4 UNIMARC in ukrainian
1864   N none
1865
1866 NOTE: If you choose N,
1867 nothing will be added, and you must create them all yourself.
1868 Only choose N if you want to use a MARC format not listed here,
1869 such as DANMARC.  We would like to hear from you if you do.
1870
1871 *** UPGRADE ***
1872 If you UPGRADE your version from a previous 2.x.x, the right choice here is N (None) to preserve your local MARC setup.
1873
1874 Choose MARC definition [1]: |;
1875
1876 $messages->{'Language'}->{en} = heading('CHOOSE LANGUAGE') . qq|
1877 This version of koha supports a few languages.
1878
1879   en : default language, all pages available
1880   fr : complete translation
1881   es : partial librarian site translation
1882   zh_TW : partial translation
1883
1884 en is used when a screen is not available in your language
1885
1886 If you specify a language here, you can still
1887 change it from the system preferences screen in the librarian sit.
1888
1889 Which language do you choose? |;
1890
1891 sub updatedatabase (;$) {
1892         my ($auto_install) = @_;
1893     # At this point, $etcdir/koha.conf must exist, for C4::Context
1894     $ENV{"KOHA_CONF"}=$etcdir.'/koha.conf';
1895     if (! -e $ENV{"KOHA_CONF"}) { $ENV{"KOHA_CONF"}=$etcdir.'/koha.conf.tmp'; }
1896         startsysout();  
1897         setmysqlclipass($pass);
1898         my $result=system ("perl -I $intranetdir/modules scripts/updater/updatedatabase -s");
1899         if ($result) {
1900                 restoremycnf();
1901                 print "Problem updating database...\n";
1902                 exit;
1903         }
1904         my $response;
1905         if ($auto_install->{UpdateMarcTables}) {
1906                 $response=$auto_install->{UpdateMarcTables};
1907                 print ON_YELLOW.BLACK."auto-setting UpdateMarcTable to : $response".RESET."\n";
1908         } else {
1909                 $response=showmessage(getmessage('UpdateMarcTables'), 'restrictchar 1234Nn', '1');
1910         }
1911         startsysout();
1912         if ($response eq '1') {
1913                 system("cat scripts/misc/marc_datas/marc21_en/structure_def.sql | $mysqldir/bin/mysql '-u$user' '$database'");
1914         }
1915         if ($response eq '2') {
1916                 system("cat scripts/misc/marc_datas/unimarc_fr/structure_def.sql | $mysqldir/bin/mysql '-u$user' '$database'");
1917         }
1918         if ($response eq '3') {
1919                 system("cat scripts/misc/marc_datas/unimarc_en/structure_def.sql | $mysqldir/bin/mysql '-u$user' '$database'");
1920         }
1921         if ($response eq '4') {
1922                 system("cat scripts/misc/marc_datas/unimarc_uk/structure_def.sql | $mysqldir/bin/mysql '-u$user' '$database'");
1923         }
1924         delete($ENV{"KOHA_CONF"});
1925
1926         print RESET."\nFinished updating of database. Press <ENTER> to continue..." unless ($auto_install->{NoPressEnter});
1927         <STDIN> unless ($auto_install->{NoPressEnter});
1928 }
1929
1930
1931 =item C<populatedatabase(;$)>
1932
1933 Populates the non-MARC tables and installs sample data,
1934 if wanted.
1935
1936 =cut
1937
1938 $messages->{'ConfirmFileUpload'}->{en} = qq|
1939 Confirm loading of this file into Koha  [Y]/N: |;
1940
1941 sub populatedatabase (;$) {
1942         my ($auto_install) = @_;
1943         my $input;
1944         my $response;
1945         my $branch='MAIN';
1946         if ($auto_install->{BranchName}) {
1947                 $branch=$auto_install->{BranchName};
1948                 print ON_YELLOW.BLACK."auto-setting a branch : $branch".RESET."\n";
1949         } else {
1950                 $response=showmessage(getmessage('AddBranchPrinter'), 'yn', 'y');
1951                 unless ($response =~/^n/i) {
1952                         $branch=showmessage(getmessage('BranchName', [$branch]), 'free', $branch, 1);
1953                         $branch=~s/[^A-Za-z0-9\s]//g;
1954                 }
1955         }
1956         if ($branch) {
1957                 my $branchcode=$branch;
1958                 $branchcode=~s/[^A-Za-z0-9]//g;
1959                 $branchcode=uc($branchcode);
1960                 $branchcode=substr($branchcode,0,4);
1961                 if ($auto_install->{BranchCode}) {
1962                         $branchcode=$auto_install->{BranchCode};
1963                         print ON_YELLOW.BLACK."auto-setting branch code : $branchcode".RESET."\n";
1964                 } else {
1965                         $branchcode=showmessage(getmessage('BranchCode', [$branchcode]), 'free', $branchcode, 1);
1966                 }
1967                 $branchcode=~s/[^A-Za-z0-9]//g;
1968                 $branchcode=uc($branchcode);
1969                 $branchcode=substr($branchcode,0,4);
1970                 $branchcode or $branchcode='DEF';
1971
1972                 startsysout();
1973                 system("$mysqldir/bin/mysql '-u$user' -e \"insert into branches (branchcode,branchname,issuing) values ('$branchcode', '$branch', 1)\" $database");
1974                 system("$mysqldir/bin/mysql '-u$user' -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'IS')\" $database");
1975                 system("$mysqldir/bin/mysql '-u$user' -e \"insert into branchrelations (branchcode,categorycode) values ('MAIN', 'CU')\" $database");
1976
1977                 my $printername='lp';
1978                 my $printerqueue='/dev/lp0';
1979                 if ($auto_install->{PrinterName}) {
1980                         $printername=$auto_install->{PrinterName};
1981                         print ON_YELLOW.BLACK."auto-setting a printer : $printername".RESET."\n";
1982                 } else {
1983                         $printername=showmessage(getmessage('PrinterName', [$printername]), 'free', $printername, 1);
1984                         $printername=~s/[^A-Za-z0-9\s]//g;
1985                 }
1986                 if ($auto_install->{PrinterQueue}) {
1987                         $printerqueue=$auto_install->{PrinterQueue};
1988                         print ON_YELLOW.BLACK."auto-setting printer queue to : $printerqueue".RESET."\n";
1989                 } else {
1990                         $printerqueue=showmessage(getmessage('PrinterQueue', [$printerqueue]), 'free', $printerqueue, 1);
1991                         $printerqueue=~s/[^A-Za-z0-9]//g;
1992                 }
1993                 startsysout();  
1994                 system("$mysqldir/bin/mysql '-u$user' -e \"insert into printers (printername,printqueue,printtype) values ('$printername', '$printerqueue', '')\" $database");
1995         }
1996         my $language;
1997         if ($auto_install->{Language}) {
1998                 $language=$auto_install->{Language};
1999                 print ON_YELLOW.BLACK."auto-setting language to : $language".RESET."\n";
2000         } else {
2001                 $language=showmessage(getmessage('Language'), 'free', 'en');
2002         }
2003         startsysout();  
2004         system("$mysqldir/bin/mysql '-u$user' -e \"update systempreferences set value='$language' where variable='opaclanguages'\" $database");
2005         my @dirs;
2006         if (-d "scripts/misc/sql-datas") {
2007                 # ask for directory to look for files to append
2008                 my @directories;
2009                 push @directories,"FINISHED";
2010                 if (-d "scripts/misc/sql-datas") {
2011                         opendir D, "scripts/misc/sql-datas";
2012                         foreach my $dir (readdir D) {
2013                                 next if ($dir =~ /^\./);
2014                                 push @directories, $dir;
2015                         }
2016                 }
2017                 my $loopend=0;
2018                 while (not $loopend) {
2019                         print heading("SELECT SQL DIRECTORY");
2020                         print qq|
2021 Select a directory. You will see every file included in this directory and be able to choose file(s) to import into Koha
2022 This is a VERY important feature. By selecting the proper options, you can get a pre-setup Koha, almost ready to be put in production.
2023 Choose wisely.
2024 |;
2025                         for (my $i=0;$i<=$#directories;$i++) {
2026                                 print "$i => ".$directories[$i]."\n";
2027                         }
2028                         my $sqluploaddir =<STDIN>;
2029                         if ($sqluploaddir==0) {
2030                                 $loopend = 1;
2031                         } else {
2032                                 $sqluploaddir = $directories[$sqluploaddir];
2033                                 # CHECK for any other file to append...
2034                                 my @sql;
2035                                 push @sql,"FINISHED";
2036                                 if (-d "scripts/misc/sql-datas/$sqluploaddir") {
2037                                         opendir D, "scripts/misc/sql-datas/$sqluploaddir";
2038                                         foreach my $sql (readdir D) {
2039                                                 next unless ($sql =~ /.txt$/);
2040                                                 push @sql, $sql;
2041                                         }
2042                                 }
2043                                 $loopend=0;
2044                                 while (not $loopend) {
2045                                         print heading("SELECT SQL FILE");
2046                                         print qq|
2047 Select a file to append to the Koha DB.
2048 enter a number. A detailled explanation of the file will be given
2049 if you confirm, the file will be added to the DB
2050 |;
2051                                         for (my $i=0;$i<=$#sql;$i++) {
2052                                                 print "$i => ".$sql[$i]."\n";
2053                                         }
2054                                         my $response =<STDIN>;
2055                                         if ($response==0) {
2056                                                 $loopend = 1;
2057                                         } else {
2058                                                 # show the content of the file
2059                                                 my $FileToUpload = $sql[$response];
2060                                                 open FILE,"scripts/misc/sql-datas/$sqluploaddir/$FileToUpload";
2061                                                 my $content = <FILE>;
2062                                                 print heading("INSERT $sqluploaddir/$FileToUpload ?")."$content\n";
2063                                                 # ask confirmation
2064                                                 $response=showmessage(getmessage('ConfirmFileUpload'), 'yn', 'y');
2065                                                 # if confirmed, upload the file in the DB
2066                                                 unless ($response =~/^n/i) {
2067                                                         $FileToUpload =~ s/\.txt/\.sql/;
2068                                                         system("$mysqldir/bin/mysql '-u$user' '$database' <scripts/misc/sql-datas/$sqluploaddir/$FileToUpload");
2069                                                 }
2070                                         }
2071                                 }
2072                                 $loopend=0;
2073                         }
2074                 }
2075         }
2076 }
2077
2078 =item C<restartapache(;$)>
2079
2080 Asks the user whether to restart Apache, and restarts it if the user
2081 wants so.
2082
2083 =cut
2084
2085 $messages->{'RestartApache'}->{en} = heading('RESTART APACHE') . qq|
2086 The web server daemon needs to be restarted to load the new configuration for Koha.
2087 The installer can do this if you are using Apache and give the root password.
2088
2089 Would you like to try to restart Apache now?  [Y]/N: |;
2090
2091 sub restartapache (;$) {
2092         my ($auto_install)=@_;
2093         my $response;
2094     $response=showmessage(getmessage('RestartApache'), 'yn', 'y') unless ($auto_install->{NoPressEnter});
2095     $response='y' if ($auto_install->{NoPressEnter});
2096
2097     unless ($response=~/^n/i) {
2098                 startsysout();
2099                 # Need to support other init structures here?
2100                 if (-e "/etc/rc.d/init.d/httpd") {
2101                         system('su root -c "/etc/rc.d/init.d/httpd restart"');
2102                 } elsif (-e "/etc/init.d/apache") {
2103                         system('su root -c "/etc/init.d/apache restart"');
2104                 } elsif (-e "/etc/init.d/apache-ssl") {
2105                         system('su root -c "/etc/init.d/apache-ssl restart"');
2106                 }
2107         }
2108 }
2109
2110 =item C<backupkoha(;$)>
2111
2112 Attempts to make backup copies of all koha's details.
2113
2114 =cut
2115
2116 $messages->{'BackupDir'}->{en} = heading('BACKUP STORAGE').qq|
2117 The upgrader will now try to backup your old files.
2118
2119 Please specify a directory to store the backup in [%s]: |;
2120
2121 $messages->{'BackupSummary'}->{en} = heading('BACKUP SUMMARY').qq|
2122 Backed up:
2123
2124 %6d biblio entries
2125 %6d biblioitems entries
2126 %6d items entries
2127 %6d borrowers
2128
2129 File Listing
2130 ---------------------------------------------------------------------
2131 %s
2132 ---------------------------------------------------------------------
2133
2134 Does this look right? ([Y]/N): |;
2135
2136 #FIXME: rewrite to use Install.pm
2137 sub backupkoha () {
2138 if (!$ENV{prefix}) { $ENV{prefix} = "/usr/local"; }
2139 my $backupdir=$ENV{prefix}.'/backups';
2140
2141 my $answer = showmessage(getmessage('BackupDir',[$backupdir]),'free',$backupdir);
2142 $backupdir = $answer; 
2143
2144 if (! -e $backupdir) {
2145         my $result=mkdir ($backupdir, oct(770));
2146         if ($result==0) {
2147                 my @dirs = split(m#/#, $backupdir);
2148                 my $checkdir='';
2149                 foreach (@dirs) {
2150                         $checkdir.="$_/";
2151                         unless (-e "$checkdir") {
2152                                 mkdir($checkdir, 0775);
2153                         }
2154                 }
2155         }
2156 }
2157
2158 chmod 0770, $backupdir;
2159
2160 # Backup MySql database
2161 #
2162 #
2163 my $mysqldir = getmysqldir();
2164
2165 my ($sec, $min, $hr, $day, $month, $year) = (localtime(time))[0,1,2,3,4,5];
2166 $month++;
2167 $year+=1900;
2168 my $date= sprintf "%4d-%02d-%02d_%02d:%02d:%02d", $year, $month, $day,$hr,$min,$sec;
2169
2170 setmysqlclipass($pass); 
2171 open (MD, "$mysqldir/bin/mysqldump --user=$user --host=$hostname $database|");
2172
2173 (open BF, ">$backupdir/Koha.backup_$date") || (die "Error opening up backup file $backupdir/Koha.backup_$date: $!\n");
2174
2175 my $itemcounter=0;
2176 my $bibliocounter=0;
2177 my $biblioitemcounter=0;
2178 my $membercounter=0;
2179
2180 while (<MD>) {
2181         (/insert into items /i) && ($itemcounter++);
2182         (/insert into biblioitems /i) && ($biblioitemcounter++);
2183         (/insert into biblio /i) && ($bibliocounter++);
2184         (/insert into borrowers /i) && ($membercounter++);
2185         print BF $_;
2186 }
2187
2188 close BF;
2189 close MD;
2190
2191 my $filels=`ls -hl $backupdir/Koha.backup_$date`;
2192 chomp $filels;
2193 $answer = showmessage(getmessage('BackupSummary',[$bibliocounter, $biblioitemcounter, $itemcounter, $membercounter, $filels]),'yn');
2194
2195 if ($answer=~/^n/i) {
2196     print qq|
2197
2198 Aborting.  The database dump is located in:
2199
2200         $backupdir/Koha.backup_$date
2201
2202 |;
2203     exit;
2204 } else {
2205         print "Great! continuing upgrade... \n";
2206 };
2207
2208
2209
2210 }
2211
2212 =item C<finalizeconfigfile()>
2213
2214 Renames F<koha.conf.tmp> file to F<koha.conf>.
2215
2216 This file must be renamed when the installation is complete,
2217 Currently, failure to rename the file results only in a warning.
2218
2219 =cut
2220
2221 sub finalizeconfigfile {
2222         restoremycnf();
2223    rename "$etcdir/koha.conf.tmp", "$etcdir/koha.conf"
2224       || showmessage(<<EOF, 'PressEnter', undef, 1);
2225 An unexpected error, $!, occurred
2226 while the Koha config file is being saved to its final location,
2227 $etcdir/koha.conf.
2228
2229 Couldn't rename file at $etcdir. Must have write capability.
2230
2231 Press Enter to continue.
2232 EOF
2233 #'
2234 }
2235
2236
2237 =item C<loadconfigfile()>
2238
2239 Opens the existing koha.conf file and gets its values, saving the
2240 values to some global variables.  If the existing koha.conf file
2241 cannot be opened for any reason, the file is silently ignored.
2242
2243 =cut
2244
2245 sub loadconfigfile () {
2246     my %configfile;
2247
2248         #MJR: reverted to r1.53.  Please call setetcdir().  Do NOT hardcode this.
2249         #FIXME: make a dated backup
2250     open (KC, "<$etcdir/koha.conf");
2251     while (<KC>) {
2252      chomp;
2253      (next) if (/^\s*#/);
2254      if (/(.*)\s*=\s*(.*)/) {
2255        my $variable=$1;
2256        my $value=$2;
2257        # Clean up white space at beginning and end
2258        $variable=~s/^\s*//g;
2259        $variable=~s/\s*$//g;
2260        $value=~s/^\s*//g;
2261        $value=~s/\s*$//g;
2262        $configfile{$variable}=$value;
2263      }
2264     }
2265
2266         #MJR: Reverted this too. You do not mess with my privates. Please ask for new functions if required.
2267     $intranetdir=$configfile{'intranetdir'};
2268     $opacdir=$configfile{'opacdir'};
2269     $kohaversion=$configfile{'kohaversion'};
2270     $kohalogdir=$configfile{'kohalogdir'};
2271     $database=$configfile{'database'};
2272     $hostname=$configfile{'hostname'};
2273     $user=$configfile{'user'};
2274     $pass=$configfile{'pass'};
2275 }
2276
2277 END { }       # module clean-up code here (global destructor)
2278
2279 ### These things may move
2280
2281 sub setecho {
2282 my $state=shift;
2283 my $t = POSIX::Termios->new;
2284
2285 $t->getattr();
2286 if ($state) {
2287   $t->setlflag(($t->getlflag) | &POSIX::ECHO);
2288   }
2289 else {
2290   $t->setlflag(($t->getlflag) & !(&POSIX::ECHO));
2291   }
2292 $t->setattr();
2293 }
2294
2295 sub setmysqlclipass {
2296         my $pass = shift;
2297         open(MYCNF,">$mycnf");
2298         chmod(0600,$mycnf);
2299         print MYCNF "[client]\npassword=$pass\n";
2300         close(MYCNF);
2301 }
2302
2303 sub backupmycnf {
2304         if (-e $mycnf) {
2305                 rename $mycnf,$mytmpcnf;
2306         }
2307 }
2308
2309 sub restoremycnf {
2310         if (defined $mycnf && -e $mycnf) {
2311                 unlink($mycnf);
2312         }
2313         if (defined $mytmpcnf && -e $mytmpcnf) {
2314                 rename $mytmpcnf,$mycnf;
2315         }
2316 }
2317
2318 =back
2319
2320 =head1 SEE ALSO
2321
2322 buildrelease.pl
2323 installer.pl
2324 koha.upgrade
2325
2326 =cut
2327
2328 1;