57#ifdef HAVE_UUID_UUID_H
59#elif defined(HAVE_UUID_H)
62#error "Could not find UUID library header"
74#include "DODSFilter.h"
75#include "XDRStreamMarshaller.h"
76#include "InternalErr.h"
79#include "SignalHandler.h"
80#include "EventHandler.h"
81#include "AlarmHandler.h"
91 "Usage: <handler name> -o <response> -u <url> [options ...] [data set]\n\
93 options: -o <response>: DAS, DDS, DataDDS, DDX, BLOB or Version (Required)\n\
94 -u <url>: The complete URL minus the CE (required for DDX)\n\
95 -c: Compress the response using the deflate algorithm.\n\
96 -e <expr>: When returning a DataDDS, use <expr> as the constraint.\n\
97 -v <version>: Use <version> as the version number\n\
98 -d <dir>: Look for ancillary file in <dir> (deprecated).\n\
99 -f <file>: Look for ancillary data in <file> (deprecated).\n\
100 -r <dir>: Use <dir> as a cache directory\n\
101 -l <time>: Conditional request; if data source is unchanged since\n\
102 <time>, return an HTTP 304 response.\n\
103 -t <seconds>: Timeout the handler after <seconds>.\n\
172 initialize(argc, argv);
174 DBG(cerr <<
"d_comp: " << d_comp << endl);
175 DBG(cerr <<
"d_dap2ce: " << d_dap2ce << endl);
176 DBG(cerr <<
"d_cgi_ver: " << d_cgi_ver << endl);
177 DBG(cerr <<
"d_response: " << d_response << endl);
178 DBG(cerr <<
"d_anc_dir: " << d_anc_dir << endl);
179 DBG(cerr <<
"d_anc_file: " << d_anc_file << endl);
180 DBG(cerr <<
"d_cache_dir: " << d_cache_dir << endl);
181 DBG(cerr <<
"d_conditional_request: " << d_conditional_request << endl);
182 DBG(cerr <<
"d_if_modified_since: " << d_if_modified_since << endl);
183 DBG(cerr <<
"d_url: " << d_url << endl);
184 DBG(cerr <<
"d_timeout: " << d_timeout << endl);
187DODSFilter::~DODSFilter()
199 d_bad_options =
false;
200 d_conditional_request =
false;
207 d_response = Unknown_Response;;
210 d_if_modified_since = -1;
212 d_program_name =
"Unknown";
219 _setmode(_fileno(stdout), _O_BINARY);
239 d_program_name = argv[0];
247 if (next_arg < argc) {
248 d_dataset = argv[next_arg];
249 d_dataset =
www2id(d_dataset,
"%",
"%20");
266 DBG(cerr <<
"Entering process_options... ");
269 GetOpt getopt (argc, argv,
"ce: v: d: f: r: l: o: u: t: ");
271 while ((option_char = getopt()) != -1) {
272 switch (option_char) {
273 case 'c': d_comp =
true;
break;
274 case 'e': set_ce(getopt.optarg);
break;
276 case 'd': d_anc_dir = getopt.optarg;
break;
277 case 'f': d_anc_file = getopt.optarg;
break;
278 case 'r': d_cache_dir = getopt.optarg;
break;
280 case 'u':
set_URL(getopt.optarg);
break;
281 case 't': d_timeout = atoi(getopt.optarg);
break;
283 d_conditional_request =
true;
285 =
static_cast<time_t
>(strtol(getopt.optarg, NULL, 10));
298 DBGN(cerr <<
"exiting." << endl);
300 return getopt.optind;
310 return d_conditional_request;
356DODSFilter::set_ce(
string _ce)
358 d_dap2ce =
www2id(_ce,
"%",
"%20");
376DODSFilter::set_dataset_name(
const string ds)
378 d_dataset =
www2id(ds,
"%",
"%20");
395 if (url.find(
'?') != url.npos)
422 if (r ==
"DAS" || r ==
"das") {
423 d_response = DAS_Response;
426 else if (r ==
"DDS" || r ==
"dds") {
427 d_response = DDS_Response;
430 else if (r ==
"DataDDS" || r ==
"dods") {
431 d_response = DataDDS_Response;
434 else if (r ==
"DDX" || r ==
"ddx") {
435 d_response = DDX_Response;
438 else if (r ==
"DataDDX" || r ==
"dataddx") {
439 d_response = DataDDX_Response;
440 d_action =
"dataddx" ;
442 else if (r ==
"Version") {
443 d_response = Version_Response;
444 d_action =
"version" ;
501 DBG(cerr <<
"DODSFilter::get_das_last_modified_time(anc_location="
502 << anc_location <<
"call faf(das) d_dataset=" << d_dataset
503 <<
" d_anc_file=" << d_anc_file << endl);
507 (anc_location ==
"") ? d_anc_dir : anc_location,
524 DBG(cerr <<
"DODSFilter::get_das_last_modified_time(anc_location="
525 << anc_location <<
"call faf(dds) d_dataset=" << d_dataset
526 <<
" d_anc_file=" << d_anc_file << endl);
530 (anc_location ==
"") ? d_anc_dir : anc_location,
553 DBG(cerr <<
"DODSFilter::get_das_last_modified_time(anc_location="
554 << anc_location <<
"call faf(both) d_dataset=" << d_dataset
555 <<
" d_anc_file=" << d_anc_file << endl);
559 (anc_location ==
"") ? d_anc_dir : anc_location,
563 (anc_location ==
"") ? d_anc_dir : anc_location,
584 return d_if_modified_since;
628DODSFilter::establish_timeout(FILE *stream)
const
641DODSFilter::establish_timeout(ostream &stream)
const
653static const char *emessage =
"DODS internal server error; usage error. Please report this to the dataset maintainer, or to the opendap-tech@opendap.org mailing list.";
670 throw Error(emessage);
696DODSFilter::send_das(FILE *out,
DAS &das,
const string &anc_location,
697 bool with_mime_headers)
const
700 send_das(oss, das, anc_location, with_mime_headers);
701 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
716DODSFilter::send_das(ostream &out,
DAS &das,
const string &anc_location,
717 bool with_mime_headers)
const
722 && with_mime_headers) {
726 if (with_mime_headers)
734DODSFilter::send_das(
DAS &das,
const string &anc_location,
735 bool with_mime_headers)
const
737 send_das(cout, das, anc_location, with_mime_headers);
759 const string &anc_location,
760 bool with_mime_headers)
const
763 send_dds(oss, dds, eval, constrained, anc_location, with_mime_headers);
764 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
786 const string &anc_location,
787 bool with_mime_headers)
const
794 throw Error(
"Function calls can only be used with data requests. To see the structure of the underlying data source, reissue the URL without the function.");
799 && with_mime_headers) {
803 if (with_mime_headers)
816 bool constrained,
const string &anc_location,
817 bool with_mime_headers)
const
819 send_dds(cout, dds, eval, constrained, anc_location, with_mime_headers);
825DODSFilter::functional_constraint(BaseType &var, DDS &dds,
826 ConstraintEvaluator &eval, FILE *out)
const
829 functional_constraint(var, dds, eval, oss);
830 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
836DODSFilter::functional_constraint(BaseType &var, DDS &dds,
837 ConstraintEvaluator &eval, ostream &out)
const
839 out <<
"Dataset {\n" ;
840 var.print_decl(out,
" ",
true,
false,
true);
841 out <<
"} function_value;\n" ;
847 XDRStreamMarshaller m( out ) ;
851 var.serialize(eval, dds, m,
false);
859DODSFilter::dataset_constraint(DDS & dds, ConstraintEvaluator & eval,
860 FILE * out,
bool ce_eval)
const
863 dataset_constraint(dds, eval, oss, ce_eval);
864 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
868DODSFilter::dataset_constraint(DDS & dds, ConstraintEvaluator & eval,
869 ostream &out,
bool ce_eval)
const
872 dds.print_constrained(out);
877 XDRStreamMarshaller m( out ) ;
881 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
882 if ((*i)->send_p()) {
883 DBG(cerr <<
"Sending " << (*i)->name() << endl);
884 (*i)->serialize(eval, dds, m, ce_eval);
893DODSFilter::dataset_constraint_ddx(DDS & dds, ConstraintEvaluator & eval,
894 ostream &out,
const string &boundary,
895 const string &start,
bool ce_eval)
const
898 set_mime_ddx_boundary(out, boundary, start, dods_ddx);
904 uuid_unparse(uu, uuid);
906 if (getdomainname(domain, 255) != 0 || strlen(domain) == 0)
907 strncpy(domain,
"opendap.org", 255);
909 string cid = string(uuid) +
"@" + string(domain);
912 dds.print_xml_writer(out,
true, cid);
915 set_mime_data_boundary(out, boundary, cid, dap4_data, binary);
918 XDRStreamMarshaller m( out ) ;
922 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
923 if ((*i)->send_p()) {
924 DBG(cerr <<
"Sending " << (*i)->name() << endl);
925 (*i)->serialize(eval, dds, m, ce_eval);
951 FILE * data_stream,
const string & anc_location,
952 bool with_mime_headers)
const
955 send_data(dds, eval, oss, anc_location, with_mime_headers);
956 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), data_stream);
977 ostream & data_stream,
const string & anc_location,
978 bool with_mime_headers)
const
986 && with_mime_headers) {
991 establish_timeout(data_stream);
992 dds.set_timeout(d_timeout);
1010 throw Error(unknown_error,
"Error calling the CE function.");
1012 if (with_mime_headers)
1013 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
1015 data_stream << flush ;
1017 functional_constraint(*var, dds, eval, data_stream);
1024 if (with_mime_headers)
1025 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
1027 dataset_constraint(*fdds, eval, data_stream,
false);
1031 if (with_mime_headers)
1032 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
1034 dataset_constraint(dds, eval, data_stream);
1037 data_stream << flush ;
1052 bool with_mime_headers)
const
1055 send_ddx(dds, eval, oss, with_mime_headers);
1056 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
1071 bool with_mime_headers)
const
1074 if (!d_dap2ce.empty())
1078 throw Error(
"Function calls can only be used with data requests. To see the structure of the underlying data source, reissue the URL without the function.");
1086 && with_mime_headers) {
1091 if (with_mime_headers)
1119 ostream & data_stream,
const string &start,
1120 const string &boundary,
const string & anc_location,
1121 bool with_mime_headers)
const
1129 && with_mime_headers) {
1134 establish_timeout(data_stream);
1135 dds.set_timeout(d_timeout);
1149 throw Error(unknown_error,
"Error calling the CE function.");
1151 if (with_mime_headers)
1152 set_mime_multipart(data_stream, boundary, start, dods_data_ddx,
1153 d_cgi_ver, x_plain, data_lmt);
1154 data_stream << flush ;
1156 DDS var_dds(&btf, var->
name());
1159 serialize_dap2_data_ddx(var_dds, eval, data_stream, boundary, start);
1168 if (with_mime_headers)
1169 set_mime_multipart(data_stream, boundary, start, dods_data_ddx,
1170 d_cgi_ver, x_plain, data_lmt);
1171 data_stream << flush ;
1172 dataset_constraint(*fdds, eval, data_stream,
false);
1176 if (with_mime_headers)
1177 set_mime_multipart(data_stream, boundary, start, dods_data_ddx,
1178 d_cgi_ver, x_plain, data_lmt);
1179 data_stream << flush ;
1180 dataset_constraint_ddx(dds, eval, data_stream, boundary, start);
1183 data_stream << flush ;
1185 if (with_mime_headers)
1186 data_stream << CRLF <<
"--" << boundary <<
"--" << CRLF;
static string find_ancillary_file(const string &pathname, const string &ext, const string &dir, const string &file)
Find a file with ancillary data.
The basic data type for the DODS DAP types.
virtual string name() const
Returns the name of the class instance.
virtual void set_send_p(bool state)
Evaluate a constraint expression.
void parse_constraint(const std::string &constraint, DDS &dds)
Parse the constraint expression given the current DDS.
BaseType * eval_function(DDS &dds, const std::string &dataset)
Evaluate a function-valued constraint expression.
bool function_clauses()
Does the current constraint expression contain function clauses.
DDS * eval_function_clauses(DDS &dds)
Evaluate a function-valued constraint expression that contains several function calls.
bool functional_expression()
Does the current constraint expression return a BaseType pointer? This method does not evaluate the c...
Hold attribute data for a DAP2 dataset.
virtual void print(FILE *out, bool dereference=false)
void print(FILE *out)
Print the entire DDS to the specified file.
void tag_nested_sequences()
Traverse DDS, set Sequence leaf nodes.
void print_constrained(FILE *out)
Print a constrained DDS to the specified file.
void add_var(BaseType *bt)
Adds a copy of the variable to the DDS. Using the ptr_duplicate() method, perform a deep copy on the ...
void print_xml_writer(ostream &out, bool constrained, const string &blob="")
virtual string get_ce() const
Get the constraint expression.
virtual void send_data(DDS &dds, ConstraintEvaluator &eval, ostream &data_stream, const string &anc_location="", bool with_mime_headers=true) const
Transmit data.
virtual time_t get_dds_last_modified_time(const string &anc_location="") const
virtual Response get_response() const
virtual time_t get_dataset_last_modified_time() const
virtual int process_options(int argc, char *argv[])
virtual void set_URL(const string &url)
virtual string get_action() const
void set_timeout(int timeout=0)
virtual void print_usage() const
Print usage information for a filter program.
virtual string get_dataset_version() const
Get the version information for the dataset.
virtual bool is_conditional() const
Is this request conditional?
virtual string get_dataset_name() const
Get the dataset name.
virtual void send_ddx(DDS &dds, ConstraintEvaluator &eval, ostream &out, bool with_mime_headers=true) const
virtual string get_cgi_version() const
virtual void send_version_info() const
Send version information back to the client program.
virtual void send_data_ddx(DDS &dds, ConstraintEvaluator &eval, ostream &data_stream, const string &start, const string &boundary, const string &anc_location="", bool with_mime_headers=true) const
Transmit data.
virtual void set_response(const string &r)
virtual string get_URL() const
virtual void set_cgi_version(string version)
virtual string get_cache_dir() const
Get the cache directory.
virtual time_t get_das_last_modified_time(const string &anc_location="") const
virtual time_t get_request_if_modified_since() const
virtual time_t get_data_last_modified_time(const string &anc_location="") const
A class for error processing.
EventHandler * register_handler(int signum, EventHandler *eh, bool ignore_by_default=false)
static SignalHandler * instance()
top level DAP object to house generic methods
string www2id(const string &in, const string &escape, const string &except)
time_t last_modified_time(const string &name)
void set_mime_not_modified(FILE *out)
Send a ‘Not Modified’ response.
void set_mime_binary(FILE *out, ObjectType type, const string &ver, EncodingType enc, const time_t last_modified)
bool do_version(const string &script_ver, const string &dataset_ver)
Send a version number.
void ErrMsgT(const string &Msgt)
Logs an error message.
void set_mime_text(FILE *out, ObjectType type, const string &ver, EncodingType enc, const time_t last_modified)