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

Last change on this file since 928 was 928, checked in by kjm18, 24 years ago

search history stuff added.

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