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