source: trunk/gsdl/src/recpt/receptionist.cpp@ 388

Last change on this file since 388 was 388, checked in by rjmcnab, 25 years ago

Moved the setting of argsinfo into the constructor. Added the configuration
command argdefault (as used by the actions). Added code to output the
correct charset based on the page encoding so that the user does not need
to specify the encoding used for a particular page.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 22.4 KB
Line 
1/**********************************************************************
2 *
3 * receptionist.cpp -- a web interface for the gsdl
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * PUT COPYRIGHT NOTICE HERE
7 *
8 * $Id: receptionist.cpp 388 1999-07-15 06:02:05Z rjmcnab $
9 *
10 *********************************************************************/
11
12/*
13 $Log$
14 Revision 1.19 1999/07/15 06:02:05 rjmcnab
15 Moved the setting of argsinfo into the constructor. Added the configuration
16 command argdefault (as used by the actions). Added code to output the
17 correct charset based on the page encoding so that the user does not need
18 to specify the encoding used for a particular page.
19
20 Revision 1.18 1999/07/11 01:05:20 rjmcnab
21 Stored origin of cgiarg with argument.
22
23 Revision 1.17 1999/07/10 22:18:26 rjmcnab
24 Added calls to define_external_cgiargs.
25
26 Revision 1.16 1999/06/27 21:49:03 sjboddie
27 fixed a couple of version conflicts - tidied up some small things
28
29 Revision 1.15 1999/06/26 01:14:32 rjmcnab
30 Made a couple of changes to handle different encodings.
31
32 Revision 1.14 1999/06/09 00:08:36 sjboddie
33 query string macro (_cgiargq_) is now made html safe before being set
34
35 Revision 1.13 1999/06/08 04:29:31 sjboddie
36 added argsinfo to the call to check_cgiargs to make it easy to set
37 args to their default if they're found to be screwed up
38
39 Revision 1.12 1999/04/30 01:59:42 sjboddie
40 lots of stuff - getting documentaction working (documentaction replaces
41 old browseaction)
42
43 Revision 1.11 1999/03/25 03:06:43 sjboddie
44
45 altered receptionist slightly so it now passes *collectproto to
46 define_internal_macros and define_external_macros - need it
47 for browseaction
48
49 Revision 1.10 1999/03/05 03:53:54 sjboddie
50
51 fixed some bugs
52
53 Revision 1.9 1999/02/28 20:00:16 rjmcnab
54
55
56 Fixed a few things.
57
58 Revision 1.8 1999/02/25 21:58:59 rjmcnab
59
60 Merged sources.
61
62 Revision 1.7 1999/02/21 22:33:55 rjmcnab
63
64 Lots of stuff :-)
65
66 Revision 1.6 1999/02/11 01:24:05 rjmcnab
67
68 Fixed a few compiler warnings.
69
70 Revision 1.5 1999/02/08 01:28:02 rjmcnab
71
72 Got the receptionist producing something using the statusaction.
73
74 Revision 1.4 1999/02/05 10:42:46 rjmcnab
75
76 Continued working on receptionist
77
78 Revision 1.3 1999/02/04 10:00:56 rjmcnab
79
80 Developed the idea of an "action" and having them define the cgi arguments
81 which they need and how those cgi arguments function.
82
83 Revision 1.2 1999/02/04 01:17:27 rjmcnab
84
85 Got it outputing something.
86
87
88 */
89
90
91#include "receptionist.h"
92#include "fileutil.h"
93#include "cgiutils.h"
94#include "htmlutils.h"
95#include "OIDtools.h"
96#include <assert.h>
97#include <time.h>
98
99
100
101receptionist::receptionist () {
102 // create a list of cgi arguments
103 // this must be done before the configuration
104
105 cgiarginfo ainfo;
106
107 ainfo.shortname = "e";
108 ainfo.longname = "compressed arguments";
109 ainfo.multiplechar = true;
110 ainfo.defaultstatus = cgiarginfo::good;
111 ainfo.argdefault = "";
112 ainfo.savedarginfo = cgiarginfo::mustnot;
113 argsinfo.addarginfo (NULL, ainfo);
114
115 ainfo.shortname = "a";
116 ainfo.longname = "action";
117 ainfo.multiplechar = true;
118 ainfo.defaultstatus = cgiarginfo::none;
119 ainfo.argdefault = "";
120 ainfo.savedarginfo = cgiarginfo::must;
121 argsinfo.addarginfo (NULL, ainfo);
122
123 // w=western
124 ainfo.shortname = "w";
125 ainfo.longname = "encoding";
126 ainfo.multiplechar = true;
127 ainfo.defaultstatus = cgiarginfo::weak;
128 ainfo.argdefault = "w";
129 ainfo.savedarginfo = cgiarginfo::must;
130 argsinfo.addarginfo (NULL, ainfo);
131
132 ainfo.shortname = "nw";
133 ainfo.longname = "new encoding";
134 ainfo.multiplechar = true;
135 ainfo.defaultstatus = cgiarginfo::none;
136 ainfo.argdefault = "";
137 ainfo.savedarginfo = cgiarginfo::mustnot;
138 argsinfo.addarginfo (NULL, ainfo);
139
140 ainfo.shortname = "c";
141 ainfo.longname = "collection";
142 ainfo.multiplechar = true;
143 ainfo.defaultstatus = cgiarginfo::none;
144 ainfo.argdefault = "";
145 ainfo.savedarginfo = cgiarginfo::must;
146 argsinfo.addarginfo (NULL, ainfo);
147
148 // 0=text+graphics, 1=text
149 ainfo.shortname = "v";
150 ainfo.longname = "version";
151 ainfo.multiplechar = false;
152 ainfo.defaultstatus = cgiarginfo::weak;
153 ainfo.argdefault = "0";
154 ainfo.savedarginfo = cgiarginfo::can;
155 argsinfo.addarginfo (NULL, ainfo);
156
157 // 0=normal, 1=big
158 ainfo.shortname = "f";
159 ainfo.longname = "query box size";
160 ainfo.multiplechar = false;
161 ainfo.defaultstatus = cgiarginfo::weak;
162 ainfo.argdefault = "0";
163 ainfo.savedarginfo = cgiarginfo::can;
164 argsinfo.addarginfo (NULL, ainfo);
165
166 // the interface language name should use the ISO 639
167 // standard
168 ainfo.shortname = "l";
169 ainfo.longname = "interface language";
170 ainfo.multiplechar = true;
171 ainfo.defaultstatus = cgiarginfo::weak;
172 ainfo.argdefault = "en";
173 ainfo.savedarginfo = cgiarginfo::must;
174 argsinfo.addarginfo (NULL, ainfo);
175}
176
177
178// configure should be called for each line in the
179// configuration files to configure the receptionist and everything
180// it contains. The configuration should take place after everything
181// has been added but before the initialisation.
182void receptionist::configure (const text_t &key, const text_tarray &cfgline) {
183 // configure the receptionist
184 if (cfgline.size() >= 1) {
185 cgiarginfo *info = NULL;
186 if (key == "gsdlhome") configinfo.gsdlhome = cfgline[0];
187 else if (key == "collection") {
188 configinfo.collection = cfgline[0];
189 // also need to set the default arg to this collection
190 if ((info = argsinfo.getarginfo("c")) != NULL) {
191 info->defaultstatus = cgiarginfo::good;
192 info->argdefault = cfgline[0];
193 }
194
195 } else if (key == "collectdir") configinfo.collectdir = cfgline[0];
196 else if (key == "httpprefix") configinfo.httpprefix = cfgline[0];
197 else if (key == "httpimg") configinfo.httpimg = cfgline[0];
198 else if (key == "gwcgi") configinfo.gwcgi = cfgline[0];
199 else if (key == "macrofiles") configinfo.macrofiles = cfgline;
200 else if (key == "saveconf") configinfo.saveconf = cfgline[0];
201
202 else if ((key == "argdefault") && (cfgline.size() == 2) &&
203 ((info = argsinfo.getarginfo(cfgline[0])) != NULL)) {
204 if (info->defaultstatus <= cgiarginfo::config) {
205 info->defaultstatus = cgiarginfo::config;
206 info->argdefault = cfgline[1];
207 }
208 }
209 }
210
211 // configure the actions
212 actionptrmap::iterator actionhere = actions.begin ();
213 actionptrmap::iterator actionend = actions.end ();
214
215 while (actionhere != actionend) {
216 assert ((*actionhere).second.a != NULL);
217 if ((*actionhere).second.a != NULL)
218 (*actionhere).second.a->configure(key, cfgline);
219
220 actionhere++;
221 }
222
223 // configure the protocols
224 recptprotolistclass::iterator protohere = protocols.begin ();
225 recptprotolistclass::iterator protoend = protocols.end ();
226
227 while (protohere != protoend) {
228 assert ((*protohere).p != NULL);
229 if ((*protohere).p != NULL)
230 (*protohere).p->configure(key, cfgline);
231
232 protohere++;
233 }
234}
235
236void receptionist::configure (const text_t &key, const text_t &value) {
237 text_tarray cfgline;
238 cfgline.push_back (value);
239 configure(key, cfgline);
240}
241
242
243// init should be called after all the actions, protocols, and
244// converters have been added to the receptionist and after everything
245// has been configured but before any pages are created.
246// It returns true on success and false on failure. If false is
247// returned getpage should not be called (without producing
248// meaningless output), instead an error page should be
249// produced by the calling code.
250bool receptionist::init (ostream &logout) {
251 // first configure collectdir
252 text_t thecollectdir = configinfo.gsdlhome;
253 if (!configinfo.collection.empty()) {
254 // collection specific mode
255 if (!configinfo.collectdir.empty()) {
256 // has already been configured
257 thecollectdir = configinfo.collectdir;
258 } else {
259 // decide where collectdir is by searching for collect.cfg
260 // look in $GSDLHOME/collect/collection-name/etc/collect.cfg and
261 // then $GSDLHOME/etc/collect.cfg
262 thecollectdir = filename_cat (configinfo.gsdlhome, "collect");
263 thecollectdir = filename_cat (thecollectdir, configinfo.collection);
264 text_t filename = filename_cat (thecollectdir, "etc");
265 filename = filename_cat (filename, "collect.cfg");
266 if (!file_exists(filename)) thecollectdir = configinfo.gsdlhome;
267 }
268 }
269 configure("collectdir", thecollectdir);
270
271 // read in the macro files
272 if (!read_macrofiles (logout)) return false;
273
274 // there must be at least one action defined
275 if (actions.empty()) {
276 logout << "Error: no actions have been added to the receptionist\n";
277 return false;
278 }
279
280 // add the cgi arguments from the actions
281 actionptrmap::iterator here = actions.begin ();
282 actionptrmap::iterator end = actions.end ();
283 while (here != end) {
284 assert ((*here).second.a != NULL);
285 if ((*here).second.a != NULL) {
286 if (!argsinfo.addarginfo (&logout, (*here).second.a->getargsinfo()))
287 return false;
288 }
289 here++;
290 }
291
292 // create a saveconf string if there isn't one already
293 if (configinfo.saveconf.empty())
294 configinfo.saveconf = create_save_conf_str (argsinfo, logout);
295
296 // check the saveconf string
297 if (!check_save_conf_str (configinfo.saveconf, argsinfo, logout))
298 return false;
299
300 // set a random seed
301 srand (time(NULL));
302
303 // make the output converters remove all the zero-width spaces
304 convertinfoclass::iterator converthere = converters.begin ();
305 convertinfoclass::iterator convertend = converters.end ();
306 text_t defaultconvertname;
307 while (converthere != convertend) {
308 assert ((*converthere).second.outconverter != NULL);
309 if ((*converthere).second.outconverter != NULL) {
310 (*converthere).second.outconverter->set_rzws(1);
311 if (defaultconvertname.empty())
312 defaultconvertname = (*converthere).second.name;
313 }
314 converthere++;
315 }
316
317 // set default converter if no good one has been defined
318 if (!defaultconvertname.empty()) {
319 cgiarginfo *ainfo = argsinfo.getarginfo ("w");
320 if ((ainfo != NULL) && (ainfo->defaultstatus < cgiarginfo::config)) {
321 ainfo->defaultstatus = cgiarginfo::good;
322 ainfo->argdefault = defaultconvertname;
323 }
324 }
325
326 // init the actions
327 actionptrmap::iterator actionhere = actions.begin ();
328 actionptrmap::iterator actionend = actions.end ();
329 while (actionhere != actionend) {
330 if (((*actionhere).second.a == NULL) ||
331 !(*actionhere).second.a->init(logout)) return false;
332 actionhere++;
333 }
334
335 // init the protocols
336 recptprotolistclass::iterator protohere = protocols.begin ();
337 recptprotolistclass::iterator protoend = protocols.end ();
338 while (protohere != protoend) {
339 if (((*protohere).p == NULL) ||
340 !(*protohere).p->init(logout)) return false;
341 protohere++;
342 }
343
344 return true;
345}
346
347
348// parse_cgi_args parses cgi arguments into an argument class.
349// This function should be called for each page request. It returns false
350// if there was a major problem with the cgi arguments.
351bool receptionist::parse_cgi_args (const text_t &argstr, cgiargsclass &args,
352 ostream &logout) {
353 outconvertclass text_t2ascii;
354
355 // get an initial list of cgi arguments
356 args.clear();
357 split_cgi_args (argstr, args);
358
359 // expand the compressed argument (if there was one)
360 if (!expand_save_args (argsinfo, configinfo.saveconf, args, logout)) return false;
361
362 // add the defaults
363 add_default_args (argsinfo, args, logout);
364
365
366 // get the input encoding
367 text_t &arg_w = args["w"];
368 inconvertclass defaultinconvert;
369 inconvertclass *inconvert = converters.get_inconverter (arg_w);
370 if (inconvert == NULL) inconvert = &defaultinconvert;
371
372 // see if the next page will have a different encoding
373 if (args.getarg("nw") != NULL) arg_w = args["nw"];
374
375 // convert arguments which aren't in unicode to unicode
376 args_tounicode (args, *inconvert);
377
378
379 // decide on the output conversion class (needed for checking the external
380 // cgi arguments)
381 rzwsoutconvertclass defaultoutconverter;
382 rzwsoutconvertclass *outconverter = converters.get_outconverter (arg_w);
383 if (outconverter == NULL) outconverter = &defaultoutconverter;
384 outconverter->reset();
385
386
387 // check the main cgi arguments
388 if (!check_mainargs (args, logout)) return false;
389
390 // check the arguments for the action
391 action *a = actions.getaction (args["a"]);
392 if (a != NULL) {
393 if (!a->check_cgiargs (argsinfo, args, logout)) return false;
394 } else {
395 // the action was not found!!
396 logout << text_t2ascii << "Error: the action \"" << args["a"]
397 << "\" could not be found.\n";
398 return false;
399 }
400
401 // check external cgi arguments for each action
402 actionptrmap::iterator actionhere = actions.begin ();
403 actionptrmap::iterator actionend = actions.end ();
404 while (actionhere != actionend) {
405 assert ((*actionhere).second.a != NULL);
406 if ((*actionhere).second.a != NULL) {
407 if (!(*actionhere).second.a->check_external_cgiargs (argsinfo, args, *outconverter,
408 configinfo.saveconf, logout))
409 return false;
410 }
411 actionhere++;
412 }
413
414 // the action might have changed but we will assume that
415 // the cgiargs were checked properly when the change was made
416
417 return true;
418}
419
420
421// produce_cgi_page will call get_cgihead_info and
422// produce_content in the appropriate way to output a cgi header and
423// the page content (if needed). If a page could not be created it
424// will return false
425bool receptionist::produce_cgi_page (cgiargsclass &args, ostream &contentout,
426 ostream &logout) {
427 outconvertclass text_t2ascii;
428
429 response_t response;
430 text_t response_data;
431
432 // produce cgi header
433 get_cgihead_info (args, response, response_data, logout);
434 if (response == location) {
435 // I've forgotten how to do this :-/
436 return true;
437 } else if (response == content) {
438 // content response
439 contentout << text_t2ascii << "Content-type: " << response_data << "\n\n";
440 } else {
441 // unknown response
442 logout << "Error: get_cgihead_info returned an unknown response type.\n";
443 return false;
444 }
445
446 // produce cgi page
447 if (!produce_content (args, contentout, logout)) return false;
448
449 // flush contentout
450 contentout << flush;
451 return true;
452}
453
454
455// get_cgihead_info determines the cgi header information for
456// a set of cgi arguments. If response contains location then
457// response_data contains the redirect address. If reponse
458// contains content then reponse_data contains the content-type.
459// Note that images can now be produced by the receptionist.
460void receptionist::get_cgihead_info (cgiargsclass &args, response_t &response,
461 text_t &response_data, ostream &logout) {
462 outconvertclass text_t2ascii;
463
464 // get the action
465 action *a = actions.getaction (args["a"]);
466 if (a != NULL) {
467 a->get_cgihead_info (args, response, response_data, logout);
468
469 } else {
470 // the action was not found!!
471 logout << text_t2ascii << "Error receptionist::get_cgihead_info: the action \""
472 << args["a"] << "\" could not be found.\n";
473 response = content;
474 response_data = "text/html";
475 }
476
477 // add the encoding information
478 if (response == content) {
479 if (args["w"] == "u") {
480 response_data += "; charset=UTF-8";
481 } else {
482 response_data += "; charset=ISO-8859-1";
483 }
484 }
485}
486
487
488// produce the page content
489bool receptionist::produce_content (cgiargsclass &args, ostream &contentout,
490 ostream &logout) {
491 // decide on the output conversion class
492 text_t &arg_w = args["w"];
493 rzwsoutconvertclass defaultoutconverter;
494 rzwsoutconvertclass *outconverter = converters.get_outconverter (arg_w);
495 if (outconverter == NULL) outconverter = &defaultoutconverter;
496 outconverter->reset();
497
498 // decide on the protocol used for communicating with
499 // the collection server
500 recptproto *collectproto = NULL;
501 if (!args["c"].empty()) {
502 collectproto = protocols.getrecptproto (args["c"], logout);
503 }
504
505 // produce the page using the desired action
506 action *a = actions.getaction (args["a"]);
507 if (a != NULL) {
508 if (a->uses_display(args)) prepare_page (a, args, collectproto, (*outconverter), logout);
509 if (!a->do_action (args, collectproto, disp, (*outconverter), contentout, logout))
510 return false;
511
512 } else {
513 // the action was not found!!
514 outconvertclass text_t2ascii;
515
516 logout << text_t2ascii << "Error receptionist::produce_content: the action \""
517 << args["a"] << "\" could not be found.\n";
518
519 contentout << (*outconverter)
520 << "<html>\n"
521 << "<head>\n"
522 << "<title>Error</title>\n"
523 << "</head>\n"
524 << "<body>\n"
525 << "<h2>Oops!</h2>\n"
526 << "Undefined Page. The action \""
527 << args["a"] << "\" could not be found.\n"
528 << "</body>\n"
529 << "</html>\n";
530 }
531
532 return true;
533}
534
535
536// returns the compressed argument ("e") corresponding to the argument
537// list. This can be used to save preferences between sessions.
538text_t receptionist::get_compressed_arg (cgiargsclass &args, ostream &logout) {
539 // decide on the output conversion class
540 text_t &arg_w = args["w"];
541 rzwsoutconvertclass defaultoutconverter;
542 rzwsoutconvertclass *outconverter = converters.get_outconverter (arg_w);
543 if (outconverter == NULL) outconverter = &defaultoutconverter;
544 outconverter->reset();
545
546 text_t compressed_args;
547 if (compress_save_args (argsinfo, configinfo.saveconf, args,
548 compressed_args, *outconverter, logout))
549 return compressed_args;
550
551 return "";
552}
553
554
555// will read in all the macro files. If one is not found an
556// error message will be written to logout and the method will
557// return false.
558bool receptionist::read_macrofiles (ostream &logout) {
559 outconvertclass text_t2ascii;
560
561 // redirect the error output to logout
562 disp.setlogout (&logout);
563
564 // load up the default macro files, the collection directory
565 // is searched first for the file (if this is being used in
566 // collection specific mode) and then the main directory
567 text_t colmacrodir = filename_cat (configinfo.collectdir, "macros");
568 text_t gsdlmacrodir = filename_cat (configinfo.gsdlhome, "macros");
569 text_tarray::iterator arrhere = configinfo.macrofiles.begin();
570 text_tarray::iterator arrend = configinfo.macrofiles.end();
571 text_t filename;
572 while (arrhere != arrend) {
573 // filename is used as a flag to indicate whether
574 // the macro file has been found
575 filename.clear();
576
577 // try in the collection directory if this is being
578 // run in collection specific mode
579 if (!configinfo.collection.empty()) {
580 filename = filename_cat (colmacrodir, *arrhere);
581 if (!file_exists (filename)) filename.clear ();
582 }
583
584 // if we haven't found the macro file yet try in
585 // the main macro directory
586 if (filename.empty()) {
587 filename = filename_cat (gsdlmacrodir, *arrhere);
588 if (!file_exists (filename)) filename.clear ();
589 }
590
591 // see if we found the file or not
592 if (filename.empty()) {
593 logout << text_t2ascii
594 << "Error: the macro file \"" << *arrhere << "\" could not be found.\n";
595 if (configinfo.collection.empty()) {
596 logout << text_t2ascii
597 << "It should be in " << gsdlmacrodir << ".\n\n";
598 } else {
599 logout << text_t2ascii
600 << "It should be in either " << colmacrodir << " or in "
601 << gsdlmacrodir << ".\n\n";
602 }
603 return false;
604
605 } else { // found the file
606 disp.loaddefaultmacros(filename);
607 }
608
609 arrhere++;
610 }
611
612 // success
613 return true;
614}
615
616
617// check_mainargs will check all the main arguments. If a major
618// error is found it will return false and no cgi page should
619// be created using the arguments.
620bool receptionist::check_mainargs (cgiargsclass &args, ostream &/*logout*/) {
621 // if this receptionist is running in collection dependant mode
622 // then it should always set the collection argument to the
623 // collection
624 if (!configinfo.collection.empty()) args["c"] = configinfo.collection;
625
626 // argument "v" can only be 0 or 1. Use the default value
627 // if it is out of range
628 int arg_v = args.getintarg ("v");
629 if (arg_v != 0 && arg_v != 1) {
630 cgiarginfo *vinfo = argsinfo.getarginfo ("v");
631 if (vinfo != NULL) args["v"] = vinfo->argdefault;
632 }
633
634 // argument "f" can only be 0 or 1. Use the default value
635 // if it is out of range
636 int arg_f = args.getintarg ("f");
637 if (arg_f != 0 && arg_f != 1) {
638 cgiarginfo *finfo = argsinfo.getarginfo ("f");
639 if (finfo != NULL) args["f"] = finfo->argdefault;
640 }
641
642 return true;
643}
644
645// prepare_page sets up page parameters, sets display macros
646// and opens the page ready for output
647void receptionist::prepare_page (action *a, cgiargsclass &args, recptproto *collectproto,
648 outconvertclass &outconvert, ostream &logout) {
649 // set up page parameters
650 text_t pageparams;
651
652 bool first = true;
653 if (!args["c"].empty()) {
654 pageparams += "collection=" + args["c"]; first = false;}
655 if (args.getintarg("u") == 1)
656 if (first) {pageparams += "style=htmlonly"; first = false;}
657 else pageparams += ",style=htmlonly";
658 if (args.getintarg("v") == 1)
659 if (first) {pageparams += "version=text"; first = false;}
660 else pageparams += ",version=text";
661 if (args.getintarg("f") == 1)
662 if (first) {pageparams += ",queryversion=big"; first = false;}
663 else pageparams += ",queryversion=big";
664 if (args["l"] != "en")
665 if (first) pageparams += ",language=" + args["l"];
666 else pageparams += ",language=" + args["l"];
667
668 // open the page
669 disp.openpage(pageparams, MACROPRECEDENCE);
670
671
672 // define general macros
673 define_general_macros (args, outconvert, logout);
674
675
676 // define external macros for each action
677 actionptrmap::iterator actionhere = actions.begin ();
678 actionptrmap::iterator actionend = actions.end ();
679
680 while (actionhere != actionend) {
681 assert ((*actionhere).second.a != NULL);
682 if ((*actionhere).second.a != NULL)
683 (*actionhere).second.a->define_external_macros (disp, args, collectproto, logout);
684 actionhere++;
685 }
686
687
688 // define internal macros for the current action
689 a->define_internal_macros (disp, args, collectproto, logout);
690}
691
692void receptionist::define_general_macros (cgiargsclass &args, outconvertclass &/*outconvert*/,
693 ostream &logout) {
694 disp.setmacro ("gwcgi", "Global", configinfo.gwcgi);
695 disp.setmacro ("httpimg", "Global", configinfo.httpimg);
696 disp.setmacro ("httpprefix", "Global", configinfo.httpprefix);
697 disp.setmacro("compressedoptions", "Global", get_compressed_arg(args, logout));
698
699 // set _cgiargX_ macros for each cgi argument
700 cgiargsclass::const_iterator argshere = args.begin();
701 cgiargsclass::const_iterator argsend = args.end();
702 while (argshere != argsend) {
703 if ((*argshere).first == "q")
704 // need to escape special characters from query string
705 disp.setmacro ("cgiargq", "Global", html_safe((*argshere).second.value));
706 else
707 disp.setmacro ("cgiarg" + (*argshere).first, "Global", (*argshere).second.value);
708 argshere ++;
709 }
710}
Note: See TracBrowser for help on using the repository browser.