libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
DODSFilter.cc
Go to the documentation of this file.
1
2// -*- mode: c++; c-basic-offset:4 -*-
3
4// This file is part of libdap, A C++ implementation of the OPeNDAP Data
5// Access Protocol.
6
7// Copyright (c) 2002,2003 OPeNDAP, Inc.
8// Author: James Gallagher <jgallagher@opendap.org>
9//
10// This library is free software; you can redistribute it and/or
11// modify it under the terms of the GNU Lesser General Public
12// License as published by the Free Software Foundation; either
13// version 2.1 of the License, or (at your option) any later version.
14//
15// This library 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 GNU
18// Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public
21// License along with this library; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23//
24// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25
26// (c) COPYRIGHT URI/MIT 1997-1999
27// Please read the full copyright statement in the file COPYRIGHT_URI.
28//
29// Authors:
30// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
31
32// Implementation of the DODSFilter class. This class is used to build dods
33// filter programs which, along with a CGI program, comprise OPeNDAP servers.
34// jhrg 8/26/97
35
36#include "config.h"
37
38#include <signal.h>
39
40#ifndef WIN32
41#include <sys/wait.h>
42#include <unistd.h> // for getopt
43#else
44#include <fcntl.h>
45#include <io.h>
46#include <process.h>
47#endif
48
49#include <algorithm>
50#include <cstdlib>
51#include <cstring>
52#include <iostream>
53#include <sstream>
54#include <string>
55
56#ifdef HAVE_UUID_UUID_H
57#include <uuid/uuid.h> // used to build CID header value for data ddx
58#elif defined(HAVE_UUID_H)
59#include <uuid.h>
60#else
61#error "Could not find UUID library header"
62#endif
63
64#include <GetOpt.h>
65
66#include "Ancillary.h"
67#include "DAS.h"
68#include "DDS.h"
69#include "DODSFilter.h"
70#include "InternalErr.h"
71#include "XDRStreamMarshaller.h"
72#include "debug.h"
73#include "escaping.h"
74#include "mime_util.h"
75#include "util.h"
76
77#ifndef WIN32
78#include "AlarmHandler.h"
79#include "EventHandler.h"
80#include "SignalHandler.h"
81#endif
82
83#define CRLF "\r\n" // Change here, expr-test.cc and DODSFilter.cc
84
85using namespace std;
86
87namespace libdap {
88
89const string usage = "Usage: <handler name> -o <response> -u <url> [options ...] [data set]\n\
90 \n\
91 options: -o <response>: DAS, DDS, DataDDS, DDX, BLOB or Version (Required)\n\
92 -u <url>: The complete URL minus the CE (required for DDX)\n\
93 -c: Compress the response using the deflate algorithm.\n\
94 -e <expr>: When returning a DataDDS, use <expr> as the constraint.\n\
95 -v <version>: Use <version> as the version number\n\
96 -d <dir>: Look for ancillary file in <dir> (deprecated).\n\
97 -f <file>: Look for ancillary data in <file> (deprecated).\n\
98 -r <dir>: Use <dir> as a cache directory\n\
99 -l <time>: Conditional request; if data source is unchanged since\n\
100 <time>, return an HTTP 304 response.\n\
101 -t <seconds>: Timeout the handler after <seconds>.\n\
102 -h: This message.";
103
167
168DODSFilter::DODSFilter(int argc, char *argv[]) throw(Error) {
169 initialize(argc, argv);
170
171 DBG(cerr << "d_comp: " << d_comp << endl);
172 DBG(cerr << "d_dap2ce: " << d_dap2ce << endl);
173 DBG(cerr << "d_cgi_ver: " << d_cgi_ver << endl);
174 DBG(cerr << "d_response: " << d_response << endl);
175 DBG(cerr << "d_anc_dir: " << d_anc_dir << endl);
176 DBG(cerr << "d_anc_file: " << d_anc_file << endl);
177 DBG(cerr << "d_cache_dir: " << d_cache_dir << endl);
178 DBG(cerr << "d_conditional_request: " << d_conditional_request << endl);
179 DBG(cerr << "d_if_modified_since: " << d_if_modified_since << endl);
180 DBG(cerr << "d_url: " << d_url << endl);
181 DBG(cerr << "d_timeout: " << d_timeout << endl);
182}
183
185
189 // Set default values. Don't use the C++ constructor initialization so
190 // that a subclass can have more control over this process.
191 d_comp = false;
192 d_bad_options = false;
193 d_conditional_request = false;
194 d_dataset = "";
195 d_dap2ce = "";
196 d_cgi_ver = "";
197 d_anc_dir = "";
198 d_anc_file = "";
199 d_cache_dir = "";
201 ;
202 d_anc_das_lmt = 0;
203 d_anc_dds_lmt = 0;
205 d_url = "";
206 d_program_name = "Unknown";
207 d_timeout = 0;
208
209#ifdef WIN32
210 // We want serving from win32 to behave in a manner
211 // similar to the UNIX way - no CR->NL terminated lines
212 // in files. Hence stdout goes to binary mode.
213 _setmode(_fileno(stdout), _O_BINARY);
214#endif
215}
216
228void DODSFilter::initialize(int argc, char *argv[]) {
229 initialize();
230
231 d_program_name = argv[0];
232
233 // This should be specialized by a subclass. This may throw Error.
234 int next_arg = process_options(argc, argv);
235
236 // Look at what's left after processing the command line options. Either
237 // there MUST be a dataset name OR the caller is asking for version
238 // information. If neither is true, then the options are bad.
239 if (next_arg < argc) {
240 d_dataset = argv[next_arg];
241 d_dataset = www2id(d_dataset, "%", "%20");
242 } else if (get_response() != Version_Response)
243 print_usage(); // Throws Error
244}
245
254int DODSFilter::process_options(int argc, char *argv[]) {
255 DBG(cerr << "Entering process_options... ");
256
257 int option_char;
258 GetOpt getopt(argc, argv, "ce: v: d: f: r: l: o: u: t: ");
259
260 while ((option_char = getopt()) != -1) {
261 switch (option_char) {
262 case 'c':
263 d_comp = true;
264 break;
265 case 'e':
266 set_ce(getopt.optarg);
267 break;
268 case 'v':
269 set_cgi_version(getopt.optarg);
270 break;
271 case 'd':
272 d_anc_dir = getopt.optarg;
273 break;
274 case 'f':
275 d_anc_file = getopt.optarg;
276 break;
277 case 'r':
278 d_cache_dir = getopt.optarg;
279 break;
280 case 'o':
281 set_response(getopt.optarg);
282 break;
283 case 'u':
284 set_URL(getopt.optarg);
285 break;
286 case 't':
287 d_timeout = atoi(getopt.optarg);
288 break;
289 case 'l':
291 d_if_modified_since = static_cast<time_t>(strtol(getopt.optarg, NULL, 10));
292 break;
293 case 'h':
294 print_usage();
295 break;
296 // exit(1);
297 // Removed 12/29/2011; exit should
298 // not be called by a library. NB:
299 // print_usage() throws Error.
300 default:
301 print_usage(); // Throws Error
302 break;
303 }
304 }
305
306 DBGN(cerr << "exiting." << endl);
307
308 return getopt.optind; // return the index of the next argument
309}
310
316
331
337string DODSFilter::get_cgi_version() const { return d_cgi_ver; }
338
345string DODSFilter::get_ce() const { return d_dap2ce; }
346
347void DODSFilter::set_ce(string _ce) { d_dap2ce = www2id(_ce, "%", "%20"); }
348
357string DODSFilter::get_dataset_name() const { return d_dataset; }
358
359void DODSFilter::set_dataset_name(const string ds) { d_dataset = www2id(ds, "%", "%20"); }
360
364string DODSFilter::get_URL() const { return d_url; }
365
368void DODSFilter::set_URL(const string &url) {
369 if (url.find('?') != url.npos)
370 print_usage(); // Throws Error
371
372 d_url = url;
373}
374
382string DODSFilter::get_dataset_version() const { return ""; }
383
390void DODSFilter::set_response(const string &r) {
391 if (r == "DAS" || r == "das") {
393 d_action = "das";
394 } else if (r == "DDS" || r == "dds") {
396 d_action = "dds";
397 } else if (r == "DataDDS" || r == "dods") {
399 d_action = "dods";
400 } else if (r == "DDX" || r == "ddx") {
402 d_action = "ddx";
403 } else if (r == "DataDDX" || r == "dataddx") {
405 d_action = "dataddx";
406 } else if (r == "Version") {
408 d_action = "version";
409 } else
410 print_usage(); // Throws Error
411}
412
415
417string DODSFilter::get_action() const { return d_action; }
418
440
450time_t DODSFilter::get_das_last_modified_time(const string &anc_location) const {
451 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location=" << anc_location
452 << "call faf(das) d_dataset=" << d_dataset << " d_anc_file=" << d_anc_file << endl);
453
454 string name =
455 Ancillary::find_ancillary_file(d_dataset, "das", (anc_location == "") ? d_anc_dir : anc_location, d_anc_file);
456
457 return max((name != "") ? last_modified_time(name) : 0, get_dataset_last_modified_time());
458}
459
467time_t DODSFilter::get_dds_last_modified_time(const string &anc_location) const {
468 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location=" << anc_location
469 << "call faf(dds) d_dataset=" << d_dataset << " d_anc_file=" << d_anc_file << endl);
470
471 string name =
472 Ancillary::find_ancillary_file(d_dataset, "dds", (anc_location == "") ? d_anc_dir : anc_location, d_anc_file);
473
474 return max((name != "") ? last_modified_time(name) : 0, get_dataset_last_modified_time());
475}
476
490time_t DODSFilter::get_data_last_modified_time(const string &anc_location) const {
491 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location=" << anc_location
492 << "call faf(both) d_dataset=" << d_dataset << " d_anc_file=" << d_anc_file << endl);
493
494 string dds_name =
495 Ancillary::find_ancillary_file(d_dataset, "dds", (anc_location == "") ? d_anc_dir : anc_location, d_anc_file);
496 string das_name =
497 Ancillary::find_ancillary_file(d_dataset, "das", (anc_location == "") ? d_anc_dir : anc_location, d_anc_file);
498
499 time_t m = max((das_name != "") ? last_modified_time(das_name) : (time_t)0,
500 (dds_name != "") ? last_modified_time(dds_name) : (time_t)0);
501 // Note that this is a call to get_dataset_... not get_data_...
503
504 return max(m, n);
505}
506
515
522string DODSFilter::get_cache_dir() const { return d_cache_dir; }
523
529
531int DODSFilter::get_timeout() const { return d_timeout; }
532
543
544void DODSFilter::establish_timeout(FILE *stream) const {
545#ifndef WIN32
546 if (d_timeout > 0) {
548 EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler(stream));
549 delete old_eh;
550 alarm(d_timeout);
551 }
552#endif
553}
554
555void DODSFilter::establish_timeout(ostream &stream) const {
556#ifndef WIN32
557 if (d_timeout > 0) {
559 EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler(stream));
560 delete old_eh;
561 alarm(d_timeout);
562 }
563#endif
564}
565
566static const char *emessage = "DODS internal server error; usage error. Please report this to the dataset maintainer, "
567 "or to the opendap-tech@opendap.org mailing list.";
568
579 // Write a message to the WWW server error log file.
580 ErrMsgT(usage.c_str());
581
582 throw Error(emessage);
583}
584
591
603void DODSFilter::send_das(FILE *out, DAS &das, const string &anc_location, bool with_mime_headers) const {
604 ostringstream oss;
605 send_das(oss, das, anc_location, with_mime_headers);
606 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
607}
608
620void DODSFilter::send_das(ostream &out, DAS &das, const string &anc_location, bool with_mime_headers) const {
621 time_t das_lmt = get_das_last_modified_time(anc_location);
622 if (is_conditional() && das_lmt <= get_request_if_modified_since() && with_mime_headers) {
624 } else {
625 if (with_mime_headers)
626 set_mime_text(out, dods_das, d_cgi_ver, x_plain, das_lmt);
627 das.print(out);
628 }
629 out << flush;
630}
631
632void DODSFilter::send_das(DAS &das, const string &anc_location, bool with_mime_headers) const {
633 send_das(cout, das, anc_location, with_mime_headers);
634}
635
652void DODSFilter::send_dds(FILE *out, DDS &dds, ConstraintEvaluator &eval, bool constrained, const string &anc_location,
653 bool with_mime_headers) const {
654 ostringstream oss;
655 send_dds(oss, dds, eval, constrained, anc_location, with_mime_headers);
656 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
657}
658
675void DODSFilter::send_dds(ostream &out, DDS &dds, ConstraintEvaluator &eval, bool constrained,
676 const string &anc_location, bool with_mime_headers) const {
677 // If constrained, parse the constraint. Throws Error or InternalErr.
678 if (constrained)
679 eval.parse_constraint(d_dap2ce, dds);
680
681 if (eval.functional_expression())
682 throw Error("Function calls can only be used with data requests. To see the structure of the underlying data "
683 "source, reissue the URL without the function.");
684
685 time_t dds_lmt = get_dds_last_modified_time(anc_location);
686 if (is_conditional() && dds_lmt <= get_request_if_modified_since() && with_mime_headers) {
688 } else {
689 if (with_mime_headers)
690 set_mime_text(out, dods_dds, d_cgi_ver, x_plain, dds_lmt);
691 if (constrained)
692 dds.print_constrained(out);
693 else
694 dds.print(out);
695 }
696
697 out << flush;
698}
699
700void DODSFilter::send_dds(DDS &dds, ConstraintEvaluator &eval, bool constrained, const string &anc_location,
701 bool with_mime_headers) const {
702 send_dds(cout, dds, eval, constrained, anc_location, with_mime_headers);
703}
704
705// 'lmt' unused. Should it be used to supply a LMT or removed from the
706// method? jhrg 8/9/05
707void DODSFilter::functional_constraint(BaseType &var, DDS &dds, ConstraintEvaluator &eval, FILE *out) const {
708 ostringstream oss;
709 functional_constraint(var, dds, eval, oss);
710 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
711}
712
713// 'lmt' unused. Should it be used to supply a LMT or removed from the
714// method? jhrg 8/9/05
715void DODSFilter::functional_constraint(BaseType &var, DDS &dds, ConstraintEvaluator &eval, ostream &out) const {
716 out << "Dataset {\n";
717 var.print_decl(out, " ", true, false, true);
718 out << "} function_value;\n";
719 out << "Data:\n";
720
721 out << flush;
722
723 // Grab a stream that encodes using XDR.
724 XDRStreamMarshaller m(out);
725
726 try {
727 // In the following call to serialize, suppress CE evaluation.
728 var.serialize(eval, dds, m, false);
729 } catch (Error &e) {
730 throw;
731 }
732}
733
734void DODSFilter::dataset_constraint(DDS &dds, ConstraintEvaluator &eval, FILE *out, bool ce_eval) const {
735 ostringstream oss;
736 dataset_constraint(dds, eval, oss, ce_eval);
737 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
738}
739
740void DODSFilter::dataset_constraint(DDS &dds, ConstraintEvaluator &eval, ostream &out, bool ce_eval) const {
741 // send constrained DDS
742 dds.print_constrained(out);
743 out << "Data:\n";
744 out << flush;
745
746 // Grab a stream that encodes using XDR.
747 XDRStreamMarshaller m(out);
748
749 try {
750 // Send all variables in the current projection (send_p())
751 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
752 if ((*i)->send_p()) {
753 DBG(cerr << "Sending " << (*i)->name() << endl);
754 (*i)->serialize(eval, dds, m, ce_eval);
755 }
756 } catch (Error &e) {
757 throw;
758 }
759}
760
761void DODSFilter::dataset_constraint_ddx(DDS &dds, ConstraintEvaluator &eval, ostream &out, const string &boundary,
762 const string &start, bool ce_eval) const {
763 // Write the MPM headers for the DDX (text/xml) part of the response
764 set_mime_ddx_boundary(out, boundary, start, dods_ddx);
765
766 // Make cid
767 uuid_t uu;
768 uuid_generate(uu);
769 char uuid[37];
770 uuid_unparse(uu, uuid);
771 char domain[256];
772 if (getdomainname(domain, 255) != 0 || strlen(domain) == 0)
773 strncpy(domain, "opendap.org", 255);
774
775 string cid = string(uuid) + "@" + string(domain);
776
777 // Send constrained DDX with a data blob reference
778 dds.print_xml_writer(out, true, cid);
779
780 // Write the MPM headers for the data part of the response.
781 set_mime_data_boundary(out, boundary, cid, dap4_data, binary);
782
783 // Grab a stream that encodes using XDR.
784 XDRStreamMarshaller m(out);
785
786 try {
787 // Send all variables in the current projection (send_p())
788 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
789 if ((*i)->send_p()) {
790 DBG(cerr << "Sending " << (*i)->name() << endl);
791 (*i)->serialize(eval, dds, m, ce_eval);
792 }
793 } catch (Error &e) {
794 throw;
795 }
796}
797
814void DODSFilter::send_data(DDS &dds, ConstraintEvaluator &eval, FILE *data_stream, const string &anc_location,
815 bool with_mime_headers) const {
816 ostringstream oss;
817 send_data(dds, eval, oss, anc_location, with_mime_headers);
818 fwrite(oss.str().data(), sizeof(char), oss.str().length(), data_stream);
819}
820
837void DODSFilter::send_data(DDS &dds, ConstraintEvaluator &eval, ostream &data_stream, const string &anc_location,
838 bool with_mime_headers) const {
839 // If this is a conditional request and the server should send a 304
840 // response, do that and exit. Otherwise, continue on and send the full
841 // response.
842 time_t data_lmt = get_data_last_modified_time(anc_location);
843 if (is_conditional() && data_lmt <= get_request_if_modified_since() && with_mime_headers) {
844 set_mime_not_modified(data_stream);
845 return;
846 }
847 // Set up the alarm.
848 establish_timeout(data_stream);
850
851 eval.parse_constraint(d_dap2ce, dds); // Throws Error if the ce doesn't
852 // parse.
853
854 dds.tag_nested_sequences(); // Tag Sequences as Parent or Leaf node.
855
856 // Start sending the response...
857
858 // Handle *functional* constraint expressions specially
859#if 0
860 if (eval.functional_expression()) {
861 // Get the result and then start sending the headers. This provides a
862 // way to send errors back to the client w/o colliding with the
863 // normal response headers. There's some duplication of code with this
864 // and the else-clause.
865 BaseType *var = eval.eval_function(dds, d_dataset);
866 if (!var)
867 throw Error(unknown_error, "Error calling the CE function.");
868
869 if (with_mime_headers)
870 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
871
872 data_stream << flush ;
873
874 functional_constraint(*var, dds, eval, data_stream);
875 delete var;
876 var = 0;
877 }
878#endif
879 if (eval.function_clauses()) {
880 DDS *fdds = eval.eval_function_clauses(dds);
881 if (with_mime_headers)
882 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
883
884 dataset_constraint(*fdds, eval, data_stream, false);
885 delete fdds;
886 } else {
887 if (with_mime_headers)
888 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
889
890 dataset_constraint(dds, eval, data_stream);
891 }
892
893 data_stream << flush;
894}
895
906void DODSFilter::send_ddx(DDS &dds, ConstraintEvaluator &eval, FILE *out, bool with_mime_headers) const {
907 ostringstream oss;
908 send_ddx(dds, eval, oss, with_mime_headers);
909 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
910}
911
922void DODSFilter::send_ddx(DDS &dds, ConstraintEvaluator &eval, ostream &out, bool with_mime_headers) const {
923 // If constrained, parse the constraint. Throws Error or InternalErr.
924 if (!d_dap2ce.empty())
925 eval.parse_constraint(d_dap2ce, dds);
926
927 if (eval.functional_expression())
928 throw Error("Function calls can only be used with data requests. To see the structure of the underlying data "
929 "source, reissue the URL without the function.");
930
931 time_t dds_lmt = get_dds_last_modified_time(d_anc_dir);
932
933 // If this is a conditional request and the server should send a 304
934 // response, do that and exit. Otherwise, continue on and send the full
935 // response.
936 if (is_conditional() && dds_lmt <= get_request_if_modified_since() && with_mime_headers) {
938 return;
939 } else {
940 if (with_mime_headers)
941 set_mime_text(out, dods_ddx, d_cgi_ver, x_plain, dds_lmt);
942 dds.print_xml_writer(out, !d_dap2ce.empty(), "");
943 }
944}
945
966void DODSFilter::send_data_ddx(DDS &dds, ConstraintEvaluator &eval, ostream &data_stream, const string &start,
967 const string &boundary, const string &anc_location, bool with_mime_headers) const {
968 // If this is a conditional request and the server should send a 304
969 // response, do that and exit. Otherwise, continue on and send the full
970 // response.
971 time_t data_lmt = get_data_last_modified_time(anc_location);
972 if (is_conditional() && data_lmt <= get_request_if_modified_since() && with_mime_headers) {
973 set_mime_not_modified(data_stream);
974 return;
975 }
976 // Set up the alarm.
977 establish_timeout(data_stream);
979
980 eval.parse_constraint(d_dap2ce, dds); // Throws Error if the ce doesn't
981 // parse.
982
983 dds.tag_nested_sequences(); // Tag Sequences as Parent or Leaf node.
984
985 // Start sending the response...
986
987 // Handle *functional* constraint expressions specially
988#if 0
989 if (eval.functional_expression()) {
990 BaseType *var = eval.eval_function(dds, d_dataset);
991 if (!var)
992 throw Error(unknown_error, "Error calling the CE function.");
993
994 if (with_mime_headers)
995 set_mime_multipart(data_stream, boundary, start, dods_data_ddx,
996 d_cgi_ver, x_plain, data_lmt);
997 data_stream << flush ;
998 BaseTypeFactory btf;
999 DDS var_dds(&btf, var->name());
1000 var->set_send_p(true);
1001 var_dds.add_var(var);
1002 serialize_dap2_data_ddx(var_dds, eval, data_stream, boundary, start);
1003
1004 // functional_constraint_ddx(*var, dds, eval, data_stream, boundary);
1005 delete var;
1006 var = 0;
1007 }
1008#endif
1009 if (eval.function_clauses()) {
1010 DDS *fdds = eval.eval_function_clauses(dds);
1011 if (with_mime_headers)
1012 set_mime_multipart(data_stream, boundary, start, dods_data_ddx, d_cgi_ver, x_plain, data_lmt);
1013 data_stream << flush;
1014 dataset_constraint(*fdds, eval, data_stream, false);
1015 delete fdds;
1016 } else {
1017 if (with_mime_headers)
1018 set_mime_multipart(data_stream, boundary, start, dods_data_ddx, d_cgi_ver, x_plain, data_lmt);
1019 data_stream << flush;
1020 dataset_constraint_ddx(dds, eval, data_stream, boundary, start);
1021 }
1022
1023 data_stream << flush;
1024
1025 if (with_mime_headers)
1026 data_stream << CRLF << "--" << boundary << "--" << CRLF;
1027}
1028
1029} // namespace libdap
#define CRLF
#define unknown_error
Unknown error (the default code) (HTTP 400)
Definition Error.h:62
char * optarg
Definition GetOpt.h:95
int optind
Definition GetOpt.h:108
static string find_ancillary_file(const string &pathname, const string &ext, const string &dir, const string &file)
Find a file with ancillary data.
Definition Ancillary.cc:68
The basic data type for the DODS DAP types.
Definition BaseType.h:118
virtual string name() const
Returns the name of the class instance.
Definition BaseType.cc:296
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.
Definition BaseType.cc:868
virtual void set_send_p(bool state)
Definition BaseType.cc:488
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Move data to the net, then remove them from the object.
Definition BaseType.cc:810
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.
Definition DAS.h:119
virtual void print(FILE *out, bool dereference=false)
Definition DAS.cc:304
void print(FILE *out)
Print the entire DDS to the specified file.
Definition DDS.cc:812
void tag_nested_sequences()
Traverse DDS, set Sequence leaf nodes.
Definition DDS.cc:730
Vars_iter var_begin()
Definition DDS.h:336
void print_constrained(FILE *out)
Print a constrained DDS to the specified file.
Definition DDS.cc:1071
void set_timeout(int t)
Definition DDS.cc:714
Vars_iter var_end()
Return an iterator.
Definition DDS.h:341
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 ...
Definition DDS.cc:482
std::vector< BaseType * >::iterator Vars_iter
Definition DDS.h:211
void print_xml_writer(ostream &out, bool constrained, const string &blob="")
Definition DDS.cc:1148
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 ~DODSFilter()
virtual void send_dds(DDS &dds, ConstraintEvaluator &eval, bool constrained=false, const string &anc_location="", bool with_mime_headers=true) 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 establish_timeout(ostream &stream) const
virtual void set_URL(const string &url)
time_t d_if_modified_since
Definition DODSFilter.h:112
virtual string get_action() const
virtual void set_ce(string _ce)
virtual void functional_constraint(BaseType &var, DDS &dds, ConstraintEvaluator &eval, ostream &out) const
void set_timeout(int timeout=0)
virtual void send_das(DAS &das, const string &anc_location="", bool with_mime_headers=true) const
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 set_dataset_name(const string _dataset)
virtual void dataset_constraint(DDS &dds, ConstraintEvaluator &eval, ostream &out, bool ce_eval=true) 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)
int get_timeout() const
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 void dataset_constraint_ddx(DDS &dds, ConstraintEvaluator &eval, ostream &out, const string &boundary, const string &start, bool ce_eval=true) const
virtual time_t get_data_last_modified_time(const string &anc_location="") const
A class for error processing.
Definition Error.h:92
static EventHandler * register_handler(int signum, EventHandler *eh, bool ignore_by_default=false)
static SignalHandler * instance()
Marshaller that knows how serialize dap data objects to a C++ iostream using XDR.
#define DBGN(x)
Definition debug.h:59
#define DBG(x)
Definition debug.h:58
const char * version
Definition getdap.cc:65
top level DAP object to house generic methods
Definition AISConnect.cc:30
void set_mime_data_boundary(ostream &strm, const string &boundary, const string &cid, ObjectType type, EncodingType enc)
Definition mime_util.cc:748
string www2id(const string &in, const string &escape, const string &except)
Definition escaping.cc:202
void set_mime_ddx_boundary(ostream &strm, const string &boundary, const string &cid, ObjectType type, EncodingType enc)
Definition mime_util.cc:734
time_t last_modified_time(const string &name)
Definition mime_util.cc:94
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)
Definition mime_util.cc:575
const string usage
Definition DODSFilter.cc:89
bool do_version(const string &script_ver, const string &dataset_ver)
Send a version number.
Definition mime_util.cc:178
void set_mime_multipart(ostream &strm, const string &boundary, const string &start, ObjectType type, const string &version, EncodingType enc, const time_t last_modified)
Definition mime_util.cc:665
void ErrMsgT(const string &Msgt)
Logs an error message.
Definition mime_util.cc:209
@ dods_das
Definition ObjectType.h:59
@ dods_data_ddx
Definition ObjectType.h:63
@ dap4_data
Definition ObjectType.h:68
@ dods_data
Definition ObjectType.h:61
@ dods_dds
Definition ObjectType.h:60
@ dods_ddx
Definition ObjectType.h:62
void set_mime_text(FILE *out, ObjectType type, const string &ver, EncodingType enc, const time_t last_modified)
Definition mime_util.cc:349