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

Last change on this file since 781 was 781, checked in by sjboddie, 24 years ago

fixed bug in last changes

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 32.2 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 * $Id: documentaction.cpp 781 1999-11-13 08:57:00Z sjboddie $
25 *
26 *********************************************************************/
27
28/*
29 $Log$
30 Revision 1.31 1999/11/13 08:57:00 sjboddie
31 fixed bug in last changes
32
33 Revision 1.30 1999/11/01 21:54:27 sjboddie
34 changes for cross-collection searching - changes to arguments
35 of many functions
36
37 Revision 1.29 1999/10/24 07:23:40 sjboddie
38 added FullTOC option
39
40 Revision 1.28 1999/10/19 03:23:42 davidb
41 Collection building support through web pages
42 and internal and external link handling for collection documents
43
44 Revision 1.27 1999/10/14 23:00:53 sjboddie
45 finished changes to browsing support
46
47 Revision 1.26 1999/10/10 08:14:06 sjboddie
48 - metadata now returns mp rather than array
49 - redesigned browsing support (although it's not finished so
50 won't currently work ;-)
51
52 Revision 1.25 1999/09/17 04:46:05 sjboddie
53 fixed a couple of problems with 'unknown' classifier
54
55 Revision 1.24 1999/09/17 04:00:26 sjboddie
56 tidied up navigation bar to produce a default "unknown" button if
57 it comes across metadata it can't display
58
59 Revision 1.23 1999/09/07 04:56:54 sjboddie
60 added GPL notice
61
62 Revision 1.22 1999/08/20 01:00:22 sjboddie
63 split some of the larger functions up to simplify the creation of
64 collection specific receptionists
65
66 Revision 1.21 1999/08/11 23:28:03 sjboddie
67 -added support for html classifier
68 - removed _random_ macro - now use _blank for detach page
69
70 Revision 1.20 1999/08/10 23:16:39 sjboddie
71 a couple of small changes to get format options DocumentArrowsBottom
72 and DocumentArrowsTop working correctly
73
74 Revision 1.19 1999/08/10 22:40:01 sjboddie
75 added some more format options including the ability to format the
76 document text
77
78 Revision 1.18 1999/08/09 04:25:18 sjboddie
79 moved OID translation stuff from documentaction::define_external_macros
80 to receptionist
81
82 Revision 1.17 1999/08/09 02:13:53 sjboddie
83 fixed small bug in ShowSectionTitles
84
85 Revision 1.16 1999/08/03 03:30:47 sjboddie
86 a few small changes related to new format options
87
88 Revision 1.15 1999/07/30 02:18:49 sjboddie
89 -added collectinfo argument to some functions
90 -caught up with changes to browsetools (allowing nested classifications)
91 -added showtoppage format option
92
93 Revision 1.14 1999/07/21 05:01:09 sjboddie
94 fixed up wrapping of classificationlinks
95
96 Revision 1.13 1999/07/20 02:59:54 sjboddie
97 List and AZList classifications now use format strings
98
99 Revision 1.12 1999/07/16 00:19:01 sjboddie
100 some changes to the way quoted queries are handled
101
102 Revision 1.11 1999/07/07 05:47:41 sjboddie
103 changed around the way browsetools works
104
105 Revision 1.10 1999/06/29 01:46:44 sjboddie
106 now sets a _navigationbar_ macro even if there aren't any
107 classifications (it will just have the 'search' button
108
109 Revision 1.9 1999/06/27 22:05:58 sjboddie
110 now set a _thisOID_ macro for use in displaying images
111
112 Revision 1.8 1999/06/24 05:12:20 sjboddie
113 lots of small changes
114
115 Revision 1.7 1999/06/17 03:06:58 sjboddie
116 got detach button working properly - the close book icon is now disabled
117 when page is detached as the javascript close() function I was using is
118 too unreliable over different browsers
119 note that in my last comment I meant the "cl" arg (not the "c" arg).
120
121 Revision 1.6 1999/06/16 23:53:15 sjboddie
122 tidied a few things up. documentaction::define_external_macros now
123 resets the "c" arg if it's set to something stupid by the .xx suffixes
124
125 Revision 1.5 1999/06/16 03:10:49 sjboddie
126 define_internal_macros() now sets _pagetitle_ macro to document's title
127 (including parents of current document)
128
129 Revision 1.4 1999/06/15 01:55:29 sjboddie
130 - got text highlighting working
131 - got multiple collections working (now outputs error message if an
132 attempt is made to get a document when the "c" arg isn't set.
133
134 Revision 1.3 1999/06/08 04:29:37 sjboddie
135 added argsinfo to the call to check_cgiargs to make it easy to set
136 args to their default if they're found to be screwed up
137
138 Revision 1.2 1999/05/10 03:40:35 sjboddie
139 lots of changes - slowly getting document action sorted out
140
141 Revision 1.1 1999/04/30 01:59:40 sjboddie
142 lots of stuff - getting documentaction working (documentaction replaces
143 old browseaction)
144
145 Revision 1.2 1999/03/29 02:14:27 sjboddie
146
147 More changes to browseaction
148
149 Revision 1.1 1999/03/25 03:09:40 sjboddie
150
151 subjectbrowseaction became browseaction
152
153
154 */
155
156
157#include <string.h>
158#include "documentaction.h"
159#include "browsetools.h"
160#include "OIDtools.h"
161#include "querytools.h"
162#include "unitool.h"
163
164documentaction::documentaction () {
165
166 // this action uses cgi variables "a", "d", "cl",
167 // "x", "gc", "gt", "gp", and "hl"
168 cgiarginfo arg_ainfo;
169 arg_ainfo.shortname = "a";
170 arg_ainfo.longname = "action";
171 arg_ainfo.multiplechar = true;
172 arg_ainfo.defaultstatus = cgiarginfo::weak;
173 arg_ainfo.argdefault = "p";
174 arg_ainfo.savedarginfo = cgiarginfo::must;
175 argsinfo.addarginfo (NULL, arg_ainfo);
176
177 arg_ainfo.shortname = "d";
178 arg_ainfo.longname = "document OID";
179 arg_ainfo.multiplechar = true;
180 arg_ainfo.defaultstatus = cgiarginfo::none;
181 arg_ainfo.argdefault = "";
182 arg_ainfo.savedarginfo = cgiarginfo::can;
183 argsinfo.addarginfo (NULL, arg_ainfo);
184
185 // whether or not a document should be retrieved from the
186 // library or the Web.
187 arg_ainfo.shortname = "il";
188 arg_ainfo.longname = "internal link preference";
189 arg_ainfo.multiplechar = false;
190 arg_ainfo.defaultstatus = cgiarginfo::weak;
191 arg_ainfo.argdefault = "l";
192 arg_ainfo.savedarginfo = cgiarginfo::must;
193 argsinfo.addarginfo (NULL, arg_ainfo);
194
195 arg_ainfo.shortname = "cl";
196 arg_ainfo.longname = "classification OID";
197 arg_ainfo.multiplechar = true;
198 arg_ainfo.defaultstatus = cgiarginfo::none;
199 arg_ainfo.argdefault = "";
200 arg_ainfo.savedarginfo = cgiarginfo::can;
201 argsinfo.addarginfo (NULL, arg_ainfo);
202
203 // in this action "gc" controls the expand/contract
204 // contents function
205 arg_ainfo.shortname = "gc";
206 arg_ainfo.longname = "expand contents";
207 arg_ainfo.multiplechar = false;
208 arg_ainfo.defaultstatus = cgiarginfo::weak;
209 arg_ainfo.argdefault = "0";
210 arg_ainfo.savedarginfo = cgiarginfo::can;
211 argsinfo.addarginfo (NULL, arg_ainfo);
212
213 // in this action "gt" controls the expand/contract
214 // text function 0 = not expanded, 1 = expand unless
215 // there are more than 10 sections containing text,
216 // 2 = expand all
217 arg_ainfo.shortname = "gt";
218 arg_ainfo.longname = "expand text";
219 arg_ainfo.multiplechar = false;
220 arg_ainfo.defaultstatus = cgiarginfo::weak;
221 arg_ainfo.argdefault = "0";
222 arg_ainfo.savedarginfo = cgiarginfo::can;
223 argsinfo.addarginfo (NULL, arg_ainfo);
224
225 // in this action "gp" is the "go to page" control
226 // used by the Book type of toc
227 arg_ainfo.shortname = "gp";
228 arg_ainfo.longname = "go to page";
229 arg_ainfo.multiplechar = true;
230 arg_ainfo.defaultstatus = cgiarginfo::none;
231 arg_ainfo.argdefault = "";
232 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
233 argsinfo.addarginfo (NULL, arg_ainfo);
234
235 // in this action "hl" is the "highlighting on/
236 // highlighting off control
237 arg_ainfo.shortname = "hl";
238 arg_ainfo.longname = "highlighting on/off";
239 arg_ainfo.multiplechar = false;
240 arg_ainfo.defaultstatus = cgiarginfo::weak;
241 arg_ainfo.argdefault = "1";
242 arg_ainfo.savedarginfo = cgiarginfo::must;
243 argsinfo.addarginfo (NULL, arg_ainfo);
244
245 // "x" is 0 normally or 1 if page
246 // has been "detached"
247 arg_ainfo.shortname = "x";
248 arg_ainfo.longname = "detached page";
249 arg_ainfo.multiplechar = false;
250 arg_ainfo.defaultstatus = cgiarginfo::weak;
251 arg_ainfo.argdefault = "0";
252 arg_ainfo.savedarginfo = cgiarginfo::must;
253 argsinfo.addarginfo (NULL, arg_ainfo);
254}
255
256documentaction::~documentaction () {
257}
258
259bool documentaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
260 ostream &logout) {
261
262 // check gc argument
263 int arg_gc = args.getintarg("gc");
264 if (arg_gc != 0 && arg_gc != 1) {
265 logout << "Warning: \"gc\" argument out of range (" << arg_gc << ")\n";
266 cgiarginfo *gcinfo = argsinfo.getarginfo ("gc");
267 if (gcinfo != NULL) args["gc"] = gcinfo->argdefault;
268 }
269
270 // check gt argument (may be either 0, 1 or 2)
271 int arg_gt = args.getintarg("gt");
272 if (arg_gt != 0 && arg_gt != 1 && arg_gt != 2) {
273 logout << "Warning: \"gt\" argument out of range (" << arg_gt << ")\n";
274 cgiarginfo *gtinfo = argsinfo.getarginfo ("gt");
275 if (gtinfo != NULL) args["gt"] = gtinfo->argdefault;
276 }
277
278 // check hl argument
279 int arg_hl = args.getintarg("hl");
280 if (arg_hl != 0 && arg_hl != 1) {
281 logout << "Warning: \"hl\" argument out of range (" << arg_hl << ")\n";
282 cgiarginfo *hlinfo = argsinfo.getarginfo ("hl");
283 if (hlinfo != NULL) args["hl"] = hlinfo->argdefault;
284 }
285
286 // check x argument
287 int arg_x = args.getintarg("x");
288 if (arg_x != 0 && arg_x != 1) {
289 logout << "Warning: \"x\" argument out of range (" << arg_x << ")\n";
290 cgiarginfo *xinfo = argsinfo.getarginfo ("x");
291 if (xinfo != NULL) args["x"] = xinfo->argdefault;
292 }
293
294 return true;
295}
296
297void documentaction::get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
298 response_t &response,text_t &response_data,
299 ostream &logout) {
300
301 if ((args["il"] == "w") && (!args["d"].empty())) {
302
303 recptproto* collectproto = protos->getrecptproto (args["c"], logout);
304 if (collectproto != NULL) {
305
306 text_tset metadata;
307 FilterResponse_t filt_response;
308 text_t top;
309
310 metadata.insert ("URL");
311
312 // get metadata for parent document
313 get_top (args["d"], top);
314 if (get_info (top, args["c"], metadata, false, collectproto, filt_response, logout)) {
315 text_t url = filt_response.docInfo[0].metadata["URL"].values[0];
316
317 response = location;
318 response_data = url;
319 return;
320 } else {
321 // error, no URL
322 logout << "Error: documentaction::get_cgihead_info failed on get_info" << endl;
323 }
324 }
325 }
326 response = content;
327 response_data = "text/html";
328}
329
330// set_widthtspace calculates how wide the spaces in the nav bar should
331// be and sets the appropriate macro
332void documentaction::set_spacemacro (displayclass &disp, FilterResponse_t &response) {
333
334 text_t width;
335 int twidth, swidth, iwidth = 0;
336
337 int numc = response.docInfo.size();
338 ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
339 ResultDocInfo_tarray::iterator docend = response.docInfo.end();
340
341 disp.expandstring ("Global", "_pagewidth_", width);
342 twidth = width.getint();
343
344 disp.expandstring ("query", "_searchwidth_", width);
345 iwidth += width.getint();
346
347 while (dochere != docend) {
348 const text_t &title = (*dochere).metadata["Title"].values[0];
349
350 disp.expandstring ("document", "_" + title + "width_", width);
351 if (width == ("_" + title + "width_"))
352 disp.expandstring ("document", "_defaultwidth_", width);
353 iwidth += width.getint();
354 dochere ++;
355 }
356 if ((twidth - iwidth) < numc) swidth = 2;
357 else {
358 swidth = twidth - iwidth;
359 if (numc > 0) swidth = swidth / numc;
360 }
361 disp.setmacro ("widthtspace", "Global", swidth);
362}
363
364// set_navbarmacros sets _navigationbar_, _javaimagesnavbar_ and _httpbrowseXXX_ macros
365// reponse contains 1 metadata field (Title)
366void documentaction::set_navbarmacros (displayclass &disp, FilterResponse_t &response,
367 cgiargsclass &args) {
368
369 text_t javaimagesnavbar, topparent;
370 text_t &arg_d = args["d"];
371 text_t navigationbar = "<!-- Navigation Bar -->\n";
372
373 get_top (args["cl"], topparent);
374 int numc = response.docInfo.size();
375 ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
376 ResultDocInfo_tarray::iterator docend = response.docInfo.end();
377
378 navigationbar += "<nobr>\n";
379 if (args["a"] == "q") {
380 navigationbar += "_icontabsearchgreen_";
381 } else {
382 navigationbar += "_imagesearch_";
383 javaimagesnavbar = "_javasearch_";
384 }
385 if (numc == 0) navigationbar += "_imagespacer_";
386
387 while (dochere != docend) {
388 text_t title = (*dochere).metadata["Title"].values[0];
389
390 bool unknown = false;
391
392 // test the _XXXwidth_ macro to see if image macros are
393 // defined for this type of classification - if not we'll
394 // just display the text
395 text_t tmpwidth;
396 disp.expandstring ("document", "_" + title + "width_", tmpwidth);
397 if (tmpwidth == ("_" + title + "width_")) unknown = true;
398
399 // if we're inside a document all the classification buttons should be enabled
400 if (arg_d.empty() && ((*dochere).OID == topparent)) {
401 if (unknown) navigationbar += "_imagespacer_&nbsp;" + title + "&nbsp;";
402 else navigationbar += "_imagespacer__icontab" + title + "green_";
403 } else {
404
405 // set the _httpbrowseXXX_ macro for this classification
406 if (unknown) navigationbar += "_imagespacer_&nbsp;<a href=\"_httpdocument_&cl=" +
407 (*dochere).OID + "\">" + title + "</a>&nbsp;";
408 else {
409 navigationbar += "_imagespacer__image" + title + "_";
410 disp.setmacro ("httpbrowse" + title, "Global", "_httpdocument_&cl=" + (*dochere).OID);
411 }
412 }
413 if (!unknown) javaimagesnavbar += "_java" + title + "_";
414 dochere ++;
415 }
416 navigationbar += "\n</nobr>\n";
417 navigationbar += "<!-- End of Navigation Bar -->\n";
418 disp.setmacro ("navigationbar", "Global", navigationbar);
419 if (args.getintarg("v") == 0)
420 disp.setmacro ("javaimagesnavbar", "Global", javaimagesnavbar);
421}
422
423// define all the macros which might be used by other actions
424// to produce pages.
425void documentaction::define_external_macros (displayclass &disp, cgiargsclass &args,
426 recptprotolistclass *protos, ostream &logout) {
427
428 // define_external_macros sets the following macros:
429
430 // _navigationbar_ this is the navigation bar containing the search button
431 // and any classification buttons - it goes at the top of
432 // most pages. for now we're assuming that there'll always
433 // be a search button - we should probably check that there
434 // is a query action before making this assumption
435
436 // _httpbrowseXXX_ the http macros for each classification (i.e. if there
437 // are Title and Creator classifications _httpbrowseTitle_
438 // and _httpbrowseCreator_ will be set
439
440 // _javaimagesnavbar_ this is the javascript code to shove in to make the
441 // flashy images used by _navigationbar_ work
442
443 // _widthtspace_ the width of the spacers between buttons in navigation
444 // bar
445
446
447 // must have a valid collection server to continue
448 text_t &collection = args["c"];
449 if (collection.empty()) return;
450 recptproto *collectproto = protos->getrecptproto (collection, logout);
451 if (collectproto == NULL) return;
452
453 outconvertclass text_t2ascii;
454 comerror_t err;
455 InfoFiltersResponse_t filterinfo;
456 FilterResponse_t response;
457 text_tset metadata;
458
459 // don't want navigation bar if page is 'detached'
460 if (!args.getintarg("x")) {
461
462 collectproto->get_filterinfo (collection, filterinfo, err, logout);
463 if (err == noError) {
464 // check that there's a browse filter
465 if (filterinfo.filterNames.find ("BrowseFilter") != filterinfo.filterNames.end()) {
466
467 metadata.insert ("Title");
468 bool getParents = false;
469 get_children ("", collection, metadata, getParents, collectproto, response, logout);
470
471 // calculate width of spacers and set _widthtspace_ macro
472 if (args.getintarg("v") == 0) set_spacemacro (disp, response);
473
474 // set _navigationbar_ and _javaimagesnavbar_ macros
475 set_navbarmacros (disp, response, args);
476 }
477 } else {
478 logout << text_t2ascii
479 << "Error (documentaction::define_external_macros()) in call to get_filterinfo() "
480 << get_comerror_string (err);
481 }
482 }
483}
484
485void documentaction::load_formatinfo (const text_tmap &colformat, int gt) {
486
487 formatinfo.clear();
488 text_tmap::const_iterator format_here = colformat.begin();
489 text_tmap::const_iterator format_end = colformat.end();
490
491 while (format_here != format_end) {
492 if (((*format_here).first == "DocumentImages") &&
493 ((*format_here).second == "true"))
494 formatinfo.DocumentImages = true;
495 else if (((*format_here).first == "DocumentTitles") &&
496 ((*format_here).second == "false"))
497 formatinfo.DocumentTitles = false;
498 else if ((*format_here).first == "DocumentHeading")
499 formatinfo.DocumentHeading = (*format_here).second;
500 else if (((*format_here).first == "DocumentContents") &&
501 ((*format_here).second == "false"))
502 formatinfo.DocumentContents = false;
503 else if (((*format_here).first == "DocumentArrowsBottom") &&
504 ((*format_here).second == "false"))
505 formatinfo.DocumentArrowsBottom = false;
506 else if ((*format_here).first == "DocumentButtons")
507 splitchar ((*format_here).second.begin(), (*format_here).second.end(),
508 '|', formatinfo.DocumentButtons);
509 else if ((*format_here).first == "DocumentText")
510 formatinfo.DocumentText = (*format_here).second;
511 else
512 formatinfo.formatstrings[(*format_here).first] = (*format_here).second;
513
514 format_here ++;
515 }
516
517 // never want arrows when text is expanded
518 if (gt)
519 formatinfo.DocumentArrowsBottom = false;
520}
521
522void documentaction::set_java_macros (cgiargsclass &args, displayclass &disp) {
523
524 text_t javaimagescontent = "_javaextras_";
525
526 int arg_gt = args.getintarg("gt");
527 int arg_gc = args.getintarg("gc");
528 int arg_hl = args.getintarg("hl");
529
530 text_tarray::const_iterator button_here = formatinfo.DocumentButtons.begin();
531 text_tarray::const_iterator button_end = formatinfo.DocumentButtons.end();
532
533 while (button_here != button_end) {
534 if (*button_here == "Detach")
535 javaimagescontent += "_javadetach_";
536 else if (*button_here == "Expand Text") {
537 if (arg_gt == 1)
538 javaimagescontent += "_javacontracttext__javacontinue_";
539 else if (arg_gt == 2)
540 javaimagescontent += "_javacontracttext_";
541 else
542 javaimagescontent += "_javaexpandtext_";
543 } else if (*button_here == "Expand Contents") {
544 if (arg_gc == 1)
545 javaimagescontent += "_javacontractcontents_";
546 else
547 javaimagescontent += "_javaexpandcontents_";
548 } else if (*button_here == "Highlight") {
549 if (arg_hl == 1)
550 javaimagescontent += "_javanohighlighting_";
551 else
552 javaimagescontent += "_javahighlighting_";
553 }
554 button_here ++;
555 }
556 disp.setmacro ("javaimagescontent", "document", javaimagescontent);
557}
558
559
560// define all the macros which are related to pages generated
561// by this action. we also load up the formatinfo structure
562// here (it's used in do_action as well as here)
563void documentaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
564 recptprotolistclass *protos, ostream &logout) {
565
566 // define_internal_macros sets the following macros:
567
568 // _pagetitle_ the title to be displayed at the top of the browser window
569
570 // _imagethispage_ the title image to be displayed at top right of page
571
572 // _navarrows_ this may be overridden to "" when format option
573 // DocumentArrowsBottom is false
574
575 // _header_ the header macro is overridden if we're not at a top level
576 // classification to remove the title block
577
578 // _javaimagescontent_ this is the javascript code to shove in to make the
579 // flashy buttons work
580
581 // _thisOID_ the OID (directory) of the current document - this corresponds
582 // to the archivedir metadata element
583
584
585 // must have a valid collection server to continue
586 text_t &collection = args["c"];
587 if (collection.empty()) return;
588 recptproto *collectproto = protos->getrecptproto (collection, logout);
589 if (collectproto == NULL) return;
590
591 text_tset metadata;
592 FilterResponse_t response;
593 text_t &arg_d = args["d"];
594 text_t &arg_cl = args["cl"];
595 int gt = args.getintarg("gt");
596
597 // get info on current collection and load up formatinfo
598 ColInfoResponse_t cinfo;
599 comerror_t err;
600 collectproto->get_collectinfo (collection, cinfo, err, logout);
601 load_formatinfo (cinfo.format, gt);
602
603 if (!formatinfo.DocumentArrowsBottom)
604 disp.setmacro("navarrows", "document", "");
605
606 metadata.insert ("Title");
607
608 bool fulltoc = false;
609
610 if (args["cl"] != "search") {
611 // see if there's a FullTOC string
612 text_t cl_top, full_toc;
613 get_top (arg_cl, cl_top);
614 if (get_formatstring (cl_top, "FullTOC", formatinfo.formatstrings, full_toc))
615 if (full_toc == "true") fulltoc = true;
616 }
617
618 if (!arg_d.empty() && !fulltoc) {
619 // we're at document level
620
621 metadata.insert ("archivedir");
622
623 // get metadata for this document and it's parents
624 if (get_info (arg_d, collection, metadata, true, collectproto, response, logout)) {
625 disp.setmacro ("header", "document", "_textheader_");
626
627 text_tarray pagetitlearray;
628 if (!response.docInfo[0].metadata["Title"].values[0].empty())
629 pagetitlearray.push_back (response.docInfo[0].metadata["Title"].values[0]);
630 if (!gt) {
631 MetadataInfo_t *parenttitle = response.docInfo[0].metadata["Title"].parent;
632 while (parenttitle != NULL) {
633 if (!parenttitle->values[0].empty())
634 pagetitlearray.push_back (parenttitle->values[0]);
635 parenttitle = parenttitle->parent;
636 }
637 }
638 reverse (pagetitlearray.begin(), pagetitlearray.end());
639 text_t pagetitle;
640 joinchar (pagetitlearray, ": ", pagetitle);
641 disp.setmacro ("pagetitle", "document", pagetitle);
642
643 if (is_top (arg_d))
644 disp.setmacro ("thisOID", "Global", response.docInfo[0].metadata["archivedir"].values[0]);
645 else {
646 MetadataInfo_t *parentad = response.docInfo[0].metadata["archivedir"].parent;
647 text_t thisOID;
648 while (parentad != NULL) {
649 thisOID = parentad->values[0];
650 parentad = parentad->parent;
651 }
652 disp.setmacro ("thisOID", "Global", thisOID);
653 }
654
655 if (args["u"] != "1")
656 set_java_macros (args, disp);
657
658 }
659 } else {
660 if (!arg_cl.empty()) {
661
662 // get metadata for top level classification
663 text_t classtop;
664 get_top (arg_cl, classtop);
665 if (get_info (classtop, collection, metadata, false, collectproto, response, logout)) {
666
667 text_t &title = response.docInfo[0].metadata["Title"].values[0];
668 bool unknown = false;
669
670 // test the _XXXwidth_ macro to see if image macros are
671 // defined for this type of classification - if not we'll
672 // just display the text
673 text_t tmp;
674 disp.expandstring ("document", "_" + title + "width_", tmp);
675 if (tmp == ("_" + title + "width_")) unknown = true;
676
677 if (unknown) {
678 disp.setmacro ("pagetitle", "document", title);
679 disp.setmacro ("imagethispage", "document", "<h2>" + title + "</h2>");
680 } else {
681 disp.setmacro ("pagetitle", "document", "_text" + title + "page_");
682 disp.setmacro ("imagethispage", "document", "_icon" + title + "page_");
683 }
684 }
685 }
686 }
687}
688
689
690bool documentaction::do_action (cgiargsclass &args, recptprotolistclass *protos,
691 browsermapclass *browsers, displayclass &disp,
692 outconvertclass &outconvert, ostream &textout,
693 ostream &logout) {
694
695
696 // must have a valid collection server
697 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
698 if (collectproto == NULL) {
699 logout << "documentaction::do_action called with NULL collectproto\n";
700 textout << outconvert << disp << "_document:header_\n"
701 << "Error: Attempt to get document without setting collection\n"
702 << "_document:footer_\n";
703 } else {
704
705 text_t OID = args["d"];
706 if (OID.empty()) OID = args["cl"];
707 if (OID.empty()) {
708 textout << outconvert << disp << "Document contains no data_document:footer_\n";
709 return true;
710 }
711
712 textout << outconvert << disp << "_document:header_\n"
713 << "_document:content_\n";
714
715 // output the table of contents
716 output_toc (args, browsers, formatinfo, collectproto,
717 disp, outconvert, textout, logout);
718
719 // output the document text
720 textout << "<p>\n";
721 output_document (OID, args, collectproto, disp, outconvert, textout, logout);
722
723 textout << outconvert << disp << "_document:footer_\n";
724 }
725 return true;
726}
727
728void documentaction::output_text (ResultDocInfo_t &docinfo, format_t *formatlistptr,
729 const TermInfo_tarray &terminfo, const text_t &OID,
730 bool highlight, int hastxt, int wanttext,
731 text_t &collection, recptproto *collectproto,
732 displayclass &disp, outconvertclass &outconvert,
733 ostream &textout, ostream &logout) {
734
735 DocumentRequest_t docrequest;
736 DocumentResponse_t docresponse;
737 comerror_t err;
738
739 if (hastxt == 1) {
740
741 if (wanttext) {
742 // get the text
743 docrequest.OID = OID;
744 collectproto->get_document (collection, docrequest, docresponse, err, logout);
745
746 // cut down on overhead by not using formattools if we only want the text
747 // (wanttext will equal 2 if we want text and other stuff too)
748 if (wanttext == 1)
749 if (highlight)
750 highlighttext(docresponse.doc, terminfo, disp, outconvert, textout, logout);
751 else
752 textout << outconvert << disp << docresponse.doc;
753 }
754
755 if (wanttext != 1) {
756 text_t doctext = get_formatted_string (docinfo, formatlistptr, docresponse.doc);
757
758 if (highlight)
759 highlighttext(doctext, terminfo, disp, outconvert, textout, logout);
760 else
761 textout << outconvert << disp << doctext;
762 }
763 }
764}
765
766
767void documentaction::output_document (const text_t &OID, cgiargsclass &args,
768 recptproto *collectproto, displayclass &disp,
769 outconvertclass &outconvert, ostream &textout,
770 ostream &logout) {
771 FilterResponse_t inforesponse;
772 FilterResponse_t queryresponse;
773 text_tset metadata;
774 bool getParents = false;
775 bool highlight = false;
776 int wanttext = 0;
777 int arg_gt = args.getintarg("gt");
778 text_t &collection = args["c"];
779
780 // if we have a query string and highlighting is turned on we need
781 // to redo the query to get the terms for highlighting
782 if (!args["q"].empty() && args.getintarg("hl")) {
783 FilterRequest_t request;
784 comerror_t err;
785 request.filterResultOptions = FRmatchTerms;
786 text_t formattedstring = args["q"];
787 format_querystring (formattedstring, args.getintarg("b"));
788 set_queryfilter_options (request, formattedstring, args);
789 collectproto->filter (args["c"], request, queryresponse, err, logout);
790 if (err != noError) {
791 outconvertclass text_t2ascii;
792 logout << text_t2ascii
793 << "documentaction::output_document: call to QueryFilter failed "
794 << "for " << args["c"] << " collection (" << get_comerror_string (err) << ")\n";
795 highlight = false;
796 } else {
797 highlight = true;
798 }
799 }
800
801 format_t *formatlistptr = new format_t();
802 parse_formatstring (formatinfo.DocumentText, formatlistptr, metadata, getParents);
803
804 metadata.insert ("hastxt");
805 metadata.insert ("haschildren");
806
807 if (formatinfo.DocumentText == "[Text]")
808 wanttext = 1;
809 else {
810 char *docformat = formatinfo.DocumentText.getcstr();
811 if (strstr (docformat, "[Text]") != NULL)
812 wanttext = 2;
813 delete docformat;
814 }
815
816 if (get_info (OID, collection, metadata, getParents, collectproto, inforesponse, logout)) {
817 int hastxt = inforesponse.docInfo[0].metadata["hastxt"].values[0].getint();
818 int haschildren = inforesponse.docInfo[0].metadata["haschildren"].values[0].getint();
819
820 if (arg_gt == 0) {
821 output_text (inforesponse.docInfo[0], formatlistptr, queryresponse.termInfo,
822 OID, highlight, hastxt, wanttext, collection, collectproto,
823 disp, outconvert, textout, logout);
824
825
826 } else {
827
828 ResultDocInfo_t thisdocinfo = inforesponse.docInfo[0];
829
830 // text is to be expanded
831 text_t exOID = OID;
832 if (haschildren != 1) exOID = get_parent (OID);
833 if (exOID.empty()) exOID = OID;
834
835 // if we're not in a document (i.e. we're in a top level classification)
836 // we need to pass "is_classify = true" to get_contents so that it
837 // doesn't recurse all the way through each document in the classification
838 bool is_classify = false;
839 if (args["d"].empty()) is_classify = true;
840
841 get_contents (exOID, is_classify, metadata, collection,
842 collectproto, inforesponse, logout);
843
844 ResultDocInfo_tarray::iterator sechere = inforesponse.docInfo.begin();
845 ResultDocInfo_tarray::iterator secend = inforesponse.docInfo.end();
846
847 if (arg_gt == 1) {
848 // check if there are more than 10 sections containing text to be expanded -
849 // if there are output warning message - this isn't a great way to do this
850 // since the sections may be very large or very small - one day I'll fix it
851 // -- Stefan.
852 int seccount = 0;
853 while (sechere != secend) {
854 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
855 if (shastxt == 1) seccount ++;
856 if (seccount > 10) break;
857 sechere ++;
858 }
859 if (seccount > 10) {
860 // more than 10 sections so output warning message and text
861 // for current section only
862 textout << outconvert << disp << "_document:textltwarning_";
863
864 output_text (thisdocinfo, formatlistptr, queryresponse.termInfo,
865 OID, highlight, hastxt, wanttext, collection,
866 collectproto, disp, outconvert, textout, logout);
867
868 }
869 else arg_gt = 2;
870 }
871
872 if (arg_gt == 2) {
873 // get the text for each section
874 sechere = inforesponse.docInfo.begin();
875 int count = 0;
876 while (sechere != secend) {
877 textout << outconvert << disp << "\n<p><a name=" << count << "></a>\n";
878
879 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
880
881 output_text (*sechere, formatlistptr, queryresponse.termInfo,
882 (*sechere).OID, highlight, shastxt, wanttext, collection,
883 collectproto, disp, outconvert, textout, logout);
884 count ++;
885 sechere ++;
886 }
887 }
888 }
889 }
890 delete formatlistptr;
891}
892
893// highlighttext highlights query terms in text string and outputs the resulting text string
894void documentaction::highlighttext(text_t &text, const TermInfo_tarray &terms,
895 displayclass &disp, outconvertclass &outconvert,
896 ostream &textout, ostream &/*logout*/) {
897
898 text_tmap allterms;
899 text_tmap::const_iterator it;
900
901 // first load all the term variations into a map
902 TermInfo_tarray::const_iterator this_term = terms.begin();
903 TermInfo_tarray::const_iterator last_term = terms.end();
904 while (this_term != last_term) {
905 text_tarray::const_iterator this_var = (*this_term).matchTerms.begin();
906 text_tarray::const_iterator last_var = (*this_term).matchTerms.end();
907 while (this_var != last_var) {
908 allterms[*this_var] = 1;
909 this_var ++;
910 }
911 this_term ++;
912 }
913
914 // get the text to start and end a hightlight
915 text_t starthighlight = "<b><u>";
916 text_t endhighlight = "</u></b>";
917 if (disp.isdefaultmacro("Global", "starthighlight"))
918 disp.expandstring("Global", "_starthighlight_", starthighlight);
919 if (disp.isdefaultmacro("Global", "endhighlight"))
920 disp.expandstring("Global", "_endhighlight_", endhighlight);
921
922
923 text_t::iterator here = text.begin();
924 text_t::iterator end = text.end();
925 text_t word, buffer;
926 while (here != end) {
927 if (is_unicode_letdig(*here)) {
928 // not word boundary
929 word.push_back(*here);
930 here++;
931
932 } else {
933 // found word boundary
934 // add last word if there was one
935 if (!word.empty()) {
936 it = allterms.find(word);
937 if (it != allterms.end()) {
938 word = starthighlight + word + endhighlight;
939 }
940 buffer += word;
941 word.clear();
942 }
943
944 if (*here == '<') {
945 // skip over rest of html tag
946 while ((here != end) && (*here != '>')) {
947 buffer.push_back(*here);
948 here++;
949 }
950 }
951
952 buffer.push_back(*here);
953 here++;
954
955 if (buffer.size() > 1024) {
956 textout << outconvert << disp << buffer;
957 buffer.clear();
958 }
959 }
960 }
961 textout << outconvert << disp << buffer;
962}
Note: See TracBrowser for help on using the repository browser.