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

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

Receptionist now caches collection information to avoid making multiple
get_collectinfo calls to collection server

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