#!/www/perl/bin/perl.exe
#
# ajaxupload.cgi
#
# This program is the copyrighted work of Encodable Industries.
# You may not redistribute it; instead simply refer people to
# the homepage to get their own free copy. Â You are free to
# modify the program for your own use, but you may not distribute
# any modified copies of it.
#
# Homepage: http://encodable.com/tech/ajaxupload/
# Contact: http://encodable.com/contact/
my %PREF = ();
###
### User preferences section: adjust these variables
### to suit your own server/setup/tastes.
###
# Title appearing at the top of the page.
$PREF{title} = 'Poster Uploader';
# Choose whether the script should display a link to the list of
# uploaded files.
$PREF{show_link_to_uploads} = 'no';
# THIS IS A SECURITY HAZARD. Â ONLY ENABLE IT WHILE DEBUGGING.
$PREF{show_errors_in_browser} = 'yes';
# Set the maximum size file that can be uploaded. Â One megabyte
# is 1024*1024*1; 5 MB is 1024*1024*5, etc.
$PREF{sizelimit} = 1024*1024*150;
# By default, if you upload a file that's 1 megabyte or bigger,
# the file sizes and upload rate will be in MB and MB/s. Â If
# you want to force them to always be in KB instead, set this.
$PREF{force_KB_sizes} = 'no';
# Password hashes (optional): if you want to require a password
# for access to the uploader and/or the list of uploaded files,
# you need to set these. Â Go to:
#
# Â Â yoursite.com/cgi-bin/upload/ajaxupload.cgi?makePasswordHash
#
# ...enter the password you want to use into that page, and it
# will generate a "hash" of the password, which is a string that
# looks something like this:
#
# Â Â cdfc81932491375c34c842bcebc7dc15
#
# Copy and paste the hash into one of the following preferences.
# Then when you want to log in, enter the password, not the hash.
# (This is so that we don't store the actual password on disk, which
# would be very insecure.)
#
# We specify two possible user-levels: member and admin. Â If you
# want, you can use just one of them, and have a single password
# for both uploading and viewing the file-list. Â Or you can specify
# both, and set the "must_be_" preferences accordingly, so that only
# the admin can view the uploaded files. Â Or vice-versa. Â Or you
# could require no password to view the file-list, but require one
# to upload. Â Etc, etc. Â Just set the prefs accordingly.
#
# Note that the admin is automatically a "member" too, so someone
# with the admin password automatically has access to anything that
# requires the member password.
#
# Finally, note that to delete uploaded files, you must be logged
# in as admin. Â So you probably at least want to create the admin
# password hash, even if you don't set any of the upload/list prefs
# to yes.
#
$PREF{member_password_hash} = '';
$PREF{admin_password_hash} = '';
$PREF{must_be_member_to_upload} = 'no';
$PREF{must_be_admin_to_upload} = 'no';
$PREF{must_be_member_to_list_files} = 'no';
$PREF{must_be_admin_to_list_files} = 'no';
# Once you allow someone to download a file from your uploads area,
# they will know the path to all your uploads. Â If you don't want
# them to be able to see all the other files by just visiting that
# directory's address, you'll need to put a .htaccess file in that
# directory with the line "Options -Indexes" (without quotes).
# However, as long as they know the address, they can still try to
# guess filenames that might be in there. Â As an extra security
# precaution, you can set serialize_all_uploads, which adds a long
# pseudo-random number to each filename, making it virtually
# impossible that someone could guess the name of a file in the
# directory.
$PREF{serialize_all_uploads} = 'yes';
# This is where the uploaded files will go. Â It must be world-readable
# and world-writable, aka "chmod a+rwx" or "chmod 0777". Â Set this to
# "/dev/null" if you want the files to not be saved at all. Â Note that
# this is relative to your server's $ENV{DOCUMENT_ROOT}, so if you set
# it to '/uploads' then it will be at mysite.com/uploads.
$PREF{uploaded_files_dir} = '/upload/posters';
# If you're using SSI (<!--#include virtual="/cgi-bin/upload/ajaxupload.cgi?$QUERY_STRING" -->)
# or a PHP include (<?PHP virtual("/cgi-bin/upload/ajaxupload.cgi"); ?>)
# to display this script at a shorter URL (like mysite.com/upload/ instead
# of mysite.com/cgi-bin/upload/ajaxupload.cgi) then enter that shorter URL here.
# Otherwise leave it set to $ENV{SCRIPT_NAME}.
$PREF{here} = $ENV{SCRIPT_NAME};
# This is where logfiles are stored. Â (The logs are crucial to the functioning
# of this program.) Â It's relative to the value of $ENV{SCRIPT_NAME}; i.e. if
# the script name is /cgi-bin/upload/ajaxupload.cgi and you set logpath to 'logs'
# then it'll be at /cgi-bin/upload/logs/. Â This must be world-readable and
# world-writable too.
$PREF{logpath} = 'logs';
###
### End of user preferences section. Â You probably don't want to mess with
### anything below here unless you really know what you're doing.
###
# Error logger
open STDERR, ">>/www/cgi-bin/error.log" or die $!;
my $version = 20051103;
if($ENV{QUERY_STRING} eq 'version') { print "Content-type: text/plain\n\n"; print "$version\n"; exit; }
my ($cwd) = ($ENV{SCRIPT_FILENAME} =~ m!^(.+)/.*?$!);
chdir $cwd;
$| = 1;
use strict;
#use warnings;
if($PREF{show_errors_in_browser} =~ /yes/i)
{
use CGI::Carp 'fatalsToBrowser';
}
use CGI;
use CGI qw/:standard/;
$CGI::POST_MAX = $PREF{sizelimit} =~ /^\d+$/ ? $PREF{sizelimit} : 1024 * 1024 * 150; Â # max 3MB posts
load_prefs();
my $output_started = 0;
my $qs
= $ENV{QUERY_STRING};
my $starttime = time;
my $total_upload_size = ();
if($qs =~ /serial=(\d+)&action=get_progress_and_size/)
{
print "Cache-Control: no-store, no-cache\n";
print "Content-type: text/xml\n\n";
my ($progress,$size,$elapsedtime) = get_progress_and_size($1);
my $toobig = $size > $CGI::POST_MAX ? '|toobig' : '';
my $output = "$progress|$size|$elapsedtime$toobig";
print $output;
}
elsif($qs eq 'listfiles')
{
list_uploaded_files();
}
elsif($qs eq 'makePasswordHash')
{
make_password_hash();
}
elsif($qs =~ /(?:^login$|action=login&target=(.+?)(&|$))/)
{
do_login($1);
}
elsif($qs eq 'logout')
{
do_logout();
}
elsif($qs =~ /action=delete&file=(.+?)(!ly=yes)?(?:&|$)/)
{
delete_file($1,$2);
}
elsif($ENV{REQUEST_METHOD} =~ /post/i)
{
process_upload();
}
else
{
print_new_upload_form();
}
sub print_new_upload_form()
{
do_authentication('upload','redirect');
start_html_output('Upload a file', 'css', 'js');
print qq`
<div id="title">$PREF{title}</div>
<form name="theuploadform" method="post" onsubmit="startprogress()" enctype="multipart/form-data" action="$ENV{SCRIPT_NAME}?serial=$PREF{serial}">
`;
print  qq`<div id="intro">$PREF{intro}</div>\n\n` if $PREF{intro};
print qq`
Datei zum hochladen wählen:
<br /><br /><input type="file" name="uploadname" id="uploadfilefield" />
<br /><br /><input type="submit" value="Bild hochladen" id="uploadbutton" />
</form>
<div id="progressMeter" style="display: none;">
<div id="progressMeterText"></div>
<div id="progressMeterBar">
<div id="progressMeterBarDone"></div>
</div>
<div id="transferRate">uploading data at: ?</div>
<table>
<tr id="upload-row-1"><td id="tca1"></td><td id="tca2" class="headercell">Completed</td><td id="tca3" class="headercell">Remaining</td><td id="tca4" class="headercell">Total</td></tr>
<tr id="upload-row-2"><td id="tcb1" class="headercell">Time</td><td id="donet">0</td><td id="leftt">?</td><td id="totalt">?</td></tr>
<tr id="upload-row-3"><td id="tcc1" class="headercell">Size</td><td id="dones">0</td><td id="lefts">?</td><td id="totals">?</td></tr>
</table>
</div>
`;
print_footer_links('list','logout','login');
finish_html_output();
}
sub hook
{
my ($filename, $buffer, $bytes_read, $logfh) = @_;
flock $logfh, 2; # lock the log
seek $logfh, 0, 0; # seek to the beginning
print $logfh "${bytes_read}:${total_upload_size}:${starttime}"; # print the new size
truncate $logfh, tell $logfh; # truncate the file (on the off chance that the new size is less than the old)
flock $logfh, 8; # release the lock
}
sub get_progress_and_size
{
do_authentication('progress','redirect');
my $serial = shift;
my ($line,$progress,$size,$start_time,$elapsedtime) = ();
my $logfile = "$PREF{'logpath'}/$serial.log";
if(-T $logfile)
{
open(READLOGFILE,"<$logfile") or die "$0: couldn't open $logfile for reading: $!\n";
flock READLOGFILE, 1;
seek READLOGFILE, 0, 0;
$line = <READLOGFILE>;
close READLOGFILE or die "$0: couldn't close $logfile after reading: $!\n";
($progress,$size,$start_time) = split(/:/, $line);
$elapsedtime = time - $start_time;
}
return ($progress,$size,$elapsedtime);
}
sub process_upload()
{
do_authentication('upload','redirect');
($PREF{serial}) = ($qs =~ /(?:^|&)serial=(\d+)(?:&|$)/);
$total_upload_size = $ENV{CONTENT_LENGTH};
my $logfile = "$PREF{logpath}/$PREF{serial}.log";
open(my $logfh,">$logfile") or die "$0: couldn't open $logfile for writing: $!\n";
flock $logfh, 2;
seek $logfh, 0, 0;
print $logfh "0:${total_upload_size}:$starttime";
flock $logfh, 8;
  my $query = CGI->new(\&hook,$logfh);
my $serial = $PREF{serial};
my $filename = $query->param('uploadname');
$filename =~ s/^.*[\\\/]//; # remove any path info.
my $filesize = ();
my $file_ext = 'null';
($filename,$file_ext) = ($filename =~ /(.+)\.(.+)$/);
my $upload_filehandle = $query->upload('uploadname');
my $fullfile = "$PREF{DOCROOT}$PREF{uploaded_files_dir}/$filename.$serial.$file_ext";
my $fullfile_noserial = "$PREF{DOCROOT}$PREF{uploaded_files_dir}/$filename.$file_ext";
my $finalfile = "$PREF{uploaded_files_dir}/$filename.$serial.$file_ext";
if($ENV{CONTENT_LENGTH} > $CGI::POST_MAX)
{
print "Content-type: text/plain\n\n";
print "ERROR: you tried to send $ENV{CONTENT_LENGTH} bytes,\nbut the current limit is $CGI::POST_MAX bytes.\nPlease go back and choose a smaller file.\n";
exit;
}
elsif(!$query->param('uploadname'))
{
print "Content-type: text/plain\n\n";
print "ERROR: the upload file-field is blank.\nEither you didn't choose a file, or there's some problem with your server.\nMaybe you need a newer version of the CGI.pm module?\nOr maybe your webhost/server doesn't allow file uploads?\n";
exit;
}
unless($PREF{uploaded_files_dir} eq '/dev/null')
{
open(UPLOADFILE,">$fullfile") or die "$0: couldn't create file $fullfile: $!\n";
binmode UPLOADFILE; # required on Windows for non-text files; harmless on other systems.
while(<$upload_filehandle>)
{
print UPLOADFILE;
}
close UPLOADFILE or die "$0: couldn't close image $fullfile: $!\n";
chmod 0666, $fullfile;
$filesize = (stat($fullfile))[7];
# remove the serial number only if a file by the same name doesn't already exist.
if( Â (! -e $fullfile_noserial) Â && Â ($PREF{serialize_all_uploads} !~ /yes/i) Â )
{
rename($fullfile, $fullfile_noserial);
$finalfile =~ s/\.$serial//;
}
}
close $logfh or die "$0: couldn't close $logfile after writing: $!\n";
chmod 0666, $logfile;
$filesize = $ENV{CONTENT_LENGTH} unless $filesize;
$filesize = $filesize > 999999 ? onedecimal($filesize/(1024*1024)) . ' MB' : int($filesize/1024) . ' KB';
my $linktofile = (!user_has_list_rights() || ($PREF{uploaded_files_dir} eq '/dev/null')) ? "$filename.$file_ext" : qq`<a href="$finalfile" target="_blank">$filename.$file_ext</a>`;
start_html_output('Upload complete', 'css');
print  qq`\n <IMG SRC=/phpthumb/phpThumb.php?src=$finalfile&h=70 border=0 alt=$filename> Ihre Datei: $filename ($filesize) wurde erfolgreich hochgeladen.
<form name="print" method="get" action="managecart.php" target="_top">
gewünschtes Druckformat:
<input type="hidden" name="PRICE" id="PRICE" value="">
<input type="hidden" name="NAME" id="NAME" value="">
<input type="hidden" name="ID_NUM" id="ID_NUM" value="">
<input type="hidden" name="SHIPPING" value="0">
<input type="hidden" name="LIMIT" value="5">
<input type="hidden" name="Thumb" id="Thumb" value="<IMG SRC=/phpthumb/phpThumb.php?src=$finalfile&h=70 border=0 alt=$filename>">
<select name="PRODUCTSELECTOR">
      <option selected="selected" name="select32" style="font-weight:bold;">---- 3:2 Formate ----</option>
<option cost="3.99" id_num="$filename.$file_ext" name="Poster 30 x 45 cm (Art.-Nr.: 003) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$finalfile&h=70 border=0 alt=$filename>">Poster 30 x 45 cm = 3.99 EUR </option>
<option cost="5.99" id_num="$filename.$file_ext" name="Poster 40 x 60 cm (Art.-Nr.: 002) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 40 x 60 cm = 5.99 EUR </option>
<option cost="8.99" id_num="$filename.$file_ext" name="Poster 50 x 75 cm (Art.-Nr.: 004) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 50 x 75 cm = 8.99 EUR </option>
<option cost="12.99" id_num="$filename.$file_ext" name="Poster 60 x 90 cm (Art.-Nr.: 005) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 60 x 90 cm = 12.99 EUR </option>
<option cost="21.99" id_num="$filename.$file_ext" name="Poster 80 x 120 cm (Art.-Nr.: 012) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 80 x 120 cm = 21.99 EUR </option>
<option cost="42.99" id_num="$filename.$file_ext" name="Poster 100 x 150 cm (Art.-Nr.: 014) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 100 x 150 cm = 42.99 EUR </option>
      <option name="select43" style="font-weight:bold;">---- 4:3 Formate ----</option>
<option cost="3.89" id_num="$filename.$file_ext" name="Poster 30 x 40 cm (Art.-Nr.: 015) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 30 x 40 cm = 3.89 EUR </option>
<option cost="5.99" id_num="$filename.$file_ext" name="Poster 45 x 60 cm (Art.-Nr.: 016) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 45 x 60 cm = 5.99 EUR </option>
<option cost="11.99" id_num="$filename.$file_ext" name="Poster 60 x 80 cm (Art.-Nr.: 017) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 60 x 80 cm = 11.99 EUR </option>
<option cost="25.99" id_num="$filename.$file_ext" name="Poster 90 x 120 cm (Art.-Nr.: 018) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 90 x 120 cm = 25.99 EUR </option>
<option cost="39.99" id_num="$filename.$file_ext" name="Poster 105 x 140 cm (Art.-Nr.: 019) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 105 x 140 cm = 39.99 EUR </option> Â Â Â Â Â
      <option name="selectDIN" style="font-weight:bold;">---- DIN Formate ----</option>
    <option cost="5.99" id_num="$filename.$file_ext" name="DIN A2 (59 x 42 cm) (Art.-Nr.: 020) Poster von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">DIN A2 Print = 5.99 EUR </option>
    <option cost="9.99" id_num="$filename.$file_ext" name="DIN A1 (84 x 59 cm) (Art.-Nr.: 021) Poster von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">DIN A1 Print = 9.99 EUR </option>
    <option cost="19.99" id_num="$filename.$file_ext" name="DIN A0 (112 x 84 cm) (Art.-Nr.: 022) Poster von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">DIN A0 Print = 19.99 EUR </option>
    <option cost="35.99" id_num="$filename.$file_ext" name="DIN B0 (145 x 103 cm) (Art.-Nr.: 023) Poster von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">DIN B0 Print = 35.99 EUR </option>
    <option name="selectPano" style="font-weight:bold;">---- Panorama Formate ----</option>
    <option cost="6.99" id_num="$filename.$file_ext" name="Pano 30 x 90 cm (Art.-Nr.: 024) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Pano 30 x 90 cm = 6.99 EUR </option>
    <option cost="8.99" id_num="$filename.$file_ext" name="Pano 30 x 120 cm (Art.-Nr.: 025) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Pano 30 x 120 cm = 8.99 EUR </option>
    <option cost="12.99" id_num="$filename.$file_ext" name="Pano 40 x 120 cm (Art.-Nr.: 026) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Pano 40 x 120 cm = 12.99 EUR </option>
    <option cost="16.99" id_num="$filename.$file_ext" name="Pano 40 x 160 cm (Art.-Nr.: 027) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Pano 40 x 160 cm = 16.99 EUR </option>
<option cost="21.99" id_num="$filename.$file_ext" name="Pano 50 x 150 cm (Art.-Nr.: 028) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Pano 50 x 150 cm = 21.99 EUR </option>
      <option cost="29.99" id_num="$filename.$file_ext" name="Pano 50 x 200 cm (Art.-Nr.: 029) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Pano 50 x 200 cm = 29.99 EUR </option>     Â
<option cost="59.99" id_num="$filename.$file_ext" name="Pano 100 x 200 cm (Art.-Nr.: 030) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Pano 100 x 200 cm = 59.99 EUR </option>
      <option name="selectPost" style="font-weight:bold;">---- Poster Formate ----</option>
<option cost="7.99" id_num="$filename.$file_ext" name="Poster 50 x 70 cm (Art.-Nr.: 031) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 50 x 70 cm = 7.99 EUR </option>
      <option cost="16.99" id_num="$filename.$file_ext" name="Poster 70 x 100 cm (Art.-Nr.: 032) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">Poster 70 x 100 cm = 16.99 EUR </option>
      <option name="selectQuad" style="font-weight:bold;">---- Quadratische Formate ----</option>
      <option cost="4.99" id_num="$filename.$file_ext" name="QFormat 40 x 40 cm (Art.-Nr.: 033) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">QFormat 40 x 40 cm = 4.99 EUR </option>
      <option cost="6.99" id_num="$filename.$file_ext" name="QFormat 50 x 50 cm (Art.-Nr.: 034) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">QFormat 50 x 50 cm = 6.99 EUR </option>
      <option cost="9.99" id_num="$filename.$file_ext" name="QFormat 60 x 60 cm (Art.-Nr.: 035) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">QFormat 60 x 60 cm = 9.99 EUR </option>
      <option cost="12.99" id_num="$filename.$file_ext" name="QFormat 70 x 70 cm (Art.-Nr.: 036) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">QFormat 70 x 70 cm = 12.99 EUR </option>
      <option cost="15.99" id_num="$filename.$file_ext" name="QFormat 80 x 80 cm (Art.-Nr.: 037) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">QFormat 80 x 80 cm = 15.99 EUR </option>
      <option cost="22.99" id_num="$filename.$file_ext" name="QFormat 90 x 90 cm (Art.-Nr.: 038) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">QFormat 90 x 90 cm = 22.99 EUR </option>
      <option cost="29.99" id_num="$filename.$file_ext" name="QFormat 100 x 100 cm (Art.-Nr.: 039) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">QFormat 100 x 100 cm = 29.99 EUR </option>
      <option cost="35.99" id_num="$filename.$file_ext" name="QFormat 110 x 110 cm (Art.-Nr.: 040) von: *$filename.$file_ext*" shipping="0.00" Thumb="<IMG src=/phpthumb/phpThumb.php?src=$filename.$serial.$file_ext&h=70 border=0 alt=$filename>">QFormat 110 x 110 cm = 35.99 EUR </option>
</select><BR><br />
Anzahl:
<input type=text size=2 maxlength=3 name=QUANTITY onChange='this.value=CKquantity(this.value)' value="1">
Beschneiden?
<input type="image" onClick='AddOneOfManyToCart(print)' src="/images/images/basket_add.gif" name="buy" WIDTH="33" HEIGHT="20" Â border=0 value="Add to Cart" ALT="Add to Cart" align=top>
</form>`
. qq`\n`;
finish_html_output();
}
sub load_prefs()
{
# Some servers seem to not set $ENV{DOCUMENT_ROOT} properly for users who serve pages from their
# home directories, so we'll make our own version based on the start of SCRIPT_FILENAME. Â 99% of
# the time it'll be equal to the normal DOCUMENT_ROOT though.
$PREF{DOCROOT} = $ENV{DOCUMENT_ROOT};
if($ENV{SCRIPT_FILENAME} !~ /^$ENV{DOCUMENT_ROOT}/) # server is screwy!
{
($PREF{DOCROOT}) = ( Â $ENV{SCRIPT_FILENAME} =~ m!^(.+?)/cgi-bin/! Â );
}
my $prefs_file = 'upload_prefs.txt';
if(-T $prefs_file)
{
open(IN,"<$prefs_file") or die "$0: couldn't open $prefs_file: $!\n";
flock IN, 1;
seek IN, 0, 0;
while(<IN>)
{
chomp; next if /^\s*(#|$)/;
my ($pref, $value) = split(/=/, $_, 2);
for($pref, $value)
{
s/\s+$//g;
s/^\s+//g;
}
$PREF{$pref} = $value;
}
close IN or die "$0: couldn't close $prefs_file: $!\n";
}
# Any files in the prefs should be specified WRT server-root, so we'll prepend it here.
$PREF{serial} = time . $$ . $ENV{REMOTE_ADDR} . $ENV{HTTP_USER_AGENT};
$PREF{serial} =~ s/[^\d]//g;
$PREF{title} = 'Encodable Industries' &nb
sp; unless exists $PREF{title};
$PREF{here} = '/cgi-bin/digiupload.cgi' unless exists $PREF{here};
$PREF{logpath} = '/cgi-bin/logs' unless exists $PREF{logpath};
$PREF{uploaded_files_dir} = '/upload/posters' &nb
sp; unless exists $PREF{uploaded_files_dir};
$PREF{max_upload_size} = 1024*1024*150 unless exists $PREF{max_upload_size};
$PREF{show_errors_in_browser} = 'yes' &nb
sp; unless exists $PREF{show_errors_in_browser};
$PREF{show_link_to_uploads} = 'no' &nb
sp; unless exists $PREF{show_link_to_uploads};
$PREF{sizelimit} = 1024*1024*150  
; unless exists $PREF{sizelimit};
$PREF{num_days_login_lasts} = 7  
; unless $PREF{num_days_login_lasts};
}
sub get_js
{
return qq`
<script type="text/javascript">
/* <![CDATA[ */ Â /* so (X)HTML validators ignore the javascript. */
var theRequest = false;
var total_upload_size = 1;
var forceKB = ` . ($PREF{force_KB_sizes} =~ /yes/i ? 1 : 0) . qq`
function goajax(page)
{
theRequest = false;
if(window.XMLHttpRequest)
{
theRequest = new XMLHttpRequest();
if(theRequest.overrideMimeType)
{
theRequest.overrid
eMimeType('text/xml');
}
}
else if(window.ActiveXObject)
{
try
{
theRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try
{
theRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if(!theRequest)
{
alert('Error: could not create XMLHTTP object.');
return false;
}
theRequest.onreadystatechange = updateProgress;
theRequest.open('GET', page, true);
theRequest.send(null);
}
function updateProgress()
{
if(theRequest.readyState == 4)
{
if(theRequest.status == 200)
{
var update = new Array();
update = theRequest.responseText.split('|');
if(update[1] != 0)
{
total_upload_size = update[1];
}
if(update[3] == 'toobig')
{
document.getElementById('progressMeter').innerHTML = 'Error: you tried to send ' +
format_filesize_with_unit(total_upload_size, ' ', 0) +
' (' + total_upload_size + ' bytes), which exceeds the current limit of ' +
format_filesize_with_unit($CGI::POST_MAX, ' ', 0) +
' ($CGI::POST_MAX bytes). Hit the stop button in your browser, ' +
'then <a href="$PREF{here}">click here</a> to choose a smaller file.';
return null;
}
var completed_upload_size = update[0];
var elapsedtime = update[2];
var progressPercent = Math.ceil((completed_upload_size/total_upload_size)*100);
document.getElemen
tById('progressMeterText').innerHTML = 'upload in progress: ' + progressPercent + '%';
document.getElemen
tById('progressMeterBarDone').style.width = parseInt(progressPercent*3.5) + 'px';
var totaltime = parseInt((elapsedtime * 100) / progressPercent);
var totaltime_forprint = format_timespan_with_unit(totaltime, ' ');
var remainingtime_forprint = format_timespan_with_unit(eval(totaltime - elapsedtime), ' ');
var elapsedtime_forprint = format_timespan_with_unit(elapsedtime, ' ');
var force_MB = total_upload_size > 999999 ? 1 : 0;
var total_upload_size_forprint = format_filesize_with_unit(total_upload_size, ' ', force_MB);
var remaining_upload_size_forprint = format_filesize_with_unit(total_upload_size - completed_upload_size, ' ', force_MB);
var completed_upload_size_forprint = format_filesize_with_unit(completed_upload_size, ' ', force_MB);
var transfer_rate = format_filesize_with_unit(completed_upload_size/elapsedtime, ' ', force_MB);
document.getElemen
tById('donet').innerHTML = elapsedtime_forprint;
document.getElemen
tById('dones').innerHTML = completed_upload_size_forprint;
document.getElemen
tById('leftt').innerHTML = remainingtime_forprint;
document.getElemen
tById('lefts').innerHTML = remaining_upload_size_forprint;
document.getElemen
tById('totalt').innerHTML = totaltime_forprint;
document.getElemen
tById('totals').innerHTML = total_upload_size_forprint;
document.getElemen
tById('transferRate').innerHTML = 'uploading data at: ' + transfer_rate + '/s';
window.setTimeout&
("goajax('$ENV{SCRIPT_NAME}?serial=$PREF{serial}&action=get_progress_and_size')", 700);
}
else
{
alert('Error: got a not-OK status code...');
}
}
}
function startprogress()
{
document.getElementById('progressMeter').style.display = 'block';
document.getElementById('progressMeterText').innerHTML = 'upload in progress: 0%';
document.getElementById('uploadbutton').disabled = true;
document.getElementById('uploadfilefield').readonly = true;
window.setTimeout("goajax('$ENV{SCRIPT_NAME}?serial=$PREF{serial}&action=get_progress_and_size')", 1200);
}
function format_filesize_with_unit(num,space,forceMB)
{
var unit;
if( Â ((num > 999999) Â || Â forceMB) Â && Â !forceKB)
{
num = num/(1024*1024);
num = num.toString();
// note extra escaping necessary since we're printing this JS code from Perl...
var testnum = num.replace( /^(\\d+\\.\\d).*/, '\$1' ); // show 1 decimal place.
if(testnum == '0.0')
{
testnum = num.replace( /^(\\d+\\.\\d\\d).*/, '\$1' ); // show 2 decimal places.
}
if(testnum == '0.00')
{
testnum = num.replace( /^(\\d+\\.\\d\\d\\d).*/, '\$1' ); // show 3 decimal places.
}
num = testnum;
unit = 'MB';
}
else
{
num = parseInt(num/(1024));
unit = 'KB';
}
return num + space + unit;
}
function format_timespan_with_unit(num,space)
{
var unit;
if(num >= (60*60))
{
var secs_left = num % (60*60);
var mins_left = secs_left / 60;
mins_left = mins_left.toString();
// note extra escaping necessary since we're printing this JS code from Perl...
mins_left = mins_left.replace( /^(\\d+)\\..*/, '\$1' ); // show no decimal places.
mins_left = mins_left.replace( /^(\\d)\$/, '0\$1' ); // for single-digits, prepend a zero.
num = num/(60*60);
num = num.toString();
// note extra escaping necessary since we're printing this JS code from Perl...
num = num.replace( /^(\\d+)\\..*/, '\$1' ); // show no decimal places.
num = num + space + 'h' + space + mins_left + space + 'm';
space = '';
unit = '';
}
else if(num >= 60)
{
var secs_left = num % 60;
secs_left = secs_left.toString().replace( /^(\\d)\$/, '0\$1' ); // for single-digits, prepend a zero.
num = num/60;
num = num.toString();
// note extra escaping necessary since we're printing this JS code from Perl...
num = num.replace( /^(\\d+)\\..*/, '\$1' ); // show no decimal places.
num = num.replace( /^(\\d)\$/, '0\$1' ); // for single-digits, prepend a zero.
num = num + space + 'm' + space + secs_left + space + 's';
space = '';
unit = '';
}
else
{
unit = 's';
}
return num + space + unit;
}
/* ]]> */ Â /* so (X)HTML validators ignore the javascript. */
</script>
`;
}
sub get_css
{
return qq`
<style type="text/css">
body { background: #ddd; font-family: sans-serif; text-align: center; }
#pb { margin: 14px auto 2px auto; padding: 3px; font-size: 80%; }
#pb a { color: }
#pb a:hover { color: #aaa; }
#footer { color: #aaa; margin: 24px auto 4px auto; }
a { color: #2222bb; }
a:hover { color: #aaa; }
#filelist a:link { color: #2222bb; }
#filelist a:visited { color: }
#filelist a:hover { color: #aaa; }
#progMeterContainer { margin: 14px auto; width: ` . ($qs eq 'listfiles' ? '400px' : '350px') . qq`; background: white; border: 1px solid ϧ padding: 10px; }
#progMeterContainer #title { font-size: 100%; font-weight: bold; padding: 8px; }
#progMeterContainer #intro { font-size: 90%; text-align: justify; margin-bottom: 15px; }
#progressMeter { padding-top: 15px; }
#progressMeterBar { margin: 2px auto; width: 290px; height: 20px; border: 1px inset; background: #eee; text-align: left; }
#progressMeterBarDone1 { width: 0; height: 20px; border-right: 1px solid Ƽ background: url(/layout/ajaxupload-scrolling-bg-08.gif) repeat-x; }
#progressMeterBarDone { width: 0; height: 20px; border-right: 1px solid Ƽ background: #6953b2; }
#progressMeter table { width: 290px; margin: 20px auto; text-align: right; border-collapse: collapse; border: 0; border-bottom: 1px solid #bbb;}
#progressMeter table td { border-top: 1px solid #bbb; text-align: center; }
#progressMeter #upload-row-1, #progressMeter #upload-row-3 { background: #e6e6e6; }
#progressMeter #upload-row-2 { background: #efefef; }
#transferRate { font-style: italic; }
td.headercell { font-weight: bold; }
#tca1,#tcb1,#tcc1 { width: 14%; }
#tca2,#donet,#dones { width: 29%; }
#tca3,#leftt,#lefts { width: 28%; }
#tca4,#totalt,#totals { width: 29%; }
#filelist { text-align: left; }
</style>
`;
}
sub onedecimal
{
my $num = shift;
$num =~ /^(\d+\.\d).*/;
return $1 ? $1 : $num;
}
sub list_uploaded_files()
{
do_authentication('list_files','redirect');
my $dir = $PREF{DOCROOT} . $PREF{uploaded_files_dir};
my @files = ();
if(-d $dir)
{
opendir(my $dirh,$dir) or die "$0: couldn't open $dir: $!\n";
@files = grep { !/^(\.|\.\.|\.ht*)$/ } sort { lc($a) cmp lc($b) } readdir($dirh);
closedir($dirh) or die "$0: couldn't close $dir: $!\n";
}
start_html_output('Uploaded Files', 'css');
print  qq`<h3>Uploaded Files:</h3>\n\n<div id="filelist">\n`;
foreach my $file (@files)
{
my $displayname = $file;
if($displayname =~ /(\d{15,})(\..{1,6})$/)
{
my ($to_replace,$end) = ($1,$2);
my ($replacement) = ($to_replace =~ /^(\d{12})/);
$displayname =~ s/$to_replace$end/$replacement...$end/;
}
print qq`<a href="$PREF{uploaded_files_dir}/$file">$displayname</a>`;
print qq` [<a href="$PREF{here}?action=delete&file=$file">delete</a>]` if admin_is_logged_in();
print qq`<br />\n`;
}
print qq`\n</div>\n\n`;
print_footer_links('back');
finish_html_output('power');
}
sub start_html_output
{
my $title = shift;
my $css = shift;
my $js = shift;
$css = get_css() if $css;
$js = get_js() if $js;
unless($output_started)
{
print "Cache-Control: no-store, no-cache\n";
print "Content-type: text/html\n\n";
$output_started = 1;
}
print  qq`<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">`
. qq`\n<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">`
. qq`\n<head>`
. qq`\n<meta http-equiv="Content-type" content="text/html; charset=ISO-8859-1" />`
. qq`\n<script SRC="nopcart.js"></SCRIPT>`
    . qq`\n<script SRC="language-en.js"></SCRIPT>`
. qq`\n<title>$title</title>\n$js\n$css\n</head>\n<body>\n<div id="progMeterContainer">`
. qq`\n`;
}
sub finish_html_output
{
my $power = shift;
print_powered_by() if $power;
print  qq`\n</div>\n`;
if(($CGI::VERSION < 3.03) Â && Â ($PREF{ignore_version_error} !~ /yes/i))
{
print  qq`\n<div style="text-align: center; color: #aaa; margin-top: 20px;">`
. qq`The version of the CGI.pm Perl module on your server is $CGI::VERSION.`
. qq`<br />The progress bar probably won't work unless you upgrade to at least version 3.03.`
. qq`<br />To disable this message, add <strong>\$PREF{ignore_version_error}='yes';</strong> near the top of this script.`
. qq`</div>`
. qq`\n`;
}
print  qq`</body>\n</html>\n`;
}
sub print_footer_links
{
my @links = ();
while(my $i = shift)
{
 if($i =~ /back/) { push @links, qq`<a href="$PREF{here}">Uploader</a>`; }
elsif($i =~ /home/) { push @links, qq`<a href="/">Home</a>`; }
elsif($i =~ /enc/) { push @links, get_powered_by(); }
elsif($i =~ /list/) { push (@links, qq`<a href="$PREF{here}?listfiles">List Files</a>`) if $PREF{show_link_to_uploads} =~ /yes/i; }
elsif($i =~ /logout/) { push (@links, qq`<a href="$ENV{SCRIPT_NAME}?logout">Logout</a>`) if user_is_logged_in(); }
elsif($i =~ /login/) { push (@links, qq`<a href="$PREF{here}?login">Login</a>`) if (login_features_enabled() && !user_is_logged_in()); }
}
print  qq`<div id="footer">\n`;
print join " | ", @links;
print  qq`</div>\n`;
}
sub print_powered_by
{
print  qq`<div id="pb">\n`;
print get_powered_by();
print  qq`</div>\n`;
}
sub get_powered_by
{
return qq`<a href="http://encodable.com/tech/ajaxupload/" target="_blank">Powered by Encodable</a>`;
}
sub make_password_hash
{
if($ENV{REQUEST_METHOD} =~ /post/i)
{
use Digest::MD5 'md5_hex';
use CGI ':param';
my $hashed_password = md5_hex(param('password'));
start_html_output('Here is your hashed password...', 'css', 'js');
print  qq`<div>The hashed version of the password you just entered is:<br /><br />$hashed_password</div>`
. qq`\n`;
print_footer_links('back');
finish_html_output('power');
}
else
{
start_html_output('Enter your new password', 'css', 'js');
print  qq`<form method="post" action="$ENV{SCRIPT_NAME}?makePasswordHash">`
. qq`\nEnter your new password:`
. qq`\n<br /><br /><input type="password" name="password" maxlength="200" />`
. qq`\n<br /><br /><input type="submit" value="create hash" />`
. qq`\n</form>`
. qq`\n`;
print_footer_links('back');
finish_html_output('power');
}
}
sub user_is_logged_in
{
my $hashed_password_in_cookie = get_cookie('enc-uploader-password');
return 0 unless $hashed_password_in_cookie;
return( Â $hashed_password_in_cookie eq $PREF{admin_password_hash} Â || Â $hashed_password_in_cookie eq $PREF{member_password_hash} Â );
}
sub admin_is_logged_in
{
my $hashed_password_in_cookie = get_cookie('enc-uploader-password');
return 0 unless $hashed_password_in_cookie;
return($hashed_password_in_cookie eq $PREF{admin_password_hash});
}
sub do_authentication
{
return 1 if !login_features_enabled();
my $target = shift;
my $mode = shift;
my $hashed_password_in_cookie = get_cookie('enc-uploader-password');
if($PREF{"must_be_admin_to_$target"} =~ /yes/i)
{
if(!$hashed_password_in_cookie  ||  ($hashed_password_in_cookie ne $PREF{admin_password_hash}))
{
if($mode eq 'redirect')
{
print_needlogin_error($target);
}
else
{
return 0;
}
}
else
{
return 1;
}
}
elsif($PREF{"must_be_member_to_$target"} =~ /yes/i)
{
# the admin is considered a member too, i.e. if you have the
# admin password, then you meet the requirements for being a
# member too.
if( !$hashed_password_in_cookie
||
(
$hashed_password_in_cookie ne $PREF{member_password_hash}
&&
$hashed_password_in_cookie ne $PREF{admin_password_hash}
)
)
{
if($mode eq 'redirect')
{
print_needlogin_error($target);
}
else
{
return 0;
}
}
else
{
return 1;
}
}
}
sub print_needlogin_error
{
my $target = shift;
start_html_output('Error: Authentication Required', 'css', 'js');
print  qq`<h2>Error: Authentication Required</h2>`
. qq`\n<div>You must <a href="$PREF{here}?action=login&target=$target">log in</a> first.</div>`
. qq`\n`;
finish_html_output('power');
exit;
}
sub do_login
{
my $target = shift;
if($ENV{REQUEST_METHOD} =~ /post/i)
{
use Digest::MD5 'md5_hex';
use CGI ':param';
if(param('password') !~ /\S/) # don't allow blank passwords.
{
start_html_output&
('Error', 'css');
print qq`<div>You must enter the password.</div>`;
finish_html_output
('power');
exit;
}
my $hashed_password = md5_hex(param('password'));
my $expiry = ();
if(param('persist') eq 'on')
{
$expiry = "+$PREF{num_days_login_lasts}d";
}
if($hashed_password eq $PREF{admin_password_hash} Â || Â $hashed_password eq $PREF{member_password_hash})
{
set_cookie('enc-uploader-password', $hashed_password, $expiry);
if($target eq 'list_files')
{
print "Location: http://$ENV{HTTP_HOST}$PREF{here}?listfiles\n\n";
}
else # default to the front page (the upload page).
{
print "Location: http://$ENV{HTTP_HOST}$PREF{here}\n\n";
}
}
else
{
start_html_output&
('Invalid Login', 'css');
print &
nbsp; Â qq`<div>The password you entered is incorrect.<br />Go back and try again.</div>`
. qq`\n`;
finish_html_output
('power');
}
}
else
{
my $scripttarget = $target ? "action=login&target=$target" : 'login';
start_html_output('Enter the password', 'css');
print  qq`<form method="post" action="$ENV{SCRIPT_NAME}?$scripttarget">`
. qq`\nEnter the password:`
. qq`\n<br /><br /><input type="password" name="password" maxlength="200" />`
. qq`\n<br /><br /><input type="checkbox" name="persist" /> Keep me logged in for $PREF{num_days_login_lasts} days`
. qq`\n<br /><br /><input type="submit" value="log in" />`
. qq`\n</form>`
. qq`\n`;
finish_html_output('power');
}
}
sub get_cookies()
{
use CGI ':standard';
use CGI::Cookie;
my %cookies = fetch CGI::Cookie;
return %cookies;
}
sub get_cookie($)
{
my $which = shift;
my %jar = get_cookies();
my $value;
if(exists $jar{$which})
{
$value = $jar{$which}->value;
}
return $value;
}
sub set_cookie($$$)
{
my $name = shift;
my $value = shift;
my $expiry = shift;
my $cookie;
if($expiry eq "") # cookie expires at end of this session.
{
$cookie = new CGI::Cookie( -name   => $name,
-value  => $value,
-path   => '/');
}
else
{
$cookie = new CGI::Cookie( -name   => $name,
-value  => $value,
-expires => $expiry,
-path   => '/');
}
print "Set-Cookie: $cookie\n";
}
sub login_features_enabled
{
if(
(
$PREF{member_password_hash} =~ /\S/
||
$PREF{admin_password_hash} =~ /\S/
)
&&
(
$PREF{must_be_member_to_upload} =~ /yes/i
||
$PREF{must_be_admin_to_upload} =~ /yes/i
||
$PREF{must_be_member_to_list_files} =~ /yes/i
||
$PREF{must_be_admin_to_list_files} =~ /yes/i
)
)
{
return 1;
}
}
sub user_has_list_rights
{
return do_authentication('list_files');
}
sub do_logout()
{
set_cookie('enc-uploader-password', 'blank', '-1d');
# Remove the "logout" from the referrer, otherwise we'll get stuck
# in an infinite logout loop with this Location: call.
$ENV{HTTP_REFERER} =~ s/\?logout$//;
my $go = $ENV{HTTP_REFERER} ? $ENV{HTTP_REFERER} : "http://$ENV{HTTP_HOST}$PREF{here}";
print "Location: $go\n\n";
}
sub delete_file
{
my $file = shift;
my $really = shift;
unless(admin_is_logged_in())
{
start_html_output('Error: Authentication Required', 'css', 'js');
print  qq`<h2>Error: Authentication Required</h2>`
. qq`\n<div>You must <a href="$PREF{here}?login">log in</a> as admin to do that.</div>`
. qq`\n`;
print_footer_links('back','list');
finish_html_output('power');
}
my $displayname = $file;
$displayname =~ s/%([A-Fa-f\d]{2})/chr hex $1/eg;
if($displayname =~ /(\d{15,})(\..{1,6})$/)
{
my ($to_replace,$end) = ($1,$2);
my ($replacement) = ($to_replace =~ /^(\d{12})/);
$displayname =~ s/$to_replace$end/$replacement...$end/;
}
if($really)
{
my $diskfile = $file;
$diskfile =~ s/%([A-Fa-f\d]{2})/chr hex $1/eg;
$diskfile = "$PREF{DOCROOT}$PREF{uploaded_files_dir}/$diskfile";
unlink($diskfile) or die "$0: couldn't delete \"$diskfile\": $!\n";
start_html_output('File deleted', 'css');
print  qq`<h3>File deleted successfully:</h3>`
. qq`\n<div>$displayname</div>`
. qq`\n`;
print_footer_links('back','list');
finish_html_output('power');
}
else
{
start_html_output('Confirm deletion', 'css');
print  qq`<h3>Really delete this file?</h3>`
. qq`\n<div><a href="$PREF{uploaded_files_dir}/$file" target="_blank">$displayname</a>`
. qq`\n<br /><br />[<a href="$PREF{here}?$qs&really=yes">Yes</a>] `
. qq`\n[<a href="$PREF{here}?listfiles">No</a>]</div>`
. qq`\n`;
finish_html_output('power');
}
}