[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 1667 - (view) (download) (as text)
Original Path: trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9