#!/usr/bin/perl -w use lib qw(. ./ddc-perl ./DDC-perl); use DDC::Concordance; use JSON; use Encode qw(encode decode); use Getopt::Long qw(:config no_ignore_case); use File::Basename qw(basename dirname); use CGI qw(:standard :cgi-lib); use strict; ##====================================================================== ## Constants & Globals our $prog = basename($0); our $progdir = dirname($0); (our $rcfile = "$progdir/$prog") =~ s/\.perl$/.rc/i; ## $cfg: site configuration & defaults (loaded from $rcfile if available) our $cfg = { ##-- user options server => 'localhost:50250', ##-- ddc server mode => 'json', ##-- ddc query mode (json,html,table,text) corpus => '', start => 1, limit => 10, ##-- client options timeout => 60, encoding=>'utf8', parseMeta=>1, parseContext=>1, keepRaw=>0, fieldNames=>undef, fieldSeparator=>"\x{1f}", tokenSeparator=>"\x{1e}", dropFields => [], expandFields => 1, }; ## @defaults: user-level keys in $cfg with a default value our @defaults = qw(server corpus mode start limit); ##====================================================================== ## Subs: Configuration ## \%cfg = loadConfig($jsonFile) ## \%cfg = loadConfig($jsonFile,\%cfg) sub loadConfig { my ($rcfile,$cfg)=@_; open(RC,"<$rcfile") or die("$prog: open failed for config file '$rcfile': $!"); local $/=undef; my $rcstr = <RC>; close(RC) or die("$prog: close failed for config file '$rcfile': $!"); ##-- remove comments $rcstr =~ s/^\#.*$//mg; ##-- decode my $rcdata = decode_json($rcstr) or die("$prog: could not decode config data from '$rcfile': $!"); ##-- merge (clobber) %$cfg = (%$cfg,%$rcdata); return $cfg; } ##====================================================================== ## MAIN ##-- site configuration $cfg = loadConfig($rcfile,$cfg) if (-r $rcfile); ##-- CGI init charset($cfg->{encoding}); ##-- initialize CGI charset my $vars = {}; if (param()) { $vars = Vars(); } my ($dclient,$content); eval { ##-- get query my $query = $vars->{'q'}; die("$prog: no 'q' (query) parameter specified!") if (($query//'') eq ''); $query = decode($cfg->{encoding},$query) if (defined($cfg->{qencoding})); ##-- defaults $vars->{$_} = $cfg->{$_} foreach (grep {!exists($vars->{$_})} @defaults); ##-- create client my $server = $vars->{server} or die("$prog: no 'server' (ddc server) parameter defined!"); $dclient = DDC::Client::Distributed->new(%$cfg, connect=>{PeerAddr=>$server}, mode=>$vars->{mode}, start=>($vars->{start} > 0 ? ($vars->{start}-1) : 0), limit=>$vars->{limit}, ) or die("$prog: could not create DDC::Client::Distributed: $!"); $dclient->open() or die("$prog: could not connect to DDC server at $server: $!"); ##-- append subcorpus clause to query if requested my @corpora = grep {defined($_) && $_ ne ''} split(/[\s\,\:\+]+/,$vars->{corpus}); $query .= ' :'.join(',',@corpora) if (@corpora); ##-- send query $content = $dclient->queryRaw($query) or die("$prog: query ($query) failed: $!"); }; ##-- check for errors if ($@) { print (header(-status=>500), start_html('Error'), h1('Error'),"\n", pre(escapeHTML($@)), end_html); exit 1; } ##-- dump content my %mode_opts = ( html => {type=>'text/html'}, text => {type=>'text/plain',headers=>{'-Content-Disposition'=>"inline; filename=\"ddc.txt\""}}, table => {type=>'text/plain',headers=>{'-Content-Disposition'=>"inline; filename=\"ddc.tab\""}}, json => {type=>'application/json',headers=>{'-Content-Disposition'=>"inline; filename=\"ddc.json\""}}, ); my $modeh = $mode_opts{$dclient->{mode}}; if ($vars->{raw} || $vars->{debug} || $dclient->{mode} eq 'req') { delete $modeh->{headers}{'-Content-Disposition'}; $modeh->{type} = 'text/plain'; } print header($vars->{debug} ? (-type=>'text/plain') : (-type=>$modeh->{type},%{$modeh->{headers}||{}})), $content;