40 {
"$Id: DODSFilter.cc 23477 2010-09-02 21:02:59Z jimg $" 60 #include <uuid/uuid.h> 84 #define CRLF "\r\n" // Change here, expr-test.cc and DODSFilter.cc 93 "Usage: <handler name> -o <response> -u <url> [options ...] [data set]\n\ 95 options: -o <response>: DAS, DDS, DataDDS, DDX, BLOB or Version (Required)\n\ 96 -u <url>: The complete URL minus the CE (required for DDX)\n\ 97 -c: Compress the response using the deflate algorithm.\n\ 98 -e <expr>: When returning a DataDDS, use <expr> as the constraint.\n\ 99 -v <version>: Use <version> as the version number\n\ 100 -d <dir>: Look for ancillary file in <dir> (deprecated).\n\ 101 -f <file>: Look for ancillary data in <file> (deprecated).\n\ 102 -r <dir>: Use <dir> as a cache directory\n\ 103 -l <time>: Conditional request; if data source is unchanged since\n\ 104 <time>, return an HTTP 304 response.\n\ 105 -t <seconds>: Timeout the handler after <seconds>.\n\ 172 DODSFilter::DODSFilter(
int argc,
char *argv[])
throw(
Error)
174 initialize(argc, argv);
176 DBG(cerr <<
"d_comp: " << d_comp << endl);
177 DBG(cerr <<
"d_ce: " << d_ce << endl);
178 DBG(cerr <<
"d_cgi_ver: " << d_cgi_ver << endl);
179 DBG(cerr <<
"d_response: " << d_response << endl);
180 DBG(cerr <<
"d_anc_dir: " << d_anc_dir << endl);
181 DBG(cerr <<
"d_anc_file: " << d_anc_file << endl);
182 DBG(cerr <<
"d_cache_dir: " << d_cache_dir << endl);
183 DBG(cerr <<
"d_conditional_request: " << d_conditional_request << endl);
184 DBG(cerr <<
"d_if_modified_since: " << d_if_modified_since << endl);
185 DBG(cerr <<
"d_url: " << d_url << endl);
186 DBG(cerr <<
"d_timeout: " << d_timeout << endl);
189 DODSFilter::~DODSFilter()
196 DODSFilter::initialize()
201 d_bad_options =
false;
202 d_conditional_request =
false;
209 d_response = Unknown_Response;;
212 d_if_modified_since = -1;
214 d_program_name =
"Unknown";
221 _setmode(_fileno(stdout), _O_BINARY);
237 DODSFilter::initialize(
int argc,
char *argv[])
241 d_program_name = argv[0];
244 int next_arg = process_options(argc, argv);
249 if (next_arg < argc) {
250 d_dataset = argv[next_arg];
251 d_dataset =
www2id(d_dataset,
"%",
"%20");
253 else if (get_response() != Version_Response)
266 DODSFilter::process_options(
int argc,
char *argv[])
268 DBG(cerr <<
"Entering process_options... ");
271 GetOpt getopt (argc, argv,
"ce: v: d: f: r: l: o: u: t: ");
273 while ((option_char = getopt()) != EOF) {
274 switch (option_char) {
275 case 'c': d_comp =
true;
break;
276 case 'e': set_ce(getopt.optarg);
break;
277 case 'v': set_cgi_version(getopt.optarg);
break;
278 case 'd': d_anc_dir = getopt.optarg;
break;
279 case 'f': d_anc_file = getopt.optarg;
break;
280 case 'r': d_cache_dir = getopt.optarg;
break;
281 case 'o': set_response(getopt.optarg);
break;
282 case 'u': set_URL(getopt.optarg);
break;
283 case 't': d_timeout = atoi(getopt.optarg);
break;
285 d_conditional_request =
true;
287 =
static_cast<time_t
>(strtol(getopt.optarg, NULL, 10));
289 case 'h': print_usage(); exit(1);
290 default: print_usage();
294 DBGN(cerr <<
"exiting." << endl);
296 return getopt.optind;
304 DODSFilter::is_conditional()
const 306 return d_conditional_request;
334 DODSFilter::get_cgi_version()
const 346 DODSFilter::get_ce()
const 352 DODSFilter::set_ce(
string _ce)
354 d_ce =
www2id(_ce,
"%",
"%20");
366 DODSFilter::get_dataset_name()
const 372 DODSFilter::set_dataset_name(
const string ds)
374 d_dataset =
www2id(ds,
"%",
"%20");
381 DODSFilter::get_URL()
const 389 DODSFilter::set_URL(
const string &url)
391 if (url.find(
'?') != url.npos)
405 DODSFilter::get_dataset_version()
const 416 void DODSFilter::set_response(
const string &r)
418 if (r ==
"DAS" || r ==
"das") {
419 d_response = DAS_Response;
422 else if (r ==
"DDS" || r ==
"dds") {
423 d_response = DDS_Response;
426 else if (r ==
"DataDDS" || r ==
"dods") {
427 d_response = DataDDS_Response;
430 else if (r ==
"DDX" || r ==
"ddx") {
431 d_response = DDX_Response;
434 else if (r ==
"DataDDX" || r ==
"dataddx") {
435 d_response = DataDDX_Response;
436 d_action =
"dataddx" ;
438 else if (r ==
"Version") {
439 d_response = Version_Response;
440 d_action =
"version" ;
448 DODSFilter::get_response()
const 454 string DODSFilter::get_action()
const 480 DODSFilter::get_dataset_last_modified_time()
const 495 DODSFilter::get_das_last_modified_time(
const string &anc_location)
const 497 DBG(cerr <<
"DODSFilter::get_das_last_modified_time(anc_location=" 498 << anc_location <<
"call faf(das) d_dataset=" << d_dataset
499 <<
" d_anc_file=" << d_anc_file << endl);
502 = Ancillary::find_ancillary_file(d_dataset,
"das",
503 (anc_location ==
"") ? d_anc_dir : anc_location,
507 get_dataset_last_modified_time());
518 DODSFilter::get_dds_last_modified_time(
const string &anc_location)
const 520 DBG(cerr <<
"DODSFilter::get_das_last_modified_time(anc_location=" 521 << anc_location <<
"call faf(dds) d_dataset=" << d_dataset
522 <<
" d_anc_file=" << d_anc_file << endl);
525 = Ancillary::find_ancillary_file(d_dataset,
"dds",
526 (anc_location ==
"") ? d_anc_dir : anc_location,
530 get_dataset_last_modified_time());
547 DODSFilter::get_data_last_modified_time(
const string &anc_location)
const 549 DBG(cerr <<
"DODSFilter::get_das_last_modified_time(anc_location=" 550 << anc_location <<
"call faf(both) d_dataset=" << d_dataset
551 <<
" d_anc_file=" << d_anc_file << endl);
554 = Ancillary::find_ancillary_file(d_dataset,
"dds",
555 (anc_location ==
"") ? d_anc_dir : anc_location,
558 = Ancillary::find_ancillary_file(d_dataset,
"das",
559 (anc_location ==
"") ? d_anc_dir : anc_location,
565 time_t n = get_dataset_last_modified_time();
578 DODSFilter::get_request_if_modified_since()
const 580 return d_if_modified_since;
590 DODSFilter::get_cache_dir()
const 600 DODSFilter::set_timeout(
int t)
607 DODSFilter::get_timeout()
const 625 DODSFilter::establish_timeout(FILE *stream)
const 640 DODSFilter::establish_timeout(ostream &stream)
const 652 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.";
664 DODSFilter::print_usage()
const 678 DODSFilter::send_version_info()
const 696 DODSFilter::send_das(FILE *out,
DAS &das,
const string &anc_location,
697 bool with_mime_headers)
const 699 time_t das_lmt = get_das_last_modified_time(anc_location);
701 && das_lmt <= get_request_if_modified_since()
702 && with_mime_headers) {
706 if (with_mime_headers)
726 DODSFilter::send_das(ostream &out,
DAS &das,
const string &anc_location,
727 bool with_mime_headers)
const 729 time_t das_lmt = get_das_last_modified_time(anc_location);
731 && das_lmt <= get_request_if_modified_since()
732 && with_mime_headers) {
736 if (with_mime_headers)
744 DODSFilter::send_das(
DAS &das,
const string &anc_location,
745 bool with_mime_headers)
const 747 send_das(cout, das, anc_location, with_mime_headers);
770 const string &anc_location,
771 bool with_mime_headers)
const 778 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.");
780 time_t dds_lmt = get_dds_last_modified_time(anc_location);
782 && dds_lmt <= get_request_if_modified_since()
783 && with_mime_headers) {
787 if (with_mime_headers)
818 const string &anc_location,
819 bool with_mime_headers)
const 826 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.");
828 time_t dds_lmt = get_dds_last_modified_time(anc_location);
830 && dds_lmt <= get_request_if_modified_since()
831 && with_mime_headers) {
835 if (with_mime_headers)
848 bool constrained,
const string &anc_location,
849 bool with_mime_headers)
const 851 send_dds(cout, dds, eval, constrained, anc_location, with_mime_headers);
861 fprintf(out,
"Dataset {\n");
863 fprintf(out,
"} function_value;\n");
864 fprintf(out,
"Data:\n");
886 out <<
"Dataset {\n" ;
888 out <<
"} function_value;\n" ;
908 FILE * out,
bool ce_eval)
const 912 fprintf(out,
"Data:\n");
921 if ((*i)->send_p()) {
922 DBG(cerr <<
"Sending " << (*i)->name() << endl);
923 (*i)->serialize(eval, dds, m, ce_eval);
934 ostream &out,
bool ce_eval)
const 947 if ((*i)->send_p()) {
948 DBG(cerr <<
"Sending " << (*i)->name() << endl);
949 (*i)->serialize(eval, dds, m, ce_eval);
959 ostream &out,
const string &boundary,
960 const string &start,
bool ce_eval)
const 969 uuid_unparse(uu, &uuid[0]);
971 if (getdomainname(domain, 255) != 0 || strlen(domain) == 0)
972 strncpy(domain,
"opendap.org", 255);
974 string cid = string(&uuid[0]) +
"@" + string(&domain[0]);
988 if ((*i)->send_p()) {
989 DBG(cerr <<
"Sending " << (*i)->name() << endl);
990 (*i)->serialize(eval, dds, m, ce_eval);
1017 FILE * data_stream,
const string & anc_location,
1018 bool with_mime_headers)
const 1023 time_t data_lmt = get_data_last_modified_time(anc_location);
1024 if (is_conditional()
1025 && data_lmt <= get_request_if_modified_since()
1026 && with_mime_headers) {
1031 establish_timeout(data_stream);
1052 #if COMPRESSION_FOR_SERVER3 1053 if (with_mime_headers)
1056 fflush(data_stream);
1060 data_stream =
compressor(data_stream, childpid);
1062 if (with_mime_headers)
1065 fflush(data_stream);
1067 functional_constraint(*var, dds, eval, data_stream);
1075 if (with_mime_headers)
1078 dataset_constraint(*fdds, eval, data_stream,
false);
1082 if (with_mime_headers)
1085 dataset_constraint(dds, eval, data_stream);
1088 fflush(data_stream);
1110 ostream & data_stream,
const string & anc_location,
1111 bool with_mime_headers)
const 1116 time_t data_lmt = get_data_last_modified_time(anc_location);
1117 if (is_conditional()
1118 && data_lmt <= get_request_if_modified_since()
1119 && with_mime_headers) {
1124 establish_timeout(data_stream);
1145 if (with_mime_headers)
1148 data_stream << flush ;
1150 functional_constraint(*var, dds, eval, data_stream);
1157 if (with_mime_headers)
1160 dataset_constraint(*fdds, eval, data_stream,
false);
1164 if (with_mime_headers)
1167 dataset_constraint(dds, eval, data_stream);
1170 data_stream << flush ;
1186 bool with_mime_headers)
const 1193 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.");
1195 time_t dds_lmt = get_dds_last_modified_time(d_anc_dir);
1200 if (is_conditional() && dds_lmt <= get_request_if_modified_since()
1201 && with_mime_headers) {
1206 if (with_mime_headers)
1225 bool with_mime_headers)
const 1232 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.");
1234 time_t dds_lmt = get_dds_last_modified_time(d_anc_dir);
1239 if (is_conditional() && dds_lmt <= get_request_if_modified_since()
1240 && with_mime_headers) {
1245 if (with_mime_headers)
1269 ostream & data_stream,
const string &start,
1270 const string &boundary,
const string & anc_location,
1271 bool with_mime_headers)
const 1276 time_t data_lmt = get_data_last_modified_time(anc_location);
1277 if (is_conditional()
1278 && data_lmt <= get_request_if_modified_since()
1279 && with_mime_headers) {
1284 establish_timeout(data_stream);
1301 if (with_mime_headers)
1303 d_cgi_ver,
x_plain, data_lmt);
1304 data_stream << flush ;
1306 DDS var_dds(&btf, var->
name());
1308 var_dds.add_var(var);
1309 dataset_constraint_ddx(var_dds, eval, data_stream, boundary, start);
1318 if (with_mime_headers)
1320 d_cgi_ver,
x_plain, data_lmt);
1321 data_stream << flush ;
1322 dataset_constraint(*fdds, eval, data_stream,
false);
1326 if (with_mime_headers)
1328 d_cgi_ver,
x_plain, data_lmt);
1329 data_stream << flush ;
1330 dataset_constraint_ddx(dds, eval, data_stream, boundary, start);
1333 data_stream << flush ;
1335 if (with_mime_headers)
1336 data_stream <<
CRLF <<
"--" << boundary <<
"--" <<
CRLF;
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.
void set_mime_data_boundary(ostream &strm, const string &boundary, const string &cid, ObjectType type, EncodingType enc)
time_t last_modified_time(const string &name)
BaseType * eval_function(DDS &dds, const string &dataset)
Evaluate a function-valued constraint expression.
Vars_iter var_begin()
Return an iterator to the first variable.
void parse_constraint(const string &constraint, DDS &dds)
Parse the constraint expression given the current DDS.
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)=0
Move data to the net.
void print_xml(FILE *out, bool constrained, const string &blob="")
void set_mime_text(FILE *out, ObjectType type, const string &ver, EncodingType enc, const time_t last_modified)
virtual void print(FILE *out, bool dereference=false)
#define unknown_error
Unknown error.
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_ddx_boundary(ostream &strm, const string &boundary, const string &cid, ObjectType type, EncodingType enc)
std::vector< BaseType * >::iterator Vars_iter
void set_mime_binary(FILE *out, ObjectType type, const string &ver, EncodingType enc, const time_t last_modified)
marshaller that knows how to marshall/serialize dap data objects to a file using XDR ...
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.
void set_mime_multipart(ostream &strm, const string &boundary, const string &start, ObjectType type, const string &version, EncodingType enc, const time_t last_modified)
bool function_clauses()
Does the current constraint expression return a DDS pointer?
A class for error processing.
EventHandler * register_handler(int signum, EventHandler *eh, bool override=false)
marshaller that knows how to marshal/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.
FILE * compressor(FILE *output, int &childpid)