source: main/trunk/greenstone2/runtime-src/src/recpt/documentaction.cpp@ 27065

Last change on this file since 27065 was 22984, checked in by ak19, 14 years ago
  1. Undoing commit of 22934 where decode_commas was called on stem and fold comma separated list: previously separated due to url-encoding of commas. Now that the problem has been fixed at the source, the decode_commas hack is no longer necessary. 2. Commas in stem and fold are no longer url-encoded because the multiple_value field of the continuously-reused struct arg_ainfo is always set back to the default false after ever being set to true. So it no longer subtly stays at true to affect Greenstone functioning in unforeseen ways (such as suddenly and unnecessarily URL-encoding commas where this is not wanted).
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 56.3 KB
Line 
1/**********************************************************************
2 *
3 * documentaction.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
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.
9 *
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 *
24 *********************************************************************/
25
26#include <string.h>
27
28#include "documentaction.h"
29#include "recptprototools.h"
30#include "OIDtools.h"
31#include "querytools.h"
32#include "unitool.h"
33#include "gsdltools.h"
34#include "highlighttext.h"
35#include "browsetoolsclass.h"
36
37documentaction::documentaction () {
38 recpt = NULL;
39
40 // this action uses cgi variables "a", "d", "cl",
41 // "x", "gc", "gt", "gp", and "hl"
42 cgiarginfo arg_ainfo;
43 arg_ainfo.shortname = "a";
44 arg_ainfo.longname = "action";
45 arg_ainfo.multiplechar = true;
46 arg_ainfo.multiplevalue = false;
47 arg_ainfo.defaultstatus = cgiarginfo::weak;
48 arg_ainfo.argdefault = "p";
49 arg_ainfo.savedarginfo = cgiarginfo::must;
50 argsinfo.addarginfo (NULL, arg_ainfo);
51
52 arg_ainfo.shortname = "d";
53 arg_ainfo.longname = "document OID";
54 arg_ainfo.multiplechar = true;
55 arg_ainfo.multiplevalue = false;
56 arg_ainfo.defaultstatus = cgiarginfo::none;
57 arg_ainfo.argdefault = g_EmptyText;
58 arg_ainfo.savedarginfo = cgiarginfo::can;
59 argsinfo.addarginfo (NULL, arg_ainfo);
60
61 // whether or not a document should be retrieved from the
62 // library or the Web.
63 arg_ainfo.shortname = "il";
64 arg_ainfo.longname = "internal link preference";
65 arg_ainfo.multiplechar = false;
66 arg_ainfo.multiplevalue = false;
67 arg_ainfo.defaultstatus = cgiarginfo::weak;
68 arg_ainfo.argdefault = "l";
69 arg_ainfo.savedarginfo = cgiarginfo::must;
70 argsinfo.addarginfo (NULL, arg_ainfo);
71
72 arg_ainfo.shortname = "cl";
73 arg_ainfo.longname = "classification OID";
74 arg_ainfo.multiplechar = true;
75 arg_ainfo.multiplevalue = false;
76 arg_ainfo.defaultstatus = cgiarginfo::none;
77 arg_ainfo.argdefault = g_EmptyText;
78 arg_ainfo.savedarginfo = cgiarginfo::can;
79 argsinfo.addarginfo (NULL, arg_ainfo);
80
81 // in this action "gc" controls the expand/contract
82 // contents function
83 arg_ainfo.shortname = "gc";
84 arg_ainfo.longname = "expand contents";
85 arg_ainfo.multiplechar = false;
86 arg_ainfo.multiplevalue = false;
87 arg_ainfo.defaultstatus = cgiarginfo::weak;
88 arg_ainfo.argdefault = "0";
89 arg_ainfo.savedarginfo = cgiarginfo::can;
90 argsinfo.addarginfo (NULL, arg_ainfo);
91
92 // in this action "gt" controls the expand/contract
93 // text function 0 = not expanded, 1 = expand unless
94 // there are more than 10 sections containing text,
95 // 2 = expand all
96 arg_ainfo.shortname = "gt";
97 arg_ainfo.longname = "expand text";
98 arg_ainfo.multiplechar = false;
99 arg_ainfo.multiplevalue = false;
100 arg_ainfo.defaultstatus = cgiarginfo::weak;
101 arg_ainfo.argdefault = "0";
102 arg_ainfo.savedarginfo = cgiarginfo::can;
103 argsinfo.addarginfo (NULL, arg_ainfo);
104
105 // in this action "gp" is the "go to page" control
106 // used by the Book type of toc
107 arg_ainfo.shortname = "gp";
108 arg_ainfo.longname = "go to page";
109 arg_ainfo.multiplechar = true;
110 arg_ainfo.multiplevalue = false;
111 arg_ainfo.defaultstatus = cgiarginfo::none;
112 arg_ainfo.argdefault = g_EmptyText;
113 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
114 argsinfo.addarginfo (NULL, arg_ainfo);
115
116 // in this action "hl" is the "highlighting on/
117 // highlighting off control ("hl" == "2" is a
118 // special case that forces phrase highlighting
119 // to be used even if the query string doesn't
120 // appear to be a phrase)
121 arg_ainfo.shortname = "hl";
122 arg_ainfo.longname = "highlighting on/off";
123 arg_ainfo.multiplechar = false;
124 arg_ainfo.multiplevalue = false;
125 arg_ainfo.defaultstatus = cgiarginfo::weak;
126 arg_ainfo.argdefault = "1";
127 arg_ainfo.savedarginfo = cgiarginfo::must;
128 argsinfo.addarginfo (NULL, arg_ainfo);
129
130 // "x" is 0 normally or 1 if page
131 // has been "detached"
132 arg_ainfo.shortname = "x";
133 arg_ainfo.longname = "detached page";
134 arg_ainfo.multiplechar = false;
135 arg_ainfo.multiplevalue = false;
136 arg_ainfo.defaultstatus = cgiarginfo::weak;
137 arg_ainfo.argdefault = "0";
138 arg_ainfo.savedarginfo = cgiarginfo::must;
139 argsinfo.addarginfo (NULL, arg_ainfo);
140
141 // "xx" is 0 normally or 1 if documents should be detached by default
142 arg_ainfo.shortname = "xx";
143 arg_ainfo.longname = "detach all doc pages";
144 arg_ainfo.multiplechar = false;
145 arg_ainfo.multiplevalue = false;
146 arg_ainfo.defaultstatus = cgiarginfo::weak;
147 arg_ainfo.argdefault = "0";
148 arg_ainfo.savedarginfo = cgiarginfo::must;
149 argsinfo.addarginfo (NULL, arg_ainfo);
150
151
152 // f arg is set to 1 if document is to
153 // be displayed in a frame
154 arg_ainfo.shortname = "f";
155 arg_ainfo.longname = "frame";
156 arg_ainfo.multiplechar = false;
157 arg_ainfo.multiplevalue = false;
158 arg_ainfo.defaultstatus = cgiarginfo::weak;
159 arg_ainfo.argdefault = "0";
160 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
161 argsinfo.addarginfo (NULL, arg_ainfo);
162
163 // fc arg is "1" if search bar is to be included (i.e. if "fc" == 1
164 // the httpdocument macro will include "&f=1"
165 arg_ainfo.shortname = "fc";
166 arg_ainfo.longname = "include search bar";
167 arg_ainfo.multiplechar = false;
168 arg_ainfo.multiplevalue = false;
169 arg_ainfo.defaultstatus = cgiarginfo::weak;
170 arg_ainfo.argdefault = "1";
171 arg_ainfo.savedarginfo = cgiarginfo::must;
172 argsinfo.addarginfo (NULL, arg_ainfo);
173
174 //rd is whether a document will be displayed
175 //with a relevant document list
176 arg_ainfo.shortname = "rd";
177 arg_ainfo.longname = "include relevant documents";
178 arg_ainfo.multiplechar = false;
179 arg_ainfo.multiplevalue = false;
180 arg_ainfo.defaultstatus = cgiarginfo::weak;
181 arg_ainfo.argdefault = "0";
182 arg_ainfo.savedarginfo = cgiarginfo::must;
183 argsinfo.addarginfo (NULL, arg_ainfo);
184
185 //dm is the metadata that has been used for the datelist
186 arg_ainfo.shortname = "dm";
187 arg_ainfo.longname = "date metadata";
188 arg_ainfo.multiplechar = true;
189 arg_ainfo.multiplevalue = false;
190 arg_ainfo.defaultstatus = cgiarginfo::weak;
191 arg_ainfo.argdefault = g_EmptyText;
192 arg_ainfo.savedarginfo = cgiarginfo::must;
193 argsinfo.addarginfo (NULL, arg_ainfo);
194
195}
196
197documentaction::~documentaction()
198{
199}
200
201bool documentaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
202 recptprotolistclass *protos, ostream &logout) {
203
204 if(!args["d"].empty())
205 {
206 text_t docTop;
207 get_top(args["d"],docTop);
208
209 recptproto* collectproto = protos->getrecptproto (args["c"], logout);
210 if (collectproto != NULL)
211 {
212 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
213
214 if(cinfo->authenticate == "document")
215 {
216 // both are either commented out or uncomment and are empty
217 if (cinfo->public_documents.empty() && cinfo->private_documents.empty())
218 {
219 //deny everything
220 args["uan"] = "1";
221 args["ug"] = cinfo->auth_group;
222 }
223
224 // both public_documents and private_documents are turned on !
225 else if (!cinfo->public_documents.empty() && !cinfo->private_documents.empty())
226 {
227 //deny everything
228 args["uan"] = "1";
229 args["ug"] = cinfo->auth_group;
230 }
231
232 // if public_documents is set but this document isn't
233 // listed in it we need to authenticate
234 else if ((!cinfo->public_documents.empty()) &&
235 (cinfo->public_documents.find(docTop) == cinfo->public_documents.end()))
236 {
237 args["uan"] = "1";
238 args["ug"] = cinfo->auth_group;
239 }
240
241 // if private_documents is set and this document is
242 // listed in it we need to authenticate
243 else if ((!cinfo->private_documents.empty()) &&
244 (cinfo->private_documents.find(docTop) != cinfo->private_documents.end()))
245 {
246 args["uan"] = "1";
247 args["ug"] = cinfo->auth_group;
248 }
249
250 }
251 }
252 }
253 // check gc argument
254 int arg_gc = args.getintarg("gc");
255 if (arg_gc < 0 || arg_gc > 2) {
256 logout << "Warning: \"gc\" argument out of range (" << arg_gc << ")\n";
257 cgiarginfo *gcinfo = argsinfo.getarginfo ("gc");
258 if (gcinfo != NULL) args["gc"] = gcinfo->argdefault;
259 }
260
261 // check gt argument (may be either 0, 1 or 2)
262 int arg_gt = args.getintarg("gt");
263 if (arg_gt != 0 && arg_gt != 1 && arg_gt != 2) {
264 logout << "Warning: \"gt\" argument out of range (" << arg_gt << ")\n";
265 cgiarginfo *gtinfo = argsinfo.getarginfo ("gt");
266 if (gtinfo != NULL) args["gt"] = gtinfo->argdefault;
267 }
268
269 // check hl argument
270 int arg_hl = args.getintarg("hl");
271 if (arg_hl < 0 || arg_hl > 2) {
272 logout << "Warning: \"hl\" argument out of range (" << arg_hl << ")\n";
273 cgiarginfo *hlinfo = argsinfo.getarginfo ("hl");
274 if (hlinfo != NULL) args["hl"] = hlinfo->argdefault;
275 }
276
277 // check x argument
278 int arg_x = args.getintarg("x");
279 if (arg_x != 0 && arg_x != 1) {
280 logout << "Warning: \"x\" argument out of range (" << arg_x << ")\n";
281 cgiarginfo *xinfo = argsinfo.getarginfo ("x");
282 if (xinfo != NULL) args["x"] = xinfo->argdefault;
283 }
284
285 //checks whether rd arg is valid
286 int arg_rd = args.getintarg("rd");
287 if (arg_rd != 0 && arg_rd != 1) {
288 logout << "Warning: \"rd\" argument out of range (" << arg_rd << ")\n";
289 cgiarginfo *rdinfo = argsinfo.getarginfo ("rd");
290 if (rdinfo != NULL) args["rd"] = rdinfo->argdefault;
291 }
292
293
294 return true;
295}
296
297void documentaction::get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
298 response_t &response,text_t &response_data,
299 ostream &logout) {
300
301 if ((args["il"] == "w") && (!args["d"].empty())) {
302
303 recptproto* collectproto = protos->getrecptproto (args["c"], logout);
304 if (collectproto != NULL) {
305
306 text_tset metadata;
307 FilterResponse_t filt_response;
308 text_t top;
309
310 metadata.insert ("URL");
311
312 // get metadata for parent document
313 get_top (args["d"], top);
314 if (get_info (top, args["c"], args["l"], metadata, false, collectproto, filt_response, logout)) {
315 text_t url = filt_response.docInfo[0].metadata["URL"].values[0];
316
317 response = location;
318 response_data = url;
319 return;
320 } else {
321 // error, no URL
322 logout << "Error: documentaction::get_cgihead_info failed on get_info" << endl;
323 }
324 }
325 }
326 response = content;
327 response_data = "text/html";
328}
329
330// set_widthtspace calculates how wide the spaces in the nav bar should
331// be and sets the appropriate macro
332void documentaction::set_spacemacro (displayclass &disp, FilterResponse_t &response,
333 bool has_search_button) {
334
335 text_t width;
336 int twidth, swidth, iwidth = 0;
337
338 int numc = response.docInfo.size();
339 ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
340 ResultDocInfo_tarray::iterator docend = response.docInfo.end();
341
342 disp.expandstring (displayclass::defaultpackage, "_pagewidth_", width);
343 twidth = width.getint();
344
345 if (has_search_button) {
346 disp.expandstring ("query", "_searchwidth_", width);
347 iwidth += width.getint();
348 } else {
349 numc -= 1;
350 }
351
352 while (dochere != docend) {
353 const text_t &title = (*dochere).metadata["Title"].values[0];
354
355 disp.expandstring ("document", "_" + title + "width_", width);
356 if (width == ("_" + title + "width_")) {
357 disp.expandstring ("document", "_defaultwidth_", width);
358 }
359 iwidth += width.getint();
360 ++dochere;
361 }
362
363 if ((twidth - iwidth) < numc) swidth = 2;
364 else {
365 swidth = twidth - iwidth;
366 if (numc > 0) swidth = swidth / numc;
367 }
368 disp.setmacro ("widthtspace", displayclass::defaultpackage, swidth);
369}
370
371// set_navbarmacros sets _navigationbar_ and _httpbrowseXXX_ macros
372// reponse contains 1 metadata field (Title)
373void documentaction::set_navbarmacros (displayclass &disp, FilterResponse_t &response,
374 bool has_search_button, cgiargsclass &args,
375 ColInfoResponse_t &cinfo) {
376
377
378 bool use_pulldown = false;
379 text_tmap::iterator it = cinfo.format.find("NavigationBar");
380 if (it != cinfo.format.end()) {
381 if (it->second == "pulldown") {
382 use_pulldown = true;
383 }
384 }
385
386 text_t topparent;
387 text_t &arg_d = args["d"];
388 text_t navigationbar = "<!-- Navigation Bar -->\n";
389
390 get_top (args["cl"], topparent);
391 int numc = response.docInfo.size();
392 ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
393 ResultDocInfo_tarray::iterator docend = response.docInfo.end();
394
395 if (!use_pulldown) {
396 if (has_search_button) {
397 // search uses its own navtab, as it may be suppressed based on other args
398 navigationbar += "_navtabsearch_";
399 if (args["a"] == "q") {
400 navigationbar += "(selected)";
401 }
402 }
403
404 if (has_search_button || numc == 0) navigationbar += "_navbarspacer_";
405
406 bool first = true;
407 while (dochere != docend) {
408 if (!first) navigationbar += "_navbarspacer_";
409
410 text_t title = (*dochere).metadata["Title"].values[0];
411
412 navigationbar += "_navtab_(_httpbrowse"+(*dochere).OID+"_,"+title;
413 // if we are at this classifier
414 if (arg_d.empty() && ((*dochere).OID == topparent)) {
415 // don't link to this classifier as it is the current one
416 navigationbar += ",selected";
417 }
418 navigationbar += ")";
419
420 // set the _httpbrowseCLX_ macro for this classification
421 disp.setmacro ("httpbrowse" + (*dochere).OID, displayclass::defaultpackage, "_httpdocument_&amp;cl=" + (*dochere).OID);
422 ++dochere;
423 first = false;
424 }
425
426 navigationbar += "_dynamicclassifiernavbarentries_";
427 navigationbar += "\n<!-- End of Navigation Bar -->\n";
428
429 } else {
430
431 navigationbar = "<form method=\"get\" name=\"navform\">\n";
432 navigationbar += "<select name=\"navbar\" onChange=\"location.href=";
433 navigationbar += "document.navform.navbar.options[document.navform.navbar.selectedIndex].value\">\n";
434
435 if (args["a"] != "q" && args["cl"].empty()) {
436 navigationbar += "<option value=\"\" selected>_textselectpage_</option>\n";
437 }
438
439 if (has_search_button) {
440 navigationbar += "<option value=\"_httpquery_\"";
441 if (args["a"] == "q") {
442 navigationbar += " selected";
443 }
444 navigationbar += ">_labelSearch_</option>\n";
445 }
446
447 while (dochere != docend) {
448 text_t title = dochere->metadata["Title"].values[0];
449
450 navigationbar += "<option value=\"_httpdocument_&amp;cl=" + dochere->OID + "\"";
451 if (topparent == dochere->OID) {
452 navigationbar += " selected";
453 }
454 navigationbar += ">_navlinktitle_(" + title + ")</option>\n";
455 ++dochere;
456 }
457
458 navigationbar += "</select>\n";
459 navigationbar += "</form>\n";
460 }
461
462 disp.setmacro ("navigationbar", displayclass::defaultpackage, navigationbar);
463}
464
465// define all the macros which might be used by other actions
466// to produce pages.
467void documentaction::define_external_macros (displayclass &disp, cgiargsclass &args,
468 recptprotolistclass *protos, ostream &logout) {
469
470 // define_external_macros sets the following macros:
471
472 // _navigationbar_ this is the navigation bar containing the search button
473 // and any classification buttons - it goes at the top of
474 // most pages. for now we're assuming that there'll always
475 // be a search button - we should probably check that there
476 // is a query action before making this assumption
477
478 // _httpbrowseXXX_ the http macros for each classification (i.e. if there
479 // are Title and Creator classifications _httpbrowseTitle_
480 // and _httpbrowseCreator_ will be set
481
482 // _widthtspace_ the width of the spacers between buttons in navigation
483 // bar
484
485 // _httpdocument_ has '&f=1' added if displaying document inside a frame
486
487 // _gsdltop_ macro to replace _top targets with
488
489 // _httppagehome_ overridden home url if html collections have own homepage
490
491 // _usability_ macros for remote usability reporting: if
492 // _usabinterface_ "format Usability [multi|textonly|stepwise]" is in
493 // _usabilityscript_ collect.cfg
494
495 // _versionnnum_ greenstone version number (hard-coded)
496 // must have a valid collection server to continue
497
498 text_t &collection = args["c"];
499 if (collection.empty()) return;
500 recptproto *collectproto = protos->getrecptproto (collection, logout);
501 if (collectproto == NULL) return;
502
503 if (recpt == NULL) {
504 logout << "ERROR (documentaction::define_external_macros): This action does not contain\n"
505 << " information about any receptionists. The method set_receptionist was\n"
506 << " probably not called from the module which instantiated this action.\n";
507 return;
508 }
509
510 outconvertclass text_t2ascii;
511 comerror_t err;
512 InfoFiltersResponse_t filterinfo;
513 FilterResponse_t response;
514 text_tset metadata;
515
516 // get info on current collection and load up formatinfo
517 // I'd prefer not to do this here as we're getting
518 // collection info every time (and probably also getting
519 // it in other places some of the time) - One day I'll
520 // fix it ... maybe - Stefan.
521 ColInfoResponse_t cinfo;
522
523 collectproto->get_collectinfo (collection, cinfo, err, logout);
524 load_formatinfo (cinfo.format, args.getintarg("gt"));
525 // ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, collection, logout);
526 // if (cinfo == NULL) {
527 // logout << "ERROR (documentaction::define_external_macros): get_collectinfo_ptr returned NULL\n";
528 // return;
529 // }
530 //load_formatinfo (cinfo->format, args.getintarg("gt"));
531
532 if (formatinfo.DocumentUseHTML) {
533
534 // frame stuff
535 if (args["fc"] == "1") {
536 text_t httpdocument;
537 disp.expandstring (displayclass::defaultpackage, "_httpdocument_", httpdocument);
538 httpdocument += "&amp;f=1";
539 disp.setmacro ("httpdocument", displayclass::defaultpackage, httpdocument);
540 disp.setmacro ("gsdltop", displayclass::defaultpackage, "documenttop");
541 formatinfo.DocumentText = "[Text]";
542 }
543 text_tmap::iterator it = cinfo.format.find ("homepage");
544 if (it != cinfo.format.end()) {
545 text_t httppagehome;
546 if (get_link (args, protos, (*it).second, httppagehome, logout))
547 disp.setmacro ("httppagehome", displayclass::defaultpackage, httppagehome);
548 }
549 }
550
551 // don't want navigation bar if page is 'detached'
552 if (!args.getintarg("x")) {
553
554 collectproto->get_filterinfo (collection, filterinfo, err, logout);
555 if (err == noError) {
556 // check that there's a browse filter
557 if (filterinfo.filterNames.find ("BrowseFilter") != filterinfo.filterNames.end()) {
558
559 metadata.insert ("Title");
560 bool getParents = false;
561 get_children ("", collection, args["l"], metadata, getParents, collectproto, response, logout);
562
563 bool has_search_button = true;
564 collectproto->is_searchable(collection, has_search_button, err, logout);
565 if (err != noError) has_search_button = false;
566
567 // calculate width of spacers and set _widthtspace_ macro
568 if (args.getintarg("v") == 0) set_spacemacro (disp, response, has_search_button);
569
570 // set _navigationbar_ macro
571 set_navbarmacros (disp, response, has_search_button, args, cinfo);
572
573 }
574 } else {
575 logout << text_t2ascii
576 << "Error (documentaction::define_external_macros()) in call to get_filterinfo() "
577 << get_comerror_string (err);
578 }
579 }
580
581 // send feedback button and pages
582 text_tmap::iterator usability = cinfo.format.find("Usability");
583 if(usability!=cinfo.format.end()){
584 disp.setmacro("usability",displayclass::defaultpackage,"_usablink_");
585 disp.setmacro("usabinterface",displayclass::defaultpackage,("_usab"+(*usability).second+"_"));
586 disp.setmacro("usabilityscript", displayclass::defaultpackage, "_usabshowscript_");
587 }
588
589 // version num
590 disp.setmacro("versionnum", displayclass::defaultpackage, GSDL_VERSION);
591
592}
593
594bool documentaction::get_link (cgiargsclass &args, recptprotolistclass *protos,
595 const text_t &inlink, text_t &outlink, ostream &logout) {
596
597 FilterResponse_t response;
598 text_tset metadata;
599 metadata.insert ("section");
600
601 // check current collection first
602 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
603
604 if (get_info (inlink, args["c"], args["l"], metadata, false, collectproto, response, logout)) {
605 if (!response.docInfo[0].metadata["section"].values[0].empty()) {
606#ifndef DOCHANDLE
607 outlink = "_httpdocument_&amp;d=" + response.docInfo[0].metadata["section"].values[0];
608#else
609 outlink = "_httpdocumenthandle_("+args["c"]+","+response.docInfo[0].metadata["section"].values[0]+")";
610#endif
611
612 return true;
613 }
614 }
615
616 // check all the other enabled collections
617
618 if (args["ccs"] == "1" && !args["cc"].empty()) {
619 text_tarray collections;
620 splitchar (args["cc"].begin(), args["cc"].end(), ',', collections);
621
622 text_tarray::const_iterator col_here = collections.begin();
623 text_tarray::const_iterator col_end = collections.end();
624
625 while (col_here != col_end) {
626
627 // don't need to check current collection again
628 if (*col_here == args["c"]) {++col_here; continue;}
629
630 collectproto = protos->getrecptproto (*col_here, logout);
631
632 if (get_info (inlink, *col_here, args["l"], metadata, false, collectproto, response, logout)) {
633 if (!response.docInfo[0].metadata["section"].values[0].empty()) {
634#ifndef DOCHANDLE
635 outlink = "_httpdocument_&amp;c=" + *col_here + "&amp;d=" +
636 response.docInfo[0].metadata["section"].values[0];
637#else
638 outlink = "_httpdocumenthandle_("+*col_here+","+response.docInfo[0].metadata["section"].values[0]+")";
639#endif
640
641 return true;
642 }
643 }
644 ++col_here;
645 }
646 }
647 return false;
648}
649
650void documentaction::load_formatinfo (const text_tmap &colformat, int gt) {
651
652 formatinfo.clear();
653 text_tmap::const_iterator format_here = colformat.begin();
654 text_tmap::const_iterator format_end = colformat.end();
655
656 while (format_here != format_end) {
657 if (((*format_here).first == "DocumentImages") &&
658 ((*format_here).second == "true"))
659 formatinfo.DocumentImages = true;
660 else if (((*format_here).first == "DocumentTitles") &&
661 ((*format_here).second == "false"))
662 formatinfo.DocumentTitles = false;
663 else if ((*format_here).first == "DocumentHeading")
664 formatinfo.DocumentHeading = (*format_here).second;
665 else if (((*format_here).first == "DocumentContents") &&
666 ((*format_here).second == "false"))
667 formatinfo.DocumentContents = false;
668 else if (((*format_here).first == "DocumentArrowsBottom") &&
669 ((*format_here).second == "false"))
670 formatinfo.DocumentArrowsBottom = false;
671 else if (((*format_here).first == "DocumentArrowsTop") &&
672 ((*format_here).second == "true"))
673 formatinfo.DocumentArrowsTop = true;
674 else if ((*format_here).first == "DocumentButtons")
675 splitchar ((*format_here).second.begin(), (*format_here).second.end(),
676 '|', formatinfo.DocumentButtons);
677 else if ((*format_here).first == "DocumentText")
678 formatinfo.DocumentText = (*format_here).second;
679 else if ((*format_here).first == "RelatedDocuments")
680 formatinfo.RelatedDocuments = (*format_here).second;
681 else if (((*format_here).first == "DocumentUseHTML") &&
682 ((*format_here).second == "true"))
683 formatinfo.DocumentUseHTML = true;
684 else if (((*format_here).first == "AllowExtendedOptions") &&
685 ((*format_here).second == "true"))
686 formatinfo.AllowExtendedOptions = true;
687 else
688 formatinfo.formatstrings[(*format_here).first] = (*format_here).second;
689
690 ++format_here;
691 }
692
693 // never want arrows when text is expanded
694 if (gt) {
695 formatinfo.DocumentArrowsBottom = false;
696 formatinfo.DocumentArrowsTop = false;
697 }
698}
699
700
701// define all the macros which are related to pages generated
702// by this action. we also load up the formatinfo structure
703// here (it's used in do_action as well as here)
704void documentaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
705 recptprotolistclass *protos, ostream &logout) {
706
707 // define_internal_macros sets the following macros:
708
709 // _pagetitle_ the title to be displayed at the top of the browser window
710
711 // _imagethispage_ the title image to be displayed at top right of page
712
713 // _navarrowsbottom_ this may be overridden to "" when format option
714 // DocumentArrowsBottom is false
715
716 // _navarrowstop_ likewise for DocumentArrowsTop
717
718 // _httpprevarrow_ links to next and previous sections of document - used
719 // _httpnextarrow_ by DocumentArrowsBottom
720
721 // _header_ the header macro is overridden if we're not at a top level
722 // classification to remove the title block
723
724 // _thisOID_ the OID (directory) of the current document - this corresponds
725 // to the assocfilepath metadata element
726
727 // _documentheader_ Custom header info for the specified document
728 // must have a valid collection server to continue
729
730 text_t &collection = args["c"];
731 if (collection.empty()) return;
732 recptproto *collectproto = protos->getrecptproto (collection, logout);
733 if (collectproto == NULL) return;
734
735 text_tset metadata;
736 FilterResponse_t response;
737 text_t &arg_d = args["d"];
738 text_t &arg_cl = args["cl"];
739
740 if (!formatinfo.DocumentArrowsBottom) {
741 disp.setmacro("navarrowsbottom", "document", "");
742 } else if (!formatinfo.DocumentArrowsBottom) {
743 disp.setmacro("navarrowstop", "document", "");
744 }
745
746 if (!arg_d.empty() && (formatinfo.DocumentArrowsBottom || formatinfo.DocumentArrowsTop)) {
747 // set _httpprevarrow_ and _httpnextarrow_
748 set_arrow_macros (args, collectproto, disp, logout);
749 }
750
751 metadata.insert ("Title");
752 metadata.insert ("gs.DocumentHeader");
753 metadata.insert ("DocumentHeader");
754
755 bool fulltoc = false;
756
757 if (args["cl"] != "search") {
758 // see if there's a FullTOC string
759 text_t cl_top, full_toc;
760 get_top (arg_cl, cl_top);
761 if (get_formatstring (cl_top, "FullTOC", formatinfo.formatstrings, full_toc))
762 if (full_toc == "true") fulltoc = true;
763 disp.setmacro("cltop", "document", cl_top);
764 }
765
766 if (!arg_d.empty() && !fulltoc) {
767 // we're at document level
768
769 metadata.insert ("assocfilepath");
770
771 comerror_t err;
772 OptionValue_tarray options;
773 // we need to do the query again for the z3950proto
774 if (collectproto->get_protocol_name(err)=="z3950proto") {
775 OptionValue_t opt;
776 opt.name="Term";opt.value=args["q"];options.push_back(opt);
777 opt.name="QueryType";
778 opt.value=(args.getintarg("t")) ? "ranked" : "boolean";
779 options.push_back(opt);
780 opt.name="Index";opt.value=args["h"];options.push_back(opt);
781 }
782
783 //do not display relation metadata
784 disp.setmacro ("relateddoc", "document", "");
785
786 //if preferences indicate relevant docs should be collected
787 //and there is no particular format specified then display
788 //this default format.
789 if(args["rd"] == "1" && formatinfo.RelatedDocuments.empty()){
790
791 text_t relation = g_EmptyText; //string for displaying relation metadata
792
793 //call function in formattools.cpp which will return the text of the
794 //related documents in a vertical list. This is the default format.
795
796 if (get_info (arg_d, collection, args["l"], metadata, options, false, collectproto, response, logout))
797 relation += get_related_docs(collection, collectproto, response.docInfo[0], logout);
798
799 //set macro to be the related document string
800
801 disp.setmacro ("relateddoc", "document", relation);
802 }
803
804
805 // get metadata for this document and it's parents
806 if (get_info (arg_d, collection, args["l"], metadata, options,
807 true, collectproto, response, logout)) {
808
809 disp.setmacro ("header", "document", "_textheader_");
810 text_tarray pagetitlearray;
811 if (!response.docInfo[0].metadata["Title"].values[0].empty())
812 pagetitlearray.push_back (response.docInfo[0].metadata["Title"].values[0]);
813
814 if (args["gt"] != "1") {
815 MetadataInfo_t *parenttitle = response.docInfo[0].metadata["Title"].parent;
816 while (parenttitle != NULL) {
817 if (!parenttitle->values[0].empty())
818 pagetitlearray.push_back (parenttitle->values[0]);
819 parenttitle = parenttitle->parent;
820 }
821 }
822 reverse (pagetitlearray.begin(), pagetitlearray.end());
823 text_t pagetitle;
824 joinchar (pagetitlearray, ": ", pagetitle);
825 // remove html tags from the title
826 text_t::iterator open_tag=pagetitle.begin();
827 while (open_tag < pagetitle.end()) {
828 if (*open_tag == '<') {
829 text_t::iterator close_tag=open_tag+1;
830 text_t::iterator donechar=pagetitle.end();
831 while (close_tag < donechar) {
832 if (*close_tag == '>')
833 break;
834 ++close_tag;
835 }
836 if (close_tag < donechar) // remove this html tag, replace with space
837 *close_tag=' ';
838 pagetitle.erase(open_tag, close_tag);
839 }
840 ++open_tag;
841 }
842 disp.setmacro ("pagetitle", "document", pagetitle);
843
844 // custom header info
845 text_t custom_header;
846 if (is_top (arg_d)) {
847 custom_header = response.docInfo[0].metadata["gs.DocumentHeader"].values[0];
848 if (custom_header.empty()) {
849 // try ex header
850 custom_header = response.docInfo[0].metadata["DocumentHeader"].values[0];
851 }
852 } else {
853 MetadataInfo_t *parentch = response.docInfo[0].metadata["gs.DocumentHeader"].parent;
854 while (parentch != NULL) {
855 custom_header = parentch->values[0];
856 parentch = parentch->parent;
857 }
858 if (custom_header.empty()) {
859 // try ex header
860 MetadataInfo_t *parentch = response.docInfo[0].metadata["DocumentHeader"].parent;
861 while (parentch != NULL) {
862 custom_header = parentch->values[0];
863 parentch = parentch->parent;
864 }
865 }
866 }
867 if (!custom_header.empty()) {
868 disp.setmacro("documentheader", "document", custom_header);
869 }
870
871 if (is_top (arg_d))
872 disp.setmacro ("thisOID", displayclass::defaultpackage, dm_safe(response.docInfo[0].metadata["assocfilepath"].values[0]));
873 else {
874 MetadataInfo_t *parentad = response.docInfo[0].metadata["assocfilepath"].parent;
875 text_t thisOID;
876 while (parentad != NULL) {
877 thisOID = parentad->values[0];
878 parentad = parentad->parent;
879 }
880 disp.setmacro ("thisOID", displayclass::defaultpackage, dm_safe(thisOID));
881 }
882 }
883 } else {
884 if (!arg_cl.empty()) {
885
886 // create the currentnodevalue macro - this is the value of the node
887 // in the hierarchy that is currently open.
888 if (get_info (arg_cl, collection, args["l"], metadata, false, collectproto, response, logout)) {
889 text_t &title = response.docInfo[0].metadata["Title"].values[0];
890 disp.setmacro ("currentnodevalue", "document", title);
891 }
892 // get metadata for top level classification
893 text_t classtop;
894 get_top (arg_cl, classtop);
895 metadata.insert ("childtype");
896 metadata.insert ("parameters");
897
898 if (get_info (classtop, collection, args["l"], metadata, false, collectproto, response, logout)) {
899
900 text_t &title = response.docInfo[0].metadata["Title"].values[0];
901 bool unknown = false;
902
903 // test if we have macros defined for this classification's
904 // metadata name - if not we'll just display the name
905 text_t tmp;
906 text_t macroname="_label" + title + "_";
907 disp.expandstring ("Global", macroname, tmp);
908 if (tmp == macroname) unknown = true; // it wasn't expanded
909
910 if (unknown) {
911 disp.setmacro ("pagetitle", "document", title);
912 } else {
913 disp.setmacro ("pagetitle", "document", macroname);
914 }
915 /* for ns4/image layout compatibility. when this is no longer
916 * needed, set imagethispage to _label+title+_ */
917 text_t titlemacroname="_titleimage" + title + "_";
918 disp.expandstring ("Global", titlemacroname, tmp);
919 if (tmp == titlemacroname) { /* _titleimage$META_ isn't defined */
920 if (!unknown) /* _label$META_ is defined */
921 disp.setmacro ("imagethispage", "document", macroname);
922 else
923 disp.setmacro ("imagethispage", "document", title);
924 } else { /* _titleimage$META_ is defined */
925 disp.setmacro ("imagethispage", "document", titlemacroname);
926 }
927
928 //if the document is not a document from a collection
929 //we must set the macro to be an empty string
930 disp.setmacro ("relateddoc", "document", "");
931
932 // Add macros specific to the Collage/Phind classifiers
933 text_t &childtype = response.docInfo[0].metadata["childtype"].values[0];
934 if (childtype == "Collage") {
935
936 text_t::iterator a = arg_cl.begin();
937 text_t::iterator b = arg_cl.end();
938
939 bool collage = true;
940 while (a != b) {
941 if (*a == 46) collage = false;
942 ++a;
943 }
944
945 if (collage) {
946 disp.setmacro ("collageclassifier", "document", "_collageapplet_");
947
948 // Next, macros that control the way the classifier is displayed
949 text_t parameters = response.docInfo[0].metadata["parameters"].values[0];
950
951 // extract key=value pairs and set as macros
952 text_t::iterator here = parameters.begin();
953 text_t::iterator end = parameters.end();
954 text_t key, value;
955
956 while (here != end) {
957 // get the next key and value pair
958 here = getdelimitstr (here, end, '=', key);
959 here = getdelimitstr (here, end, ';', value);
960
961 // store this key=value pair
962 if (!key.empty() && !value.empty()) {
963 disp.setmacro ("collage"+key, "document", value);
964 }
965 }
966
967
968 }
969 }
970
971 if (childtype == "Phind") {
972
973 // First, a macro to display the phind classifier
974 disp.setmacro ("phindclassifier", "document", "_phindapplet_");
975
976 // Next, macros that control the way the classifier is displayed
977 text_t parameters = response.docInfo[0].metadata["parameters"].values[0];
978
979 // extract key=value pairs and set as macros
980 text_t::iterator here = parameters.begin();
981 text_t::iterator end = parameters.end();
982 text_t key, value;
983
984 while (here != end) {
985 // get the next key and value pair
986 here = getdelimitstr (here, end, '=', key);
987 here = getdelimitstr (here, end, ';', value);
988
989 // store this key=value pair
990 if (!key.empty() && !value.empty()) {
991 disp.setmacro (key, "document", value);
992 }
993 }
994 } // end if (childtype == "Phind")
995 }
996 } // end if (!arg_cl.empty()) {
997 }
998}
999
1000
1001bool documentaction::do_action(cgiargsclass &args, recptprotolistclass *protos,
1002 browsermapclass *browsers, displayclass &disp,
1003 outconvertclass &outconvert, ostream &textout,
1004 ostream &logout)
1005{
1006 if ((args["book"] == "flashxml") && (!args["d"].empty()))
1007 {
1008 return do_action_flashxml(args,protos,browsers,disp,outconvert,textout,logout);
1009 }
1010 else if ((args["book"] == "on") && (!args["d"].empty()))
1011 {
1012 return do_action_book(args,protos,browsers,disp,outconvert,textout,logout);
1013 }
1014 else
1015 {
1016 return do_action_html(args,protos,browsers,disp,outconvert,textout,logout);
1017 }
1018
1019}
1020
1021//displaying the normal display when bookswitch=0(html)
1022bool documentaction::do_action_html(cgiargsclass &args, recptprotolistclass *protos,
1023 browsermapclass *browsers, displayclass &disp,
1024 outconvertclass &outconvert, ostream &textout,
1025 ostream &logout)
1026{
1027 // must have a valid collection server
1028 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
1029 if (collectproto == NULL) {
1030 logout << "documentaction::do_action called with NULL collectproto\n";
1031 textout << outconvert << disp << "_document:header_\n"
1032 << "Error: Attempt to get document without setting collection\n"
1033 << "_document:footer_\n";
1034 } else {
1035
1036 text_t OID = args["d"];
1037 if (OID.empty()) OID = args["cl"];
1038 if (OID.empty()) {
1039 textout << outconvert << disp << "Document contains no data_document:footer_\n";
1040 return true;
1041 }
1042
1043
1044 if (formatinfo.DocumentUseHTML && !args["d"].empty()) {
1045
1046 if (args["f"] == "1") {
1047 textout << outconvert << disp
1048 << "<html><head></head>\n"
1049 << "<frameset rows=\"68,*\" noresize border=0>\n"
1050 << "<frame scrolling=no frameborder=0 src=\"_gwcgi_?_optsite_e=_compressedoptions_&a=p&p=nav\">\n"
1051#ifndef DOCHANDLE
1052 << "<frame name=\"documenttop\" frameborder=0 src=\"_gwcgi_?_optsite_e=_compressedoptions_&a=d&d="
1053 << args["d"] << "\">"
1054#else
1055 << "<frame name=\"documenttop\" frameborder=0 src=\"_httpdocumenthandle_("
1056 << args["c"] << "," << args["d"] << ")\">"
1057#endif
1058 << "<noframes>\n"
1059 << "<p>You must have a frame enabled browser to view this.</p>\n"
1060 << "</noframes>\n"
1061 << "</frameset>\n"
1062 << "</html>\n";
1063 } else {
1064 output_document (OID, args, collectproto, browsers, disp, outconvert, textout, logout);
1065 }
1066 return true;
1067 }
1068
1069
1070 textout << outconvert << disp << "_document:header_\n"
1071 << "_document:content_\n";
1072
1073 // output the table of contents
1074 browsetoolsclass b;
1075 b.output_toc(args, browsers, formatinfo, collectproto,
1076 disp, outconvert, textout, logout);
1077
1078 if (formatinfo.DocumentArrowsTop && !args["d"].empty()) {
1079 textout << outconvert << disp << "_document:navarrowstop_\n";
1080 }
1081
1082 //output the related documents (may be the empty string)
1083 //will not output the docs if a format string is specified
1084 textout << outconvert << disp << "_document:relateddoc_\n";
1085
1086 // output the document text
1087 if (!args["d"].empty()) {
1088 output_document (OID, args, collectproto, browsers, disp, outconvert, textout, logout);
1089 }
1090
1091 textout << outconvert << disp << "_document:footer_\n";
1092 }
1093 return true;
1094}
1095
1096//displaying the book display when bookswitch=on
1097bool documentaction::do_action_book(cgiargsclass &args, recptprotolistclass *protos,
1098 browsermapclass *browsers, displayclass &disp,
1099 outconvertclass &outconvert, ostream &textout,
1100 ostream &logout)
1101{
1102 // must have a valid collection server
1103 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
1104 if (collectproto == NULL)
1105 {
1106 logout << "documentaction::do_action called with NULL collectproto\n";
1107 textout << outconvert << disp << "_document:header_\n"
1108 << "Error: Attempt to get document without setting collection\n";
1109 }
1110 else
1111 {
1112 text_t OID = args["d"];
1113 if (OID.empty()) OID = args["cl"];
1114 if (OID.empty())
1115 {
1116 textout << outconvert << disp << "Document contains no data\n";
1117 return true;
1118 }
1119
1120 if (formatinfo.DocumentUseHTML && !args["d"].empty())
1121 {
1122 if (args["f"] == "1")
1123 {
1124 textout << outconvert << disp
1125 << "<html><head></head>\n"
1126 << "<frameset rows=\"68,*\" noresize border=0>\n"
1127 << "<frame scrolling=no frameborder=0 src=\"_gwcgi_?_optsite_e=_compressedoptions_&a=p&p=nav\">\n"
1128 #ifndef DOCHANDLE
1129 << "<frame name=\"documenttop\" frameborder=0 src=\"_gwcgi_?_optsite_e=_compressedoptions_&a=d&d="
1130 << args["d"] << "\">"
1131 #else
1132 << "<frame name=\"documenttop\" frameborder=0 src=\"_httpdocumenthandle_("
1133 << args["c"] << "," << args["d"] << ")\">"
1134 #endif
1135 << "<noframes>\n"
1136 << "<p>You must have a frame enabled browser to view this.</p>\n"
1137 << "</noframes>\n"
1138 << "</frameset>\n"
1139 << "</html>\n";
1140 }
1141 else
1142 {
1143 output_document (OID, args, collectproto, browsers, disp, outconvert, textout, logout);
1144 }
1145
1146 return true;
1147 }
1148
1149
1150 //the header bit and the navigation button
1151 textout << outconvert << disp << "_document:header_\n" << "_document:content_\n";
1152
1153 //display the book
1154 textout << outconvert << disp << "_document:flashbook_\n";
1155
1156 //the footer bit without the document arrow
1157 textout << outconvert << disp << "</div> <!-- id=document -->\n";
1158 textout << outconvert << disp << "_endspacer__htmlfooter_\n";
1159 }
1160
1161 return true;
1162}
1163
1164//Displaying the xml when bookswitch=flashxml
1165bool documentaction::do_action_flashxml(cgiargsclass &args, recptprotolistclass *protos,
1166 browsermapclass *browsers, displayclass &disp,
1167 outconvertclass &outconvert, ostream &textout,
1168 ostream &logout)
1169{
1170 // must have a valid collection server
1171 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
1172 if (collectproto == NULL)
1173 {
1174 logout << "documentaction::do_action called with NULL collectproto\n";
1175 textout << outconvert << disp
1176 << "<Message>\n"
1177 << " Error: Attempt to get document without setting collection\n"
1178 << "</Message>\n";
1179 }
1180 else
1181 {
1182 text_t OID = args["d"];
1183 if (OID.empty()) OID = args["cl"];
1184 if (OID.empty())
1185 {
1186 textout << outconvert << disp
1187 << "<Message>\n"
1188 << " Document contains no data\n"
1189 << "</Message>\n";
1190 return true;
1191 }
1192
1193 if (formatinfo.DocumentUseHTML && !args["d"].empty())
1194 {
1195 if (args["f"] == "1")
1196 {
1197 textout << outconvert << disp
1198 << "<Message>\n"
1199 << " Using frames makes no sense for XML output\n"
1200 << "</Message>\n";
1201 }
1202 else
1203 {
1204 output_document_flashxml (OID, args, collectproto, browsers, disp, outconvert, textout, logout);
1205 }
1206
1207 return true;
1208 }
1209
1210 // output the document text
1211 if (!args["d"].empty())
1212 {
1213 output_document_flashxml (OID, args, collectproto, browsers, disp, outconvert, textout, logout);
1214 }
1215 }
1216
1217 return true;
1218}
1219
1220
1221
1222void documentaction::output_text (ResultDocInfo_t &docinfo, format_t *formatlistptr,
1223 const TermInfo_tarray &terminfo, const text_t &OID,
1224 bool highlight, int hastxt, int wanttext,
1225 text_t &collection, recptproto *collectproto,
1226 browsermapclass *browsers, displayclass &disp,
1227 outconvertclass &outconvert, ostream &textout,
1228 ostream &logout, cgiargsclass &args) {
1229
1230 DocumentRequest_t docrequest;
1231 DocumentResponse_t docresponse;
1232 comerror_t err;
1233 if (hastxt == 1) {
1234
1235 if (wanttext) {
1236 // get the text
1237 docrequest.OID = OID;
1238 collectproto->get_document (collection, docrequest, docresponse, err, logout);
1239
1240 // cut down on overhead by not using formattools if we only want the text
1241 // (wanttext will equal 2 if we want text and other stuff too)
1242 if (wanttext == 1)
1243 if (highlight) {
1244 highlighttext(docresponse.doc, args, terminfo, disp, outconvert, textout);
1245 } else {
1246 textout << outconvert << disp << docresponse.doc;
1247 }
1248 }
1249
1250 if (wanttext != 1) {
1251 text_tmap options;
1252 options["text"] = docresponse.doc;
1253
1254 browsetoolsclass b;
1255 options["assocfilepath"] = b.get_assocfile_path();
1256 if (formatinfo.AllowExtendedOptions) {
1257 b.load_extended_options(options, args, browsers, formatinfo,
1258 collectproto, disp, outconvert, logout);
1259 }
1260
1261 text_t doctext
1262 = get_formatted_string (collection, collectproto, docinfo, disp,
1263 formatlistptr, options, logout);
1264
1265 if (highlight) {
1266 highlighttext(doctext, args, terminfo, disp, outconvert, textout);
1267 } else {
1268 textout << outconvert << disp << doctext;
1269 }
1270 }
1271 }
1272}
1273
1274
1275void documentaction::output_document (const text_t &OID, cgiargsclass &args,
1276 recptproto *collectproto, browsermapclass *browsers,
1277 displayclass &disp, outconvertclass &outconvert,
1278 ostream &textout, ostream &logout) {
1279 FilterResponse_t inforesponse;
1280 FilterResponse_t queryresponse;
1281 text_tset metadata;
1282 bool getParents = false;
1283 bool highlight = false;
1284 int wanttext = 0;
1285 int arg_gt = args.getintarg("gt");
1286 text_t &collection = args["c"];
1287
1288 // if we have a query string and highlighting is turned on we need
1289 // to redo the query to get the terms for highlighting
1290
1291 if (!args["q"].empty() && args.getintarg("hl")) {
1292
1293 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, collection, logout);
1294 bool segment = false;
1295 if (cinfo != NULL) {
1296 segment = cinfo->isSegmented;
1297 }
1298 FilterRequest_t request;
1299 comerror_t err;
1300 request.filterResultOptions = FRmatchTerms;
1301 text_t formattedstring = args["q"];
1302 format_querystring (formattedstring, args.getintarg("b"), segment);
1303 set_fulltext_queryfilter_options (request, formattedstring, args);
1304 args["q"] = formattedstring; // need to set this here for phrase
1305 // highlighting, where we look at the querystring
1306 collectproto->filter (args["c"], request, queryresponse, err, logout);
1307 if (err != noError) {
1308 outconvertclass text_t2ascii;
1309 logout << text_t2ascii
1310 << "documentaction::output_document: call to QueryFilter failed "
1311 << "for " << args["c"] << " collection (" << get_comerror_string (err) << ")\n";
1312 highlight = false;
1313 } else {
1314 highlight = true;
1315 }
1316 }
1317
1318 format_t *formatlistptr = new format_t();
1319 parse_formatstring (formatinfo.DocumentText, formatlistptr, metadata, getParents);
1320
1321 metadata.insert ("hastxt");
1322 metadata.insert ("haschildren");
1323
1324 if (formatinfo.DocumentText == "[Text]")
1325 wanttext = 1;
1326 else {
1327 char *docformat = formatinfo.DocumentText.getcstr();
1328 if (strstr (docformat, "[Text]") != NULL)
1329 wanttext = 2;
1330 delete []docformat;
1331 }
1332
1333 textout << outconvert << "<div class=\"documenttext\">\n";
1334
1335 if (get_info (OID, collection, args["l"], metadata, getParents, collectproto, inforesponse, logout)) {
1336 int hastxt = inforesponse.docInfo[0].metadata["hastxt"].values[0].getint();
1337 int haschildren = inforesponse.docInfo[0].metadata["haschildren"].values[0].getint();
1338
1339 if (arg_gt == 0) {
1340 output_text (inforesponse.docInfo[0], formatlistptr, queryresponse.termInfo,
1341 OID, highlight, hastxt, wanttext, collection, collectproto,
1342 browsers, disp, outconvert, textout, logout, args);
1343
1344 } else {
1345
1346 ResultDocInfo_t thisdocinfo = inforesponse.docInfo[0];
1347
1348 // text is to be expanded
1349 text_t exOID = OID;
1350 if (haschildren != 1) exOID = get_parent (OID);
1351 if (exOID.empty()) exOID = OID;
1352
1353 // if we're not in a document (i.e. we're in a top level classification)
1354 // we need to pass "is_classify = true" to get_contents so that it
1355 // doesn't recurse all the way through each document in the classification
1356 bool is_classify = false;
1357 if (args["d"].empty()) is_classify = true;
1358
1359 get_contents (exOID, is_classify, metadata, collection, args["l"],
1360 collectproto, inforesponse, logout);
1361
1362 ResultDocInfo_tarray::iterator sechere = inforesponse.docInfo.begin();
1363 ResultDocInfo_tarray::iterator secend = inforesponse.docInfo.end();
1364
1365 if (arg_gt == 1) {
1366 // check if there are more than 10 sections containing text to be expanded -
1367 // if there are output warning message - this isn't a great way to do this
1368 // since the sections may be very large or very small - one day I'll fix it
1369 // -- Stefan.
1370 int seccount = 0;
1371 while (sechere != secend) {
1372 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
1373 if (shastxt == 1) ++seccount;
1374 if (seccount > 10) break;
1375 ++sechere;
1376 }
1377 if (seccount > 10) {
1378 // more than 10 sections so output warning message and text
1379 // for current section only
1380 textout << outconvert << disp << "<div class=\"warning\">_document:textltwarning_</div>\n";
1381
1382 output_text (thisdocinfo, formatlistptr, queryresponse.termInfo,
1383 OID, highlight, hastxt, wanttext, collection,
1384 collectproto, browsers, disp, outconvert, textout, logout, args);
1385
1386 }
1387 else arg_gt = 2;
1388 }
1389
1390 if (arg_gt == 2) {
1391 // get the text for each section
1392 sechere = inforesponse.docInfo.begin();
1393 int count = 0;
1394 while (sechere != secend) {
1395 textout << outconvert << disp << "\n<p><a name=\"" << (*sechere).OID << "\"></a>\n";
1396
1397 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
1398
1399
1400 output_text (*sechere, formatlistptr, queryresponse.termInfo,
1401 (*sechere).OID, highlight, shastxt, wanttext, collection,
1402 collectproto, browsers, disp, outconvert, textout, logout, args);
1403
1404 ++count;
1405 ++sechere;
1406 }
1407 }
1408 }
1409 }
1410 textout << outconvert << "</div>\n";
1411 delete formatlistptr;
1412}
1413
1414void documentaction::output_document_flashxml(const text_t &OID, cgiargsclass &args,
1415 recptproto *collectproto, browsermapclass *browsermap,
1416 displayclass &disp, outconvertclass &outconvert,
1417 ostream &textout, ostream &logout) {
1418 //if this is not at the document level --> do Nothing!!
1419 if (args["d"].empty())
1420 return;
1421
1422 //if we have a query string and highlighting is turned on we need
1423 //to redo the query to get the terms for highlighting
1424 FilterResponse_t queryresponse;
1425 bool highlight = false;
1426 if (!args["q"].empty() && args.getintarg("hl"))
1427 {
1428 text_t &collection = args["c"];
1429 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, collection, logout);
1430 bool segment = false;
1431 if (cinfo != NULL)
1432 {
1433 segment = cinfo->isSegmented;
1434 }
1435 FilterRequest_t request;
1436 comerror_t err;
1437 request.filterResultOptions = FRmatchTerms;
1438 text_t formattedstring = args["q"];
1439 format_querystring (formattedstring, args.getintarg("b"), segment);
1440 set_fulltext_queryfilter_options (request, formattedstring, args);
1441 args["q"] = formattedstring; //need to set this here for phrase
1442 //highlighting, where we look at the querystring
1443 collectproto->filter (args["c"], request, queryresponse, err, logout);
1444 if (err != noError)
1445 {
1446 outconvertclass text_t2ascii;
1447 logout << text_t2ascii
1448 << "documentaction::output_document: call to QueryFilter failed "
1449 << "for " << args["c"] << " collection (" << get_comerror_string (err) << ")\n";
1450 highlight = false;
1451 }
1452 else
1453 {
1454 highlight = true;
1455 }
1456 }
1457
1458 FilterResponse_t response;
1459 bool getParents = false;
1460 text_tset metadata;
1461 text_t classifytype, classification, formatstring;
1462
1463 //metadata elements needed by recurse_contents
1464 metadata.insert ("Title");
1465 metadata.insert ("gs.allowPrinting");
1466 metadata.insert ("haschildren");
1467
1468 //protocol call
1469 if (!get_info (OID, args["c"], args["l"], metadata, getParents, collectproto, response, logout))
1470 return;
1471
1472 recurse_contents (response.docInfo[0], args, metadata,
1473 getParents, collectproto, disp, outconvert, textout, logout, highlight, queryresponse.termInfo);
1474}
1475
1476void documentaction::recurse_contents(ResultDocInfo_t &section, cgiargsclass &args,
1477 text_tset &metadata, bool &getParents,
1478 recptproto *collectproto, displayclass &disp,
1479 outconvertclass &outconvert, ostream &textout, ostream &logout,
1480 bool highlight, const TermInfo_tarray &terminfo)
1481{
1482 text_t formatstring;
1483
1484 bool is_classify = false;
1485
1486 //output this section
1487 text_t classification = "Document";
1488
1489 textout << outconvert << disp << "<Section>\n";
1490
1491 //get the title
1492 textout << outconvert << disp << "<Description>\n";
1493
1494 textout << outconvert << disp << " <Metadata name=\"Title\">";
1495 text_t t_title = section.metadata["Title"].values[0];
1496
1497 //if it is highlighted
1498 /*if (highlight == true)
1499 {
1500 highlighttext(t_title, args, terminfo, disp, outconvert, textout);
1501 }
1502 else
1503 {*/
1504 textout << outconvert << disp << t_title;
1505 //}
1506
1507 textout << outconvert << disp << "</Metadata>\n";
1508
1509 // if top-level document section, add in allowPrint metadata
1510 if (is_top(section.OID)) {
1511 textout << outconvert << disp << " <Metadata name=\"allowPrint\">";
1512 text_t t_allowprint = "true";
1513
1514 if (section.metadata["gs.allowPrinting"].values.size()>0) {
1515 text_t opt_allowprint = section.metadata["gs.allowPrinting"].values[0];
1516 if (!opt_allowprint.empty()) {
1517 t_allowprint = opt_allowprint;
1518 }
1519 }
1520
1521 textout << outconvert << disp << t_allowprint;
1522 textout << outconvert << disp << "</Metadata>\n";
1523 }
1524
1525 textout << outconvert << disp << "</Description>\n";
1526
1527 //get the text
1528 DocumentRequest_t docrequest;
1529 DocumentResponse_t docresponse;
1530 comerror_t err;
1531 docrequest.OID = section.OID;
1532 text_t &collection = args["c"];
1533 collectproto->get_document(collection, docrequest, docresponse, err, logout);
1534 //if it is highlighted
1535 if (highlight == true)
1536 {
1537 highlighttext(docresponse.doc, args, terminfo, disp, outconvert, textout);
1538 }
1539 else
1540 {
1541 textout << outconvert << disp << docresponse.doc;
1542 }
1543 textout << outconvert << disp << "\n";
1544
1545 int haschildren = section.metadata["haschildren"].values[0].getint();
1546
1547 // recurse through children
1548 if (haschildren == 1)
1549 {
1550 FilterResponse_t tmp;
1551 get_children (section.OID, args["c"], args["l"], metadata, getParents, collectproto, tmp, logout);
1552 ResultDocInfo_tarray::iterator thisdoc = tmp.docInfo.begin();
1553 ResultDocInfo_tarray::iterator lastdoc = tmp.docInfo.end();
1554
1555 while (thisdoc != lastdoc)
1556 {
1557 recurse_contents (*thisdoc, args, metadata, getParents, collectproto, disp, outconvert, textout, logout, highlight, terminfo);
1558 ++thisdoc;
1559 }
1560 }
1561
1562 textout << outconvert << disp << "</Section>\n";
1563}
1564
1565void documentaction::set_arrow_macros (cgiargsclass &args, recptproto *collectproto,
1566 displayclass &disp, ostream &logout) {
1567
1568 text_tset metadata;
1569 FilterResponse_t response;
1570 FilterResponse_t presponse;
1571
1572 int haschildren = 0;
1573 text_tarray next_siblings;
1574 text_t previous_sibling;
1575 text_t &arg_d = args["d"];
1576
1577 // get info on current section
1578 metadata.insert("haschildren");
1579 if (!get_info(arg_d, args["c"], args["l"], metadata, false, collectproto, response, logout)) {
1580 logout << "error 1 in documentaction::set_arrow_macros\n";
1581 return;
1582 }
1583 haschildren = response.docInfo[0].metadata["haschildren"].values[0].getint();
1584
1585 // get OIDs of next and previous siblings of current section and
1586 // all it's parents
1587 int parentcount = countchar(arg_d.begin(), arg_d.end(), '.');
1588 text_t thisoid = arg_d;
1589 while (parentcount > 0) {
1590 get_children (get_parent(thisoid), args["c"], args["l"], metadata, false,
1591 collectproto, response, logout);
1592 ResultDocInfo_tarray::iterator this_sibling = response.docInfo.begin();
1593 ResultDocInfo_tarray::iterator last_sibling = response.docInfo.end();
1594 bool first = true;
1595 while (this_sibling != last_sibling) {
1596 if ((*this_sibling).OID == thisoid) {
1597 if (!first && next_siblings.empty()) {
1598 previous_sibling = (*(this_sibling-1)).OID;
1599 int section_has_children = (*(this_sibling-1)).metadata["haschildren"].values[0].getint();
1600 // if previous sibling has children we need to recurse
1601 // down to the last descendant
1602 while (section_has_children) {
1603 get_children (previous_sibling, args["c"], args["l"], metadata, false,
1604 collectproto, presponse, logout);
1605 if (!presponse.docInfo.empty()) {
1606 ResultDocInfo_tarray::iterator it = presponse.docInfo.end() - 1;
1607 previous_sibling = (*it).OID;
1608 section_has_children = (*it).metadata["haschildren"].values[0].getint();
1609 } else {
1610 section_has_children = 0; // this should never happen
1611 }
1612 }
1613 }
1614
1615 if ((this_sibling+1) != last_sibling) {
1616 next_siblings.push_back((*(this_sibling+1)).OID);
1617 } else {
1618 next_siblings.push_back("");
1619 }
1620 break;
1621 }
1622 ++this_sibling;
1623 first = false;
1624 }
1625 thisoid = get_parent(thisoid);
1626 --parentcount;
1627 }
1628
1629 // work out values for next link
1630 if (haschildren) {
1631#ifndef DOCHANLE
1632 disp.setmacro ("httpnextarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1633 "&amp;d=" + arg_d + ".fc");
1634#else
1635 disp.setmacro ("httpnextarrow", "document", "_httpdocumenthandle_("+args["c"]+","+arg_d + ".fc)";
1636
1637#endif
1638
1639 } else {
1640 text_tarray::const_iterator h = next_siblings.begin();
1641 text_tarray::const_iterator e = next_siblings.end();
1642 while (h != e) {
1643 if (!(*h).empty()) {
1644#ifndef DOCHANLE
1645 disp.setmacro ("httpnextarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1646 "&amp;d=" + *h);
1647#else
1648 disp.setmacro ("httpnextarrow", "document", "_httpdocumenthandle_("+args["c"]+","+*h+")";
1649
1650#endif
1651
1652 break;
1653 }
1654 ++h;
1655 }
1656 }
1657
1658 // work out value for previous link
1659 if (!previous_sibling.empty()) {
1660#ifndef DOCHANDLE
1661 disp.setmacro ("httpprevarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1662 "&amp;d=" + previous_sibling);
1663#else
1664 disp.setmacro ("httpprevarrow", "document", "_httpdocumenthandle_("+args["c"]+","+ previous_sibling+")");
1665
1666#endif
1667
1668 } else {
1669 if (countchar(arg_d.begin(), arg_d.end(), '.')) {
1670#ifndef DOCHANDLE
1671 disp.setmacro ("httpprevarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1672 "&amp;d=" + get_parent(arg_d));
1673#else
1674 disp.setmacro ("httpprevarrow", "document", "_httpdocumenthandle_("+args["c"]+","+get_parent(arg_d)+")");
1675
1676#endif
1677
1678 }
1679 }
1680}
Note: See TracBrowser for help on using the repository browser.