In article <[EMAIL PROTECTED]>, [EMAIL PROTECTED] (Ilya Sterin) wrote:
> Well post the script and we can look. Please eliminate the parts that are > not relevant if you script is big. it's about 255 lines of code incuding comments.. I'll remove the comments from the file to shorten it a bit. The linewrapping will suck but I'll try and clean it up a bit. it's *considerably* streamlined from my first hackish attempts at writing cgi scripts and from working with the original CSV/Tab-delimited tables using DBD::CSV and more recently DBD::AnyData. I'm damned proud of how far I've come in the year since I started working with Perl, and situations like this just <gross understatement>annoy me</gross understatement>. Your help will be most greatly appreciated. I'm starting to wonder how much of a threat to Perl the PHP crowd really is, and how much of a resource hog mod_perl is compared with the embedded PHP in Apache, and why, if PHP is based on Perl, there could be such a huge disparity in performance. > These benchmarks are a bunch of crap. There are 900 times more bytes > transfered. The files look way to much different in sizes. So we are yet > to see an exact comparison:-) definitely. I *KNOW* how hard I've worked on streamlining this code, and I'll be damned if someone can hack together a php script that does things in half the time, and with fewer memory resources used, much less what that so-called-benchmark shows. the code: #!/usr/bin/perl -T #### search.cgi use warnings; use strict; use CGI qw/:standard :html3 *table *div *form -no_xhtml escapeHTML unescapeHTML/; # do these get left out if you use CGI->compile(':all') # and in particular with mod_perl and Apache::DBI? # security sanity check. $CGI::POST_MAX = 1024 * 16; # max 16k POSTs $CGI::DISABLE_UPLOADS++; # no uploads $ENV{'PATH'} = '/bin:/usr/bin:'; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; use CGI::Carp qw(fatalsToBrowser set_message); BEGIN { sub handle_errors { my $msg = join( br(), @_); print header, start_html( "CGI/Perl Script Error" ), h2( "aCk!"), p( "I must be currently beta-testing some changes, so E-mail me, ", a({-href=>'mailto:[EMAIL PROTECTED]'}, "fuzzbuster"), ", about this if it persists for very long.", ), hr, p( "Got an error: $msg" ), end_html; } set_message(\&handle_errors); }; use DBI; my $dbiuser = 'nalicity'; my $dbipass = 'password'; my $map_db = 'maps'; my $download_url = 'http://www.planetunreal.com/dl/nc.asp?nalicity/'; my @types = (qw/empty unknown unknown unknown unknown unknown utdm utassault utdomination utctf utother/); my $newStyle = <<'EOS'; table, caption, th, td { background: #1E2B4A; font-family: "Trebuchet MS", "Sapir Sans", sans-serif; font-size: 12pt; } body { font-family: "Trebuchet MS", "Sapir Sans", sans-serif; font-size: 12pt; } EOS my %files_list = ( '7' => 'UT Assault Maps', '9' => 'UT Capture The Flag Maps', '6' => 'UT DeathMatch Maps', '8' => 'UT Domination maps', '10' => 'UT Other Maps' ); sub size_calc ($) { my $mapsize = shift; ($mapsize <= 1024) ? return $mapsize . "k" : return sprintf('%.2f', ($mapsize/1024)) . "MB"; }; sub checkrating ($$$) { my($rating, $reviewfile, $id) = @_; if ( $rating == -1 ) { return "N/A"; } else { if ($reviewfile eq "-1") { return a({-href=>"http://nalicity.beyondunreal.com/testbed/review.php?Id=${id}", -target=>"review"}, b($rating), ); } else { return a({-href=>"http://nalicity.beyondunreal.com/testbed/reviews/${reviewfile} .html", -target=>"review"}, b($rating), ); } } }; sub create_dbi_table ($) { my $displayselect = shift; my $dbh = DBI->connect("DBI:mysql:database=nalicity;host=localhost", $dbiuser, $dbipass, {RaiseError => 1}) or die("Cannot connect to database - $!"); END { $dbh->disconnect if $dbh } my $sth = $dbh->prepare($displayselect) or die $dbh->errstr; $sth->execute; my $rowcount = $sth->rows; unless( $rowcount ) { print Tr( td({-colspan=>3, -align=>'center', }, b("No Match Found") )); return ''; } print Tr( td({-colspan=>3, -align=>'center', }, b("Found $rowcount matches") )); my( $type, $id, $filename, $title, $size, $reviewfile, $rating, $rated, $oldtype ); $sth->bind_columns(\$type, \$id, \$filename, \$title, \$size, \$reviewfile, \$rating); while ( $sth->fetch ) { # in english: If oldrating is empty, or different from the # previous rating AND the rating is now < 0 if ( !defined($rated) or ($rated != $rating and $rating < 0) ) { # then check to see whether we're rated or unrated and print # an appropriate header for that section if ($rating < 0) { print Tr( td({-colspan=>3, -align=>'center', }, b( u("Unrated Maps")) )), Tr( th({-align=>"center"}, "Map Name"), th({-align=>"right"}, "Size"), th({-align=>"center"}, "Rating"), ); $oldtype = -1; #re-set oldtype ;) } else { print Tr( td({-colspan=>3, -align=>'center', }, b( u("Rated Maps")) )), Tr( th({-align=>"center"}, "Map Name"), th({-align=>"right"}, "Size"), th({-align=>"center"}, "Rating"), ); }; }; # okay so we have nice section headers.. # how about some type section headers for the unrated section? if ( $rating == -1 and $type != $oldtype ) { print Tr( td({-colspan=>3, -align=>'center'}, $files_list{$type} ) ); } $filename= unescapeHTML($filename); print Tr( td({-align=>"left", -valign=>"top"}, a({-href=>"${download_url}$types[${type}]/${filename}.zip", -target=>"_new"}, $title ), ), td({-align=>"right", -valign=>"top"}, size_calc($size), ), td({-align=>"center", -valign=>"top",}, checkrating($rating, $reviewfile, $id), ), ), "\n"; # adjust loop vars for prettyprint $rated = $rating; $oldtype = $type; }; die $sth->errstr if $sth->err; } my $search_obj = escapeHTML( param('searchfor') ) || ''; # un-taint the search object $search_obj =~ m/([ a-zA-Z-_\[\]\{\}0-9]+)/; $search_obj = $1; if (!param() && cgi_error()) { print header(-status=>cgi_error()); goto FINISH;# don't call exit 0; !!! (unless you LIKE killing your perl process over and over, ass-hat) :P } my $expires = (localtime(time + 30)); print header({'head'=>meta( {-http_equiv=>'Expires', -content=>$expires } )}), start_html({-Title=>"FuzzBuster's NaliCity Quick Search!", -Style=>{-Code=>$newStyle}, -bgcolor=>'#003366', -text=>'white', -"link"=>'#ffff99', -vlink=>'yellow'}); print start_form, div({-align=>'center'}, h3("Map Search"), p("Enter the name of a map title or file to search for:"), textfield(-name=>'searchfor', -default=>'', -size=>30, -maxlength=>68, -override=>1), br, submit(-name=>'Submit', -value=>'Submit'), ), end_form, hr; if ( $search_obj eq '' ) { # skip the database query print end_html; goto FINISH; } my $query = "SELECT Type, ID, FileName, Title, Size, ReviewFile, ROUND(Rating, 2) FROM $map_db WHERE FileName LIKE '%$search_obj%' OR Title LIKE '%$search_obj%' ORDER BY Rating DESC, Type, FileName"; print start_div({-align=>"center"}), start_table({-border=>"0", -cellpadding=>"0", -cellspacing=>"2", -width=>"300"}); create_dbi_table($query); print end_table, end_div, hr, end_html; FINISH: # end of code If anyone is interested I can provide particulars on the maps table in the MySQL database as well. -- Scott R. Godin | e-mail : [EMAIL PROTECTED] Laughing Dragon Services | web : http://www.webdragon.net/