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

Last change on this file since 22984 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
RevLine 
[248]1/**********************************************************************
2 *
3 * documentaction.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.
[248]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 *
[248]24 *********************************************************************/
25
[443]26#include <string.h>
[4936]27
[248]28#include "documentaction.h"
[15418]29#include "recptprototools.h"
[248]30#include "OIDtools.h"
[267]31#include "querytools.h"
32#include "unitool.h"
[1148]33#include "gsdltools.h"
[3322]34#include "highlighttext.h"
[12044]35#include "browsetoolsclass.h"
[248]36
37documentaction::documentaction () {
[1270]38 recpt = NULL;
[600]39
[248]40 // this action uses cgi variables "a", "d", "cl",
[257]41 // "x", "gc", "gt", "gp", and "hl"
[248]42 cgiarginfo arg_ainfo;
43 arg_ainfo.shortname = "a";
44 arg_ainfo.longname = "action";
45 arg_ainfo.multiplechar = true;
[22984]46 arg_ainfo.multiplevalue = false;
[248]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;
[22984]55 arg_ainfo.multiplevalue = false;
[248]56 arg_ainfo.defaultstatus = cgiarginfo::none;
[7441]57 arg_ainfo.argdefault = g_EmptyText;
[248]58 arg_ainfo.savedarginfo = cgiarginfo::can;
59 argsinfo.addarginfo (NULL, arg_ainfo);
60
[722]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;
[22984]66 arg_ainfo.multiplevalue = false;
[722]67 arg_ainfo.defaultstatus = cgiarginfo::weak;
68 arg_ainfo.argdefault = "l";
69 arg_ainfo.savedarginfo = cgiarginfo::must;
70 argsinfo.addarginfo (NULL, arg_ainfo);
71
[248]72 arg_ainfo.shortname = "cl";
73 arg_ainfo.longname = "classification OID";
74 arg_ainfo.multiplechar = true;
[22984]75 arg_ainfo.multiplevalue = false;
[248]76 arg_ainfo.defaultstatus = cgiarginfo::none;
[7441]77 arg_ainfo.argdefault = g_EmptyText;
[248]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;
[22984]86 arg_ainfo.multiplevalue = false;
[248]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
[257]93 // text function 0 = not expanded, 1 = expand unless
94 // there are more than 10 sections containing text,
95 // 2 = expand all
[248]96 arg_ainfo.shortname = "gt";
97 arg_ainfo.longname = "expand text";
98 arg_ainfo.multiplechar = false;
[22984]99 arg_ainfo.multiplevalue = false;
[248]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;
[22984]110 arg_ainfo.multiplevalue = false;
[248]111 arg_ainfo.defaultstatus = cgiarginfo::none;
[7441]112 arg_ainfo.argdefault = g_EmptyText;
[248]113 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
114 argsinfo.addarginfo (NULL, arg_ainfo);
115
[257]116 // in this action "hl" is the "highlighting on/
[3322]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)
[257]121 arg_ainfo.shortname = "hl";
122 arg_ainfo.longname = "highlighting on/off";
123 arg_ainfo.multiplechar = false;
[22984]124 arg_ainfo.multiplevalue = false;
[257]125 arg_ainfo.defaultstatus = cgiarginfo::weak;
126 arg_ainfo.argdefault = "1";
127 arg_ainfo.savedarginfo = cgiarginfo::must;
128 argsinfo.addarginfo (NULL, arg_ainfo);
129
[248]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;
[22984]135 arg_ainfo.multiplevalue = false;
[248]136 arg_ainfo.defaultstatus = cgiarginfo::weak;
137 arg_ainfo.argdefault = "0";
[282]138 arg_ainfo.savedarginfo = cgiarginfo::must;
[248]139 argsinfo.addarginfo (NULL, arg_ainfo);
[870]140
[5124]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;
[22984]145 arg_ainfo.multiplevalue = false;
[5124]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
[870]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;
[22984]157 arg_ainfo.multiplevalue = false;
[870]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;
[22984]168 arg_ainfo.multiplevalue = false;
[870]169 arg_ainfo.defaultstatus = cgiarginfo::weak;
170 arg_ainfo.argdefault = "1";
171 arg_ainfo.savedarginfo = cgiarginfo::must;
172 argsinfo.addarginfo (NULL, arg_ainfo);
[1941]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;
[22984]179 arg_ainfo.multiplevalue = false;
[1941]180 arg_ainfo.defaultstatus = cgiarginfo::weak;
181 arg_ainfo.argdefault = "0";
182 arg_ainfo.savedarginfo = cgiarginfo::must;
183 argsinfo.addarginfo (NULL, arg_ainfo);
184
[6645]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;
[22984]189 arg_ainfo.multiplevalue = false;
[6645]190 arg_ainfo.defaultstatus = cgiarginfo::weak;
[7441]191 arg_ainfo.argdefault = g_EmptyText;
[6645]192 arg_ainfo.savedarginfo = cgiarginfo::must;
193 argsinfo.addarginfo (NULL, arg_ainfo);
194
[248]195}
196
[12044]197documentaction::~documentaction()
198{
[248]199}
200
[284]201bool documentaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
[4974]202 recptprotolistclass *protos, ostream &logout) {
[284]203
[4974]204 if(!args["d"].empty())
205 {
[4984]206 text_t docTop;
207 get_top(args["d"],docTop);
208
[4974]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
[5024]214 if(cinfo->authenticate == "document")
[4974]215 {
216 // both are either commented out or uncomment and are empty
[5024]217 if (cinfo->public_documents.empty() && cinfo->private_documents.empty())
[4974]218 {
219 //deny everything
220 args["uan"] = "1";
221 args["ug"] = cinfo->auth_group;
222 }
223
[5024]224 // both public_documents and private_documents are turned on !
225 else if (!cinfo->public_documents.empty() && !cinfo->private_documents.empty())
[4974]226 {
227 //deny everything
228 args["uan"] = "1";
229 args["ug"] = cinfo->auth_group;
230 }
231
[5179]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 }
[4974]240
[5179]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 }
[4974]249
250 }
251 }
252 }
253 // check gc argument
254 int arg_gc = args.getintarg("gc");
[2805]255 if (arg_gc < 0 || arg_gc > 2) {
[284]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");
[3322]271 if (arg_hl < 0 || arg_hl > 2) {
[284]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
[1941]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
[248]294 return true;
295}
296
[758]297void documentaction::get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
298 response_t &response,text_t &response_data,
299 ostream &logout) {
[722]300
[758]301 if ((args["il"] == "w") && (!args["d"].empty())) {
[722]302
[758]303 recptproto* collectproto = protos->getrecptproto (args["c"], logout);
304 if (collectproto != NULL) {
305
[722]306 text_tset metadata;
307 FilterResponse_t filt_response;
[758]308 text_t top;
[722]309
310 metadata.insert ("URL");
[758]311
312 // get metadata for parent document
313 get_top (args["d"], top);
[7432]314 if (get_info (top, args["c"], args["l"], metadata, false, collectproto, filt_response, logout)) {
[781]315 text_t url = filt_response.docInfo[0].metadata["URL"].values[0];
[758]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 }
[722]324 }
[758]325 }
326 response = content;
327 response_data = "text/html";
[248]328}
329
[600]330// set_widthtspace calculates how wide the spaces in the nav bar should
331// be and sets the appropriate macro
[4774]332void documentaction::set_spacemacro (displayclass &disp, FilterResponse_t &response,
333 bool has_search_button) {
[600]334
335 text_t width;
336 int twidth, swidth, iwidth = 0;
337
338 int numc = response.docInfo.size();
[649]339 ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
340 ResultDocInfo_tarray::iterator docend = response.docInfo.end();
[600]341
[7433]342 disp.expandstring (displayclass::defaultpackage, "_pagewidth_", width);
[600]343 twidth = width.getint();
[9923]344
[4774]345 if (has_search_button) {
346 disp.expandstring ("query", "_searchwidth_", width);
347 iwidth += width.getint();
348 } else {
349 numc -= 1;
350 }
[600]351
352 while (dochere != docend) {
[649]353 const text_t &title = (*dochere).metadata["Title"].values[0];
[600]354
355 disp.expandstring ("document", "_" + title + "width_", width);
[9923]356 if (width == ("_" + title + "width_")) {
[649]357 disp.expandstring ("document", "_defaultwidth_", width);
[9923]358 }
[600]359 iwidth += width.getint();
[9620]360 ++dochere;
[600]361 }
[9923]362
[600]363 if ((twidth - iwidth) < numc) swidth = 2;
364 else {
365 swidth = twidth - iwidth;
366 if (numc > 0) swidth = swidth / numc;
367 }
[7433]368 disp.setmacro ("widthtspace", displayclass::defaultpackage, swidth);
[600]369}
370
[1419]371// set_navbarmacros sets _navigationbar_ and _httpbrowseXXX_ macros
[649]372// reponse contains 1 metadata field (Title)
373void documentaction::set_navbarmacros (displayclass &disp, FilterResponse_t &response,
[4893]374 bool has_search_button, cgiargsclass &args,
375 ColInfoResponse_t &cinfo) {
[600]376
377
[4893]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 }
[600]385
[4893]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) {
[12229]397 // search uses its own navtab, as it may be suppressed based on other args
[11413]398 navigationbar += "_navtabsearch_";
[12174]399 if (args["a"] == "q") {
400 navigationbar += "(selected)";
401 }
[4893]402 }
[12174]403
[10873]404 if (has_search_button || numc == 0) navigationbar += "_navbarspacer_";
[12174]405
[4893]406 bool first = true;
407 while (dochere != docend) {
[12174]408 if (!first) navigationbar += "_navbarspacer_";
409
410 text_t title = (*dochere).metadata["Title"].values[0];
411
[12229]412 navigationbar += "_navtab_(_httpbrowse"+(*dochere).OID+"_,"+title;
[12174]413 // if we are at this classifier
414 if (arg_d.empty() && ((*dochere).OID == topparent)) {
[10873]415 // don't link to this classifier as it is the current one
[12174]416 navigationbar += ",selected";
[10873]417 }
[12174]418 navigationbar += ")";
[10873]419
[12229]420 // set the _httpbrowseCLX_ macro for this classification
421 disp.setmacro ("httpbrowse" + (*dochere).OID, displayclass::defaultpackage, "_httpdocument_&amp;cl=" + (*dochere).OID);
[9620]422 ++dochere;
[4893]423 first = false;
424 }
[12174]425
[15846]426 navigationbar += "_dynamicclassifiernavbarentries_";
[10873]427 navigationbar += "\n<!-- End of Navigation Bar -->\n";
[4774]428
[4893]429 } else {
[4774]430
[4893]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";
[600]434
[4893]435 if (args["a"] != "q" && args["cl"].empty()) {
[5019]436 navigationbar += "<option value=\"\" selected>_textselectpage_</option>\n";
[4893]437 }
438
439 if (has_search_button) {
440 navigationbar += "<option value=\"_httpquery_\"";
441 if (args["a"] == "q") {
442 navigationbar += " selected";
443 }
[11355]444 navigationbar += ">_labelSearch_</option>\n";
[4893]445 }
[649]446
[4893]447 while (dochere != docend) {
448 text_t title = dochere->metadata["Title"].values[0];
[6645]449
[11771]450 navigationbar += "<option value=\"_httpdocument_&amp;cl=" + dochere->OID + "\"";
[4893]451 if (topparent == dochere->OID) {
452 navigationbar += " selected";
453 }
[12174]454 navigationbar += ">_navlinktitle_(" + title + ")</option>\n";
[9620]455 ++dochere;
[4893]456 }
[649]457
[4893]458 navigationbar += "</select>\n";
459 navigationbar += "</form>\n";
460 }
[649]461
[7433]462 disp.setmacro ("navigationbar", displayclass::defaultpackage, navigationbar);
[600]463}
464
[248]465// define all the macros which might be used by other actions
466// to produce pages.
[758]467void documentaction::define_external_macros (displayclass &disp, cgiargsclass &args,
468 recptprotolistclass *protos, ostream &logout) {
[248]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
[600]482 // _widthtspace_ the width of the spacers between buttons in navigation
483 // bar
[438]484
[870]485 // _httpdocument_ has '&f=1' added if displaying document inside a frame
[248]486
[870]487 // _gsdltop_ macro to replace _top targets with
488
489 // _httppagehome_ overridden home url if html collections have own homepage
490
[11355]491 // _usability_ macros for remote usability reporting: if
492 // _usabinterface_ "format Usability [multi|textonly|stepwise]" is in
493 // _usabilityscript_ collect.cfg
[3880]494
[12463]495 // _versionnnum_ greenstone version number (hard-coded)
[758]496 // must have a valid collection server to continue
[4936]497
[758]498 text_t &collection = args["c"];
499 if (collection.empty()) return;
500 recptproto *collectproto = protos->getrecptproto (collection, logout);
[267]501 if (collectproto == NULL) return;
[758]502
[1270]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
[248]510 outconvertclass text_t2ascii;
511 comerror_t err;
512 InfoFiltersResponse_t filterinfo;
513 FilterResponse_t response;
[649]514 text_tset metadata;
[277]515
[1347]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;
[870]522
[1347]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
[870]532 if (formatinfo.DocumentUseHTML) {
533
534 // frame stuff
535 if (args["fc"] == "1") {
536 text_t httpdocument;
[7433]537 disp.expandstring (displayclass::defaultpackage, "_httpdocument_", httpdocument);
[10873]538 httpdocument += "&amp;f=1";
[7433]539 disp.setmacro ("httpdocument", displayclass::defaultpackage, httpdocument);
540 disp.setmacro ("gsdltop", displayclass::defaultpackage, "documenttop");
[2422]541 formatinfo.DocumentText = "[Text]";
[870]542 }
[1348]543 text_tmap::iterator it = cinfo.format.find ("homepage");
544 if (it != cinfo.format.end()) {
[870]545 text_t httppagehome;
546 if (get_link (args, protos, (*it).second, httppagehome, logout))
[7433]547 disp.setmacro ("httppagehome", displayclass::defaultpackage, httppagehome);
[870]548 }
549 }
550
[282]551 // don't want navigation bar if page is 'detached'
552 if (!args.getintarg("x")) {
[248]553
[282]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()) {
[248]558
[649]559 metadata.insert ("Title");
[405]560 bool getParents = false;
[7432]561 get_children ("", collection, args["l"], metadata, getParents, collectproto, response, logout);
[282]562
[4774]563 bool has_search_button = true;
564 collectproto->is_searchable(collection, has_search_button, err, logout);
[11413]565 if (err != noError) has_search_button = false;
[4774]566
[600]567 // calculate width of spacers and set _widthtspace_ macro
[4774]568 if (args.getintarg("v") == 0) set_spacemacro (disp, response, has_search_button);
[450]569
[1419]570 // set _navigationbar_ macro
[4893]571 set_navbarmacros (disp, response, has_search_button, args, cinfo);
[928]572
[248]573 }
[282]574 } else {
575 logout << text_t2ascii
576 << "Error (documentaction::define_external_macros()) in call to get_filterinfo() "
577 << get_comerror_string (err);
[248]578 }
579 }
[11355]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
[12463]589 // version num
590 disp.setmacro("versionnum", displayclass::defaultpackage, GSDL_VERSION);
591
[248]592}
593
[870]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
[7432]604 if (get_info (inlink, args["c"], args["l"], metadata, false, collectproto, response, logout)) {
[870]605 if (!response.docInfo[0].metadata["section"].values[0].empty()) {
[11998]606#ifndef DOCHANDLE
[10873]607 outlink = "_httpdocument_&amp;d=" + response.docInfo[0].metadata["section"].values[0];
[11998]608#else
609 outlink = "_httpdocumenthandle_("+args["c"]+","+response.docInfo[0].metadata["section"].values[0]+")";
610#endif
611
[870]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
[9620]628 if (*col_here == args["c"]) {++col_here; continue;}
[870]629
630 collectproto = protos->getrecptproto (*col_here, logout);
631
[7432]632 if (get_info (inlink, *col_here, args["l"], metadata, false, collectproto, response, logout)) {
[870]633 if (!response.docInfo[0].metadata["section"].values[0].empty()) {
[11998]634#ifndef DOCHANDLE
[10873]635 outlink = "_httpdocument_&amp;c=" + *col_here + "&amp;d=" +
[870]636 response.docInfo[0].metadata["section"].values[0];
[11998]637#else
638 outlink = "_httpdocumenthandle_("+*col_here+","+response.docInfo[0].metadata["section"].values[0]+")";
639#endif
640
[870]641 return true;
642 }
643 }
[9620]644 ++col_here;
[870]645 }
646 }
647 return false;
648}
649
[464]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) {
[1079]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;
[464]668 else if (((*format_here).first == "DocumentArrowsBottom") &&
669 ((*format_here).second == "false"))
670 formatinfo.DocumentArrowsBottom = false;
[4868]671 else if (((*format_here).first == "DocumentArrowsTop") &&
672 ((*format_here).second == "true"))
673 formatinfo.DocumentArrowsTop = true;
[464]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")
[1941]678 formatinfo.DocumentText = (*format_here).second;
679 else if ((*format_here).first == "RelatedDocuments")
680 formatinfo.RelatedDocuments = (*format_here).second;
[870]681 else if (((*format_here).first == "DocumentUseHTML") &&
682 ((*format_here).second == "true"))
683 formatinfo.DocumentUseHTML = true;
[4972]684 else if (((*format_here).first == "AllowExtendedOptions") &&
685 ((*format_here).second == "true"))
686 formatinfo.AllowExtendedOptions = true;
[649]687 else
688 formatinfo.formatstrings[(*format_here).first] = (*format_here).second;
[870]689
[9620]690 ++format_here;
[464]691 }
692
693 // never want arrows when text is expanded
[4868]694 if (gt) {
695 formatinfo.DocumentArrowsBottom = false;
696 formatinfo.DocumentArrowsTop = false;
697 }
[464]698}
699
700
[248]701// define all the macros which are related to pages generated
[443]702// by this action. we also load up the formatinfo structure
703// here (it's used in do_action as well as here)
[758]704void documentaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
705 recptprotolistclass *protos, ostream &logout) {
[464]706
[248]707 // define_internal_macros sets the following macros:
[464]708
[277]709 // _pagetitle_ the title to be displayed at the top of the browser window
710
[248]711 // _imagethispage_ the title image to be displayed at top right of page
712
[4868]713 // _navarrowsbottom_ this may be overridden to "" when format option
[448]714 // DocumentArrowsBottom is false
715
[4868]716 // _navarrowstop_ likewise for DocumentArrowsTop
717
718 // _httpprevarrow_ links to next and previous sections of document - used
719 // _httpnextarrow_ by DocumentArrowsBottom
720
[248]721 // _header_ the header macro is overridden if we're not at a top level
722 // classification to remove the title block
[257]723
[300]724 // _thisOID_ the OID (directory) of the current document - this corresponds
[21743]725 // to the assocfilepath metadata element
[300]726
[12943]727 // _documentheader_ Custom header info for the specified document
[758]728 // must have a valid collection server to continue
[4936]729
730 text_t &collection = args["c"];
[758]731 if (collection.empty()) return;
732 recptproto *collectproto = protos->getrecptproto (collection, logout);
[267]733 if (collectproto == NULL) return;
[758]734
[649]735 text_tset metadata;
[248]736 FilterResponse_t response;
[277]737 text_t &arg_d = args["d"];
738 text_t &arg_cl = args["cl"];
739
[4868]740 if (!formatinfo.DocumentArrowsBottom) {
741 disp.setmacro("navarrowsbottom", "document", "");
742 } else if (!formatinfo.DocumentArrowsBottom) {
743 disp.setmacro("navarrowstop", "document", "");
744 }
[448]745
[4868]746 if (!arg_d.empty() && (formatinfo.DocumentArrowsBottom || formatinfo.DocumentArrowsTop)) {
747 // set _httpprevarrow_ and _httpnextarrow_
748 set_arrow_macros (args, collectproto, disp, logout);
749 }
750
[649]751 metadata.insert ("Title");
[12943]752 metadata.insert ("gs.DocumentHeader");
753 metadata.insert ("DocumentHeader");
754
[738]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;
[17985]763 disp.setmacro("cltop", "document", cl_top);
[738]764 }
[248]765
[738]766 if (!arg_d.empty() && !fulltoc) {
[248]767 // we're at document level
[649]768
[21743]769 metadata.insert ("assocfilepath");
[1347]770
[2113]771 comerror_t err;
[1347]772 OptionValue_tarray options;
[2646]773 // we need to do the query again for the z3950proto
[2113]774 if (collectproto->get_protocol_name(err)=="z3950proto") {
[1347]775 OptionValue_t opt;
[2646]776 opt.name="Term";opt.value=args["q"];options.push_back(opt);
777 opt.name="QueryType";
778 opt.value=(args.getintarg("t")) ? "ranked" : "boolean";
[1347]779 options.push_back(opt);
[2646]780 opt.name="Index";opt.value=args["h"];options.push_back(opt);
[1347]781 }
[1941]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()){
[1347]790
[7441]791 text_t relation = g_EmptyText; //string for displaying relation metadata
[1941]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.
[4936]795
[7432]796 if (get_info (arg_d, collection, args["l"], metadata, options, false, collectproto, response, logout))
[1941]797 relation += get_related_docs(collection, collectproto, response.docInfo[0], logout);
798
799 //set macro to be the related document string
[4936]800
[1941]801 disp.setmacro ("relateddoc", "document", relation);
802 }
803
804
[277]805 // get metadata for this document and it's parents
[7432]806 if (get_info (arg_d, collection, args["l"], metadata, options,
[1347]807 true, collectproto, response, logout)) {
[1941]808
[248]809 disp.setmacro ("header", "document", "_textheader_");
[669]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]);
[1941]813
[870]814 if (args["gt"] != "1") {
[669]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;
[284]820 }
[277]821 }
[669]822 reverse (pagetitlearray.begin(), pagetitlearray.end());
823 text_t pagetitle;
824 joinchar (pagetitlearray, ": ", pagetitle);
[6936]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 }
[277]842 disp.setmacro ("pagetitle", "document", pagetitle);
[669]843
[12943]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
[669]871 if (is_top (arg_d))
[21743]872 disp.setmacro ("thisOID", displayclass::defaultpackage, dm_safe(response.docInfo[0].metadata["assocfilepath"].values[0]));
[669]873 else {
[21743]874 MetadataInfo_t *parentad = response.docInfo[0].metadata["assocfilepath"].parent;
[669]875 text_t thisOID;
876 while (parentad != NULL) {
877 thisOID = parentad->values[0];
878 parentad = parentad->parent;
879 }
[7433]880 disp.setmacro ("thisOID", displayclass::defaultpackage, dm_safe(thisOID));
[669]881 }
[248]882 }
883 } else {
[277]884 if (!arg_cl.empty()) {
[248]885
[9917]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 }
[248]892 // get metadata for top level classification
[257]893 text_t classtop;
[277]894 get_top (arg_cl, classtop);
[1804]895 metadata.insert ("childtype");
[2017]896 metadata.insert ("parameters");
[1804]897
[7432]898 if (get_info (classtop, collection, args["l"], metadata, false, collectproto, response, logout)) {
[248]899
[649]900 text_t &title = response.docInfo[0].metadata["Title"].values[0];
901 bool unknown = false;
[257]902
[11152]903 // test if we have macros defined for this classification's
904 // metadata name - if not we'll just display the name
[649]905 text_t tmp;
[11152]906 text_t macroname="_label" + title + "_";
907 disp.expandstring ("Global", macroname, tmp);
[10873]908 if (tmp == macroname) unknown = true; // it wasn't expanded
[604]909
[649]910 if (unknown) {
911 disp.setmacro ("pagetitle", "document", title);
912 } else {
[11152]913 disp.setmacro ("pagetitle", "document", macroname);
[649]914 }
[11158]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 }
[1804]927
[1941]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
[6811]932 // Add macros specific to the Collage/Phind classifiers
[1804]933 text_t &childtype = response.docInfo[0].metadata["childtype"].values[0];
[6811]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;
[9620]942 ++a;
[6811]943 }
944
[7333]945 if (collage) {
[6811]946 disp.setmacro ("collageclassifier", "document", "_collageapplet_");
[7333]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 }
[6811]969 }
970
[1804]971 if (childtype == "Phind") {
[2017]972
973 // First, a macro to display the phind classifier
[1804]974 disp.setmacro ("phindclassifier", "document", "_phindapplet_");
[2017]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")
[248]995 }
[2017]996 } // end if (!arg_cl.empty()) {
[248]997 }
998}
999
[464]1000
[12044]1001bool documentaction::do_action(cgiargsclass &args, recptprotolistclass *protos,
1002 browsermapclass *browsers, displayclass &disp,
1003 outconvertclass &outconvert, ostream &textout,
1004 ostream &logout)
1005{
[13967]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{
[758]1027 // must have a valid collection server
1028 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
[267]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 {
[758]1035
[649]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 }
[420]1042
[1941]1043
[1991]1044 if (formatinfo.DocumentUseHTML && !args["d"].empty()) {
[870]1045
[1991]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"
[11998]1051#ifndef DOCHANDLE
[1991]1052 << "<frame name=\"documenttop\" frameborder=0 src=\"_gwcgi_?_optsite_e=_compressedoptions_&a=d&d="
1053 << args["d"] << "\">"
[11998]1054#else
1055 << "<frame name=\"documenttop\" frameborder=0 src=\"_httpdocumenthandle_("
1056 << args["c"] << "," << args["d"] << ")\">"
1057#endif
[1991]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 {
[4936]1064 output_document (OID, args, collectproto, browsers, disp, outconvert, textout, logout);
[870]1065 }
[1991]1066 return true;
[870]1067 }
1068
[1941]1069
[267]1070 textout << outconvert << disp << "_document:header_\n"
1071 << "_document:content_\n";
[1079]1072
1073 // output the table of contents
[12044]1074 browsetoolsclass b;
1075 b.output_toc(args, browsers, formatinfo, collectproto,
1076 disp, outconvert, textout, logout);
[1941]1077
[4868]1078 if (formatinfo.DocumentArrowsTop && !args["d"].empty()) {
1079 textout << outconvert << disp << "_document:navarrowstop_\n";
1080 }
1081
[1941]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
[284]1086 // output the document text
[3087]1087 if (!args["d"].empty()) {
[4936]1088 output_document (OID, args, collectproto, browsers, disp, outconvert, textout, logout);
[3087]1089 }
[284]1090
1091 textout << outconvert << disp << "_document:footer_\n";
1092 }
1093 return true;
1094}
1095
[13967]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
[649]1222void documentaction::output_text (ResultDocInfo_t &docinfo, format_t *formatlistptr,
[443]1223 const TermInfo_tarray &terminfo, const text_t &OID,
[649]1224 bool highlight, int hastxt, int wanttext,
[4936]1225 text_t &collection, recptproto *collectproto,
1226 browsermapclass *browsers, displayclass &disp,
1227 outconvertclass &outconvert, ostream &textout,
1228 ostream &logout, cgiargsclass &args) {
[443]1229
1230 DocumentRequest_t docrequest;
1231 DocumentResponse_t docresponse;
1232 comerror_t err;
[649]1233 if (hastxt == 1) {
[443]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)
[3322]1243 if (highlight) {
1244 highlighttext(docresponse.doc, args, terminfo, disp, outconvert, textout);
1245 } else {
[443]1246 textout << outconvert << disp << docresponse.doc;
[3322]1247 }
[443]1248 }
1249
1250 if (wanttext != 1) {
[4906]1251 text_tmap options;
1252 options["text"] = docresponse.doc;
[4936]1253
[22671]1254 browsetoolsclass b;
1255 options["assocfilepath"] = b.get_assocfile_path();
[4972]1256 if (formatinfo.AllowExtendedOptions) {
[12044]1257 b.load_extended_options(options, args, browsers, formatinfo,
1258 collectproto, disp, outconvert, logout);
[4936]1259 }
1260
[1443]1261 text_t doctext
[4906]1262 = get_formatted_string (collection, collectproto, docinfo, disp,
1263 formatlistptr, options, logout);
[443]1264
[3322]1265 if (highlight) {
1266 highlighttext(doctext, args, terminfo, disp, outconvert, textout);
1267 } else {
[443]1268 textout << outconvert << disp << doctext;
[3322]1269 }
[443]1270 }
1271 }
1272}
1273
1274
[284]1275void documentaction::output_document (const text_t &OID, cgiargsclass &args,
[4936]1276 recptproto *collectproto, browsermapclass *browsers,
1277 displayclass &disp, outconvertclass &outconvert,
1278 ostream &textout, ostream &logout) {
[284]1279 FilterResponse_t inforesponse;
1280 FilterResponse_t queryresponse;
[649]1281 text_tset metadata;
[443]1282 bool getParents = false;
[284]1283 bool highlight = false;
[443]1284 int wanttext = 0;
[284]1285 int arg_gt = args.getintarg("gt");
1286 text_t &collection = args["c"];
[267]1287
[284]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
[4936]1290
[284]1291 if (!args["q"].empty() && args.getintarg("hl")) {
[6584]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 }
[284]1298 FilterRequest_t request;
[758]1299 comerror_t err;
[284]1300 request.filterResultOptions = FRmatchTerms;
[758]1301 text_t formattedstring = args["q"];
[6584]1302 format_querystring (formattedstring, args.getintarg("b"), segment);
[22047]1303 set_fulltext_queryfilter_options (request, formattedstring, args);
[8715]1304 args["q"] = formattedstring; // need to set this here for phrase
1305 // highlighting, where we look at the querystring
[758]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 {
[284]1314 highlight = true;
[758]1315 }
[284]1316 }
1317
[443]1318 format_t *formatlistptr = new format_t();
1319 parse_formatstring (formatinfo.DocumentText, formatlistptr, metadata, getParents);
[431]1320
[649]1321 metadata.insert ("hastxt");
1322 metadata.insert ("haschildren");
[2422]1323
[443]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;
[9633]1330 delete []docformat;
[443]1331 }
[267]1332
[11144]1333 textout << outconvert << "<div class=\"documenttext\">\n";
1334
[7432]1335 if (get_info (OID, collection, args["l"], metadata, getParents, collectproto, inforesponse, logout)) {
[649]1336 int hastxt = inforesponse.docInfo[0].metadata["hastxt"].values[0].getint();
1337 int haschildren = inforesponse.docInfo[0].metadata["haschildren"].values[0].getint();
[669]1338
[284]1339 if (arg_gt == 0) {
[443]1340 output_text (inforesponse.docInfo[0], formatlistptr, queryresponse.termInfo,
1341 OID, highlight, hastxt, wanttext, collection, collectproto,
[4936]1342 browsers, disp, outconvert, textout, logout, args);
[443]1343
[284]1344 } else {
[443]1345
1346 ResultDocInfo_t thisdocinfo = inforesponse.docInfo[0];
[267]1347
[284]1348 // text is to be expanded
1349 text_t exOID = OID;
[649]1350 if (haschildren != 1) exOID = get_parent (OID);
[443]1351 if (exOID.empty()) exOID = OID;
[267]1352
[284]1353 // if we're not in a document (i.e. we're in a top level classification)
[649]1354 // we need to pass "is_classify = true" to get_contents so that it
[284]1355 // doesn't recurse all the way through each document in the classification
[649]1356 bool is_classify = false;
1357 if (args["d"].empty()) is_classify = true;
[284]1358
[7432]1359 get_contents (exOID, is_classify, metadata, collection, args["l"],
[443]1360 collectproto, inforesponse, logout);
[267]1361
[649]1362 ResultDocInfo_tarray::iterator sechere = inforesponse.docInfo.begin();
1363 ResultDocInfo_tarray::iterator secend = inforesponse.docInfo.end();
[1860]1364
[284]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) {
[649]1372 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
[9620]1373 if (shastxt == 1) ++seccount;
[284]1374 if (seccount > 10) break;
[9620]1375 ++sechere;
[267]1376 }
[284]1377 if (seccount > 10) {
1378 // more than 10 sections so output warning message and text
1379 // for current section only
[11153]1380 textout << outconvert << disp << "<div class=\"warning\">_document:textltwarning_</div>\n";
[443]1381
1382 output_text (thisdocinfo, formatlistptr, queryresponse.termInfo,
1383 OID, highlight, hastxt, wanttext, collection,
[4936]1384 collectproto, browsers, disp, outconvert, textout, logout, args);
[284]1385
1386 }
1387 else arg_gt = 2;
1388 }
[257]1389
[284]1390 if (arg_gt == 2) {
[267]1391 // get the text for each section
[284]1392 sechere = inforesponse.docInfo.begin();
1393 int count = 0;
1394 while (sechere != secend) {
[22047]1395 textout << outconvert << disp << "\n<p><a name=\"" << (*sechere).OID << "\"></a>\n";
[437]1396
[649]1397 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
[443]1398
[22047]1399
[443]1400 output_text (*sechere, formatlistptr, queryresponse.termInfo,
1401 (*sechere).OID, highlight, shastxt, wanttext, collection,
[4936]1402 collectproto, browsers, disp, outconvert, textout, logout, args);
[22047]1403
[9620]1404 ++count;
1405 ++sechere;
[267]1406 }
1407 }
1408 }
[257]1409 }
[11144]1410 textout << outconvert << "</div>\n";
[443]1411 delete formatlistptr;
[267]1412}
[4868]1413
[13967]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);
[22047]1440 set_fulltext_queryfilter_options (request, formattedstring, args);
[13967]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");
[22647]1465 metadata.insert ("gs.allowPrinting");
[13967]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
[20917]1492 textout << outconvert << disp << "<Description>\n";
1493
1494 textout << outconvert << disp << " <Metadata name=\"Title\">";
[13967]1495 text_t t_title = section.metadata["Title"].values[0];
[20917]1496
[13967]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 //}
[20917]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
[22647]1514 if (section.metadata["gs.allowPrinting"].values.size()>0) {
1515 text_t opt_allowprint = section.metadata["gs.allowPrinting"].values[0];
[20917]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
[13967]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
[4868]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");
[7432]1579 if (!get_info(arg_d, args["c"], args["l"], metadata, false, collectproto, response, logout)) {
[4868]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) {
[7432]1590 get_children (get_parent(thisoid), args["c"], args["l"], metadata, false,
[4868]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) {
[7432]1603 get_children (previous_sibling, args["c"], args["l"], metadata, false,
[4868]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 }
[9620]1622 ++this_sibling;
[4868]1623 first = false;
1624 }
1625 thisoid = get_parent(thisoid);
[9620]1626 --parentcount;
[4868]1627 }
1628
1629 // work out values for next link
1630 if (haschildren) {
[11998]1631#ifndef DOCHANLE
[10873]1632 disp.setmacro ("httpnextarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1633 "&amp;d=" + arg_d + ".fc");
[11998]1634#else
1635 disp.setmacro ("httpnextarrow", "document", "_httpdocumenthandle_("+args["c"]+","+arg_d + ".fc)";
1636
1637#endif
1638
[4868]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()) {
[11998]1644#ifndef DOCHANLE
[10873]1645 disp.setmacro ("httpnextarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1646 "&amp;d=" + *h);
[11998]1647#else
1648 disp.setmacro ("httpnextarrow", "document", "_httpdocumenthandle_("+args["c"]+","+*h+")";
1649
1650#endif
1651
[4868]1652 break;
1653 }
[9620]1654 ++h;
[4868]1655 }
1656 }
1657
1658 // work out value for previous link
1659 if (!previous_sibling.empty()) {
[11998]1660#ifndef DOCHANDLE
[10873]1661 disp.setmacro ("httpprevarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1662 "&amp;d=" + previous_sibling);
[11998]1663#else
1664 disp.setmacro ("httpprevarrow", "document", "_httpdocumenthandle_("+args["c"]+","+ previous_sibling+")");
1665
1666#endif
1667
[4868]1668 } else {
1669 if (countchar(arg_d.begin(), arg_d.end(), '.')) {
[11998]1670#ifndef DOCHANDLE
[10873]1671 disp.setmacro ("httpprevarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1672 "&amp;d=" + get_parent(arg_d));
[11998]1673#else
1674 disp.setmacro ("httpprevarrow", "document", "_httpdocumenthandle_("+args["c"]+","+get_parent(arg_d)+")");
1675
1676#endif
1677
[4868]1678 }
1679 }
1680}
Note: See TracBrowser for help on using the repository browser.