#!/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.6 2003-07-30 22:16:36 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 = '/var/www/www.420.am/staff/table.html'; $data_directory = '/var/www/www.420.am/staff/data'; #$mail_smtpserver = 'localhost'; # set blank to disable $mail_smtpserver = ''; # 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") =~ /^\s*(\w[\w\s\.\'\-]{0,99}?)\s*$/ || $cgi->param($field. "_new") =~ /^\s*()$/ ) { my $new = $1; open(FILE,">$data_directory/.new.$field") or die "Can't open file $data_directory/$field: $!"; print FILE $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", '"'. $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 { $magic = defined $cgi->param('__MAGIC') ? $cgi->param('__MAGIC') : ''; $cgi->delete_all(); $cgi->start_form(); } sub inputbox { my $field = shift; return encode_entities($shifthash{$field}) || " " if $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; }