#!/usr/bin/perl -wT # Note: let the program create the output file # Do not modify the structure of the created output file use strict; use CGI; use CGI::Carp 'fatalsToBrowser'; use Fcntl ":flock"; use Text::ParseWords; ### START Global variables # Form data my ($fname, $lname, $hours_min, $hours_max, $kitc, $sitc, $email, $phone, $notes); # Derived from form data my ($name, $initials, $which_itc, $num_hours, $output_file, @hour_array); # Other my ($cgi, $timestamp); # a 7 by 16 array to hold the selected hours # each group of 7 elements represents a certain time period across the week # for example, the first 7 elements represent Mon thru Sun, 8a - 9a # the second 7 represent Mon thru Sun, 9a - 10a # a 0 means the hour was not selected # later on, some elements will be changed to 1's to show the selected hours @hour_array = (0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0,); ### END Global variables # main() # Command line functionality! # This is to remove a user from a given requests file # Usage: itc_make_schedule.pl remove employee_name sitc|kitc # Must use full name and it must be quoted: "Firstname Lastname" if ( @ARGV == 3 && ($ARGV[0] eq "remove" ) && ($ARGV[1] && $ARGV[2]) ) { if ( $ARGV[2] eq "kitc" ) { $output_file = "kitc_requests.csv"; unless ( -e $output_file ) { print( "The kitc requests file does not exist!\n" ); exit(1); } } elsif ( $ARGV[2] eq "sitc" ) { $output_file = "sitc_requests.csv"; unless ( -e $output_file ) { print( "The sitc requests file does not exist!\n" ); exit(1); } } else { print("Error: lab given not valid.\n", "Command format: ", "itc_make_schedule.pl ", "remove ", "\"firstname lastname\" ", "sitc OR kitc\n" ); exit(1); } &removeRecord( $ARGV[1] ); exit(0); } if ( @ARGV >= 1 && @ARGV != 3 ) { print("Error in command format. Use:\n", "itc_make_schedule.pl ", "remove ", "\"firstname lastname\" ", "sitc OR kitc\n" ); exit(1); } processFormData(); createOutputFile(); fillHourArray(); &removeRecord( $name ); printDataToFile(); printMessageToBrowser(); # main # sub processFormData() { $cgi = new CGI; $timestamp = localtime; $num_hours = countHours(); $notes = $cgi->param('notes'); $kitc = "off"; $sitc = "off"; # Make sure all the form variables are defined if ( $cgi->param('fname') ) { $fname = $cgi->param('fname'); } else { &catchUserError(0); } if ( $cgi->param('lname') ) { $lname = $cgi->param('lname'); } else { &catchUserError(1); } if ( $cgi->param('hours_min') != -1 ) { $hours_min = $cgi->param('hours_min'); } else { &catchUserError(2); } if ( $cgi->param('hours_max') != -1 ) { $hours_max = $cgi->param('hours_max'); if ( $hours_max < $hours_min ) { &catchUserError(2); } } else { $hours_max = $hours_min; } if ( !($cgi->param('kitc') || $cgi->param('sitc')) || ($cgi->param('kitc') && $cgi->param('sitc')) ) { &catchUserError(3); } if ( $cgi->param('kitc') ) { $kitc = $cgi->param('kitc'); } if ( $cgi->param('sitc') ) { $sitc = $cgi->param('sitc'); } if ( $cgi->param('email') ) { $email = $cgi->param('email'); } else { &catchUserError(4); } if ( $cgi->param('phone1') && $cgi->param('phone1') ) { $phone = $cgi->param('phone1') . "-" . $cgi->param('phone2') ; } else { &catchUserError(5); } unless ( $num_hours > 0 ) { &catchUserError(6); } # Check that names, email, and phone are well-formed if ( $fname =~ /[^A-Za-z\-]/ || $lname =~ /[^A-Za-z\-]/) { &catchUserError(7); } if ( !($email =~ /^([A-Za-z]{1}[\w]*([\.]{1}[\w]+)*[\@]{1}[A-Za-z]+([\.]{1}[A-Za-z]+)+)/ && $email =~ /([A-Za-z]{1}[\w]*([\.]{1}[\w]+)*[\@]{1}[A-Za-z]+([\.]{1}[A-Za-z]+)+)$/) ) { &catchUserError(8); } if( !($phone =~ /^[\d]{3}[\-]{1}[\d]{4}/ && $phone =~ /[\d]{3}[\-]{1}[\d]{4}$/) ) { &catchUserError(9); } # Initialize dependent variables $name = lc( $fname . " " . $lname ); $initials = lc( (substr( $fname, 0, 2 )) . "" . (substr( $lname, 0, 2 )) ); if ( $kitc eq "on" ) { $which_itc = "kitc"; $output_file= "kitc_requests.csv"; } elsif ( $sitc eq "on" ) { $which_itc = "sitc"; $output_file= "sitc_requests.csv"; } $notes =~ s/,/;/g; } # processFormData # Args # A number corresponding to a descriptive string that gives the type of # error. This descriptive string is in @code # What it does # An appropriate error message is printed sub catchUserError() { my @code = ("No first name entered.", "No last name entered.", "No hours/week selected OR max hours less than min hours.", "No lab selected OR both selected.", "No email address entered.", "No phone number entered.", "No available hours were checked.", "Name fields may only contain letters. Make sure there are no spaces after the name.", "Email address is malformed.", "Phone number is malformed.", ); print $cgi->header( "text/html" ), $cgi->start_html( -title => "Error!" ), $cgi->h1( "Error in Form Data." ), $cgi->div( "$code[$_[0]]
Please return to form and correct." ), $cgi->end_html; exit(1); } # catchUserError # Create the output file, *iff* it doesn't already exist sub createOutputFile() { unless ( -e $output_file ) { open OUT, ">>$output_file" or die$!; flock OUT, LOCK_EX; # Create skeleton of file print OUT ",Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday\n", "08:00am,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,CLOSED,CLOSED,\n", "09:00am,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,CLOSED,CLOSED,\n", "10:00am,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,CLOSED,CLOSED,\n", "11:00am,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,CLOSED,CLOSED,\n", "12:00am,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,\n", "01:00pm,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,\n", "02:00pm,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,\n", "03:00pm,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,\n", "04:00pm,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,\n", "05:00pm,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,\n", "06:00pm,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,NO ONE,\n", "07:00pm,NO ONE,NO ONE,NO ONE,NO ONE,CLOSED,CLOSED,NO ONE,\n", "08:00pm,NO ONE,NO ONE,NO ONE,NO ONE,CLOSED,CLOSED,NO ONE,\n", "09:00pm,CLOSED,CLOSED,CLOSED,CLOSED,CLOSED,CLOSED,CLOSED,\n", "10:00pm,CLOSED,CLOSED,CLOSED,CLOSED,CLOSED,CLOSED,CLOSED,\n", "11:00pm,CLOSED,CLOSED,CLOSED,CLOSED,CLOSED,CLOSED,CLOSED,\n", "\n", "NAME,INITIALS,HOURS/WEEK,WHICH ITC,EMAIL,", "PHONE,DATE SUBMITTED,NOTES\n", ; close OUT or die $!; } } # createOutputFile sub fillHourArray() { my $h; foreach $h ( $cgi->param( 'array_hour' ) ) { $hour_array[$h] = 1; } } # fillHourArray # Counts the number of hours the user has selected sub countHours() { my $count = 0; my $h; foreach $h ($cgi->param('array_hour')) { $count += 1; } return $count; } # countHours # Remove a record from the request file sub removeRecord() { my $the_name = "$_[0]"; my $inits = ""; # If the request file doesn't exist, don't do anything unless ( -e $output_file ) { return; } # Presumably, the request file exists... open( IN, "$output_file" ) or die($!); my $line = ""; # to hold each line in the file my $content = ""; # concatenate $line to this my @fields = (); # Look at every line in requests # When (if) the name is found, extract the associated initials, then # delete the line with the_name while ( $line = ) { # If $the_name is found (at the beginning of the line), delete the # line, but get the inits first if ( $line =~ /^$the_name/ ) { @fields = quotewords(",", 0, $line); $inits = $fields[1] . " "; $line = ""; } $content .= $line; } # Print $content to file, such that file now contains everything except # $the_name's "info" line close( IN ) or die $!; open( FILE, ">$output_file" ) or die$!; flock( FILE, LOCK_EX ); print( FILE $content ); close( FILE ) or die $!; # Look at every line again. This time, remove all instances of $inits. In # high level terms, remove a user's initials from the availability table. open( IN, "<$output_file" ) or die($!); $line = ""; $content = ""; my $boolean = "false"; while ( $line = ) { if ( $line eq "\n" ) { # Skip blank lines $boolean = "true"; } # if $inits is found, remove it from the line if ( $boolean eq "false" && $line =~ /$inits/ ) { $line =~ s/$inits//g; } $content .= $line; } close(IN) or die($!); # Print $content to file open( FILE, ">$output_file" ) or die($!); flock( FILE, LOCK_EX ); print( FILE $content ); close( FILE ) or die($!); } # removeRecord # Add a new record to the output file sub printDataToFile() { # Create the user's "info" # (The user's info is distinguished from the the user's hours) my $com = ","; my $info = "$name$com$initials$com$hours_min to $hours_max$com"; $info .= "$which_itc$com$email$com$phone$com$timestamp$com$com$notes"; # Append user's "info" to file open( FILE, ">>$output_file" ) or die$!; flock FILE, LOCK_EX; print FILE "$info\n"; close FILE or die $!; # Here comes the tricky part: # Add the user's selected hours to the file my $content = ""; my $line = ""; my @slots = (); my ($i, $j, $k); my $count = 0; my $start = 0; my $stop = 6; open( IN, "<$output_file" ) or die($!); # in effect, skip the first line if ( !($content = ) ) { die($!, "Problem with output file"); } # Modify each line as necessary, then concatenate the line to $content # If output file doesn't exist, there will be big problems, and it means # someone has been modifying the output file by hand. if ( !($line = ) ) { die($!, "Problem with output file"); } # When the blank line is reached, stop. Also stop if count reaches 100, # meaning the output file's been tampered with until ( $line eq "\n" || $count == 100) { @slots = quotewords(",", 0, $line); # Read current line into an array # for ( $i=$start, $j=1; $i<=$stop; $i++, $j++ ) { if ( $hour_array[$i] == 1 ) { if ( $slots[$j] eq "NO ONE" ) { $slots[$j] = ""; } $slots[$j] .= $initials . " "; } if ( $slots[$j] eq "" ) { $slots[$j] = "NO ONE"; } } for ( $k = 0; $k < @slots; $k++ ) { $content .= $slots[$k]; # Put comma after each field, unless it's the last field (the "\n") unless ( $k == @slots-1 ) { $content .= ","; } } $start += 7; $stop += 7; if ( !($line = ) ) { die($!, "Problem with output file"); } $count++; } # Add the blank line to $content $content .= $line; # Add the rest of the lines to content (These are the "info" section lines) while ( $line = ) { $content .= $line; } close( IN ); open( FILE, ">$output_file" ) or die$!; print( FILE $content ); close( FILE ); } # printDataToFile # Print the user's form data to the browser sub printMessageToBrowser() { # Do not indent the "Content-type..." line!!! print <<"EOF"; Content-type: text/html\n\n\n Form Response

