#!/usr/bin/perl # Search AREA members by name or AREA ID or games by title. # Bruno Wolff III # Last revised October 20,2012 use utf8; use feature 'unicode_strings'; use open ':encoding(utf8)'; use POSIX qw(locale_h); setlocale(LC_ALL, "en_US.utf8"); # Flush output immediately as database lookups can cause delays. select(STDOUT); $| = 1; # Prevent ridiculously large requests from causing problems. $MAXPOST = 10000; # Turn off space seperators when including arrays in quoted text. $" = ''; use Pg; # Use this to clean stuff extracted from the database for html output sub clean(@) { local $str = "@_"; $str =~ s/&/&/g; $str =~ s//>/g; $str =~ s/"/"/g; return $str; } # Use this to convert REQUEST_URI to unescaped string sub urldecode(@) { local $str = "@_"; $str =~ s/\%[[:digit:]abcdefABCDEF]{2}/$urldhash{$&}/eg; return $str; } # Use this to make sure urls don't contain url specials sub urlencode(@) { local $str = "@_"; $str =~ s/[^-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ[:digit:].$+!*(),]/$urlehash{$&}/eg; return $str; } # One time build of data used by url decode sub urlinit() { my $c; my $f; my $i; for ($i=0; $i<=255; $i++) { $c = chr($i); $f = sprintf('%%%.2X', $i); $urldhash{$f} = $c; $urldhash{lc($f)} = $c; $urldhash{lc($f)} = '' if $i > 127; $urlehash{$c} = $f; } } urlinit; # Get paramters. if ($ENV{REQUEST_METHOD} eq 'POST') { $ENV{QUERY_STRING} = ''; if ($ENV{CONTENT_LENGTH} =~ m/^\d+$/ && $ENV{CONTENT_LENGTH} >= 0 && $ENV{CONTENT_LENGTH} <= $MAXPOST && lc($ENV{CONTENT_TYPE}) eq 'application/x-www-form-urlencoded') { if (read(STDIN, $ENV{QUERY_STRING}, $ENV{CONTENT_LENGTH}) != $ENV{CONTENT_LENGTH}) { $ENV{QUERY_STRING} = ''; } } } elsif ($ENV{REQUEST_METHOD} eq '') { $ENV{QUERY_STRING} = ''; } elsif ($ENV{REQUEST_METHOD} ne 'GET' && $ENV{REQUEST_METHOD} ne 'HEAD') { $meth = clean($ENV{REQUEST_METHOD}); $uri = clean($ENV{REQUEST_URI}); print <<"EOF"; content-type: text/html; charset=UTF-8 status: 501 Method not implemented 501 Method Not Implemented

Method Not Implemented

