From 0b86cab3c9766089206f59475d55b7f42606bb4d Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 11 May 2000 11:27:32 +0000 Subject: [PATCH 1/1] initial module creation --- convert-template.pl | 2 + shift.cgi | 234 ++++++++++++++++++++++++++++++++++++++++++++++ table.html | 260 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 496 insertions(+) create mode 100755 convert-template.pl create mode 100755 shift.cgi create mode 100644 table.html diff --git a/convert-template.pl b/convert-template.pl new file mode 100755 index 0000000..e6b2d9e --- /dev/null +++ b/convert-template.pl @@ -0,0 +1,2 @@ +#!/usr/bin/perl -p +s/\([\w\s]+)\<\/WORKSHIFT\>/\{ inputbox\(\"$1\"\); \}/ig; diff --git a/shift.cgi b/shift.cgi new file mode 100755 index 0000000..7f9bcd6 --- /dev/null +++ b/shift.cgi @@ -0,0 +1,234 @@ +#!/usr/bin/perl -w +#!/usr/bin/perl -Tw +# (Text::Template can't do -T, but no user input is used dangerously) +# +# $Id: shift.cgi,v 1.1 2000-05-11 11:27:32 ivan Exp $ +# +# Copyright (C) 2000 Adam Gould +# Copyright (C) 2000 Michal Migurski +# Copyright (C) 2000 Ivan Kohler +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify it under +# the same terms as Perl itself. + +### +# user-servicable parts +### + +$template_file = '/home/ivan/staffsheet/table.html'; +$data_directory = '/home/ivan/staffsheet/data'; +$mail_smtpserver = 'localhost'; # set blank to disable +$mail_from = 'ivan-misconfigured-shift-from@420.am'; +$mail_subject = 'Your shift has been replaced'; +@mail_cc = ( + 'ivan-misconfigured-shift-cc@420.am', + 'ivan-misconfigured-shift-cc2@420.am' +); +$mail_footer = < 'FILE', + SOURCE => $template_file, +) or die "Can't create template for $template_file: $Text::Template::ERROR"; + +# fill in new data if provided +%warning = (); +@messages = (); +if ( $cgi->param() ) { + + # kludge - grep for inputbox("field") in template to find valid form fields + # (DON'T get them from form submission - that's insecure!) + open (TEMPLATE_FILE,"<$template_file") + or die "Can't open template for $template_file: $!"; + my @form_fields = + map { /inputbox\s*\(\s*([\'\"])(.*)\1\s*\)/; $2 } + #grep { /inputbox\s*\(\s*([\'\"])(.*)\1\s*\)/ } + grep { /inputbox\s*\(\s*([\'\"])(.*)\1\s*\);?\s*\}/ } + ; + close TEMPLATE_FILE; + + #changed fields + #foreach $_ ( @form_fields ) { + # warn "${_}_old undefined!" unless defined $cgi->param($_. '_old'); + # warn "${_}_new undefined!" unless defined $cgi->param($_. '_new'); + #} + my @diff_fields = + grep { $cgi->param($_. '_old') ne $cgi->param($_. '_new') } @form_fields; + + if ( @diff_fields ) { + + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + #open(LOCKFILE,">>$data_directory/.lock") + open(LOCKFILE,"+<$data_directory/.lock") + or open(LOCKFILE,">>$data_directory/.lock") + or die "Can't open $data_directory/.lock: $!"; + flock(LOCKFILE,LOCK_EX); #blocks until we have the lock + seek(LOCKFILE, 0, 0); + print LOCKFILE "$$ \n"; #superfluous + + get_data(); + + foreach my $field ( @diff_fields ) { + $shifthash{$field}='' unless defined $shifthash{$field}; + if ( $shifthash{$field} eq $cgi->param($field. '_old') ) { + if ( $cgi->param($field. "_new") =~ + /\b(\w[\w\-\.\+]*\@(([\w\.\-]+\.)+\w+))\b/ + || $cgi->param($field. "_new") =~ /^\s*$/ + ) { + open(FILE,">$data_directory/.new.$field") + or die "Can't open file $data_directory/$field: $!"; + print FILE $cgi->param($field. "_new"); + close FILE; + rename "$data_directory/.new.$field", "$data_directory/$field"; + $warning{$field} = ''; + if ( + $mail_smtpserver + && $shifthash{$field} =~ /\b(\w[\w\-\.\+]*\@(([\w\.\-]+\.)+\w+))\b/ + ) { + my $to = $1; + my $header = Mail::Header->new( [ + "From: $mail_from", + "To: $to", + "Cc: ". join(", ", @mail_cc), + "Sender: $mail_from", + "Reply-To: $mail_from", + "Date: ". time2str("%a, %d %b %Y %X %z", time), + "Subject: $mail_subject", + ] ); + my $msg = Mail::Internet->new( + 'Header' => $header, + 'Body' => [ map "$_\n", + "Hi,", + "", + "The \"$field\" shift you signed up for has been changed to", + '"'. $cgi->param($field. "_new"). '"', + "", + split("\n", $mail_footer), + ], + ); + #send later - don't want to block on smtp while we have the lock + push @messages, $msg; + } + } else { + $warning{$field} = + "WARNING: you tried to sign up for $field, but your entry ". + "\"". $cgi->param($field. '_new'). + "\" does not contain a valid email address." + ; + } + } elsif ( $shifthash{$field} eq $cgi->param($field. '_new') ) { + #somebody else made the same change (or you hit reload); no need to warn + $warning{$field} = ''; + } else { + $warning{$field} = + "WARNING: you tried to change $field from \"". + $cgi->param($field. '_old'). + "\" to \"". + $cgi->param($field. "_new"). + "\", but in the meantime someone changed it to: " + ; + } + } + + flock(LOCKFILE,LOCK_UN); + close LOCKFILE; + + } + +} + +get_data(); + +my $text = $template->fill_in() + or die "Can't fill in template for $template_file: $Text::Template::ERROR"; + +print $cgi->header, $text; + +$ENV{SMTPHOSTS} = $mail_smtpserver; +$ENV{MAILADDRESS} = $mail_from; +foreach my $msg ( @messages ) { + $msg->smtpsend; +} + +# subroutines + +sub get_data { + opendir DATA_DIR, $data_directory + or die "Can't open directory $data_directory: $!"; + %shifthash = map { + open(FILE, "<$data_directory/$_") + or die "Can't open file $data_directory/$_: $!"; + my $value = scalar() || ''; + close FILE; + chomp $value; + ( $_ => $value ); + } grep { ! /^\.{1,2}(lock)?$/ } readdir(DATA_DIR); + closedir DATA_DIR; +} + +# subroutines for the template + +sub form { + $cgi->start_form; +} + +sub inputbox { + my $field = shift; + return $shifthash{$field} || " " + if defined $cgi->param('__MAGIC') && $cgi->param('__MAGIC') eq 'print'; + $shifthash{$field}='' unless defined $shifthash{$field}; + $warning{$field}='' unless defined $warning{$field}; + #"$field ". + $cgi->hidden( + -name => $field. '_old', + -default => $shifthash{$field}, + -force => 1, + ). + $warning{$field}. + $cgi->textfield( + -name => $field. '_new', + -default => $shifthash{$field}, + -force => 1, + -size => 15, + ); +} + +sub warnings { + join "
", map { + "$warning{$_}$shifthash{$_}" + } grep { + $warning{$_} + } keys %warning; +} + diff --git a/table.html b/table.html new file mode 100644 index 0000000..8603c82 --- /dev/null +++ b/table.html @@ -0,0 +1,260 @@ + + + + + + +Viberation + + + + + + + + +
+ + + +
+ + + + + + + + + + +
+ +  
+  
+ + + + + +{ form(); } + +

