I try to create a form that can save a person's form data so that he can later finish completing the form. I have no problem to save the data to an external file and I know that it would be easy to do what I try to do if the user was permitted to save his data only once a full page form was completed. However, I want to be able to save the data of the form at any time, even if one of multiple pages have not been fully completed. Also, I like to use my own html scripting through my Perl scripts instead of calling CGI.pm form commands.
So the user saves his incomplete data at the end of a session and log in with a password at a later time to retrieve his data. So I retrieve data from the external file based on the password using
#--------------------------------------------
open(INFO, "MYTEXTFILE.txt");
#data = <INFO>;
close(INFO);
#--------------------------------------------
foreach $key (#data)
{
($aaa1,$aaa2,$aaa3,$aaa4,$aaa5,$e)=split(/,/,$key);
}
And then I try to input the available data back into the html form. This is pretty easy when data have been collected with text-boxes:
print"
<p>Your response is: input type='text' name='aaa1' value='$aaa1' <\p>";
But more tricky when it is a radiobutton. I use:
print"
<table width='600' align='center' cellpadding='3'>
<tr bgcolor=''>
td bgcolor=''>1. Question #1
</td>
<td>1
<input name='aaa1' type='radio' value='1'"; if ($aaa1==1) {print " CHECKED ";} print"/>/td>
<td>2
<input name='aaa1' type='radio' value='2'"; if ($aaa1==2) {print " CHECKED ";} print" />/td>
<td>3
<input name='aaa1' type='radio' value='3'"; if ($aaa1==3) {print " CHECKED ";} print" />/td>
<td>4
<input name='aaa1' type='radio' value='4'"; if ($aaa1==4) {print " CHECKED ";} print" />/td>
<td>5
<input name='aaa1' type='radio' value='5'"; if ($aaa1==5) {print " CHECKED ";} print" />/td>
</tr>
</table>
";
Is there a more convenient or handy way to do it?
Yes there's an easier way.
foreach my $value (1,2,3,4,5) {
my $checked = ($aaa1 == $value) ? "CHECKED " : "";
print "<td>$value <input name='aaa1' type='radio' value='$value' $checked/></td>\n";
}
However, if you insist on hand-rolling your own templating solution (as opposed to using a great number of existing Perl templating ones), you should do it the RIGHT way. Have generic methods for various input types, etc...
Also, as others have pointed out in comments, there's a REASON for separating code from HTML via a templating solution - it greatly simplifies maintenance.
Your output contains almost the same text and code repeating 5 times. Using a for loop would be more convenient.
Related
This question already has answers here:
Can't find string terminator "str" anywhere before EOF
(3 answers)
Closed 6 years ago.
I am having trouble getting this script to work, It seems to work fine locally but not on the server for 1 and 1.
The error I am getting is:
Can't find string terminator HERE anywhere before EOF
I also seem to be getting this error:
255 perl returned nonzero status
Status: 500
Content-type: text/html**
I am new to CGI, but I could not find anything online about this particular issue.
Here is the HTML:
<div class="form"><h1>Free Quote</h1>
<form action="/quote.cgi">
First Name: <input type="text" name="fName" placeholder="John"> <br>
Last Name: <input type="text" name="lName" placeholder="Smith"><br>
<br>
Company: <input type="text" name="company" placeholder="Mr Kittles"><br>
Phone Number: <input type="text" name="number" placeholder="xxx-xxx-xxx"><br>
E-Mail: <input type="text" name="email" placeholder="Something#gmail.com"><br><br>
Tell us what you you are looking for:<br><br><textarea name="message" rows="10" cols="35" placeholder="Tell us all about your website. Include type of business, colors, current web address if possible, and anything else you think is relevant for us to do some research before we call you back."></textarea><br><br>
<input type="submit" value="Submit">
</form>
</div>
And here is the CGI
#! /usr/bin/perl
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser);
use strict;
use warnings;
print "Content-type: text/html\n\n";
my $fName = param('fName');
my $lName = param('lName');
my $company = param('company');
my $number = param('number');
my $email = param('email');
print <<HERE;
<HTML>
<BODY>
<H3>Item has been registered and added to inventory.txt</H3>
HERE
open (INVENTORY, ">>tet.txt") or die "File error, $!";
print INVENTORY "$fName|$lName|$company|$number|$email\n";
close INVENTORY;
Your cgi file is not compiling because you have some trailing whitespace after the here-doc closing string HERE.
According to perldoc perlop #Quote-and-Quote-like-Operators in the <<EOF section:
The terminating string must appear by itself (unquoted and with no surrounding whitespace) on the terminating line.
To fix, just remove the extra whitespace characters.
This is my first post. So please excuse me of any irregularities. I am newbie to Perl and I have got the following issue. I get the error "Use of uninitialized value ...at" when I use the param function in Perl. Here's the code.
use CGI qw(param);
print "Content-type: text/plain \n\n";
$key_value=param('sososo');
print $key_value;
and my html file is
<input type="radio" name="rate" id="sososo" value="1"/>
<label for="sososo">so</label> <br>
In other words I want the value 1 to be displayed. But obviously it does not assign the value to $key_value. I don't know why. Thank you in advance.
To get the value of an input field, you have to use the name of the element, not the id.
use
$key_value=param('rate');
instead of
$key_value=param('sososo');
In perl is there a lib/package for getting the file upload data directly to a scalar without going through a 'tmp' file. My form is like:
<form method="post" enctype="multipart/form-data">
<input type="file" name="myfile">
</form>
I could not figure out how to get the data using the CGI module without going through a temporary file. I can read the full contents on stdin, but I don't want to have to re-invent the wheel decoding multipart data.
take a look at CGI->upload function
my $fh = $cgi->upload('data');
{
# enable 'slurp' mode
local $/;
$data = <$fh>;
}
I have many long files but I am interested just in part of the information of each one. So far I have a code that trims the file and gives me the line that contains the information I need, working one file at the time.
This is the code I am using:
#!/usr/bin/perl
use strict;
use warnings;
my $data;
open FILE, "<$ARGV[0]" or die "cannot open file '$ARGV[0]'!\n\n";
while ($data= <FILE>){
chomp $data;
if( $data=~m/\<input type="hidden" name="description" value="454read"><input type="hidden" name="format" value="fasta"><input type="submit" name="submitbutton" value="FASTA"/)
{
$data=~s/[^ACTGN]//g;
print $data;
}
}
And this is the input I get:
<input type="hidden" name="sequence" value="TTGTTGAGCTCGACGGTCATGACCCAGCTGGAGTCGGCACGGGCACCCGCGCGCTTCTGCCAGACGCCAATGTGGGACTTCTCGGTGTCGAGGC"><input type="hidden" name="name" value="FUY784js_7HL"><input type="hidden" name="description" value="454read"><input type="hidden" name="format" value="fasta"><input type="submit" name="submitbutton" value="FASTA">
From this I only need two parts, the TTGTT....AGGC, this part will always be uppercase A,T,C,G,or N, however the length might differ in each file. I also need to save the name for this that in this case is FUY784js_7HL, this name will change every time.
The ideal output should look like this:
FUY784js_7HL
TTGTTGAGCTCGACGGTCATGACCCAGCTGGAGTCGGCACGGGCACCCGCGCGCTTCTGCCAGACGCCAATGTGGGACTTCTCGGTGTCGAGGC
Do you have any idea of how can I do it? I have many files like this. I will appreciate if any of you can help me to figure out how to get this to work for multiple files.
Thanks!
perl -pe 's/[^ACTGN]//g;'
As a proxy for the bit which appears to be problematic, the above command seems to work, at least with the input line starting with <input and the second output line.
If you don't have any other prints in your real program, I'm not sure how it could produce the line you said it did.
Actually, that was a lie. I got:
TTGTTGAGCTCGACGGTCATGACCCAGCTGGAGTCGGCACGGGCACCCGCGCGCTTCTGCCAGACGCCAATGTGGGACTTCTCGGTGTCGAGGCATA
back because of the FASTA value at the end. If you want to restrict to the main value:
perl -pe 's/.*"([ACTGN]+)".*<input\b[^>]*\bname="name"\s[^>]*\bvalue="([^"]+)".*/$2\n$1/;'
Please note that all of the standard disclaimers about the stupidity and fragility of parsing XML with a regex apply. Specifically, it is perfectly legal to reorder the name and value attributes and this example regex doesn't allow that.
If I understand the problem correctly, it looks like making use of capturing groups addresses your need. Specially since you know the beginning and the end but don't know the middle, something like this should work:
$data =~ /TTGTT(.+)AGGC/;
print $1;
Check out the section on capture groups on perldoc:
http://perldoc.perl.org/perlre.html#Regular-Expressions
From what has been posted, I think this would return the sequence:
$data =~ /name="sequence" value="([AGCT]*).*name="name" value="([^"])"/;
print "$2\n$1";
in the html file:
<!--#exec cgi="/cgi-bin/test.pl"-->
the perl script:
#!/usr/bin/perl
print "Content-Type: text/html\n\n";
print "<input type=\"hidden\" name=\"aname\" value=\"avalue\">\n";
print "<img src=\"/cgi-bin/script.pl\" />";
This does not give me an 'error processing directive' error, nor does it output my HTML inplace of the tag. I'll also add that the ssi tag gets replaced with nothing.
Are you sure the script is executing? If you print something to STDERR does it show up in th error log?
Beyond that I have a few comments:
I'm pretty sure printing the Content-Type is redundant, you (well, Apache anyway) have already done that by serving the HTML file that contains the SSI.
reference
exec is really meant for running commands like 'ls -l'. You should use include virtual instead. It also allows you to add arguments to the url. e.g.
<!--#include virtual="/cgi-bin/example.cgi?argument=value" --\>
do yourself a favor and use qq[] instead of the double-quotes. You won't have to escape everything then... e.g.
print qq[< input type="hidden" name="aname" value="avalue"\b];