I have a problem with a CGI script on a Win2000 server.
The script is for sending E-cards and was written by Jason Maloney.
You can choose from some cards, add your own text and send it to a friend.
This friend get a mail which tell him/her that he/she has a mail and have to
click a link.
So far everything works just fine.
But when the recipient clicks the link he/she gets the following error
message in the browser window:
----------------------------------------------------
CGI Error
The specified CGI application misbehaved by not returning a complete set of
HTTP headers. The headers it did return are:
Can't open perl script
"D:\Inetpub\HCO\www\cgi-bin\postcard\card.cgi1070022045": No such file or
directory
--------------------------------------------------------
The cgi script is in \cgi-bin\postcard\card.cgi
But the data it has to retrieve is in
\cgi-bin\postcard\cards\1070022045.dat(for example)
Each mail generates a new .dat file.
Any ideas???
You can try it on our test site:
http://195.86.135.223/cgi-bin/postcard/index.html
Thanks,
Bernard
I was able to repeat the problem. Seems to me to be a bug.
You'd better ask the author about it.
--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
Well, then I suppose you'd better show us relevant parts of the code.
Doing so would increase the chances that somebody is able to help,
don't you think? ;-)
Ok Gunnar, here is the code.
The first one is card.cgi
#!D:/Program Files/Perl/bin/perl.exe
###########################################################
# A Postcard Program #
# Written by Jason W. Maloney - December 20, 1998 #
# Updated - February 22, 2001 #
# #
# This script is very easy to set-up, even for those #
# just starting out with CGI. It shouldn't take longer #
# than 10 minutes to get it up and running. It has been #
# tested on UNIX & NT and no problems were discovered. #
# #
# The use of templates make it very easy to customize #
# the postcard script to your needs. #
# #
# MAKE SURE THAT YOU READ OVER THE TERMS OF AGREEMENT #
# BEFORE USING THIS SCRIPT. BY USING THIS SCRIPT, #
# YOU ARE AGREEING TO ABIDE BY THEM. HOWEVER, IF YOU #
# DON'T AGREE WITH IT, THEN DON'T USE MY SCRIPTS. ALSO, #
# PLEASE READ THE 'README.TXT' FILE BEFORE INSTALLING. #
# KEEP IN MIND THAT JASON'S SCRIPTS & THE AESTHETIC #
# SURGERY CENTER SHALL NOT BE HELD LIABLE FOR ANY #
# DAMAGES THAT MAY OCCUR FROM DOWNLOADING AND/OR #
# INSTALLING MY PROGRAMS. IN SHORT, DOWNLOAD AND USE MY #
# PROGRAMS AT YOUR OWN RISK! IF YOU DO NOT AGREE WITH #
# THIS, THEN DO NOT USE ANY OF MY PROGRAMS. #
# #
###########################################################
###########################################################
$domain_name = "195.86.135.223";
$location = "http://195.86.135.223/cgi-bin/postcard/";
$basepicurl = "http://195.86.135.223/cgi-bin/postcard/pictures/";
$cgi = "http://195.86.135.223/cgi-bin/postcard/card.cgi";
$cards = "d:\\Inetpub\\HCO\\www\\cgi-bin\\postcard\\cards\\";
$basepicdir = "d:\\Inetpub\\HCO\\www\\cgi-bin\\postcard\\pictures\\";
$preview1 = "d:\\Inetpub\\HCO\\www\\cgi-bin\\postcard\\preview1.html";
$preview2 = "d:\\Inetpub\\HCO\\www\\cgi-bin\\postcard\\preview2.html";
$makecard = "d:\\Inetpub\\HCO\\www\\cgi-bin\\postcard\\makecard.html";
$thank_you = "d:\\Inetpub\\HCO\\www\\cgi-bin\\postcard\\thankyou.html";
$error = "d:\\Inetpub\\HCO\\www\\cgi-bin\\postcard\\error.html";
$email1 = "d:\\Inetpub\\HCO\\www\\cgi-bin\\postcard\\email1.txt";
$email2 = "d:\\Inetpub\\HCO\\www\\cgi-bin\\postcard\\email2.txt";
$mailprog = 'windmail';
$MAX_DAYS = '10';
@picsallowed = ('gif','jpg','jpeg');
$subject1 = "je hebt een 'Groet uit Zwolle!' E-card.";
$subject2 = "Bedankt voor het gebruik van onze E-card(s)";
$uploadmax = '50';
$allowed = '1500';
require "d:\\Inetpub\\HCO\\www\\cgi-bin\\postcard\\program.cgi";
The second one is program.cgi
#!D:/Program Files/Perl/bin/perl.exe
########################################################
########################################################
# Don't Edit This CGI Part #
########################################################
########################################################
$i=0;
read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});
if ($ENV{'QUERY_STRING'})
{$buffer = "$buffer\&$ENV{'QUERY_STRING'}";}
@pairs = split(/&/,$buffer);
foreach $pair (@pairs){
($name,$value) = split(/=/,$pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
$VALUE{$name} = $value;
}
############################################
#Gets the Current Date
############################################
($sec,$min,$hr,$day,$month,$year,$day_of_week,$day_of_year,$some) =
localtime(time);
@months =
("January","February","March","April","May","June","July","August","Septembe
r","October","November","December");
$year = $year + 1900;
$DATE = "$months[$month]-$day";
$SHORTDATE = "$months[$month] $day, $year at $hr:$min:$sec";
############################################
#Gets Picture Data and Moves on to Next Page
############################################
if ($VALUE{'action'} eq 'preview') {
$pic = $VALUE{'PICTURES'};
$VALUE{'PICTURE'} = $VALUE{'PICTURES'};
$VALUE{'PICTURES'} = "$basepicurl$pic";
print "Content-type: text/html\n\n";
open(TEMPLATE,"$preview1");
&template;
print $template;
exit;
}
#########################
#Prints the Preview Page
#########################
if ($VALUE{'action'} eq 'preview1') {
$pic = $VALUE{'PICTURE'};
$VALUE{'PICTURES'} = "$basepicurl$pic";
$VALUE{'MESSAGE'} =~ s/\r//g;
$VALUE{'MESSAGE'} =~ s/\<[^\>]*\>//ig;
$VALUE{'MESSAGE'} =~ s/"/'/g;
$VALUE{'MESSAGE'} =~ s/\n/<BR>/g;
print "Content-type: text/html\n\n";
open(TEMPLATE,"$preview2");
&template;
print $template;
exit;
}
##########
#Send Card
##########
if ($VALUE{'action'} eq 'send') {
&no_email unless $VALUE{'MAILFROM'} && $VALUE{'MAILTO'};
######################
#Save the Data
######################
$date = time;
$create_card = "$cards$date.dat";
open(DATA, ">>$create_card");
print DATA
"$VALUE{'SENDER'}|$VALUE{'MAILFROM'}|$VALUE{'RECIPIENT'}|$VALUE{'MAILTO'}|$V
ALUE{'MESSAGE'}|$VALUE{'PICTURE'}|0\n";
close(DATA);
$url_of_card = "$cgi?$date";
##########################
#Print Thank You HTML
##########################
print "Content-type: text/html\n\n";
open(TEMPLATE,"$thank_you");
&template;
print $template;
$template = '';
##########################
#Send E-mail to Recipient
##########################
open (MAIL, "|$mailprog -t") || die "Kan $mailprog niet openen!\n";
print MAIL "To: $VALUE{'MAILTO'} ($VALUE{'RECIPIENT'})\n";
print MAIL "From: $VALUE{'MAILFROM'} ($VALUE{'SENDER'})\n";
print MAIL "Subject: $VALUE{'RECIPIENT'}, $subject1\n\n";
open(TEMPLATE,"$email1");
&template;
print MAIL $template;
print MAIL ".\n" ;
close(MAIL);
$deletes = "$cards$DATE.dat";
if(-e $deletes){
}
else{
open(DATA, ">>$deletes");
close(DATA);
&delete;
}
exit;
}
########################
#No E-Mail Addresses
########################
sub no_email {
print "Content-type: text/html\n\n";
print "<HTML>\n<TITLE>Fout! E-Mail adres niet geldig</TITLE>\n";
print "<BODY COLOR=\"#FFFFFF\">\n";
print "Kan niet verstuurd worden!<BR>\n";
print "<B>[Mogelijke oorzaken:]</B><BR>\n";
print " 1.) U bent beide e-mail adressen vergeten in te
vullen<BR>";
print " 2.) E-Mail Adres(en) niet in de goed formaat ingetypt,
<B>b.v. na...@bedrijf.com</B>";
exit;
}
#######################################
#Creates the Postcard
#######################################
if ($ENV{'QUERY_STRING'}) {
############################################
#Makes Postcards and Sends Thank You E-mail
############################################
$create_card = "$cards$ENV{'QUERY_STRING'}.dat";
if(-e $create_card){
open(DATA, "$create_card");
@data = <DATA>;
close(DATA);
foreach $temp (@data){
chop($temp);
($SENDER, $MAILFROM, $RECIPIENT, $MAILTO, $MESSAGE, $PICTURES, $COUNT) =
split(/\|/, $temp);
$VALUE{'SENDER'} = $SENDER;
$VALUE{'MAILFROM'} = $MAILFROM;
$VALUE{'RECIPIENT'} = $RECIPIENT;
$VALUE{'MAILTO'} = $MAILTO;
$VALUE{'MESSAGE'} = $MESSAGE;
$VALUE{'MESSAGE'} =~ s/ / /g;
$VALUE{'PICTURES'} = "$basepicurl$PICTURES";
$VALUE{'LINK'} = "$link$LINK";
$VALUE{'PICTURE'} = "$basepicurl$PICTURES";
}
unlink("$create_card");
open(DATA, ">>$create_card");
$COUNT++;
print DATA
"$SENDER|$MAILFROM|$RECIPIENT|$MAILTO|$MESSAGE|$PICTURES|$COUNT\n";
close(DATA);
print "Content-type: text/html\n\n";
open(TEMPLATE,"$makecard");
&template;
print $template;
$template = '';
if($COUNT eq '1'){
open (MAIL, "|$mailprog -t") || die "Kan $mailprog niet openen!\n";
print MAIL "To: $VALUE{'MAILFROM'} ($VALUE{'SENDER'})\n";
print MAIL "From: $VALUE{'MAILTO'} ($VALUE{'RECIPIENT'})\n";
print MAIL "Subject: $subject2\n\n";
open(TEMPLATE,"$email2");
&template;
print MAIL $template;
print MAIL ".\n" ;
close(MAIL);
}
}
else {
print "Content-type: text/html\n\n";
open(TEMPLATE,"$error");
&template;
print $template;
}
exit;
}
#######################################
#DELETES the information
#######################################
sub delete {
local(@items, $pair);
opendir(DELETE, "$cards");
@items = grep(/.dat/,readdir(DELETE));
closedir(DELETE);
foreach $pair (@items){
if (-M "$cards$pair" > $MAX_DAYS){
unlink("$cards$pair");
}
}
}
#####################
#Calls the Template
#####################
sub template {
while (<TEMPLATE>){
$template .= $_;
}
close(TEMPLATE);
$template =~ s/\%%%PICTURES%%%/$VALUE{'PICTURES'}/g;
$template =~ s/\%%%PICTURE%%%/$VALUE{'PICTURE'}/g;
$template =~ s/\%%%SENDER%%%/$VALUE{'SENDER'}/g;
$template =~ s/\%%%MAILFROM%%%/$VALUE{'MAILFROM'}/g;
$template =~ s/\%%%MAILTO%%%/$VALUE{'MAILTO'}/g;
$template =~ s/\%%%RECIPIENT%%%/$VALUE{'RECIPIENT'}/g;
$template =~ s/\%%%MESSAGE%%%/$VALUE{'MESSAGE'}/g;
$template =~ s/\%%%CGI%%%/$cgi/g;
$template =~ s/\%%%MAX_DAYS%%%/$MAX_DAYS/g;
$template =~ s/\%%%SHORTDATE%%%/$SHORTDATE/g;
$template =~ s/\%%%url_of_card%%%/$url_of_card/g;
}
That's it!
Bernard
And the relevant errors in the error logs too.
Paul
Nothing to find in the logs, the error message (first post) is the only
error I get.
Bernard
I used Postcard.Zip (No Flash).
Bernard
Well, it's not the best script I have seen. :(
Anyway, in card.cgi you have:
$cards = "d:\\Inetpub\\HCO\\www\\cgi-bin\\postcard\\cards\\";
Backslashes and double quotes is a tricky combination. You'd better
change the line in card.cgi to:
$cards = 'd:/Inetpub/HCO/www/cgi-bin/postcard/cards/';
You'd better change all the paths that way, btw. And you'd better make
it a habit to never use backslashes as directory separators in Perl
scripts, even if you are on Windows.
Let us know if that makes a difference.
Gunnar,
I joined the Google newsgroup, so I can see what's happening here from
my home PC.
I just changed the code like you said, but with no results. I still
get the same error message.
Here is the change I made:
$domain_name = '195.86.135.223';
$location = 'http://195.86.135.223/cgi-bin/postcard/';
$basepicurl = 'http://195.86.135.223/cgi-bin/postcard/pictures/';
$cgi = 'http://195.86.135.223/cgi-bin/postcard/card.cgi';
$cards = 'd:/Inetpub/HCO/www/cgi-bin/postcard/cards/';
$basepicdir = 'd:/Inetpub/HCO/www/cgi-bin/postcard/pictures/';
$preview1 = 'd:/Inetpub/HCO/www/cgi-bin/postcard/preview1.html';
$preview2 = 'd:/Inetpub/HCO/www/cgi-bin/postcard/preview2.html';
$makecard = 'd:/Inetpub/HCO/www/cgi-bin/postcard/makecard.html';
$thank_you = 'd:/Inetpub/HCO/www/cgi-bin/postcard/thankyou.html';
$error = 'd:/Inetpub/HCO/www/cgi-bin/postcard/error.html';
$email1 = 'd:/Inetpub/HCO/www/cgi-bin/postcard/email1.txt';
$email2 = 'd:/Inetpub/HCO/www/cgi-bin/postcard/email2.txt';
$mailprog = 'windmail';
$MAX_DAYS = '10';
@picsallowed = ('gif','jpg','jpeg');
$subject1 = "je hebt een 'Groet uit Zwolle!' E-card.";
$subject2 = "Bedankt voor het gebruik van onze E-card(s)";
$uploadmax = '50';
$allowed = '1500';
require 'd:/Inetpub/HCO/www/cgi-bin/postcard/program.cgi';
Or do I have also to change something in the program.cgi file?
Would 't be better to put the map "postcard/" out of the cgi-bin map?
Bernard
<snip>
> Or do I have also to change something in the program.cgi file?
Actually, the script is bad. One reason why I say so is the total lack
of checks whether various system calls succeed or fail. However, I'm
not able to detect any obvious bug that explains the problem.
One thing you can do is to manually check for the existence of files
in the $cards folder (using your FTP program or whatever).
If you don't find any files, you can try chmod the folder 777.
That's all I can think of. (Besides a total rewrite of the script.)
> Would 't be better to put the map "postcard/" out of the cgi-bin
> map?
That should not make a difference.
The script is pretty horrible, if you ask me, but you're not going to find
the cause just by looking in it. Rather, you need to look at the url that's
being generated in the email:
http://195.86.135.223/cgi-bin/postcard/card.cgi?1070208188
Seems you get a value with no key, which is what appears to be choking your
server. From what I see in the code, the author expects to be able to use
the query_string variable (the number, in this case) to retrieve your card,
but your server isn't accepting the url as being valid because it does not
contain a valid key=value pairing.
To fix the problem you're going to have to output a url with, for example,
?card=107028188, and then instead of checking for query_string and operating
on it, check for the paramter card and use it's value. So, change this line
in your code:
$url_of_card = "$cgi?$date";
to
$url_of_card = "$cgi?card=$date";
And then change these lines:
if ($ENV{'QUERY_STRING'}) {
############################################
#Makes Postcards and Sends Thank You E-mail
############################################
$create_card = "$cards$ENV{'QUERY_STRING'}.dat";
to:
if ($VALUES{'CARD'}) {
############################################
#Makes Postcards and Sends Thank You E-mail
############################################
$create_card = "$cards$VALUES{'CARD'}.dat";
And in theory the script should then start working for you.
Matt
I'm not following you now, Matt. Are you saying that the _server_
accomplishes some kind of validation of query strings, requiring that
they consist of '=' separated key/value pairs? I'm not exactly an
expert on this, but I have never heard of such checks.
Neither had I, to tell you the truth... : )
It just seemed odd that when I clicked on the link the server gave me an
error that it was trying to execute a script that corresponded to the url,
so I tried adding in a key and it worked (although it gave me a "card not
found" error). Could just be an IIS bug (assuming that's what he's running),
or could be something odd in the way the cgi-bin is configured to execute
scripts.
Matt
You are right ... For some inscrutable reason, a '=' character makes a
difference.
I'm totally lost. :(
Matt and Gunnar,
Thanks both for your input.
I just changed the code, but it still doesn't work. I now get a different
CGI Error message:
CGI Error
The specified CGI application misbehaved by not returning a complete set of
HTTP headers. The headers it did return are:
d:/Inetpub/HCO/www/cgi-bin/postcard/program.cgi did not return a true value
at D:\Inetpub\HCO\www\cgi-bin\postcard\card.cgi line 53.
------------------------------------------------
Line 53 calls program.cgi, so the error is generated somewhere in it (I
think!).
What next???
Bernard
Try adding
1;
at the bottom of program.cgi.
Gunnar,
I now get the following error message:
CGI Error
The specified CGI application misbehaved by not returning a complete set of
HTTP headers. The headers it did return are:
That's it.
What if you add this line to card.cgi (before program.cgi is required):
use CGI::Carp 'fatalsToBrowser';
Nothing changed. Still get:
CGI Error
The specified CGI application misbehaved by not returning a complete set of
HTTP headers. The headers it did return are:
Is it possible that it has to do with some IIS 5 configuration? File Type
(parameters) for example?
At this moment it's set like this:
.CGI CGI Script
Action > Open
Aplication used to perform action:
"D:\Program Files\Perl\bin\perl.exe" %s%s
Bernard
Maybe. Your server does not seem to behave as you would expect, but
I'm not able to help you with that.
Bernard
Yep, now it works for me too.
> I'm very sorry to misused your time for something, whom afterward,
> had nothing to do with Perl.
It's okay, Matt suspected quickly that it had something to do with
IIS, but I think that at least I learned something.
Glad to hear it.
Thanks Gunnar.
Over and Out
Bernard
The moral of the story is never trust Microsoft to do the right thing.
As a side note, you probably don't want your web scripts running off the
perl executable. If you have the Activestate build, it should give you the
option on install to confgure the perlis.dll for iis. If you don't want to
re-install, just change the cgi mapping to point to the dll, which is
located in your \perl\bin directory (no other arguments are necessary).
Matt