{ warnings(); }

+ +


+show results in printable format

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Time + Door + Parking + Time +
9pm - 10pm{ inputbox("Door 1"); }{ inputbox("Park 1"); } 9pm - 10pm
10pm - 11pm{ inputbox("Park 2"); }10pm - 11pm
11pm - 12am{ inputbox("Door 2"); }{ inputbox("Park 3"); }11pm - 12am
12am - 1am{ inputbox("Park 4"); }12am - 1am
1am - 2am{ inputbox("Door 3"); }{ inputbox("Park 5"); }1am - 2am
2am - 3am{ inputbox("Park 6"); }2am - 3am
3am - 4am{ inputbox("Door 5"); }{ inputbox("Park 7"); }3am - 4am
4am - 5am{ inputbox("Park 8"); }4am - 5am
5am - 6am  5am - 6am
+ +

+ + + + +

+©2000 Adam Gould and Michal Migurski. +

+ + + + +
+ +

+ Above is an example of the Online Staffing Sheet in action. Names can be modified by typing in the fields. Hitting "Submit" automatically updates the storage directory. +

+ +

Download

+ +

All relevant files are included in the staffingsheet.sit archive.

+

You also need the Text::Template, MailTools and TimeDate perl modules. (CPAN will query, download and build perl modules automatically) + + +

