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

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

now dm_safe _thisOID_ macro

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