#####################################################################
### ###
### M U L T I P L E F I L E U P L O A D ###
### Modified: 30 Mar 2003 ###
### ###
### Mod based on a script created by ###
### Jeff Carnahan jeffc@terminalp.com ###
### Adapted for use by DBMan by ###
### JPDeni deni@jpdeni.com ###
### Integration with DBMan script by ###
### Jim Kangosjärvi Jim.Kangosjarvi@Abc.se ###
### ###
#####################################################################
# #
# This modification will allow you to add file uploading capability #
# to your database. Users can upload multiple files per record. The #
# most common use of the mod will probably be to upload graphic #
# files to accompany a record. #
# #
# The mod creates a directory for the files with a name to match #
# the key value of the associated record. #
# #
# This script requires that the CGI.pm module is installed on your #
# system. It probably is, but if you run into problems, you might #
# ask your server admin if the CGI.pm module is installed. #
# #
# You will not be able to use the autogenerate feature of DBMan with#
# this mod. You must create your own html_record and #
# html_record_form subroutines. #
# #
#####################################################################
#####################################################################
# Create a directory in your public html directory -- the place #
# where you normally put web pages -- for the graphics to be #
# uploaded. On most systems, this should *not* be within the #
# cgi-bin. #
# #
# Set the permissions for this directory to 777. #
#####################################################################
#####################################################################
# file: default.cfg #
# #
# add the following field to your field definitions #
#####################################################################
# If you want to require at least one graphic to be uploaded when a
# record is added
Graphic => [11,'alpha',0,3,1,'','Yes']
# If you uploading a file is optional
Graphic => [11,'alpha',0,3,0,'','Yes']
# (Change the field number to fit with your database definition.)
# If you wish users to be able to search for records that have at least
# one graphic associated with them, add the following. You will also
# need to add a checkbox field to your search form.
%db_checkbox_fields = ( Graphic => 'Yes' );
#####################################################################
# file: default.cfg #
# #
# After the Authorization Options section #
# add the following #
#####################################################################
# File upload parameters
# --------------------------------------------------------
#
# File uploads -- if you want to be able to upload files, set this to 1
$db_upload = 1;
# Full path to directory for uploaded files -- NOT A URL!!!! No trailing slash please.
$SAVE_DIRECTORY = "/home/username/public_html/uploads";
# Full URL to directory for uploaded files. No trailing slash please.
$SAVE_DIRECTORY_URL = "http://www.server.com/uploads";
# Defines the total number of bytes that can be uploaded. Files that exceed
# this limit will not be saved on the server. Set this to zero in order to
# disable size checking.
$MAXIMUM_UPLOAD = 50000;
# Defines the total number of files that can be attached to a file. If a user
# tries to exceed the limit, no files will be added. You must set this to a value.
# It cannot be 0.
$MAXIMUM_FILES = 5;
# List of allowable file extensions. If the file does not have one of the extensions
# listed, it will not be saved to the server. The format for the setting is
# \.[extension]$ If you want to allow more than one extension, separate the options by
# a | character. Note that case counts!
$ALLOWED_EXT = '\.gif$|\.jpg$|\.GIF$|\.JPG$';
######################################################################
# file: db.cgi #
# after #
# $db_script_path = "."; #
# add the following #
######################################################################
use CGI;
$query = new CGI;
######################################################################
# file: db.cgi #
# sub parse_form #
# replace subroutine with the following #
######################################################################
sub parse_form {
# --------------------------------------------------------
my (%in);
my ($buffer, $pair, $name, $value);
PAIR: foreach $name ($query->param()) {
$value = $query->param("$name");
$name =~ tr/+/ /;
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$value =~ s///g;
if ($value eq "---") { next PAIR; }
(exists $in{$name}) ?
($in{$name} .= "~~$value") :
($in{$name} = $value);
}
return %in;
}
######################################################################
# file: db.cgi #
# sub add_record #
######################################################################
# before
$status = &validate_record;
# add
if ($in{'file-to-upload-1'}) { $in{'Graphic'} = 'Yes'; }
else { $in{'Graphic'} = ''; }
# after #
# while ($status eq "duplicate key error" and $db_key_track) { #
# return "duplicate key error" if ($counter++ > 50); #
# $in{$db_key}++; #
# $status = &validate_record; #
# } #
# add
if (($status eq "ok") && ($in{'file-to-upload-1'})) { $status = &validate_upload; } #Validate Pictures
######################################################################
# file: db.cgi #
# sub validate_upload #
# new subroutine #
######################################################################
sub validate_upload {
# --------------------------------------------------------
my ($filekey,$filename,$extlength,$filehandle,$totalbytes,$buffer,$bytes,@extensions,@ext,
$newdirname,$dirsuccess,$num_files,$prev_files,$prev_bytes);
$| = 1;
if (!(-e $SAVE_DIRECTORY)) {
return "The directory doesn't exist. Make sure that this directory is a complete path name,
not a URL or something similar. It should look similar to
/home/username/public_html/uploads";
}
if (!(-W $SAVE_DIRECTORY)) {
return "The directory isn't writable. Make sure that this directory is writable by all users.
At your UNIX command prompt, type chmod 777 $SAVE_DIRECTORY";
}
if (!(-d $SAVE_DIRECTORY)) {
return "The directory you specified isn't really a directory.
Make sure that this is indeed a directory and not a file.";
}
$newdirname = $in{$db_key};
if (!(-e "$SAVE_DIRECTORY/$newdirname")) {
$dirsuccess = mkdir "$SAVE_DIRECTORY/$newdirname", 0777;
}
else {
opendir (GRAPHIC, $SAVE_DIRECTORY/$newdirname) or &cgierr("unable to open directory. Reason: $!");
@files = readdir(GRAPHIC);
closedir (GRAPHIC);
foreach $file (@files) {
next if ($file =~ /^\./); # Skip "." and ".." entries..
next if ($file =~ /^index/); # Skip index.htm type files..
++$prev_files;
@stats = stat "$SAVE_DIRECTORY/$newdirname/$file";
$prev_bytes +=$stats[7];
}
}
foreach $key (sort {$a <=> $b} $query->param()) {
next if ($key =~ /^\s*$/);
next if ($query->param($key) =~ /^\s*$/);
next if ($key !~ /^file-to-upload-(\d+)$/);
$Number = $1;
++$num_files;
if ($query->param($key) =~ /([^\/\\]+)$/) {
$filename = $1;
$File_Handle = $query->param($key);
unless ($filename =~ /$ALLOWED_EXT/) {
$ALLOWED_EXT =~ s/\\//g;
$ALLOWED_EXT =~ s/\$//g;
@ext = split (/\Q|\E/o,$ALLOWED_EXT);
$ALLOWED_EXT = join(" or ",@ext);
return "Only files with the following extension(s) are allowed: $ALLOWED_EXT";
}
}
else {
return "You attempted to upload $filekey that isn't properly formatted. Please rename the file
on your computer, and attempt to upload it again. Files may not have forward or backward slashes in
their names. Also, they may not be prefixed with one (or more) periods.";
}
if (!open(OUTFILE, ">$SAVE_DIRECTORY\/$newdirname\/$filename")) {
return "There was an error opening '$SAVE_DIRECTORY\/$newdirname\/$filename' for Writing.\n";
}
binmode(OUTFILE); # This is needed to work on Windows/NT platforms.
undef $BytesRead;
undef $Buffer;
while ($bytes = read($File_Handle,$buffer,1024)) {
$totalbytes += $bytes;
print OUTFILE $buffer;
}
push(@Files_Written, "$SAVE_DIRECTORY\/$newdirname\/$filename");
close($File_Handle);
close(OUTFILE);
chmod (0666, "$SAVE_DIRECTORY\/$newdirname\/$filename");
}
if (($totalbytes + $prev_bytes) > $MAXIMUM_UPLOAD && $MAXIMUM_UPLOAD > 0) {
foreach $written (@Files_Written) {
unlink "$written";
}
return "You have exceeded your upload limit for this record.
Your files contain $totalbytes bytes.
Combined with previous uploads totaling $prev_bytes, this
exceeds the maximum limit of $MAXIMUM_UPLOAD bytes per record.
Your files were not saved.
Please try again.";
}
if (($num_files + $prev_files) > $MAXIMUM_FILES) {
foreach $written (@Files_Written) {
unlink "$written";
}
return "You have exceeded your upload limit for this record.
You uploaded $num_files files.
Combined with previous $prev_files uploads, this
exceeds the maximum limit of $MAXIMUM_FILES files per record.
Your files were not saved.
Please try again.";
}
return "ok";
}
######################################################################
# file: db.cgi #
# sub delete_records #
# #
# if you want to delete the associated files when a record is #
# delete, change #
# #
# $delete_list{$data[$db_key_pos]} ? #
# ($delete_list{$data[$db_key_pos]} = 0) : #
# ($output .= $line . "\n"); #
# #
# to the following: #
# #
# IMPORTANT!!!! Do *not* delete the } which follows the line #
# ($output .= $line . "\n"); #
# in the subroutine. If you get a syntax error, the first place you #
# should look is to be sure you have not removed the bracket. #
######################################################################
if ($delete_list{$data[$db_key_pos]}) { # if this id is one we want to delete
$delete_list{$data[$db_key_pos]} = 0; # then mark it deleted and don't print it to the new database.
if ($db_upload) {
if (-e "$SAVE_DIRECTORY/$data[$db_key_pos]") {
opendir (GRAPHIC, "$SAVE_DIRECTORY/$data[$db_key_pos]") or &cgierr("unable to open directory in delete records: $SAVE_DIRECTORY/$data[$db_key_pos]. Reason: $!");
@files = readdir(GRAPHIC);
closedir (GRAPHIC);
foreach $file (@files) {
unlink ("$SAVE_DIRECTORY/$data[$db_key_pos]/$file");
}
rmdir "$SAVE_DIRECTORY/$data[$db_key_pos]";
}
}
}
else { $output .= $line . "\n"; }
######################################################################
# file: db.cgi #
# sub modify_record #
# replace subroutine #
######################################################################
sub modify_record {
# --------------------------------------------------------
# This routine does the actual modification of a record. It expects
# to find in %in a record that is already in the database, and will
# rewrite the database with the new entry. First it checks to make
# sure that the modified record is ok with validate record.
# It then goes through the database looking for the right record to
# modify, if found, it prints out the modified record, and returns
# the user to a success page. Otherwise the user is returned to an error
# page with a reason why.
my ($status, $line, @lines, @data, $output, $found, %rec, $key, $num_files, @files, $file);
if ($auth_modify_own and !$per_admin) {
%rec = &get_record($in{$db_key});
unless ($rec{$db_cols[$auth_user_field]} eq $db_userid) {
&html_modify_failure("You are not authorized to modify this record");
return;
}
}
foreach $key (keys %in) {
if ($in{$key} eq 'delete') {
unlink "$SAVE_DIRECTORY/$in{$db_key}/$key";
}
}
$num_files=0;
if (-e "$SAVE_DIRECTORY/$in{$db_key}") {
opendir (GRAPHIC, "$SAVE_DIRECTORY/$in{$db_key}") or &cgierr("unable to open directory: $SAVE_DIRECTORY/$rec{$db_key}. Reason: $!");
@files = readdir(GRAPHIC);
closedir (GRAPHIC);
foreach $file (@files) {
next if ($file =~ /^\./); # Skip "." and ".." entries..
next if ($file =~ /^index/); # Skip index.htm type files..
++$num_files;
}
}
if ($num_files or $in{'file-to-upload-1'}) { $in{'Graphic'} = 'Yes'; }
else { $in{'Graphic'} = ''; }
$status = &validate_record; # Check to make sure the modifications are ok!
if (($status eq "ok") && ($in{'file-to-upload-1'})) { $status = &validate_upload; } #Validate Pictures
if ($status eq "ok") {
open (DB, "<$db_file_name") or &cgierr("error in modify_records. unable to open db file: $db_file_name.\nReason: $!");
if ($db_use_flock) { flock(DB, 1); }
@lines = ; # Slurp the database into @lines..
close DB;
$found = 0; # Make sure the record is in here!
LINE: foreach $line (@lines) {
if ($line =~ /^$/) { next LINE; } # Skip and Remove blank lines
if ($line =~ /^#/) { $output .= $line; next LINE; } # Comment Line
chomp ($line);
@data = &split_decode($line);
if ($data[$db_key_pos] eq $in{$db_key}) {
# If we have userid's and this is not an admin, then we force the record to keep it's own
# userid.
if ($auth_user_field >= 0 and (!$per_admin or !$in{$db_cols[$auth_user_field]})) {
$in{$db_cols[$auth_user_field]} = $data[$auth_user_field];
}
$output .= &join_encode(%in);
$found = 1;
}
else {
$output .= $line . "\n"; # else print regular line.
}
}
if ($found) {
open (DB, ">$db_file_name") or &cgierr("error in modify_records. unable to open db file: $db_file_name.\nReason: $!");
if ($db_use_flock) {
flock(DB, 2) or &cgierr("unable to get exclusive lock on $db_file_name.\nReason: $!");
}
print DB $output;
close DB; # automatically removes file lock
&auth_logging("modified record: $in{$db_key}") if ($auth_logging);
&html_modify_success;
}
else {
&html_modify_failure("$in{$db_key} (can't find requested record)");
}
}
else {
&html_modify_failure($status); # Validation Error
}
}
######################################################################
# file: html.pl #
# sub html_record #
# #
# after #
# my (%rec) = @_; #
# #
# add #
# #
######################################################################
$rec{$db_key} =~ s/<.?B>//g;
### Wherever you want your graphics to print out, use the following:
|;
if (-e "$SAVE_DIRECTORY/$rec{$db_key}") {
opendir (GRAPHIC, "$SAVE_DIRECTORY/$rec{$db_key}") or &cgierr("unable to open directory: $SAVE_DIRECTORY/$rec{$db_key}. Reason: $!");
@files = readdir(GRAPHIC);
closedir (GRAPHIC);
foreach $file (@files) {
next if ($file =~ /^\./); # Skip "." and ".." entries..
next if ($file =~ /^index/); # Skip index.htm type files..
print qq||;
}
}
print qq|
######################################################################
# If you are using the long/short display mod, you will need to make #
# the same changes in sub html_record_long that you made in #
# sub html_record. Or, if you prefer, you can just make the changes #
# in sub html_record_long. #
######################################################################
######################################################################
# file: html.pl #
# sub html_record_form #
# probably near the bottom of the form, but before the closing #
# tag #
# #
# add #
# #
######################################################################
|;
if ($form_upload_add) {
print qq|
You may upload up to $MAXIMUM_FILES files, for a total of
$MAXIMUM_UPLOAD bytes.
|;
for ($u=1;$u<=$MAXIMUM_FILES ;++$u) {
print qq|
Browse Picture:
|;
}
}
if ($form_upload_mod) {
if (-e "$SAVE_DIRECTORY/$rec{$db_key}") {
opendir (GRAPHIC, "$SAVE_DIRECTORY/$rec{$db_key}") or &cgierr("unable to open directory: $SAVE_DIRECTORY/$rec{$db_key}. Reason: $!");
@files = readdir(GRAPHIC);
closedir (GRAPHIC);
foreach $file (@files) {
next if ($file =~ /^\./); # Skip "." and ".." entries..
next if ($file =~ /^index/); # Skip index.htm type files..
++$num_files;
@stats = stat "$SAVE_DIRECTORY/$rec{$db_key}/$file";
$prev_bytes +=$stats[7];
}
foreach $file (@files) {
next if ($file =~ /^\./); # Skip "." and ".." entries..
next if ($file =~ /^index/); # Skip index.htm type files..
print qq|
You currently have $num_files files associated with this record, for a
total of $prev_bytes bytes. You may upload up to $new_files additional files, with a total byte
size of $new_bytes bytes.
|;
for ($u=1;$u<=$new_files ;++$u) {
print qq|
Browse Picture:
|;
}
}
print qq|
######################################################################
# file: html.pl #
# sub html_add_form #
# sub html_add_failure #
# add #
# right at the beginning of the subroutines #
######################################################################
$form_upload_add = 1;
######################################################################
# file: html.pl #
# sub html_modify_form_record #
# sub html_modify_failure #
# add #
# right at the beginning of the subroutines #
######################################################################
$form_upload_mod = 1;
######################################################################
# file: html.pl #
# sub html_add_form #
# sub html_add_failure #
# sub html_modify_form_record #
# sub html_modify_failure #
# change #
#