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

Last change on this file since 727 was 722, checked in by davidb, 25 years ago

Collection building support through web pages
and internal and external link handling for collection documents

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