File:  [LON-CAPA] / loncom / configuration / Checksumming.pm
Revision 1.9: download - view: text, annotated - select for diffs
Wed Oct 24 18:16:14 2018 UTC (5 years, 7 months ago) by raeburn
Branches: MAIN
CVS tags: version_2_11_X, version_2_11_4_uiuc, version_2_11_4_msu, version_2_11_4, version_2_11_3_uiuc, version_2_11_3_msu, version_2_11_3, HEAD
- Original text file for wrapped files now checked by &compare_checksums().

    1: # The LearningOnline Network with CAPA
    2: # Checksum installed LON-CAPA modules and some configuration files
    3: #
    4: # $Id: Checksumming.pm,v 1.9 2018/10/24 18:16:14 raeburn Exp $
    5: #
    6: # The LearningOnline Network with CAPA
    7: #
    8: # Copyright Michigan State University Board of Trustees
    9: #
   10: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   11: #
   12: # LON-CAPA is free software; you can redistribute it and/or modify
   13: # it under the terms of the GNU General Public License as published by
   14: # the Free Software Foundation; either version 2 of the License, or
   15: # (at your option) any later version.
   16: #
   17: # LON-CAPA is distributed in the hope that it will be useful,
   18: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   19: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20: # GNU General Public License for more details.
   21: #
   22: # You should have received a copy of the GNU General Public License
   23: # along with LON-CAPA; if not, write to the Free Software
   24: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   25: #
   26: # /home/httpd/html/adm/gpl.txt
   27: #
   28: # http://www.lon-capa.org/
   29: #
   30: 
   31: package LONCAPA::Checksumming;
   32: 
   33: use strict;
   34: use lib '/home/httpd/lib/perl/';
   35: use Apache::lonlocal();
   36: use Apache::loncommon();
   37: use Digest::SHA;
   38: 
   39: sub get_checksums {
   40:     my ($distro,$londaemons,$lonlib,$lonincludes,$lontabdir) = @_;
   41:     my $output;
   42:     my (%versions,%chksums);
   43:     my $dirh;
   44:     my $revtag = '$Id:';
   45:     my @paths;
   46:     if ($londaemons) {
   47:         push(@paths,($londaemons.'/*',
   48:                      $londaemons.'/debug/*.pl'));
   49:     }
   50:     if ($lonlib) {
   51:         push(@paths,($lonlib.'/perl/Apache/*.pm',
   52:                      $lonlib.'/perl/Apache/localize/*.pm',
   53:                      $lonlib.'/perl/LONCAPA/*.pm',
   54:                      $lonlib.'/perl/AlgParser.pm',
   55:                      $lonlib.'/perl/LONCAPA.pm',
   56:                      $lonlib.'/perl/Safe.pm',
   57:                      $lonlib.'/perl/*-std.pm',
   58:                      $lonlib.'/perl/HTML/*.pm',
   59:                      $lonlib.'/perl/Safe.pm'));
   60:     }
   61:     if ($lonincludes) {
   62:         push(@paths,$lonincludes.'/*.lcpm');
   63:     }
   64:     push(@paths,('/home/httpd/cgi-bin/*.pl','/home/httpd/cgi-bin/*.png'));
   65:     my $confdir = '/etc/httpd/conf';
   66:     if ($distro =~ /^(ubuntu|debian)(\d+)$/) {
   67:         $confdir = '/etc/apache2';
   68:     } elsif ($distro =~ /^sles(\d+)$/) {
   69:         if ($1 >= 10) {
   70:             $confdir = '/etc/apache2';
   71:         }
   72:     } elsif ($distro =~ /^suse(\d+\.\d+)$/) {
   73:         if ($1 >= 10.0) {
   74:             $confdir = '/etc/apache2';
   75:         }
   76:     }
   77:     push(@paths,("$confdir/loncapa_apache.conf","$confdir/startup.pl"));
   78:     if ($lontabdir) {
   79:         push(@paths,$lontabdir.'/mydesk.tab');
   80:     }
   81:     if (@paths) {
   82:         my $pathstr = join (' ',@paths);
   83:         if (open($dirh,"grep '$revtag' $pathstr 2>&1 |")) {
   84:             while (my $line=<$dirh>) {
   85:                 if ($line =~ m{^([^#]+):#\s\$Id:\s[\w.]+,v\s([\d.]+)\s}) {
   86:                     $versions{$1} = $2;
   87:                 }
   88:             }
   89:             close($dirh);
   90:         }
   91:         if ($londaemons) {
   92:             my @binaries = qw (apachereload lchttpdlogs lcinstallfile lciptables lcnfsoff lcnfson lcpasswd lcuserdel pwchange);
   93:             foreach my $file (@binaries) {
   94:                 next if ($versions{"$londaemons/$file"});
   95:                 if (-B "$londaemons/$file") {
   96:                     if (-T $londaemons.'/.'.$file) {
   97:                         if (open(my $fh,'<',$londaemons.'/.'.$file)) {
   98:                             while (my $line=<$fh>) {
   99:                                 if ($line =~ m{^#\s\$Id:\s[\w.]+,v\s([\d.]+)\s}) {
  100:                                     $versions{"$londaemons/$file"} = $1;
  101:                                     last;
  102:                                 }
  103:                             }
  104:                             close($fh);
  105:                         }
  106:                         if ($versions{"$londaemons/$file"}) {
  107:                             if (open(my $fh,'<',$londaemons.'/.'.$file)) {
  108:                                 binmode $fh;
  109:                                 my $sha_obj = Digest::SHA->new();
  110:                                 $sha_obj->addfile($fh);
  111:                                 $chksums{"$londaemons/$file"} = $sha_obj->hexdigest;
  112:                                 close($fh);
  113:                             }
  114:                         }
  115:                     }
  116:                 }
  117:             }
  118:         }
  119:         foreach my $key (sort(keys(%versions))) {
  120:             next if ($key =~ /\.lpmlsave$/);
  121:             unless (exists($chksums{$key})) {
  122:                 if (open(my $fh,"<$key")) {
  123:                     binmode $fh;
  124:                     my $sha_obj = Digest::SHA->new();
  125:                     $sha_obj->addfile($fh);
  126:                     $chksums{$key} = $sha_obj->hexdigest;
  127:                     close($fh);
  128:                 }
  129:             }
  130:             $output .= "$key,$versions{$key},$chksums{$key}\n";
  131:         }
  132:     }
  133:     if ($lontabdir ne '') {
  134:         if (open(my $tabfh,">$lontabdir/lonchksums.tab")) {
  135:             print $tabfh '# Last written: '.localtime(time)."\n";
  136:             print $tabfh "$output\n";
  137:             close($tabfh);
  138:         }
  139:     }
  140:     return (\%chksums,\%versions);
  141: }
  142: 
  143: sub compare_checksums {
  144:     my ($target,$lonhost,$version,$serversums,$serverversions) = @_;
  145:     my ($message,$numchg,$linefeed);
  146:     if ($target eq 'web') {
  147:         $linefeed = '<br />';
  148:     } else {
  149:         $linefeed = "\n";
  150:     }
  151:     if (!$Apache::lonlocal::lh) {
  152:         &Apache::lonlocal::get_language_handle();
  153:     }
  154:     if ((ref($serversums) eq 'HASH') && (keys(%{$serversums}))) {
  155:         my $checksums = &Apache::lonnet::fetch_dns_checksums();
  156:         my (%extra,%missing,%diffs,%stdsums,%stdversions);
  157:         if (ref($checksums) eq 'HASH') {
  158:             if (ref($checksums->{'sums'}) eq 'HASH') {
  159:                 %stdsums = %{$checksums->{'sums'}};
  160:             }
  161:             if (ref($checksums->{'versions'}) eq 'HASH') {
  162:                 %stdversions = %{$checksums->{'versions'}};
  163:             }
  164:             if (keys(%stdsums)) {
  165:                 foreach my $key (keys(%stdsums)) {
  166:                     if (exists($serversums->{$key})) {
  167:                         if ($serversums->{$key} ne $stdsums{$key}) {
  168:                             $diffs{$key} = 1;
  169:                             $numchg ++;
  170:                         }
  171:                     } else {
  172:                         $missing{$key} = 1;
  173:                         $numchg ++;
  174:                     }
  175:                 }
  176:                 foreach my $key (keys(%{$serversums})) {
  177:                     unless (exists($stdsums{$key})) {
  178:                         $extra{$key} = 1;
  179:                         $numchg ++;
  180:                     }
  181:                 }
  182:             }
  183:             if ($numchg) {
  184:                 $message =
  185:                     &Apache::lonlocal::mt('[quant,_1,difference was,differences were] found'.
  186:                                           ' between LON-CAPA modules installed on your server [_2]'.
  187:                                           ' and those expected for the LON-CAPA version you are'.
  188:                                           ' currently running.',$numchg,"($lonhost)$linefeed");
  189:                 if ($target eq 'web') {
  190:                     $message = '<p>'.$message.'</p>';
  191:                 } else {
  192:                     $message .= "\n\n";
  193:                 }
  194:                 my (@diffversion,@modified);
  195:                 if (keys(%diffs) > 0) {
  196:                     foreach my $file (sort(keys(%diffs))) {
  197:                         if ($serverversions->{$file} ne $stdversions{$file}) {
  198:                             push(@diffversion,$file);
  199:                         } else {
  200:                             push(@modified,$file);
  201:                         }
  202:                     }
  203:                     if (@diffversion > 0) {
  204:                         my $text =
  205:                             &Apache::lonlocal::mt('The following [quant,_1,file is a,files are]'.
  206:                                                   ' different version(s) from that expected for LON-CAPA [_2]:',
  207:                                                   scalar(@diffversion),$version);
  208:                         if ($target eq 'web') {
  209:                             $message .= '<p>'.$text.'</p>'.
  210:                                         &Apache::loncommon::start_data_table().
  211:                                         &Apache::loncommon::start_data_table_header_row()."\n".
  212:                                         '<th>'.&Apache::lonlocal::mt('File').'</th>'."\n".
  213:                                         '<th>'.&Apache::lonlocal::mt('Server version').'</th>'."\n".
  214:                                         '<th>'.&Apache::lonlocal::mt('Expected version').'</th>'."\n".
  215:                                         &Apache::loncommon::end_data_table_header_row()."\n";
  216:                         } else {
  217:                             $message .= "$text\n";
  218:                         }
  219:                         foreach my $file (sort(@diffversion)) {
  220:                             my $revnum = $stdversions{$file};
  221:                             if ($target eq 'web') {
  222:                                 $message .=  &Apache::loncommon::start_data_table_row().
  223:                                              '<td>'.$file.'</td>'."\n".
  224:                                              '<td>'.$serverversions->{$file}.'</td>'."\n".
  225:                                              '<td>'.$revnum.'</td>'."\n".
  226:                                              &Apache::loncommon::end_data_table_row()."\n";
  227:                             } else {
  228:                                 $message .= $file.' '.
  229:                                             &Apache::lonlocal::mt('(local rev: [_1])',
  230:                                                                   $serverversions->{$file});
  231:                                 if ($revnum) {
  232:                                     $message .= '; '.
  233:                                                 &Apache::lonlocal::mt('(expected rev: [_1])',
  234:                                                                       $revnum);
  235:                                 }
  236:                                 $message .= "\n";
  237:                             }
  238:                         }
  239:                         if ($target eq 'web') {
  240:                             $message .= &Apache::loncommon::end_data_table().'<br />';
  241:                         } else {
  242:                             $message .= "\n";
  243:                         }
  244:                     }
  245:                     if (@modified > 0) {
  246:                         my $text =
  247:                             &Apache::lonlocal::mt('The following [quant,_1,file appears,files appear]'.
  248:                                                   ' to have been modified locally:',scalar(@modified));
  249:                         if ($target eq 'web') {
  250:                             $message .= '<p>'.$text.'</p>'.
  251:                                         &Apache::loncommon::start_data_table().
  252:                                         &Apache::loncommon::start_data_table_header_row()."\n".
  253:                                         '<th>'.&Apache::lonlocal::mt('File').'</th>'."\n".
  254:                                         '<th>'.&Apache::lonlocal::mt('Version').'</th>'."\n".
  255:                                         &Apache::loncommon::end_data_table_header_row()."\n";
  256:                         } else {
  257:                             $message .= "$text\n";
  258:                         }
  259:                         foreach my $file (sort(@modified)) {
  260:                             if ($target eq 'web') {
  261:                                 $message .= &Apache::loncommon::start_data_table_row()."\n".
  262:                                             '<td>'.$file.'</td>'."\n".
  263:                                             '<td>'.$serverversions->{$file}.'</td>'."\n".
  264:                                             &Apache::loncommon::end_data_table_row()."\n";
  265:                             } else {
  266:                                 $message .= $file.' '.
  267:                                             &Apache::lonlocal::mt('(local rev: [_1])',
  268:                                                                   $serverversions->{$file}).
  269:                                             "\n";
  270:                             }
  271:                         }
  272:                         if ($target eq 'web') {
  273:                             $message .= &Apache::loncommon::end_data_table().'<br />';
  274:                         } else {
  275:                             $message .= "\n";
  276:                         }
  277:                     }
  278:                 }
  279:                 if (keys(%missing) > 0) {
  280:                     my $text = 
  281:                         &Apache::lonlocal::mt('The following [quant,_1,local file appears,local files appear]'.
  282:                                               ' to be missing:',scalar(keys(%missing))); 
  283:                     if ($target eq 'web') {
  284:                         $message .= '<p>'.$text.'</p>'.
  285:                                     &Apache::loncommon::start_data_table().
  286:                                     &Apache::loncommon::start_data_table_header_row()."\n".
  287:                                     '<th>'.&Apache::lonlocal::mt('File').'</th>'."\n".
  288:                                     '<th>'.&Apache::lonlocal::mt('Expected version').'</th>'."\n".
  289:                                     &Apache::loncommon::end_data_table_header_row()."\n";
  290:                     } else {
  291:                         $message .= "$text\n";
  292:                     }
  293:                     foreach my $file (sort(keys(%missing))) {
  294:                         my $revnum = $stdversions{$file};
  295:                         if ($target eq 'web') {
  296:                             $message .= &Apache::loncommon::start_data_table_row()."\n".
  297:                                         '<td>'.$file.'</td>'."\n".
  298:                                         '<td>'.$revnum.'</td>'."\n".
  299:                                         &Apache::loncommon::end_data_table_row()."\n";
  300:                         } else {
  301:                             $message .= $file;
  302:                             if ($revnum) {
  303:                                 $message .= ' '.
  304:                                             &Apache::lonlocal::mt('(expected rev: [_1])',
  305:                                                                   $revnum);
  306:                             }
  307:                             $message .= "\n";
  308:                         }
  309:                     }
  310:                     if ($target eq 'web') {
  311:                         $message .= &Apache::loncommon::end_data_table();
  312:                     } else {
  313:                         $message .= "\n";
  314:                     }
  315:                 }
  316:                 if (keys(%extra) > 0) {
  317:                     my $text = 
  318:                         &Apache::lonlocal::mt('The following [quant,_1,file is,files are]'.
  319:                                               ' not required by the release you have installed:',
  320:                                               scalar(keys(%extra)));
  321:                     if ($target eq 'web') {
  322:                         $message .= '<p>'.$text.'</p>'.
  323:                                     &Apache::loncommon::start_data_table().
  324:                                     &Apache::loncommon::start_data_table_header_row()."\n".
  325:                                     '<th>'.&Apache::lonlocal::mt('File').'</th>'."\n".
  326:                                     '<th>'.&Apache::lonlocal::mt('Version').'</th>'."\n".
  327:                                     &Apache::loncommon::end_data_table_header_row()."\n";
  328:                     } else {
  329:                         $message .= "$text\n";
  330:                     }
  331:                     foreach my $file (sort(keys(%extra))) {
  332:                         if ($target eq 'web') {
  333:                             $message .= &Apache::loncommon::start_data_table_row()."\n".
  334:                                         '<td>'.$file.'</td>'."\n".
  335:                                         '<td>'.$serverversions->{$file}.'</td>'."\n".
  336:                                         &Apache::loncommon::end_data_table_row()."\n";
  337:                         } else {
  338:                             $message .= $file.' '.
  339:                                         &Apache::lonlocal::mt('(local rev: [_1])',
  340:                                                               $serverversions->{$file}).
  341:                                         "\n";
  342:                         }
  343:                     }
  344:                     if ($target eq 'web') {
  345:                         $message .= &Apache::loncommon::end_data_table().'<br />';
  346:                     } else {
  347:                         $message .= "\n";
  348:                     }
  349:                 }
  350:             } else {
  351:                 $message = &Apache::lonlocal::mt('No differences detected between installed files and files expected for LON-CAPA [_1]',$version);
  352:             }
  353:         } else {
  354:             $message = &Apache::lonlocal::mt('No comparison attempted - failed to retrieve checksums for installed files.');
  355:         }
  356:     } else {
  357:         $message = &Apache::lonlocal::mt('No comparison attempted - failed to retrieve checksums for installed files.');
  358:     }
  359:     unless ($message) {
  360:         $message = &Apache::lonlocal::mt('LON-CAPA module check found no file changes.')."\n";
  361:     }
  362:     return ($message,$numchg);
  363: }
  364: 
  365: 1;
  366: 

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