Method '$meth' not implented for '$uri'. EOF exit; } $ENV{QUERY_STRING} =~ s/\+/ /g; foreach $s (split('&', $ENV{QUERY_STRING})) { my $s1; my $s2; next if $s eq ''; if ($s =~ m/\=/) { $s1 = $`; $s2 = $'; $par{urldecode($s1)} .= urldecode($s2); } else { $par{urldecode($s)} .= ''; } } $keywords = clean($par{keywords}); utf8::decode($par{keywords}); $uri = $ENV{REQUEST_URI}; $uri =~ s%\?.*$%%; $uri =~ s%^.*/%%; print << "EOF"; content-type: text/html; charset=UTF-8 Search AREA for members by name or AREA ID or games by title

Search AREA for members by name or AREA ID or games by Title

Search text:
EOF # Only one query is done so we don't need to set transaction isolation. if (defined($par{namefull})) { print "

Member name search results (using full word matching)

\n"; $conn = Pg::connectdb('dbname=area client_encoding=UTF8'); if ($conn->status != PGRES_CONNECTION_OK) { print "Unable to connect the AREA database.\n"; } else { $s = ''; $j = 'where'; foreach $word (split(/[^[:graph:]]+/, $par{keywords})) { next if $word eq ''; $word =~ s/[^[:graph:]]//g; $word =~ s/[^[:alnum:]]/\\$&/g; $word =~ s/\\|\'/\\$&/g; $s .= " $j (lname ~* '(^| )$word( |\$)' or fmname ~* '(^| )$word( |\$)' or aname ~* '(^| )$word( |\$)' or coalesce(genlab, to_char(gen, 'FMRN')) ~* '(^| )$word( |\$)')"; $j = 'and'; } $result = $conn->exec("select areaid, lname, fmname, aname, coalesce(genlab, to_char(gen, 'FMRN')) from cname_web $s order by lower(lname), lower(coalesce((aname || ' ') || fmname, fmname, aname)), gen, genlab, areaid"); if ($result->resultStatus != PGRES_TUPLES_OK) { print "Unable to access the cname_web table.\n"; print "select areaid, lname, fmname, aname, coalesce(genlab, to_char(gen, 'FMRN')) from cname_web $s order by lower(lname), lower(coalesce((aname || ' ') || fmname, fmname, aname)), gen, genlab, areaid\n"; } elsif ($result->ntuples <= 0) { print "No members with matching names were found.\n"; } else { print "\n\n"; while (@row = $result->fetchrow) { $id = clean(urlencode($row[0])); $areaid = clean($row[0]); if (!defined($row[1])) { $name = '* Name Withheld *'; } else { $name = $row[1]; if (defined($row[4])) { $name .= ' ' . $row[4]; } if (defined($row[2])) { if (defined($row[3])) { $name .= ', ' . $row[3] . ' (' . $row[2] . ')'; } else { $name .= ', ' . $row[2]; } } elsif (defined($row[3])) { $name .= ', ' . $row[3]; } } $name = clean($name); print "
AREA IDName
$areaid$name\n"; } print "
\n"; } } } elsif (defined($par{namepre})) { print "

Member name search results (using word prefix matching)

\n"; $conn = Pg::connectdb('dbname=area'); if ($conn->status != PGRES_CONNECTION_OK) { print "Unable to connect the AREA database.\n"; } else { $s = ''; $j = 'where'; foreach $word (split(/[^[:graph:]]+/, $par{keywords})) { next if $word eq ''; $word =~ s/[^[:graph:]]//g; $word =~ s/[^[:alnum:]]/\\$&/g; $word =~ s/\\|\'/\\$&/g; $s .= " $j (lname ~* '(^| )$word' or fmname ~* '(^| )$word' or aname ~* '(^| )$word' or coalesce(genlab, to_char(gen, 'FMRN')) ~* '(^| )$word')"; $j = 'and'; } $result = $conn->exec("select areaid, lname, fmname, aname, coalesce(genlab, to_char(gen, 'FMRN')) from cname_web $s order by lower(lname), lower(coalesce((aname || ' ') || fmname, fmname, aname)), gen, genlab, areaid"); if ($result->resultStatus != PGRES_TUPLES_OK) { print "Unable to access the cname_web table.\n"; } elsif ($result->ntuples <= 0) { print "No members with matching names were found.\n"; } else { print "\n\n\n\n"; while (@row = $result->fetchrow) { $id = clean(urlencode($row[0])); $areaid = clean($row[0]); if (!defined($row[1])) { $name = '* Name Withheld *'; } else { $name = $row[1]; if (defined($row[4])) { $name .= ' ' . $row[4]; } if (defined($row[2])) { if (defined($row[3])) { $name .= ', ' . $row[3] . ' (' . $row[2] . ')'; } else { $name .= ', ' . $row[2]; } } elsif (defined($row[3])) { $name .= ', ' . $row[3]; } } $name = clean($name); print "
AREA IDName\n
$areaid$name\n"; } print "
\n"; } } } elsif (defined($par{gamefull})) { print "

Title search results (using full word matching)

\n"; $conn = Pg::connectdb('dbname=area'); if ($conn->status != PGRES_CONNECTION_OK) { print "Unable to connect the AREA database.\n"; } else { $s = ''; $j = 'where'; foreach $word (split(/[^[:graph:]]+/, $par{keywords})) { next if $word eq ''; $word =~ s/[^[:graph:]]//g; $word =~ s/[^[:alnum:]]/\\$&/g; $word =~ s/\\|\'/\\$&/g; $s .= " $j title ~* '(^| )$word( |\$)'"; $j = 'and'; } $result = $conn->exec("select gameid, title from games $s order by lower(title)"); if ($result->resultStatus != PGRES_TUPLES_OK) { print "Unable to access the games table.\n"; } elsif ($result->ntuples <= 0) { print "No games with matching titles were found.\n"; } else { print "\n\n\n\n"; while (@row = $result->fetchrow) { $code = clean(urlencode($row[0])); $title = clean($row[1]); print "
Title\n
$title\n"; } print "
\n"; } } } elsif (defined($par{gamepre})) { print "

Title search results (using word prefix matching)

\n"; $conn = Pg::connectdb('dbname=area'); if ($conn->status != PGRES_CONNECTION_OK) { print "Unable to connect the AREA database.\n"; } else { $s = ''; $j = 'where'; foreach $word (split(/[^[:graph:]]+/, $par{keywords})) { next if $word eq ''; $word =~ s/[^[:graph:]]//g; $word =~ s/[^[:alnum:]]/\\$&/g; $word =~ s/\\|\'/\\$&/g; $s .= " $j title ~* '(^| )$word'"; $j = 'and'; } $result = $conn->exec("select gameid, title from games $s order by lower(title)"); if ($result->resultStatus != PGRES_TUPLES_OK) { print "Unable to access the games table.\n"; } elsif ($result->ntuples <= 0) { print "No games with matching titles were found.\n"; } else { print "\n\n\n\n"; while (@row = $result->fetchrow) { $code = clean(urlencode($row[0])); $title = clean($row[1]); print "
Title\n
$title\n"; } print "
\n"; } } } elsif (defined($par{idfull})) { print "

Member AREA ID search results (using full word matching)

\n"; $conn = Pg::connectdb('dbname=area'); if ($conn->status != PGRES_CONNECTION_OK) { print "Unable to connect the AREA database.\n"; } else { $s = ''; $j = 'where'; foreach $word (split(/[^[:graph:]]+/, $par{keywords})) { next if $word eq ''; $word =~ s/[^[:graph:]]//g; $word =~ s/[^[:alnum:]]/\\$&/g; $word =~ s/\\|\'/\\$&/g; $s .= " $j areaid ~* '(^| )$word( |\$)'"; $j = 'and'; } $result = $conn->exec("select areaid, lname, fmname, aname, coalesce(genlab, to_char(gen, 'FMRN')) from cname_web $s order by areaid"); if ($result->resultStatus != PGRES_TUPLES_OK) { print "Unable to access the cname_web table.\n"; } elsif ($result->ntuples <= 0) { print "No members with matching AREA IDs were found.\n"; } else { print "\n\n\n\n"; while (@row = $result->fetchrow) { $id = clean(urlencode($row[0])); $areaid = clean($row[0]); if (!defined($row[1])) { $name = '* Name Withheld *'; } else { $name = $row[1]; if (defined($row[4])) { $name .= ' ' . $row[4]; } if (defined($row[2])) { if (defined($row[3])) { $name .= ', ' . $row[3] . ' (' . $row[2] . ')'; } else { $name .= ', ' . $row[2]; } } elsif (defined($row[3])) { $name .= ', ' . $row[3]; } } $name = clean($name); print "
AREA IDName\n
$areaid$name\n"; } print "
\n"; } } } elsif (defined($par{idpre})) { print "

Member AREA ID search results (using word prefix matching)

"; $conn = Pg::connectdb('dbname=area'); if ($conn->status != PGRES_CONNECTION_OK) { print "Unable to connect the AREA database.\n"; } else { $s = ''; $j = 'where'; foreach $word (split(/[^[:graph:]]+/, $par{keywords})) { next if $word eq ''; $word =~ s/[^[:graph:]]//g; $word =~ s/[^[:alnum:]]/\\$&/g; $word =~ s/\\|\'/\\$&/g; $s .= " $j areaid ~* '(^| )$word'"; $j = 'and'; } $result = $conn->exec("select areaid, lname, fmname, aname, coalesce(genlab, to_char(gen, 'FMRN')) from cname_web $s order by areaid"); if ($result->resultStatus != PGRES_TUPLES_OK) { print "Unable to access the cname_web table.\n"; } elsif ($result->ntuples <= 0) { print "No members with matching AREA IDs were found.\n"; } else { print "\n\n\n\n"; while (@row = $result->fetchrow) { $id = clean(urlencode($row[0])); $areaid = clean($row[0]); if (!defined($row[1])) { $name = '* Name Withheld *'; } else { $name = $row[1]; if (defined($row[4])) { $name .= ' ' . $row[4]; } if (defined($row[2])) { if (defined($row[3])) { $name .= ', ' . $row[3] . ' (' . $row[2] . ')'; } else { $name .= ', ' . $row[2]; } } elsif (defined($row[3])) { $name .= ', ' . $row[3]; } } $name = clean($name); print "
AREA IDName\n
$areaid$name\n"; } print "
\n"; } } } print << "EOF"; EOF