root/main/trunk/greenstone2/runtime-src/src/recpt/statusaction.cpp @ 22984

Revision 22984, 38.6 KB (checked in by ak19, 8 years ago)

1. Undoing commit of 22934 where decode_commas was called on stem and fold comma separated list: previously separated due to url-encoding of commas. Now that the problem has been fixed at the source, the decode_commas hack is no longer necessary. 2. Commas in stem and fold are no longer url-encoded because the multiple_value field of the continuously-reused struct arg_ainfo is always set back to the default false after ever being set to true. So it no longer subtly stays at true to affect Greenstone functioning in unforeseen ways (such as suddenly and unnecessarily URL-encoding commas where this is not wanted).

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1/**********************************************************************
2 *
3 * statusaction.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 *********************************************************************/
25
26#include "gsdl_modules_cfg.h"
27#ifdef GSDL_USE_STATUS_ACTION
28
29// following line required to get fstream.filedesc() on darwin (Mac OS X)
30#define _STREAM_COMPAT  1
31
32#include "statusaction.h"
33#include "fileutil.h"
34#include "htmlutils.h"
35#include "gsdltools.h"
36#include <assert.h>
37#include <stdio.h>
38#include <fcntl.h> // for open() stuff
39
40void statusaction::output_frameset (cgiargsclass &/*args*/, displayclass &disp,
41                    outconvertclass &outconvert,
42                    ostream &textout, ostream &/*logout*/) {
43  textout << outconvert << disp << "_status:frameset_\n";
44}
45
46void statusaction::output_select (cgiargsclass &/*args*/, displayclass &disp,
47                  outconvertclass &outconvert,
48                  ostream &textout, ostream &/*logout*/) {
49  textout << outconvert << disp << "_status:header_(selector)\n"
50    "_status:select_\n"
51    "_status:footer_\n";
52}
53
54void statusaction::output_welcome (cgiargsclass &args, recptprotolistclass *protos,
55                   displayclass &disp, outconvertclass &outconvert,
56                   ostream &textout, ostream &logout) {
57
58  if (recpt == NULL) return;
59
60  textout << outconvert << disp
61      << "_status:infoheader_(_titlewelcome_)\n"
62      << "_status:welcome_"
63      << "<table>\n"
64      << "<th align=left>abbrev.</th><th align=left>collection</th>"
65      << "<th align=left>public?</th><th align=left>running?</th></tr>\n";
66
67  recptprotolistclass::iterator rprotolist_here = protos->begin();
68  recptprotolistclass::iterator rprotolist_end = protos->end();
69  while (rprotolist_here != rprotolist_end) {
70    if ((*rprotolist_here).p != NULL) {
71      comerror_t err;
72      text_t protoname = (*rprotolist_here).p->get_protocol_name(err);
73      text_tarray collist;
74      (*rprotolist_here).p->get_collection_list (collist, err, logout);
75      if (err == noError) {
76    text_tarray::iterator collist_here = collist.begin();
77    text_tarray::iterator collist_end = collist.end();
78
79    while (collist_here != collist_end) {
80
81        textout << outconvert << disp
82            << "<tr><td><a href=\"_gwcgi_?_optsite_e=_compressedoptions_&a=status&p=collectioninfo&pr="
83            << protoname
84            << "&c="
85            << *collist_here
86            << "\">"
87            << *collist_here
88            << "</a></td>";
89
90      ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr ((*rprotolist_here).p, *collist_here, logout);
91      if (cinfo != NULL) {
92        text_t collname = cinfo->get_collectionmeta("collectionname", args["l"]);
93        if (collname.empty()) {
94          collname = *collist_here;
95        }
96
97        textout << "<td>";
98        if (cinfo->buildDate > 0)
99          textout << outconvert << disp
100              << "<a href=\"_httppagex_(about)&c=" << *collist_here
101              << "\" target=\\_top>";
102
103        textout << outconvert << disp << collname;
104
105        if (cinfo->buildDate > 0) textout << "</a>";
106
107        textout << "</td>";
108
109        if (cinfo->isPublic) textout << "<td>yes</td>";
110        else textout << "<td>no</td>";
111       
112        if (cinfo->buildDate > 0)
113          textout << outconvert << "<td>yes</td>";
114        else
115          textout << "<td>no</td>";
116       
117      } else {
118        textout << "<td></td><td></td><td></td>";
119      }
120
121      textout << "</tr>\n";
122      ++collist_here;
123    }
124      }
125    }
126    ++rprotolist_here;
127  }
128
129  textout << "</table>\n";
130  textout << outconvert << disp << "_status:infofooter_\n";
131}
132
133void statusaction::output_generalinfo (cgiargsclass &/*args*/, displayclass &disp,
134                       outconvertclass &outconvert,
135                       ostream &textout, ostream &/*logout*/) {
136  if (recpt == NULL) return;
137  const recptconf &rcinfo = recpt->get_configinfo ();
138 
139  textout << outconvert << disp << "_status:infoheader_(General Information)\n";
140  textout << outconvert
141      << "<h2>General information</h2>\n"
142      << "<table>\n"
143      << "<tr valign=top><th>gsdlhome</th><td>\"" << rcinfo.gsdlhome
144      << "\"</td></tr>\n"
145      << "<tr valign=top><th>collection</th><td>\"" << rcinfo.collection
146      << "\"</td></tr>\n"
147      << "<tr valign=top><th>collectdir</th><td>\"" << rcinfo.collectdir
148      << "\"</td></tr>\n"
149      << "<tr valign=top><th>httpprefix</th><td>\"" << rcinfo.httpprefix
150      << "\"</td></tr>\n"
151      << "<tr valign=top><th>httpweb</th><td>\"" << rcinfo.httpweb
152      << "\"</td></tr>\n"
153      << "<tr valign=top><th>gwcgi</th><td>\"" << rcinfo.gwcgi
154      << "\"</td></tr>\n";
155   
156  // macrofiles
157  textout << outconvert << "<tr valign=top><th>macrofiles</th><td>";
158  text_tset::const_iterator macrohere = rcinfo.macrofiles.begin ();
159  text_tset::const_iterator macroend = rcinfo.macrofiles.end ();
160  bool macrofirst = true;
161  while (macrohere != macroend) {
162    if (!macrofirst) textout << outconvert << ", ";
163    macrofirst = false;
164    textout << outconvert << "\"" << *macrohere << "\"";
165    ++macrohere;
166  }
167  textout << outconvert << "</td></tr>\n";
168 
169  // saveconf
170  textout << outconvert << "<tr valign=top><th>saveconf</th><td>\"" << rcinfo.saveconf
171      << "\"</td></tr>\n";
172
173  // usecookies
174  textout << outconvert << "<tr valign=top><th>usecookies</th><td>\"";
175  if (rcinfo.usecookies) textout << outconvert << "true";
176  else textout << outconvert << "false";
177  textout << outconvert << "\"</td></tr>\n";
178 
179  // logcgiargs
180  textout << outconvert << "<tr valign=top><th>logcgiargs</th><td>\"";
181  if (rcinfo.logcgiargs) textout << outconvert << "true";
182  else textout << outconvert << "false";
183  textout << outconvert << "\"</td></tr>\n";
184
185  // pageparams
186  textout << outconvert << "<tr valign=top><th>pageparams</th><td>";
187  text_tmap::const_iterator params_here = rcinfo.pageparams.begin();
188  text_tmap::const_iterator params_end = rcinfo.pageparams.end();
189  bool params_first = true;
190  while (params_here != params_end) {
191    if (!params_first) textout << outconvert << ", ";
192    params_first = false;
193    textout << outconvert << "\"" << (*params_here).first << "\" != \""
194        << (*params_here).second << "\"";
195   
196    ++params_here;
197  }
198  textout << outconvert << "</td></tr>\n";
199
200  // macroprecedence
201  textout << outconvert << "<tr valign=top><th>macroprecedence</th><td>\"" << rcinfo.macroprecedence
202      << "\"</td></tr>\n";
203
204  // arguments
205  cgiargsinfoclass *rcargsinfo = recpt->get_cgiargsinfo_ptr ();
206  if (rcargsinfo != NULL) {
207    textout << outconvert << "<tr valign=top><th>arguments</th><td>";
208   
209    cgiargsinfoclass::const_iterator argsinfohere = rcargsinfo->begin ();
210    cgiargsinfoclass::const_iterator argsinfoend = rcargsinfo->end ();
211    bool argsinfofirst = true;
212    while (argsinfohere != argsinfoend) {
213      if (!argsinfofirst) textout << outconvert << ", ";
214      argsinfofirst = false;
215      textout << outconvert << "\"" << (*argsinfohere).second.shortname << "\"";
216      ++argsinfohere;
217    }
218   
219    textout << outconvert << "</td></tr>\n";
220  }     
221 
222  // actions
223  actionmapclass *actions = recpt->get_actionmap_ptr();
224  if (actions != NULL) {
225    textout << outconvert << "<tr valign=top><th>actions</th><td>";
226   
227    actionptrmap::iterator actionshere = actions->begin ();
228    actionptrmap::iterator actionsend = actions->end ();
229    bool actionsfirst = true;
230    while (actionshere != actionsend) {
231      if (!actionsfirst) textout << outconvert << ", ";
232      actionsfirst = false;
233      assert ((*actionshere).second.a != NULL);
234      if ((*actionshere).second.a != NULL) {
235    textout << outconvert << "\"" << (*actionshere).second.a->get_action_name() << "\"";
236      }
237      ++actionshere;
238    }
239   
240    textout << outconvert << "</td></tr>\n";
241  }
242 
243  // browsers
244  browsermapclass *browsers = recpt->get_browsermap_ptr();
245  if (browsers != NULL) {
246    textout << outconvert << "<tr valign=top><th>browsers</th><td>";
247   
248    browserptrmap::iterator browsershere = browsers->begin ();
249    browserptrmap::iterator browsersend = browsers->end ();
250    bool browsersfirst = true;
251    while (browsershere != browsersend) {
252      if (!browsersfirst) textout << outconvert << ", ";
253      browsersfirst = false;
254      assert ((*browsershere).second.b != NULL);
255      if ((*browsershere).second.b != NULL) {
256    textout << outconvert << "\"" << (*browsershere).second.b->get_browser_name() << "\"";
257      }
258      ++browsershere;
259    }
260   
261    textout << outconvert << "</td></tr>\n";
262  }
263
264  // protocols
265  recptprotolistclass *protocols = recpt->get_recptprotolist_ptr ();
266  if (protocols != NULL) {
267    textout << outconvert << "<tr valign=top><th>protocols</th><td>";
268   
269    recptprotolistclass::iterator protohere = protocols->begin ();
270    recptprotolistclass::iterator protoend = protocols->end ();
271    bool protofirst = true;
272    while (protohere != protoend) {
273      comerror_t err;
274      if (!protofirst) textout << outconvert << ", ";
275      protofirst = false;
276      if ((*protohere).p != NULL) {
277    textout << outconvert << "\"" << (*protohere).p->get_protocol_name(err) << "\"";
278      }
279      ++protohere;
280    }
281   
282    textout << outconvert << "</td></tr>\n";
283  }
284 
285  // converters
286  convertinfoclass *converters = recpt->get_convertinfo_ptr ();
287  if (converters != NULL) {
288    textout << outconvert << "<tr valign=top><th>converters</th><td>";
289   
290    convertinfoclass::iterator converthere = converters->begin ();
291    convertinfoclass::iterator convertend = converters->end ();
292    bool convertfirst = true;
293    while (converthere != convertend) {
294      if (!convertfirst) textout << outconvert << ", ";
295      convertfirst = false;
296      textout << outconvert << "\"" << (*converthere).second.name << "\"";
297      ++converthere;
298    }
299   
300    textout << outconvert << "</td></tr>\n";
301  }
302 
303  textout << outconvert << disp << "</table>\n_status:infofooter_\n";
304}
305
306void statusaction::output_argumentinfo (cgiargsclass &args, displayclass &disp,
307                    outconvertclass &outconvert,
308                    ostream &textout, ostream &/*logout*/) {
309  if (recpt == NULL) return;
310  cgiargsinfoclass *rcargsinfo = recpt->get_cgiargsinfo_ptr ();
311  if (rcargsinfo == NULL) return;
312
313  textout << outconvert << disp << "_status:infoheader_(Argument Information)\n";
314  textout << outconvert
315      << "<h2>Argument information</h2>\n"
316      << "<table>";
317
318  // argument information
319  textout << outconvert << "<tr valign=top><th>short name</th><th>long name</th>"
320      << "<th>multiple char?</th>"
321      << "<th>multiple value?</th>"
322      << "<th>default</th><th>default status</th><th>saved args</th>"
323      << "<th>current value</th></tr>\n";
324 
325
326  cgiargsinfoclass::const_iterator argsinfohere = rcargsinfo->begin();
327  cgiargsinfoclass::const_iterator argsinfoend = rcargsinfo->end();
328  text_t *arg_value;
329  while (argsinfohere != argsinfoend) {
330    const cgiarginfo &ainfo = (*argsinfohere).second;
331    textout << outconvert
332        << "<tr valign=top><td>" << ainfo.shortname << "</td>\n";
333   
334    textout << outconvert << "<td>" << ainfo.longname << "</td>\n";
335    if (ainfo.multiplechar) textout << outconvert << "<td>yes</td>\n";
336    else textout << outconvert << "<td>no</td>\n";
337    if (ainfo.multiplevalue) textout << outconvert << "<td>yes</td>\n";
338    else textout << outconvert << "<td>no</td>\n";
339    textout << outconvert << "<td>" << ainfo.argdefault << "</td>\n";
340    switch (ainfo.defaultstatus) {
341    case cgiarginfo::none: textout << outconvert << "<td>none</td>\n"; break;
342    case cgiarginfo::weak: textout << outconvert << "<td>weak</td>\n"; break;
343    case cgiarginfo::good: textout << outconvert << "<td>good</td>\n"; break;
344    case cgiarginfo::config: textout << outconvert << "<td>config</td>\n"; break;
345    case cgiarginfo::imperative: textout << outconvert << "<td>imperative</td>\n"; break;
346    }
347    switch (ainfo.savedarginfo) {
348    case cgiarginfo::mustnot: textout << outconvert << "<td>mustnot</td>\n"; break;
349    case cgiarginfo::can: textout << outconvert << "<td>can</td>\n"; break;
350    case cgiarginfo::must: textout << outconvert << "<td>must</td>\n"; break;
351    }
352   
353    arg_value = args.getarg (ainfo.shortname);
354    if (arg_value == NULL) textout << outconvert << "<td></td></tr>\n";
355    else textout << outconvert << "<td>\"" << *arg_value << "\"</td></tr>\n";
356   
357    ++argsinfohere;
358  }
359 
360  textout << outconvert << disp << "</table>\n_status:infofooter_\n";
361}
362
363void statusaction::output_actioninfo (cgiargsclass &/*args*/, displayclass &disp,
364                      outconvertclass &outconvert,
365                      ostream &textout, ostream &/*logout*/) {
366  if (recpt == NULL) return;
367  actionmapclass *actions = recpt->get_actionmap_ptr();
368
369  textout << outconvert << disp << "_status:infoheader_(Action Information)\n";
370  textout << outconvert
371      << "<h2>Action information</h2>\n"
372      << "<table>";
373
374  // action information
375  if (actions != NULL) {
376    textout << outconvert
377        << "<tr><th>action name</th><th>cgi arguments</th></tr>\n";
378   
379    actionptrmap::iterator actionshere = actions->begin ();
380    actionptrmap::iterator actionsend = actions->end ();
381    while (actionshere != actionsend) {
382      assert ((*actionshere).second.a != NULL);
383      if ((*actionshere).second.a != NULL) {
384    textout << outconvert
385        << "<tr><td>" << (*actionshere).second.a->get_action_name()
386        << "</td><td>";
387   
388    cgiargsinfoclass *argsinfo = (*actionshere).second.a->getargsinfo();
389    cgiargsinfoclass::const_iterator argsinfohere = argsinfo->begin ();
390    cgiargsinfoclass::const_iterator argsinfoend = argsinfo->end ();
391    bool aifirst = true;
392    while (argsinfohere != argsinfoend) {
393      if (!aifirst) textout << outconvert << ", ";
394      aifirst = false;
395      textout << outconvert << (*argsinfohere).second.shortname;
396      ++argsinfohere;
397    }
398   
399    textout << outconvert << "</td></tr>\n";
400      }
401      ++actionshere;
402    }
403  }
404 
405  textout << outconvert << disp << "</table>\n_status:infofooter_\n";
406}
407
408void statusaction::output_browserinfo (cgiargsclass &/*args*/, displayclass &disp,
409                       outconvertclass &outconvert,
410                       ostream &textout, ostream &/*logout*/) {
411  if (recpt == NULL) return;
412  browsermapclass *browsers = recpt->get_browsermap_ptr();
413
414  textout << outconvert << disp << "_status:infoheader_(Browser Information)\n";
415  textout << outconvert
416      << "<h2>Browser information</h2>\n"
417      << "<table>";
418
419  // browser information
420  if (browsers != NULL) {
421    textout << outconvert
422        << "<tr><th>browser name</th><th>default formatstring</th></tr>\n";
423   
424    browserptrmap::iterator browsershere = browsers->begin ();
425    browserptrmap::iterator browsersend = browsers->end ();
426    while (browsershere != browsersend) {
427      assert ((*browsershere).second.b != NULL);
428      if ((*browsershere).second.b != NULL) {
429    textout << outconvert
430        << "<tr><td>" << (*browsershere).second.b->get_browser_name()
431        << "</td><td>" << html_safe ((*browsershere).second.b->get_default_formatstring())
432        << "</td></tr>\n";
433      }
434      ++browsershere;
435    }
436  }
437 
438  textout << outconvert << disp << "</table>\n_status:infofooter_\n";
439}
440
441void statusaction::output_protocolinfo (cgiargsclass &/*args*/, displayclass &disp,
442                    outconvertclass &outconvert,
443                    ostream &textout, ostream &logout) {
444  if (recpt == NULL) return;
445  const recptconf &rcinfo = recpt->get_configinfo ();
446  bool colspecific = !rcinfo.collection.empty();
447  bool unreachablecol = false;
448
449  recptprotolistclass *rprotolist = recpt->get_recptprotolist_ptr ();
450  if (rprotolist == NULL) return;
451
452  textout << outconvert << disp << "_status:infoheader_(Protocol Information)\n";
453  textout << outconvert
454      << "<h2>Protocol information</h2>\n"
455      << "<table>\n"
456      << "<tr><th>protocol</th><th>collections</th></tr>\n";
457
458  text_t protoname;
459  recptprotolistclass::iterator rprotolist_here = rprotolist->begin();
460  recptprotolistclass::iterator rprotolist_end = rprotolist->end();
461  while (rprotolist_here != rprotolist_end) {
462    if ((*rprotolist_here).p != NULL) {
463      comerror_t err;
464      protoname = (*rprotolist_here).p->get_protocol_name(err);
465      textout << outconvert
466          << "<tr><td>"
467          << protoname
468          << "</td><td>";
469
470      text_tarray collist;
471      (*rprotolist_here).p->get_collection_list (collist, err, logout);
472      if (err == noError) {
473    text_tarray::iterator collist_here = collist.begin();
474    text_tarray::iterator collist_end = collist.end();
475    bool first = true;
476    while (collist_here != collist_end) {
477      if (!first) textout << outconvert << ", ";
478      first = false;
479
480      if (colspecific && *collist_here != rcinfo.collection) {
481        unreachablecol = true;
482        textout << outconvert << "\"" << *collist_here << "\"";
483      } else {
484        textout << outconvert << disp
485            << "\"<a href=\"_gwcgi_?e=_compressedoptions_&a=status&p=collectioninfo&pr="
486            << protoname
487            << "&c="
488            << *collist_here
489            << "\">"
490            << *collist_here
491            << "</a>\"";
492      }
493
494      ++collist_here;
495    }
496
497      } else {
498    textout << outconvert << "Error (" << get_comerror_string (err)
499        << ") while getting collect list\n";
500      }
501
502      textout << outconvert
503          << "</td></tr>\n";
504    }
505
506    ++rprotolist_here;
507  }
508
509  textout << outconvert << "</table>\n";
510  if (unreachablecol) {
511    textout << outconvert
512        << "<b>Warning:</b> the receptionist is running in collection specific\n"
513        << "mode making some of the collections unreachable.\n";
514  }
515  textout << outconvert << disp << "_status:infofooter_\n";
516}
517
518void statusaction::output_collectioninfo (cgiargsclass &args, displayclass &disp,
519                      outconvertclass &outconvert,
520                      ostream &textout, ostream &logout) {
521  if (recpt == NULL) return;
522
523  textout << outconvert << disp << "_status:infoheader_(Collection info)\n";
524  textout << outconvert << "<h2>Collection info</h2>\n";
525
526  // get the list of protocols
527  recptprotolistclass *rprotolist = recpt->get_recptprotolist_ptr ();
528  if (rprotolist == NULL) return;
529
530  // look for the desired protocol
531  text_t &arg_pr = args["pr"];
532  text_t &arg_c = args["c"];
533  recptproto *rproto = NULL;
534  recptprotolistclass::iterator rprotolist_here = rprotolist->begin();
535  recptprotolistclass::iterator rprotolist_end = rprotolist->end();
536  while (rprotolist_here != rprotolist_end) {
537    rproto = (*rprotolist_here).p;
538    comerror_t err;
539    if (rproto != NULL && rproto->get_protocol_name(err) == arg_pr) {
540      // see if the protocol has the collection
541      bool hascollection;
542      rproto->has_collection (arg_c, hascollection, err, logout);
543      if (err == noError && hascollection) break;
544    }
545    ++rprotolist_here;
546  }
547 
548  if (rprotolist_here == rprotolist_end) {
549    textout << outconvert << "Protocol \"" << arg_pr << "\" with collection \""
550        << arg_c << "\" was not found\n";
551
552  } else {
553    // rproto can't be NULL to get here
554    ColInfoResponse_t *collectinfo = recpt->get_collectinfo_ptr (rproto, arg_c, logout);
555    if (collectinfo != NULL) {
556      textout << outconvert << "<table>\n"
557          << "<tr><th>collection name</th><td>\""
558          << collectinfo->shortInfo.name
559          << "\"</td></tr>\n"
560
561          << "<tr><th>host</th><td>\""
562          << collectinfo->shortInfo.host
563          << "\"</td></tr>\n"
564
565          << "<tr><th>port</th><td>\""
566          << collectinfo->shortInfo.port
567          << "\"</td></tr>\n"
568
569          << "<tr><th>is public?</th><td>";
570      if (collectinfo->isPublic) textout << outconvert << "true";
571      else textout << outconvert << "false";
572      textout << outconvert
573          << "</td></tr>\n"
574
575          << "<tr><th>is beta?</th><td>";
576      if (collectinfo->isBeta) textout << outconvert << "true";
577      else textout << outconvert << "false";
578      textout << outconvert
579          << "</td></tr>\n"
580
581          << "<tr><th>use realistic book?</th><td>";
582      if (collectinfo->useBook) textout << outconvert << "true";
583      else textout << outconvert << "false";
584      textout << outconvert
585          << "</td></tr>\n"
586         
587          << "<tr><th>build date</th><td>\""
588          << collectinfo->buildDate
589          << "\"</td></tr>\n"
590
591          << "<tr><th>interface languages</th><td>";
592      text_tarray::iterator languages_here = collectinfo->languages.begin();
593      text_tarray::iterator languages_end = collectinfo->languages.end();
594      bool languages_first = true;
595      while (languages_here != languages_end) {
596    if (!languages_first) textout << outconvert << ", ";
597    languages_first = false;
598    textout << outconvert << "\"" << *languages_here << "\"";
599    ++languages_here;
600      }
601
602      textout << "<tr><th valign=top>collection metadata</th><td><table>\n";
603      collectionmeta_map::iterator meta_here = collectinfo->collectionmeta.begin();
604      collectionmeta_map::iterator meta_end = collectinfo->collectionmeta.end();
605     
606      while (meta_here != meta_end) {
607    textout << outconvert << "<tr><td valign=top>" << (*meta_here).first
608        << "</td><td><table>" ;
609        text_tmap lang_map = (*meta_here).second;
610    text_tmap::iterator lang_here = lang_map.begin();
611    text_tmap::iterator lang_end = lang_map.end();
612    while (lang_here != lang_end) {
613      textout << outconvert << "<tr><td>" << (*lang_here).first
614            << "</td><td>" << (*lang_here).second << "</td></tr>\n";
615     
616      ++lang_here;
617    }
618    textout << outconvert << "</table></td></tr>\n";
619    ++meta_here;
620      }
621      textout << "</table></td></tr>\n";
622
623      textout << "<tr><th valign=top>format info</th><td><table>\n";
624      text_tmap::iterator format_here = collectinfo->format.begin();
625      text_tmap::iterator format_end = collectinfo->format.end();
626      while (format_here != format_end) {
627    textout << outconvert << "<tr><td valign=top>" << (*format_here).first
628        << "</td><td>" << html_safe((*format_here).second) << "</td></tr>\n";
629    ++format_here;
630      }
631      textout << "</table></td></tr>\n";
632
633      textout << "<tr><th valign=top>building info</th><td><table>\n";
634      text_tmap::iterator building_here = collectinfo->building.begin();
635      text_tmap::iterator building_end = collectinfo->building.end();
636      while (building_here != building_end) {
637    textout << outconvert << "<tr><td>" << (*building_here).first
638        << "</td><td>" << (*building_here).second << "</td></tr>\n";
639    ++building_here;
640      }
641      textout << "</table></td></tr>\n";
642
643      textout << outconvert
644          << "</td></tr>\n"
645
646          << "<tr><th>number of documents</th><td>\""
647          << collectinfo->numDocs
648          << "\"</td></tr>\n"
649
650          << "<tr><th>number of sections</th><td>\""
651          << collectinfo->numSections
652          << "\"</td></tr>\n"
653
654          << "<tr><th>number of words</th><td>\""
655          << collectinfo->numWords
656          << "\"</td></tr>\n"
657
658          << "<tr><th>number of bytes</th><td>\""
659          << collectinfo->numBytes
660          << "\"</td></tr>\n"
661
662          << "<tr><th>preferred receptionist</th><td>\""
663          << collectinfo->receptionist
664          << "\"</td></tr>\n"
665
666          << "</table>";
667     
668    } else {
669      textout << "ERROR (statusaction::output_collectioninfo): while getting collect information\n";
670    }
671
672
673    InfoFiltersResponse_t filterinfo;
674    InfoFilterOptionsRequest_t filteroptions_request;
675    InfoFilterOptionsResponse_t filteroptions;
676    comerror_t err;
677    rproto->get_filterinfo (arg_c, filterinfo, err, logout);
678    if (err == noError) {
679      text_tset::iterator filternames_here = filterinfo.filterNames.begin();
680      text_tset::iterator filternames_end = filterinfo.filterNames.end();
681      while (filternames_here != filternames_end) {
682    textout << outconvert
683        << "<hr>\n"
684        << "<h3>Filter options for \"" << (*filternames_here) << "\"</h3>\n"
685        << "<table>\n"
686        << "<tr><th>option name</th><th>type</th><th>repeatable</th>"
687        << "<th>default value</th><th>valid values</th></tr>\n";
688
689    filteroptions_request.clear();
690    filteroptions_request.filterName = *filternames_here;
691    rproto->get_filteroptions (arg_c, filteroptions_request,
692                   filteroptions, err, logout);
693    if (err == noError) {
694      FilterOption_tmap::iterator filteropt_here =
695        filteroptions.filterOptions.begin();
696      FilterOption_tmap::iterator filteropt_end =
697        filteroptions.filterOptions.end();
698      while (filteropt_here != filteropt_end) {
699        textout << outconvert
700            << "<tr><td>\""
701            << (*filteropt_here).second.name
702            << "\"</td>\n"
703         
704            << "<td>";
705        text_t type_string;
706        switch ((*filteropt_here).second.type) {
707        case FilterOption_t::booleant: type_string = "boolean"; break;
708        case FilterOption_t::integert: type_string = "integer"; break;
709        case FilterOption_t::enumeratedt: type_string = "enumerated"; break;
710        case FilterOption_t::stringt: type_string = "string"; break;
711        }
712        textout << outconvert
713            << type_string
714            << "</td>\n"
715         
716            << "<td>";
717        text_t repeat_string;
718        switch ((*filteropt_here).second.repeatable) {
719        case FilterOption_t::onePerQuery: repeat_string = "one per query"; break;
720        case FilterOption_t::onePerTerm: repeat_string = "one per term"; break;
721        case FilterOption_t::nPerTerm: repeat_string = "n per term"; break;
722        }
723        textout << outconvert
724            << repeat_string
725            << "</td>\n"
726         
727            << "<td>\""
728            << (*filteropt_here).second.defaultValue
729            << "\"</td>\n"
730         
731            << "<td>";
732       
733        text_tarray::iterator valid_here =
734          (*filteropt_here).second.validValues.begin();
735        text_tarray::iterator valid_end =
736          (*filteropt_here).second.validValues.end();
737        bool valid_first = true;
738        while (valid_here != valid_end) {
739          if (!valid_first) textout << outconvert << ", ";
740          valid_first = false;
741          textout << outconvert << "\"" << *valid_here << "\"";
742          ++valid_here;
743        }
744        textout << outconvert
745            << "</td></tr>\n";
746
747        ++filteropt_here;
748      }
749
750      textout << outconvert
751          << "</table>\n";
752
753    } else {
754      textout << outconvert << "Error (" << get_comerror_string (err)
755          << ") while getting filter option information\n";
756    }
757
758    ++filternames_here;
759      }
760
761    } else {
762      textout << outconvert << "Error (" << get_comerror_string (err)
763          << ") while getting filter information\n";
764    }
765  }
766 
767  textout << outconvert << disp << "_status:infofooter_\n";
768}
769
770void statusaction::output_usagelog (cgiargsclass &/*args*/, displayclass &disp,
771                    outconvertclass &outconvert,
772                    ostream &textout, ostream &/*logout*/) {
773
774  // output last 100 lines of usage.txt
775
776  text_t logfilename = filename_cat (gsdlhome, "etc", "usage.txt");
777
778  textout << outconvert << disp << "_status:infoheader_(Usage log)\n";
779  textout << outconvert << "<h2>Usage log</h2>\n";
780
781  textout << outconvert << "<p>The usage log, "
782      << logfilename << ", contains the\n"
783      << "following information:\n"
784      << "<p>(note that if this file is more than 100 lines long only the last 100 lines will\n"
785      << "be displayed on this page)\n\n"
786      << "<pre>\n";
787
788  // note that we're expecting lines to be no more than 1500 characters on
789  // average - should fix this file_tail() thing sometime
790  textout << outconvert << file_tail (logfilename, 100, 1500);
791
792  textout << outconvert << disp << "</pre>\n"
793      << "_status:infofooter_\n";
794}
795
796void statusaction::output_errorlog (cgiargsclass &/*args*/, displayclass &disp,
797                    outconvertclass &outconvert,
798                    ostream &textout, ostream &logout) {
799
800  text_t errfilename = filename_cat (gsdlhome, "etc", "error.txt");
801  char *cerrfilename = errfilename.getcstr();
802  if (cerrfilename == NULL) return;
803
804  textout << outconvert << disp << "_status:infoheader_(Error log)\n";
805  textout << outconvert << "<h2>Error log</h2>\n";
806  logout << flush;
807
808#ifdef GSDL_USE_IOS_H
809  ifstream errin (cerrfilename, ios::in | ios::nocreate);
810#else
811  ifstream errin (cerrfilename, ios::in);
812#endif
813
814  delete []cerrfilename;
815  if (errin) {
816    textout << outconvert << "<p>The error log, "
817        << errfilename << ", contains the\n";
818    textout << outconvert << "following information:\n\n";
819    text_t errorpage = "<p><pre>\n";
820
821    char c;
822    errin.get(c);
823    while (!errin.eof ()) {
824      errorpage.push_back(c);
825      errin.get(c);
826    }
827   
828    errorpage += "</pre>\n";
829    errin.close();
830    textout << outconvert << errorpage;
831
832  } else {
833    textout << outconvert << "Couldn't read error log, "
834        << errfilename << ".\n";
835  }
836
837  textout << outconvert << disp << "_status:infofooter_\n";
838}
839
840void statusaction::output_llssite (cgiargsclass &/*args*/, displayclass &disp,
841                    outconvertclass &outconvert,
842                    ostream &textout, ostream &logout) {
843
844  textout << outconvert << disp << "_status:infoheader_(llssite.cfg)\n";
845  textout << outconvert << "<h2>llssite.cfg</h2>\n";
846  logout << flush;
847
848#ifdef GSDL_LOCAL_LIBRARY
849  text_t llssite_cfg = filename_cat (gsdlhome, "llssite.cfg");
850#else
851  text_t llssite_cfg = "llssite.cfg";
852#endif
853
854  char *llssite_cfgc = llssite_cfg.getcstr();
855#ifdef GSDL_USE_IOS_H
856  ifstream llssitein (llssite_cfgc, ios::in | ios::nocreate);
857#else
858  ifstream llssitein (llssite_cfgc, ios::in);
859#endif
860
861  delete []llssite_cfgc;
862
863  if (llssitein) {
864    textout << "<p>The llssite.cfg configuration file contains the\n"
865        << "following information:\n\n";
866    text_t llssite = "<p><pre>\n";
867
868    char c;
869    llssitein.get(c);
870    while (!llssitein.eof ()) {
871      llssite.push_back(c);
872      llssitein.get(c);
873    }
874   
875    llssite += "</pre>\n";
876    llssitein.close();
877    textout << outconvert << llssite;
878
879  } else {
880    textout << "Couldn't read llssite.cfg configuration file\n";
881  }
882
883  textout << outconvert << disp << "_status:infofooter_\n";
884}
885
886void statusaction::output_maincfg (cgiargsclass &/*args*/, displayclass &disp,
887                   outconvertclass &outconvert,
888                   ostream &textout, ostream &/*logout*/) {
889
890  text_t maincfgfile = filename_cat (dbhome, "etc", "main.cfg");
891
892  textout << outconvert << disp << "_status:infoheader_(main.cfg)\n"
893      << "<h2>main.cfg</h2>\n"
894      << "<p>The main configuration file, "
895      << dm_safe(maincfgfile) << ", contains the following information:<br>\n\n"
896      << "(Note that only users belonging to the \"administrator\" group "
897      << "may edit this file)<br>\n"
898      << "_status:maincfg_<br>\n"
899      << "_status:infofooter_\n";
900}
901
902void statusaction::change_maincfg (cgiargsclass &args, displayclass &disp,
903                   outconvertclass &outconvert,
904                   ostream &textout, ostream &logout) {
905
906  // write out the contents of the cfgfile argument to main.cfg
907  text_t cfgfile = filename_cat(gsdlhome, "etc", "main.cfg");
908  char *cfgfilec = cfgfile.getcstr();
909
910  int fd=open(cfgfilec, O_WRONLY | O_CREAT | O_TRUNC
911#if defined(__WIN32__)
912          | O_BINARY
913#endif
914          , 432);
915
916  if (fd != -1) {
917
918    int lock_val = 1;
919    GSDL_LOCK_FILE (fd);
920    if (lock_val != 0) {
921      logout << "statusaction::change_maincfg: Error: Couldn't lock file " << cfgfilec << "\n";
922      textout << outconvert << disp << "_status:changemaincfgfail_";
923      close (fd);
924    } else {
925      outconvertclass text_t2ascii;
926      text_t2ascii.setinput(&args["cfgfile"]);
927      size_t buffersize=args["cfgfile"].size();
928      char *buffer=new char[buffersize];
929      size_t num_chars;
930      convertclass::status_t status;
931      text_t2ascii.convert(buffer, buffersize, num_chars, status);
932      // ignore status - assume it is "finished" as buffer is big enough
933      write(fd, buffer, num_chars);
934      GSDL_UNLOCK_FILE (fd);
935      delete []buffer;
936      close (fd);
937      textout << outconvert << disp << "_status:changemaincfgsuccess_";
938    }
939  } else {
940    logout << "statusaction::change_maincfg: Error: Couldn't open file " << cfgfilec << "for writing\n";
941    textout << outconvert << disp << "_status:changemaincfgfail_";
942  }
943  delete []cfgfilec;
944}
945
946void statusaction::output_errorpage (outconvertclass &outconvert,
947                     ostream &textout, ostream &/*logout*/,
948                     text_t message) {
949  textout << outconvert
950      << "<html>\n"
951      << "<head>\n"
952      << "<title>Error</title>\n"
953      << "</head>\n"
954      << "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#006666\" "
955      << "alink=\"#cc9900\" vlink=\"#666633\">\n"
956      << "<h2>Oops!</h2>\n"
957      << message
958      << "\n</body>\n"
959      << "</html>\n";
960  return;
961}
962
963
964
965statusaction::statusaction () {
966  disabled = true;
967  recpt = NULL;
968
969  // this action uses cgi variable "a"
970  cgiarginfo arg_ainfo;
971  arg_ainfo.shortname = "a";
972  arg_ainfo.longname = "action";
973  arg_ainfo.multiplechar = true;
974  arg_ainfo.multiplevalue = false;
975  arg_ainfo.defaultstatus = cgiarginfo::weak;
976  arg_ainfo.argdefault = "status";
977  arg_ainfo.savedarginfo = cgiarginfo::must;
978  argsinfo.addarginfo (NULL, arg_ainfo);
979
980  // "p" -- status page
981  arg_ainfo.shortname = "p";
982  arg_ainfo.longname = "page";
983  arg_ainfo.multiplechar = true;
984  arg_ainfo.multiplevalue = false;
985  arg_ainfo.defaultstatus = cgiarginfo::weak;
986  arg_ainfo.argdefault = "frameset";
987  arg_ainfo.savedarginfo = cgiarginfo::must;
988  argsinfo.addarginfo (NULL, arg_ainfo);
989
990  // "pr" -- protocol
991  arg_ainfo.shortname = "pr";
992  arg_ainfo.longname = "protocol";
993  arg_ainfo.multiplechar = true;
994  arg_ainfo.multiplevalue = false;
995  arg_ainfo.defaultstatus = cgiarginfo::none;
996  arg_ainfo.argdefault = g_EmptyText;
997  arg_ainfo.savedarginfo = cgiarginfo::can;
998  argsinfo.addarginfo (NULL, arg_ainfo);
999
1000  arg_ainfo.shortname = "cfgfile";
1001  arg_ainfo.longname = "configuration file contents";
1002  arg_ainfo.multiplechar = true;
1003  arg_ainfo.multiplevalue = false;
1004  arg_ainfo.defaultstatus = cgiarginfo::weak;
1005  arg_ainfo.argdefault = g_EmptyText;
1006  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
1007  argsinfo.addarginfo (NULL, arg_ainfo);
1008}
1009
1010statusaction::~statusaction () {
1011}
1012
1013bool statusaction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &args,
1014                  recptprotolistclass * /*protos*/, ostream &/*logout*/) {
1015
1016  // only users belonging to the "administrator" group may edit
1017  // the main.cfg file
1018  if (args["p"] == "maincfg" || args["p"] == "changemaincfg") {
1019    args["uan"] = "1";
1020    args["ug"] = "administrator";
1021  }
1022  return true;
1023}
1024
1025void statusaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
1026                     response_t &response, text_t &response_data,
1027                     ostream &/*logout*/) {
1028  response = content;
1029  response_data = "text/html";
1030}
1031
1032
1033void statusaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
1034                       recptprotolistclass * /*protos*/, ostream &logout) {
1035
1036  // define_internal_macros sets the following macros:
1037  // _maincfgfile_   the contents of the main.cfg configuration file
1038
1039  // _versionnnum_   greenstone version number (hard-coded)
1040
1041  disp.setmacro("versionnum", "status", GSDL_VERSION);
1042
1043  if (args["p"] == "maincfg") {
1044
1045    // read in main.cfg
1046    text_t maincfg = filename_cat(gsdlhome, "etc", "main.cfg"); 
1047    char *maincfgc = maincfg.getcstr();
1048   
1049#ifdef GSDL_USE_IOS_H
1050    ifstream cfg_ifs (maincfgc, ios::in | ios::nocreate);
1051#else
1052    ifstream cfg_ifs (maincfgc, ios::in);
1053#endif
1054   
1055    if (cfg_ifs) { 
1056      text_t cfgtext;
1057      char c;
1058      cfg_ifs.get(c);
1059      while (!cfg_ifs.eof ()) {
1060    cfgtext.push_back(c);
1061    cfg_ifs.get(c);
1062      }
1063      cfg_ifs.close();
1064     
1065      // define it as a macro
1066      disp.setmacro("maincfgfile", "status", dm_safe(cfgtext));
1067     
1068    } else {
1069      logout << "statusaction::define_internal_macros: couldn't open configuration file ("
1070         << maincfgc << ") for reading\n";
1071      disp.setmacro("maincfgfile", "status", g_EmptyText);
1072    }   
1073    delete []maincfgc;
1074  }
1075}
1076
1077bool statusaction::do_action (cgiargsclass &args, recptprotolistclass *protos,
1078                  browsermapclass * /*browsers*/, displayclass &disp,
1079                  outconvertclass &outconvert, ostream &textout,
1080                  ostream &logout) {
1081  // make sure the status function is enabled
1082  if (disabled) {
1083    textout << outconvert
1084        << "<html>\n"
1085        << "<head>\n"
1086        << "<title>Status disabled</title>\n"
1087        << "</head>\n"
1088        << "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#006666\" "
1089        << "alink=\"#cc9900\" vlink=\"#666633\">\n"
1090        << "<h2>Facility disabled</h2>\n"
1091        << "Sorry, the Maintenance and Administration facility is currently disabled\n"
1092        << "\n</body>\n"
1093        << "</html>\n";
1094    return true;
1095  }
1096 
1097  // make sure we know about a receptionist
1098  if (recpt == NULL) {
1099    output_errorpage (outconvert, textout, logout,
1100              "The status action does not contain information\n"
1101              "about any receptionists. The method set_receptionist\n"
1102              "was probably not called from the module which instantiated\n"
1103              "this status action.\n");
1104    return true;
1105  }
1106
1107  // check to make sure status.dm was read in
1108  const recptconf &rcinfo = recpt->get_configinfo ();
1109  text_tset::const_iterator macrohere = rcinfo.macrofiles.begin ();
1110  text_tset::const_iterator macroend = rcinfo.macrofiles.end ();
1111  while (macrohere != macroend) {
1112    if (*macrohere == "status.dm") break;
1113    ++macrohere;
1114  }
1115  if (macrohere == macroend) {
1116    output_errorpage (outconvert, textout, logout,
1117              "The status.dm file was not read in. This macro file is\n"
1118              "needed to display configuration and status information.\n");
1119    return true;
1120  }
1121
1122  // output the required status page
1123  text_t &arg_p = args["p"];
1124  if (arg_p == "frameset") output_frameset (args, disp, outconvert, textout, logout);
1125  else if (arg_p == "select") output_select (args, disp, outconvert, textout, logout);
1126  else if (arg_p == "welcome") output_welcome (args, protos, disp, outconvert, textout, logout);
1127  else if (arg_p == "generalinfo") output_generalinfo (args, disp, outconvert, textout, logout);
1128  else if (arg_p == "argumentinfo") output_argumentinfo (args, disp, outconvert, textout, logout);
1129  else if (arg_p == "actioninfo") output_actioninfo (args, disp, outconvert, textout, logout);
1130  else if (arg_p == "browserinfo") output_browserinfo (args, disp, outconvert, textout, logout);
1131  else if (arg_p == "protocolinfo") output_protocolinfo (args, disp, outconvert, textout, logout);
1132  else if (arg_p == "collectioninfo") output_collectioninfo (args, disp, outconvert, textout, logout);
1133  else if (arg_p == "usagelog") output_usagelog (args, disp, outconvert, textout, logout);
1134  else if (arg_p == "errorlog") output_errorlog (args, disp, outconvert, textout, logout);
1135  else if (arg_p == "llssite") output_llssite (args, disp, outconvert, textout, logout);
1136  else if (arg_p == "maincfg") output_maincfg (args, disp, outconvert, textout, logout);
1137  else if (arg_p == "changemaincfg") change_maincfg (args, disp, outconvert, textout, logout);
1138  else {
1139    output_errorpage (outconvert, textout, logout,
1140              "Unknown page \"" + arg_p + "\".\n");
1141  }
1142
1143  return true;
1144}
1145
1146void statusaction::configure (const text_t &key, const text_tarray &cfgline) {
1147  if ((key == "status") && (cfgline.size() == 1) &&
1148      (cfgline[0] == "true" || cfgline[0] == "on" || cfgline[0] == "enabled")) {
1149    disabled = false;
1150  } else {
1151    // call the parent class to deal with the things which
1152    // are not dealt with here
1153    action::configure (key, cfgline);
1154  }
1155}
1156
1157#endif //GSDL_USE_STATUS_ACTION
Note: See TracBrowser for help on using the browser.