Annotation of loncom/configuration/Checksumming.pm, revision 1.5
1.1 raeburn 1: # The LearningOnline Network with CAPA
2: # Checksum installed LON-CAPA modules and some configuration files
3: #
1.5 ! raeburn 4: # $Id: Checksumming.pm,v 1.4 2013/02/06 13:47:47 raeburn Exp $
1.1 raeburn 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:
38: sub get_checksums {
39: my ($distro,$londaemons,$lonlib,$lonincludes,$lontabdir) = @_;
40: my $output;
41: my (%versions,%chksums);
42: my $dirh;
43: my $revtag = '$Id:';
44: my @paths;
45: if ($londaemons) {
46: push(@paths,($londaemons.'/*',
47: $londaemons.'/debug/*.pl'));
48: }
49: if ($lonlib) {
50: push(@paths,($lonlib.'/perl/Apache/*.pm',
51: $lonlib.'/perl/Apache/localize/*.pm',
52: $lonlib.'/perl/LONCAPA/*.pm',
53: $lonlib.'/perl/AlgParser.pm',
54: $lonlib.'/perl/LONCAPA.pm',
55: $lonlib.'/perl/Safe.pm',
56: $lonlib.'/perl/*-std.pm',
57: $lonlib.'/perl/HTML/*.pm',
58: $lonlib.'/perl/Safe.pm'));
59: }
60: if ($lonincludes) {
61: push(@paths,$lonincludes.'/*.lcpm');
62: }
63: push(@paths,('/home/httpd/cgi-bin/*.pl','/home/httpd/cgi-bin/*.png'));
64: my $confdir = '/etc/httpd/conf';
65: my $sha = 'SHA1';
66: if ($distro =~ /^(ubuntu|debian)(\d+)$/) {
67: $confdir = '/etc/apache2';
68: if (($1 eq 'ubuntu') && ($2 >= 12)) {
69: $sha = 'SHA';
70: }
71: } elsif ($distro =~ /^sles(\d+)$/) {
72: if ($1 >= 10) {
73: $confdir = '/etc/apache2';
74: }
75: } elsif ($distro =~ /^suse(\d+\.\d+)$/) {
76: if ($1 >= 10.0) {
77: $confdir = '/etc/apache2';
78: }
79: }
80: push(@paths,("$confdir/loncapa_apache.conf","$confdir/startup.pl"));
81: if ($sha eq 'SHA1') {
82: require Digest::SHA1;
83: } else {
84: require Digest::SHA;
85: }
86: if (@paths) {
87: my $pathstr = join (' ',@paths);
1.5 ! raeburn 88: if (open($dirh,"grep '$revtag' $pathstr 2>&1 |")) {
1.1 raeburn 89: while (my $line=<$dirh>) {
90: if ($line =~ m{^([^#]+):#\s\$Id:\s[\w.]+,v\s([\d.]+)\s}) {
91: $versions{$1} = $2;
92: }
93: }
94: close($dirh);
95: }
96: foreach my $key (sort(keys(%versions))) {
97: next if ($key =~ /\.lpmlsave$/);
98: my $sum;
99: if (open(my $fh,"<$key")) {
100: binmode $fh;
101: my $sha_obj;
102: if ($sha eq 'SHA') {
103: $sha_obj = Digest::SHA->new();
104: } else {
105: $sha_obj = Digest::SHA1->new();
106: }
107: $sha_obj->addfile($fh);
108: $sum = $sha_obj->hexdigest;
109: close($fh);
110: $chksums{$key} = $sum;
111: }
112: $output .= "$key,$versions{$key},$sum\n";
113: }
114: }
115: if ($lontabdir ne '') {
116: if (open(my $tabfh,">$lontabdir/lonchksums.tab")) {
117: print $tabfh '# Last written: '.localtime(time)."\n";
118: print $tabfh "$output\n";
119: close($tabfh);
120: }
121: }
122: return (\%chksums,\%versions);
123: }
124:
125: sub compare_checksums {
126: my ($target,$lonhost,$version,$serversums,$serverversions) = @_;
1.2 raeburn 127: my ($message,$numchg,$linefeed);
1.3 raeburn 128: if ($target eq 'web') {
1.2 raeburn 129: $linefeed = '<br />';
130: } else {
131: $linefeed = "\n";
132: }
1.5 ! raeburn 133: if (!$Apache::lonlocal::lh) {
! 134: &Apache::lonlocal::get_language_handle();
! 135: }
1.1 raeburn 136: if ((ref($serversums) eq 'HASH') && (keys(%{$serversums}))) {
137: my $checksums = &Apache::lonnet::fetch_dns_checksums();
138: my (%extra,%missing,%diffs,%stdsums,%stdversions);
139: if (ref($checksums) eq 'HASH') {
140: if (ref($checksums->{'sums'}) eq 'HASH') {
141: %stdsums = %{$checksums->{'sums'}};
142: }
143: if (ref($checksums->{'versions'}) eq 'HASH') {
144: %stdversions = %{$checksums->{'versions'}};
145: }
146: if (keys(%stdsums)) {
147: foreach my $key (keys(%stdsums)) {
148: if (exists($serversums->{$key})) {
149: if ($serversums->{$key} ne $stdsums{$key}) {
150: $diffs{$key} = 1;
151: $numchg ++;
152: }
153: } else {
1.4 raeburn 154: unless ((-e $key) && (-B $key)) {
155: $missing{$key} = 1;
156: $numchg ++;
157: }
1.1 raeburn 158: }
159: }
160: foreach my $key (keys(%{$serversums})) {
161: unless (exists($stdsums{$key})) {
162: $extra{$key} = 1;
163: $numchg ++;
164: }
165: }
166: }
167: if ($numchg) {
1.2 raeburn 168: $message =
1.1 raeburn 169: &Apache::lonlocal::mt('[quant,_1,difference was,differences were] found'.
1.2 raeburn 170: ' between LON-CAPA modules installed on your server [_2]'.
171: ' and those expected for the LON-CAPA version you are'.
172: ' currently running.',$numchg,"($lonhost)$linefeed");
1.1 raeburn 173: if ($target eq 'web') {
174: $message = '<p>'.$message.'</p>';
175: } else {
176: $message .= "\n\n";
177: }
178: my (@diffversion,@modified);
179: if (keys(%diffs) > 0) {
180: foreach my $file (sort(keys(%diffs))) {
181: if ($serverversions->{$file} ne $stdversions{$file}) {
182: push(@diffversion,$file);
183: } else {
184: push(@modified,$file);
185: }
186: }
187: if (@diffversion > 0) {
1.2 raeburn 188: my $text =
189: &Apache::lonlocal::mt('The following [quant,_1,file is a,files are]'.
1.1 raeburn 190: ' different version(s) from that expected for LON-CAPA [_2]:',
191: scalar(@diffversion),$version);
192: if ($target eq 'web') {
193: $message .= '<p>'.$text.'</p>'.
194: &Apache::loncommon::start_data_table().
195: &Apache::loncommon::start_data_table_header_row()."\n".
196: '<th>'.&Apache::lonlocal::mt('File').'</th>'."\n".
197: '<th>'.&Apache::lonlocal::mt('Server version').'</th>'."\n".
198: '<th>'.&Apache::lonlocal::mt('Expected version').'</th>'."\n".
199: &Apache::loncommon::end_data_table_header_row()."\n";
200: } else {
201: $message .= "$text\n";
202: }
203: foreach my $file (sort(@diffversion)) {
204: my $revnum = $stdversions{$file};
205: if ($target eq 'web') {
206: $message .= &Apache::loncommon::start_data_table_row().
1.2 raeburn 207: '<td>'.$file.'</td>'."\n".
1.1 raeburn 208: '<td>'.$serverversions->{$file}.'</td>'."\n".
209: '<td>'.$revnum.'</td>'."\n".
210: &Apache::loncommon::end_data_table_row()."\n";
211: } else {
212: $message .= $file.' '.
213: &Apache::lonlocal::mt('(local rev: [_1])',
214: $serverversions->{$file});
215: if ($revnum) {
216: $message .= '; '.
217: &Apache::lonlocal::mt('(expected rev: [_1])',
218: $revnum);
219: }
220: $message .= "\n";
221: }
222: }
1.2 raeburn 223: if ($target eq 'web') {
224: $message .= &Apache::loncommon::end_data_table().'<br />';
225: } else {
226: $message .= "\n";
227: }
1.1 raeburn 228: }
229: if (@modified > 0) {
1.2 raeburn 230: my $text =
1.1 raeburn 231: &Apache::lonlocal::mt('The following [quant,_1,file appears,files appear]'.
232: ' to have been modified locally:',scalar(@modified));
233: if ($target eq 'web') {
234: $message .= '<p>'.$text.'</p>'.
235: &Apache::loncommon::start_data_table().
236: &Apache::loncommon::start_data_table_header_row()."\n".
237: '<th>'.&Apache::lonlocal::mt('File').'</th>'."\n".
238: '<th>'.&Apache::lonlocal::mt('Version').'</th>'."\n".
239: &Apache::loncommon::end_data_table_header_row()."\n";
240: } else {
241: $message .= "$text\n";
242: }
243: foreach my $file (sort(@modified)) {
244: if ($target eq 'web') {
245: $message .= &Apache::loncommon::start_data_table_row()."\n".
246: '<td>'.$file.'</td>'."\n".
247: '<td>'.$serverversions->{$file}.'</td>'."\n".
248: &Apache::loncommon::end_data_table_row()."\n";
249: } else {
250: $message .= $file.' '.
251: &Apache::lonlocal::mt('(local rev: [_1])',
252: $serverversions->{$file}).
253: "\n";
254: }
255: }
1.2 raeburn 256: if ($target eq 'web') {
257: $message .= &Apache::loncommon::end_data_table().'<br />';
258: } else {
259: $message .= "\n";
260: }
1.1 raeburn 261: }
262: }
263: if (keys(%missing) > 0) {
264: my $text =
265: &Apache::lonlocal::mt('The following [quant,_1,local file appears,local files appear]'.
266: ' to be missing:',scalar(keys(%missing)));
267: if ($target eq 'web') {
268: $message .= '<p>'.$text.'</p>'.
269: &Apache::loncommon::start_data_table().
270: &Apache::loncommon::start_data_table_header_row()."\n".
271: '<th>'.&Apache::lonlocal::mt('File').'</th>'."\n".
272: '<th>'.&Apache::lonlocal::mt('Expected version').'</th>'."\n".
273: &Apache::loncommon::end_data_table_header_row()."\n";
274: } else {
275: $message .= "$text\n";
276: }
277: foreach my $file (sort(keys(%missing))) {
278: my $revnum = $stdversions{$file};
279: if ($target eq 'web') {
1.2 raeburn 280: $message .= '<td>'.$file.'</td>'."\n".
1.1 raeburn 281: '<td>'.$revnum.'</td>'."\n".
282: &Apache::loncommon::end_data_table_row()."\n";
283: } else {
284: $message .= $file;
285: if ($revnum) {
286: $message .= ' '.
287: &Apache::lonlocal::mt('(expected rev: [_1])',
288: $revnum);
289: }
290: $message .= "\n";
291: }
292: }
1.2 raeburn 293: if ($target eq 'web') {
294: $message .= &Apache::loncommon::end_data_table();
295: } else {
296: $message .= "\n";
297: }
1.1 raeburn 298: }
299: if (keys(%extra) > 0) {
300: my $text =
301: &Apache::lonlocal::mt('The following [quant,_1,file is,files are]'.
302: ' not required by the release you have installed:',
303: scalar(keys(%extra)));
304: if ($target eq 'web') {
305: $message .= '<p>'.$text.'</p>'.
306: &Apache::loncommon::start_data_table().
307: &Apache::loncommon::start_data_table_header_row()."\n".
308: '<th>'.&Apache::lonlocal::mt('File').'</th>'."\n".
309: '<th>'.&Apache::lonlocal::mt('Version').'</th>'."\n".
310: &Apache::loncommon::end_data_table_header_row()."\n";
311: } else {
312: $message .= "$text\n";
313: }
314: foreach my $file (sort(keys(%extra))) {
315: if ($target eq 'web') {
1.2 raeburn 316: $message .= '<td>'.$file.'</td>'."\n".
1.1 raeburn 317: '<td>'.$serverversions->{$file}.'</td>'."\n".
318: &Apache::loncommon::end_data_table_row()."\n";
319: } else {
320: $message .= $file.' '.
321: &Apache::lonlocal::mt('(local rev: [_1])',
322: $serverversions->{$file}).
323: "\n";
324: }
325: }
1.2 raeburn 326: if ($target eq 'web') {
327: $message .= &Apache::loncommon::end_data_table().'<br />';
328: } else {
329: $message .= "\n";
330: }
1.1 raeburn 331: }
332: } else {
333: $message = &Apache::lonlocal::mt('No differences detected between installed files and files expected for LON-CAPA [_1]',$version);
334: }
335: } else {
336: $message = &Apache::lonlocal::mt('No comparison attempted - failed to retrieve checksums for installed files.');
337: }
338: } else {
339: $message = &Apache::lonlocal::mt('No comparison attempted - failed to retrieve checksums for installed files.');
340: }
341: unless ($message) {
342: $message = &Apache::lonlocal::mt('LON-CAPA module check found no file changes.')."\n";
343: }
344: return ($message,$numchg);
345: }
346:
347: 1;
348:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>