Diff for /doc/install/linux/install.pl between versions 1.45.2.23 and 1.75

version 1.45.2.23, 2024/08/05 13:42:44 version 1.75, 2021/03/26 18:38:03
Line 26 Line 26
 use strict;  use strict;
 use File::Copy;  use File::Copy;
 use Term::ReadKey;  use Term::ReadKey;
   use Socket;
   use Sys::Hostname::FQDN();
 use DBI;  use DBI;
 use File::Spec;  use File::Spec;
 use Cwd();  use Cwd();
Line 210  sub get_distro { Line 212  sub get_distro {
             $distro = 'rhes'.$1;              $distro = 'rhes'.$1;
             $updatecmd = 'dnf install LONCAPA-prerequisites';              $updatecmd = 'dnf install LONCAPA-prerequisites';
             $installnow = 'dnf -y install LONCAPA-prerequisites';              $installnow = 'dnf -y install LONCAPA-prerequisites';
         } elsif ($versionstring =~ /CentOS(| Linux| Stream) release (\d+)/) {          } elsif ($versionstring =~ /CentOS(?:| Linux| Stream) release (\d+)/) {
             $distro = 'centos'.$2;              $distro = 'centos'.$1;
             if ($1 eq ' Stream') {  
                 $distro .= '-stream';  
             }  
             $updatecmd = 'yum install LONCAPA-prerequisites';              $updatecmd = 'yum install LONCAPA-prerequisites';
             $installnow = 'yum -y install LONCAPA-prerequisites';              $installnow = 'yum -y install LONCAPA-prerequisites';
         } elsif ($versionstring =~ /Scientific Linux (?:SL )?release ([\d.]+) /) {          } elsif ($versionstring =~ /Scientific Linux (?:SL )?release ([\d.]+) /) {
Line 223  sub get_distro { Line 222  sub get_distro {
             $distro = 'scientific'.$ver;              $distro = 'scientific'.$ver;
             $updatecmd = 'yum install LONCAPA-prerequisites';              $updatecmd = 'yum install LONCAPA-prerequisites';
             $installnow = 'yum -y install LONCAPA-prerequisites';              $installnow = 'yum -y install LONCAPA-prerequisites';
         } elsif ($versionstring =~ /Rocky Linux release ([\d.]+)/) {  
             my $ver = $1;  
             $ver =~ s/\.\d+$//;  
             $distro = 'rocky'.$ver;  
             $updatecmd = 'dnf install LONCAPA-prerequisites';  
             $installnow = 'dnf -y install LONCAPA-prerequisites';  
         } elsif ($versionstring =~ /AlmaLinux release ([\d.]+) /) {  
             my $ver = $1;  
             $ver =~ s/\.\d+$//;  
             $distro = 'alma'.$ver;  
             $updatecmd = 'dnf install LONCAPA-prerequisites';  
             $installnow = 'dnf -y install LONCAPA-prerequisites';  
         } else {          } else {
             print &mt('Unable to interpret [_1] to determine system type.',              print &mt('Unable to interpret [_1] to determine system type.',
                       '/etc/redhat-release')."\n";                        '/etc/redhat-release')."\n";
Line 343  sub get_distro { Line 330  sub get_distro {
     return ($distro,$packagecmd,$updatecmd,$installnow);      return ($distro,$packagecmd,$updatecmd,$installnow);
 }  }
   
   #
   # get_hostname() prompts the user to provide the server's hostname.
   #
   # If invalid input is provided, the routine is called recursively 
   # until, a valid hostname is provided.
   # 
   
   sub get_hostname {
       my $hostname;
       print &mt('Enter the hostname of this server, e.g., loncapa.somewhere.edu'."\n");
       my $choice = <STDIN>;
       chomp($choice);
       $choice =~ s/(^\s+|\s+$)//g;
       if ($choice eq '') {
           print &mt("Hostname you entered was either blank or contanied only white space.\n");
       } elsif ($choice =~ /^[\w\.\-]+$/) {
           $hostname = $choice;
       } else {
           print &mt("Hostname you entered was invalid --  a hostname may only contain letters, numbers, - and .\n");
       }
       while ($hostname eq '') {
           $hostname = &get_hostname();
       }
       print "\n";
       return $hostname;
   }
   
   #
   # get_hostip() prompts the user to provide the server's IPv4 IP address
   #
   # If invalid input is provided, the routine is called recursively 
   # until, a valid IPv4 address is provided.
   #
   
   sub get_hostip {
       my $hostip;
       print &mt('Enter the IP address of this server, e.g., 192.168.10.24'."\n");
       my $choice = <STDIN>;
       chomp($choice);
       $choice =~ s/(^\s+|\s+$)//g;
       my $badformat = 1;
       if ($choice eq '') {
           print &mt("IP address you entered was either blank or contained only white space.\n"); 
       } else {
           if ($choice =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) {
               if (($1<=255) && ($2<=255) && ($3<=255) && ($4<=255)) {
                   $badformat = 0; 
               }
           }
           if ($badformat) { 
                print &mt('Host IP you entered was invalid -- a host IP has the format d.d.d.d where each d is an integer between 0 and 255')."\n";
           } else {
               $hostip = $choice;
           }
       }
       while ($hostip eq '') {
           $hostip = &get_hostip();
       }
       print "\n";
       return $hostip;
   }
   
 sub check_prerequisites {  sub check_prerequisites {
     my ($packagecmd,$distro) = @_;      my ($packagecmd,$distro) = @_;
     my $gotprereqs;      my $gotprereqs;
Line 373  sub check_prerequisites { Line 422  sub check_prerequisites {
   
 sub check_locale {  sub check_locale {
     my ($distro) = @_;      my ($distro) = @_;
     my ($fh,$langvar,$command,$langcmd,$earlyout,$default);      my ($fh,$langvar,$command,$earlyout);
     $langvar = 'LANG';      $langvar = 'LANG';
     if ($distro =~ /^(ubuntu|debian)/) {      if ($distro =~ /^(ubuntu|debian)/) {
         if (!open($fh,"</etc/default/locale")) {          if (!open($fh,"</etc/default/locale")) {
Line 408  sub check_locale { Line 457  sub check_locale {
                       '/etc/sysconfig/i18n');                        '/etc/sysconfig/i18n');
             $earlyout = 1;              $earlyout = 1;
         }          }
     } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle|rocky|alma)(\d+)/) {      } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle)(\d+)/) {
         if ($1 >= 7) {          if ($1 >= 7) {
             if (!open($fh,"</etc/locale.conf")) {              if (!open($fh,"</etc/locale.conf")) {
                 print &mt('Failed to open: [_1], default locale not checked.',                  print &mt('Failed to open: [_1], default locale not checked.',
Line 427  sub check_locale { Line 476  sub check_locale {
             $earlyout = 1;              $earlyout = 1;
         }          }
     }      }
     return () if ($earlyout);      return if ($earlyout);
     my @data = <$fh>;      my @data = <$fh>;
     chomp(@data);      chomp(@data);
     close($fh);  
     foreach my $item (@data) {      foreach my $item (@data) {
         if ($item =~ /^\Q$langvar\E=\"?([^\"]*)\"?/) {          if ($item =~ /^\Q$langvar\E=\"?([^\"]*)\"?/) {
             $default = $1;              my $default = $1;
             if ($default ne 'en_US.UTF-8') {              if ($default ne 'en_US.UTF-8') {
                 if ($distro =~ /^debian/) {                  if ($distro =~ /^debian/) {
                     $command = 'locale-gen en_US.UTF-8'."\n".                      $command = 'locale-gen en_US.UTF-8'."\n".
Line 454  sub check_locale { Line 502  sub check_locale {
             last;              last;
         }          }
     }      }
 # Check for locales      close($fh);
     if ($default ne 'en_US.UTF-8') {      return $command;
         my ($has_us_english,$has_other_code,$has_other_lang);  
         if (open(PIPE,"locale -a 2>/dev/null |")) {  
             while (<PIPE>) {  
                 chomp();  
                 next if (/^(C(|\.utf8)|POSIX)$/i);  
                 if (/^en_US\.utf8/i) {  
                     $has_us_english = 1;  
                 } elsif (/^[A-Za-z]{2}_[A-Za-z]{2}/) {  
                     $has_other_code = 1;  
                 } elsif (/^[A-Za-z]{3,}/) {  
                     $has_other_lang = 1;  
                 }  
             }  
             close(PIPE);  
             if (!$has_us_english) {  
                 if ($has_other_code || $has_other_lang) {  
                     if ($distro =~ /^ubuntu/) {  
                         $langcmd = "sudo apt-get install language-pack-en\n";  
                     } elsif ($distro =~ /^debian/) {  
                         $langcmd = "apt-get install language-pack-en\n";  
                     } elsif ($distro =~ /^(suse|sles)/) {  
                         $langcmd = &mt('Use yast: System > Language > Primary Language = English')."\n";  
                     } elsif ($distro =~ /^fedora(\d+)$/) {  
                         if ($1 > 23) {  
                             $langcmd = "dnf install glibc-langpack-en\n";  
                         } else {  
                             $langcmd = "yum install glibc-common\n";  
                         }  
                     } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle|rocky|alma)(\d+)/) {  
                         if ($1 > 7) {  
                             $langcmd = "dnf install glibc-langpack-en\n";  
                         } else {  
                             $langcmd = "yum install glibc-common\n";  
                         }  
                     }  
                 } else {  
                     if ($distro =~ /^ubuntu/) {  
                         $langcmd = "sudo apt-get install language-pack-en\n";  
                     } elsif ($distro =~ /^debian/) {  
                         $langcmd = "apt-get install language-pack-en\n";  
                     } elsif ($distro =~ /^(suse|sles)/) {  
                         $langcmd = &mt('Use yast: System > Language > Primary Language = English')."\n";  
                     } elsif ($distro =~ /^fedora(\d+)$/) {  
                         if ($1 > 23) {  
                             $langcmd = &mt('Either install all languages[_1]or install English only[_2]',  
                                            ":\ndnf install glibc-all-langpacks\n\n",  
                                            ":\ndnf install glibc-langpack-en\n");  
                         } else {  
                             $langcmd = "yum install glibc-common\n";  
                         }  
                     } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle|rocky|alma)(\d+)/) {  
                         if ($1 > 7) {  
                             $langcmd = &mt('Either install all languages[_1]or install English only[_2]',  
                                            ":\ndnf install glibc-all-langpacks\n\n",  
                                            ":\ndnf install glibc-langpack-en\n");  
                         } else {  
                             $langcmd = "yum install glibc-common\n";  
                         }  
                     }  
                 }  
             }  
         }  
     }  
     return ($command,$langcmd);  
 }  }
   
 sub check_required {  sub check_required {
Line 530  sub check_required { Line 514  sub check_required {
     }      }
     my $gotprereqs = &check_prerequisites($packagecmd,$distro);       my $gotprereqs = &check_prerequisites($packagecmd,$distro); 
     if ($gotprereqs eq '') {      if ($gotprereqs eq '') {
         return ($distro,$gotprereqs,'','',$packagecmd,$updatecmd);          return ($distro,$gotprereqs,'',$packagecmd,$updatecmd);
     }      }
     my ($localecmd,$langcmd) = &check_locale($distro);      my $localecmd = &check_locale($distro);
     unless ($localecmd eq '') {      unless ($localecmd eq '') {
         return ($distro,$gotprereqs,$localecmd,$langcmd);          return ($distro,$gotprereqs,$localecmd);
     }      }
     my ($mysqlon,$mysqlsetup,$mysqlrestart,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,      my ($mysqlon,$mysqlsetup,$mysqlrestart,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,
         %recommended,$downloadstatus,$filetouse,$production,$testing,$apachefw,          %recommended,$downloadstatus,$filetouse,$production,$testing,$apachefw,
         $tostop,$uses_systemctl,$mysql_has_wwwuser);          $tostop,$uses_systemctl,$mysql_has_wwwuser,$hostname,$hostip);
     my $wwwuid = &uid_of_www();      my $wwwuid = &uid_of_www();
     my $wwwgid = getgrnam('www');      my $wwwgid = getgrnam('www');
     if (($wwwuid eq '') || ($wwwgid eq '')) {      if (($wwwuid eq '') || ($wwwgid eq '')) {
Line 547  sub check_required { Line 531  sub check_required {
     unless( -e "/usr/local/sbin/pwauth") {      unless( -e "/usr/local/sbin/pwauth") {
         $recommended{'pwauth'} = 1;          $recommended{'pwauth'} = 1;
     }      }
       $hostname = Sys::Hostname::FQDN::fqdn();
       if ($hostname eq '') {
           $hostname =&get_hostname();
       } else {
           print &mt("Hostname detected: $hostname. Is that correct? ~[Y/n~]");
           if (!&get_user_selection(1)) {
               $hostname =&get_hostname();
           }
       }
       $hostip = Socket::inet_ntoa(scalar(gethostbyname($hostname)) || 'localhost');
       if ($hostip eq '') {
           $hostip=&get_hostip();
       } else {
           print &mt("Host IP address detected: $hostip. Is that correct? ~[Y/n~]");
           if (!&get_user_selection(1)) {
               $hostip=&get_hostip();
           }
       }
       print_and_log("\n".&mt('Hostname is [_1] and IP address is [_2]',$hostname,$hostip)."\n");
     $mysqlon = &check_mysql_running($distro);      $mysqlon = &check_mysql_running($distro);
     if ($mysqlon) {      if ($mysqlon) {
         ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser,$mysql_unix_socket) =          ($mysqlsetup,$has_pass,$dbh,$mysql_has_wwwuser,$mysql_unix_socket) =
Line 554  sub check_required { Line 557  sub check_required {
         if ($mysqlsetup eq 'needsrestart') {          if ($mysqlsetup eq 'needsrestart') {
             $mysqlrestart = '';              $mysqlrestart = '';
             if ($distro eq 'ubuntu') {              if ($distro eq 'ubuntu') {
                 $mysqlrestart = 'sudo ';                  $mysqlrestart = 'sudo '; 
             }              }
             $mysqlrestart .= 'service mysql restart';              $mysqlrestart .= 'service mysql restart';
             return ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart);              return ($distro,$gotprereqs,$localecmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart);
         } else {          } else {
             if ($mysqlsetup eq 'noroot') {              if ($mysqlsetup eq 'noroot') {
                 $recommended{'mysqlperms'} = 1;                  $recommended{'mysqlperms'} = 1;
Line 574  sub check_required { Line 577  sub check_required {
             }              }
         }          }
     }      }
       my ($sslhostsfilesref,$has_std,$has_int,$rewritenum,$nochgstd,$nochgint);
     ($recommended{'firewall'},$apachefw) = &chkfirewall($distro);      ($recommended{'firewall'},$apachefw) = &chkfirewall($distro);
     ($recommended{'runlevels'},$tostop,$uses_systemctl) = &chkconfig($distro,$instdir);      ($recommended{'runlevels'},$tostop,$uses_systemctl) = &chkconfig($distro,$instdir);
     if ((ref($uses_systemctl) eq 'HASH') && ($uses_systemctl->{'apache'})) {  
         $recommended{'systemd'} = &check_systemd_security($distro);  
     }  
     $recommended{'apache'} = &chkapache($distro,$instdir);      $recommended{'apache'} = &chkapache($distro,$instdir);
       ($recommended{'apachessl'},$sslhostsfilesref,$has_std,$has_int,$rewritenum,
        $nochgstd,$nochgint) = &chkapachessl($distro,$instdir,$hostname,$hostip);
     $recommended{'stopsrvcs'} = &chksrvcs($distro,$tostop);      $recommended{'stopsrvcs'} = &chksrvcs($distro,$tostop);
     ($recommended{'download'},$downloadstatus,$filetouse,$production,$testing)       ($recommended{'download'},$downloadstatus,$filetouse,$production,$testing) 
         = &need_download($distro,$instdir);          = &need_download();
     return ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,      return ($distro,$gotprereqs,$localecmd,$packagecmd,$updatecmd,$installnow,
             $mysqlrestart,\%recommended,$dbh,$has_pass,$mysql_unix_socket,              $mysqlrestart,\%recommended,$dbh,$has_pass,$mysql_unix_socket,
             $has_lcdb,$downloadstatus,$filetouse,$production,$testing,$apachefw,              $has_lcdb,$downloadstatus,$filetouse,$production,$testing,$apachefw,
             $uses_systemctl);              $uses_systemctl,$hostname,$hostip,$sslhostsfilesref,$has_std,$has_int,
               $rewritenum,$nochgstd,$nochgint);
 }  }
   
 sub check_mysql_running {  sub check_mysql_running {
Line 603  sub check_mysql_running { Line 607  sub check_mysql_running {
             $process = 'mysqld';              $process = 'mysqld';
             $proc_owner = 'mysql';              $proc_owner = 'mysql';
         }          }
         if ($1 >= 16) {  
             $use_systemctl = 1;  
         }  
     } elsif ($distro =~ /^debian(\w+)/) {  
         if ($1 >= 10) {  
             $process = 'mysql';  
             $proc_owner = 'mysql';  
         }  
         if ($1 >= 11) {  
             $mysqldaemon = 'mariadb';  
         }  
         if ($1 >= 9) {  
             $use_systemctl = 1;  
         }  
     } elsif ($distro =~ /^fedora(\d+)/) {      } elsif ($distro =~ /^fedora(\d+)/) {
         if ($1 >= 16) {          if ($1 >= 16) {
             $process = 'mysqld';              $process = 'mysqld';
Line 626  sub check_mysql_running { Line 616  sub check_mysql_running {
         if ($1 >= 19) {          if ($1 >= 19) {
             $mysqldaemon ='mariadb';              $mysqldaemon ='mariadb';
         }          }
         if ($1 >= 34) {      } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle)(\d+)/) {
             $process = 'mariadb';  
         }  
     } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {  
         if ($1 >= 7) {          if ($1 >= 7) {
             $mysqldaemon ='mariadb';              $mysqldaemon ='mariadb';
             $process = 'mysqld';              $process = 'mysqld';
             $proc_owner = 'mysql';              $proc_owner = 'mysql';
             $use_systemctl = 1;              $use_systemctl = 1;
         }          }
         if ($1 >= 9) {  
             $process = 'mariadb';  
         }  
     } elsif ($distro =~ /^sles(\d+)/) {      } elsif ($distro =~ /^sles(\d+)/) {
         if ($1 >= 12) {          if ($1 >= 12) {
             $use_systemctl = 1;              $use_systemctl = 1;
             $proc_owner = 'mysql';              $proc_owner = 'mysql';
             $process = 'mysqld';              $process = 'mysqld';
         }          }
         if ($1 >= 12) {          if ($1 >= 15) {
             $mysqldaemon ='mariadb';              $mysqldaemon ='mariadb';
         }          }
     } elsif ($distro =~ /^suse(\d+)/) {      } elsif ($distro =~ /^suse(\d+)/) {
Line 731  sub chkconfig { Line 715  sub chkconfig {
                     $uses_systemctl{'ntp'} = 1;                      $uses_systemctl{'ntp'} = 1;
                     $uses_systemctl{'cups'} = 1;                      $uses_systemctl{'cups'} = 1;
                     $uses_systemctl{'memcached'} = 1;                      $uses_systemctl{'memcached'} = 1;
                     if ($name eq 'sles') {                      if (($name eq 'sles') && ($num >= 15)) {
                         if ($num >= 12) {                          $daemon{'ntp'} = 'chronyd';
                             $daemon{'mysql'} = 'mariadb';                          $daemon{'mysql'} = 'mariadb';
                         }  
                         if ($num >= 15) {  
                             $daemon{'ntp'} = 'chronyd';  
                         } else {  
                             $daemon{'ntp'} = 'ntpd';  
                         }  
                     } else {                      } else {
                         $daemon{'ntp'} = 'ntpd';                          $daemon{'ntp'} = 'ntpd';
                     }                      }
Line 765  sub chkconfig { Line 743  sub chkconfig {
         if (($distro =~ /^ubuntu/) && ($version <= 8)) {          if (($distro =~ /^ubuntu/) && ($version <= 8)) {
             $daemon{'cups'} = 'cupsys';              $daemon{'cups'} = 'cupsys';
         }          }
         if ((($distro =~ /^ubuntu/) && ($version >= 18)) ||          if (($distro =~ /^ubuntu/) && ($version >= 18)) {
             (($distro  =~ /^debian/) && ($version >= 10))) {  
             $daemon{'ntp'}    = 'chrony';              $daemon{'ntp'}    = 'chrony';
         }          }
         if (($distro  =~ /^debian/) && ($version >= 10)) {  
             $daemon{'mysql'} = 'mariadb';  
         }  
     } elsif ($distro =~ /^fedora(\d+)/) {      } elsif ($distro =~ /^fedora(\d+)/) {
         my $version = $1;          my $version = $1;
         if ($version >= 15) {          if ($version >= 15) {
Line 789  sub chkconfig { Line 763  sub chkconfig {
         if ($version >= 26) {          if ($version >= 26) {
             $daemon{'ntp'} = 'chronyd';              $daemon{'ntp'} = 'chronyd';
         }          }
     } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {      } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle)(\d+)/) {
         my $version = $1;          my $version = $1;
         if ($version >= 7) {          if ($version >= 7) {
             $uses_systemctl{'ntp'} = 1;              $uses_systemctl{'ntp'} = 1;
Line 894  sub chkconfig { Line 868  sub chkconfig {
     return (\%needfix,\%tostop,\%uses_systemctl);      return (\%needfix,\%tostop,\%uses_systemctl);
 }  }
   
 sub check_systemd_security {  
     my ($distro) = @_;  
     my $service = 'httpd.service';  
     if ($distro =~ /^(suse|sles|ubuntu|debian)/) {  
         $service = 'apache2.service';  
     }  
     system("systemctl daemon-reload");  
     if (open(PIPE,"systemctl show $service --property=ProtectHome 2>/dev/null |")) {  
         my $protection = <PIPE>;  
         close(PIPE);  
         chomp($protection);  
         if ($protection =~ /^ProtectHome=(read-only|yes)$/i) {  
             return 1;  
         }  
     } else {  
          print &mt('Could not check systemctl configuration for Apache')."\n";  
     }  
     return 0;  
 }  
   
 sub uses_firewalld {  sub uses_firewalld {
     my ($distro) = @_;      my ($distro) = @_;
     my ($inuse,$checkfirewalld,$zone);      my ($inuse,$checkfirewalld,$zone);
Line 925  sub uses_firewalld { Line 879  sub uses_firewalld {
         if ($1 >= 18) {          if ($1 >= 18) {
             $checkfirewalld = 1;              $checkfirewalld = 1;
         }          }
     } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {      } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle)(\d+)/) {
         if ($1 >= 7) {          if ($1 >= 7) {
             $checkfirewalld = 1;              $checkfirewalld = 1;
         }          }
Line 1017  sub chkapache { Line 971  sub chkapache {
         my $distname = $1;          my $distname = $1;
         my $version = $2;          my $version = $2;
         my ($stdconf,$stdsite);          my ($stdconf,$stdsite);
         if ((($distname eq 'ubuntu') && ($version > 12)) ||          if (($distname eq 'ubuntu') && ($version > 12)) {
             (($distname eq 'debian') && ($version >= 10))) {  
             $stdconf = "$instdir/debian-ubuntu/ubuntu14/loncapa_conf";              $stdconf = "$instdir/debian-ubuntu/ubuntu14/loncapa_conf";
             $stdsite = "$instdir/debian-ubuntu/ubuntu14/loncapa_sites";              $stdsite = "$instdir/debian-ubuntu/ubuntu14/loncapa_sites";
         } else {          } else {
Line 1029  sub chkapache { Line 982  sub chkapache {
             print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n";               print &mt('Warning: No LON-CAPA Apache configuration file found for installation check.')."\n"; 
         } else {          } else {
             my ($configfile,$sitefile);              my ($configfile,$sitefile);
             if ((($distname eq 'ubuntu') && ($version > 12)) ||              if (($distname eq 'ubuntu') && ($version > 12)) {
                 (($distname eq 'debian') && ($version >= 10))) {  
                 $sitefile = '/etc/apache2/sites-available/loncapa.conf';                  $sitefile = '/etc/apache2/sites-available/loncapa.conf';
                 $configfile = '/etc/apache2/conf-available/loncapa.conf';                  $configfile = '/etc/apache2/conf-available/loncapa.conf';
             } else {              } else {
Line 1046  sub chkapache { Line 998  sub chkapache {
                     }                      }
                 }                  }
             }              }
             if ((!$fixapache) && ((($distname eq 'ubuntu') && ($version > 12)) ||              if ((!$fixapache) && ($distname eq 'ubuntu') && ($version > 12)) {
                                   (($distname eq 'debian') && ($version >= 10))))  {  
                 if (($sitefile ne '') && (-e $sitefile) && (-e $stdsite)) {                  if (($sitefile ne '') && (-e $sitefile) && (-e $stdsite)) {
                     if (open(PIPE, "diff --brief $stdsite $sitefile |")) {                      if (open(PIPE, "diff --brief $stdsite $sitefile |")) {
                         my $diffres = <PIPE>;                          my $diffres = <PIPE>;
                         close(PIPE);                          close(PIPE);
                         chomp($diffres);                          chomp($diffres);
                         if ($diffres) {                          unless ($diffres) {
                             $fixapache = 1;  
                         } else {  
                             $fixapache = 0;                              $fixapache = 0;
                         }                          }
                     }                      }
Line 1069  sub chkapache { Line 1018  sub chkapache {
                 }                  }
             }              }
         }          }
         if ((!$fixapache) && (($distname eq 'ubuntu') || ($distname eq 'debian'))) {          if ((!$fixapache) && ($distname eq 'ubuntu')) {
             my $sitestatus = "/etc/apache2/mods-available/status.conf";              my $sitestatus = "/etc/apache2/mods-available/status.conf";
             my $stdstatus = "$instdir/debian-ubuntu/status.conf";              my $stdstatus = "$instdir/debian-ubuntu/status.conf";
             if ((-e $stdstatus) && (-e $sitestatus)) {              if ((-e $stdstatus) && (-e $sitestatus)) {
Line 1123  sub chkapache { Line 1072  sub chkapache {
     } else {      } else {
         my $configfile = 'httpd.conf';          my $configfile = 'httpd.conf';
         my $mpmfile = 'mpm.conf';          my $mpmfile = 'mpm.conf';
         if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {          if ($distro =~ /^(?:centos|rhes|scientific|oracle)(\d+)$/) {
             if ($1 >= 7) {              if ($1 >= 7) {
                 $configfile = 'apache2.4/httpd.conf';                  $configfile = 'apache2.4/httpd.conf';
             } elsif ($1 > 5) {              } elsif ($1 > 5) {
Line 1167  sub chkapache { Line 1116  sub chkapache {
     return $fixapache;      return $fixapache;
 }  }
   
   #
   # chkapachessl() determines whether a server's Apache SSL configuration
   # needs updating to support LON-CAPA.
   #
   # LON-CAPA uses VirtualHosts for port 443, and requires that they are 
   # defined in one Apache configuration file containing two VirtualHost
   # blocks, in order:
   #
   # (1) a block with no ServerName, or with ServerName set to the
   #     server's hostname. This block should contain:
   #
   # <IfModule mod_rewrite.c>
   # LON-CAPA rewrite rules defined in sslrewrite.conf
   # </IfModule>
   #
   # (2) a block with ServerName set to internal-$hostname
   #     (where $hostname is server's hostname).
   #    This block should contain the config and rewrite rules
   #    found in loncapassl.conf.
   #
   # chkapachessl() retrieves the names of .conf files in
   # the directory appropriate for the particular Linux distro,
   # and then checks to see which .conf file is the best candidate as
   # the single file containing VirtualHosts definitions and 
   # <IfModule mod_rewrite.c> </IfModule> rewrite blocks.
   #
   # The best candidate is the one containing a block:
   # <VirtualHost ????? :443> 
   # (where ????? might be _default_ or * or an IP address)
   # <IfModule mod_rewrite.c>
   # </IfModule>
   # </VirtualHost>
   # with the fewest differences between the contents of the 
   # IfModule block and the expected contents (from sslrewrite.conf)
   #
   # If there are no files with rewrite blocks, then a candidate file 
   # is chosen from the .conf files containing VirtualHosts definitions.
   #
   # If the user includes "Configure SSL for Apache web server" as
   # one of the actions to take to prepare the server for LON-CAPA
   # installation, then the output from &chkapachessl() will be
   # used to determined which file will contain VirtualHost configs.  
   #
   # If there are no files containing VirtualHosts definitions, then
   # <VirtualHost *:443> </VirtualHost> blocks will be appended to
   # the standard Apache SSL config for the particular distro:
   # ssl.conf for RHEL/CentOS/Scientific/Fedora, vhost-ssl.conf
   # for SuSE/SLES, and default-ssl.conf for Ubuntu.
   #
   # Once a file is selected, the contents of sslrewrite.conf and 
   # loncapassl.conf are compared with appropriate blocks in the file
   # and the user will be prompted to agree to insertion of missing
   # lines and/or deletion of surplus lines.
   #
   
   sub chkapachessl {
       my ($distro,$instdir,$hostname,$hostip) = @_;
       my $fixapachessl = 1;
       my $sslintconf = "$instdir/loncapassl.conf";
       my $sslrewriteconf = "$instdir/sslrewrite.conf";
       my (%sslfiles,%rewrites,%vhostonly,$has_std,$has_int,$rewritenum,$nochgint,$nochgstd);
       $nochgstd = 0;
       $nochgint = 0; 
       if (!-e $sslintconf) {
           $fixapachessl = 0;
           print &mt('Warning: LON-CAPA SSL Apache configuration file [_1] needed for installation check.',$sslintconf)."\n";
       } elsif (!-e $sslrewriteconf) {
           $fixapachessl = 0;
           print &mt('Warning: LON-CAPA SSL Apache configuration file [_1] needed for installation check is missing.',$sslrewriteconf)."\n";
       } else {
           my $ssldir;
           if ($distro =~ /^(debian|ubuntu)(\d+)$/) {
               $ssldir = '/etc/apache2/sites-available';
           } elsif ($distro =~ /(suse|sles)/) {
               $ssldir = '/etc/apache2/vhosts.d';
           } else {
               $ssldir = '/etc/httpd/conf.d';
           }
           my @rewritessl = ();
           if (open(my $fh,'<',$sslrewriteconf)) {
               my $skipnext = 0;
               while (<$fh>) {
                   chomp();
                   s/(^\s+|\s+$)//g;
                   next if ($_ eq '');
                   next if ($_ eq '<IfModule mod_rewrite.c>');
                   next if ($_ eq '</IfModule>');
                   if ($_ eq 'RewriteCond %{REMOTE_ADDR} {[[[[HostIP]]]]}') {
                       if (($hostip ne '') && ($hostip ne '127.0.0.1')) {
                           push(@rewritessl,'RewriteCond %{REMOTE_ADDR} '.$hostip);
                           next;
                       } else {
                           $skipnext = 1;
                       }
                   } elsif (($_ eq 'RewriteRule (.*) - [L]') && ($skipnext)) {
                       $skipnext = 0;
                       next;
                   }
                   push(@rewritessl,$_);
               }
           }
           my @intssl = ();
           if (open(my $fh,'<',$sslintconf)) {
               while(<$fh>) {
                   chomp();
                   s/(^\s+|\s+$)//g;
                   next if ($_ eq '');
                   if ($_ eq 'ServerName internal-{[[[[Hostname]]]]}') {
                       if ($hostname ne '') {
                           push(@intssl,'ServerName internal-'.$hostname);
                           next;
                       }
                   }
                   next if ($_ eq '<VirtualHost *:443>');
                   next if ($_ eq '</VirtualHost>');
                   push(@intssl,$_);
               }
           }
           if (-d $ssldir) {
               my @actualint = ();
               if (opendir(my $dir,$ssldir)) {
                   my @sslconf_files;
                   foreach my $file (grep(!/^\.+/,readdir($dir))) {
                       next if (($distro =~ /(suse|sles)/) && ($file =~ /\.template$/));
                       next if ($file =~ /\.rpmnew$/);
                       if (open(my $fh,'<',"$ssldir/$file")) {
                           while (<$fh>) {
                               if (/^\s*<VirtualHost\s+[^:]*\:443>\s*$/) {
                                   push(@sslconf_files,$file);
                                   last;
                               }
                           }
                           close($fh);
                       }
                   }
                   closedir($dir);
                   if (@sslconf_files) {
                       foreach my $file (@sslconf_files) {
                           if (open(my $fh,'<',"$ssldir/$file")) {
                               my ($virtualhost,$rewrite,$num) = (0,0,0);
                               my ($currname,$has_rewrite);
                               while (<$fh>) {
                                   chomp();
                                   next if (/^\s*$/);
                                   if ($virtualhost) {
                                       if (/^\s*<\/VirtualHost>/) {
                                           if ($currname !~ /^\Qinternal-$hostname\E/) {
                                               if ($has_rewrite) {
                                                   delete($vhostonly{$file});
                                               } else {
                                                   $vhostonly{$file} = 1;
                                               }
                                           }
                                           $sslfiles{$currname}{$file} = 1;
                                           $virtualhost = 0;
                                           $currname = '';
                                           $has_rewrite = '';
                                           next;
                                       } elsif (/^\s*ServerName\s+([^\s]+)\s*$/) {
                                           $currname = $1;
                                       }
                                       if ($currname =~ /^\Qinternal-$hostname\E/) {
                                           s/(^\s+|\s+$)//g;
                                           push(@actualint,$_);
                                           $has_int = $file;
                                       } else {
                                           if ($rewrite) {
                                               if (/^\s*<\/IfModule>/) {
                                                   $rewrite = 0;
                                                   $num ++;
                                               } else {
                                                   s/(^\s+|\s+$)//g;
                                                   push(@{$rewrites{$file}[$num]},$_);
                                               }
                                           } elsif (/^\s*<IfModule\s+mod_rewrite\.c>/) {
                                               $rewrite = 1;
                                               $has_rewrite = 1;
                                               if ($currname eq '') {
                                                   $currname = $hostname;
                                               }
                                               $rewrites{$file}[$num] = [];
                                           }
                                       }
                                   } elsif (/^\s*<VirtualHost\s+[^:]*\:443>\s*$/) {
                                       $virtualhost = 1;
                                   }
                               }
                               close($fh);
                           }
                       }
                   }
                   if (keys(%rewrites)) {
                       my $mindiffsall;
                       foreach my $file (sort(keys(%rewrites))) {
                           if (ref($rewrites{$file}) eq 'ARRAY') {
                               my $mindiffs;
                               for (my $i=0; $i<@{$rewrites{$file}}; $i++) {
                                   if (ref($rewrites{$file}[$i]) eq 'ARRAY') {
                                       my @diffs = &compare_arrays($rewrites{$file}[$i],\@rewritessl);
                                       if (@diffs == 0) {
                                           $fixapachessl = 0;
                                           $mindiffs = 0;
                                           $rewritenum = 1+$i;
                                           last;
                                       } else {
                                           if ($mindiffs eq '') {
                                               $mindiffs = scalar(@diffs);
                                               $rewritenum = 1+$i; 
                                           } elsif (scalar(@diffs) <= $mindiffs) {
                                               $mindiffs = scalar(@diffs);
                                               $rewritenum = 1+$i;
                                           }
                                       }
                                   }
                               }
                               if ($mindiffsall eq '') {
                                   $mindiffsall = $mindiffs;
                                   $has_std = $file;
                               } elsif ($mindiffs <= $mindiffsall) {
                                   $mindiffsall = $mindiffs;
                                   $has_std = $file;
                               }
                               if ($mindiffsall == 0) {
                                   $nochgstd = 1;
                               }
                           }
                       }
                   } elsif (keys(%vhostonly) > 0) {
                       if (($has_int ne '') && (exists($vhostonly{$has_int}))) {
                           $has_std = $has_int;
                       }
                   }
                   if (@actualint) {
                       my @diffs = &compare_arrays(\@actualint,\@intssl);
                       if (@diffs) {
                           $fixapachessl = 1;
                       } else {
                           $nochgint = 1;
                       }
                   } else {
                       $fixapachessl = 1;
                   }
               }
           }
           unless ($fixapachessl) {
               if ($distro =~ /^(debian|ubuntu)(\d+)$/) {
                   my $enabled_dir = '/etc/apache2/sites-enabled';
                   if (keys(%sslfiles)) {
                       foreach my $key (sort(keys(%sslfiles))) {
                           if (ref($sslfiles{$key}) eq 'HASH') {
                               foreach my $file (sort(keys(%{$sslfiles{$key}}))) {
                                   unless ((-l "$enabled_dir/$file") &&
                                           (readlink("$enabled_dir/$file") eq "$ssldir/$file")) {
                                       print_and_log(&mt("Warning, use: 'sudo a2ensite $file' to activate LON-CAPA SSL Apache config\n"));
                                   }
                               }
                           }
                       }
                   }
               }
           }
       }
       return ($fixapachessl,\%sslfiles,$has_std,$has_int,$rewritenum,$nochgstd,$nochgint);
   }
   
   #
   # compare_arrays() expects two refs to arrays as args.
   #
   # The contents of the two arrays are compared, and if they
   # are different, and array of the differences is returned.
   #
   
   sub compare_arrays {
       my ($arrayref1,$arrayref2) = @_;
       my (@difference,%count);
       @difference = ();
       %count = ();
       if ((ref($arrayref1) eq 'ARRAY') && (ref($arrayref2) eq 'ARRAY')) {
           foreach my $element (@{$arrayref1}, @{$arrayref2}) { $count{$element}++; }
           foreach my $element (keys(%count)) {
               if ($count{$element} == 1) {
                   push(@difference,$element);
               }
           }
       }
       return @difference;
   }
   
 sub chksrvcs {  sub chksrvcs {
     my ($distro,$tostop) = @_;      my ($distro,$tostop) = @_;
     my %stopsrvcs;      my %stopsrvcs;
Line 1203  sub chksrvcs { Line 1440  sub chksrvcs {
 }  }
   
 sub need_download {  sub need_download {
     my ($distro,$instdir) = @_;  
     my $needs_download = 1;      my $needs_download = 1;
     my ($production,$testing,$stdsizes) = &download_versionslist();      my ($production,$testing,$stdsizes) = &download_versionslist();
     my ($localcurrent,$localtesting,%tarball,%localsize,%bymodtime,      my ($rootdir,$localcurrent,$localtesting,%tarball,%localsize,%bymodtime,
         %bysize,$filetouse,$downloadstatus);          %bysize,$filetouse,$downloadstatus);
     if (opendir(my $dir,$instdir)) {      $rootdir = '/root';
       if (opendir(my $dir,"$rootdir")) {
         my (@lcdownloads,$version);          my (@lcdownloads,$version);
         foreach my $file (readdir($dir)) {          foreach my $file (readdir($dir)) {
             if ($file =~ /^loncapa\-([\w\-.]+)\.tar\.gz$/) {              if ($file =~ /^loncapa\-([\w\-.]+)\.tar\.gz$/) {
Line 1218  sub need_download { Line 1455  sub need_download {
             }              }
             if (ref($stdsizes) eq 'HASH') {              if (ref($stdsizes) eq 'HASH') {
                 if ($version eq 'current') {                  if ($version eq 'current') {
                     my @stats = stat("$instdir/$file");                      my @stats = stat("$rootdir/$file");
                     $localcurrent = $stats[7];                      $localcurrent = $stats[7];
                     if ($localcurrent == $stdsizes->{$production}) {                      if ($localcurrent == $stdsizes->{$production}) {
                         $needs_download = 0;                          $needs_download = 0;
                         $filetouse = $file;                          $filetouse = $file;
                     }                      }
                 } elsif ($version eq 'testing') {                  } elsif ($version eq 'testing') {
                     my @stats = stat("$instdir/$file");                      my @stats = stat("$rootdir/$file");
                     $localtesting = $stats[7];                      $localtesting = $stats[7];
                     if ($localtesting == $stdsizes->{$testing}) {                      if ($localtesting == $stdsizes->{$testing}) {
                         $needs_download = 0;                          $needs_download = 0;
Line 1239  sub need_download { Line 1476  sub need_download {
         if ($needs_download) {          if ($needs_download) {
             if (@lcdownloads > 0) {              if (@lcdownloads > 0) {
                 foreach my $version (@lcdownloads) {                  foreach my $version (@lcdownloads) {
                     my @stats = stat("$instdir/$tarball{$version}");                      my @stats = stat("$rootdir/$tarball{$version}");
                     my $mtime = $stats[9];                      my $mtime = $stats[9];
                     $localsize{$version} = $stats[7];                      $localsize{$version} = $stats[7];
                     if ($mtime) {                      if ($mtime) {
Line 1272  sub need_download { Line 1509  sub need_download {
                     my $newest = $sorted[0];                      my $newest = $sorted[0];
                     if (ref($bymodtime{$newest}) eq 'ARRAY') {                      if (ref($bymodtime{$newest}) eq 'ARRAY') {
                         $downloadstatus =                           $downloadstatus = 
                               "Latest LON-CAPA source download in $instdir is: ".                                "Latest LON-CAPA source download in $rootdir is: ".
                               join(',',@{$bymodtime{$newest}})." (downloaded ".                                join(',',@{$bymodtime{$newest}})." (downloaded ".
                               localtime($newest).")\n";                                localtime($newest).")\n";
                     }                      }
                 } else {                  } else {
                     $downloadstatus =                       $downloadstatus = 
                         "The $instdir directory already contains the latest LON-CAPA version:".                          "The $rootdir directory already contains the latest LON-CAPA version:".
                         "\n".$filetouse."\n"."which can be used for installation.\n";                          "\n".$filetouse."\n"."which can be used for installation.\n";
                 }                  }
             } else {              } else {
                 $downloadstatus = "The $instdir directory does not appear to contain any downloaded LON-CAPA source code files which can be used for installation.\n";                  $downloadstatus = "The $rootdir directory does not appear to contain any downloaded LON-CAPA source code files which can be used for installation.\n";
             }              }
         }          }
     } else {      } else {
         $downloadstatus = "Could not open $instdir directory to look for existing downloads of LON-CAPA source code.\n";          $downloadstatus = "Could not open $rootdir directory to look for existing downloads of LON-CAPA source code.\n";
     }      }
     return ($needs_download,$downloadstatus,$filetouse,$production,$testing);      return ($needs_download,$downloadstatus,$filetouse,$production,$testing);
 }  }
Line 1295  sub check_mysql_setup { Line 1532  sub check_mysql_setup {
     my ($instdir,$dsn,$distro) = @_;      my ($instdir,$dsn,$distro) = @_;
     my ($mysqlsetup,$has_pass,$mysql_unix_socket,$mysql_has_wwwuser);      my ($mysqlsetup,$has_pass,$mysql_unix_socket,$mysql_has_wwwuser);
     my $dbh = DBI->connect($dsn,'root','',{'PrintError'=>0});      my $dbh = DBI->connect($dsn,'root','',{'PrintError'=>0});
     my ($mysqlversion,$mysqlminorversion,$mysqlsubver,$mysqlname) = &get_mysql_version();      my ($mysqlversion,$mysqlsubver,$mysqlname) = &get_mysql_version();
     if (($mysqlname =~ /^MariaDB/i) && (($mysqlversion == 10 && $mysqlminorversion >= 4) || ($mysqlversion >= 11))) {      if (($mysqlname =~ /^MariaDB/i) && ($mysqlversion >= 10.4)) {
         if ($dbh) {          if ($dbh) {
             my $sth = $dbh->prepare("SELECT Priv FROM mysql.global_priv WHERE (User = 'root' AND Host ='localhost')");              my $sth = $dbh->prepare("SELECT Priv FROM mysql.global_priv WHERE (User = 'root' AND Host ='localhost')");
             $sth->execute();              $sth->execute();
Line 1317  sub check_mysql_setup { Line 1554  sub check_mysql_setup {
     }      }
     if ($dbh) {      if ($dbh) {
         $mysqlsetup = 'noroot';          $mysqlsetup = 'noroot';
         if (($mysqlname !~ /^MariaDB/i) && (($mysqlversion == 5 && $mysqlminorversion >= 7) || ($mysqlversion >= 6))) {          if (($mysqlname !~ /^MariaDB/i) && ($mysqlversion >= 5.7)) {
             my $sth = $dbh->prepare("SELECT plugin from mysql.user where User='root'");              my $sth = $dbh->prepare("SELECT plugin from mysql.user where User='root'");
             $sth->execute();              $sth->execute();
             while (my $priv = $sth->fetchrow_array) {              while (my $priv = $sth->fetchrow_array) {
Line 1442  sub get_pathto_iptables { Line 1679  sub get_pathto_iptables {
   
 sub firewall_is_active {  sub firewall_is_active {
     if (-e '/proc/net/ip_tables_names') {      if (-e '/proc/net/ip_tables_names') {
         my $status;  
         if (open(PIPE,'cat /proc/net/ip_tables_names |grep filter |')) {          if (open(PIPE,'cat /proc/net/ip_tables_names |grep filter |')) {
             $status = <PIPE>;              my $status = <PIPE>;
             close(PIPE);              close(PIPE);
             chomp($status);              chomp($status);
             if ($status eq 'filter') {              if ($status eq 'filter') {
                 return 1;                  return 1;
             }              }
         }          }
         unless ($status) {  
             if (open(PIPE,'nft list tables |')) {  
                 while(<PIPE>) {  
                     chomp();  
                     if (/filter$/) {  
                         $status = 1;  
                         last;  
                     }  
                 }  
                 close(PIPE);  
                 if ($status) {  
                     return 1;  
                 }  
             }  
         }  
     }      }
     return 0;      return 0;
 }  }
Line 1627  print " Line 1848  print "
 ".&mt('3.')." ".&mt('Set-up the MySQL database.')."  ".&mt('3.')." ".&mt('Set-up the MySQL database.')."
 ".&mt('4.')." ".&mt('Set-up MySQL permissions.')."  ".&mt('4.')." ".&mt('Set-up MySQL permissions.')."
 ".&mt('5.')." ".&mt('Configure Apache web server.')."  ".&mt('5.')." ".&mt('Configure Apache web server.')."
 ".&mt('6.')." ".&mt('Configure systemd security settings for Apache web server.')."  ".&mt('6.')." ".&mt('Configure SSL for Apache web server.')."
 ".&mt('7.')." ".&mt('Configure start-up of services.')."  ".&mt('7.')." ".&mt('Configure start-up of services.')."
 ".&mt('8.')." ".&mt('Check firewall settings.')."  ".&mt('8.')." ".&mt('Check firewall settings.')."
 ".&mt('9.')." ".&mt('Stop services not used by LON-CAPA,')."  ".&mt('9.')." ".&mt('Stop services not used by LON-CAPA,')."
Line 1661  my $instdir = `pwd`; Line 1882  my $instdir = `pwd`;
 chomp($instdir);  chomp($instdir);
   
 my %callsub;  my %callsub;
 my @actions = ('wwwuser','pwauth','mysql','mysqlperms','apache','systemd',  my @actions = ('wwwuser','pwauth','mysql','mysqlperms','apache',
                'runlevels','firewall','stopsrvcs','download');                 'apachessl','runlevels','firewall','stopsrvcs','download');
 my %prompts = &texthash(   my %prompts = &texthash( 
     wwwuser    => "Create the 'www' user?",      wwwuser    => "Create the 'www' user?",
     pwauth     => 'Install the package LON-CAPA uses to authenticate users?',      pwauth     => 'Install the package LON-CAPA uses to authenticate users?',
     mysql      => 'Set-up the MySQL database?',      mysql      => 'Set-up the MySQL database?',
     mysqlperms => 'Set-up MySQL permissions?',      mysqlperms => 'Set-up MySQL permissions?',
     apache     => 'Configure Apache web server?',      apache     => 'Configure Apache web server?',
     systemd    => 'Configure systemd security settings for Apache web server?',      apachessl  => 'Configure SSL for Apache web server?', 
     runlevels  => 'Set overrides for start-up order of services?',      runlevels  => 'Set overrides for start-up order of services?',
     firewall   => 'Configure firewall settings for Apache',      firewall   => 'Configure firewall settings for Apache',
     stopsrvcs  => 'Stop extra services not required on a LON-CAPA server?',      stopsrvcs  => 'Stop extra services not required on a LON-CAPA server?',
     download   => 'Download LON-CAPA source code in readiness for installation?',      download   => 'Download LON-CAPA source code in readiness for installation?',
 );  );
   
 print "\n".&mt('Checking system status ...')."\n";  print "\n".&mt('Checking system status ...')."\n\n";
   
 my $dsn = "DBI:mysql:database=mysql";  my $dsn = "DBI:mysql:database=mysql";
 my ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart,  my ($distro,$gotprereqs,$localecmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart,
     $recommended,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,$downloadstatus,      $recommended,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,$downloadstatus,
     $filetouse,$production,$testing,$apachefw,$uses_systemctl) = &check_required($instdir,$dsn);      $filetouse,$production,$testing,$apachefw,$uses_systemctl,$hostname,$hostip,
       $sslhostsfiles,$has_std,$has_int,$rewritenum,$nochgstd,$nochgint) =
       &check_required($instdir,$dsn);
 if ($distro eq '') {  if ($distro eq '') {
     print "\n".&mt('Linux distribution could not be verified as a supported distribution.')."\n".      print "\n".&mt('Linux distribution could not be verified as a supported distribution.')."\n".
           &mt('The following are supported: [_1].',            &mt('The following are supported: [_1].',
Line 1698  if ($mysqlrestart) { Line 1921  if ($mysqlrestart) {
     exit;      exit;
 }  }
 if ($localecmd ne '') {  if ($localecmd ne '') {
     print "\n".&mt('Although the LON-CAPA application itself is localized for a number of different languages,[_1]the default locale language for the Linux OS on which it runs should be US English.',"\n")."\n\n";      print "\n".&mt('Although the LON-CAPA application itself is localized for a number of different languages, the default locale language for the Linux OS on which it runs should be US English.')."\n";
     if ($langcmd ne '') {      print "\n".&mt('Run the following command from the command line to set the default language for your OS, and then run this LON-CAPA installation set-up script again.')."\n\n".
         print &mt('Use the following command(s) or action(s) to install a required language package.')."\n\n".  
               "$langcmd\n";  
     }  
     print &mt('Run the following command from the command line to set the default language for your OS,[_1]and then run this LON-CAPA installation set-up script again.',"\n")."\n\n".  
     $localecmd."\n\n".      $localecmd."\n\n".
     &mt('Stopping execution.')."\n";      &mt('Stopping execution.')."\n";
     exit;      exit;
Line 1713  if (!$gotprereqs) { Line 1932  if (!$gotprereqs) {
           &mt('The following command can be used to install the package (and dependencies):')."\n\n".            &mt('The following command can be used to install the package (and dependencies):')."\n\n".
           $updatecmd."\n\n";            $updatecmd."\n\n";
     if ($installnow eq '') {      if ($installnow eq '') {
         print &mt('Stopping execution.')."\n";  
         exit;          exit;
     } else {      } else {
         print &mt('Run command? ~[Y/n~]');          print &mt('Run command? ~[Y/n~]');
Line 1727  if (!$gotprereqs) { Line 1945  if (!$gotprereqs) {
                           &mt('Stopping execution.')."\n";                            &mt('Stopping execution.')."\n";
                     exit;                      exit;
                 } else {                  } else {
                     ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,                      ($distro,$gotprereqs,$localecmd,$packagecmd,$updatecmd,$installnow,
                      $mysqlrestart,$recommended,$dbh,$has_pass,$mysql_unix_socket,                       $mysqlrestart,$recommended,$dbh,$has_pass,$mysql_unix_socket,
                      $has_lcdb,$downloadstatus,$filetouse,$production,$testing,$apachefw,                       $has_lcdb,$downloadstatus,$filetouse,$production,$testing,$apachefw,
                      $uses_systemctl) = &check_required($instdir,$dsn);                       $uses_systemctl,$hostname,$hostip,$sslhostsfiles,$has_std,$has_int,
                        $rewritenum,$nochgstd,$nochgint) = &check_required($instdir,$dsn);
                 }                  }
             } else {              } else {
                 print &mt('Failed to run command to install LONCAPA-prerequisites')."\n";                  print &mt('Failed to run command to install LONCAPA-prerequisites')."\n";
Line 1784  my $lctarball = 'loncapa-current.tar.gz' Line 2003  my $lctarball = 'loncapa-current.tar.gz'
 my $sourcetarball = $lctarball;  my $sourcetarball = $lctarball;
 if ($callsub{'download'}) {  if ($callsub{'download'}) {
     my ($production,$testing,$sizes) = &download_versionslist();      my ($production,$testing,$sizes) = &download_versionslist();
     my $homedir = '/root';  
     if ($distro =~ /^ubuntu/) {  
         if ($instdir ne $homedir) {  
             ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});  
         }  
     }  
     if ($production && $testing) {      if ($production && $testing) {
         if ($production ne $testing) {          if ($production ne $testing) {
             print &mt('Two recent LON-CAPA releases are available: ')."\n".              print &mt('Two recent LON-CAPA releases are available: ')."\n".
                   &mt('1.').' '.&mt('A production release - version: [_1].',$production)."\n".                    &mt('1.').' '.&mt('A production release - version: [_1].',$production)."\n".
                   &mt('2.').' '.&mt('A testing release - version: [_1].',$testing)."\n\n".                    &mt('2.').' '.&mt('A testing release - version: [_1].',$testing)."\n\n".
                   &mt("After download, the tar.gz file will be extracted into $homedir")."\n\n".                    &mt('Download the production release? ~[Y/n~]');
                   &mt("Download the production release into $instdir? ~[Y/n~]");  
             if (&get_user_selection(1)) {              if (&get_user_selection(1)) {
                 $sourcetarball = 'loncapa-'.$production.'.tar.gz';                  $sourcetarball = 'loncapa-'.$production.'.tar.gz';
                 print "$sourcetarball will be downloaded into $instdir\n";  
             } else {              } else {
                 print "\n".&mt('Download the testing release? ~[Y/n~]');                  print "\n".&mt('Download the testing release? ~[Y/n~]');
                 if (&get_user_selection(1)) {                  if (&get_user_selection(1)) {
                     $sourcetarball = 'loncapa-'.$testing.'.tar.gz';                      $sourcetarball = 'loncapa-'.$testing.'.tar.gz';
                     print "$sourcetarball will be downloaded into $instdir\n";  
                 } else {  
                     $callsub{'download'} = 0;  
                 }                  }
             }              }
         }          }
     } elsif ($production) {      } elsif ($production) {
         print &mt('The most recent LON-CAPA release is version: [_1].',$production)."\n".          print &mt('The most recent LON-CAPA release is version: [_1].',$production)."\n".
               &mt("After download, the tar.gz file will be extracted into $homedir")."\n\n".                &mt('Download the production release? ~[Y/n~]');
               &mt("Download the production release into $instdir? ~[Y/n~]");  
         if (&get_user_selection(1)) {          if (&get_user_selection(1)) {
             $sourcetarball = 'loncapa-'.$production.'.tar.gz';              $sourcetarball = 'loncapa-'.$production.'.tar.gz';
             print "$sourcetarball will be downloaded into $instdir\n";  
         } else {  
             $callsub{'download'} = 0;  
         }          }
     }      }
 } elsif ($filetouse ne '') {  } elsif ($filetouse ne '') {
Line 1869  if ($dbh) { Line 2073  if ($dbh) {
   
 if ($callsub{'apache'}) {  if ($callsub{'apache'}) {
     if ($distro =~ /^(suse|sles)/) {      if ($distro =~ /^(suse|sles)/) {
         &copy_apache2_suseconf($instdir,$distro);          &copy_apache2_suseconf($instdir,$hostname,$distro);
     } elsif ($distro =~ /^(debian|ubuntu)/) {      } elsif ($distro =~ /^(debian|ubuntu)/) {
         &copy_apache2_debconf($instdir,$distro);          &copy_apache2_debconf($instdir,$distro,$hostname);
     } else {      } else {
         &copy_httpd_conf($instdir,$distro);          &copy_httpd_conf($instdir,$distro,$hostname);
         &copy_mpm_conf($instdir,$distro);          &copy_mpm_conf($instdir,$distro);
     }      }
 } else {  } else {
     print_and_log(&mt('Skipping configuration of Apache web server.')."\n");      print_and_log(&mt('Skipping configuration of Apache web server.')."\n");
 }  }
   
 if ($callsub{'systemd'}) {  if ($callsub{'apachessl'}) {
     &check_systemd_update($distro);      my $targetdir = '/etc/httpd/conf.d';
       if ($distro =~ /^(suse|sles)/) {
           $targetdir = '/etc/apache2/vhosts.d';
       } elsif ($distro =~ /^(debian|ubuntu)/) {
           $targetdir = '/etc/apache2/sites-available';
       }
       my ($new_rewrite,$new_int) = 
           &copy_apache_sslconf_files($distro,$hostname,$hostip,$instdir,$targetdir,$sslhostsfiles,
                                      $has_std,$has_int,$rewritenum,$nochgstd,$nochgint); 
       if ($distro =~ /^(debian|ubuntu)/) {
           my $apache2_sites_enabled_dir = '/etc/apache2/sites-enabled';
           if (-d $apache2_sites_enabled_dir) {  
               if ($has_std ne '') {
                   unless ((-l "$apache2_sites_enabled_dir/$has_std") && (readlink(("$apache2_sites_enabled_dir/$has_std") eq "$targetdir/$has_std"))) {
                       my $made_symlink =  eval { symlink("$targetdir/$has_std","$apache2_sites_enabled_dir/$has_std"); 1};
                       if ($made_symlink) {
                           print_and_log(&mt('Enabling "[_1]" Apache SSL configuration.',$has_std)."\n");
                       }
                   }
               }
               if (($has_int ne '') && ($has_int ne $has_std)) {
                   unless ((-l "$apache2_sites_enabled_dir/$has_int") && (readlink("$apache2_sites_enabled_dir/$has_int") eq "$targetdir/$has_int")) {
                       my $made_symlink =  eval { symlink("$targetdir/$has_int","$apache2_sites_enabled_dir/$has_int"); 1 };
                       if ($made_symlink) {
                           print_and_log(&mt('Enabling "[_1]" Apache SSL configuration.',$has_int)."\n");
                       }
                   }
               }
           }
       }
       print_and_log("\n");
 } else {  } else {
     print_and_log('Skipping systemd configuration update for web server');      print_and_log(&mt('Skipping configuration of SSL for Apache web server.')."\n");
 }  }
   
 if ($callsub{'runlevels'}) {  if ($callsub{'runlevels'}) {
Line 1936  if ($callsub{'firewall'}) { Line 2170  if ($callsub{'firewall'}) {
         if (keys(%added) > 0) {          if (keys(%added) > 0) {
             print &mt('Firewall configured to allow access for: [_1].',              print &mt('Firewall configured to allow access for: [_1].',
                       join(', ',sort(keys(%added))))."\n";                        join(', ',sort(keys(%added))))."\n";
             system('firewall-cmd --reload');              system('firewall-cmd --reload'); 
         }          }
         if ($current{'http'} || $current{'https'}) {          if ($current{'http'} || $current{'https'}) {
             print &mt('Firewall already configured to allow access for:[_1].',              print &mt('Firewall already configured to allow access for:[_1].',
Line 1973  if ($callsub{'firewall'}) { Line 2207  if ($callsub{'firewall'}) {
                   'ssh, http')."\n";                    'ssh, http')."\n";
     } else {      } else {
         my $version;          my $version;
         if ($distro =~ /^(redhat|centos|rocky|alma)(\d+)/) {          if ($distro =~ /^(redhat|centos)(\d+)$/) {
             $version = $1;              $version = $1;
         }          }
         if ($version > 5) {          if ($version > 5) {
Line 2004  if ($callsub{'download'}) { Line 2238  if ($callsub{'download'}) {
     print &mt('LON-CAPA is available for download from: [_1]',      print &mt('LON-CAPA is available for download from: [_1]',
               'http://install.loncapa.org/')."\n";                'http://install.loncapa.org/')."\n";
     if (!-e '/etc/loncapa-release') {      if (!-e '/etc/loncapa-release') {
         &print_and_log(&mt('LON-CAPA is not yet installed on your system.')."\n\n");          &print_and_log(&mt('LON-CAPA is not yet installed on your system.'). 
         unless ($filetouse) {                         "\n\n". 
             &print_and_log(&mt('You may retrieve the source for LON-CAPA by executing:')."\n".                         &mt('You may retrieve the source for LON-CAPA by executing:')."\n".
                            "wget http://install.loncapa.org/versions/$lctarball\n");                         "wget http://install.loncapa.org/versions/$lctarball\n");
         }  
     } else {      } else {
         my $currentversion;          my $currentversion;
         if (open(my $fh,"</etc/loncapa-release")) {          if (open(my $fh,"</etc/loncapa-release")) {
Line 2037  if ($callsub{'download'}) { Line 2270  if ($callsub{'download'}) {
 print "\n".&mt('Requested configuration complete.')."\n\n";  print "\n".&mt('Requested configuration complete.')."\n\n";
 if ($have_tarball && !$updateshown) {  if ($have_tarball && !$updateshown) {
     my ($lcdir) = ($sourcetarball =~ /^([\w.\-]+)\.tar.gz$/);      my ($lcdir) = ($sourcetarball =~ /^([\w.\-]+)\.tar.gz$/);
     if ($lcdir eq 'loncapa-current') {  
         $lcdir = "loncapa-X.Y.Z (X.Y.Z should correspond to a version number like '2.11.3')";  
     }  
     my ($apachename,$lc_uses_systemctl,$uses_sudo);      my ($apachename,$lc_uses_systemctl,$uses_sudo);
     if ($distro =~ /^(suse|sles|debian|ubuntu)([\d.]+)/) {      if ($distro =~ /^(suse|sles|debian|ubuntu)([\d.]+)/) {
         if (($1 eq 'suse') && ($2 < 10)) {          if (($1 eq 'suse') && ($2 < 10)) {
Line 2054  if ($have_tarball && !$updateshown) { Line 2284  if ($have_tarball && !$updateshown) {
         if ($1 > 6) {          if ($1 > 6) {
             $lc_uses_systemctl = 1;              $lc_uses_systemctl = 1;
         }          }
     } elsif ($distro =~ /^(?:rhes|centos|rocky|alma)(\d+)/) {      } elsif ($distro =~ /^(?:rhes|centos)(\d+)$/) {
         if ($1 > 7) {          if ($1 > 7) {
             $lc_uses_systemctl = 1;              $lc_uses_systemctl = 1;
         }          }
Line 2063  if ($have_tarball && !$updateshown) { Line 2293  if ($have_tarball && !$updateshown) {
             $lc_uses_systemctl = 1;              $lc_uses_systemctl = 1;
         }          }
         $uses_sudo = 1;          $uses_sudo = 1;
     } elsif ($distro =~ /^debian(\d+)$/) {  
         if ($1 >= 10) {  
             $lc_uses_systemctl = 1;  
         }  
     } elsif ($distro =~ /^sles(\d+)$/) {      } elsif ($distro =~ /^sles(\d+)$/) {
         if ($1 > 12) {          if ($1 > 12) {
             $lc_uses_systemctl = 1;              $lc_uses_systemctl = 1;
         }          }
     } elsif ($distro =~ /^fedora(\d+)$/) {  
         if ($1 > 25) {  
             $lc_uses_systemctl = 1;  
         }  
     }      }
     if (!-e '/etc/loncapa-release') {      if (!-e '/etc/loncapa-release') {
         print &mt('If you are now ready to install LON-CAPA, enter the following commands:')."\n\n";          print &mt('If you are now ready to install LON-CAPA, enter the following commands:')."\n\n";
Line 2092  if ($have_tarball && !$updateshown) { Line 2314  if ($have_tarball && !$updateshown) {
             $apachestop = 'sudo '.$apachestop;              $apachestop = 'sudo '.$apachestop;
         }          }
         print &mt('If you are now ready to update LON-CAPA, enter the following commands:').          print &mt('If you are now ready to update LON-CAPA, enter the following commands:').
               "\n\n$lcstop\n$apachestop\n";                "\n\n$lcstop\n$apachestop\n";   
     }      }
     my ($extract,$update);      print "cd /root\n".
     my $homedir = '/root';            "tar zxf $sourcetarball\n".
     if ($uses_sudo) {            "cd $lcdir\n".
         $extract = 'sudo ';            "./UPDATE\n";
         $update = 'sudo ';  
         if ($instdir ne $homedir) {  
             ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});  
         }  
     }  
     $extract .= "tar zxf $sourcetarball --directory $homedir";  
     $update .= './UPDATE';  
     print "$extract\n".  
           "cd $homedir/$lcdir\n".  
           "$update\n";  
     if (-e '/etc/loncapa-release') {      if (-e '/etc/loncapa-release') {
         my $lcstart = '/etc/init.d/loncontrol start';          my $lcstart = '/etc/init.d/loncontrol start';
         if ($lc_uses_systemctl) {          if ($lc_uses_systemctl) {
Line 2191  sub build_and_install_mod_auth_external Line 2403  sub build_and_install_mod_auth_external
 > #define SERVER_UIDS $num /* user "www" */  > #define SERVER_UIDS $num /* user "www" */
 ENDPATCH  ENDPATCH
   
     my $patch_code = <<"ENDPATCH";  
 127a128  
 > #include <string.h>  
 214a216  
 > #include <time.h>  
 566c568  
 < check_fails()  
 ---  
 > int check_fails()  
 589c591  
 < log_failure()  
 ---  
 > void log_failure()  
 629c631  
 < snooze(int seconds)  
 ---  
 > void snooze(int seconds)  
 653c655  
 < main(int argc, char **argv)  
 ---  
 > int main(int argc, char **argv)  
 ENDPATCH  
   
     if (! -e "/usr/bin/patch") {      if (! -e "/usr/bin/patch") {
  print_and_log(&mt('You must install the software development tools package: [_1], when installing Linux.',"'patch'")."\n");   print_and_log(&mt('You must install the software development tools package: [_1], when installing Linux.',"'patch'")."\n");
         print_and_log(&mt('Authentication installation not completed.')."\n");          print_and_log(&mt('Authentication installation not completed.')."\n");
Line 2224  ENDPATCH Line 2413  ENDPATCH
         return;          return;
     }      }
     my $dir = "/tmp/pwauth-2.2.8";      my $dir = "/tmp/pwauth-2.2.8";
     my $patchedok;  
     if (open(PATCH,"| patch $dir/config.h")) {      if (open(PATCH,"| patch $dir/config.h")) {
         print PATCH $patch;          print PATCH $patch;
         close(PATCH);          close(PATCH);
         if (open(PATCH,"| patch $dir/pwauth.c")) {  
             print PATCH $patch_code;  
             close(PATCH);  
             $patchedok = 1;  
         }  
     }  
     if ($patchedok) {  
         print_and_log("\n");          print_and_log("\n");
         ##          ##
         ## Compile patched pwauth          ## Compile patched pwauth
Line 2305  sub kill_extra_services { Line 2486  sub kill_extra_services {
             &print_and_log(&mt('Removing [_1] from startup.',$service)."\n");              &print_and_log(&mt('Removing [_1] from startup.',$service)."\n");
                     if ($distro =~ /^(?:debian|ubuntu)(\d+)/) {                      if ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
                         my $version = $1;                          my $version = $1;
                         if ((($distro =~ /^ubuntu/) && ($version > 16)) ||                          if (($distro =~ /^ubuntu/) && ($version > 16)) {
                             (($distro =~ /^debian/) && ($version >= 10))) {  
                             if (ref($uses_systemctl) eq 'HASH') {                              if (ref($uses_systemctl) eq 'HASH') {
                                 if ($uses_systemctl->{$service}) {                                  if ($uses_systemctl->{$service}) {
                                     if (`systemctl is-enabled $service`) {                                      if (`systemctl is-enabled $service`) {
Line 2376  CREATE TABLE IF NOT EXISTS metadata (tit Line 2556  CREATE TABLE IF NOT EXISTS metadata (tit
   
 sub setup_mysql_permissions {  sub setup_mysql_permissions {
     my ($dbh,$has_pass,$mysql_unix_socket,@mysql_lc_commands) = @_;      my ($dbh,$has_pass,$mysql_unix_socket,@mysql_lc_commands) = @_;
     my ($mysqlversion,$mysqlminorversion,$mysqlsubver,$mysqlname) = &get_mysql_version();      my ($mysqlversion,$mysqlsubver,$mysqlname) = &get_mysql_version();
     my ($usescreate,$usesauth,$is_mariadb,$hasauthcol,@mysql_commands);      my ($usescreate,$usesauth,$is_mariadb,$hasauthcol,@mysql_commands);
     if ($mysqlname =~ /^MariaDB/i) {      if ($mysqlname =~ /^MariaDB/i) {
         $is_mariadb = 1;          $is_mariadb = 1;
         if ((($mysqlversion == 10) && ($mysqlminorversion >= 4)) || ($mysqlversion >= 11)) {          if ($mysqlversion >= 10.4) {
             $usescreate = 1;              $usescreate = 1;
         } elsif (($mysqlversion == 10) && ($mysqlminorversion >= 2)) {          } elsif ($mysqlversion >= 10.2) {
             $usesauth = 1;              $usesauth = 1;
         } elsif (($mysqlversion == 5) && ($mysqlminorversion >= 5)) {          } elsif ($mysqlversion >= 5.5) {
             $hasauthcol = 1;              $hasauthcol = 1;
         }          }
     } else {      } else {
         if (($mysqlversion > 5) || (($mysqlminorversion == 5) && ($mysqlminorversion > 7)) ||          if (($mysqlversion > 5.7) || (($mysqlversion == 5.7) && ($mysqlsubver > 5))) {
             (($mysqlversion == 5) && ($mysqlminorversion == 7) && ($mysqlsubver > 5))) {  
             $usesauth = 1;              $usesauth = 1;
         } elsif (($mysqlversion == 5) &&          } elsif (($mysqlversion >= 5.6) || (($mysqlversion == 5.5) && ($mysqlsubver >= 7))) {
                  (($mysqlminorversion >= 6) || (($mysqlminorversion == 5) && ($mysqlsubver >= 7)))) {  
             $hasauthcol = 1;              $hasauthcol = 1;
         }          }
     }      }
     if ($usescreate) {      if ($usescreate) {
         @mysql_commands = ("CREATE USER 'www'\@'localhost' IDENTIFIED BY 'localhostkey'");          @mysql_commands = ("CREATE USER 'www'\@'localhost' IDENTIFIED BY 'localhostkey'");
     } elsif ($usesauth) {      } elsif ($usesauth) {
         @mysql_commands = ("INSERT user (Host, User, ssl_cipher, x509_issuer, x509_subject, authentication_string) VALUES('localhost','www','','','','')",          @mysql_commands = ("INSERT user (Host, User, ssl_cipher, x509_issuer, x509_subject, authentication_string) VALUES('localhost','www','','','','')");
                            "FLUSH PRIVILEGES");  
         if ($is_mariadb) {          if ($is_mariadb) {
             push(@mysql_commands,"ALTER USER 'www'\@'localhost' IDENTIFIED BY 'localhostkey'");              push(@mysql_commands,"ALTER USER 'www'\@'localhost' IDENTIFIED BY 'localhostkey'");
         } else {          } else {
Line 2506  sub new_mysql_rootpasswd { Line 2683  sub new_mysql_rootpasswd {
 }  }
   
 sub get_mysql_version {  sub get_mysql_version {
     my ($version,$minorversion,$subversion,$name);      my ($version,$subversion,$name);
     if (open(PIPE," mysql -V |")) {      if (open(PIPE," mysql -V |")) {
         my $info = <PIPE>;          my $info = <PIPE>;
         chomp($info);          chomp($info);
         close(PIPE);          close(PIPE);
         ($version,$minorversion,$subversion,$name) = ($info =~ /(\d+)\.(\d+)\.(\d+)(?:\-?(\w*),|)/);          ($version,$subversion,$name) = ($info =~ /(\d+\.\d+)\.(\d+)(?:\-?(\w*),|)/);
     } else {      } else {
         print &mt('Could not determine which version of MySQL is installed.').          print &mt('Could not determine which version of MySQL is installed.').
               "\n";                "\n";
     }      }
     return ($version,$minorversion,$subversion,$name);      return ($version,$subversion,$name);
 }  
   
 sub check_systemd_update {  
     my ($distro) = @_;  
     my ($use_systemctl,$service);  
     $service = 'apache2.service';  
     if ($distro =~ /^ubuntu(\w+)/) {  
         if ($1 >= 16) {  
             $use_systemctl = 1;  
         }  
     } elsif ($distro =~ /^debian(\w+)/) {  
         if ($1 >= 9) {  
             $use_systemctl = 1;  
         }  
     } elsif ($distro =~ /^fedora(\d+)/) {  
         $service = 'httpd.service';  
         if ($1 >= 16) {  
             $use_systemctl = 1;  
         }  
     } elsif ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {  
         $service = 'httpd.service';  
         if ($1 >= 7) {  
             $use_systemctl = 1;  
         }  
     } elsif ($distro =~ /^sles(\d+)/) {  
         if ($1 >= 12) {  
             $use_systemctl = 1;  
         }  
     } elsif ($distro =~ /^suse(\d+)/) {  
         if ($1 >= 13) {  
             $use_systemctl = 1;  
         }  
     }  
     if ($use_systemctl) {  
         my $needsupdate = &check_systemd_security($distro);  
         if ($needsupdate) {  
             if (!-d '/etc/systemd/system/'.$service.'.d') {  
                 mkdir '/etc/systemd/system/'.$service.'.d', 0755;  
             }  
             if (-d '/etc/systemd/system/'.$service.'.d') {  
                 if (-e '/etc/systemd/system/'.$service.'.d/override.conf') {  
                     if (open(my $fh,'<','/etc/systemd/system/'.$service.'.d/override.conf')) {  
                         my ($inservice,$addservice,$protectoff,$linenum,$change,@lines);  
                         while (my $entry = <$fh>) {  
                             $linenum ++;  
                             chomp($entry);  
                             if ($entry eq '[Service]') {  
                                 if (!$protectoff) {  
                                     $inservice = $linenum;  
                                     push(@lines,$entry);  
                                 } else {  
                                     $addservice = 1;  
                                     next;  
                                 }  
                             }  
                             if ($entry =~ /^ProtectHome\s*=\s*([\w-]+)\s*$/) {  
                                 my $value = $1;  
                                 if ($protectoff) {  
                                     next;  
                                     if (lc($value) eq 'no') {  
                                         $protectoff = $linenum;  
                                         push(@lines,$entry);  
                                     } else {  
                                         if ($protectoff) {  
                                             next;  
                                         } else {  
                                             push(@lines,'ProtectHome=no');  
                                             $protectoff = $linenum;  
                                             $change = $linenum;  
                                         }  
                                     }  
                                 }  
                             }  
                         }  
                         close($fh);  
                         if ($addservice || $change || !$protectoff) {  
                             if (open(my $fh,'>','/etc/systemd/system/'.$service.'.d/override.conf')) {  
                                 if ($addservice) {  
                                     print $fh "[Service]\n";  
                                 }  
                                 foreach my $entry (@lines) {  
                                     print $fh "$entry\n";  
                                 }  
                                 close($fh);  
                                 print_and_log('Updated /etc/systemd/system/'.$service.'.d/override.conf');  
                                 system('systemctl daemon-reload');  
                             } else {  
                                 print_and_log('Could not open /etc/systemd/system/'.$service.'.d/override.conf for writing.');  
                             }  
                         } else {  
                             print_and_log('No change needed in /etc/systemd/system/'.$service.'.d/override.conf');  
                         }  
                     } else {  
                         print_and_log('Could not open /etc/systemd/system/'.$service.'.d/override.conf for reading.');  
                     }  
                 } else {  
                     if (open(my $fh,'>','/etc/systemd/system/'.$service.'.d/override.conf')) {  
                         print $fh '[Service]'."\n".'ProtectHome=no'."\n";  
                         close($fh);  
                         print_and_log('Created /etc/systemd/system/'.$service.'.d/override.conf');  
                         system('systemctl daemon-reload');  
                     }  
                 }  
             } else {  
                 print_and_log('No /etc/systemd/system/'.$service.'.d directory exists and creating one failed,');  
             }  
         } else {  
             print_and_log('No update needed to systemd security settings for Apache web server.');  
         }  
     } else {  
         print_and_log('No update needed to systemd, as this Linux distro does not use systemctl');  
     }  
 }  }
   
 ###########################################################  ###########################################################
Line 2639  sub check_systemd_update { Line 2704  sub check_systemd_update {
 ###########################################################  ###########################################################
   
 sub copy_httpd_conf {  sub copy_httpd_conf {
     my ($instdir,$distro) = @_;      my ($instdir,$distro,$hostname) = @_;
     my $configfile = 'httpd.conf';      my $configfile = 'httpd.conf';
     if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {      if ($distro =~ /^(?:centos|rhes|scientific|oracle)(\d+)$/) {
         if ($1 >= 7) {          if ($1 >= 7) {
             $configfile = 'apache2.4/httpd.conf';              $configfile = 'apache2.4/httpd.conf';
         } elsif ($1 > 5) {          } elsif ($1 > 5) {
Line 2688  sub copy_mpm_conf { Line 2753  sub copy_mpm_conf {
         print_and_log("\n");          print_and_log("\n");
     } else {      } else {
         my $logfail;          my $logfail;
         if ($distro =~ /^(?:centos|rhes|scientific|oracle|rocky|alma)(\d+)/) {          if ($distro =~ /^(?:centos|rhes|scientific|oracle)(\d+)$/) {
             if ($1 > 7) {              if ($1 > 7) {
                 $logfail = 1;                  $logfail = 1;
             }              }
Line 2706  sub copy_mpm_conf { Line 2771  sub copy_mpm_conf {
     }      }
 }  }
   
   ###############################################
   ##
   ## Copy loncapassl.conf and sslrewrite.conf
   ##
   ###############################################
   
   #
   # The Apache SSL configuration used by LON-CAPA is contained in
   # two files: sslrewrite.conf and loncapassl.conf.
   #
   # Starting with LON-CAPA 2.12, name-based virtual hosts are used
   # with port 443. The default virtual host (i.e., the one listed
   # first) is for the server's standard hostname, and that is the one 
   # which will respond to client browser requests for https:// pages. 
   #
   # Accordingly, a system administrator will need to edit the config
   # config file to include paths to a signed SSL certificate (public), 
   # chain (public) and key (private) pem files. The certificate should
   # have been signed by a recognized certificate authority ((e.g., 
   # InCommon or Let's Encrypt).
   #  
   # The sslrewrite.conf file contains the rewrite configuration for
   # the default virtual host. The rewrite rules defined are used to 
   # allow internal HEAD requests to /cgi-bin/mimetex.cgi to be served
   # http://, in order to support vertical alignment of mimetex images
   # (one of the options for rendering Math content); (b) allow requests
   # for certain URLs (external resource, and syllabus, if external URL
   # used) to be served http:// to accommodate the use of iframes which 
   # would otherwise result in browser blocking of mixed active content.
   #
   # The loncapassl.conf file contains the configuration for the  
   # "internal" virtual host, which will respond to requests for https://
   # pages from other LON-CAPA servers in the network to which the node
   # belongs. The ServerName is internal-<hostname> where <hostname>
   # is the server's hostname. There is no need to create a DNS entry 
   # for internal-<hostname>, as LON-CAPA 2.12 automatically performs
   # the required hostname to IP mapping.
   # 
   # Requests to /raw on the "internal" virtual host require a valid
   # SSL client certificate, signed by the certificate authority
   # for the LON-CAPA network to which the node belongs.
   # 
   # The configuration file to which the contents of sslrewrite.conf
   # and loncapassl.conf will be written will have either been identified
   # when &chkapachessl() was run, or if no files were found with
   # existing rewrite blocks, then a candidate file will be chosen
   # from the .conf files containing VirtualHosts definitions.
   # If there is more than one suitable candidate file, the system
   # administrator will be prompted to select from the available files.
   #
   # If there are no files containing VirtualHosts definitions, then
   # <VirtualHost *:443> </VirtualHost> blocks will be appended to
   # the standard Apache SSL config for the particular distro:
   # ssl.conf for RHEL/CentOS/Scientific/Fedora, vhost-ssl.conf
   # for SuSE/SLES, and default-ssl.conf for Ubuntu.
   #
   # Once a file is selected, the contents of sslrewrite.conf and
   # loncapassl.conf are compared with appropriate blocks in the file
   # and the user will be prompted to agree to insertion of missing lines
   # and/or deletion of surplus lines.
   #
   
   sub copy_apache_sslconf_files {
       my ($distro,$hostname,$hostip,$instdir,$targetdir,$targetfilesref,
           $has_std,$has_int,$rewritenum,$nochgstd,$nochgint) = @_;
       my ($new_std,$new_int);
       my (@internal,@standard,%int_by_linenum,%int_by_linetext,
           %rule_by_linenum,%rule_by_linetext,%foundint);
       if (-e "$instdir/loncapassl.conf") {
           if (open(my $fh,'<',"$instdir/loncapassl.conf")) {
               my $num = 1;
               while (<$fh>) {
                   chomp();
                   if (/^ServerName/) {
                       s/(\Qinternal-{[[[[Hostname]]]]}\E)/internal-$hostname/;
                   }
                   push(@internal,$_);
                   $int_by_linenum{$num} = $_;
                   s/(^\s+|\s+$)//g;
                   push(@{$int_by_linetext{$_}},$num);
                   $num ++;
               }
               close($fh);
           }
       }
       if (-e "$instdir/sslrewrite.conf") {
           if (open(my $fh,'<',"$instdir/sslrewrite.conf")) {
               my $num = 1;
               while (<$fh>) {
                   chomp();
                   if (/\Q{[[[[HostIP]]]]}\E/) {
                       s/(\QRewriteCond %{REMOTE_ADDR} {[[[[HostIP]]]]}\E)/RewriteCond %{REMOTE_ADDR} $hostip/;
                   }
                   push(@standard,$_);
                   $rule_by_linenum{$num} = $_;
                   s/(^\s+|\s+$)//g;
                   push(@{$rule_by_linetext{$_}},$num);
                   $num ++;
               }
               close($fh);
           }
       }
       if (!$nochgstd) {
           if ($has_std eq '') {
               my $file;
               if ($has_int ne '') {
                   if (open(my $fh,'<',"$targetdir/$has_int")) {
                       my @saved = <$fh>;
                       close($fh);
                       if (open(my $fhout, '>',"$targetdir/$has_int")) {
                           print $fhout "<VirtualHost *:443>\n".
                                        "ServerName $hostname\n".
                                        join("\n",@standard)."\n".
                                        "</VirtualHost>\n\n".
                                        join('',@saved);
                           close($fhout);
                           $new_int = $has_int; 
                       }
                   }
               }
           } else {
               if ($rewritenum eq '') {
                   &append_to_vhost($targetdir,$has_std,$hostname,\%rule_by_linenum,'std');
                   $new_std = $has_std;
               } else {
                   $new_std = &modify_ssl_config($targetdir,$has_std,$hostname,$rewritenum,
                                                 \%rule_by_linetext,\%rule_by_linenum,'std');
               }
           }
       }
       if (!$nochgint) {
           if ($has_int eq '') {
               if ($has_std ne '') {
                   if (open(my $fhout,'>>',"$targetdir/$has_std")) {
                       print $fhout "\n".join("\n",@internal)."\n";
                       close($fhout);
                       $new_int = $has_std;
                   }
               }
           } else {
               $new_int = &modify_ssl_config($targetdir,$has_int,$hostname,$rewritenum,\%int_by_linetext,\%int_by_linenum,'int');
           }
       }
       if (($has_std eq '') && ($has_int eq '')) {
           my ($file,$numfiles) = &get_sslconf_filename($distro,$targetdir,$targetfilesref);
           if ($numfiles == 0) { 
               if (open(my $fhout, '>>', "$targetdir/$file")) {
                   print $fhout "<VirtualHost *:443>\n".
                                "ServerName $hostname\n".
                                join("\n",@standard)."\n".
                                "</VirtualHost>\n\n".
                                join("\n",@internal)."\n";
                   close($fhout);
                   $new_std = $file;
                   $new_int = $file;
               }
           } elsif ($numfiles == 1) {
               &append_to_vhost($targetdir,$file,$hostname,\%rule_by_linenum,'std');
               if (open(my $fhout, '>>', "$targetdir/$file")) {
                   print $fhout "\n".join("\n",@internal)."\n";
                   close($fhout);
                   $new_std = $file;
                   $new_int = $file;
               }
           } elsif ($numfiles == -1) {
               print_and_log(&mt('Failed to copy contents of [_1] or [_2] to a file in [_3]',
                                 "'loncapassl.conf'","'sslrewrite.conf'","'$targetdir'")."\n");
           }
       }
       if ($nochgstd) {
           print_and_log(&mt('No change required to file: [_1] in [_2], (no difference between [_3] and rewrite block.)',
                             "'$has_std'","'$targetdir'","'sslrewrite.conf'"));
       }
       if ($nochgint) {
           print_and_log(&mt('No change required to file: [_1] in [_2], (no difference between [_3] and virtualhost block.)',
                             "'$has_int'","'$targetdir'","'loncapassl.conf'"));
       }
       if ($new_int) {
           print_and_log(&mt('Successfully copied contents of [_1] to [_2].',"'loncapassl.conf'","'$targetdir/$new_int'")."\n");
           chmod(0444,"$targetdir/loncapassl.conf");
       }
       if ($new_std) {
           print_and_log(&mt('Successfully copied contents of [_1] to [_2].',"'sslrewrite.conf'","'$targetdir/$new_std'")."\n");
           chmod(0444,"$targetdir/loncapassl.conf");
       }
       return ($new_int,$new_std);
   }
   
   #
   # append_to_vhost() is called to add rewrite rules (in a 
   # <IfModule +mod_rewrite.c> </IfModule> block), provided
   # in the sslrewrite.conf configuration file, to an Apache
   # SSL configuration file within a VirtualHost for port 443
   # (for server's public-facing hostname).
   #
   sub append_to_vhost {
       my ($targetdir,$filename,$hostname,$by_linenum,$type) = @_;
       return unless (ref($by_linenum) eq 'HASH');
       my ($startvhost,$endvhost);
       if (-e "$targetdir/$filename") {
           my (@lines,$currname,$virtualhost,$hasname);
           if (open(my $fh,'<',"$targetdir/$filename")) {
               my $currline = 0;
               while (<$fh>) {
                   $currline ++;
                   push(@lines,$_);
                   chomp();
                   s/(^\s+|\s+$)//g;
                   if (/^<VirtualHost\s+[^:]*\:443>/) {
                       $virtualhost = 1;
                       unless ($endvhost) {
                           $startvhost = $currline;
                       }
                   }
                   if ($virtualhost) {
                       if (/^ServerName\s+([^\s]+)\s*$/) {
                           $currname = $1;
                           unless ($endvhost) {
                               if ((($currname eq '') || ($currname eq $hostname)) && ($type eq 'std')) {
                                   $hasname = 1;
                               }
                           }
                       }
                       if (/^<\/VirtualHost>/) {
                           $virtualhost = 0;
                           unless ($endvhost) {
                               if (((($currname eq '') || ($currname eq $hostname)) && ($type eq 'std')) ||
                                   (($currname eq 'internal-'.$hostname) && ($type eq 'int'))) { 
                                   $endvhost = $currline;
                               } else {
                                   undef($startvhost);  
                               }
                           }
                       }
                   }
               }
               close($fh);
           }
           if ($endvhost) {
               if (open(my $fout,'>',"$targetdir/$filename")) {
                   for (my $i=0; $i<@lines; $i++) {
                       if ($i == $startvhost) {
                           unless (($hasname) && ($type eq 'std')) {
                               print $fout "ServerName $hostname\n";
                           }
                       }
                       if ($i == $endvhost-1) {
                           foreach my $item (sort { $a <=> $b } keys(%{$by_linenum})) {
                               print $fout $by_linenum->{$item}."\n";
                           }
                       }
                       print $fout $lines[$i];
                   }
                   close($fout);
               }
           }
       }
       return $endvhost;
   }
   
   #
   # get_sslconf_filename() is called when the Apache SSL configuration
   # option has been selected and there are no files containing
   # VirtualHost definitions containing rewrite blocks,
   # 
   # In this case get_sslconf_filename() is used to chose from the 
   # available .conf files containing VirtualHosts definitions. If
   # there is ambiguity about which file to use, &apacheconf_choice()
   # will be called to prompt the user to choose one of the possible
   # files.
   #
   
   sub get_sslconf_filename {
       my ($distro,$targetdir,$targetfilesref) = @_;
       my ($configfile,$numfiles,@possfiles);
       if (ref($targetfilesref) eq 'HASH') {
           if (keys(%{$targetfilesref}) > 0) {
               foreach my $name (sort(keys(%{$targetfilesref}))) {
                   if (ref($targetfilesref->{$name}) eq 'HASH') {
                       foreach my $file (sort(keys(%{$targetfilesref->{$name}}))) {
                           next if ($file eq '');
                           next if (!-e "$targetdir/$file");
                           unless (grep(/^\Q$file\E$/,@possfiles)) {
                               push(@possfiles,$file);
                           }
                       }
                   }
               }
           }
           if (@possfiles == 0) {
               $configfile = 'ssl.conf';
               if ($distro =~ /^(suse|sles)/) {
                   $configfile = 'vhost-ssl.conf';
               } elsif ($distro =~ /^(debian|ubuntu)/) {
                   $configfile = 'default-ssl.conf';
               }
               $numfiles = 0;
               print &mt('No configuration files in [_1] contain a <VirtualHost *:443> </VirtualHost> block which can be used to house Apache rewrite rules from https to http.',$targetdir)."\n\n".
                     &mt('Accordingly, the contents of sslrewrite.conf will be included in a <VirtualHost *:443> </VirtualHost> block which will be added to a file named: [_1].',$configfile)."\n\n";
           } elsif (@possfiles == 1) {
               $configfile = $possfiles[0];
               $numfiles = 1;
               print &mt('A single configuration file in [_1] contains a <VirtualHost *:443> </VirtualHost> block.',$targetdir)."\n".
                     &mt('The contents of sslrewrite.conf will be added to this block.')."\n\n";
           } else {
               print &mt('More than one Apache config file contains a <VirtualHost *:443> </VirtualHost> block.')."\n\n".&mt('The possible files are:')."\n";
               my $counter = 1;
               my $max = scalar(@possfiles);
               foreach my $file (@possfiles) {
                   print "$counter. $file\n";
                   $counter ++;
               }
               print "\n".&mt('Enter a number between 1 and [_1] to indicate which file should be modified to include the contents of sslrewrite.conf.',$max)."\n";
               my $choice = &apacheconf_choice($max);
               if (($choice =~ /^\d+$/) && ($choice >= 1) && ($choice <= $max)) {
                   $configfile = $possfiles[$choice-1];
                   $numfiles = 1; 
               } else {
                   $numfiles = -1;
               }
           }
       }
       return ($configfile,$numfiles);
   }
   
   #
   # &apacheconf_choice() prompts a user to choose an integer between 1 and the  
   # maximum number of available of possible Apache SSL config files found
   # at the distros standard location for Apache config files containing
   # VirtualHost definitions.
   #
   # This routine is called recursively until the user enters a valid integer.
   #
   
   sub apacheconf_choice {
       my ($max) = @_;
       my $choice = <STDIN>;
       chomp($choice);
       $choice =~ s/(^\s+|\s+$)//g;
       my $configfile;
       if (($choice =~ /^\d+$/) && ($choice >= 1) && ($choice <= $max)) {
           $configfile = $choice;
       } 
       while ($configfile eq '') {
           print &mt('Invalid choice.  Please enter a number between 1 and [_1].',$max)."\n";
           $configfile = &apacheconf_choice($max);
       }
       print "\n";
       return $configfile;
   }
   
   #
   # &modify_ssl_config() is called to modify the contents of an Apache SSL config
   # file so that it has two <VirtualHost *:443> </VirtualHost> blocks containing
   # (a) the default VirtualHost with the <IfModule mod_rewrite.c> </IfModule> block 
   # provided in sslrewrites.conf, and (b) an "internal" VirtualHost with the 
   # content provided in loncapassl.conf.
   #
   # This routine will prompted you to agree to insertion of lines present in the
   # shipped conf file, but missing from the local config file, and also for
   # deletion of lines present in the local config file, but not required in
   # the shipped conf file.
   # 
    
   sub modify_ssl_config {
       my ($targetdir,$filename,$hostname,$rewritenum,$by_linetext,$by_linenum,$type) = @_;
       return unless ((ref($by_linetext) eq 'HASH') && (ref($by_linenum) eq 'HASH'));
       if (-e "$targetdir/$filename") {
           my (@lines,$virtualhost,$currname,$rewrite);
           if (open(my $fh,'<',"$targetdir/$filename")) {
               my %found;
               my %possible;
               my $currline = 0;
               my $rewritecount = 0;
               while (<$fh>) {
                   $currline ++;
                   push(@lines,$_);
                   chomp();
                   s/(^\s+|\s+$)//g;
                   if (/^\s*<VirtualHost\s+[^:]*\:443>\s*$/) {
                       $virtualhost = 1;
                   }
                   if ($virtualhost) {
                       if ((exists($by_linetext->{$_})) && (ref($by_linetext->{$_}) eq 'ARRAY') &&
                           (@{$by_linetext->{$_}} > 0)) {
                           $possible{$currline} = shift(@{$by_linetext->{$_}});
                       } 
                       if (/^\s*<\/VirtualHost>/) {
                           if ((($currname eq 'internal-'.$hostname) && ($type eq 'int')) ||
                               ((($currname eq $hostname) || ($currname eq '')) && ($type eq 'std') &&
                                 ($rewritecount == $rewritenum))) {
                               %found = (%found,%possible);
                           } else {
                               foreach my $line (sort {$b <=> $a } keys(%possible)) {
                                   my $num = $possible{$line};
                                   if (ref($by_linetext->{$by_linenum->{$num}}) eq 'ARRAY') { 
                                       unshift(@{$by_linetext->{$by_linenum->{$num}}},$num);
                                   }
                               } 
                           }
                           undef(%possible);
                           $virtualhost = 0;
                           $currname = '';
                       } elsif (/^\s*ServerName\s+([^\s]+)\s*$/) {
                           $currname = $1;
                       } elsif (/^\s*<IfModule\s+mod_rewrite\.c>/) {
                           $rewrite = 1;
                       } elsif (/^\s*<\/IfModule>/) {
                           $rewritecount ++;
                           $rewrite = 0;
                       }
                   }
               }
               close($fh);
               if (open(my $fout,'>',"$targetdir/$filename")) {
                   my $currline = 0;
                   my ($lastfound,$done);
                   my $numfound = 0;
                   foreach my $line (@lines) {
                       $currline ++;
                       if ($done) {
                           print $fout $line;
                       } elsif ($lastfound) {
                           if ($found{$currline}) {
                               for (my $i=$lastfound+1; $i<$found{$currline}; $i++) {
                                   print &mt('The following line is missing from the current <VirtualHost *:443> </VirtualHost> block:')."\n".
                                         $by_linenum->{$i}."\n".
                                         &mt('Add this line? ~[Y/n~]');
                                   if (&get_user_selection(1)) {
                                       print $fout $by_linenum->{$i}."\n";
                                   }
                               }
                               $numfound ++;
                               $lastfound = $found{$currline};
                               print $fout $line;
                               if ($numfound == scalar(keys(%found))) {
                                   $done = 1;
                                   for (my $i=$found{$currline}+1; $i<=scalar(keys(%{$by_linenum})); $i++) {
                                       print &mt('The following line is missing from the current <VirtualHost *:443> </VirtualHost> block:')."\n".
                                             $by_linenum->{$i}."\n".
                                             &mt('Add this line? ~[Y/n~]');
                                       if (&get_user_selection(1)) {
                                           print $fout $by_linenum->{$i}."\n";
                                       }
                                   }
                               }
                           } else {
                               print &mt('The following line found within a <VirtualHost *:443> </VirtualHost> block does not match that expected by LON-CAPA:')."\n".
                                     $line.
                                     &mt('Delete this line? ~[Y/n~]');
                               if (!&get_user_selection(1)) {
                                   print $fout $line;
                               }
                           }
                       } elsif ($found{$currline}) {
                           $numfound ++;
                           $lastfound = $found{$currline};
                           for (my $i=1; $i<$found{$currline}; $i++) {
                               print &mt('The following line is missing from the current <VirtualHost *:443> </VirtualHost> block:')."\n".
                                     $by_linenum->{$i}."\n".
                                     &mt('Add this line? ~[Y/n~]');
                               if (&get_user_selection(1)) {
                                   print $fout $by_linenum->{$i}."\n";
                               }
                           }
                           print $fout $line;
                       } else {
                           print $fout $line;
                       }
                   }
                   close($fout);
               }
           }
       }
       return $filename;
   }
   
 #########################################################  #########################################################
 ##  ##
 ## Ubuntu/Debian -- copy our loncapa configuration file to  ## Ubuntu/Debian -- copy our loncapa configuration file to
Line 2714  sub copy_mpm_conf { Line 3256  sub copy_mpm_conf {
 #########################################################  #########################################################
   
 sub copy_apache2_debconf {  sub copy_apache2_debconf {
     my ($instdir,$distro) = @_;      my ($instdir,$distro,$hostname) = @_;
     my $apache2_mods_enabled_dir = '/etc/apache2/mods-enabled';      my $apache2_mods_enabled_dir = '/etc/apache2/mods-enabled';
     my $apache2_mods_available_dir = '/etc/apache2/mods-available';      my $apache2_mods_available_dir = '/etc/apache2/mods-available';
     foreach my $module ('headers.load','expires.load') {      foreach my $module ('headers.load','expires.load') {
Line 2732  sub copy_apache2_debconf { Line 3274  sub copy_apache2_debconf {
         $distname = $1;          $distname = $1;
         $version = $2;          $version = $2;
     }      }
     if ((($distname eq 'ubuntu') && ($version > 12)) ||      if (($distname eq 'ubuntu') && ($version > 12)) {
         (($distname eq 'debian') && ($version >= 10))) {  
         $defaultconfig = "$apache2_sites_enabled_dir/000-default.conf";          $defaultconfig = "$apache2_sites_enabled_dir/000-default.conf";
     }      }
     my ($skipconf,$skipsite,$skipstatus);      my ($skipconf,$skipsite,$skipstatus);
     if ((($distname eq 'ubuntu') && ($version > 12)) ||      if (($distname eq 'ubuntu') && ($version > 12)) {
         (($distname eq 'debian') && ($version >= 10))) {  
         my $apache2_conf_enabled_dir = '/etc/apache2/conf-enabled';          my $apache2_conf_enabled_dir = '/etc/apache2/conf-enabled';
         my $apache2_conf_available_dir = '/etc/apache2/conf-available';          my $apache2_conf_available_dir = '/etc/apache2/conf-available';
         my $defaultconf = $apache2_conf_enabled_dir.'/loncapa.conf';          my $defaultconf = $apache2_conf_enabled_dir.'/loncapa.conf';
Line 2891  sub copy_apache2_debconf { Line 3431  sub copy_apache2_debconf {
             }              }
         }          }
     }      }
     if (($distname eq 'ubuntu') || ($distname eq 'debian')) {      if ($distname eq 'ubuntu') {
         my $sitestatus = "$apache2_mods_available_dir/status.conf";          my $sitestatus = "$apache2_mods_available_dir/status.conf";
         my $stdstatus = "$instdir/debian-ubuntu/status.conf";          my $stdstatus = "$instdir/debian-ubuntu/status.conf";
         if ((-e $sitestatus) && (-e $stdstatus)) {          if ((-e $sitestatus) && (-e $stdstatus)) {
Line 2926  sub copy_apache2_debconf { Line 3466  sub copy_apache2_debconf {
 ###########################################################  ###########################################################
   
 sub copy_apache2_suseconf {  sub copy_apache2_suseconf {
     my ($instdir,$distro) = @_;      my ($instdir,$hostname,$distro) = @_;
     my ($name,$version) = ($distro =~ /^(suse|sles)([\d\.]+)$/);      my ($name,$version) = ($distro =~ /^(suse|sles)([\d\.]+)$/);
     my $conf_file = "$instdir/sles-suse/default-server.conf";      my $conf_file = "$instdir/sles-suse/default-server.conf";
     if (($name eq 'sles') && ($version >= 12)) {      if (($name eq 'sles') && ($version >= 12)) {
Line 3092  sub download_loncapa { Line 3632  sub download_loncapa {
  print_and_log("   print_and_log("
 ------------------------------------------------------------------------  ------------------------------------------------------------------------
   
 ".&mt('You seem to have a version of [_1] in [_2]',$lctarball,$instdir)."\n".  ".&mt('You seem to have a version of loncapa-current.tar.gz in [_1]',$instdir)."\n".
 &mt('This copy will be used and a new version will NOT be downloaded.')."\n".  &mt('This copy will be used and a new version will NOT be downloaded.')."\n".
 &mt('If you wish, you may download a new version by executing:')."  &mt('If you wish, you may download a new version by executing:')."
   
 wget http://install.loncapa.org/versions/$lctarball  wget http://install.loncapa.org/versions/loncapa-current.tar.gz
   
 ------------------------------------------------------------------------  ------------------------------------------------------------------------
 ");  ");
     }      }
   
     ##      ##
     ## untar loncapa-X.Y.Z.tar.gz      ## untar loncapa.tar.gz
     ##      ##
     if ($have_tarball) {      if ($have_tarball) {
         my $homedir = '/root';  
         my ($targetdir,$chdircmd,$updatecmd);  
         if (($distro =~ /^ubuntu/) && ($instdir ne $homedir)) {  
             ($homedir) = ($instdir =~ m{^(.*)/[^/]+$});  
             $updatecmd = 'sudo ./UPDATE';  
         } else {  
             $updatecmd = './UPDATE';  
         }  
         print_and_log(&mt('Extracting LON-CAPA source files')."\n");          print_and_log(&mt('Extracting LON-CAPA source files')."\n");
         if (-e $homedir) {          writelog(`cd ~root; tar zxf $instdir/$lctarball`);
             writelog(`tar zxf $instdir/$lctarball --directory $homedir`);  
             $targetdir = $homedir;  
         } else {  
             writelog(`tar zxf $instdir/$lctarball`);  
             $targetdir = $instdir;  
         }  
         if ($lctarball =~ /^loncapa\-(\d+\.\d+\.\d+(?:|[^.]+))\.tar\.gz$/) {  
             $chdircmd = "cd $targetdir/loncapa-".$1;  
         } else {  
             $chdircmd = "cd $targetdir/loncapa-X.Y.Z  (X.Y.Z should correspond to a version number like '2.11.3')";  
         }  
         print_and_log("\n");          print_and_log("\n");
         print &mt('LON-CAPA source files extracted.')."\n".          print &mt('LON-CAPA source files extracted.')."\n".
               &mt('It remains for you to execute the following commands:').                &mt('It remains for you to execute the following commands:')."
               "\n$chdircmd\n$updatecmd\n".  
               &mt('If you have any trouble, please see [_1] and [_2]',  cd /root/loncapa-X.Y.Z     (X.Y.Z should correspond to a version number like '2.11.3')
                   'http://install.loncapa.org/','http://help.loncapa.org/')."\n";  ./UPDATE
   
   ".&mt('If you have any trouble, please see [_1] and [_2]',
         'http://install.loncapa.org/','http://help.loncapa.org/')."\n";
         $updateshown = 1;          $updateshown = 1;
     }      }
     return ($have_tarball,$updateshown);      return ($have_tarball,$updateshown);

Removed from v.1.45.2.23  
changed lines
  Added in v.1.75


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>