| 1 | ################################################################################ |
1 | ################################################################################ |
| 2 | # WeBWorK Online Homework Delivery System |
2 | # WeBWorK Online Homework Delivery System |
| 3 | # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/ |
3 | # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/ |
| 4 | # $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm,v 1.32 2004/05/24 15:32:11 mschmitt Exp $ |
4 | # $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm,v 1.33 2004/05/24 18:05:26 mschmitt Exp $ |
| 5 | # |
5 | # |
| 6 | # This program is free software; you can redistribute it and/or modify it under |
6 | # This program is free software; you can redistribute it and/or modify it under |
| 7 | # the terms of either: (a) the GNU General Public License as published by the |
7 | # the terms of either: (a) the GNU General Public License as published by the |
| 8 | # Free Software Foundation; either version 2, or (at your option) any later |
8 | # Free Software Foundation; either version 2, or (at your option) any later |
| 9 | # version, or (b) the "Artistic License" which comes with this package. |
9 | # version, or (b) the "Artistic License" which comes with this package. |
| … | |
… | |
| 42 | |
42 | |
| 43 | my @selected_filters; |
43 | my @selected_filters; |
| 44 | if (defined ($r->param('classList!filter'))){ @selected_filters = $r->param('classList!filter');} |
44 | if (defined ($r->param('classList!filter'))){ @selected_filters = $r->param('classList!filter');} |
| 45 | else {@selected_filters = ("all");} |
45 | else {@selected_filters = ("all");} |
| 46 | |
46 | |
|
|
47 | |
|
|
48 | # Check permissions |
|
|
49 | return unless $authz->hasPermissions($user, "access_instructor_tools"); |
| 47 | unless ($authz->hasPermissions($user, "send_mail")) { |
50 | return unless $authz->hasPermissions($user, "send_mail"); |
| 48 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("You are not authorized to send mail to students."))); |
51 | |
| 49 | return; |
|
|
| 50 | } |
|
|
| 51 | ############################################################################################# |
52 | ############################################################################################# |
| 52 | # gather directory data |
53 | # gather directory data |
| 53 | ############################################################################################# |
54 | ############################################################################################# |
| 54 | my $emailDirectory = $ce->{courseDirs}->{email}; |
55 | my $emailDirectory = $ce->{courseDirs}->{email}; |
| 55 | my $scoringDirectory = $ce->{courseDirs}->{scoring}; |
56 | my $scoringDirectory = $ce->{courseDirs}->{scoring}; |
| … | |
… | |
| 172 | if ( defined($openfilename) ) { |
173 | if ( defined($openfilename) ) { |
| 173 | if ( -e "${emailDirectory}/$openfilename") { |
174 | if ( -e "${emailDirectory}/$openfilename") { |
| 174 | if ( -R "${emailDirectory}/$openfilename") { |
175 | if ( -R "${emailDirectory}/$openfilename") { |
| 175 | $input_file = $openfilename; |
176 | $input_file = $openfilename; |
| 176 | } else { |
177 | } else { |
| 177 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p(join("", |
178 | $self->addbadmessage(CGI::p(join("", |
| 178 | "The file ${emailDirectory}/$openfilename is not readable by the webserver.",CGI::br(), |
179 | "The file ${emailDirectory}/$openfilename is not readable by the webserver.",CGI::br(), |
| 179 | "Check that it's permissions are set correctly.", |
180 | "Check that it's permissions are set correctly.", |
| 180 | )))); |
181 | ))); |
| 181 | } |
182 | } |
| 182 | } else { |
183 | } else { |
| 183 | $input_file = $default_msg_file; |
184 | $input_file = $default_msg_file; |
| 184 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p(join("", |
185 | $self->addbadmessage(CGI::p(join("", |
| 185 | "The file ${emailDirectory}/$openfilename cannot be found.",CGI::br(), |
186 | "The file ${emailDirectory}/$openfilename cannot be found.",CGI::br(), |
| 186 | "Check whether it exists and whether the directory $emailDirectory can be read by the webserver.",CGI::br(), |
187 | "Check whether it exists and whether the directory $emailDirectory can be read by the webserver.",CGI::br(), |
| 187 | "Using contents of the default message $default_msg_file instead.", |
188 | "Using contents of the default message $default_msg_file instead.", |
| 188 | )))); |
189 | ))); |
| 189 | } |
190 | } |
| 190 | } else { |
191 | } else { |
| 191 | $input_file = $default_msg_file; |
192 | $input_file = $default_msg_file; |
| 192 | } |
193 | } |
| 193 | $self->{input_file} =$input_file; |
194 | $self->{input_file} =$input_file; |
| … | |
… | |
| 200 | $output_file = $default_msg_file; |
201 | $output_file = $default_msg_file; |
| 201 | } elsif ( defined($action) and ($action =~/save/i)) { |
202 | } elsif ( defined($action) and ($action =~/save/i)) { |
| 202 | if (defined($savefilename) and $savefilename ) { |
203 | if (defined($savefilename) and $savefilename ) { |
| 203 | $output_file = $savefilename; |
204 | $output_file = $savefilename; |
| 204 | } else { |
205 | } else { |
| 205 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("No filename was specified for saving! The message was not saved."))); |
206 | $self->addbadmessage(CGI::p("No filename was specified for saving! The message was not saved.")); |
| 206 | } |
207 | } |
| 207 | } elsif ( defined($input_file) ) { |
208 | } elsif ( defined($input_file) ) { |
| 208 | $output_file = $input_file; |
209 | $output_file = $input_file; |
| 209 | } |
210 | } |
| 210 | |
211 | |
| 211 | ################################################################# |
212 | ################################################################# |
| 212 | # Sanity check on save file name |
213 | # Sanity check on save file name |
| 213 | ################################################################# |
214 | ################################################################# |
| 214 | |
215 | |
| 215 | if ($output_file =~ /^[~.]/ || $output_file =~ /\.\./) { |
216 | if ($output_file =~ /^[~.]/ || $output_file =~ /\.\./) { |
| 216 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, |
|
|
| 217 | CGI::p("For security reasons, you cannot specify a message file from a directory", |
217 | $self->addbadmessage(CGI::p("For security reasons, you cannot specify a message file from a directory", |
| 218 | "higher than the email directory (you can't use ../blah/blah for example). ", |
218 | "higher than the email directory (you can't use ../blah/blah for example). ", |
| 219 | "Please specify a different file or move the needed file to the email directory",))); |
219 | "Please specify a different file or move the needed file to the email directory",)); |
| 220 | } |
220 | } |
| 221 | unless ($output_file =~ m|\.msg$| ) { |
221 | unless ($output_file =~ m|\.msg$| ) { |
| 222 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, |
222 | $self->addbadmessage(CGI::p("Invalid file name.", |
| 223 | CGI::p("Invalid file name.", |
|
|
| 224 | "The file name \"$output_file\" does not have a \".msg\" extension", |
223 | "The file name \"$output_file\" does not have a \".msg\" extension", |
| 225 | "All email file names must end in the extension \".msg\"", |
224 | "All email file names must end in the extension \".msg\"", |
| 226 | "choose a file name with a \".msg\" extension.", |
225 | "choose a file name with a \".msg\" extension.", |
| 227 | "The message was not saved.",))); |
226 | "The message was not saved.",)); |
| 228 | } |
227 | } |
| 229 | |
228 | |
| 230 | $self->{output_file} = $output_file; # this is ok. It will be put back in the text input box for re-editing. |
229 | $self->{output_file} = $output_file; # this is ok. It will be put back in the text input box for re-editing. |
| 231 | |
230 | |
| 232 | |
231 | |
| … | |
… | |
| 255 | $from = $r->param('from'); |
254 | $from = $r->param('from'); |
| 256 | $replyTo = $r->param('replyTo'); |
255 | $replyTo = $r->param('replyTo'); |
| 257 | $subject = $r->param('subject'); |
256 | $subject = $r->param('subject'); |
| 258 | my $body = $r->param('body'); |
257 | my $body = $r->param('body'); |
| 259 | # Sanity check: body must contain non-white space |
258 | # Sanity check: body must contain non-white space |
| 260 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p('You didn\'t enter any message.'))) unless ($r->param('body') =~ /\S/); |
259 | $self->addbadmessage(CGI::p('You didn\'t enter any message.')) unless ($r->param('body') =~ /\S/); |
| 261 | $r_text = \$body; |
260 | $r_text = \$body; |
| 262 | |
261 | |
| 263 | } |
262 | } |
| 264 | # store data |
263 | # store data |
| 265 | $self->{from} = $from; |
264 | $self->{from} = $from; |
| … | |
… | |
| 331 | # warn "FIXME from $from | subject $subject |reply $replyTo|msg $temp_body"; |
330 | # warn "FIXME from $from | subject $subject |reply $replyTo|msg $temp_body"; |
| 332 | ################################################################# |
331 | ################################################################# |
| 333 | # overwrite protection |
332 | # overwrite protection |
| 334 | ################################################################# |
333 | ################################################################# |
| 335 | if ($action eq 'Save as:' and -e "$emailDirectory/$output_file") { |
334 | if ($action eq 'Save as:' and -e "$emailDirectory/$output_file") { |
| 336 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, |
|
|
| 337 | CGI::p("The file $emailDirectory/$output_file already exists and cannot be overwritten", |
335 | $self->addbadmessage(CGI::p("The file $emailDirectory/$output_file already exists and cannot be overwritten", |
| 338 | "The message was not saved"))); |
336 | "The message was not saved")); |
| 339 | return; |
337 | return; |
| 340 | } |
338 | } |
| 341 | |
339 | |
| 342 | ################################################################# |
340 | ################################################################# |
| 343 | # Back up existing file? |
341 | # Back up existing file? |
| 344 | ################################################################# |
342 | ################################################################# |
| 345 | if ($action eq 'Save as Default' and -e "$emailDirectory/$default_msg_file") { |
343 | if ($action eq 'Save as Default' and -e "$emailDirectory/$default_msg_file") { |
| 346 | rename("$emailDirectory/$default_msg_file","$emailDirectory/$old_default_msg_file") or |
344 | rename("$emailDirectory/$default_msg_file","$emailDirectory/$old_default_msg_file") or |
| 347 | die "Can't rename $emailDirectory/$default_msg_file to $emailDirectory/$old_default_msg_file ", |
345 | die "Can't rename $emailDirectory/$default_msg_file to $emailDirectory/$old_default_msg_file ", |
| 348 | "Check permissions for webserver on directory $emailDirectory. $!"; |
346 | "Check permissions for webserver on directory $emailDirectory. $!"; |
| 349 | $self->addmessage(CGI::div({class=>"ResultsWithoutError"}, CGI::p("Backup file <code>$emailDirectory/$old_default_msg_file</code> created.".CGI::br()))); |
347 | $self->addgoodmessage(CGI::p("Backup file <code>$emailDirectory/$old_default_msg_file</code> created." . CGI::br())); |
| 350 | } |
348 | } |
| 351 | ################################################################# |
349 | ################################################################# |
| 352 | # Save the message |
350 | # Save the message |
| 353 | ################################################################# |
351 | ################################################################# |
| 354 | $self->saveProblem($temp_body, "${emailDirectory}/$output_file" ) unless ($output_file =~ /^[~.]/ || $output_file =~ /\.\./ || not $output_file =~ m|\.msg$|); |
352 | $self->saveProblem($temp_body, "${emailDirectory}/$output_file" ) unless ($output_file =~ /^[~.]/ || $output_file =~ /\.\./ || not $output_file =~ m|\.msg$|); |
| 355 | unless ( $self->{submit_message} or not -w "${emailDirectory}/$output_file" ) { # if there are no errors report success |
353 | unless ( $self->{submit_message} or not -w "${emailDirectory}/$output_file" ) { # if there are no errors report success |
| 356 | $self->addmessage(CGI::div({class=>"ResultsWithoutError"}, CGI::p("Message saved to file <code>${emailDirectory}/$output_file</code>."))); |
354 | $self->addgoodmessage(CGI::p("Message saved to file <code>${emailDirectory}/$output_file</code>.")); |
| 357 | } |
355 | } |
| 358 | |
356 | |
| 359 | } elsif ($action eq 'Preview message') { |
357 | } elsif ($action eq 'Preview message') { |
| 360 | $self->{response} = 'preview'; |
358 | $self->{response} = 'preview'; |
| 361 | |
359 | |
| 362 | } elsif ($action eq 'Send Email') { |
360 | } elsif ($action eq 'Send Email') { |
| 363 | $self->{response} = 'send_email'; |
361 | $self->{response} = 'send_email'; |
| 364 | |
362 | |
| 365 | my @recipients = @{$self->{ra_send_to}}; |
363 | my @recipients = @{$self->{ra_send_to}}; |
| 366 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, |
|
|
| 367 | CGI::p("No recipients selected "))) unless @recipients; |
364 | $self->addbadmessage(CGI::p("No recipients selected ")) unless @recipients; |
| 368 | # get merge file |
365 | # get merge file |
| 369 | my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None'; |
366 | my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None'; |
| 370 | my $delimiter = ','; |
367 | my $delimiter = ','; |
| 371 | my $rh_merge_data = $self->read_scoring_file("$merge_file", "$delimiter"); |
368 | my $rh_merge_data = $self->read_scoring_file("$merge_file", "$delimiter"); |
| 372 | unless (ref($rh_merge_data) ) { |
369 | unless (ref($rh_merge_data) ) { |
| 373 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("No merge data file"))); |
370 | $self->addbadmessage(CGI::p("No merge data file")); |
| 374 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("Can't read merge file $merge_file. No message sent"))); |
371 | $self->addbadmessage(CGI::p("Can't read merge file $merge_file. No message sent")); |
| 375 | return; |
372 | return; |
| 376 | } ; |
373 | } ; |
| 377 | |
374 | |
| 378 | |
375 | |
| 379 | foreach my $recipient (@recipients) { |
376 | foreach my $recipient (@recipients) { |
| 380 | #warn "FIXME sending email to $recipient"; |
377 | #warn "FIXME sending email to $recipient"; |
| 381 | my $ur = $self->{db}->getUser($recipient); #checked |
378 | my $ur = $self->{db}->getUser($recipient); #checked |
| 382 | die "record for user $recipient not found" unless $ur; |
379 | die "record for user $recipient not found" unless $ur; |
| 383 | unless ($ur->email_address) { |
380 | unless ($ur->email_address) { |
| 384 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, |
|
|
| 385 | CGI::p("user $recipient does not have an email address -- skipping"))); |
381 | $self->addbadmessage(CGI::p("user $recipient does not have an email address -- skipping")); |
| 386 | next; |
382 | next; |
| 387 | } |
383 | } |
| 388 | my ($msg, $preview_header); |
384 | my ($msg, $preview_header); |
| 389 | eval{ ($msg,$preview_header) = $self->process_message($ur,$rh_merge_data); }; |
385 | eval{ ($msg,$preview_header) = $self->process_message($ur,$rh_merge_data); }; |
| 390 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("There were errors in processing user $ur, merge file $merge_file. $@"))) if $@; |
386 | $self->addbadmessage(CGI::p("There were errors in processing user $ur, merge file $merge_file. $@")) if $@; |
| 391 | my $mailer = Mail::Sender->new({ |
387 | my $mailer = Mail::Sender->new({ |
| 392 | from => $from, |
388 | from => $from, |
| 393 | to => $ur->email_address, |
389 | to => $ur->email_address, |
| 394 | smtp => $ce->{mail}->{smtpServer}, |
390 | smtp => $ce->{mail}->{smtpServer}, |
| 395 | subject => $subject, |
391 | subject => $subject, |
| 396 | headers => "X-Remote-Host: ".$r->get_remote_host(), |
392 | headers => "X-Remote-Host: ".$r->get_remote_host(), |
| 397 | }); |
393 | }); |
| 398 | unless (ref $mailer) { |
394 | unless (ref $mailer) { |
| 399 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("Failed to create a mailer for user $recipient: $Mail::Sender::Error"))); |
395 | $self->addbadmessage(CGI::p("Failed to create a mailer for user $recipient: $Mail::Sender::Error")); |
| 400 | next; |
396 | next; |
| 401 | } |
397 | } |
| 402 | unless (ref $mailer->Open()) { |
398 | unless (ref $mailer->Open()) { |
| 403 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("Failed to open the mailer for user $recipient: $Mail::Sender::Error"))); |
399 | $self->addbadmessage(CGI::p("Failed to open the mailer for user $recipient: $Mail::Sender::Error")); |
| 404 | next; |
400 | next; |
| 405 | } |
401 | } |
| 406 | my $MAIL = $mailer->GetHandle() or $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("Couldn't get handle"))); |
402 | my $MAIL = $mailer->GetHandle() or $self->addbadmessage(CGI::p("Couldn't get handle")); |
| 407 | print $MAIL $msg || $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("Couldn't print to $MAIL"))); |
403 | print $MAIL $msg || $self->addbadmessage(CGI::p("Couldn't print to $MAIL")); |
| 408 | close $MAIL || $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("Couldn't close $MAIL"))); |
404 | close $MAIL || $self->addbadmessage(CGI::p("Couldn't close $MAIL")); |
| 409 | #warn "FIXME mailed to ", $ur->email_address, "from $from subject $subject"; |
405 | #warn "FIXME mailed to ", $ur->email_address, "from $from subject $subject"; |
| 410 | |
406 | |
| 411 | } |
407 | } |
| 412 | |
408 | |
| 413 | } else { |
409 | } else { |
| 414 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("Didn't recognize button $action"))); |
410 | $self->addbadmessage(CGI::p("Didn't recognize button $action")); |
| 415 | } |
411 | } |
| 416 | |
412 | |
| 417 | |
413 | |
| 418 | |
414 | |
| 419 | } #end initialize |
415 | } #end initialize |
| … | |
… | |
| 424 | |
420 | |
| 425 | sub body { |
421 | sub body { |
| 426 | my ($self) = @_; |
422 | my ($self) = @_; |
| 427 | my $r = $self->r; |
423 | my $r = $self->r; |
| 428 | my $urlpath = $r->urlpath; |
424 | my $urlpath = $r->urlpath; |
|
|
425 | my $authz = $r->authz; |
| 429 | my $setID = $urlpath->arg("setID"); |
426 | my $setID = $urlpath->arg("setID"); |
| 430 | my $response = (defined($self->{response}))? $self->{response} : ''; |
427 | my $response = (defined($self->{response}))? $self->{response} : ''; |
|
|
428 | my $user = $r->param('user'); |
|
|
429 | |
|
|
430 | # Check permissions |
|
|
431 | return CGI::div({class=>"ResultsWithError"}, CGI::p("You are not authorized to access instructor tools")) |
|
|
432 | unless $authz->hasPermissions($user, "access_instructor_tools"); |
|
|
433 | |
|
|
434 | return CGI::div({class=>"ResultsWithError"}, CGI::p("You are not authorized to send mail to students")) |
|
|
435 | unless $authz->hasPermissions($user, "send_mail"); |
|
|
436 | |
| 431 | if ($response eq 'preview') { |
437 | if ($response eq 'preview') { |
| 432 | $self->print_preview($setID); |
438 | $self->print_preview($setID); |
| 433 | } elsif (($response eq 'send_email')){ |
439 | } elsif (($response eq 'send_email')){ |
| 434 | $self->addmessage(CGI::div({class=>"ResultsWithoutError"}, CGI::p("Email sent to ". scalar(@{$self->{ra_send_to}})." students."))); |
440 | $self->addgoodmessage(CGI::p("Email sent to ". scalar(@{$self->{ra_send_to}})." students.")); |
| 435 | $self->{message} .= CGI::i("Email sent to ". scalar(@{$self->{ra_send_to}})." students."); |
441 | $self->{message} .= CGI::i("Email sent to ". scalar(@{$self->{ra_send_to}})." students."); |
| 436 | $self->print_form($setID); |
442 | $self->print_form($setID); |
| 437 | } else { |
443 | } else { |
| 438 | $self->print_form($setID); |
444 | $self->print_form($setID); |
| 439 | } |
445 | } |
| … | |
… | |
| 716 | sub saveProblem { |
722 | sub saveProblem { |
| 717 | my $self = shift; |
723 | my $self = shift; |
| 718 | my ($body, $probFileName)= @_; |
724 | my ($body, $probFileName)= @_; |
| 719 | local(*PROBLEM); |
725 | local(*PROBLEM); |
| 720 | open (PROBLEM, ">$probFileName") || |
726 | open (PROBLEM, ">$probFileName") || |
| 721 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, |
|
|
| 722 | CGI::p("Could not open $probFileName for writing. |
727 | $self->addbadmessage(CGI::p("Could not open $probFileName for writing. |
| 723 | Check that the permissions for this problem are 660 (-rw-rw----)"))); |
728 | Check that the permissions for this problem are 660 (-rw-rw----)")); |
| 724 | print PROBLEM $body if -w $probFileName; |
729 | print PROBLEM $body if -w $probFileName; |
| 725 | close PROBLEM; |
730 | close PROBLEM; |
| 726 | chmod 0660, "$probFileName" || |
731 | chmod 0660, "$probFileName" || |
| 727 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, |
|
|
| 728 | CGI::p(" |
|
|
| 729 | CAN'T CHANGE PERMISSIONS ON FILE $probFileName"))); |
732 | $self->addbadmessage(CGI::p("CAN'T CHANGE PERMISSIONS ON FILE $probFileName")); |
| 730 | } |
733 | } |
| 731 | |
734 | |
| 732 | sub read_input_file { |
735 | sub read_input_file { |
| 733 | my $self = shift; |
736 | my $self = shift; |
| 734 | my $filePath = shift; |
737 | my $filePath = shift; |
| 735 | my ($text, @text); |
738 | my ($text, @text); |
| 736 | my $header = ''; |
739 | my $header = ''; |
| 737 | my ($subject, $from, $replyTo); |
740 | my ($subject, $from, $replyTo); |
| 738 | local(*FILE); |
741 | local(*FILE); |
| 739 | if (-e "$filePath" and -r "$filePath") { |
742 | if (-e "$filePath" and -r "$filePath") { |
| 740 | open FILE, "$filePath" || do { $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("Can't open $filePath"))); return}; |
743 | open FILE, "$filePath" || do { $self->addbadmessage(CGI::p("Can't open $filePath")); return}; |
| 741 | while ($header !~ s/Message:\s*$//m and not eof(FILE)) { |
744 | while ($header !~ s/Message:\s*$//m and not eof(FILE)) { |
| 742 | $header .= <FILE>; |
745 | $header .= <FILE>; |
| 743 | } |
746 | } |
| 744 | $text = join( '', <FILE>); |
747 | $text = join( '', <FILE>); |
| 745 | $text =~ s/^\s*//; # remove initial white space if any. |
748 | $text =~ s/^\s*//; # remove initial white space if any. |
| … | |
… | |
| 811 | |
814 | |
| 812 | # get record from merge file |
815 | # get record from merge file |
| 813 | # FIXME this is inefficient. The info should be cached |
816 | # FIXME this is inefficient. The info should be cached |
| 814 | my @COL = defined($rh_merge_data->{$SID}) ? @{$rh_merge_data->{$SID} } : (); |
817 | my @COL = defined($rh_merge_data->{$SID}) ? @{$rh_merge_data->{$SID} } : (); |
| 815 | if ($merge_file ne 'None' && not defined($rh_merge_data->{$SID}) ) { |
818 | if ($merge_file ne 'None' && not defined($rh_merge_data->{$SID}) ) { |
| 816 | $self->addmessage(CGI::div({class=>"ResultsWithError"}, CGI::p("No merge data for student id:$SID; name:$FN $LN; login:$LOGIN"))); |
819 | $self->addbadmessage(CGI::p("No merge data for student id:$SID; name:$FN $LN; login:$LOGIN")); |
| 817 | } |
820 | } |
| 818 | |
821 | |
| 819 | my $endCol = @COL; |
822 | my $endCol = @COL; |
| 820 | # for safety, only evaluate special variables |
823 | # for safety, only evaluate special variables |
| 821 | my $msg = $text; |
824 | my $msg = $text; |