57 #ifdef HAVE_UUID_UUID_H 58 #include <uuid/uuid.h> 59 #elif defined(HAVE_UUID_H) 62 #error "Could not find UUID library header" 70 #include "mime_util.h" 71 #include "Ancillary.h" 74 #include "DODSFilter.h" 75 #include "XDRStreamMarshaller.h" 76 #include "InternalErr.h" 79 #include "SignalHandler.h" 80 #include "EventHandler.h" 81 #include "AlarmHandler.h" 84 #define CRLF "\r\n" // Change here, expr-test.cc and DODSFilter.cc 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\ 170 DODSFilter::DODSFilter(
int argc,
char *argv[])
throw(
Error)
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);
187 DODSFilter::~DODSFilter()
194 DODSFilter::initialize()
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);
235 DODSFilter::initialize(
int argc,
char *argv[])
239 d_program_name = argv[0];
242 int next_arg = process_options(argc, argv);
247 if (next_arg < argc) {
248 d_dataset = argv[next_arg];
249 d_dataset =
www2id(d_dataset,
"%",
"%20");
251 else if (get_response() != Version_Response)
264 DODSFilter::process_options(
int argc,
char *argv[])
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;
275 case 'v': set_cgi_version(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;
279 case 'o': set_response(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));
287 case 'h': print_usage();
293 default: print_usage();
298 DBGN(cerr <<
"exiting." << endl);
300 return getopt.optind;
308 DODSFilter::is_conditional()
const 310 return d_conditional_request;
327 DODSFilter::set_cgi_version(
string version)
338 DODSFilter::get_cgi_version()
const 350 DODSFilter::get_ce()
const 356 DODSFilter::set_ce(
string _ce)
358 d_dap2ce =
www2id(_ce,
"%",
"%20");
370 DODSFilter::get_dataset_name()
const 376 DODSFilter::set_dataset_name(
const string ds)
378 d_dataset =
www2id(ds,
"%",
"%20");
385 DODSFilter::get_URL()
const 393 DODSFilter::set_URL(
const string &url)
395 if (url.find(
'?') != url.npos)
409 DODSFilter::get_dataset_version()
const 420 void DODSFilter::set_response(
const string &r)
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" ;
452 DODSFilter::get_response()
const 458 string DODSFilter::get_action()
const 484 DODSFilter::get_dataset_last_modified_time()
const 499 DODSFilter::get_das_last_modified_time(
const string &anc_location)
const 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);
506 = Ancillary::find_ancillary_file(d_dataset,
"das",
507 (anc_location ==
"") ? d_anc_dir : anc_location,
511 get_dataset_last_modified_time());
522 DODSFilter::get_dds_last_modified_time(
const string &anc_location)
const 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);
529 = Ancillary::find_ancillary_file(d_dataset,
"dds",
530 (anc_location ==
"") ? d_anc_dir : anc_location,
534 get_dataset_last_modified_time());
551 DODSFilter::get_data_last_modified_time(
const string &anc_location)
const 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);
558 = Ancillary::find_ancillary_file(d_dataset,
"dds",
559 (anc_location ==
"") ? d_anc_dir : anc_location,
562 = Ancillary::find_ancillary_file(d_dataset,
"das",
563 (anc_location ==
"") ? d_anc_dir : anc_location,
569 time_t n = get_dataset_last_modified_time();
582 DODSFilter::get_request_if_modified_since()
const 584 return d_if_modified_since;
594 DODSFilter::get_cache_dir()
const 604 DODSFilter::set_timeout(
int t)
611 DODSFilter::get_timeout()
const 628 DODSFilter::establish_timeout(FILE *stream)
const 641 DODSFilter::establish_timeout(ostream &stream)
const 653 static 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.";
665 DODSFilter::print_usage()
const 670 throw Error(emessage);
679 DODSFilter::send_version_info()
const 696 DODSFilter::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);
716 DODSFilter::send_das(ostream &out,
DAS &das,
const string &anc_location,
717 bool with_mime_headers)
const 719 time_t das_lmt = get_das_last_modified_time(anc_location);
721 && das_lmt <= get_request_if_modified_since()
722 && with_mime_headers) {
726 if (with_mime_headers)
734 DODSFilter::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.");
796 time_t dds_lmt = get_dds_last_modified_time(anc_location);
798 && dds_lmt <= get_request_if_modified_since()
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);
825 DODSFilter::functional_constraint(
BaseType &var,
DDS &dds,
829 functional_constraint(var, dds, eval, oss);
830 fwrite(oss.str().data(),
sizeof(char), oss.str().length(), out);
836 DODSFilter::functional_constraint(
BaseType &var,
DDS &dds,
839 out <<
"Dataset {\n" ;
841 out <<
"} function_value;\n" ;
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);
869 ostream &out,
bool ce_eval)
const 882 if ((*i)->send_p()) {
883 DBG(cerr <<
"Sending " << (*i)->name() << endl);
884 (*i)->serialize(eval, dds, m, ce_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[0]);
906 if (getdomainname(domain, 255) != 0 || strlen(domain) == 0)
907 strncpy(domain,
"opendap.org", 255);
909 string cid = string(&uuid[0]) +
"@" + string(&domain[0]);
915 set_mime_data_boundary(out, boundary, cid, dap4_data, binary);
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 983 time_t data_lmt = get_data_last_modified_time(anc_location);
985 && data_lmt <= get_request_if_modified_since()
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.");
1080 time_t dds_lmt = get_dds_last_modified_time(d_anc_dir);
1085 if (is_conditional() && dds_lmt <= get_request_if_modified_since()
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 1126 time_t data_lmt = get_data_last_modified_time(anc_location);
1127 if (is_conditional()
1128 && data_lmt <= get_request_if_modified_since()
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());
1158 var_dds.add_var(var);
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;
virtual string name() const
Returns the name of the class instance.
virtual void print_decl(FILE *out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false)
Print an ASCII representation of the variable structure.
void ErrMsgT(const string &Msgt)
Logs an error message.
void print(FILE *out)
Print the entire DDS to the specified file.
time_t last_modified_time(const string &name)
Vars_iter var_begin()
Return an iterator to the first variable.
void set_mime_text(FILE *out, ObjectType type, const string &ver, EncodingType enc, const time_t last_modified)
void print_xml_writer(ostream &out, bool constrained, const string &blob="")
BaseType * eval_function(DDS &dds, const std::string &dataset)
Evaluate a function-valued constraint expression.
virtual void print(FILE *out, bool dereference=false)
top level DAP object to house generic methods
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Move data to the net, then remove them from the object.
virtual void set_send_p(bool state)
DDS * eval_function_clauses(DDS &dds)
Evaluate a function-valued constraint expression that contains several function calls.
void set_mime_binary(FILE *out, ObjectType type, const string &ver, EncodingType enc, const time_t last_modified)
void parse_constraint(const std::string &constraint, DDS &dds)
Parse the constraint expression given the current DDS.
void set_mime_not_modified(FILE *out)
Send a `Not Modified' response.
string www2id(const string &in, const string &escape, const string &except)
Vars_iter var_end()
Return an iterator.
Evaluate a constraint expression.
void tag_nested_sequences()
Traverse DDS, set Sequence leaf nodes.
bool functional_expression()
Does the current constraint expression return a BaseType pointer? This method does not evaluate the c...
The basic data type for the DODS DAP types.
Hold attribute data for a DAP2 dataset.
bool function_clauses()
Does the current constraint expression contain function clauses.
A class for error processing.
EventHandler * register_handler(int signum, EventHandler *eh, bool override=false)
Marshaller that knows how serialize dap data objects to a C++ iostream using XDR. ...
bool do_version(const string &script_ver, const string &dataset_ver)
Send a version number.
void print_constrained(FILE *out)
Print a constrained DDS to the specified file.