CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
? about CGI.PM input format in regards to SPLIT

 



S_Shrum
User

Oct 30, 2001, 12:54 AM

Post #1 of 10 (1573 views)
? about CGI.PM input format in regards to SPLIT Can't Post

I am in the process of moving away from handling input myself and letting the CGI.pm do it via:


Code
$input = new CGI;

Everything is working except the SPLIT. The problem that I am running into as follows:

I have a flat file like:


Code
URL|Title|Hits 
www.someserver.com|this is someserver|1

My old code handled this beautifully before as:


Code
push @data, [ split(/\Q$input{'delimiter'}\E/, $_) ];

...now, since CGI is handling the input, I rewrote this line as:


Code
push @data, [ split(/\Q$input->param('delimiter')\E/, $_) ];

The problem is that the split doesn't work. When I test the # of columns in the data array, I get back "0" (1 row). The value of the DELIMITER param = "|"

Any ideas? The current code can be seen at http://www.shrum.net/db_increment.pl.txt

Sean Shrum
sean@shrum.net
www.shrum.net


yapp
User

Oct 30, 2001, 2:46 AM

Post #2 of 10 (1571 views)
Re: ? about CGI.PM input format in regards to SPLIT [In reply to] Can't Post

Perl replaces all the variables in your regexp. Take a look at the difference


Code
push @data, [ split(/\Q$input{'delimiter'}\E/, $_) ];


Code
push @data, [ split(/\Q$input->param('delimiter')\E/, $_) ];

Perl no longer sees the second part of your expression as a variable. You should store the value first into a variable, then use that one in your regexp.

However, I'm very pleased to see you're using the CGI module, since that solves many other problems caused by with self-build param parsing scripts.




S_Shrum
User

Oct 30, 2001, 8:38 PM

Post #3 of 10 (1564 views)
Re: ? about CGI.PM input format in regards to SPLIT [In reply to] Can't Post

Well that seemed to work.

I guess I understand the whole two-part entry theory. My assumption was that the entry returned a string (regardless of the way that the string was being returned).

Oh well, learn something new everyday. Thanks for the help.

Sean Shrum
sean@shrum.net
www.shrum.net


yapp
User

Nov 1, 2001, 5:05 AM

Post #4 of 10 (1557 views)
Re: ? about CGI.PM input format in regards to SPLIT [In reply to] Can't Post

P.S.

I took al look at your script. It looks pretty fine, and readable aswell Wink.
There are a few small things I want to mention you about.

a.
To redirect a browser, use

Code
print redirect $URL;  # or $input->redirect when the CGI module is used in object style

from the CGI module. That's a much safer method, and doesn't cause blank browser screens what sometimes happened in scripts.

b. Please use -w at the #! line. That helps finding more errors at compile time,
but any undefined value used in a string, like

Code
my $X=undef; print "X is $X";

stops with an error. When -w is used, you need to look out for undef values using a statement like

