source: trunk/gsdl/src/recpt/queryaction.cpp@ 3176

Last change on this file since 3176 was 3176, checked in by jrm21, 22 years ago

in the "Word count" freqmsg, we now print out terms with digits,
provided there is at least 1 non-digit character in it.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 49.2 KB
RevLine 
[174]1/**********************************************************************
2 *
3 * queryaction.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
[533]6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
[174]9 *
[533]10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
[174]24 *********************************************************************/
25
26#include "queryaction.h"
[275]27#include "querytools.h"
[347]28#include "formattools.h"
[757]29#include "cgiutils.h"
[772]30#include "OIDtools.h"
[928]31//#include "infodbclass.h"
32#include "fileutil.h"
33#include "text_t.h"
34#include "historydb.h"
[1915]35#include "htmlutils.h" // for html_safe in do_action
36#include "gsdltools.h"
[3176]37#include <stdlib.h> // for strtol
[174]38
[757]39void colinfo_t::clear () {
40 formatlistptr = NULL;
41 browserptr = NULL;
42}
43
44void QueryResult_t::clear() {
45 doc.clear();
46 collection.clear();
47}
48
[174]49queryaction::queryaction () {
[403]50
[1270]51 recpt = NULL;
[403]52 num_phrases = 0;
53
[174]54 // this action uses cgi variable "a"
55 cgiarginfo arg_ainfo;
56 arg_ainfo.shortname = "a";
57 arg_ainfo.longname = "action";
58 arg_ainfo.multiplechar = true;
59 arg_ainfo.defaultstatus = cgiarginfo::weak;
60 arg_ainfo.argdefault = "q";
61 arg_ainfo.savedarginfo = cgiarginfo::must;
62 argsinfo.addarginfo (NULL, arg_ainfo);
63
[1915]64 // "ct" - 0 = mg, 1 = mgpp
65 arg_ainfo.shortname = "ct";
66 arg_ainfo.longname = "collection type";
67 arg_ainfo.multiplechar = false;
68 arg_ainfo.defaultstatus = cgiarginfo::weak;
69 arg_ainfo.argdefault = "0";
70 arg_ainfo.savedarginfo = cgiarginfo::must;
71 argsinfo.addarginfo (NULL, arg_ainfo);
72
[470]73 // "b" - 0 = simple, 1 = advanced
74 arg_ainfo.shortname = "b";
75 arg_ainfo.longname = "query mode";
76 arg_ainfo.multiplechar = false;
77 arg_ainfo.defaultstatus = cgiarginfo::weak;
78 arg_ainfo.argdefault = "0";
79 arg_ainfo.savedarginfo = cgiarginfo::must;
80 argsinfo.addarginfo (NULL, arg_ainfo);
81
[174]82 // "h"
83 arg_ainfo.shortname = "h";
84 arg_ainfo.longname = "main index";
85 arg_ainfo.multiplechar = true;
86 arg_ainfo.defaultstatus = cgiarginfo::weak;
87 arg_ainfo.argdefault = "";
[295]88 arg_ainfo.savedarginfo = cgiarginfo::must;
[174]89 argsinfo.addarginfo (NULL, arg_ainfo);
90
[349]91 // "h2"
92 arg_ainfo.shortname = "h2";
93 arg_ainfo.longname = "main index for second query";
94 arg_ainfo.multiplechar = true;
95 arg_ainfo.defaultstatus = cgiarginfo::weak;
96 arg_ainfo.argdefault = "";
97 arg_ainfo.savedarginfo = cgiarginfo::must;
98 argsinfo.addarginfo (NULL, arg_ainfo);
99
[174]100 // "j"
101 arg_ainfo.shortname = "j";
102 arg_ainfo.longname = "sub collection index";
103 arg_ainfo.multiplechar = true;
104 arg_ainfo.defaultstatus = cgiarginfo::weak;
105 arg_ainfo.argdefault = "";
[295]106 arg_ainfo.savedarginfo = cgiarginfo::must;
[174]107 argsinfo.addarginfo (NULL, arg_ainfo);
108
[349]109 // "j2"
110 arg_ainfo.shortname = "j2";
111 arg_ainfo.longname = "sub collection index for second query";
112 arg_ainfo.multiplechar = true;
113 arg_ainfo.defaultstatus = cgiarginfo::weak;
114 arg_ainfo.argdefault = "";
115 arg_ainfo.savedarginfo = cgiarginfo::must;
116 argsinfo.addarginfo (NULL, arg_ainfo);
117
[174]118 // "n"
119 arg_ainfo.shortname = "n";
120 arg_ainfo.longname = "language index";
121 arg_ainfo.multiplechar = true;
122 arg_ainfo.defaultstatus = cgiarginfo::weak;
123 arg_ainfo.argdefault = "";
[295]124 arg_ainfo.savedarginfo = cgiarginfo::must;
[174]125 argsinfo.addarginfo (NULL, arg_ainfo);
126
[349]127 // "n2"
128 arg_ainfo.shortname = "n2";
129 arg_ainfo.longname = "language index for second query";
130 arg_ainfo.multiplechar = true;
131 arg_ainfo.defaultstatus = cgiarginfo::weak;
132 arg_ainfo.argdefault = "";
133 arg_ainfo.savedarginfo = cgiarginfo::must;
134 argsinfo.addarginfo (NULL, arg_ainfo);
135
[1915]136
[174]137 // "q"
138 arg_ainfo.shortname = "q";
139 arg_ainfo.longname = "query string";
140 arg_ainfo.multiplechar = true;
141 arg_ainfo.defaultstatus = cgiarginfo::weak;
142 arg_ainfo.argdefault = "";
143 arg_ainfo.savedarginfo = cgiarginfo::must;
144 argsinfo.addarginfo (NULL, arg_ainfo);
145
[349]146 // "q2"
147 arg_ainfo.shortname = "q2";
148 arg_ainfo.longname = "query string for second query";
149 arg_ainfo.multiplechar = true;
150 arg_ainfo.defaultstatus = cgiarginfo::weak;
151 arg_ainfo.argdefault = "";
152 arg_ainfo.savedarginfo = cgiarginfo::must;
153 argsinfo.addarginfo (NULL, arg_ainfo);
154
[356]155 // "cq2" ""=don't combine, "and", "or", "not"
[349]156 arg_ainfo.shortname = "cq2";
157 arg_ainfo.longname = "combine queries";
158 arg_ainfo.multiplechar = true;
159 arg_ainfo.defaultstatus = cgiarginfo::weak;
160 arg_ainfo.argdefault = "";
161 arg_ainfo.savedarginfo = cgiarginfo::must;
162 argsinfo.addarginfo (NULL, arg_ainfo);
163
[284]164 // "t" - 1 = ranked 0 = boolean
[174]165 arg_ainfo.shortname = "t";
166 arg_ainfo.longname = "search type";
167 arg_ainfo.multiplechar = false;
168 arg_ainfo.defaultstatus = cgiarginfo::weak;
[284]169 arg_ainfo.argdefault = "1";
[174]170 arg_ainfo.savedarginfo = cgiarginfo::must;
171 argsinfo.addarginfo (NULL, arg_ainfo);
172
173 // "k"
174 arg_ainfo.shortname = "k";
175 arg_ainfo.longname = "casefolding";
176 arg_ainfo.multiplechar = false;
177 arg_ainfo.defaultstatus = cgiarginfo::weak;
178 arg_ainfo.argdefault = "1";
179 arg_ainfo.savedarginfo = cgiarginfo::must;
180 argsinfo.addarginfo (NULL, arg_ainfo);
181
182 // "s"
183 arg_ainfo.shortname = "s";
184 arg_ainfo.longname = "stemming";
185 arg_ainfo.multiplechar = false;
186 arg_ainfo.defaultstatus = cgiarginfo::weak;
187 arg_ainfo.argdefault ="0";
188 arg_ainfo.savedarginfo = cgiarginfo::must;
189 argsinfo.addarginfo (NULL, arg_ainfo);
190
191 // "m"
192 arg_ainfo.shortname = "m";
193 arg_ainfo.longname = "maximum number of documents";
194 arg_ainfo.multiplechar = true;
195 arg_ainfo.defaultstatus = cgiarginfo::weak;
196 arg_ainfo.argdefault = "50";
197 arg_ainfo.savedarginfo = cgiarginfo::must;
198 argsinfo.addarginfo (NULL, arg_ainfo);
199
200 // "o"
201 arg_ainfo.shortname = "o";
202 arg_ainfo.longname = "hits per page";
203 arg_ainfo.multiplechar = true;
204 arg_ainfo.defaultstatus = cgiarginfo::weak;
205 arg_ainfo.argdefault = "20";
206 arg_ainfo.savedarginfo = cgiarginfo::must;
207 argsinfo.addarginfo (NULL, arg_ainfo);
208
209 // "r"
210 arg_ainfo.shortname = "r";
211 arg_ainfo.longname = "start results from";
212 arg_ainfo.multiplechar = true;
213 arg_ainfo.defaultstatus = cgiarginfo::weak;
214 arg_ainfo.argdefault = "1";
215 arg_ainfo.savedarginfo = cgiarginfo::must;
216 argsinfo.addarginfo (NULL, arg_ainfo);
[757]217
218 // "ccs"
219 arg_ainfo.shortname = "ccs";
220 arg_ainfo.longname = "cross collection searching";
221 arg_ainfo.multiplechar = false;
222 arg_ainfo.defaultstatus = cgiarginfo::weak;
223 arg_ainfo.argdefault = "0";
224 arg_ainfo.savedarginfo = cgiarginfo::must;
225 argsinfo.addarginfo (NULL, arg_ainfo);
226
227 // "ccp"
228 arg_ainfo.shortname = "ccp";
229 arg_ainfo.longname = "cross collection page";
230 arg_ainfo.multiplechar = false;
231 arg_ainfo.defaultstatus = cgiarginfo::weak;
232 arg_ainfo.argdefault = "0";
233 arg_ainfo.savedarginfo = cgiarginfo::must;
234 argsinfo.addarginfo (NULL, arg_ainfo);
235
236 // "cc"
237 arg_ainfo.shortname = "cc";
238 arg_ainfo.longname = "collections to search";
239 arg_ainfo.multiplechar = true;
[776]240 arg_ainfo.multiplevalue = true;
[757]241 arg_ainfo.defaultstatus = cgiarginfo::weak;
242 arg_ainfo.argdefault = "";
243 arg_ainfo.savedarginfo = cgiarginfo::must;
244 argsinfo.addarginfo (NULL, arg_ainfo);
245
[928]246 // "hd" history display - search history only displayed when
[1915]247 // this var set to something other than 0
248 // this number of records is displayed
[928]249 arg_ainfo.shortname = "hd";
250 arg_ainfo.longname = "history display";
[1915]251 arg_ainfo.multiplechar = true;
[936]252 arg_ainfo.multiplevalue = false;
[928]253 arg_ainfo.defaultstatus = cgiarginfo::weak;
254 arg_ainfo.argdefault = "0";
255 arg_ainfo.savedarginfo = cgiarginfo::must;
256 argsinfo.addarginfo (NULL, arg_ainfo);
257
[1915]258 // "hs" save - set to 1 in query form, so only save when submit
[928]259 // query
260 // 0 = no save 1 = save
261 arg_ainfo.shortname = "hs";
262 arg_ainfo.longname = "history save";
263 arg_ainfo.multiplechar = false;
264 arg_ainfo.defaultstatus = cgiarginfo::weak;
265 arg_ainfo.argdefault = "0";
266 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
267 argsinfo.addarginfo (NULL, arg_ainfo);
268
[2745]269 // "g" - new arg for granularity, for mgpp collections
[1328]270 arg_ainfo.shortname = "g";
271 arg_ainfo.longname = "granularity";
272 arg_ainfo.multiplechar = true;
273 arg_ainfo.defaultstatus = cgiarginfo::weak;
274 arg_ainfo.argdefault = "Document";
275 arg_ainfo.savedarginfo = cgiarginfo::must;
276 argsinfo.addarginfo (NULL, arg_ainfo);
[928]277
[1915]278 // "ds" - start date
[1373]279 arg_ainfo.shortname = "ds";
280 arg_ainfo.longname = "start date";
281 arg_ainfo.multiplechar = true;
282 arg_ainfo.defaultstatus = cgiarginfo::weak;
283 arg_ainfo.argdefault = "";
284 arg_ainfo.savedarginfo = cgiarginfo::must;
285 argsinfo.addarginfo (NULL, arg_ainfo);
[1328]286
[1373]287 // "de" - end date
288 arg_ainfo.shortname = "de";
289 arg_ainfo.longname = "end date";
290 arg_ainfo.multiplechar = true;
291 arg_ainfo.defaultstatus = cgiarginfo::weak;
292 arg_ainfo.argdefault = "";
293 arg_ainfo.savedarginfo = cgiarginfo::must;
294 argsinfo.addarginfo (NULL, arg_ainfo);
[1328]295
[1373]296 // "dsbc" - whether or not start date is prechristian
297 arg_ainfo.shortname = "dsbc";
298 arg_ainfo.longname = "start date bc";
299 arg_ainfo.multiplechar = false;
300 arg_ainfo.defaultstatus = cgiarginfo::weak;
301 arg_ainfo.argdefault = "0";
302 arg_ainfo.savedarginfo = cgiarginfo::must;
303 argsinfo.addarginfo (NULL, arg_ainfo);
304
305 // "debc" - whether or not end date is prechristian
306 arg_ainfo.shortname = "debc";
307 arg_ainfo.longname = "end date bc";
308 arg_ainfo.multiplechar = false;
309 arg_ainfo.defaultstatus = cgiarginfo::weak;
310 arg_ainfo.argdefault = "0";
311 arg_ainfo.savedarginfo = cgiarginfo::must;
312 argsinfo.addarginfo (NULL, arg_ainfo);
313
[1915]314 // "qt" - 0 = text, 1 = form
315 arg_ainfo.shortname = "qt";
316 arg_ainfo.longname = "query type";
317 arg_ainfo.multiplechar = false;
318 arg_ainfo.defaultstatus = cgiarginfo::weak;
319 arg_ainfo.argdefault = "0";
320 arg_ainfo.savedarginfo = cgiarginfo::must;
321 argsinfo.addarginfo (NULL, arg_ainfo);
322
323 // "qb" - 0 = regular, 1 = large
324 arg_ainfo.shortname = "qb";
325 arg_ainfo.longname = "query box type";
326 arg_ainfo.multiplechar = false;
327 arg_ainfo.defaultstatus = cgiarginfo::weak;
328 arg_ainfo.argdefault = "0";
329 arg_ainfo.savedarginfo = cgiarginfo::must;
330 argsinfo.addarginfo (NULL, arg_ainfo);
331
332 // "fqn" - number of fields in the query form
333 arg_ainfo.shortname = "fqn";
334 arg_ainfo.longname = "form query num fields";
335 arg_ainfo.multiplechar = true;
336 arg_ainfo.defaultstatus = cgiarginfo::weak;
337 arg_ainfo.argdefault = "4";
338 arg_ainfo.savedarginfo = cgiarginfo::must;
339 argsinfo.addarginfo (NULL, arg_ainfo);
340
341 // "fqf" - the list of field names in the form query
342 // - a comma separated list
343 arg_ainfo.shortname = "fqf";
344 arg_ainfo.longname = "form query fields";
345 arg_ainfo.multiplechar = true;
346 arg_ainfo.defaultstatus = cgiarginfo::weak;
347 arg_ainfo.argdefault = "";
[3145]348 arg_ainfo.savedarginfo = cgiarginfo::must;
[1915]349 argsinfo.addarginfo (NULL, arg_ainfo);
350
351 // "fqv" - the list of values in the form query
352 // - a comma separated list
353 arg_ainfo.shortname = "fqv";
354 arg_ainfo.longname = "form query values";
355 arg_ainfo.multiplechar = true;
356 arg_ainfo.defaultstatus = cgiarginfo::weak;
357 arg_ainfo.argdefault = "";
[3145]358 arg_ainfo.savedarginfo = cgiarginfo::must;
[1915]359 argsinfo.addarginfo (NULL, arg_ainfo);
360
361
362 // "fqs" - the list of stemming options in the form query
363 // - a comma separated list
364 arg_ainfo.shortname = "fqs";
365 arg_ainfo.longname = "form query stems";
366 arg_ainfo.multiplechar = true;
367 arg_ainfo.defaultstatus = cgiarginfo::weak;
368 arg_ainfo.argdefault = "";
[3145]369 arg_ainfo.savedarginfo = cgiarginfo::must;
[1915]370 argsinfo.addarginfo (NULL, arg_ainfo);
371
372
373 // "fqk" - the list of casefolding options in the form query
374 // - a comma separated list
375 arg_ainfo.shortname = "fqk";
376 arg_ainfo.longname = "form query casefolds";
377 arg_ainfo.multiplechar = true;
378 arg_ainfo.defaultstatus = cgiarginfo::weak;
379 arg_ainfo.argdefault = "";
[3145]380 arg_ainfo.savedarginfo = cgiarginfo::must;
[1915]381 argsinfo.addarginfo (NULL, arg_ainfo);
382
383 // "fqc" - the list of boolean operators in the form query
384 // - a comma separated list
385 arg_ainfo.shortname = "fqc";
386 arg_ainfo.longname = "form query combines";
387 arg_ainfo.multiplechar = true;
388 arg_ainfo.defaultstatus = cgiarginfo::weak;
389 arg_ainfo.argdefault = "";
[3145]390 arg_ainfo.savedarginfo = cgiarginfo::must;
[1915]391 argsinfo.addarginfo (NULL, arg_ainfo);
392
393 // "fqa" - form query advanced - for "run query"
394 arg_ainfo.shortname = "fqa";
395 arg_ainfo.longname = "form query advanced query";
396 arg_ainfo.multiplechar = false;
397 arg_ainfo.defaultstatus = cgiarginfo::weak;
398 arg_ainfo.argdefault = "0";
[3145]399 arg_ainfo.savedarginfo = cgiarginfo::must;
[1915]400 argsinfo.addarginfo (NULL, arg_ainfo);
401
[174]402}
403
404void queryaction::configure (const text_t &key, const text_tarray &cfgline) {
405 action::configure (key, cfgline);
406}
407
408bool queryaction::init (ostream &logout) {
409 return action::init (logout);
410}
411
[275]412bool queryaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
413 ostream &logout) {
414
[174]415 // check t argument
[275]416 int arg_t = args.getintarg("t");
417 if (arg_t != 0 && arg_t != 1) {
418 logout << "Warning: \"t\" argument out of range (" << arg_t << ")\n";
[284]419 cgiarginfo *tinfo = argsinfo.getarginfo ("t");
420 if (tinfo != NULL) args["t"] = tinfo->argdefault;
[275]421 }
[174]422
423 // check k argument
[275]424 int arg_k = args.getintarg("k");
425 if (arg_k != 0 && arg_k != 1) {
426 logout << "Warning: \"k\" argument out of range (" << arg_k << ")\n";
[284]427 cgiarginfo *kinfo = argsinfo.getarginfo ("k");
428 if (kinfo != NULL) args["k"] = kinfo->argdefault;
[275]429 }
[174]430
431 // check s argument
[275]432 int arg_s = args.getintarg("s");
433 if (arg_s != 0 && arg_s != 1) {
434 logout << "Warning: \"s\" argument out of range (" << arg_s << ")\n";
[284]435 cgiarginfo *sinfo = argsinfo.getarginfo ("s");
436 if (sinfo != NULL) args["s"] = sinfo->argdefault;
[275]437 }
[174]438
439 // check m argument
[275]440 int arg_m = args.getintarg("m");
[608]441 if (arg_m < -1) {
442 logout << "Warning: \"m\" argument less than -1 (" << arg_m << ")\n";
[284]443 cgiarginfo *minfo = argsinfo.getarginfo ("m");
444 if (minfo != NULL) args["m"] = minfo->argdefault;
[275]445 }
[174]446
447 // check o argument
[275]448 int arg_o = args.getintarg("o");
[622]449 if (arg_o < -1) {
450 logout << "Warning: \"o\" argument less than -1 (" << arg_o << ")\n";
[284]451 cgiarginfo *oinfo = argsinfo.getarginfo ("o");
452 if (oinfo != NULL) args["o"] = oinfo->argdefault;
[275]453 }
[174]454
455 // check r argument
[275]456 int arg_r = args.getintarg("r");
457 if (arg_r < 1) {
458 logout << "Warning: \"r\" argument less than 1 (" << arg_r << ")\n";
[284]459 cgiarginfo *rinfo = argsinfo.getarginfo ("r");
460 if (rinfo != NULL) args["r"] = rinfo->argdefault;
[275]461 }
[928]462 //check hd argument
[1915]463 int arg_hd = args.getintarg("hd");
464 if (arg_hd <0 ) {
465 logout << "Warning: \"hd\" argument less than 0 (" << arg_hd << ")\n";
466 cgiarginfo *hdinfo = argsinfo.getarginfo ("hd");
467 if (hdinfo != NULL) args["hd"] = hdinfo->argdefault;
468 }
469
[928]470 //check hs argument
471 int arg_hs = args.getintarg("hs");
472 if (arg_hs !=0 && arg_hs !=1) {
473 logout << "Warning: \"hs\" argument out of range (" << arg_hs << ")\n";
474 cgiarginfo *hsinfo = argsinfo.getarginfo ("hs");
475 if (hsinfo != NULL) args["hs"] = hsinfo->argdefault;
476 }
[174]477
[1915]478 // check ct argument
479 int arg_ct = args.getintarg("ct");
480 if (arg_ct !=0 && arg_ct !=1) {
481 logout << "Warning: \"ct\" argument out of range (" << arg_ct << ")\n";
482 cgiarginfo *ctinfo = argsinfo.getarginfo ("ct");
483 if (ctinfo != NULL) args["ct"] = ctinfo->argdefault;
[928]484 }
485
[1915]486 // check qt argument
487 int arg_qt = args.getintarg("qt");
488 if (arg_qt !=0 && arg_qt !=1) {
489 logout << "Warning: \"qt\" argument out of range (" << arg_qt << ")\n";
490 cgiarginfo *qtinfo = argsinfo.getarginfo ("qt");
491 if (qtinfo != NULL) args["qt"] = qtinfo->argdefault;
492 }
493
494 // check qb argument
495 int arg_qb = args.getintarg("qb");
496 if (arg_qb !=0 && arg_qb !=1) {
497 logout << "Warning: \"qb\" argument out of range (" << arg_qb << ")\n";
498 cgiarginfo *qbinfo = argsinfo.getarginfo ("qb");
499 if (qbinfo != NULL) args["qb"] = qbinfo->argdefault;
500 }
501
502 // check fqa argument
503 int arg_fqa = args.getintarg("fqa");
504 if (arg_fqa !=0 && arg_fqa !=1) {
505 logout << "Warning: \"fqa\" argument out of range (" << arg_fqa << ")\n";
506 cgiarginfo *fqainfo = argsinfo.getarginfo ("fqa");
507 if (fqainfo != NULL) args["fqa"] = fqainfo->argdefault;
508 }
509
510 // check fqn argument
511 int arg_fqn = args.getintarg("fqn");
512 if (arg_fqn < -1) {
513 logout << "Warning: \"fqn\" argument less than -1 (" << arg_fqn << ")\n";
514 cgiarginfo *fqninfo = argsinfo.getarginfo ("fqn");
515 if (fqninfo != NULL) args["fqn"] = fqninfo->argdefault;
516 }
517
[174]518 return true;
519}
520
[757]521void queryaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
522 response_t &response, text_t &response_data,
523 ostream &/*logout*/) {
[174]524 response = content;
525 response_data = "text/html";
526}
527
[757]528void queryaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
[1915]529 recptprotolistclass * protos,
530 ostream &logout) {
[275]531
[403]532 // define_internal_macros sets the following macros:
[275]533
[397]534 // _quotedquery_ the part of the query string that was quoted for post-processing
535
536
537
538 // The following macros are set later (in define_query_macros) as they can't be set until
539 // the query has been done.
540
[275]541 // _freqmsg_ the term frequency string
542
543 // _resultline_ the "x documents matched the query" string
544
545 // _prevfirst_ these are used when setting up the links to previous/next
546 // _prevlast_ pages of results (_thisfirst_ and _thislast_ are used to set
547 // _nextfirst_ the 'results x-x for query: xxxx' string in the title bar)
548 // _nextlast_
549 // _thisfirst_
550 // _thislast_
[397]551
[3152]552 if (args["ct"]==0) { // mg queries only, not mgpp
553 // get the quoted bits of the query string and set _quotedquery_
554 text_tarray phrases;
555 get_phrases (args["q"], phrases);
556 num_phrases = phrases.size();
557 text_tarray::const_iterator phere = phrases.begin();
558 text_tarray::const_iterator pend = phrases.end();
559 bool first = true;
560 text_t quotedquery;
561 while (phere != pend) {
562 if (!first)
563 if ((phere +1) == pend) quotedquery += " and ";
564 else quotedquery += ", ";
565
566 quotedquery += "\"" + *phere + "\"";
567 first = false;
568 phere ++;
569 }
570 if (args.getintarg("s") && !quotedquery.empty()) quotedquery += "_textstemon_";
571 disp.setmacro ("quotedquery", "query", quotedquery);
[403]572 }
[1915]573
574 define_form_macros(disp, args, protos, logout);
[2769]575
576 define_query_interface(disp, args, protos, logout);
577
[174]578}
579
[2769]580void queryaction::define_query_interface(displayclass &disp,
581 cgiargsclass &args,
582 recptprotolistclass * protos,
583 ostream &logout){
584 text_t collection = args["c"];
585
586 //check that the protocol is alive
587 recptproto* colproto = protos->getrecptproto (collection, logout);
588 if(colproto == NULL) {
589 logout << "ERROR: Null collection protocol trying to query"
590 << collection.getcstr() << "\n";
591 return;
592 }
593
594 //check the collection is responding/in place
595 ColInfoResponse_t *colinfo = recpt->get_collectinfo_ptr(colproto, collection,
596 logout);
597 if(colinfo == NULL){
598 logout << "ERROR: Null returned for get_collectinfo_ptr on "
599 << collection.getcstr() << "in queryaction::define_query_interface\n";
600 return;
601 }
602
603
604 text_tmap::iterator check = colinfo->format.find("QueryInterface");
605 if(check != colinfo->format.end()){
606 if((*check).second=="DateSearch"){
607 text_t current = "_basicqueryform_ _datesearch_";
[2776]608
[2769]609 disp.setmacro("queryformcontent","query",current);
610 }
611 }
612}
613
614
[275]615// sets the selection box macros _hselection_, _jselection_, and _nselection_.
616void queryaction::set_option_macro (const text_t &macroname, text_t current_value,
617 const FilterOption_t &option, displayclass &disp) {
618
[634]619 if (option.validValues.empty()) return;
620 else if (option.validValues.size() == 1) {
621 disp.setmacro (macroname + "selection", "Global", "_" + option.defaultValue + "_");
622 return;
623 }
[275]624 if (option.validValues.size() < 2) return;
[634]625
[275]626 text_t macrovalue = "<select name=\"" + macroname + "\">\n";
[634]627
[275]628 if (current_value.empty()) current_value = option.defaultValue;
[634]629
[275]630 text_tarray::const_iterator thisvalue = option.validValues.begin();
631 text_tarray::const_iterator endvalue = option.validValues.end();
632
633 while (thisvalue != endvalue) {
634 macrovalue += "<option value=\"" + *thisvalue + "\"";
635 if (*thisvalue == current_value)
636 macrovalue += " selected";
[457]637 macrovalue += ">_" + *thisvalue + "_\n";
[275]638 thisvalue ++;
639 }
640 macrovalue += "</select>\n";
641 disp.setmacro (macroname + "selection", "Global", macrovalue);
[174]642}
643
[1915]644// sets the selection box macro _fqfselection_.
645void queryaction::set_fqfselection_macro (const FilterOption_t &option,
646 displayclass &disp) {
647
648 if (option.validValues.empty()) return;
649 text_t macrovalue = "";
650
[2745]651 if (option.validValues.size() == 1) {
652 macrovalue = "_ZZ_";
653 }
654 else {
655 macrovalue += "<select name=\"fqf\" onChange=\"updatefqf();\">\n";
656
657 text_tarray::const_iterator thisvalue = option.validValues.begin();
658 text_tarray::const_iterator endvalue = option.validValues.end();
659
[3159]660 /* All fields should come first, then there may be a TextOnly field.
661 put a blank entry after these two.
662 */
663 assert (*thisvalue == "ZZ"); // Compulsory All fields
664 macrovalue += "<option value=\"" + *thisvalue + "\">_";
665 macrovalue += *thisvalue + "_\n";
666 thisvalue ++;
667
668 if (*thisvalue == "TX") { // Optional TextOnly
669 macrovalue += "<option value=\"" + *thisvalue + "\">_";
670 macrovalue += *thisvalue + "_\n";
671 thisvalue ++;
672 }
673 if (thisvalue != endvalue) {
674 // add the balnk line here
675 macrovalue += "<option>---\n";
676 }
[2745]677 while (thisvalue != endvalue) {
678 macrovalue += "<option value=\"" + *thisvalue + "\">_";
679 macrovalue += *thisvalue + "_\n";
680 thisvalue ++;
681 }
682 macrovalue += "</select>\n";
683 }
684 disp.setmacro ("fqfselection", "query", macrovalue);
685
686}
687// sets the selection box macros _gselection_.
688void queryaction::set_gselection_macro (text_t current_value,
689 const FilterOption_t &option,
690 displayclass &disp) {
[1915]691
[2745]692 if (option.validValues.size() <= 1) {
693 return;
694 }
695
696 text_t macrovalue = "<select name=\"g\">\n";
697
698 if (current_value.empty()) current_value = option.defaultValue;
699
[1915]700 text_tarray::const_iterator thisvalue = option.validValues.begin();
701 text_tarray::const_iterator endvalue = option.validValues.end();
702
703 while (thisvalue != endvalue) {
[2745]704 macrovalue += "<option value=\"" + *thisvalue + "\"";
705 if (*thisvalue == current_value)
706 macrovalue += " selected";
707 macrovalue += ">_" + *thisvalue + "_\n";
[1915]708 thisvalue ++;
709 }
710 macrovalue += "</select>\n";
[2745]711 disp.setmacro ("gselection", "Global", macrovalue);
[1915]712}
713
[757]714void queryaction::define_external_macros (displayclass &disp, cgiargsclass &args,
715 recptprotolistclass *protos, ostream &logout) {
[275]716
717 // define_external_macros sets the following macros:
718
719 // some or all of these may not be required to be set
[356]720 // _hselection_, _h2selection_ the selection box for the main part of the index
721 // _jselection_, _j2selection_ the selection box for the subcollection part of the index
722 // _nselection_, _n2selection_ the selection box for the language part of the index
723 // _cq2selection the selection box for combining two queries
[275]724
[928]725
[275]726 // can't do anything if collectproto is null (i.e. no collection was specified)
[757]727 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
[275]728 if (collectproto == NULL) return;
729
730 comerror_t err;
731 InfoFilterOptionsResponse_t response;
732 InfoFilterOptionsRequest_t request;
733 request.filterName = "QueryFilter";
734
735 collectproto->get_filteroptions (args["c"], request, response, err, logout);
736 if (err == noError) {
[356]737
[275]738 FilterOption_tmap::const_iterator it;
739 FilterOption_tmap::const_iterator end = response.filterOptions.end();
[356]740
741 // _hselection_ and _h2selection_ (Index)
[275]742 it = response.filterOptions.find ("Index");
[356]743 if (it != end) set_option_macro ("h", args["h"], (*it).second, disp);
744 if (it != end) set_option_macro ("h2", args["h2"], (*it).second, disp);
745
746 // _jselection_ and _j2selection_ (Subcollection)
[275]747 it = response.filterOptions.find ("Subcollection");
[356]748 if (it != end) set_option_macro ("j", args["j"], (*it).second, disp);
749 if (it != end) set_option_macro ("j2", args["j2"], (*it).second, disp);
750
751 // _nselection_ and _n2selection_ (Language)
752 it = response.filterOptions.find ("Language");
753 if (it != end) set_option_macro ("n", args["n"], (*it).second, disp);
754 if (it != end) set_option_macro ("n2", args["n2"], (*it).second, disp);
[275]755
[356]756 // _cq2selection_ (CombineQuery)
757 it = response.filterOptions.find ("CombineQuery");
758 if (it != end) set_option_macro ("cq2", args["cq2"], (*it).second, disp);
[928]759
[1328]760 // _gselection_ (Level) // for mgpp collections
761 it = response.filterOptions.find("Level");
[2745]762 if (it!=end) set_gselection_macro(args["g"], (*it).second, disp);
[1328]763
[1915]764 // should probably go into define_internal_macros
765 // _fqfselection_
766 it = response.filterOptions.find("IndexField");
767 if (it!=end) {
768 set_fqfselection_macro((*it).second, disp);
769 }
[275]770 }
[928]771} // define external macros
772
[1915]773void queryaction::define_form_macros (displayclass &disp, cgiargsclass &args,
774 recptprotolistclass *protos, ostream &logout) {
775
776 // defines the following macros
777 // _regformlist_
778 // _advformlist_
779
780 if (args["ct"]!="1" || args["qt"]!="1")
781 return; // dont need these macros
782
783 // mgpp & form query only needs the macros defined
784 text_t form = "";
785 int argfqn = args.getintarg("fqn");
786
787 if (args["b"] == "1") { // advanced form
788 form += "<tr>_firstadvformelement_</tr>\n";
789 for (int i=1; i<argfqn; i++) {
790 form += "<tr>_advformelement_</tr>\n";
791 }
792 disp.setmacro("advformlist", "query", form);
793 }
794 else { // simple form
795 for (int i=0; i<argfqn; i++) {
796 form += "<tr>_regformelement_</tr>\n";
797 }
798 disp.setmacro("regformlist", "query", form);
799 }
800
801}
802
[936]803void queryaction::define_history_macros (displayclass &disp, cgiargsclass &args,
804 recptprotolistclass *protos, ostream &logout) {
[928]805
806 // defines the following macros
807
808 // _searchhistorylist_
809
810 text_t historylist;
811 int arghd = args.getintarg("hd");
[1915]812 if (arghd == 0) {
[928]813 historylist="";
814 }
815 else {
816 historylist = "<!-- Search History List -->\n";
817
818 text_t userid = args["z"];
819 text_tarray entries;
[2212]820 if (get_history_info (userid, entries, gdbmhome, logout)) {
[928]821 int count = 1;
822 text_tarray::iterator here = entries.begin();
823 text_tarray::iterator end = entries.end();
[1915]824 int numrecords=(int)entries.size();
825 if (numrecords>arghd) { // only display some of them
826 numrecords = arghd;
[928]827 }
[1915]828 historylist += "<form name=\"HistoryForm\"><table width=537>\n";
[928]829
[1915]830 for (int i=0; i<numrecords;i++) {
[928]831 text_t query;
832 text_t numdocs;
833 text_t cgiargs;
[1915]834 text_t userinfo;
835 text_t escquery;
836 split_saved_query(entries[i],numdocs,cgiargs);
[936]837 parse_saved_args(cgiargs, "q", query); // get query string out
[928]838 decode_cgi_arg(query); // un cgisafe it
[2745]839 escquery = escape_quotes(query); // escape the quotes and newlines
[1915]840 text_t histvalue = "histvalue";
841 histvalue += i;
842 disp.setmacro(histvalue, "query", escquery);
843 format_user_info(cgiargs, userinfo, args, protos, logout);
[928]844
[1915]845 historylist += "<tr><td align=right>_imagehistbutton_(";
846 historylist += i;
847 historylist += ")</td>\n";
848 historylist += "<td><nobr><table border=1 cellspacing=0 ";
849 historylist += "cellpadding=0><tr><td width=365 align=left>"
850 + query
851 + "</td></tr></table></td><td width=110 align=center><small>"
852 + numdocs;
853 if (numdocs == 1) historylist += " _texthresult_";
854 else historylist += " _texthresults_";
855 if (!userinfo.empty()) {
856 historylist += "<br>( "+userinfo+" )</small></td>\n";
857 }
[928]858 }
[1915]859 historylist+="</table></form>\n\n";
[928]860
[1915]861 } // if get history info
[928]862 else {
[936]863 historylist += "_textnohistory_";
[928]864 }
865 historylist += "<p><! ---- end of history list ----->\n";
866 } // else display list
867 disp.setmacro("searchhistorylist", "query", historylist);
868
869} // define history macros
870
871void queryaction::output_ccp (cgiargsclass &args, recptprotolistclass *protos,
872 displayclass &disp, outconvertclass &outconvert,
873 ostream &textout, ostream &logout) {
874
[1270]875 ColInfoResponse_t *cinfo = NULL;
[928]876 comerror_t err;
877 InfoFilterOptionsResponse_t fresponse;
878 InfoFilterOptionsRequest_t frequest;
879 frequest.filterName = "QueryFilter";
880
881 text_t &index = args["h"];
882 text_t &subcollection = args["j"];
883 text_t &language = args["n"];
884
885 text_tset collections;
886 text_t arg_cc = args["cc"];
887 decode_cgi_arg (arg_cc);
888 splitchar (arg_cc.begin(), arg_cc.end(), ',', collections);
889
890 textout << outconvert << disp << "_query:header_\n"
891 << "<center>_navigationbar_</center><br>\n"
892 << "<form name=QueryForm method=get action=\"_gwcgi_\">\n"
893 << "<input type=hidden name=a value=\"q\">\n"
[1860]894 << "<input type=hidden name=site value=\"_cgiargsite_\"\n"
[928]895 << "<input type=hidden name=e value=\"_compressedoptions_\">\n"
896 << "<input type=hidden name=ccp value=\"1\">\n"
897 << "<center><table width=_pagewidth_><tr valign=top>\n"
898 << "<td>Select collections to search for \"" << args["q"]
899 << "\" <i>(index=" << index << " subcollection=" << subcollection
900 << " language=" << language << ")</i></td>\n"
901 << "<td><input type=\"submit\" value=\"_query:textbeginsearch_\"></td>\n"
902 << "</tr></table></center>\n"
903 << "<center><table width=_pagewidth_>\n"
904 << "<tr><td>\n";
905
906 recptprotolistclass::iterator rprotolist_here = protos->begin();
907 recptprotolistclass::iterator rprotolist_end = protos->end();
908 while (rprotolist_here != rprotolist_end) {
909 if ((*rprotolist_here).p != NULL) {
910
911 text_tarray collist;
912 (*rprotolist_here).p->get_collection_list (collist, err, logout);
913 if (err == noError) {
914 text_tarray::iterator collist_here = collist.begin();
915 text_tarray::iterator collist_end = collist.end();
916 while (collist_here != collist_end) {
917
[1270]918 cinfo = recpt->get_collectinfo_ptr ((*rprotolist_here).p, *collist_here, logout);
[928]919 // if (err == noError && cinfo.isPublic && (cinfo.buildDate > 0)) {
[1270]920 if (cinfo != NULL && (cinfo->buildDate > 0)) {
[928]921
922 (*rprotolist_here).p->get_filteroptions (*collist_here, frequest, fresponse, err, logout);
923 if (err == noError) {
924
925 FilterOption_tmap::const_iterator it;
926 FilterOption_tmap::const_iterator end = fresponse.filterOptions.end();
927 if (!index.empty()) {
928 it = fresponse.filterOptions.find ("Index");
929 if (it == end) {collist_here ++; continue;}
930 text_tarray::const_iterator there = (*it).second.validValues.begin();
931 text_tarray::const_iterator tend = (*it).second.validValues.end();
932 while (there != tend) {
933 if (*there == index) break;
934 there ++;
935 }
936 if (there == tend) {collist_here++; continue;}
937 }
938 if (!subcollection.empty()) {
939 it = fresponse.filterOptions.find ("Subcollection");
940 if (it == end) {collist_here++; continue;}
941 text_tarray::const_iterator there = (*it).second.validValues.begin();
942 text_tarray::const_iterator tend = (*it).second.validValues.end();
943 while (there != tend) {
944 if (*there == subcollection) break;
945 there ++;
946 }
947 if (there == tend) {collist_here++; continue;}
948 }
949 if (!language.empty()) {
950 it = fresponse.filterOptions.find ("Language");
951 if (it == end) {collist_here++; continue;}
952 text_tarray::const_iterator there = (*it).second.validValues.begin();
953 text_tarray::const_iterator tend = (*it).second.validValues.end();
954 while (there != tend) {
955 if (*there == language) break;
956 there ++;
957 }
958 if (there == tend) {collist_here++; continue;}
959 }
960
961 // we've got a matching collection
962 textout << "<input type=checkbox";
963
964 text_tset::const_iterator t = collections.find (*collist_here);
965 if (t != collections.end()) textout << " checked";
966
967 textout << outconvert
968 << " name=cc value=\"" << *collist_here << "\">";
969
[1270]970 if (!cinfo->collectionmeta["collectionname"].empty())
971 textout << outconvert << disp << cinfo->collectionmeta["collectionname"];
[928]972 else
973 textout << outconvert << *collist_here;
974
975 textout << "<br>\n";
976
977 }
978 }
979 collist_here ++;
980 }
981 }
982 }
983 rprotolist_here ++;
984 }
985 textout << outconvert << disp
986 << "</td></tr></table></center>\n"
987 << "</form>\n"
988 << "_query:footer_\n";
989
[174]990}
[275]991
[757]992bool queryaction::do_action (cgiargsclass &args, recptprotolistclass *protos,
993 browsermapclass *browsers, displayclass &disp,
[421]994 outconvertclass &outconvert, ostream &textout,
995 ostream &logout) {
[757]996
[1270]997 if (recpt == NULL) {
998 logout << "ERROR (queryaction::do_action): This action does not contain information\n"
999 << " about any receptionists. The method set_receptionist was probably\n"
1000 << " not called from the module which instantiated this action.\n";
1001 return true;
1002 }
1003
1004
[3152]1005
[865]1006 if (args["ccs"] == "1") {
1007 if (!args["cc"].empty()) {
[757]1008 // query the selected collections
[865]1009 text_t::const_iterator b = args["cc"].begin();
1010 text_t::const_iterator e = args["cc"].end();
1011 if (findchar (b, e, ',') != e) {
1012 if (!search_multiple_collections (args, protos, browsers, disp, outconvert,
1013 textout, logout)) return false;
1014 return true;
1015 } else {
1016 if (!search_single_collection (args, args["cc"], protos, browsers, disp,
1017 outconvert, textout, logout)) return false;
1018 return true;
1019 }
1020 }
[337]1021 }
[421]1022
[800]1023 // simply query the current collection
[865]1024 if (!search_single_collection (args, args["c"], protos, browsers, disp,
1025 outconvert, textout, logout)) return false;
[757]1026 return true;
1027}
1028
1029bool queryaction::search_multiple_collections (cgiargsclass &args, recptprotolistclass *protos,
1030 browsermapclass *browsers, displayclass &disp,
1031 outconvertclass &outconvert, ostream &textout,
1032 ostream &logout) {
1033
1034 text_tarray collections;
1035
1036 text_t arg_cc = args["cc"];
1037 decode_cgi_arg (arg_cc);
1038 splitchar (arg_cc.begin(), arg_cc.end(), ',', collections);
1039
1040 if (collections.empty()) {
1041 logout << "queryaction::search_multiple_collections: No collections "
1042 << "set for doing multiple query - will search current collection\n";
1043 textout << outconvert << disp << "_query:textwarningnocollections_\n";
[865]1044 return search_single_collection (args, args["c"], protos, browsers, disp,
[757]1045 outconvert, textout, logout);
[447]1046 }
1047
[757]1048 // queryaction uses "VList" browser to display results,
1049 // a queries clasification is "Search"
1050 text_t browsertype = "VList";
1051 text_t classification = "Search";
[337]1052
[757]1053 QueryResult_tset results;
1054 map<text_t, colinfo_t, lttext_t> colinfomap;
[275]1055
[1270]1056 ColInfoResponse_t *cinfo = NULL;
[1695]1057 recptproto *collectproto = NULL;
[757]1058 comerror_t err;
1059 FilterRequest_t request;
1060 FilterResponse_t response;
1061 request.filterResultOptions = FROID | FRmetadata | FRtermFreq | FRranking;
1062 text_t formattedstring = args["q"];
1063 text_t freqmsg = "_textfreqmsg1_";
1064 int numdocs = 0;
[800]1065 isapprox isApprox = Exact;
[772]1066
[757]1067 format_querystring (formattedstring, args.getintarg("b"));
1068 set_queryfilter_options (request, formattedstring, args);
1069
1070 // need to retrieve maxdocs matches for each collection
1071 // (will eventually want to tidy this up, do so caching etc.)
1072 OptionValue_t option;
1073 option.name = "StartResults";
1074 option.value = "1";
1075 request.filterOptions.push_back (option);
1076
1077 option.name = "EndResults";
1078 option.value = args["m"];
1079 request.filterOptions.push_back (option);
1080
1081 text_tarray::iterator col_here = collections.begin();
1082 text_tarray::iterator col_end = collections.end();
1083
[865]1084 map<text_t, int, lttext_t> termfreqs;
[757]1085 while (col_here != col_end) {
1086
1087 request.fields.erase (request.fields.begin(), request.fields.end());
1088 request.getParents = false;
1089
[1695]1090 collectproto = protos->getrecptproto (*col_here, logout);
[757]1091 if (collectproto == NULL) {
1092 logout << outconvert << "queryaction::search_multiple_collections: " << *col_here
1093 << " collection has a NULL collectproto, ignoring\n";
1094 col_here ++;
1095 continue;
1096 }
[1270]1097 cinfo = recpt->get_collectinfo_ptr (collectproto, *col_here, logout);
1098 if (cinfo == NULL) {
1099 logout << "ERROR (query_action::search_multiple_collections): get_collectinfo_ptr returned NULL\n";
1100 col_here ++;
1101 continue;
1102 }
[757]1103
1104 browserclass *bptr = browsers->getbrowser (browsertype);
1105
1106 // get the formatstring if there is one
1107 text_t formatstring;
1108 if (!get_formatstring (classification, browsertype,
[1270]1109 cinfo->format, formatstring))
[757]1110 formatstring = bptr->get_default_formatstring();
1111
1112 bptr->load_metadata_defaults (request.fields);
1113
[347]1114 format_t *formatlistptr = new format_t();
1115 parse_formatstring (formatstring, formatlistptr, request.fields, request.getParents);
1116
[757]1117 colinfo_t thiscolinfo;
1118 thiscolinfo.formatlistptr = formatlistptr;
1119 thiscolinfo.browserptr = bptr;
1120 colinfomap[*col_here] = thiscolinfo;
1121
[275]1122 // do the query
[757]1123 collectproto->filter (*col_here, request, response, err, logout);
1124 if (err != noError) {
1125 outconvertclass text_t2ascii;
1126 logout << text_t2ascii
1127 << "queryaction::search_multiple_collections: call to QueryFilter failed "
1128 << "for " << *col_here << " collection (" << get_comerror_string (err) << ")\n";
[275]1129 return false;
[757]1130 }
1131
[800]1132 if (isApprox == Exact)
1133 isApprox = response.isApprox;
1134 else if (isApprox == MoreThan)
1135 if (response.isApprox == Approximate)
1136 isApprox = response.isApprox;
1137
[757]1138 TermInfo_tarray::const_iterator this_term = response.termInfo.begin();
1139 TermInfo_tarray::const_iterator end_term = response.termInfo.end();
1140 while (this_term != end_term) {
[865]1141 termfreqs[(*this_term).term] += (*this_term).freq;
1142 if ((col_here+1) == col_end) {
1143 freqmsg += (*this_term).term + ": " + termfreqs[(*this_term).term];
1144 if ((this_term+1) != end_term) freqmsg += ", ";
1145 }
[757]1146 this_term ++;
1147 }
[275]1148
[757]1149 if (response.numDocs > 0) {
1150 numdocs += response.numDocs;
[275]1151
[757]1152 QueryResult_t thisresult;
1153 thisresult.collection = *col_here;
1154 ResultDocInfo_tarray::iterator doc_here = response.docInfo.begin();
1155 ResultDocInfo_tarray::iterator doc_end = response.docInfo.end();
1156 while (doc_here != doc_end) {
1157 thisresult.doc = *doc_here;
1158 results.insert (thisresult);
1159 doc_here ++;
[447]1160 }
[347]1161 }
[757]1162 col_here ++;
1163 }
[347]1164
[800]1165 disp.setmacro ("freqmsg", "query", freqmsg);
[349]1166
[1690]1167 int maxdocs = args.getintarg("m");
1168 int firstdoc = args.getintarg("r");
1169 int hitsperpage = args.getintarg("o");
1170 if (num_phrases > 0) isApprox = Exact;
1171 if (maxdocs == -1) maxdocs = numdocs;
1172 else if (numdocs > maxdocs) {
1173 numdocs = maxdocs;
1174 isApprox = MoreThan;
1175 }
1176 if (hitsperpage == -1) hitsperpage = numdocs;
1177
[800]1178 text_t resline;
1179 if (isApprox == Approximate) resline = "_textapprox_";
1180 else if (isApprox == MoreThan) resline = "_textmorethan_";
1181
1182 if (numdocs == 0) resline = "_textnodocs_";
1183 else if (numdocs == 1) resline += "_text1doc_";
1184 else resline += text_t(numdocs) + " _textlotsdocs_";
1185 disp.setmacro("resultline", "query", resline);
[757]1186
1187 QueryResult_tset::iterator res_here = results.begin();
1188 QueryResult_tset::iterator res_end = results.end();
1189 text_tset metadata; // empty !!
1190 bool getParents = false; // don't care !!
1191 bool use_table;
1192 ResultDocInfo_t thisdoc;
1193 format_t *formatlistptr = NULL;
1194 browserclass *browserptr = NULL;
1195
1196 // set up _thisfirst_ and _thislast_ macros
1197 disp.setmacro ("thisfirst", "query", firstdoc);
1198 int thislast = firstdoc + (hitsperpage - 1);
1199 if (thislast > numdocs) thislast = numdocs;
1200 disp.setmacro ("thislast", "query", thislast);
1201
1202 // set up _prevfirst_ and _prevlast_ macros
1203 if (firstdoc > 1) {
1204 disp.setmacro ("prevlast", "query", firstdoc - 1);
1205 int prevfirst = firstdoc - hitsperpage;
1206 if (prevfirst < 1) prevfirst = 1;
1207 disp.setmacro ("prevfirst", "query", prevfirst);
[275]1208 }
[757]1209
1210 // set up _nextfirst_ and _nextlast_ macros
1211 if (thislast < numdocs) {
1212 disp.setmacro ("nextfirst", "query", thislast + 1);
1213 int nextlast = thislast + hitsperpage;
1214 if (nextlast > numdocs) nextlast = numdocs;
1215 disp.setmacro ("nextlast", "query", nextlast);
1216 }
1217
1218 textout << outconvert << disp << "_query:header_\n"
1219 << "_query:content_";
1220
1221 int count = 1;
1222
1223 // output results
1224 while (res_here != res_end) {
1225 if (count < firstdoc) {count ++; res_here ++; continue;}
1226 if (count > thislast) break;
1227 formatlistptr = colinfomap[(*res_here).collection].formatlistptr;
1228 browserptr = colinfomap[(*res_here).collection].browserptr;
1229 thisdoc = (*res_here).doc;
1230 use_table = is_table_content (formatlistptr);
[1695]1231
1232 collectproto = protos->getrecptproto ((*res_here).collection, logout);
1233 if (collectproto == NULL) {
1234 logout << outconvert << "queryaction::search_multiple_collections: " << (*res_here).collection
1235 << " collection has a NULL collectproto, ignoring results\n";
1236 res_here ++;
1237 continue;
1238 }
1239
[757]1240 browserptr->output_section_group (thisdoc, args, (*res_here).collection, 0,
1241 formatlistptr, use_table, metadata, getParents,
1242 collectproto, disp, outconvert, textout, logout);
1243 // textout << outconvert << "(ranking: " << (*res_here).doc.ranking << ")\n";
1244 res_here ++;
1245 count ++;
1246 }
1247
1248 textout << outconvert << disp << "_query:footer_";
[349]1249
[757]1250 // clean up the format_t pointers
1251 map<text_t, colinfo_t, lttext_t>::iterator here = colinfomap.begin();
1252 map<text_t, colinfo_t, lttext_t>::iterator end = colinfomap.end();
1253 while (here != end) {
1254 delete ((*here).second.formatlistptr);
1255 here ++;
1256 }
[275]1257 return true;
1258}
[757]1259
[865]1260bool queryaction::search_single_collection (cgiargsclass &args, const text_t &collection,
1261 recptprotolistclass *protos, browsermapclass *browsers,
1262 displayclass &disp, outconvertclass &outconvert,
1263 ostream &textout, ostream &logout) {
[757]1264
[865]1265 recptproto *collectproto = protos->getrecptproto (collection, logout);
[757]1266 if (collectproto == NULL) {
[865]1267 logout << outconvert << "queryaction::search_single_collection: " << collection
[757]1268 << " collection has a NULL collectproto\n";
1269 return false;
1270 }
1271
1272 // queryaction uses "VList" browser to display results,
1273 // a queries clasification is "Search"
1274 text_t browsertype = "VList";
1275 text_t classification = "Search";
1276
1277 comerror_t err;
[1270]1278 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, collection, logout);
1279
1280 if (cinfo == NULL) {
1281 logout << "ERROR (query_action::search_single_collection): get_collectinfo_ptr returned NULL\n";
1282 return false;
1283 }
[757]1284
1285 browserclass *bptr = browsers->getbrowser (browsertype);
1286
1287 // get the formatstring if there is one
1288 text_t formatstring;
1289 if (!get_formatstring (classification, browsertype,
[1270]1290 cinfo->format, formatstring))
[757]1291 formatstring = bptr->get_default_formatstring();
1292
1293 FilterRequest_t request;
1294 FilterResponse_t response;
1295 bptr->set_filter_options (request, args);
1296 bptr->load_metadata_defaults (request.fields);
1297
1298 format_t *formatlistptr = new format_t();
1299 parse_formatstring (formatstring, formatlistptr, request.fields, request.getParents);
1300
1301 // do the query
1302 request.filterResultOptions = FROID | FRmetadata | FRtermFreq;
[1915]1303 text_t formattedstring = "";
1304
1305 if (args["qt"]=="0") { // normal text search
1306 formattedstring = args["q"];
1307 format_querystring (formattedstring, args.getintarg("b"));
1308 add_dates(formattedstring, args.getintarg("ds"), args.getintarg("de"),
1309 args.getintarg("dsbc"), args.getintarg("debc"));
[928]1310 }
[1915]1311 else if (args["qt"]=="1" ){ // form search
[1347]1312
[1915]1313 if (args["b"]=="1" && args["fqa"]=="1") { // explicit query
1314 formattedstring = args["q"];
1315 }
1316 else { // form search
1317 if (args["b"]=="0") { // regular form
1318 parse_reg_query_form(formattedstring, args);
1319 }
1320 else { // advanced form
1321 parse_adv_query_form(formattedstring, args);
1322 }
1323 args["q"] = formattedstring;
1324
[3159]1325 // reset the cgiargfqv macro - need to escape any quotes in it
1326 disp.setmacro("cgiargfqv", "query", escape_quotes(args["fqv"]));
1327
[1915]1328 // also reset the _cgiargq_ macro as it has changed now
1329 disp.setmacro("cgiargq", "Global", html_safe(args["q"]));
1330
1331 // reset the compressed options to include the q arg
1332 text_t compressedoptions = recpt->get_compressed_arg(args, logout);
1333 if (!compressedoptions.empty()) {
1334 disp.setmacro ("compressedoptions", "Global", dm_safe(compressedoptions));
1335 // need a decoded version of compressedoptions for use within forms
1336 // as browsers encode values from forms before sending to server
1337 // (e.g. %25 becomes %2525)
1338 decode_cgi_arg (compressedoptions);
1339 disp.setmacro ("decodedcompressedoptions", "Global", dm_safe(compressedoptions));
1340 }
1341 } // form search
1342 } // args["qt"]=1
1343 else {
1344 logout << "ERROR (query_action::search_single_collection): querytype not defined\n";
[757]1345 return false;
1346 }
[928]1347
[1915]1348 if (!formattedstring.empty()) { // do the query
[3152]1349 // note! formattedstring is in unicode! mg and mgpp must convert!
[1915]1350 set_queryfilter_options (request, formattedstring, args);
1351 collectproto->filter (collection, request, response, err, logout);
1352 if (err != noError) {
1353 outconvertclass text_t2ascii;
1354 logout << text_t2ascii
1355 << "queryaction::search_single_collections: call to QueryFilter failed "
1356 << "for " << collection << " collection (" << get_comerror_string (err) << ")\n";
1357 return false;
1358 }
1359
1360 define_query_macros (args, disp, response);
[757]1361
[1915]1362 // save the query if appropriate
1363 if (!save_search_history(args, response))
1364 logout << "save failed";
1365 }
[928]1366
[936]1367 define_history_macros (disp, args, protos, logout);
[1915]1368
[757]1369 textout << outconvert << disp << "_query:header_\n"
1370 << "_query:content_";
1371
1372 // output the results
1373 bool use_table = is_table_content (formatlistptr);
[865]1374 bptr->output_section_group (response, args, collection, 0, formatlistptr,
[757]1375 use_table, request.fields, request.getParents,
1376 collectproto, disp, outconvert, textout, logout);
1377
1378
1379 textout << outconvert << disp << "_query:footer_";
1380
1381 delete (formatlistptr);
1382
1383 return true;
1384}
1385
[298]1386// define_query_macros sets the macros that couldn't be set until the
[275]1387// query had been done. Those macros are _freqmsg_, _quotedquery_,
1388// _resultline_, _nextfirst_, _nextlast_, _prevfirst_, _prevlast_,
1389// _thisfirst_, and _thislast_
1390void queryaction::define_query_macros (cgiargsclass &args, displayclass &disp,
[397]1391 const FilterResponse_t &response) {
[275]1392 // set up _freqmsg_ and _quotedquery_ macros
1393 text_t freqmsg = "_textfreqmsg1_";
1394 TermInfo_tarray::const_iterator this_term = response.termInfo.begin();
1395 TermInfo_tarray::const_iterator end_term = response.termInfo.end();
1396 while (this_term != end_term) {
[3176]1397 // check that the term doesn't consist completely of digits...
[1373]1398 char *term = (*this_term).term.getcstr();
[3176]1399 char *lastchar;
1400 strtol(term,&lastchar,10);
1401 if(*lastchar != '\0'){
[2848]1402 freqmsg += (*this_term).term + ": " + (*this_term).freq;
1403 if ((this_term + 1) != end_term)
1404 freqmsg += ", ";
1405 }
[1373]1406 delete term;
[275]1407 this_term ++;
1408 }
[2848]1409 disp.setmacro ("freqmsg", "query", freqmsg);
[275]1410
1411 // set up _resultline_ macro
1412 text_t resline;
[398]1413 int maxdocs = args.getintarg("m");
[400]1414 int numdocs = response.numDocs;
[403]1415 isapprox isApprox = response.isApprox;
[800]1416 if (num_phrases > 0) isApprox = Exact;
[1717]1417 if (maxdocs == -1) maxdocs = numdocs;
1418 else if (numdocs > maxdocs) {
1419 numdocs = maxdocs;
1420 isApprox = MoreThan;
1421 }
[403]1422
1423 if (isApprox == Approximate) resline = "_textapprox_";
1424 else if (isApprox == MoreThan) resline = "_textmorethan_";
[400]1425
[275]1426 if (numdocs == 0) resline = "_textnodocs_";
1427 else if (numdocs == 1) resline += "_text1doc_";
[400]1428 else resline += text_t(numdocs) + " _textlotsdocs_";
[398]1429
[275]1430 disp.setmacro("resultline", "query", resline);
1431
1432 int firstdoc = args.getintarg("r");
1433 int hitsperpage = args.getintarg("o");
[622]1434 if (hitsperpage == -1) hitsperpage = numdocs;
[275]1435
1436 // set up _thisfirst_ and _thislast_ macros
1437 disp.setmacro ("thisfirst", "query", firstdoc);
1438 int thislast = firstdoc + (hitsperpage - 1);
1439 if (thislast > numdocs) thislast = numdocs;
1440 disp.setmacro ("thislast", "query", thislast);
1441
1442 // set up _prevfirst_ and _prevlast_ macros
1443 if (firstdoc > 1) {
1444 disp.setmacro ("prevlast", "query", firstdoc - 1);
1445 int prevfirst = firstdoc - hitsperpage;
1446 if (prevfirst < 1) prevfirst = 1;
1447 disp.setmacro ("prevfirst", "query", prevfirst);
1448 }
1449
1450 // set up _nextfirst_ and _nextlast_ macros
1451 if (thislast < numdocs) {
1452 disp.setmacro ("nextfirst", "query", thislast + 1);
1453 int nextlast = thislast + hitsperpage;
1454 if (nextlast > numdocs) nextlast = numdocs;
1455 disp.setmacro ("nextlast", "query", nextlast);
1456 }
1457}
1458
[928]1459bool queryaction::save_search_history (cgiargsclass &args, const FilterResponse_t &response)
1460{
1461 if (args["q"]=="") return true; // null query, dont save
1462 if (args["hs"]=="0") return true; // only save when submit query
[1915]1463 // displayed
[928]1464 // get userid
1465 text_t userid = args["z"];
[275]1466
[928]1467 // the number of docs goes on the front of the query string
1468 int numdocs= response.numDocs;
1469 text_t query = text_t(numdocs);
1470 if (response.isApprox==MoreThan) { // there were more docs found
1471 query.push_back('+');
1472 }
[1915]1473 query += "c="+args["c"];
[928]1474 query += "&h="+args["h"];
1475 query += "&t="+args["t"];
1476 query += "&b="+args["b"];
1477 query += "&j="+args["j"];
1478 query += "&n="+args["n"];
1479 query += "&s="+args["s"];
1480 query += "&k="+args["k"];
[1915]1481 query += "&g="+args["g"];
1482
[928]1483 text_t qstring = args["q"];
1484 text_t formattedquery =cgi_safe(qstring);
1485 query += "&q="+formattedquery;
1486
[1915]1487 bool display=false;
1488 int hd = args.getintarg("hd");
1489 if (hd > 0) display=true;
[2212]1490 if (set_history_info(userid, query, gdbmhome, display)) return true;
[928]1491 else return false;
1492
1493
1494}
[1373]1495
1496
1497
Note: See TracBrowser for help on using the repository browser.