Configuration

+ +

+ Configuring the staffing sheet is easy. +

+ +

+ Front-end changes can be made to the table.html file, which stores the layout of the staffing sheet and is used to generate the database file. The table.html file uses some non-standard tags: +

    +
  • \{ form(); \}
    + Use this tag to start your form instead of the HTML <FORM> tag. (You should end the form with the normal </FORM> tag.) +
  • \{ inputbox("shift"); \}
    + This tag specifies the name of a workshift, as in \{ inputbox("Door 1"); \}. The text enclosed in the tag is used as the workshift name, and is used to generate FORM INPUT fields by the shift.cgi program. Characters allowed within the tag include spaces, digits, and letters; however the tag cannot begin or end with a space. To ensure trouble-free use, please keep the tag on ONE line. For an example of intended use, check the source of table.html. +
  • \{ warnings(); \}
    + If, during the time between when you load the form and when you submit your changes, one of the fields you are changing has been changed by someone else, your changes will not be accepted and a warning will be issued next to the input box for that field. You can use the \{ warnings(); \} tag to return a list of all warnings, so that you can locate them prominantly on the resulting page. +
  • Note: old-style <WORKSHIFT>shift</WORKSHIFT> tags can be converted to \{ inputbox("shift"); \} tags with the convert-template.pl program: ./convert-template.pl old-table-file.html >new-table-file.html. +
+ Other than these tags, anything goes. You can include tables, various types of text formatting, and anything else not covered by the above restrictions. If you need to use the \{ or \} characters (the curly braces), you must preceed them with a \ (backslash). See the Text::Template documentation for details on the substitution language. +

+ +

+ Back-end configuration involves editing a few lines in the shift.cgi file. The $template_file variable must be set to the full path and name of the front-end table.html file. The $data_directory must be set to the full path and name of a directory where the data will be stored. If you want to enable the optional mail-notification feature (will send email to anyone who has their shift replaced if they included an email address), set the $mail_smtpserver variable to the name of an SMTP server which will relay your messages, set the $mail_from variable to the address you wish to appear in the From:, Sender: and Reply-To: headers, set the $mail_subject variable to the subject you wish to appear in the Subject: header, set the @mail_cc variable to any addresses you wish Cc:'ed, and set the $mail_footer variable to a message which will appear at the bottom of all warning messages.
+

###
+# user-servicable parts
+###
+
+$template_file = '/home/ivan/staffsheet/table.html';
+$data_directory = '/home/ivan/staffsheet/data';
+$mail_smtpserver = 'localhost'; # set blank to disable
+$mail_from = 'ivan-misconfigured-shift-from@420.am';
+$mail_subject = 'Your shift has been replaced';
+@mail_cc = (
+  'ivan-misconfigured-shift-cc@420.am',
+  'ivan-misconfigured-shift-cc2@420.am',
+);
+$mail_footer = <<END;
+
+Sorry, I don't have any more information.  The person who installed the 
+staff sheet didn't customize this message.
+
+END
+
+###
+# end of user-servicable parts
+###
+
+ +

Use

+ +

+ To use the files, install shift.cgi in a public web directory as a CGI program. (probably by placing it in a cgi-bin directory or using AddHandler). Permissions for all files must be set correctly. To make the shift.cgi excecutable, set its permissions to 755 (rwxr-xr-x):
+

chmod 755 shift.cgi

+ To create the the data directory:
+
mkdir /path/to/data_dir

+ The data directory needs to be writable by the user executing the CGI. It's probably best to simply make the data directory owned by the user as which shift.cgi runs (probably the user as which the web server answers requests, unless you are using suEXEC), and set its permissions to 755:
+
chown httpd /path/to/data_dir
+chmod 755 /path/to/data_dir
+

+ +

Contact

+ +

+ Any questions or problems with the staffing sheet should be directed at mike@viberation.com or goolie@cloudfactory.org - We'd be happy to answer reasonable questions about the functions of the staffing list program.
+

+ +
+ + + + + + + +
+
+ +
+ + + + + + -- 2.11.0