Code
if(! defined $X) { #More code

.

c.
You commented out use strict, but why? Is it really that bad? You can also split things up, or omit one of the floowing strict rules:

Code
use strict 'vars'; # declaration with my() 
use strict 'subs'; # Subroutine and constants need to be defined
use strict 'refs'; # Can assume reference, a double doller NEEDS to be a reference



S_Shrum
User

Nov 1, 2001, 10:49 AM

Post #5 of 10 (1556 views)
Re: ? about CGI.PM input format in regards to SPLIT [In reply to] Can't Post

Thanks for the suggestions...I'll look into the redirect thing.

As for commenting out the strict...ya...it's that bad. With strict on I get like 50 errors...ack! The script would never run if I used it (I plan on putting it back in later as I get better at my Perl coding). I looked at the log once and decided to deal with it later. This works great as I am working out concepts and getting the basic framework in.

As for the -w...well...my error log is getting HUGH if I leave this on and I am only on a modem. I figured I get the scripts working first (which means a lot of d/l the error log to get the specific error). After that, I can get my host to reset the log (to make it smaller to d/l) and then work on the scripts one at a time with strict and -w.

Sean Shrum
sean@shrum.net
www.shrum.net


S_Shrum
User

Nov 1, 2001, 12:59 PM

Post #6 of 10 (1552 views)
Re: ? about CGI.PM input format in regards to SPLIT [In reply to] Can't Post

Okay...I tried the redirect thing and am getting errors. I replaced the old redirect line with this new one that uses the CGI redirect:


Code
unless ( $input->param() ) { print $input->redirect(-uri=>'http://www.shrum.net/cgi-bin/db_table2.pl?file=docs.dat&page=http://www.shrum.net/templates/programming.shtml&record=templates/layout_document.shtml&for=' . $script{'whitepaper'} . '&in=ID', -nph=>1); exit; }

...is generating the following error in the log:


Code
malformed header from script. Bad header=HTTP/1.1 302 Moved: /a/home/shrum/cgi-bin/db_formfields.pl

Any ides?

Thanks for all the help so far.

Sean Shrum
sean@shrum.net
www.shrum.net


yapp
User

Nov 1, 2001, 1:15 PM

Post #7 of 10 (1551 views)
Re: ? about CGI.PM input format in regards to SPLIT [In reply to] Can't Post

Whoa.

I never realized it was that bad, but here are some other notes.

Type

Code
use CGI::Carp qw(fatalsToBrowser);

at the beginning of your program to see the errors in your browser.

If you re-open STDERR to an other handle, your errors won't be dumped into the error log. You can choose your own log file, or reopen STDERR to STDOUT (the screen). However, if you dump something into STDOUT, a HTTP header should be printed first. The CGI::Carp module also has a method for that task, so you're not bothered with re opening STDERR. You can also reopen STDERR to a just-created file (which should be cleared up everytime your script starts) There are also the $SIG{'__DIE__'} and $SIG{'__WARN__'} variables in perl. They contain a subroutine reference (= \&subname). The subroutine is called every time a die or warn error is thrown. (this included the ones inside a eval()).


However, why don't you visit http://www.perl.com and get a perl interpreter for yourself. Then you can test and debug your script locally first. If you succed in installing a webserver and link perl with cgi files, you can test everything locally. Then you don't need to worry about large server logs anymore.


Second about the use strict. use strict 'vars' means that all the variables you use should be declared with my() first (BLOCK scoped). This prevents quite some typoos, which causes a new variable to be initialized with that name (and the old is then not used or updated).

use strict 'refs' helps you with references. Then you can't write $$var and assuming $var is a reference. Then is MUST be a reference.

use strict 'subs' tells the compiler all the subroutine and constants should be declared first. This is just as useful as use strict 'vars'.

The -w makes perl more verbose (display more warnings). It also notifies you when your programming style causes perl to slow down, etc. -w is useful because a variable with an undef value can't be used anywhere. If that annoys you, you can set $^W to 0 (no -w) or $^W to 1 (using -w) at runtime.

-w can be irritating, an undef value would print out an empty string when -w is not used. Here are some techniques to avoid errors with -w:

Code
#!/usr/bin/perl -w 

use strict;

my $X = 34;
my($Y, $Z) = (45, 23);
my $Text; # undef value

print $Text if defined $Text;

&SubroutineCall( $Text || '' ); # Replaces $Text with '' is $Text evaluates to false (undef, empty or zero)

$Text ||= ''; # Replace with '' if the value is '', undef or 0.
print qq[Text is $Text\n]; # is OK now.

my $Text2;
$Text2 = '' if not defined $Text2; # better because 0 is also false.
$Text2 = '' unless defined $Text2; # other perl style. The ( ) characters aren't needed now.

#.....
# somewhat further in the script

foreach ($Var1, $Text $Text2, $Var4, $X, $Y, $Z)
{
# $_ not references to one of the values (one by one).
$_ = '' if not defined; # $_ can be omitted in defined() call
s/a+/b/g; # substitutes all the aaaaaas into a b (global match)
chomp; # remove \n at the end
print; # prints $_
}


One of the webservers my familysite is located doesn't even allow scripts without -w !!!!! A 500 Internal Server error is returned when -w is missing.

-Tw would even be better and safer, but is even more difficult to handle.



yapp
User

Nov 1, 2001, 1:25 PM

Post #8 of 10 (1550 views)
Re: ? about CGI.PM input format in regards to SPLIT [In reply to] Can't Post

Weird.

I never use the -uri => prefix. Omitting it would be fine (and works aswell for simple redirects), so

Code
print $input->redirect($URL); 
exit; # we're done aren't we??

There could be an other problem. The parameters passed through should be escaped. Did you ever notice all those weird % signs in the location bar?? The CGI module provides the escape() function to convert that value into weird %nn characters. Properly you need to import that function aswell (I don't have experience with the object-orientated version calling of CGI.pm.

Code
use CGI qw(:cgi escape); # This is what I use today




Next, check if there isn't a HTTP header printed at an other location. If so, that causes the troubles.

P.S. You can put the unless() statement after the print statement aswell. Then you can remove the ( ) characters. (forgot how they were called) This syntax is useful when the main point of your statement isn't the unless disision, but the print statement. (larry wall quoted)

Example:

Code
print "Variable X is now $X" if $Verbose; 
print "name: $name" unless($name eq '');

In both of these statements it isn't the main point whether verbose is activated, or the name is omitted by the user. Then it's mostly better to put the controlling statement behind the action statement. Wink



S_Shrum
User

Nov 1, 2001, 4:30 PM

Post #9 of 10 (1547 views)
Re: ? about CGI.PM input format in regards to SPLIT [In reply to] Can't Post

Well, removing the -URI= and the -NPH=1 from the redirect line worked. That seemed odd as this is the code that was listed in the PERLDOC.

The -nph is for Microsoft servers (no parse headers) but since my host is running BSD, it's not an issue (I guess).

I like the idea of dumping the error data to a new file or the screen.

I can set up two params in all my scripts, DEBUG and OUTPUT. If DEBUG is defined, the errors won't go to the standard web error log. OUTPUT can be either file or screen, which would allow me the choice of where I want the error to go....That would be great!

Do you have a code snippet that illustrates a error redirect to file and a error redirect to screen?

Thanks for the excellent idea.

Sean Shrum
sean@shrum.net
www.shrum.net


yapp
User

Nov 2, 2001, 1:55 AM

Post #10 of 10 (1543 views)
Re: ? about CGI.PM input format in regards to SPLI [In reply to] Can't Post

Your explaination of -nph is correct, but the I'ts used for something else.
"Non parsed headers" mean that the webserver doesn't look and validate your HTTP headers. (just redirects them to the browser)
Under the apache webserver your script filename needs to start with nph- to make it work.
This is used to 'server push' document contents. That means that the server keeps the connection open ( the perl program does a sleep() )
and it starts re-sending a new HTTP header. With this technique the server can refresh or add content to the document already shown in the browser.

I looked at perldoc -q STDERR and found this line:

Code
open(STDERR, ">&STDOUT");

However, there are some comments about reopening to STDOUT (look for yourself).
You can replace STDOUT with a filehandle off course.
However, you can also take advantage of the $SIG{'__DIE__'} and $SIG{'__WARN__'} variables.
Look at this sample: (I type in in direwctly, so fix any errors you might find)


Code
#!/usr/bin/perl -w 

use stirct;
use CGI qw(:cgi); # non-object CGI calling version
#use CGI::Carp qw(fatalsToBrowser); # Disabled (we have out own)

BEGIN
{

# Code in a BEGIN block runs earlier, so we can trap compile errors.

sub TrapError
{ my($Error) = @_;
print header();
print <<ERROR_PAGE;
<HTML><HEAD><TITLE>Error!</TITLE></HEAD>
<BODY>
<H1>Error!</H1>
$Error
</BODY>
</HTML>
ERROR_PAGE
}

# The CGI::Carp module also has the set_message() sub to do this task
# like this: use CGI::Carp qw(fatalsToBrowser set_message);
$SIG{'__DIE__'} = \&TrapError; # fatal errors and die() statements
$SIG{'__WARN__'} = &TrapError; # compile errors, warn() statements (-w make more warnings)

# You can also use the carpout() sub exported by CGI::Carp
# like this: use CGI::Carp qw(carpout);
open(LOG, ">log.txt") or die "Can't open LOG";
open(STDERR, ">&LOG") or die "Can't reopen STDERR";

} #End BEGIN

# more code

Recently I've written some modules for some CGI tasks. I found out that I always needed this:

I've written them, and they are available at
http://www.cool-programming.f2s.com/cgi-perl/cgimodules
XProgramming::CGI::ASCII2HTML - ASCII characters converting into HTML escape codes, like &reg; for &reg; and &amp; for &
XProgramming::CGI::Template - Template Handling
XProgramming::CGI::ErrorTrap - Errors are handled immidiately when the script starts
XProgramming::CGI::Location - Location Detection of the script at the webserver - VERY COOL
XProgramming::File::DBIO - File IO routines for flat database files
XProgramming::Test::Input - Validation of input
XProgramming::Net::Mailer - Mailer routines





(This post was edited by yapp on Nov 2, 2001, 5:07 AM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives