bes  Updated for version 3.20.6
get_html_form.cc
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // Copyright (c) 2006 OPeNDAP, Inc.
5 // Author: James Gallagher <jgallagher@opendap.org>
6 //
7 // This is free software; you can redistribute it and/or modify it under the
8 // terms of the GNU Lesser General Public License as published by the Free
9 // Software Foundation; either version 2.1 of the License, or (at your
10 // option) any later version.
11 //
12 // This is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 // more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
22 
23 // This file holds the interface for the 'get data as ascii' function of the
24 // OPeNDAP/HAO data server. This function is called by the BES when it loads
25 // this as a module. The functions in the file ascii_val.cc also use this, so
26 // the same basic processing software can be used both by Hyrax and tie older
27 // Server3.
28 
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 
33 #include <iostream>
34 #include <sstream>
35 
36 #include <DataDDS.h>
37 #include <escaping.h>
38 
39 #include "get_html_form.h"
40 #include "WWWOutput.h"
41 #include "WWWOutputFactory.h"
42 
43 #include "WWWByte.h"
44 #include "WWWInt16.h"
45 #include "WWWUInt16.h"
46 #include "WWWInt32.h"
47 #include "WWWUInt32.h"
48 #include "WWWFloat32.h"
49 #include "WWWFloat64.h"
50 #include "WWWStr.h"
51 #include "WWWUrl.h"
52 #include "WWWArray.h"
53 #include "WWWStructure.h"
54 #include "WWWSequence.h"
55 #include "WWWGrid.h"
56 
57 namespace dap_html_form {
58 
59 #include "javascript.h" // Try to hide this stuff...
60 
61 // A better way to do this would have been to make WWWStructure, ..., inherit
62 // from both Structure and WWWOutput. But I didn't... jhrg 8/29/05
63 WWWOutput *wo = 0;
64 
70 BaseType *basetype_to_wwwtype(BaseType * bt)
71 {
72  switch (bt->type()) {
73  case dods_byte_c:
74  return new WWWByte(dynamic_cast < Byte * >(bt));
75  case dods_int16_c:
76  return new WWWInt16(dynamic_cast < Int16 * >(bt));
77  case dods_uint16_c:
78  return new WWWUInt16(dynamic_cast < UInt16 * >(bt));
79  case dods_int32_c:
80  return new WWWInt32(dynamic_cast < Int32 * >(bt));
81  case dods_uint32_c:
82  return new WWWUInt32(dynamic_cast < UInt32 * >(bt));
83  case dods_float32_c:
84  return new WWWFloat32(dynamic_cast < Float32 * >(bt));
85  case dods_float64_c:
86  return new WWWFloat64(dynamic_cast < Float64 * >(bt));
87  case dods_str_c:
88  return new WWWStr(dynamic_cast < Str * >(bt));
89  case dods_url_c:
90  return new WWWUrl(dynamic_cast < Url * >(bt));
91  case dods_array_c:
92  return new WWWArray(dynamic_cast < Array * >(bt));
93  case dods_structure_c:
94  return new WWWStructure(dynamic_cast < Structure * >(bt));
95  case dods_sequence_c:
96  return new WWWSequence(dynamic_cast < Sequence * >(bt));
97  case dods_grid_c:
98  return new WWWGrid(dynamic_cast < Grid * >(bt));
99  default:
100  throw InternalErr(__FILE__, __LINE__, "Unknown type.");
101  }
102 }
103 
110 DDS *dds_to_www_dds(DDS * dds)
111 {
112 #if 0
113  // Using the factory class has no effect because it does not control
114  // how a class like Structure or Grid builds child instances, so we have
115  // to use the basetype_to_wwwtype() function.
116  WWWOutputFactory wwwfactory;
117  dds->set_factory(&wwwfactory);
118 #endif
119  // Use the copy constructor to copy all the various private fields in DDS
120  // including the attribute table for global attributes
121  DDS *wwwdds = new DDS(*dds);
122 
123  // Because the DDS copy constructor copies the variables, we now, erase
124  // them and...
125  wwwdds->del_var(wwwdds->var_begin(), wwwdds->var_end());
126 
127  // Build copies of the variables using the WWW* types and manually add
128  // their attribute tables.
129  DDS::Vars_iter i = dds->var_begin();
130  while (i != dds->var_end()) {
131  BaseType *abt = basetype_to_wwwtype(*i);
132  abt->set_attr_table((*i)->get_attr_table());
133 #if 0
134  cerr << "dds attr: "; (*i)->get_attr_table().print(cerr); cerr << endl;
135  cerr << "abt attr: "; abt->get_attr_table().print(cerr); cerr << endl;
136 #endif
137  wwwdds->add_var(abt);
138  // add_var makes a copy of the base type passed to it, so delete it
139  // here
140  delete abt;
141  i++;
142  }
143 
144 #if 0
145  // Should the following use WWWOutputFactory instead of the source DDS'
146  // factory class?
147  DDS *wwwdds = new DDS(dds->get_factory(), dds->get_dataset_name());
148 
149  wwwdds->set_attr_table(dds->get_attr_table);
150 
151  DDS::Vars_iter i = dds->var_begin();
152  while (i != dds->var_end()) {
153  BaseType *abt = basetype_to_wwwtype(*i);
154  wwwdds->add_var(abt);
155  // add_var makes a copy of the base type passed to it, so delete it
156  // here
157  delete abt;
158  i++;
159  }
160 #endif
161  return wwwdds;
162 }
163 
164 // This hack is needed because we have moved the #define of FILE_METHODS to
165 // the libdap header files until we can remove those methods from the library.
166 #undef FILE_METHODS
167 
168 #ifdef FILE_METHODS
169 
188 void write_html_form_interface(FILE * dest, DDS * dds,
189  const string & url, bool html_header,
190  const string & admin_name,
191  const string & help_location)
192 {
193  wo = new WWWOutput(dest);
194 
195  if (html_header)
196  wo->write_html_header();
197 
198  ostringstream oss;
199  oss <<
200  "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n"
201  << "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n" <<
202  "<html><head><title>OPeNDAP Server Dataset Query Form</title>\n"
203  << "<base href=\"" << help_location << "\">\n" <<
204  "<script type=\"text/javascript\">\n"
205  // Javascript code here
206  << java_code << "\n"
207  << "DODS_URL = new dods_url(\"" << url << "\");\n"
208  << "</script>\n"
209 
210  << "<style id=\"antiClickjack\">body{display:none !important;}</style>\n" //cross frame fix.
211  << "<script type=\"text/javascript\">\n"
212  << " if (self === top) {\n"
213  << " var antiClickjack = document.getElementById(\"antiClickjack\");\n"
214  << " antiClickjack.parentNode.removeChild(antiClickjack);\n"
215  << " } else {\n"
216  << " top.location = self.location;\n"
217  << " }\n"
218  << "</script>\n"
219 
220  << "</head>\n"
221  << "<body>\n"
222  <<
223  "<p><h2 align='center'>OPeNDAP Server Dataset Access Form</h2>\n"
224  << "<hr>\n" << "<form action=\"\">\n" << "<table>\n";
225  fprintf(dest, "%s", oss.str().c_str());
226 
227  wo->write_disposition(url);
228 
229  fprintf(dest, "<tr><td><td><hr>\n\n");
230 
231  wo->write_global_attributes(dds->get_attr_table());
232 
233  fprintf(dest, "<tr><td><td><hr>\n\n");
234 
235  wo->write_variable_entries(*dds);
236 
237  oss.str("");
238  oss << "</table></form>\n\n" << "<hr>\n\n";
239  oss << "<address>Send questions or comments to: <a href=\"mailto:"
240  << admin_name << "\">" << admin_name << "</a></address>" << "<p>\n\
241  <a href=\"http://validator.w3.org/check?uri=referer\"><img\n\
242  src=\"http://www.w3.org/Icons/valid-html40\"\n\
243  alt=\"Valid HTML 4.0 Transitional\" height=\"31\" width=\"88\">\n\
244  </a></p>\n" << "</body></html>\n";
245 
246  fprintf(dest, "%s", oss.str().c_str());
247 
248 }
249 #endif
250 
269 void write_html_form_interface(ostream &strm, DDS * dds, const string & url, bool html_header,
270  bool netcdf3_file_response, bool netcdf4_file_response, const string & admin_name,
271  const string & help_location)
272 {
273  wo = new WWWOutput(strm);
274 
275  if (html_header)
276  wo->write_html_header();
277 
278  strm <<
279  "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n"
280  << "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n" <<
281  "<html><head><title>OPeNDAP Server Dataset Query Form</title>\n"
282  << "<base href=\"" << help_location << "\">\n" <<
283  "<script type=\"text/javascript\">\n"
284  // Javascript code here
285  << java_code << "\n"
286  << "DODS_URL = new dods_url(\"" << url << "\");\n"
287  << "</script>\n"
288 
289  << "<style id=\"antiClickjack\">body{display:none !important;}</style>\n" //cross frame fix.
290  << "<script type=\"text/javascript\">\n"
291  << " if (self === top) {\n"
292  << " var antiClickjack = document.getElementById(\"antiClickjack\");\n"
293  << " antiClickjack.parentNode.removeChild(antiClickjack);\n"
294  << " } else {\n"
295  << " top.location = self.location;\n"
296  << " }\n"
297  << "</script>\n"
298 
299  << "</head>\n"
300  << "<body>\n"
301  <<
302  "<p><h2 align='center'>OPeNDAP Server Dataset Access Form</h2>\n"
303  << "<hr>\n" << "<form action=\"\">\n" << "<table>\n";
304 
305  wo->write_disposition(url, netcdf3_file_response, netcdf4_file_response);
306 
307  strm << "<tr><td><td><hr>\n\n" ;
308 
309  wo->write_global_attributes(dds->get_attr_table());
310 
311  strm << "<tr><td><td><hr>\n\n" ;
312 
313  wo->write_variable_entries(*dds);
314 
315  strm << "</table></form>\n\n" << "<hr>\n\n";
316  strm << "<address>Send questions or comments to: <a href=\"mailto:"
317  << admin_name << "\">" << admin_name << "</a></address>" << "<p>\n\
318  <a href=\"http://validator.w3.org/check?uri=referer\"><img\n\
319  src=\"http://www.w3.org/Icons/valid-html40\"\n\
320  alt=\"Valid HTML 4.0 Transitional\" height=\"31\" width=\"88\">\n\
321  </a></p>\n" << "</body></html>\n";
322 }
323 
324 const string allowable =
325  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
326 
327 // This function adds some text to the variable name so that conflicts with
328 // JavaScript's reserved words and other conflicts are avoided (or
329 // minimized...) 7/13/2001 jhrg
330 //
331 // I've modified this so that it no longer include the PID. Not sure why that
332 // was included... However, removing it will make using the HTML form in tests
333 // easier. jhrg 11/28/06
334 string name_for_js_code(const string & dods_name)
335 {
336  return string("org_opendap_") +
337  esc2underscore(id2www(dods_name, allowable));
338 }
339 
345 string
346 get_fqn(BaseType *var)
347 {
348  // I made this a local static object to avoid the repeated cost of creation
349  // and also the issues with global static objects in dynamically-loaded
350  // code.
351  static const string dot = ".";
352 
353  // Testing !get_parent() means that the function returns the top most name.
354  // If we tested !var instead it would return "" and the FQN would have a
355  // leading dot. The test for !var is here as cheap insurance; it should
356  // never happen.
357  if (!var)
358  return string("");
359  else if (!var->get_parent())
360  return var->name();
361  else
362  return get_fqn(var->get_parent()) + dot + var->name();
363 }
364 
365 string fancy_typename(BaseType * v)
366 {
367  switch (v->type()) {
368  case dods_byte_c:
369  return "Byte";
370  case dods_int16_c:
371  return "16 bit Integer";
372  case dods_uint16_c:
373  return "16 bit Unsigned integer";
374  case dods_int32_c:
375  return "32 bit Integer";
376  case dods_uint32_c:
377  return "32 bit Unsigned integer";
378  case dods_float32_c:
379  return "32 bit Real";
380  case dods_float64_c:
381  return "64 bit Real";
382  case dods_str_c:
383  return "string";
384  case dods_url_c:
385  return "URL";
386  case dods_array_c:{
387  ostringstream type;
388  Array *a = (Array *) v;
389  type << "Array of " << fancy_typename(a->var()) << "s ";
390  for (Array::Dim_iter p = a->dim_begin(); p != a->dim_end();
391  ++p)
392  type << "[" << a->dimension_name(p) << " = 0.." << a->
393  dimension_size(p, false) - 1 << "]";
394  return type.str();
395  }
396  case dods_structure_c:
397  return "Structure";
398  case dods_sequence_c:
399  return "Sequence";
400  case dods_grid_c:{
401  ostringstream type;
402  Grid &g = dynamic_cast<Grid&>(*v);
403  type << "Grid of " << fancy_typename(g.get_array());
404 #if 0
405  << "s ";
406  for (Grid::Map_iter p = g.map_begin(); p != g.map_end(); ++p) {
407  Array &a = dynamic_cast<Array&>(**p);
408  type << "[" << a.dimension_name(a.dim_begin()) << " = 0.." \
409  << a.dimension_size(a.dim_begin(), false) - 1 << "]";
410  }
411 #endif
412  return type.str();
413  }
414 #if 0
415  return "Grid";
416 #endif
417  default:
418  return "Unknown";
419  }
420 }
421 
428 void
429 write_simple_variable(FILE * os, BaseType *var)
430 // const string & name, const string & type)
431 {
432  ostringstream ss;
433  write_simple_variable( ss, var); //name, type ) ;
434 
435  // Now write that string to os
436  fprintf(os, "%s", ss.str().c_str());
437 }
438 
445 void
446 write_simple_variable(ostream &strm, BaseType *var)
447 // const string & name, const string & type)
448 {
449  const string fqn = get_fqn(var);
450 
451  strm << "<script type=\"text/javascript\">\n"
452  << name_for_js_code(fqn) << " = new dods_var(\""
453  << id2www_ce(fqn)
454  << "\", \"" << name_for_js_code(fqn) << "\", 0);\n" <<
455  "DODS_URL.add_dods_var(" << name_for_js_code(fqn) << ");\n"
456  << "</script>\n";
457 
458  strm << "<b>"
459  << "<input type=\"checkbox\" name=\"get_" << name_for_js_code(fqn)
460  << "\"\n" << "onclick=\"" << name_for_js_code(fqn)
461  << ".handle_projection_change(get_" << name_for_js_code(fqn)
462  << ") \" onfocus=\"describe_projection()\">\n" << "<font size=\"+1\">"
463  << var->name() << "</font>" << ": "
464  << fancy_typename(var) << "</b><br>\n\n";
465 
466  strm << var->name() << " <select name=\"" << name_for_js_code(fqn)
467  << "_operator\"" << " onfocus=\"describe_operator()\""
468  << " onchange=\"DODS_URL.update_url()\">\n"
469  << "<option value=\"=\" selected>=\n"
470  << "<option value=\"!=\">!=\n" << "<option value=\"<\"><\n"
471  << "<option value=\"<=\"><=\n" << "<option value=\">\">>\n"
472  << "<option value=\">=\">>=\n" << "<option value=\"-\">--\n"
473  << "</select>\n";
474 
475  strm << "<input type=\"text\" name=\"" << name_for_js_code(fqn)
476  << "_selection"
477  << "\" size=12 onFocus=\"describe_selection()\" "
478  << "onChange=\"DODS_URL.update_url()\">\n";
479 
480  strm << "<br>\n\n";
481 }
482 #if 0
483 void
484 write_simple_var_attributes(FILE * os, BaseType *var)
485 {
486  ostringstream ss;
487  write_simple_var_attributes(ss, var);
488 
489  // Now write that string to os
490  fprintf(os, "%s", ss.str().c_str());
491 }
492 
493 void
494 write_simple_var_attributes(ostream &os, int rows, int cols, BaseType *btp)
495 {
496  AttrTable &attr = btp->get_attr_table();
497 
498  // Don't write anything if there are no attributes.
499  if (attr.get_size() == 0) {
500  return;
501  }
502 
503  os << "<textarea name=\"" << btp->name()
504  << "_attr\" rows=\"" << rows
505  << "\" cols=\"" << cols << "\">\n" ;
506  write_attributes(os, attr, "");
507  os << "</textarea>\n\n" ;
508 }
509 
510 void
511 write_attributes(ostream &os, AttrTable &attr, const string &prefix)
512 {
513  for (AttrTable::Attr_iter a = attr.attr_begin(); a != attr.attr_end(); ++a) {
514  if (attr.is_container(a))
515  write_attributes(os, attr.get_attr_table(a), (prefix == "") ? attr.get_name(a) : prefix + string(".") + attr.get_name(a));
516  else {
517  if (prefix != "")
518  os << prefix << "." << attr.get_name(a) << ": ";
519  else
520  os << attr.get_name(a) << ": ";
521 
522  int num_attr = attr.get_attr_num(a) - 1;
523  for (int i = 0; i < num_attr; ++i) {
524  os << attr.get_attr(a, i) << ", ";
525  }
526  os << attr.get_attr(a, num_attr) << "\n";
527  }
528  }
529 }
530 #endif
531 } // namespace dap_html_form
WWWFloat32
Definition: WWWFloat32.h:43
WWWByte
Definition: WWWByte.h:44
WWWStructure
Definition: WWWStructure.h:43
WWWInt32
Definition: WWWInt32.h:43
WWWGrid
Definition: WWWGrid.h:43
WWWOutput::write_global_attributes
void write_global_attributes(AttrTable &attr)
Definition: WWWOutput.cc:142
WWWOutput::write_html_header
void write_html_header()
Definition: WWWOutput.cc:73
WWWSequence
Definition: WWWSequence.h:43
WWWOutput::write_disposition
void write_disposition(string url, bool netcdf3_file_response, bool netcdf4_file_response)
Definition: WWWOutput.cc:80
WWWFloat64
Definition: WWWFloat64.h:43
WWWArray
Definition: WWWArray.h:43
WWWUrl
Definition: WWWUrl.h:43
WWWUInt16
Definition: WWWUInt16.h:43
WWWOutput
Definition: WWWOutput.h:48
WWWUInt32
Definition: WWWUInt32.h:43
WWWOutputFactory
Definition: WWWOutputFactory.h:48
WWWInt16
Definition: WWWInt16.h:43
WWWStr
Definition: WWWStr.h:44