$fname $lname, here is what you submitted:

Hours desired per week: $hours_min to $hours_max
Which lab(s): $which_itc
Email address: $email
Phone number: $phone
Notes to scheduler: $notes
Number of hours checked: $num_hours

EOF # Create a table showing the user's availability # Concatenate everything to $out, then print $out at the end my $out = "\n"; my $time1 = 9; my $time2 = 10; for (my $i = 0; $i < @hour_array; $i++) { if ( $i != 0 && $i % 7 == 0 ) { $out .= "\n"; $out .= "\n"; $time1++; $time2++; if ($time1 == 13 ) { $time1 = 1; } if ($time2 == 13 ) { $time2 = 1; } } # endif $out .= "\n"; } $out .= "
  MondayTuesdayWednesday ThursdayFridaySaturday Sunday
8:00 - 9:00
$time1:00 - $time2:00"; if ( $hour_array[$i] == 0 ) { $out .= " "; } elsif ( $hour_array[$i] == 1 ) { $out .= "+"; } $out .= "
"; print $out; } # printMessageToBrowser # For testing my $test = 0; if ($test) { my $field = &extractFieldsFromLine ( 'wyatt baldwin,wlb,45,email,field4', ',', 3 ); print "Content-type: text/plain\n\n", "field: ", $field, ; exit 0; }