1 # Perl module for sending queries to Sherlock search servers and parsing answers
3 # (c) 2002 Martin Mares <mj@ucw.cz>
5 # This software may be freely distributed and used according to the terms
6 # of the GNU Lesser General Public License.
8 package Sherlock::Query;
15 sub do_parse_tree($$$$);
20 my $server = shift @_;
33 my $sock = IO::Socket::INET->new(PeerAddr => $q->{SERVER}, Proto => 'tcp')
34 or return "-900 Cannot connect to search server: $!";
35 print $sock $string, "\n";
40 $stat =~ /^[+-]/ or return "-901 Reply parse error";
51 if (!defined $block) {
53 push @{$q->{RAW}}, $block;
96 our $footer_syntax = {
101 my ($q,$string) = @_;
103 # Send the query and gather results
104 my $stat = $q->command($string);
105 my @raw = @{$q->{RAW}};
107 # Split results to header, cards and footer
108 $q->{HEADER} = { RAW => [] };
109 if (@raw) { $q->{HEADER}{RAW} = shift @raw; }
110 elsif (!$stat) { return "-902 Incomplete reply"; }
111 $q->{FOOTER} = { RAW => [] };
112 if (@raw && $raw[@raw-1]->[0] =~ /^\+/) {
113 $q->{FOOTER}{RAW} = pop @raw;
117 push @{$q->{CARDS}}, { RAW => pop @raw };
121 parse_tree($q->{HEADER}, $hdr_syntax);
122 foreach my $c (@{$q->{CARDS}}) {
123 parse_tree($c, $card_syntax);
125 parse_tree($q->{FOOTER}, $footer_syntax);
132 my $syntax = shift @_;
133 do_parse_tree($tree->{RAW}, 0, $tree, $syntax);
136 sub do_parse_tree($$$$) {
139 my $cooked = shift @_;
140 my $syntax = shift @_;
143 $raw->[$i] =~ /^(.)(.*)/;
144 if (!defined($syntax->{$1}) && !defined($syntax->{''})) { return $i; }
145 if (ref $syntax->{$1} eq "ARRAY") {
146 push @{$cooked->{$1}}, $2;
148 } elsif (ref $syntax->{$1} eq "HASH") {
150 push @{$cooked->{$1}}, $block;
151 $i = do_parse_tree($raw, $i, $block, $syntax->{$1});
153 $cooked->{$1} = $2 if !defined($cooked->{$1});
161 my $indent = shift @_;
163 if (ref $a eq "ARRAY") {
164 if (@{$a} == 0) { print "[]\n"; }
167 foreach my $k (@{$a}) {
169 print_tree($k, "$indent\t");
171 print $indent, "]\n";
175 foreach my $k (sort keys %{$a}) {
176 print "$indent\t$k => ";
177 print_tree($a->{$k}, "$indent\t");
179 print $indent, "}\n";
180 } elsif (defined $a) {