[system] / branches / rel-2-3-dev / webwork-modperl / lib / WeBWorK / ContentGenerator / Instructor / SendMail.pm Repository:
ViewVC logotype

Annotation of /branches/rel-2-3-dev/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1381 - (view) (download) (as text)
Original Path: trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm

1 : gage 1368 package WeBWorK::ContentGenerator::Instructor::SendMail;
2 :     use base qw(WeBWorK::ContentGenerator::Instructor);
3 :    
4 :     =head1 NAME
5 :    
6 :     WeBWorK::ContentGenerator::Instructor::SendMail - Entry point for User-specific data editing
7 :    
8 :     =cut
9 :    
10 :     use strict;
11 :     use warnings;
12 :     use CGI qw();
13 : gage 1370 use HTML::Entities;
14 : gage 1373 use Mail::Sender;
15 : gage 1368
16 :     sub initialize {
17 :     my ($self) = @_;
18 :     my $r = $self->{r};
19 :     my $db = $self->{db};
20 :     my $ce = $self->{ce};
21 :     my $authz = $self->{authz};
22 :     my $user = $r->param('user');
23 :    
24 :     unless ($authz->hasPermissions($user, "send_mail")) {
25 :     $self->{submitError} = "You are not authorized to send mail to students.";
26 :     return;
27 :     }
28 : gage 1369 #############################################################################################
29 :     # gather directory data
30 :     #############################################################################################
31 :     my $emailDirectory = $ce->{courseDirs}->{email};
32 :     my $scoringDirectory = $ce->{courseDirs}->{scoring};
33 :     my $templateDirectory = $ce->{courseDirs}->{templates};
34 : gage 1368
35 : gage 1369 my $action = $r->param('action');
36 :     my $openfilename = $r->param('openfilename');
37 :     my $savefilename = $r->param('savefilename');
38 : gage 1370
39 :    
40 :     #FIXME get these values from global course environment (see subroutines as well)
41 :     my $default_msg_file = 'default.msg';
42 :     my $old_default_msg_file = 'old_default.msg';
43 :    
44 : gage 1372
45 : gage 1370 # store data
46 :     $self->{defaultFrom} = 'FIXME from';
47 :     $self->{defaultReply} = 'FIXME reply';
48 :     $self->{rows} = (defined($r->param('rows'))) ? $r->param('rows') : $ce->{mail}->{editor_window_rows};
49 :     $self->{columns} = (defined($r->param('columns'))) ? $r->param('columns') : $ce->{mail}->{editor_window_columns};
50 :     $self->{default_msg_file} = $default_msg_file;
51 :     $self->{old_default_msg_file} = $old_default_msg_file;
52 : gage 1372 $self->{merge_file} = (defined($r->param('merge_file' ))) ? $r->param('merge_file') : 'None';
53 : gage 1376 $self->{preview_user} = (defined($r->param('preview_user'))) ? $r->param('preview_user') : $user;
54 : gage 1372
55 :    
56 :     #############################################################################################
57 :     # gather database data
58 :     #############################################################################################
59 :     # FIXME this might be better done in body? We don't always need all of this data. or do we?
60 :     my @users = sort $db->listUsers;
61 :     my @user_records = ();
62 :     push(@user_records,$db->getUser($_)) foreach (@users);
63 :    
64 :     # store data
65 :     $self->{ra_users} = \@users;
66 :     $self->{ra_user_records} = \@user_records;
67 :    
68 :     #############################################################################################
69 :     # gather list of recipients
70 :     #############################################################################################
71 :     my @send_to = ();
72 :     #FIXME this (radio) is a lousy name
73 :     my $recipients = $r->param('radio');
74 : gage 1375 if (defined($recipients) and $recipients eq 'all_students') { #only active students #FIXME status check??
75 : gage 1372 foreach my $ur (@user_records) {
76 :     push(@send_to,$ur->user_id) if $ur->status eq 'C' and not($ur->user_id =~ /practice/);
77 :     }
78 : gage 1375 } elsif (defined($recipients) and $recipients eq 'studentID' ) {
79 : gage 1372 @send_to = $r->param('classList');
80 :     } else {
81 : gage 1375 # no recipients have been defined -- probably the first time on the page
82 : gage 1372 }
83 :     $self->{ra_send_to} = \@send_to;
84 : gage 1370 #################################################################
85 :     # Check the validity of the input file name
86 :     #################################################################
87 :     my $input_file = '';
88 :     #make sure an input message file was submitted and exists
89 :     #else use the default message
90 :     if ( defined($openfilename) ) {
91 :     if ( -e "${emailDirectory}/$openfilename") {
92 :     if ( -R "${emailDirectory}/$openfilename") {
93 :     $input_file = $openfilename;
94 : gage 1369 } else {
95 : gage 1370 warn join("",
96 :     "The file ${emailDirectory}/$openfilename is not readable by the webserver.",CGI::br(),
97 :     "Check that it's permissions are set correctly.",
98 :     );
99 : gage 1369 }
100 :     } else {
101 : gage 1370 $input_file = $default_msg_file;
102 :     warn join("",
103 :     "The file ${emailDirectory}/$openfilename cannot be found.",CGI::br(),
104 :     "Check whether it exists and whether the directory $emailDirectory can be read by the webserver.",CGI::br(),
105 :     "Using contents of the default message $default_msg_file instead.",
106 :     );
107 : gage 1369 }
108 : gage 1370 } else {
109 : gage 1372 $input_file = $default_msg_file;
110 : gage 1370 }
111 : gage 1372 $self->{input_file} =$input_file;
112 : gage 1370
113 :     #################################################################
114 :     # Determine the file name to save message into
115 :     #################################################################
116 : gage 1371 my $output_file = 'FIXME no output file specified';
117 : gage 1370 if (defined($action) and $action eq 'Save as Default') {
118 :     $output_file = $default_msg_file;
119 : gage 1371 } elsif ( defined($action) and ($action =~/save/i) and defined($savefilename) ){
120 : gage 1370 $output_file = $savefilename;
121 :     } elsif ( defined($input_file) ) {
122 :     $output_file = $input_file;
123 :     }
124 : gage 1371 # warn "FIXME savefilename $savefilename output file $output_file";
125 : gage 1370 #################################################################
126 :     # Sanity check on save file name
127 :     #################################################################
128 :    
129 :     if ($output_file =~ /^[~.]/ || $output_file =~ /\.\./) {
130 : gage 1371 $self->submission_error("For security reasons, you cannot specify a merge file from a directory",
131 :     "higher than the email directory (you can't use ../blah/blah). ",
132 :     "Please specify a different file or move the needed file to the email directory",
133 :     );
134 : gage 1370 }
135 : gage 1371 unless ($output_file =~ m|\.msg$| ) {
136 :     $self->submission_error("Invalid file name.",
137 :     "The file name \"$output_file\" does not have a \".msg\" extension",
138 :     "All email file names must end in the extension \".msg\"",
139 :     "choose a file name with a \".msg\" extension.",
140 :     "The message was not saved.",
141 :     );
142 :     }
143 :     $self->{output_file} = $output_file; # this is ok. It will be put back in the text input box for re-editing.
144 : gage 1370 # FIXME $output_file can be blank if there was no savefilename
145 :    
146 :     #############################################################################################
147 :     # Determine input source
148 :     #############################################################################################
149 :     my $input_source = ( defined( $r->param('body') ) and $action ne 'Open' ) ? 'form' : 'file';
150 :     # warn "FIXME input source is $input_source from $input_file";
151 :     #############################################################################################
152 :     # Get inputs
153 :     #############################################################################################
154 :     my($from, $replyTo, $r_text, $subject);
155 :     if ($input_source eq 'file') {
156 : gage 1371 # warn "FIXME obtaining source from $emailDirectory/$input_file";
157 : gage 1370 ($from, $replyTo,$subject,$r_text) = $self->read_input_file("$emailDirectory/$input_file");
158 : gage 1371 # warn "FIXME Done reading source";
159 : gage 1370
160 :     } elsif ($input_source eq 'form') {
161 :     # read info from the form
162 :     # bail if there is no message body
163 : gage 1369
164 : gage 1370 $from = $r->param('from');
165 :     $replyTo = $r->param('replyTo');
166 :     $subject = $r->param('subject');
167 :     my $body = $r->param('body');
168 :     # Sanity check: body must contain non-white space
169 :     $self->submission_error('You didn\'t enter any message.') unless ($r->param('body') =~ /\S/);
170 :     $r_text = \$body;
171 : gage 1369
172 : gage 1370 }
173 :     # store data
174 :     $self->{from} = $from;
175 :     $self->{replyTo} = $replyTo;
176 :     $self->{subject} = $subject;
177 :     $self->{r_text} = $r_text;
178 :    
179 :    
180 : gage 1372
181 :     ###################################################################################
182 :     #Determine the appropriate script action from the buttons
183 :     ###################################################################################
184 :     # first time actions
185 :     # open new file
186 :     # open default file
187 :     # choose merge file actions
188 :     # chose merge button
189 :     # option actions
190 :     # 'reset rows'
191 :    
192 :     # save actions
193 :     # "save" button
194 :     # "save as" button
195 :     # "save as default" button
196 :     # preview actions
197 :     # 'preview' button
198 :     # email actions
199 :     # 'entire class'
200 :     # 'selected studentIDs'
201 :     # error actions (various)
202 :    
203 :    
204 : gage 1369 #############################################################################################
205 : gage 1370 # if no form is submitted, gather data needed to produce the mail form and return
206 : gage 1369 #############################################################################################
207 : gage 1372 my $to = $r->param('To');
208 :     my $script_action = '';
209 :    
210 :    
211 : gage 1371 if(not defined($action) or $action eq 'Open' or $action eq 'Resize message window'
212 : gage 1375 or $action eq 'Set merge file to:' ){
213 : gage 1370 # warn "FIXME action is |$action| no further initialization required";
214 : gage 1369 return '';
215 :     }
216 :    
217 :    
218 :    
219 :    
220 :    
221 :     #############################################################################################
222 : gage 1370 # If form is submitted deal with filled out forms
223 : gage 1369 # and various actions resulting from different buttons
224 :     #############################################################################################
225 :    
226 : gage 1372
227 : gage 1370 if ($action eq 'Save' or $action eq 'Save as:' or $action eq 'Save as Default') {
228 :    
229 :     # warn "FIXME Saving files action = $action outputFileName=$output_file";
230 : gage 1369
231 : gage 1370 #################################################################
232 :     # construct message body
233 :     #################################################################
234 :     my $temp_body = ${ $r_text };
235 :     $temp_body =~ s/\r\n/\n/g;
236 :     $temp_body = join("",
237 :     "From: $from \nReply-To: $replyTo\n" ,
238 :     "Subject: $subject\n" ,
239 :     "Message: \n $temp_body");
240 :     # warn "FIXME from $from | subject $subject |reply $replyTo|msg $temp_body";
241 :     #################################################################
242 :     # overwrite protection
243 :     #################################################################
244 :     if ($action eq 'Save as:' and -e "$emailDirectory/$output_file") {
245 : gage 1371 $self->submission_error("The file $emailDirectory/$output_file already exists and cannot be overwritten",
246 :     "The message was not saved");
247 : gage 1370 return;
248 :     }
249 :    
250 :     #################################################################
251 :     # Back up existing file?
252 :     #################################################################
253 : gage 1371 if ($action eq 'Save as Default' and -e "$emailDirectory/$default_msg_file") {
254 :     rename("$emailDirectory/$default_msg_file","$emailDirectory/$old_default_msg_file") or
255 :     die "Can't rename $emailDirectory/$default_msg_file to $emailDirectory/$old_default_msg_file ",
256 :     "Check permissions for webserver on directory $emailDirectory. $!";
257 :     $self->{message} .= "Backup file <code>$emailDirectory/$old_default_msg_file</code> created.".CGI::br();
258 : gage 1370 }
259 :     #################################################################
260 :     # Save the message
261 :     #################################################################
262 :     $self->saveProblem($temp_body, "${emailDirectory}/$output_file" );
263 : gage 1371 $self->{message} .= "Message saved to file <code>${emailDirectory}/$output_file</code>.";
264 : gage 1370 # warn "FIXME saving to ${emailDirectory}/$output_file";
265 : gage 1372 } elsif ($action eq 'Preview') {
266 :     $self->{response} = 'preview';
267 : gage 1370
268 :     } elsif ($action eq 'Send Email') {
269 : gage 1373 $self->{response} = 'send_email';
270 :    
271 :     my @recipients = @{$self->{ra_send_to}};
272 :     warn "No recipients selected " unless @recipients;
273 :     # get merge file
274 :     my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None';
275 :     my $delimiter = ',';
276 :     my $rh_merge_data = $self->read_merge_file("$merge_file", "$delimiter");
277 : gage 1376 unless (ref($rh_merge_data) ) {
278 :     warn "no merge data file";
279 :     $self->submission_error("Can't read merge file $merge_file. No message sent");
280 :     return;
281 :     } ;
282 : gage 1373
283 : gage 1376
284 : gage 1373 foreach my $recipient (@recipients) {
285 :     #warn "FIXME sending email to $recipient";
286 :     my $ur = $self->{db}->getUser($recipient);
287 :     my ($msg, $preview_header);
288 :     eval{ ($msg,$preview_header) = $self->process_message($ur,$rh_merge_data); };
289 :     warn "There were errors in processing user $ur, merge file $merge_file. $@" if $@;
290 :     my $mailer = Mail::Sender->new({
291 :     from => $from,
292 :     to => $ur->email_address,
293 :     smtp => $ce->{mail}->{smtpServer},
294 :     subject => $subject,
295 :     headers => "X-Remote-Host: ".$r->get_remote_host(),
296 :     });
297 :     unless (ref $mailer) {
298 :     warn "Failed to create a mailer: $Mail::Sender::Error";
299 :     next;
300 :     }
301 :     unless (ref $mailer->Open()) {
302 :     warn "Failed to open the mailer: $Mail::Sender::Error";
303 :     next;
304 :     }
305 :     my $MAIL = $mailer->GetHandle() or warn "Couldn't get handle";
306 :     print $MAIL $msg || warn "Couldn't print to $MAIL";
307 :     close $MAIL || warn "Couldn't close $MAIL";
308 :     #warn "FIXME mailed to ", $ur->email_address, "from $from subject $subject";
309 :    
310 :     }
311 :    
312 : gage 1370 } else {
313 : gage 1373 warn "Didn't recognize button $action";
314 : gage 1370 }
315 : gage 1369
316 :    
317 :    
318 :     } #end initialize
319 :    
320 : gage 1368
321 :     sub title {
322 :     my $self = shift;
323 :     return 'Send mail to ' .$self->{ce}->{courseName};
324 :     }
325 :    
326 :     sub path {
327 :     my $self = shift;
328 :     my $args = $_[-1];
329 :    
330 :     my $ce = $self->{ce};
331 :     my $root = $ce->{webworkURLs}->{root};
332 :     my $courseName = $ce->{courseName};
333 :     return $self->pathMacro($args,
334 :     "Home" => "$root",
335 :     $courseName => "$root/$courseName",
336 :     'instructor' => "$root/$courseName/instructor",
337 :     "Send Mail to: $courseName" => '',
338 :     );
339 :     }
340 :    
341 :     sub body {
342 : gage 1372 my ($self, $setID) = @_;
343 :     my $response = (defined($self->{response}))? $self->{response} : '';
344 :     if ($response eq 'preview') {
345 :     $self->print_preview($setID);
346 : gage 1373 } elsif (($response eq 'send_email')){
347 :     $self->{message} .= CGI::h3("Email sent to "). join(" ", @{$self->{ra_send_to}});
348 : gage 1372 $self->print_form($setID);
349 : gage 1375 } else {
350 :     $self->print_form($setID);
351 : gage 1372 }
352 :    
353 :     }
354 :     sub print_preview {
355 :     my ($self, $setID) = @_;
356 :     # get preview user
357 :     my $ur = $self->{db}->getUser($self->{preview_user});
358 :    
359 :     # get merge file
360 :     my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None';
361 :     my $delimiter = ',';
362 :     my $rh_merge_data = $self->read_merge_file("$merge_file", "$delimiter");
363 :    
364 :     my ($msg, $preview_header) = $self->process_message($ur,$rh_merge_data);
365 :    
366 :     my $recipients = join(" ",@{$self->{ra_send_to} });
367 : gage 1373 my $errorMessage = defined($self->{submitError}) ? CGI::h3($self->{submitError} ) : '' ;
368 :     $msg = join("",
369 :     $errorMessage,
370 :     $preview_header,
371 :     "To: " , $ur->email_address,"\n",
372 :     "From: " , $self->{from} , "\n" ,
373 :     "Reply-To: " , $self->{replyTo} , "\n" ,
374 :     "Subject: " , $self->{subject} , "\n" ,"\n" ,
375 :     $msg , "\n"
376 :     );
377 : gage 1372
378 : gage 1373 return join("", '<pre>',$msg,"\n","\n",
379 : gage 1372 '</pre>',
380 :     CGI::p('Use browser back button to return from preview mode'),
381 :     CGI::h3('Emails to be sent to the following:'),
382 :     $recipients, "\n",
383 :    
384 :     );
385 :    
386 :     }
387 :     sub print_form {
388 : gage 1368 my ($self, $setID) = @_;
389 :     my $r = $self->{r};
390 :     my $authz = $self->{authz};
391 :     my $user = $r->param('user');
392 :     my $db = $self->{db};
393 :     my $ce = $self->{ce};
394 :     my $root = $ce->{webworkURLs}->{root};
395 :     my $courseName = $ce->{courseName};
396 :    
397 :     return CGI::em("You are not authorized to access the Instructor tools.") unless $authz->hasPermissions($user, "access_instructor_tools");
398 :    
399 :     my $userTemplate = $db->newUser;
400 :     my $permissionLevelTemplate = $db->newPermissionLevel;
401 :    
402 :     # This code will require changing if the permission and user tables ever have different keys.
403 : gage 1372 my @users = @{ $self->{ra_users} };
404 :     my $ra_user_records = $self->{ra_user_records};
405 :     my %classlistLabels = ();# %$hr_classlistLabels;
406 :     foreach my $ur (@{ $ra_user_records }) {
407 :     $classlistLabels{$ur->user_id} = $ur->user_id.' '.$ur->last_name. ', '. $ur->first_name.' - '.$ur->section;
408 :     }
409 : gage 1368
410 :    
411 :     ##############################################################################################################
412 :    
413 : gage 1372
414 : gage 1369 my $from = $self->{from};
415 :     my $subject = $self->{subject};
416 :     my $replyTo = $self->{replyTo};
417 :     my $columns = $self->{columns};
418 :     my $rows = $self->{rows};
419 : gage 1370 my $text = defined($self->{r_text}) ? ${ $self->{r_text} }: 'FIXME no text was produced by initialization!!';
420 :     my $input_file = $self->{input_file};
421 :     my $output_file = $self->{output_file};
422 : gage 1371 my @sorted_messages = $self->get_message_file_names;
423 :     my @sorted_merge_files = $self->get_merge_file_names;
424 :     my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None';
425 : gage 1372 my $delimiter = ',';
426 :     my $rh_merge_data = $self->read_merge_file("$merge_file", "$delimiter");
427 :     my @merge_keys = keys %$rh_merge_data;
428 :     my $preview_user = $self->{preview_user};
429 :     my $preview_record = $db->getUser($preview_user);
430 :    
431 :     #############################################################################################
432 :    
433 : gage 1369 print CGI::start_form({method=>"post", action=>$r->uri()});
434 : gage 1372 print $self->hidden_authen_fields();
435 :     #############################################################################################
436 :     # begin upper table
437 :     #############################################################################################
438 :    
439 : gage 1368 print CGI::start_table({-border=>'2', -cellpadding=>'4'});
440 : gage 1370 print CGI::Tr({-align=>'left',-valign=>'VCENTER'},
441 : gage 1372 #############################################################################################
442 :     # first column
443 :     #############################################################################################
444 :    
445 : gage 1371 CGI::td("Message file: $input_file","\n",CGI::br(),
446 :     CGI::submit(-name=>'action', -value=>'Open'), '&nbsp;&nbsp;&nbsp;&nbsp;',"\n",
447 :     CGI::popup_menu(-name=>'openfilename',
448 :     -values=>\@sorted_messages,
449 :     -default=>$input_file
450 :     ), "\n",CGI::br(),
451 :    
452 :     "Save file to: $output_file","\n",CGI::br(),
453 : gage 1370 "\n", 'From:','&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;', CGI::textfield(-name=>"from", -size=>30, -value=>$from, -override=>1),
454 :     "\n", CGI::br(),'Reply-To: ', CGI::textfield(-name=>"replyTo", -size=>30, -value=>$replyTo, -override=>1),
455 : gage 1376 "\n", CGI::br(),'Subject: ', CGI::br(), CGI::textarea(-name=>'subject', -default=>$subject, -rows=>3,-columns=>30, -override=>1),
456 : gage 1370 ),
457 : gage 1372 #############################################################################################
458 :     # second column
459 :     #############################################################################################
460 : gage 1370 CGI::td({-align=>'left'},
461 :     CGI::radio_group(-name=>'radio', -values=>['all_students','studentID'],
462 :     -labels=>{all_students=>'All active students',studentID => 'Select recipients'},
463 :     -default=>'studentID',
464 :     -linebreak=>1),
465 :     CGI::br(),
466 :     CGI::popup_menu(-name=>'classList',
467 :     -values=>\@users,
468 :     -labels=>\%classlistLabels,
469 :     -size => 10,
470 :     -multiple => 1,
471 : gage 1372 -default=>$user
472 : gage 1370 ),
473 :    
474 :    
475 :     ),
476 : gage 1372 #############################################################################################
477 :     # third column
478 :     #############################################################################################
479 : gage 1370 CGI::td({align=>'left'},
480 : gage 1372 "Merge file is: $merge_file", CGI::br(),
481 : gage 1375 CGI::submit(-name=>'action', -value=>'Set merge file to:'),CGI::br(),
482 : gage 1371 CGI::popup_menu(-name=>'merge_file',
483 :     -values=>\@sorted_merge_files,
484 :     -default=>$merge_file,
485 : gage 1372 ), "\n",CGI::hr(),CGI::br(),
486 :     CGI::submit(-name=>'action', -value=>'preview',-label=>'Preview')," email to ",
487 :     CGI::popup_menu(-name=>'preview_user',
488 : gage 1370 -values=>\@users,
489 : gage 1372 #-labels=>\%classlistLabels,
490 :     -default=>$preview_user,
491 : gage 1369 ),
492 : gage 1372 CGI::hr(),
493 : gage 1370 CGI::submit(-name=>'action', -value=>'resize', -label=>'Resize message window'),CGI::br(),
494 :     " Rows: ", CGI::textfield(-name=>'rows', -size=>3, -value=>$rows),
495 :     " Columns: ", CGI::textfield(-name=>'columns', -size=>3, -value=>$columns),
496 :     CGI::br(),CGI::br(),
497 :     #show available macros
498 :     CGI::popup_menu(
499 :     -name=>'dummyName',
500 :     -values=>['', '$SID', '$FN', '$LN', '$SECTION', '$RECITATION','$STATUS', '$EMAIL', '$LOGIN', '$COL[3]', '$COL[-1]'],
501 :     -labels=>{''=>'list of insertable macros',
502 :     '$SID'=>'$SID - Student ID',
503 :     '$FN'=>'$FN - First name',
504 :     '$LN'=>'$LN - Last name',
505 : gage 1372 '$SECTION'=>'$SECTION',
506 : gage 1370 '$RECITATION'=>'$RECITATION',
507 :     '$STATUS'=>'$STATUS - C, Audit, Drop, etc.',
508 :     '$EMAIL'=>'$EMAIL - Email address',
509 :     '$LOGIN'=>'$LOGIN - Login',
510 : gage 1372 '$COL[3]'=>'$COL[3] - 3rd col',
511 : gage 1370 '$COL[-1]'=>'$COL[-1] - Last column'
512 :     }
513 :     ), "\n",
514 :     ),
515 : gage 1368
516 : gage 1370 ); # end Tr
517 : gage 1372 print CGI::end_table();
518 :     #############################################################################################
519 :     # end upper table
520 :     #############################################################################################
521 :    
522 :     # show merge file
523 :     # print "<pre>",(map {$_ =~s/\s/\./g;$_} map {sprintf('%-8.8s',$_);} 0..8),"</pre>";
524 :     # print CGI::popup_menu(
525 :     # -name=>'dummyName2',
526 :     # -values=>\@merge_keys,
527 :     # -labels=>$rh_merge_data,
528 :     # -multiple=>1,
529 :     # -size =>2,
530 :     #
531 :     # ), "\n",CGI::br();
532 :     # warn "merge keys ", join( " ",@merge_keys);
533 :     #############################################################################################
534 :     # merge file fragment and message text area field
535 :     #############################################################################################
536 : gage 1373 my @tmp2;
537 :     eval{ @tmp2= @{$rh_merge_data->{ $db->getUser($preview_user)->student_id } };};
538 :     if ($@) {
539 : gage 1381 # print CGI::p( "Couldn't get merge data for $preview_user", CGI::br(), $@) ;
540 :     print "No merge data for $preview_user in merge file: &lt;$merge_file&gt;",CGI::br();
541 : gage 1373 } else {
542 :     print CGI::pre("",data_format(0..($#tmp2)),"\n", data_format(@tmp2));
543 :     }
544 : gage 1368 #create a textbox with the subject and a textarea with the message
545 :     #print actual body of message
546 : gage 1369
547 : gage 1370 print "\n", CGI::p( $self->{message}) if defined($self->{message});
548 : gage 1369 print "\n", CGI::p( CGI::textarea(-name=>'body', -default=>$text, -rows=>$rows, -columns=>$columns, -override=>1));
549 : gage 1372
550 :     #############################################################################################
551 :     # action button table
552 :     #############################################################################################
553 : gage 1370 print CGI::table( { -border=>2,-cellpadding=>4},
554 :     CGI::Tr(
555 :     CGI::td( CGI::submit(-name=>'action', -value=>'Send Email') ), "\n",
556 :     CGI::td(CGI::submit(-name=>'action', -value=>'Save')," to $output_file"), " \n",
557 :     CGI::td(CGI::submit(-name=>'action', -value=>'Save as:'),
558 :     CGI::textfield(-name=>'savefilename', -size => 20, -value=> "$output_file", -override=>1)
559 :     ), "\n",
560 :     CGI::td(CGI::submit(-name=>'action', -value=>'Save as Default')),
561 :     )
562 :     );
563 : gage 1368
564 :     ##############################################################################################################
565 : gage 1369
566 :     print CGI::end_form();
567 : gage 1368 return "";
568 :     }
569 :    
570 : gage 1369 ##############################################################################
571 :     # Utility methods
572 :     ##############################################################################
573 : gage 1370 sub submission_error {
574 : gage 1369 my $self = shift;
575 : gage 1371 my $msg = join( " ", @_);
576 : gage 1376 $self->{submitError} .= CGI::br().$msg; #CGI::b(HTML::Entities::encode($msg));
577 : gage 1371 # qq{Please hit the &quot;<B>Back</B>&quot; button on your browser to
578 :     # try again, or notify your web master
579 :     # if you believe this message is in error.
580 :     # };
581 : gage 1369 return;
582 :     }
583 :    
584 : gage 1370 sub saveProblem {
585 :     my $self = shift;
586 :     my ($body, $probFileName)= @_;
587 :     local(*PROBLEM);
588 :     open (PROBLEM, ">$probFileName") ||
589 :     $self->submission_error("Could not open $probFileName for writing.
590 :     Check that the permissions for this problem are 660 (-rw-rw----)");
591 :     print PROBLEM $body;
592 :     close PROBLEM;
593 :     chmod 0660, "$probFileName" ||
594 :     $self->submission_error("
595 :     CAN'T CHANGE PERMISSIONS ON FILE $probFileName");
596 :     }
597 :    
598 :     sub read_input_file {
599 :     my $self = shift;
600 :     my $filePath = shift;
601 :     my ($text, @text);
602 :     my $header = '';
603 :     my ($subject, $from, $replyTo);
604 :     local(*FILE);
605 : gage 1371 if (-e "$filePath" and -r "$filePath") {
606 :     open FILE, "$filePath" || do { $self->submission_error("Can't open $filePath"); return};
607 :     while ($header !~ s/Message:\s*$//m and not eof(FILE)) {
608 : gage 1370 $header .= <FILE>;
609 :     }
610 :     $text = join( '', <FILE>);
611 :     $text =~ s/^\s*//; # remove initial white space if any.
612 :     $header =~ /^From:\s(.*)$/m;
613 :     $from = $1 or $from = $self->{defaultFrom};
614 :    
615 :     $header =~ /^Reply-To:\s(.*)$/m;
616 :     $replyTo = $1 or $replyTo = $self->{defaultReply};
617 :    
618 :     $header =~ /^Subject:\s(.*)$/m;
619 :     $subject = $1;
620 :    
621 :     } else {
622 :     $from = $self->{defaultFrom};
623 :     $replyTo = $self->{defaultReply};
624 : gage 1371 $text = (-e "$filePath") ? "FIXME file $filePath can't be read" :"FIXME file $filePath doesn't exist";
625 : gage 1370 $subject = "FIXME default subject";
626 :     }
627 :     return ($from, $replyTo, $subject, \$text);
628 :     }
629 : gage 1371
630 :     sub get_message_file_names {
631 :     my $self = shift;
632 :     my $emailDirectory = $self->{ce}->{courseDirs}->{email};
633 :     #get all message files and create a list
634 :     local(*EMAILDIR);
635 :     opendir( EMAILDIR, $emailDirectory )|| die "Can't access directory $emailDirectory. Please check that webserver has permission to read this directory.";
636 :     my @messageFiles = grep /\.msg$/, readdir EMAILDIR; #all message files
637 :     closedir EMAILDIR;
638 :    
639 :     return sort @messageFiles;
640 :     }
641 :     sub get_merge_file_names {
642 :     my $self = shift;
643 :     my $scoringDirectory = $self->{ce}->{courseDirs}->{scoring};
644 :     #get all message files and create a list
645 :     local(*SCORINGDIR);
646 :     opendir( SCORINGDIR, $scoringDirectory )|| die "Can't access directory $scoringDirectory.",
647 :     "Please check that webserver has permission to read this directory.";
648 :     my @mergeFiles = grep( /\.csv$/, readdir SCORINGDIR); #all message files
649 :     closedir SCORINGDIR;
650 :     @mergeFiles = sort @mergeFiles;
651 :     # warn "FIXME scoring directory $scoringDirectory merge Files", join(" ", @mergeFiles);
652 :     unshift(@mergeFiles, 'None');
653 :     return @mergeFiles;
654 :     }
655 : gage 1372
656 :     sub read_merge_file {
657 :     my $self = shift;
658 :     my $fileName = shift;
659 :     my $delimiter = shift;
660 :     $delimiter = ',' unless defined($delimiter);
661 :     my $scoringDirectory= $self->{ce}->{courseDirs}->{scoring};
662 :     my $filePath = "$scoringDirectory/$fileName";
663 :     # Takes a delimited file as a parameter and returns an
664 :     # associative array with the first field as the key.
665 :     # Blank lines are skipped. White space is removed
666 : gage 1375 my(@dbArray,$key,$dbString);
667 :     my %assocArray = ();
668 : gage 1372 local(*FILE);
669 : gage 1375 if ($fileName eq 'None') {
670 :     # do nothing
671 : gage 1376 } elsif ( open(FILE, "$filePath") ) {
672 : gage 1375 my $index=0;
673 :     while (<FILE>){
674 :     unless ($_ =~ /\S/) {next;} ## skip blank lines
675 :     chomp;
676 :     @{$dbArray[$index]} =$self->getRecord($_,$delimiter);
677 :     $key =$dbArray[$index][0];
678 :     #@dbArray = map {$_ =~s/\s/\./g;$_} map {sprintf('%-8.8s',$_);} @dbArray;
679 :     #$dbString = join(" | ",@dbArray);
680 :     $assocArray{$key}=$dbArray[$index];
681 :     $index++;
682 :     }
683 :     close(FILE);
684 :     } else {
685 :     warn "Couldn't read file $filePath";
686 :     }
687 :     return \%assocArray;
688 : gage 1372 }
689 :     sub getRecord {
690 :     my $self = shift;
691 :     my $line = shift;
692 :     my $delimiter = shift;
693 :     $delimiter = ',' unless defined($delimiter);
694 :    
695 :     # Takes a delimited line as a parameter and returns an
696 :     # array. Note that all white space is removed. If the
697 :     # last field is empty, the last element of the returned
698 :     # array is also empty (unlike what the perl split command
699 :     # would return). E.G. @lineArray=&getRecord(\$delimitedLine).
700 :    
701 :     my(@lineArray);
702 :     $line.=$delimiter; # add 'A' to end of line so that
703 :     # last field is never empty
704 :     @lineArray = split(/\s*${delimiter}\s*/,$line);
705 :     $lineArray[0] =~s/^\s*//; # remove white space from first element
706 :     @lineArray;
707 :     }
708 :    
709 :     sub process_message {
710 :     my $self = shift;
711 :     my $ur = shift;
712 :     my $rh_merge_data = shift;
713 :     my $text = defined($self->{r_text}) ? ${ $self->{r_text} }:
714 :     'FIXME no text was produced by initialization!!';
715 :     #user macros that can be used in the email message
716 :     my $SID = $ur->student_id;
717 :     my $FN = $ur->first_name;
718 :     my $LN = $ur->last_name;
719 :     my $SECTION = $ur->section;
720 :     my $RECITATION = $ur->recitation;
721 :     my $STATUS = $ur->status;
722 :     my $EMAIL = $ur->email_address;
723 :     my $LOGIN = $ur->user_id;
724 :     # get record from merge file
725 :     # FIXME this is inefficient. The info should be cached
726 : gage 1373 my @COL = defined($rh_merge_data->{$SID}) ? @{$rh_merge_data->{$SID} } : ();
727 :     $self->submission_error( "No merge data for $SID $FN $LN $LOGIN") unless defined($rh_merge_data->{$SID});
728 : gage 1372
729 :     my $endCol = @COL;
730 :     # for safety, only evaluate special variables
731 : gage 1373 my $msg = $text;
732 :     $msg =~ s/(\$SID)/eval($1)/ge;
733 :     $msg =~ s/(\$LN)/eval($1)/ge;
734 :     $msg =~ s/(\$FN)/eval($1)/ge;
735 :     $msg =~ s/(\$STATUS)/eval($1)/ge;
736 :     $msg =~ s/(\$SECTION)/eval($1)/ge;
737 :     $msg =~ s/(\$RECITATION)/eval($1)/ge;
738 :     $msg =~ s/(\$EMAIL)/eval($1)/ge;
739 :     $msg =~ s/(\$LOGIN)/eval($1)/ge;
740 :     $msg =~ s/\$COL\[ *-/\$COL\[$endCol-/g;
741 :     $msg =~ s/(\$COL\[.*?\])/eval($1)/ge;
742 :    
743 :     $msg =~ s/\r//g;
744 : gage 1372
745 :     my $preview_header = CGI::pre("",data_format(0..($#COL)),"\n", data_format(@COL)).
746 :     CGI::h3( "This sample mail would be sent to $EMAIL");
747 :    
748 :    
749 :     return $msg, $preview_header;
750 :     }
751 :     sub data_format {
752 :     map {$_ =~s/\s/\./g;$_} map {sprintf('%-8.8s',$_);} @_;
753 :     }
754 : gage 1368 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9