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

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

added DocumentUseHTML - tidied some things up (and messed up some others)

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