#!/usr/bin/perl # Bibliotecas Requeridas # -------------------------------------------------------- eval { ($0 =~ m,(.*)/[^/]+,) && unshift (@INC, "$1"); # Pega o local do script: UNIX / ($0 =~ m,(.*)\\[^\\]+,) && unshift (@INC, "$1"); # Pega o local do script: Windows \ require "/home/oriod137/public_html/oriodejaneiro.net/scgi-bin/busca/admin/links.cfg"; require "$db_lib_path/db_utils.pl"; require "$db_lib_path/links.def"; require "$db_lib_path/site_html.pl"; }; if ($@) { print "Content-type: text/plain\n\n"; print "Erro incluindo bibliotecas: $@\n"; print "Tenha certeza de que elas existem, permissões estão corretas e caminhos estão definidos corretamente."; exit; } # ======================================================== eval { &main; }; if ($@) { &cgierr("fatal error: $@"); } exit; sub main { # -------------------------------------------------------- %in = &parse_form(); # Exibe o formulário chamado sem nenhuma entrada. (keys %in <= 0) and &site_html_search_form() and return; # Define o nº max de hits - padrao para 25. local $maxhits = 25; if ($in{'mh'} && (($in{'mh'} == 10) || ($in{'mh'} == 25) || ($in{'mh'} == 50) || ($in{'mh'} = 100))) { $maxhits = $in{'mh'}; } # Define o tipo de busca -- ou frase ou palavras-chave. Também constroi uma lista ser procurada. my @search_terms = (); ($in{'type'} eq 'phrase') ? (@search_terms = ($in{'query'})) : (@search_terms = split (/\s/, $in{'query'})); # Define o conector booleano e a próxima página de hits. my $bool = $in{'bool'} || 'and'; my $nh = $in{'nh'} || 1; my $search_subcategories = $in{'subcategories'} || 0; # Busca em Subcategorias # Store the search results here. local (%link_results, @category_results); # Setup for category-search local (@categories, @category_search_fields); open (DB, "<$db_category_name") or &cgierr("unable to open $db_file_name. Reason: $!"); @categories = ; close DB; @category_search_fields = (1,2,4,5,8); # Do the actual search. if ($in{'where'}) { my $status = &catsearch(\@search_terms, $bool, $search_subcategories); if ($status ne "ok") { &site_html_search_failure ($status); return; } } else { my $status = &search (\@search_terms, $bool); if ($status ne "ok") { &site_html_search_failure ($status); return; } } # Return unless we have results. ((keys %link_results > 0) or ($#category_results >= 0)) or &site_html_search_failure ("nenhum registro encontrado") and return; # The HTML used in the output is stored here. local ($cat_hits, $link_hits, $category_results, $link_results, $next); # Build the HTML for the category results and store it in "$category_results". Only build the html # if we are on the first set of link results. foreach $category (@category_results) { if ($nh == 1) { $cat_clean = &build_clean($category); $linked_title = &build_linked_title_mb ($category); $category_results .= qq|
  • $linked_title\n|; } $cat_hits++; } $cat_hits ||= 0; $lowrange = ($nh-1) * $maxhits + 1; $highrange = $nh * $maxhits; # Go through each category of links returned, and build the HTML. Store in hash %link_output. SETOFLINKS: foreach $setoflinks (sort keys %link_results) { my $hits = ($#{$link_results{$setoflinks}} + 1) / ($#db_cols+1); LINK: for ($i = 0; $i < $hits; $i++) { $link_hits++; if (($link_hits <= $highrange) && ($link_hits >= $lowrange)) { %tmp = &array_to_hash ($i, @{$link_results{$setoflinks}}); $link_output{$setoflinks} .= &site_html_link (%tmp) . "\n"; } } } # Go through the hash just built, and build the complete link output. Store in $link_results. foreach $setoflinks (sort keys %link_output) { $cat_clean = &build_clean ($setoflinks); $title_linked = &build_linked_title_mb ($setoflinks); $link_results .= qq|

    <$font>$title_linked\n|; $link_results .= $link_output{$setoflinks}; } # If we want to bold the search terms... if ($search_bold) { foreach $term (@search_terms) { # This reg expression will do the trick, and doesn't bold things inside <> tags such as # URL's. $link_results =~ s,(<[^>]+>)|(\Q$term\E),defined($1) ? $1 : "$2",gie; $category_results =~ s,(<[^>]+>)|(\Q$term\E),defined($1) ? $1 : "$2",gie; } } # If we have to many hits, let's build the next toolbar, and return only the hits we want. my ($next_hit, $prev_hit, $next_url, $left, $right, $lower, $upper, $i); if ($link_hits > $maxhits) { # Remove the nh= from the query string. $next_url = $ENV{'QUERY_STRING'}; $next_url =~ s/\&nh=\d+//; $next_hit = $nh + 1; $prev_hit = $nh - 1; # First, set how many pages we have on the left and the right. $left = $nh; $right = int($numhits/$maxhits) - $nh; # Then work out what page number we can go above and below. ($left > 7) ? ($lower = $left - 7) : ($lower = 1); ($right > 7) ? ($upper = $nh + 7) : ($upper = int($link_hits/$maxhits) + 1); # Finally, adjust those page numbers if we are near an endpoint. (7 - $nh >= 0) and ($upper = $upper + (8 - $nh)); ($nh > ($link_hits/$maxhits - 7)) and ($lower = $lower - ($nh - int($link_hits/$maxhits - 7) - 1)); $next = ""; # Then let's go through the pages and build the HTML. ($nh > 1) and ($next .= qq~[<<] ~); for ($i = 1; $i <= int($link_hits/$maxhits) + 1; $i++) { if ($i < $lower) { $next .= " ... "; $i = ($lower-1); next; } if ($i > $upper) { $next .= " ... "; last; } ($i == $nh) ? ($next .= qq~$i ~) : ($next .= qq~$i ~); (($i * $maxhits) >= $link_hits) and last; # Special case if we hit exact. } $next .= qq~[>>] ~ unless ($nh == $i); } &logsearch; # Print out the HTML results. &site_html_search_results; } sub search { # -------------------------------------------------------- # This routine does the actual search of the database. # my ($search_terms, $bool) = @_; my ($regexp, @values, $grand_total, $match, $andmatch, $field, $or_match, %seen, $link, $tmp); &logsearch; # Save the reg expressions to avoid rebuilding. $or_match = $bool ne 'and'; if ($or_match) { for (0 .. $#{$search_terms}) { next if (length ${$search_terms}[$_] < 2); # Skip single letter words. $tmp .= "m/\Q${$search_terms}[$_]\E/io ||"; } } else { for (0 .. $#{$search_terms}) { next if (length ${$search_terms}[$_] < 2); # Skip single letter words. $tmp .= "m/\Q${$search_terms}[$_]\E/io &&"; } } chop ($tmp); chop ($tmp); # We can also search by field names. my @field_search; for (0 .. $#db_cols) { exists $in{$db_cols[$_]} and (push (@field_search, $_)); } if (!$tmp and !@field_search) { return ("Por favor, entre uma ou mais palavras chaves."); } if ($tmp) { $regexp = eval "sub { $tmp }"; $@ and &cgierr ("Can't compile reg exp: $tmp! Reason: $@");} # Go through the database. open (DB, "<$db_file_name") or &cgierr("error in search. unable to open database: $db_file_name. Reason: $!"); flock (DB, 1) if ($db_use_flock); LINE: while () { /^#/ and next LINE; # Skip comment Lines. /^\s*$/ and next LINE; # Skip blank lines. chomp; # Remove trailing new line. @values = &split_decode($_); $grand_total++; # Check to see if the link matches. $match = 0; $andmatch = 1; if ($regexp) { FIELD: foreach $field (@search_fields) { $_ = $values[$field]; $or_match ? ($match = $match || &{$regexp}) : ($match = &{$regexp}); last FIELD if ($match); } } # Check to see if the link matches any database fields. Only exact matches # here. if ($or_match || $match || !$regexp) { FIELD: foreach $field (@field_search) { if ($or_match) { $match = $match || ($in{$db_cols[$field]} eq $values[$field]); $match and last FIELD; } else { $match = ($in{$db_cols[$field]} eq $values[$field]); $match or last FIELD; } } } $andmatch = $andmatch && $match; # If we have a hit, add it in! if (($or_match && $match) or $andmatch) { push (@{$link_results{$values[$db_category]}}, @values); $numhits++; # We have a match! } } close DB; # Check to see if the category matches in the category db. CATEGORY: foreach $category (@categories) { if ($category =~ /^#/) { next CATEGORY; } # Skip comment lines. if ($category =~ /^\s*$/) { next CATEGORY; } # Skip blank lines. chomp; # Remove trailing new line. @values = &split_decode($category); # First we check to make sure the category is not already in our @category_results. if (!(grep $_ eq $values[1], @category_results)) { # Check to see if the category matches. $match = 0; $andmatch = 1; if ($regexp) { FIELD: foreach $field (@category_search_fields) { $_ = $values[$field]; $or_match ? ($match = $match || &{$regexp}) : ($match = &{$regexp}); last FIELD if ($match); } } $andmatch = $andmatch && $match; # If we have a hit, add it in! if (($or_match && $match) or $andmatch) { $numcat++; push (@category_results, $values[1]); } } } # Word is too common, don't try and sort it, can cause problems. if (($numhits > 1000) and (($grand_total * 0.75) < $numhits)) { return "Termo de busca é muito comum."; } # Sort the results using build_sorthit found in db.pl. foreach $link ( keys %link_results ) { @{$link_results{$link}} = &build_sorthit (@{$link_results{$link}}); } @category_results = sort @category_results; return "ok"; } sub build_linked_title { # -------------------------------------------------------- # A little different then the one found in nph-build.cgi as it also # links up the last field as well. my ($input) = shift; my ($dir, $output, $path, $last); foreach $dir ((split m!/!, $input)) { $path .= "/$dir"; $dir = &build_clean ($dir); $output .= qq|$dir:|; } chop ($output); return $output; } sub build_linked_title_mb { # -------------------------------------------------------- # A little different then the one found in nph-build.cgi as it also # links up the last field as well. my ($input) = $_[0]; my (@dirs, $dir, $output, $path, $nonenglish, $category, @fields, @descs, $desc); @dirs = split (/\//, $input); $nonenglish = ""; CATEGORY: foreach $category (@categories) { if ($category =~ /^#/) { next CATEGORY; } # Skip comment lines. chomp ($category); @fields = &split_decode ($category); if ($fields[1] eq $input) { $nonenglish = $fields[8]; last CATEGORY; } } if ($nonenglish eq "") { @descs = @dirs; } else { @descs = split (/\\/, $nonenglish); } foreach $dir (@dirs) { $path .= "/$dir"; $desc = shift (@descs); $output .= qq|$desc: |; } chop ($output); return $output; } sub catsearch { # -------------------------------------------------------- # This routine does the actual search of the database. # my ($search_terms, $bool, $search_subcategories) = @_; my ($regexp, @values, $grand_total, $match, $andmatch, $field, $or_match, %seen, $link, $tmp); &logsearch; # Save the reg expressions to avoid rebuilding. $or_match = $bool ne 'and'; if ($or_match) { for (0 .. $#{$search_terms}) { next if (length ${$search_terms}[$_] < 2); # Skip single letter words. $tmp .= "m/\Q${$search_terms}[$_]\E/io ||"; } } else { for (0 .. $#{$search_terms}) { next if (length ${$search_terms}[$_] < 2); # Skip single letter words. $tmp .= "m/\Q${$search_terms}[$_]\E/io &&"; } } chop ($tmp); chop ($tmp); # We can also search by field names. my @field_search; for (0 .. $#db_cols) { exists $in{$db_cols[$_]} and (push (@field_search, $_)); } if (!$tmp and !@field_search) { return ("Please enter one or more keywords."); } if ($tmp) { $regexp = eval "sub { $tmp }"; $@ and &cgierr ("Can't compile reg exp: $tmp! Reason: $@");} # Go through the database. open (DB, "<$db_file_name") or &cgierr("error in search. unable to open database: $db_file_name. Reason: $!"); flock (DB, 1) if ($db_use_flock); LINE: while () { /^#/ and next LINE; # Skip comment Lines. /^\s*$/ and next LINE; # Skip blank lines. chomp; # Remove trailing new line. @values = &split_decode($_); $grand_total++; # Check to see if the link matches. $match = 0; $andmatch = 1; if ($regexp) { FIELD: foreach $field (@search_fields) { $_ = $values[$field]; if ($or_match) {$category = $values[$db_category] ; if ( ($search_subcategories && ($category =~ /$in{'where'}\/.+/)) or ($in{'where'} eq $category) ){ $match = $match || &{$regexp}; last FIELD if ($match); } } else {$category = $values[$db_category] ; if ( ($search_subcategories && ($category =~ /$in{'where'}\/.+/)) or ($in{'where'} eq $category) ){ $match = &{$regexp}; last FIELD if ($match); } } } } # Check to see if the link matches any database fields. Only exact matches # here. if ($or_match || $match || !$regexp) { FIELD: foreach $field (@field_search) { if ($or_match) {$category = $values[$db_category] ; if ( ($search_subcategories && ($category =~ /$in{'where'}\/.+/)) or ($in{'where'} eq $category) ){ $match = $match || ($in{$db_cols[$field]} eq $values[$field]); $match and last FIELD; } } else {$category = $values[$db_category] ; if ( ($search_subcategories && ($category =~ /$in{'where'}\/.+/)) or ($in{'where'} eq $category) ){ $match = ($in{$db_cols[$field]} eq $values[$field]); $match or last FIELD; } } } } $andmatch = $andmatch && $match; # If we have a hit, add it in! if (($or_match && $match) or $andmatch) { push (@{$link_results{$values[$db_category]}}, @values); $numhits++; # We have a match! } # Check to see if the category matches. if ($regexp and !$seen{$values[$db_category]}++) { $match=0; $andmatch = 1; $_ = $values[$db_category]; if ($or_match) {$category = $values[$db_category] ; if ( ($search_subcategories && ($category =~ /$in{'where'}\/.+/)) or ($in{'where'} eq $category) ){ $match = $match || &{$regexp}; } } else {$category = $values[$db_category] ; if ( ($search_subcategories && ($category =~ /$in{'where'}\/.+/)) or ($in{'where'} eq $category) ){ $match = &{$regexp}; } } $andmatch = $andmatch && $match; if (($or_match && $match) or $andmatch) { $numcat++; push (@category_results, $values[$db_category]); } } } close DB; # Word is too common, don't try and sort it, can cause problems. if (($numhits > 1000) and (($grand_total * 0.75) < $numhits)) { return "Termo de Busca é muito comum."; } # Sort the results using build_sorthit found in db.pl. foreach $link ( keys %link_results ) { @{$link_results{$link}} = &build_sorthit (@{$link_results{$link}}); } @category_results = sort @category_results; return "ok"; } sub logsearch { $in{'query'} =~ tr/A-Z/a-z/; if (!$in{'query'}) { $in{'query'} = "Busca Falhou"; } # Se não existe termo de busca, adiciona "Busca Falhou" para evitar algo como "|1". open (KEYWORDS,"$keyword_file") or &cgierr("Erro na busca. Impossível abrir $keyword_file"); @lines = ; close(KEYWORDS); open (KEYWORDS, ">$keyword_file") or &cgierr("Erro na busca. Impossível abrir $keyword_file"); foreach $line (@lines) { ($log_query, $log_query_calls) = split(/\|/,$line); if ("$in{'query'}" eq $log_query) { $log_query_calls++; print KEYWORDS ("$log_query|$log_query_calls\n"); $addnew=1; } else { print KEYWORDS $line; } } if ($addnew == 0) { print KEYWORDS ("$in{'query'}|1\n"); } close (KEYWORDS); }