#!/usr/local/bin/perl



package WWW::Search::MSIndexServer;



=head1 NAME



WWW::Search::MSIndexServer - class for searching MSIndexServer search engine



=head1 SYNOPSIS



    require WWW::Search;

    $search = new WWW::Search('MSIndexServer');



=head1 DESCRIPTION



This class is a MSIndexServer specialization of WWW::Search.  It queries and

interprets searches based on MSIndexServer, which is available at

F<http://www.microsoft.com/>



This class exports no public interface; all interaction should be

done through WWW::Search objects.



=head1 OPTIONS



This search supports standard WWW::Search arguments



=over 8



=item search_url



The MSIndexServer URL to search.  This usually looks like

F<http://somehost/scripts/queryhit.idq>



=item search_args



The arguments used for the search engine, separate them by &.



=item search_method



POST or GET



=item search_debug



Turn debugging on or off



=item search_how



Possible values match_any, match_all, match_phrase



=back



=head1 SEE ALSO



To make new back-ends, see L<WWW::Search>,



=head1 AUTHOR



C<WWW::Search::MSIndexServer> is written by Paul Lindner, <lindner@itu.int>,

Nicholas Sapirie <sapirie@unicc.org>



=head1 COPYRIGHT



Copyright (c) 1998 by the United Nations Administrative Committee 

on Coordination (ACC)



All rights reserved.



=cut



use strict;

use vars qw(@EXPORT @EXPORT_OK @ISA $debug);



require Exporter;

@EXPORT = qw();

@EXPORT_OK = qw();

@ISA = qw(WWW::Search Exporter);





use Carp ();

require WWW::SearchResult;



my($debug) = 0;



#private



sub native_setup_search {

    my($self, $native_query, $native_opt) = @_;

    my($native_url);

    my($default_native_url) =

 "http://www.fao.org/scripts/samples/search/queryhit.idq?CiRestriction=%s&CiMaxRecordsPerPage=%n&CiScope=%2F&TemplateName=queryhit&CiSort=rank%5Bd%5D&HTMLQueryForm=%2Fsearch%2Fqueryhit.htm";

    

    if (defined($native_opt)) {

	#print "Got " . join(' ', keys(%$native_opt)) . "\n";

	# Process options..



	if ($self->{'search_url'} && $native_opt->{'search_args'}) {

	    $native_url = $native_opt->{'search_url'} . "?" . $native_opt->{'search_args'};

	}

	$debug = 1 if ($native_opt->{'search_debug'});

    } 



    $native_url = $default_native_url if (!$native_url);





    ## Change behaviour depending on 'search_how'

    my $how = $self->{'search_how'};

    if (defined($how)) {

	if ($how eq 'match%5Fany') {

	    $native_query =~ s/ and //g;

	} 

	elsif ($how eq 'match%5Fall') {

	    ### Add 'and'

	    $native_query =~ s/\s+and\s+//g;

	    $native_query =~ s/\s+/ and /g;

	} 

	elsif ($how eq 'match%5Fphrase') {

	    ### Add quotes around the item..

	    $native_query =~ s/[\'\"]+//g;

	    $native_query =~ s/\+/ /g;

	    $native_query = "'$native_query'";

	} 

	elsif ($how eq 'match_boolean') {

	    ## Leave asis

	    ;

	}

    }



    $native_url =~ s/%s/$native_query/g; # Substitute search terms...

    $native_url =~ s/%n/40/g; # Substitute num hits...

    $native_url .= "&MaxRecordsPerPage=40" if ($native_url !~ /MaxRecordsPerPage=/);



    $self->user_agent(1);

    $self->{_next_to_retrieve} = 0;

    $self->{_base_url} = $native_url;

    $self->{_next_url} = $native_url;

}





# private

sub native_retrieve_some

{

    my ($self) = @_;

    my ($hit)  = ();

    my ($hits_found) = 0;

    my($step) = 0;



    # fast exit if already done

    return undef if (!defined($self->{_next_url}));



    # get some

    my $method = $self->{search_method};

    if (! defined($method)) {

	$method = 'GET';

    }

    warn "$method ", $self->{_next_url}, "\n" if ($debug);



    my $response = $self->http_request($method, $self->{_next_url}); 



    $self->{response} = $response;



    if (!$response->is_success) {

	#warn $response->as_string();

	warn " --- HTTP request failed: ", $response->as_string, "\n" if ($debug);

	return (undef);

    };



    my $results = $response->content();

    # parse the output

	

    @{$self->{cache}} = (1);

    @{$self->{cache}} = ();

    if (!$results) {

	return(0);

    }

	

    my ($url);

    my (@lines) = $self->split_lines($results);



    my($mstitle, $msurl, $mssize, $mshits, $msdesc);

    ($mstitle, $msurl, $mssize, $mshits, $msdesc) = ('', '', 0, 0, undef);



    while ($#lines > -1) {

	$_ = shift(@lines);



        if ($step == 0) {

	    ($mstitle, $msurl, $mssize, $msdesc) = ('', '', 0, undef);



          if ($_ =~ m/matching the query/) {

            $_ =~ s/[^0-9]//g;

            $mshits = $_;

          }

        }

	if ($step == 0) {

	  if ($_ =~ m/<dt>/) {

	    $step = 1;

	  }

	} elsif ($step == 1) {

	  if ($_ =~ m/<b><a href=/) {

	    $_ =~ s/^.*\">//;

	    $_ =~ s/<\/a>.*$//; 

            $mstitle = $_;

            $step = 2;

          } 

	} elsif ($step == 2) {

	    if ($_ =~ m/Abstract: /) {

		$msdesc = $_;

		$msdesc =~ s/^.*Abstract: //;

		$step = 3;

	    }

	} elsif ($step == 3) {

	    # collect abstract info..

	    if ($_ =~ m/cite/) {

		$step = 4;

	    } else {

		s/\s+/ /;

		$msdesc .= $_;

	    }

	} elsif ($step == 4) {

          if ($_ =~ m/a href=/) {

	    $_ =~ s/^.*\">//;

	    $_ =~ s/<\/a.*$//;

	    $msurl = $_;                 #print url 

	    $step = 5;

	  } 

	} elsif ($step == 5) {

	  if ($_ =~ m/size.*bytes/) {

	    $_ =~ s/^.*- size //;

	    $_ =~ s/ - .*$//;

	    $_ =~ s/,//;

	    $mssize = $_;               #print document size

	    $step = 0;

	    

	    my($hit) = new WWW::SearchResult;

	    # change into an absolute URL

	    my($linkobj) = new URI::URL $msurl, $self->{_next_url};

	    $hit->add_url($linkobj->abs->as_string);

	    $hit->title($mstitle);

	    $hit->size($mssize);

	    $msdesc =~ s,<[A-Za-z/]*?>,,g; #remove tags..

	    $hit->description($msdesc);

	    $hits_found++;

	    $hit->score(800 - (20 * $hits_found));

	    $hit->normalized_score(800 - (20 * $hits_found));

	    push(@{$self->{cache}}, $hit);      

	  } 

	}

	

      }

    if ($mshits) {

      $self->approximate_result_count($mshits);

    } else {

      $self->approximate_result_count($hits_found);

    }

    $self->{_next_url} = undef;

    

    return($hits_found);

  }





1;

