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

Last change on this file since 772 was 758, checked in by sjboddie, 25 years ago

changes for cross-collection searching - changes to arguments
of many functions

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