source: trunk/gsdl/src/recpt/documentaction.cpp@ 11771

Last change on this file since 11771 was 11771, checked in by kjdon, 18 years ago

removed the dm arg from the date list classifier in navigation bar link. now we work it out when we are displaying a datelist

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 45.0 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 "browsetools.h"
30#include "OIDtools.h"
31#include "querytools.h"
32#include "unitool.h"
33#include "gsdltools.h"
34#include "highlighttext.h"
35
36documentaction::documentaction () {
37 recpt = NULL;
38
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.defaultstatus = cgiarginfo::weak;
47 arg_ainfo.argdefault = "p";
48 arg_ainfo.savedarginfo = cgiarginfo::must;
49 argsinfo.addarginfo (NULL, arg_ainfo);
50
51 arg_ainfo.shortname = "d";
52 arg_ainfo.longname = "document OID";
53 arg_ainfo.multiplechar = true;
54 arg_ainfo.defaultstatus = cgiarginfo::none;
55 arg_ainfo.argdefault = g_EmptyText;
56 arg_ainfo.savedarginfo = cgiarginfo::can;
57 argsinfo.addarginfo (NULL, arg_ainfo);
58
59 // whether or not a document should be retrieved from the
60 // library or the Web.
61 arg_ainfo.shortname = "il";
62 arg_ainfo.longname = "internal link preference";
63 arg_ainfo.multiplechar = false;
64 arg_ainfo.defaultstatus = cgiarginfo::weak;
65 arg_ainfo.argdefault = "l";
66 arg_ainfo.savedarginfo = cgiarginfo::must;
67 argsinfo.addarginfo (NULL, arg_ainfo);
68
69 arg_ainfo.shortname = "cl";
70 arg_ainfo.longname = "classification OID";
71 arg_ainfo.multiplechar = true;
72 arg_ainfo.defaultstatus = cgiarginfo::none;
73 arg_ainfo.argdefault = g_EmptyText;
74 arg_ainfo.savedarginfo = cgiarginfo::can;
75 argsinfo.addarginfo (NULL, arg_ainfo);
76
77 // in this action "gc" controls the expand/contract
78 // contents function
79 arg_ainfo.shortname = "gc";
80 arg_ainfo.longname = "expand contents";
81 arg_ainfo.multiplechar = false;
82 arg_ainfo.defaultstatus = cgiarginfo::weak;
83 arg_ainfo.argdefault = "0";
84 arg_ainfo.savedarginfo = cgiarginfo::can;
85 argsinfo.addarginfo (NULL, arg_ainfo);
86
87 // in this action "gt" controls the expand/contract
88 // text function 0 = not expanded, 1 = expand unless
89 // there are more than 10 sections containing text,
90 // 2 = expand all
91 arg_ainfo.shortname = "gt";
92 arg_ainfo.longname = "expand text";
93 arg_ainfo.multiplechar = false;
94 arg_ainfo.defaultstatus = cgiarginfo::weak;
95 arg_ainfo.argdefault = "0";
96 arg_ainfo.savedarginfo = cgiarginfo::can;
97 argsinfo.addarginfo (NULL, arg_ainfo);
98
99 // in this action "gp" is the "go to page" control
100 // used by the Book type of toc
101 arg_ainfo.shortname = "gp";
102 arg_ainfo.longname = "go to page";
103 arg_ainfo.multiplechar = true;
104 arg_ainfo.defaultstatus = cgiarginfo::none;
105 arg_ainfo.argdefault = g_EmptyText;
106 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
107 argsinfo.addarginfo (NULL, arg_ainfo);
108
109 // in this action "hl" is the "highlighting on/
110 // highlighting off control ("hl" == "2" is a
111 // special case that forces phrase highlighting
112 // to be used even if the query string doesn't
113 // appear to be a phrase)
114 arg_ainfo.shortname = "hl";
115 arg_ainfo.longname = "highlighting on/off";
116 arg_ainfo.multiplechar = false;
117 arg_ainfo.defaultstatus = cgiarginfo::weak;
118 arg_ainfo.argdefault = "1";
119 arg_ainfo.savedarginfo = cgiarginfo::must;
120 argsinfo.addarginfo (NULL, arg_ainfo);
121
122 // "x" is 0 normally or 1 if page
123 // has been "detached"
124 arg_ainfo.shortname = "x";
125 arg_ainfo.longname = "detached page";
126 arg_ainfo.multiplechar = false;
127 arg_ainfo.defaultstatus = cgiarginfo::weak;
128 arg_ainfo.argdefault = "0";
129 arg_ainfo.savedarginfo = cgiarginfo::must;
130 argsinfo.addarginfo (NULL, arg_ainfo);
131
132 // "xx" is 0 normally or 1 if documents should be detached by default
133 arg_ainfo.shortname = "xx";
134 arg_ainfo.longname = "detach all doc pages";
135 arg_ainfo.multiplechar = 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
142 // f arg is set to 1 if document is to
143 // be displayed in a frame
144 arg_ainfo.shortname = "f";
145 arg_ainfo.longname = "frame";
146 arg_ainfo.multiplechar = false;
147 arg_ainfo.defaultstatus = cgiarginfo::weak;
148 arg_ainfo.argdefault = "0";
149 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
150 argsinfo.addarginfo (NULL, arg_ainfo);
151
152 // fc arg is "1" if search bar is to be included (i.e. if "fc" == 1
153 // the httpdocument macro will include "&f=1"
154 arg_ainfo.shortname = "fc";
155 arg_ainfo.longname = "include search bar";
156 arg_ainfo.multiplechar = false;
157 arg_ainfo.defaultstatus = cgiarginfo::weak;
158 arg_ainfo.argdefault = "1";
159 arg_ainfo.savedarginfo = cgiarginfo::must;
160 argsinfo.addarginfo (NULL, arg_ainfo);
161
162 //rd is whether a document will be displayed
163 //with a relevant document list
164 arg_ainfo.shortname = "rd";
165 arg_ainfo.longname = "include relevant documents";
166 arg_ainfo.multiplechar = false;
167 arg_ainfo.defaultstatus = cgiarginfo::weak;
168 arg_ainfo.argdefault = "0";
169 arg_ainfo.savedarginfo = cgiarginfo::must;
170 argsinfo.addarginfo (NULL, arg_ainfo);
171
172 //dm is the metadata that has been used for the datelist
173 arg_ainfo.shortname = "dm";
174 arg_ainfo.longname = "date metadata";
175 arg_ainfo.multiplechar = true;
176 arg_ainfo.defaultstatus = cgiarginfo::weak;
177 arg_ainfo.argdefault = g_EmptyText;
178 arg_ainfo.savedarginfo = cgiarginfo::must;
179 argsinfo.addarginfo (NULL, arg_ainfo);
180
181}
182
183documentaction::~documentaction () {
184}
185
186bool documentaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
187 recptprotolistclass *protos, ostream &logout) {
188
189 if(!args["d"].empty())
190 {
191 text_t docTop;
192 get_top(args["d"],docTop);
193
194 recptproto* collectproto = protos->getrecptproto (args["c"], logout);
195 if (collectproto != NULL)
196 {
197 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
198
199 if(cinfo->authenticate == "document")
200 {
201 // both are either commented out or uncomment and are empty
202 if (cinfo->public_documents.empty() && cinfo->private_documents.empty())
203 {
204 //deny everything
205 args["uan"] = "1";
206 args["ug"] = cinfo->auth_group;
207 }
208
209 // both public_documents and private_documents are turned on !
210 else if (!cinfo->public_documents.empty() && !cinfo->private_documents.empty())
211 {
212 //deny everything
213 args["uan"] = "1";
214 args["ug"] = cinfo->auth_group;
215 }
216
217 // if public_documents is set but this document isn't
218 // listed in it we need to authenticate
219 else if ((!cinfo->public_documents.empty()) &&
220 (cinfo->public_documents.find(docTop) == cinfo->public_documents.end()))
221 {
222 args["uan"] = "1";
223 args["ug"] = cinfo->auth_group;
224 }
225
226 // if private_documents is set and this document is
227 // listed in it we need to authenticate
228 else if ((!cinfo->private_documents.empty()) &&
229 (cinfo->private_documents.find(docTop) != cinfo->private_documents.end()))
230 {
231 args["uan"] = "1";
232 args["ug"] = cinfo->auth_group;
233 }
234
235 }
236 }
237 }
238 // check gc argument
239 int arg_gc = args.getintarg("gc");
240 if (arg_gc < 0 || arg_gc > 2) {
241 logout << "Warning: \"gc\" argument out of range (" << arg_gc << ")\n";
242 cgiarginfo *gcinfo = argsinfo.getarginfo ("gc");
243 if (gcinfo != NULL) args["gc"] = gcinfo->argdefault;
244 }
245
246 // check gt argument (may be either 0, 1 or 2)
247 int arg_gt = args.getintarg("gt");
248 if (arg_gt != 0 && arg_gt != 1 && arg_gt != 2) {
249 logout << "Warning: \"gt\" argument out of range (" << arg_gt << ")\n";
250 cgiarginfo *gtinfo = argsinfo.getarginfo ("gt");
251 if (gtinfo != NULL) args["gt"] = gtinfo->argdefault;
252 }
253
254 // check hl argument
255 int arg_hl = args.getintarg("hl");
256 if (arg_hl < 0 || arg_hl > 2) {
257 logout << "Warning: \"hl\" argument out of range (" << arg_hl << ")\n";
258 cgiarginfo *hlinfo = argsinfo.getarginfo ("hl");
259 if (hlinfo != NULL) args["hl"] = hlinfo->argdefault;
260 }
261
262 // check x argument
263 int arg_x = args.getintarg("x");
264 if (arg_x != 0 && arg_x != 1) {
265 logout << "Warning: \"x\" argument out of range (" << arg_x << ")\n";
266 cgiarginfo *xinfo = argsinfo.getarginfo ("x");
267 if (xinfo != NULL) args["x"] = xinfo->argdefault;
268 }
269
270 //checks whether rd arg is valid
271 int arg_rd = args.getintarg("rd");
272 if (arg_rd != 0 && arg_rd != 1) {
273 logout << "Warning: \"rd\" argument out of range (" << arg_rd << ")\n";
274 cgiarginfo *rdinfo = argsinfo.getarginfo ("rd");
275 if (rdinfo != NULL) args["rd"] = rdinfo->argdefault;
276 }
277
278
279 return true;
280}
281
282void documentaction::get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
283 response_t &response,text_t &response_data,
284 ostream &logout) {
285
286 if ((args["il"] == "w") && (!args["d"].empty())) {
287
288 recptproto* collectproto = protos->getrecptproto (args["c"], logout);
289 if (collectproto != NULL) {
290
291 text_tset metadata;
292 FilterResponse_t filt_response;
293 text_t top;
294
295 metadata.insert ("URL");
296
297 // get metadata for parent document
298 get_top (args["d"], top);
299 if (get_info (top, args["c"], args["l"], metadata, false, collectproto, filt_response, logout)) {
300 text_t url = filt_response.docInfo[0].metadata["URL"].values[0];
301
302 response = location;
303 response_data = url;
304 return;
305 } else {
306 // error, no URL
307 logout << "Error: documentaction::get_cgihead_info failed on get_info" << endl;
308 }
309 }
310 }
311 response = content;
312 response_data = "text/html";
313}
314
315// set_widthtspace calculates how wide the spaces in the nav bar should
316// be and sets the appropriate macro
317void documentaction::set_spacemacro (displayclass &disp, FilterResponse_t &response,
318 bool has_search_button) {
319
320 text_t width;
321 int twidth, swidth, iwidth = 0;
322
323 int numc = response.docInfo.size();
324 ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
325 ResultDocInfo_tarray::iterator docend = response.docInfo.end();
326
327 disp.expandstring (displayclass::defaultpackage, "_pagewidth_", width);
328 twidth = width.getint();
329
330 if (has_search_button) {
331 disp.expandstring ("query", "_searchwidth_", width);
332 iwidth += width.getint();
333 } else {
334 numc -= 1;
335 }
336
337 while (dochere != docend) {
338 const text_t &title = (*dochere).metadata["Title"].values[0];
339
340 disp.expandstring ("document", "_" + title + "width_", width);
341 if (width == ("_" + title + "width_")) {
342 disp.expandstring ("document", "_defaultwidth_", width);
343 }
344 iwidth += width.getint();
345 ++dochere;
346 }
347
348 if ((twidth - iwidth) < numc) swidth = 2;
349 else {
350 swidth = twidth - iwidth;
351 if (numc > 0) swidth = swidth / numc;
352 }
353 disp.setmacro ("widthtspace", displayclass::defaultpackage, swidth);
354}
355
356// set_navbarmacros sets _navigationbar_ and _httpbrowseXXX_ macros
357// reponse contains 1 metadata field (Title)
358void documentaction::set_navbarmacros (displayclass &disp, FilterResponse_t &response,
359 bool has_search_button, cgiargsclass &args,
360 ColInfoResponse_t &cinfo) {
361
362
363 bool use_pulldown = false;
364 text_tmap::iterator it = cinfo.format.find("NavigationBar");
365 if (it != cinfo.format.end()) {
366 if (it->second == "pulldown") {
367 use_pulldown = true;
368 }
369 }
370
371 text_t topparent;
372 text_t &arg_d = args["d"];
373 text_t navigationbar = "<!-- Navigation Bar -->\n";
374
375 get_top (args["cl"], topparent);
376 int numc = response.docInfo.size();
377 ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
378 ResultDocInfo_tarray::iterator docend = response.docInfo.end();
379
380 if (!use_pulldown) {
381 if (has_search_button) {
382 navigationbar += "_navtabsearch_";
383 if (args["a"] == "q") {
384 navigationbar += "(selected)";
385 }
386 }
387
388 if (has_search_button || numc == 0) navigationbar += "_navbarspacer_";
389
390 bool first = true;
391 while (dochere != docend) {
392 if (!first) navigationbar += "_navbarspacer_";
393
394 bool unknown = false;
395
396 // test if the _tabtext$FIELD_ macro is defined, which means
397 // this is a "known" metadata type and we have a translation for it
398 text_t title = (*dochere).metadata["Title"].values[0];
399 text_t tmpwidth;
400 text_t macroname="_tabtext" + title + "_";
401 disp.expandstring ("document", macroname, tmpwidth);
402 if (tmpwidth == macroname) // it wasn't expanded
403 unknown = true;
404
405 // if we're inside a document all the classification buttons should be enabled
406 text_t this_tab;
407 bool is_top;
408
409 is_top = ((*dochere).OID == topparent);
410 // set default text fragment
411 this_tab = "_navtab_(";
412
413 if (unknown) { // just give the field name
414 if (!arg_d.empty() || !is_top) {
415 // work out the link for this classifier, as it isn't the
416 // current page
417 this_tab += "_httpdocument_&amp;cl=" + (*dochere).OID;
418 }
419 this_tab += "," + title + "," + title;
420 } else { // use the macro for this field so we get translations
421 this_tab += "_httpbrowse" + title;
422 this_tab += "_,_tabtext" + title;
423 this_tab += "_,_textdescr" + title + "_";
424 }
425
426 if (arg_d.empty() && is_top) {
427 // don't link to this classifier as it is the current one
428 this_tab += ",selected";
429 }
430
431 // set the _httpbrowseXXX_ macro for this classification
432 // set the correct url for this link
433 disp.setmacro ("httpbrowse" + title, displayclass::defaultpackage, "_httpdocument_&amp;cl=" + (*dochere).OID);
434
435
436 this_tab += ")";
437
438 navigationbar += this_tab;
439
440 ++dochere;
441 first = false;
442 }
443
444 //if (!has_search_button && numc == 1) navigationbar += "_navbarspacer_";
445
446 navigationbar += "\n<!-- End of Navigation Bar -->\n";
447
448 } else {
449
450 navigationbar = "<form method=\"get\" name=\"navform\">\n";
451 navigationbar += "<select name=\"navbar\" onChange=\"location.href=";
452 navigationbar += "document.navform.navbar.options[document.navform.navbar.selectedIndex].value\">\n";
453
454 if (args["a"] != "q" && args["cl"].empty()) {
455 navigationbar += "<option value=\"\" selected>_textselectpage_</option>\n";
456 }
457
458 if (has_search_button) {
459 navigationbar += "<option value=\"_httpquery_\"";
460 if (args["a"] == "q") {
461 navigationbar += " selected";
462 }
463 navigationbar += ">_labelSearch_</option>\n";
464 }
465
466 while (dochere != docend) {
467 text_t title = dochere->metadata["Title"].values[0];
468
469 navigationbar += "<option value=\"_httpdocument_&amp;cl=" + dochere->OID + "\"";
470 if (topparent == dochere->OID) {
471 navigationbar += " selected";
472 }
473 navigationbar += ">" + title + "</option>\n";
474 ++dochere;
475 }
476
477 navigationbar += "</select>\n";
478 navigationbar += "</form>\n";
479 }
480
481 disp.setmacro ("navigationbar", displayclass::defaultpackage, navigationbar);
482}
483
484// define all the macros which might be used by other actions
485// to produce pages.
486void documentaction::define_external_macros (displayclass &disp, cgiargsclass &args,
487 recptprotolistclass *protos, ostream &logout) {
488
489 // define_external_macros sets the following macros:
490
491 // _navigationbar_ this is the navigation bar containing the search button
492 // and any classification buttons - it goes at the top of
493 // most pages. for now we're assuming that there'll always
494 // be a search button - we should probably check that there
495 // is a query action before making this assumption
496
497 // _httpbrowseXXX_ the http macros for each classification (i.e. if there
498 // are Title and Creator classifications _httpbrowseTitle_
499 // and _httpbrowseCreator_ will be set
500
501 // _widthtspace_ the width of the spacers between buttons in navigation
502 // bar
503
504 // _httpdocument_ has '&f=1' added if displaying document inside a frame
505
506 // _gsdltop_ macro to replace _top targets with
507
508 // _httppagehome_ overridden home url if html collections have own homepage
509
510 // _usability_ macros for remote usability reporting: if
511 // _usabinterface_ "format Usability [multi|textonly|stepwise]" is in
512 // _usabilityscript_ collect.cfg
513
514 // must have a valid collection server to continue
515
516 text_t &collection = args["c"];
517 if (collection.empty()) return;
518 recptproto *collectproto = protos->getrecptproto (collection, logout);
519 if (collectproto == NULL) return;
520
521 if (recpt == NULL) {
522 logout << "ERROR (documentaction::define_external_macros): This action does not contain\n"
523 << " information about any receptionists. The method set_receptionist was\n"
524 << " probably not called from the module which instantiated this action.\n";
525 return;
526 }
527
528 outconvertclass text_t2ascii;
529 comerror_t err;
530 InfoFiltersResponse_t filterinfo;
531 FilterResponse_t response;
532 text_tset metadata;
533
534 // get info on current collection and load up formatinfo
535 // I'd prefer not to do this here as we're getting
536 // collection info every time (and probably also getting
537 // it in other places some of the time) - One day I'll
538 // fix it ... maybe - Stefan.
539 ColInfoResponse_t cinfo;
540
541 collectproto->get_collectinfo (collection, cinfo, err, logout);
542 load_formatinfo (cinfo.format, args.getintarg("gt"));
543 // ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, collection, logout);
544 // if (cinfo == NULL) {
545 // logout << "ERROR (documentaction::define_external_macros): get_collectinfo_ptr returned NULL\n";
546 // return;
547 // }
548 //load_formatinfo (cinfo->format, args.getintarg("gt"));
549
550 if (formatinfo.DocumentUseHTML) {
551
552 // frame stuff
553 if (args["fc"] == "1") {
554 text_t httpdocument;
555 disp.expandstring (displayclass::defaultpackage, "_httpdocument_", httpdocument);
556 httpdocument += "&amp;f=1";
557 disp.setmacro ("httpdocument", displayclass::defaultpackage, httpdocument);
558 disp.setmacro ("gsdltop", displayclass::defaultpackage, "documenttop");
559 formatinfo.DocumentText = "[Text]";
560 }
561 text_tmap::iterator it = cinfo.format.find ("homepage");
562 if (it != cinfo.format.end()) {
563 text_t httppagehome;
564 if (get_link (args, protos, (*it).second, httppagehome, logout))
565 disp.setmacro ("httppagehome", displayclass::defaultpackage, httppagehome);
566 }
567 }
568
569 // don't want navigation bar if page is 'detached'
570 if (!args.getintarg("x")) {
571
572 collectproto->get_filterinfo (collection, filterinfo, err, logout);
573 if (err == noError) {
574 // check that there's a browse filter
575 if (filterinfo.filterNames.find ("BrowseFilter") != filterinfo.filterNames.end()) {
576
577 metadata.insert ("Title");
578 bool getParents = false;
579 get_children ("", collection, args["l"], metadata, getParents, collectproto, response, logout);
580
581 bool has_search_button = true;
582 collectproto->is_searchable(collection, has_search_button, err, logout);
583 if (err != noError) has_search_button = false;
584
585 // calculate width of spacers and set _widthtspace_ macro
586 if (args.getintarg("v") == 0) set_spacemacro (disp, response, has_search_button);
587
588 // set _navigationbar_ macro
589 set_navbarmacros (disp, response, has_search_button, args, cinfo);
590
591 }
592 } else {
593 logout << text_t2ascii
594 << "Error (documentaction::define_external_macros()) in call to get_filterinfo() "
595 << get_comerror_string (err);
596 }
597 }
598
599 // send feedback button and pages
600 text_tmap::iterator usability = cinfo.format.find("Usability");
601 if(usability!=cinfo.format.end()){
602 disp.setmacro("usability",displayclass::defaultpackage,"_usablink_");
603 disp.setmacro("usabinterface",displayclass::defaultpackage,("_usab"+(*usability).second+"_"));
604 disp.setmacro("usabilityscript", displayclass::defaultpackage, "_usabshowscript_");
605 }
606
607}
608
609bool documentaction::get_link (cgiargsclass &args, recptprotolistclass *protos,
610 const text_t &inlink, text_t &outlink, ostream &logout) {
611
612 FilterResponse_t response;
613 text_tset metadata;
614 metadata.insert ("section");
615
616 // check current collection first
617 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
618
619 if (get_info (inlink, args["c"], args["l"], metadata, false, collectproto, response, logout)) {
620 if (!response.docInfo[0].metadata["section"].values[0].empty()) {
621 outlink = "_httpdocument_&amp;d=" + response.docInfo[0].metadata["section"].values[0];
622 return true;
623 }
624 }
625
626 // check all the other enabled collections
627
628 if (args["ccs"] == "1" && !args["cc"].empty()) {
629 text_tarray collections;
630 splitchar (args["cc"].begin(), args["cc"].end(), ',', collections);
631
632 text_tarray::const_iterator col_here = collections.begin();
633 text_tarray::const_iterator col_end = collections.end();
634
635 while (col_here != col_end) {
636
637 // don't need to check current collection again
638 if (*col_here == args["c"]) {++col_here; continue;}
639
640 collectproto = protos->getrecptproto (*col_here, logout);
641
642 if (get_info (inlink, *col_here, args["l"], metadata, false, collectproto, response, logout)) {
643 if (!response.docInfo[0].metadata["section"].values[0].empty()) {
644 outlink = "_httpdocument_&amp;c=" + *col_here + "&amp;d=" +
645 response.docInfo[0].metadata["section"].values[0];
646 return true;
647 }
648 }
649 ++col_here;
650 }
651 }
652 return false;
653}
654
655void documentaction::load_formatinfo (const text_tmap &colformat, int gt) {
656
657 formatinfo.clear();
658 text_tmap::const_iterator format_here = colformat.begin();
659 text_tmap::const_iterator format_end = colformat.end();
660
661 while (format_here != format_end) {
662 if (((*format_here).first == "DocumentImages") &&
663 ((*format_here).second == "true"))
664 formatinfo.DocumentImages = true;
665 else if (((*format_here).first == "DocumentTitles") &&
666 ((*format_here).second == "false"))
667 formatinfo.DocumentTitles = false;
668 else if ((*format_here).first == "DocumentHeading")
669 formatinfo.DocumentHeading = (*format_here).second;
670 else if (((*format_here).first == "DocumentContents") &&
671 ((*format_here).second == "false"))
672 formatinfo.DocumentContents = false;
673 else if (((*format_here).first == "DocumentArrowsBottom") &&
674 ((*format_here).second == "false"))
675 formatinfo.DocumentArrowsBottom = false;
676 else if (((*format_here).first == "DocumentArrowsTop") &&
677 ((*format_here).second == "true"))
678 formatinfo.DocumentArrowsTop = true;
679 else if ((*format_here).first == "DocumentButtons")
680 splitchar ((*format_here).second.begin(), (*format_here).second.end(),
681 '|', formatinfo.DocumentButtons);
682 else if ((*format_here).first == "DocumentText")
683 formatinfo.DocumentText = (*format_here).second;
684 else if ((*format_here).first == "RelatedDocuments")
685 formatinfo.RelatedDocuments = (*format_here).second;
686 else if (((*format_here).first == "DocumentUseHTML") &&
687 ((*format_here).second == "true"))
688 formatinfo.DocumentUseHTML = true;
689 else if (((*format_here).first == "AllowExtendedOptions") &&
690 ((*format_here).second == "true"))
691 formatinfo.AllowExtendedOptions = true;
692 else
693 formatinfo.formatstrings[(*format_here).first] = (*format_here).second;
694
695 ++format_here;
696 }
697
698 // never want arrows when text is expanded
699 if (gt) {
700 formatinfo.DocumentArrowsBottom = false;
701 formatinfo.DocumentArrowsTop = false;
702 }
703}
704
705
706// define all the macros which are related to pages generated
707// by this action. we also load up the formatinfo structure
708// here (it's used in do_action as well as here)
709void documentaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
710 recptprotolistclass *protos, ostream &logout) {
711
712 // define_internal_macros sets the following macros:
713
714 // _pagetitle_ the title to be displayed at the top of the browser window
715
716 // _imagethispage_ the title image to be displayed at top right of page
717
718 // _navarrowsbottom_ this may be overridden to "" when format option
719 // DocumentArrowsBottom is false
720
721 // _navarrowstop_ likewise for DocumentArrowsTop
722
723 // _httpprevarrow_ links to next and previous sections of document - used
724 // _httpnextarrow_ by DocumentArrowsBottom
725
726 // _header_ the header macro is overridden if we're not at a top level
727 // classification to remove the title block
728
729 // _thisOID_ the OID (directory) of the current document - this corresponds
730 // to the archivedir metadata element
731
732 // must have a valid collection server to continue
733
734 text_t &collection = args["c"];
735 if (collection.empty()) return;
736 recptproto *collectproto = protos->getrecptproto (collection, logout);
737 if (collectproto == NULL) return;
738
739 text_tset metadata;
740 FilterResponse_t response;
741 text_t &arg_d = args["d"];
742 text_t &arg_cl = args["cl"];
743
744 if (!formatinfo.DocumentArrowsBottom) {
745 disp.setmacro("navarrowsbottom", "document", "");
746 } else if (!formatinfo.DocumentArrowsBottom) {
747 disp.setmacro("navarrowstop", "document", "");
748 }
749
750 if (!arg_d.empty() && (formatinfo.DocumentArrowsBottom || formatinfo.DocumentArrowsTop)) {
751 // set _httpprevarrow_ and _httpnextarrow_
752 set_arrow_macros (args, collectproto, disp, logout);
753 }
754
755 metadata.insert ("Title");
756
757 bool fulltoc = false;
758
759 if (args["cl"] != "search") {
760 // see if there's a FullTOC string
761 text_t cl_top, full_toc;
762 get_top (arg_cl, cl_top);
763 if (get_formatstring (cl_top, "FullTOC", formatinfo.formatstrings, full_toc))
764 if (full_toc == "true") fulltoc = true;
765 }
766
767 if (!arg_d.empty() && !fulltoc) {
768 // we're at document level
769
770 metadata.insert ("archivedir");
771
772 comerror_t err;
773 OptionValue_tarray options;
774 // we need to do the query again for the z3950proto
775 if (collectproto->get_protocol_name(err)=="z3950proto") {
776 OptionValue_t opt;
777 opt.name="Term";opt.value=args["q"];options.push_back(opt);
778 opt.name="QueryType";
779 opt.value=(args.getintarg("t")) ? "ranked" : "boolean";
780 options.push_back(opt);
781 opt.name="Index";opt.value=args["h"];options.push_back(opt);
782 }
783
784 //do not display relation metadata
785 disp.setmacro ("relateddoc", "document", "");
786
787 //if preferences indicate relevant docs should be collected
788 //and there is no particular format specified then display
789 //this default format.
790 if(args["rd"] == "1" && formatinfo.RelatedDocuments.empty()){
791
792 text_t relation = g_EmptyText; //string for displaying relation metadata
793
794 //call function in formattools.cpp which will return the text of the
795 //related documents in a vertical list. This is the default format.
796
797 if (get_info (arg_d, collection, args["l"], metadata, options, false, collectproto, response, logout))
798 relation += get_related_docs(collection, collectproto, response.docInfo[0], logout);
799
800 //set macro to be the related document string
801
802 disp.setmacro ("relateddoc", "document", relation);
803 }
804
805
806 // get metadata for this document and it's parents
807 if (get_info (arg_d, collection, args["l"], metadata, options,
808 true, collectproto, response, logout)) {
809
810 disp.setmacro ("header", "document", "_textheader_");
811
812 text_tarray pagetitlearray;
813 if (!response.docInfo[0].metadata["Title"].values[0].empty())
814 pagetitlearray.push_back (response.docInfo[0].metadata["Title"].values[0]);
815
816 if (args["gt"] != "1") {
817 MetadataInfo_t *parenttitle = response.docInfo[0].metadata["Title"].parent;
818 while (parenttitle != NULL) {
819 if (!parenttitle->values[0].empty())
820 pagetitlearray.push_back (parenttitle->values[0]);
821 parenttitle = parenttitle->parent;
822 }
823 }
824 reverse (pagetitlearray.begin(), pagetitlearray.end());
825 text_t pagetitle;
826 joinchar (pagetitlearray, ": ", pagetitle);
827 // remove html tags from the title
828 text_t::iterator open_tag=pagetitle.begin();
829 while (open_tag < pagetitle.end()) {
830 if (*open_tag == '<') {
831 text_t::iterator close_tag=open_tag+1;
832 text_t::iterator donechar=pagetitle.end();
833 while (close_tag < donechar) {
834 if (*close_tag == '>')
835 break;
836 ++close_tag;
837 }
838 if (close_tag < donechar) // remove this html tag, replace with space
839 *close_tag=' ';
840 pagetitle.erase(open_tag, close_tag);
841 }
842 ++open_tag;
843 }
844 disp.setmacro ("pagetitle", "document", pagetitle);
845
846 if (is_top (arg_d))
847 disp.setmacro ("thisOID", displayclass::defaultpackage, dm_safe(response.docInfo[0].metadata["archivedir"].values[0]));
848 else {
849 MetadataInfo_t *parentad = response.docInfo[0].metadata["archivedir"].parent;
850 text_t thisOID;
851 while (parentad != NULL) {
852 thisOID = parentad->values[0];
853 parentad = parentad->parent;
854 }
855 disp.setmacro ("thisOID", displayclass::defaultpackage, dm_safe(thisOID));
856 }
857 }
858 } else {
859 if (!arg_cl.empty()) {
860
861 // create the currentnodevalue macro - this is the value of the node
862 // in the hierarchy that is currently open.
863 if (get_info (arg_cl, collection, args["l"], metadata, false, collectproto, response, logout)) {
864 text_t &title = response.docInfo[0].metadata["Title"].values[0];
865 disp.setmacro ("currentnodevalue", "document", title);
866 }
867 // get metadata for top level classification
868 text_t classtop;
869 get_top (arg_cl, classtop);
870 metadata.insert ("childtype");
871 metadata.insert ("parameters");
872
873 if (get_info (classtop, collection, args["l"], metadata, false, collectproto, response, logout)) {
874
875 text_t &title = response.docInfo[0].metadata["Title"].values[0];
876 bool unknown = false;
877
878 // test if we have macros defined for this classification's
879 // metadata name - if not we'll just display the name
880 text_t tmp;
881 text_t macroname="_label" + title + "_";
882 disp.expandstring ("Global", macroname, tmp);
883 if (tmp == macroname) unknown = true; // it wasn't expanded
884
885 if (unknown) {
886 disp.setmacro ("pagetitle", "document", title);
887 } else {
888 disp.setmacro ("pagetitle", "document", macroname);
889 }
890 /* for ns4/image layout compatibility. when this is no longer
891 * needed, set imagethispage to _label+title+_ */
892 text_t titlemacroname="_titleimage" + title + "_";
893 disp.expandstring ("Global", titlemacroname, tmp);
894 if (tmp == titlemacroname) { /* _titleimage$META_ isn't defined */
895 if (!unknown) /* _label$META_ is defined */
896 disp.setmacro ("imagethispage", "document", macroname);
897 else
898 disp.setmacro ("imagethispage", "document", title);
899 } else { /* _titleimage$META_ is defined */
900 disp.setmacro ("imagethispage", "document", titlemacroname);
901 }
902
903 //if the document is not a document from a collection
904 //we must set the macro to be an empty string
905 disp.setmacro ("relateddoc", "document", "");
906
907 // Add macros specific to the Collage/Phind classifiers
908 text_t &childtype = response.docInfo[0].metadata["childtype"].values[0];
909 if (childtype == "Collage") {
910
911 text_t::iterator a = arg_cl.begin();
912 text_t::iterator b = arg_cl.end();
913
914 bool collage = true;
915 while (a != b) {
916 if (*a == 46) collage = false;
917 ++a;
918 }
919
920 if (collage) {
921 disp.setmacro ("collageclassifier", "document", "_collageapplet_");
922
923 // Next, macros that control the way the classifier is displayed
924 text_t parameters = response.docInfo[0].metadata["parameters"].values[0];
925
926 // extract key=value pairs and set as macros
927 text_t::iterator here = parameters.begin();
928 text_t::iterator end = parameters.end();
929 text_t key, value;
930
931 while (here != end) {
932 // get the next key and value pair
933 here = getdelimitstr (here, end, '=', key);
934 here = getdelimitstr (here, end, ';', value);
935
936 // store this key=value pair
937 if (!key.empty() && !value.empty()) {
938 disp.setmacro ("collage"+key, "document", value);
939 }
940 }
941
942
943 }
944 }
945
946 if (childtype == "Phind") {
947
948 // First, a macro to display the phind classifier
949 disp.setmacro ("phindclassifier", "document", "_phindapplet_");
950
951 // Next, macros that control the way the classifier is displayed
952 text_t parameters = response.docInfo[0].metadata["parameters"].values[0];
953
954 // extract key=value pairs and set as macros
955 text_t::iterator here = parameters.begin();
956 text_t::iterator end = parameters.end();
957 text_t key, value;
958
959 while (here != end) {
960 // get the next key and value pair
961 here = getdelimitstr (here, end, '=', key);
962 here = getdelimitstr (here, end, ';', value);
963
964 // store this key=value pair
965 if (!key.empty() && !value.empty()) {
966 disp.setmacro (key, "document", value);
967 }
968 }
969 } // end if (childtype == "Phind")
970 }
971 } // end if (!arg_cl.empty()) {
972 }
973}
974
975
976bool documentaction::do_action (cgiargsclass &args, recptprotolistclass *protos,
977 browsermapclass *browsers, displayclass &disp,
978 outconvertclass &outconvert, ostream &textout,
979 ostream &logout) {
980
981 // must have a valid collection server
982 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
983 if (collectproto == NULL) {
984 logout << "documentaction::do_action called with NULL collectproto\n";
985 textout << outconvert << disp << "_document:header_\n"
986 << "Error: Attempt to get document without setting collection\n"
987 << "_document:footer_\n";
988 } else {
989
990 text_t OID = args["d"];
991 if (OID.empty()) OID = args["cl"];
992 if (OID.empty()) {
993 textout << outconvert << disp << "Document contains no data_document:footer_\n";
994 return true;
995 }
996
997
998 if (formatinfo.DocumentUseHTML && !args["d"].empty()) {
999
1000 if (args["f"] == "1") {
1001 textout << outconvert << disp
1002 << "<html><head></head>\n"
1003 << "<frameset rows=\"68,*\" noresize border=0>\n"
1004 << "<frame scrolling=no frameborder=0 src=\"_gwcgi_?_optsite_e=_compressedoptions_&a=p&p=nav\">\n"
1005 << "<frame name=\"documenttop\" frameborder=0 src=\"_gwcgi_?_optsite_e=_compressedoptions_&a=d&d="
1006 << args["d"] << "\">"
1007 << "<noframes>\n"
1008 << "<p>You must have a frame enabled browser to view this.</p>\n"
1009 << "</noframes>\n"
1010 << "</frameset>\n"
1011 << "</html>\n";
1012 } else {
1013 output_document (OID, args, collectproto, browsers, disp, outconvert, textout, logout);
1014 }
1015 return true;
1016 }
1017
1018
1019 textout << outconvert << disp << "_document:header_\n"
1020 << "_document:content_\n";
1021
1022 // output the table of contents
1023 output_toc (args, browsers, formatinfo, collectproto,
1024 disp, outconvert, textout, logout);
1025
1026 if (formatinfo.DocumentArrowsTop && !args["d"].empty()) {
1027 textout << outconvert << disp << "_document:navarrowstop_\n";
1028 }
1029
1030 //output the related documents (may be the empty string)
1031 //will not output the docs if a format string is specified
1032 textout << outconvert << disp << "_document:relateddoc_\n";
1033
1034 // output the document text
1035 if (!args["d"].empty()) {
1036 textout << outconvert << "<p>\n";
1037 output_document (OID, args, collectproto, browsers, disp, outconvert, textout, logout);
1038 }
1039
1040 textout << outconvert << disp << "_document:footer_\n";
1041 }
1042 return true;
1043}
1044
1045void documentaction::output_text (ResultDocInfo_t &docinfo, format_t *formatlistptr,
1046 const TermInfo_tarray &terminfo, const text_t &OID,
1047 bool highlight, int hastxt, int wanttext,
1048 text_t &collection, recptproto *collectproto,
1049 browsermapclass *browsers, displayclass &disp,
1050 outconvertclass &outconvert, ostream &textout,
1051 ostream &logout, cgiargsclass &args) {
1052
1053 DocumentRequest_t docrequest;
1054 DocumentResponse_t docresponse;
1055 comerror_t err;
1056 if (hastxt == 1) {
1057
1058 if (wanttext) {
1059 // get the text
1060 docrequest.OID = OID;
1061 collectproto->get_document (collection, docrequest, docresponse, err, logout);
1062
1063 // cut down on overhead by not using formattools if we only want the text
1064 // (wanttext will equal 2 if we want text and other stuff too)
1065 if (wanttext == 1)
1066 if (highlight) {
1067 highlighttext(docresponse.doc, args, terminfo, disp, outconvert, textout);
1068 } else {
1069 textout << outconvert << disp << docresponse.doc;
1070 }
1071 }
1072
1073 if (wanttext != 1) {
1074 text_tmap options;
1075 options["text"] = docresponse.doc;
1076
1077 if (formatinfo.AllowExtendedOptions) {
1078 load_extended_options(options, args, browsers, formatinfo,
1079 collectproto, disp, outconvert, logout);
1080 }
1081
1082 text_t doctext
1083 = get_formatted_string (collection, collectproto, docinfo, disp,
1084 formatlistptr, options, logout);
1085
1086 if (highlight) {
1087 highlighttext(doctext, args, terminfo, disp, outconvert, textout);
1088 } else {
1089 textout << outconvert << disp << doctext;
1090 }
1091 }
1092 }
1093}
1094
1095
1096void documentaction::output_document (const text_t &OID, cgiargsclass &args,
1097 recptproto *collectproto, browsermapclass *browsers,
1098 displayclass &disp, outconvertclass &outconvert,
1099 ostream &textout, ostream &logout) {
1100 FilterResponse_t inforesponse;
1101 FilterResponse_t queryresponse;
1102 text_tset metadata;
1103 bool getParents = false;
1104 bool highlight = false;
1105 int wanttext = 0;
1106 int arg_gt = args.getintarg("gt");
1107 text_t &collection = args["c"];
1108
1109 // if we have a query string and highlighting is turned on we need
1110 // to redo the query to get the terms for highlighting
1111
1112 if (!args["q"].empty() && args.getintarg("hl")) {
1113
1114 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, collection, logout);
1115 bool segment = false;
1116 if (cinfo != NULL) {
1117 segment = cinfo->isSegmented;
1118 }
1119 FilterRequest_t request;
1120 comerror_t err;
1121 request.filterResultOptions = FRmatchTerms;
1122 text_t formattedstring = args["q"];
1123 format_querystring (formattedstring, args.getintarg("b"), segment);
1124 set_queryfilter_options (request, formattedstring, args);
1125 args["q"] = formattedstring; // need to set this here for phrase
1126 // highlighting, where we look at the querystring
1127 collectproto->filter (args["c"], request, queryresponse, err, logout);
1128 if (err != noError) {
1129 outconvertclass text_t2ascii;
1130 logout << text_t2ascii
1131 << "documentaction::output_document: call to QueryFilter failed "
1132 << "for " << args["c"] << " collection (" << get_comerror_string (err) << ")\n";
1133 highlight = false;
1134 } else {
1135 highlight = true;
1136 }
1137 }
1138
1139 format_t *formatlistptr = new format_t();
1140 parse_formatstring (formatinfo.DocumentText, formatlistptr, metadata, getParents);
1141
1142 metadata.insert ("hastxt");
1143 metadata.insert ("haschildren");
1144
1145 if (formatinfo.DocumentText == "[Text]")
1146 wanttext = 1;
1147 else {
1148 char *docformat = formatinfo.DocumentText.getcstr();
1149 if (strstr (docformat, "[Text]") != NULL)
1150 wanttext = 2;
1151 delete []docformat;
1152 }
1153
1154 textout << outconvert << "<div class=\"documenttext\">\n";
1155
1156 if (get_info (OID, collection, args["l"], metadata, getParents, collectproto, inforesponse, logout)) {
1157 int hastxt = inforesponse.docInfo[0].metadata["hastxt"].values[0].getint();
1158 int haschildren = inforesponse.docInfo[0].metadata["haschildren"].values[0].getint();
1159
1160 if (arg_gt == 0) {
1161 output_text (inforesponse.docInfo[0], formatlistptr, queryresponse.termInfo,
1162 OID, highlight, hastxt, wanttext, collection, collectproto,
1163 browsers, disp, outconvert, textout, logout, args);
1164
1165 } else {
1166
1167 ResultDocInfo_t thisdocinfo = inforesponse.docInfo[0];
1168
1169 // text is to be expanded
1170 text_t exOID = OID;
1171 if (haschildren != 1) exOID = get_parent (OID);
1172 if (exOID.empty()) exOID = OID;
1173
1174 // if we're not in a document (i.e. we're in a top level classification)
1175 // we need to pass "is_classify = true" to get_contents so that it
1176 // doesn't recurse all the way through each document in the classification
1177 bool is_classify = false;
1178 if (args["d"].empty()) is_classify = true;
1179
1180 get_contents (exOID, is_classify, metadata, collection, args["l"],
1181 collectproto, inforesponse, logout);
1182
1183 ResultDocInfo_tarray::iterator sechere = inforesponse.docInfo.begin();
1184 ResultDocInfo_tarray::iterator secend = inforesponse.docInfo.end();
1185
1186 if (arg_gt == 1) {
1187 // check if there are more than 10 sections containing text to be expanded -
1188 // if there are output warning message - this isn't a great way to do this
1189 // since the sections may be very large or very small - one day I'll fix it
1190 // -- Stefan.
1191 int seccount = 0;
1192 while (sechere != secend) {
1193 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
1194 if (shastxt == 1) ++seccount;
1195 if (seccount > 10) break;
1196 ++sechere;
1197 }
1198 if (seccount > 10) {
1199 // more than 10 sections so output warning message and text
1200 // for current section only
1201 textout << outconvert << disp << "<div class=\"warning\">_document:textltwarning_</div>\n";
1202
1203 output_text (thisdocinfo, formatlistptr, queryresponse.termInfo,
1204 OID, highlight, hastxt, wanttext, collection,
1205 collectproto, browsers, disp, outconvert, textout, logout, args);
1206
1207 }
1208 else arg_gt = 2;
1209 }
1210
1211 if (arg_gt == 2) {
1212 // get the text for each section
1213 sechere = inforesponse.docInfo.begin();
1214 int count = 0;
1215 while (sechere != secend) {
1216 textout << outconvert << disp << "\n<p><a name=" << (*sechere).OID << "></a>\n";
1217
1218 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
1219
1220 output_text (*sechere, formatlistptr, queryresponse.termInfo,
1221 (*sechere).OID, highlight, shastxt, wanttext, collection,
1222 collectproto, browsers, disp, outconvert, textout, logout, args);
1223 ++count;
1224 ++sechere;
1225 }
1226 }
1227 }
1228 }
1229 textout << outconvert << "</div>\n";
1230 delete formatlistptr;
1231}
1232
1233void documentaction::set_arrow_macros (cgiargsclass &args, recptproto *collectproto,
1234 displayclass &disp, ostream &logout) {
1235
1236 text_tset metadata;
1237 FilterResponse_t response;
1238 FilterResponse_t presponse;
1239
1240 int haschildren = 0;
1241 text_tarray next_siblings;
1242 text_t previous_sibling;
1243 text_t &arg_d = args["d"];
1244
1245 // get info on current section
1246 metadata.insert("haschildren");
1247 if (!get_info(arg_d, args["c"], args["l"], metadata, false, collectproto, response, logout)) {
1248 logout << "error 1 in documentaction::set_arrow_macros\n";
1249 return;
1250 }
1251 haschildren = response.docInfo[0].metadata["haschildren"].values[0].getint();
1252
1253 // get OIDs of next and previous siblings of current section and
1254 // all it's parents
1255 int parentcount = countchar(arg_d.begin(), arg_d.end(), '.');
1256 text_t thisoid = arg_d;
1257 while (parentcount > 0) {
1258 get_children (get_parent(thisoid), args["c"], args["l"], metadata, false,
1259 collectproto, response, logout);
1260 ResultDocInfo_tarray::iterator this_sibling = response.docInfo.begin();
1261 ResultDocInfo_tarray::iterator last_sibling = response.docInfo.end();
1262 bool first = true;
1263 while (this_sibling != last_sibling) {
1264 if ((*this_sibling).OID == thisoid) {
1265 if (!first && next_siblings.empty()) {
1266 previous_sibling = (*(this_sibling-1)).OID;
1267 int section_has_children = (*(this_sibling-1)).metadata["haschildren"].values[0].getint();
1268 // if previous sibling has children we need to recurse
1269 // down to the last descendant
1270 while (section_has_children) {
1271 get_children (previous_sibling, args["c"], args["l"], metadata, false,
1272 collectproto, presponse, logout);
1273 if (!presponse.docInfo.empty()) {
1274 ResultDocInfo_tarray::iterator it = presponse.docInfo.end() - 1;
1275 previous_sibling = (*it).OID;
1276 section_has_children = (*it).metadata["haschildren"].values[0].getint();
1277 } else {
1278 section_has_children = 0; // this should never happen
1279 }
1280 }
1281 }
1282
1283 if ((this_sibling+1) != last_sibling) {
1284 next_siblings.push_back((*(this_sibling+1)).OID);
1285 } else {
1286 next_siblings.push_back("");
1287 }
1288 break;
1289 }
1290 ++this_sibling;
1291 first = false;
1292 }
1293 thisoid = get_parent(thisoid);
1294 --parentcount;
1295 }
1296
1297 // work out values for next link
1298 if (haschildren) {
1299 disp.setmacro ("httpnextarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1300 "&amp;d=" + arg_d + ".fc");
1301 } else {
1302 text_tarray::const_iterator h = next_siblings.begin();
1303 text_tarray::const_iterator e = next_siblings.end();
1304 while (h != e) {
1305 if (!(*h).empty()) {
1306 disp.setmacro ("httpnextarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1307 "&amp;d=" + *h);
1308 break;
1309 }
1310 ++h;
1311 }
1312 }
1313
1314 // work out value for previous link
1315 if (!previous_sibling.empty()) {
1316 disp.setmacro ("httpprevarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1317 "&amp;d=" + previous_sibling);
1318 } else {
1319 if (countchar(arg_d.begin(), arg_d.end(), '.')) {
1320 disp.setmacro ("httpprevarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1321 "&amp;d=" + get_parent(arg_d));
1322 }
1323 }
1324}
Note: See TracBrowser for help on using the repository browser.