00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "config.h"
00038
00039 static char rcsid[] not_used =
00040 {"$Id: DODSFilter.cc 23477 2010-09-02 21:02:59Z jimg $"
00041 };
00042
00043 #include <signal.h>
00044
00045 #ifndef WIN32
00046 #include <unistd.h>
00047 #include <sys/wait.h>
00048 #else
00049 #include <io.h>
00050 #include <fcntl.h>
00051 #include <process.h>
00052 #endif
00053
00054 #include <iostream>
00055 #include <string>
00056 #include <algorithm>
00057 #include <cstdlib>
00058 #include <cstring>
00059
00060 #include <uuid/uuid.h>
00061
00062 #include <GetOpt.h>
00063
00064 #include "DAS.h"
00065 #include "DDS.h"
00066 #include "debug.h"
00067 #include "mime_util.h"
00068 #include "Ancillary.h"
00069 #include "util.h"
00070 #include "escaping.h"
00071 #include "DODSFilter.h"
00072 #if FILE_METHODS
00073 #include "XDRFileMarshaller.h"
00074 #endif
00075 #include "XDRStreamMarshaller.h"
00076 #include "InternalErr.h"
00077
00078 #ifndef WIN32
00079 #include "SignalHandler.h"
00080 #include "EventHandler.h"
00081 #include "AlarmHandler.h"
00082 #endif
00083
00084 #define CRLF "\r\n" // Change here, expr-test.cc and DODSFilter.cc
00085
00086
00087
00088 using namespace std;
00089
00090 namespace libdap {
00091
00092 const string usage =
00093 "Usage: <handler name> -o <response> -u <url> [options ...] [data set]\n\
00094 \n\
00095 options: -o <response>: DAS, DDS, DataDDS, DDX, BLOB or Version (Required)\n\
00096 -u <url>: The complete URL minus the CE (required for DDX)\n\
00097 -c: Compress the response using the deflate algorithm.\n\
00098 -e <expr>: When returning a DataDDS, use <expr> as the constraint.\n\
00099 -v <version>: Use <version> as the version number\n\
00100 -d <dir>: Look for ancillary file in <dir> (deprecated).\n\
00101 -f <file>: Look for ancillary data in <file> (deprecated).\n\
00102 -r <dir>: Use <dir> as a cache directory\n\
00103 -l <time>: Conditional request; if data source is unchanged since\n\
00104 <time>, return an HTTP 304 response.\n\
00105 -t <seconds>: Timeout the handler after <seconds>.\n\
00106 -h: This message.";
00107
00172 DODSFilter::DODSFilter(int argc, char *argv[]) throw(Error)
00173 {
00174 initialize(argc, argv);
00175
00176 DBG(cerr << "d_comp: " << d_comp << endl);
00177 DBG(cerr << "d_ce: " << d_ce << endl);
00178 DBG(cerr << "d_cgi_ver: " << d_cgi_ver << endl);
00179 DBG(cerr << "d_response: " << d_response << endl);
00180 DBG(cerr << "d_anc_dir: " << d_anc_dir << endl);
00181 DBG(cerr << "d_anc_file: " << d_anc_file << endl);
00182 DBG(cerr << "d_cache_dir: " << d_cache_dir << endl);
00183 DBG(cerr << "d_conditional_request: " << d_conditional_request << endl);
00184 DBG(cerr << "d_if_modified_since: " << d_if_modified_since << endl);
00185 DBG(cerr << "d_url: " << d_url << endl);
00186 DBG(cerr << "d_timeout: " << d_timeout << endl);
00187 }
00188
00189 DODSFilter::~DODSFilter()
00190 {
00191 }
00192
00195 void
00196 DODSFilter::initialize()
00197 {
00198
00199
00200 d_comp = false;
00201 d_bad_options = false;
00202 d_conditional_request = false;
00203 d_dataset = "";
00204 d_ce = "";
00205 d_cgi_ver = "";
00206 d_anc_dir = "";
00207 d_anc_file = "";
00208 d_cache_dir = "";
00209 d_response = Unknown_Response;;
00210 d_anc_das_lmt = 0;
00211 d_anc_dds_lmt = 0;
00212 d_if_modified_since = -1;
00213 d_url = "";
00214 d_program_name = "Unknown";
00215 d_timeout = 0;
00216
00217 #ifdef WIN32
00218
00219
00220
00221 _setmode(_fileno(stdout), _O_BINARY);
00222 #endif
00223 }
00224
00236 void
00237 DODSFilter::initialize(int argc, char *argv[])
00238 {
00239 initialize();
00240
00241 d_program_name = argv[0];
00242
00243
00244 int next_arg = process_options(argc, argv);
00245
00246
00247
00248
00249 if (next_arg < argc) {
00250 d_dataset = argv[next_arg];
00251 d_dataset = www2id(d_dataset, "%", "%20");
00252 }
00253 else if (get_response() != Version_Response)
00254 print_usage();
00255 }
00256
00265 int
00266 DODSFilter::process_options(int argc, char *argv[])
00267 {
00268 DBG(cerr << "Entering process_options... ");
00269
00270 int option_char;
00271 GetOpt getopt (argc, argv, "ce: v: d: f: r: l: o: u: t: ");
00272
00273 while ((option_char = getopt()) != EOF) {
00274 switch (option_char) {
00275 case 'c': d_comp = true; break;
00276 case 'e': set_ce(getopt.optarg); break;
00277 case 'v': set_cgi_version(getopt.optarg); break;
00278 case 'd': d_anc_dir = getopt.optarg; break;
00279 case 'f': d_anc_file = getopt.optarg; break;
00280 case 'r': d_cache_dir = getopt.optarg; break;
00281 case 'o': set_response(getopt.optarg); break;
00282 case 'u': set_URL(getopt.optarg); break;
00283 case 't': d_timeout = atoi(getopt.optarg); break;
00284 case 'l':
00285 d_conditional_request = true;
00286 d_if_modified_since
00287 = static_cast<time_t>(strtol(getopt.optarg, NULL, 10));
00288 break;
00289 case 'h': print_usage(); exit(1);
00290 default: print_usage();
00291 }
00292 }
00293
00294 DBGN(cerr << "exiting." << endl);
00295
00296 return getopt.optind;
00297 }
00298
00303 bool
00304 DODSFilter::is_conditional() const
00305 {
00306 return d_conditional_request;
00307 }
00308
00322 void
00323 DODSFilter::set_cgi_version(string version)
00324 {
00325 d_cgi_ver = version;
00326 }
00327
00333 string
00334 DODSFilter::get_cgi_version() const
00335 {
00336 return d_cgi_ver;
00337 }
00338
00345 string
00346 DODSFilter::get_ce() const
00347 {
00348 return d_ce;
00349 }
00350
00351 void
00352 DODSFilter::set_ce(string _ce)
00353 {
00354 d_ce = www2id(_ce, "%", "%20");
00355 }
00356
00365 string
00366 DODSFilter::get_dataset_name() const
00367 {
00368 return d_dataset;
00369 }
00370
00371 void
00372 DODSFilter::set_dataset_name(const string ds)
00373 {
00374 d_dataset = www2id(ds, "%", "%20");
00375 }
00376
00380 string
00381 DODSFilter::get_URL() const
00382 {
00383 return d_url;
00384 }
00385
00388 void
00389 DODSFilter::set_URL(const string &url)
00390 {
00391 if (url.find('?') != url.npos)
00392 print_usage();
00393
00394 d_url = url;
00395 }
00396
00404 string
00405 DODSFilter::get_dataset_version() const
00406 {
00407 return "";
00408 }
00409
00416 void DODSFilter::set_response(const string &r)
00417 {
00418 if (r == "DAS" || r == "das") {
00419 d_response = DAS_Response;
00420 d_action = "das" ;
00421 }
00422 else if (r == "DDS" || r == "dds") {
00423 d_response = DDS_Response;
00424 d_action = "dds" ;
00425 }
00426 else if (r == "DataDDS" || r == "dods") {
00427 d_response = DataDDS_Response;
00428 d_action = "dods" ;
00429 }
00430 else if (r == "DDX" || r == "ddx") {
00431 d_response = DDX_Response;
00432 d_action = "ddx" ;
00433 }
00434 else if (r == "DataDDX" || r == "dataddx") {
00435 d_response = DataDDX_Response;
00436 d_action = "dataddx" ;
00437 }
00438 else if (r == "Version") {
00439 d_response = Version_Response;
00440 d_action = "version" ;
00441 }
00442 else
00443 print_usage();
00444 }
00445
00447 DODSFilter::Response
00448 DODSFilter::get_response() const
00449 {
00450 return d_response;
00451 }
00452
00454 string DODSFilter::get_action() const
00455 {
00456 return d_action;
00457 }
00458
00479 time_t
00480 DODSFilter::get_dataset_last_modified_time() const
00481 {
00482 return last_modified_time(d_dataset);
00483 }
00484
00494 time_t
00495 DODSFilter::get_das_last_modified_time(const string &anc_location) const
00496 {
00497 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location="
00498 << anc_location << "call faf(das) d_dataset=" << d_dataset
00499 << " d_anc_file=" << d_anc_file << endl);
00500
00501 string name
00502 = Ancillary::find_ancillary_file(d_dataset, "das",
00503 (anc_location == "") ? d_anc_dir : anc_location,
00504 d_anc_file);
00505
00506 return max((name != "") ? last_modified_time(name) : 0,
00507 get_dataset_last_modified_time());
00508 }
00509
00517 time_t
00518 DODSFilter::get_dds_last_modified_time(const string &anc_location) const
00519 {
00520 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location="
00521 << anc_location << "call faf(dds) d_dataset=" << d_dataset
00522 << " d_anc_file=" << d_anc_file << endl);
00523
00524 string name
00525 = Ancillary::find_ancillary_file(d_dataset, "dds",
00526 (anc_location == "") ? d_anc_dir : anc_location,
00527 d_anc_file);
00528
00529 return max((name != "") ? last_modified_time(name) : 0,
00530 get_dataset_last_modified_time());
00531 }
00532
00546 time_t
00547 DODSFilter::get_data_last_modified_time(const string &anc_location) const
00548 {
00549 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location="
00550 << anc_location << "call faf(both) d_dataset=" << d_dataset
00551 << " d_anc_file=" << d_anc_file << endl);
00552
00553 string dds_name
00554 = Ancillary::find_ancillary_file(d_dataset, "dds",
00555 (anc_location == "") ? d_anc_dir : anc_location,
00556 d_anc_file);
00557 string das_name
00558 = Ancillary::find_ancillary_file(d_dataset, "das",
00559 (anc_location == "") ? d_anc_dir : anc_location,
00560 d_anc_file);
00561
00562 time_t m = max((das_name != "") ? last_modified_time(das_name) : (time_t)0,
00563 (dds_name != "") ? last_modified_time(dds_name) : (time_t)0);
00564
00565 time_t n = get_dataset_last_modified_time();
00566
00567 return max(m, n);
00568 }
00569
00577 time_t
00578 DODSFilter::get_request_if_modified_since() const
00579 {
00580 return d_if_modified_since;
00581 }
00582
00589 string
00590 DODSFilter::get_cache_dir() const
00591 {
00592 return d_cache_dir;
00593 }
00594
00599 void
00600 DODSFilter::set_timeout(int t)
00601 {
00602 d_timeout = t;
00603 }
00604
00606 int
00607 DODSFilter::get_timeout() const
00608 {
00609 return d_timeout;
00610 }
00611
00612 #if FILE_METHODS
00613
00624 void
00625 DODSFilter::establish_timeout(FILE *stream) const
00626 {
00627 #ifndef WIN32
00628 if (d_timeout > 0) {
00629 SignalHandler *sh = SignalHandler::instance();
00630 EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler(stream));
00631 delete old_eh;
00632 alarm(d_timeout);
00633 }
00634 #endif
00635 }
00636 #endif
00637
00638
00639 void
00640 DODSFilter::establish_timeout(ostream &stream) const
00641 {
00642 #ifndef WIN32
00643 if (d_timeout > 0) {
00644 SignalHandler *sh = SignalHandler::instance();
00645 EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler(stream));
00646 delete old_eh;
00647 alarm(d_timeout);
00648 }
00649 #endif
00650 }
00651
00652 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.";
00653
00663 void
00664 DODSFilter::print_usage() const
00665 {
00666
00667 ErrMsgT(usage.c_str());
00668
00669 throw Error(unknown_error, emessage);
00670 }
00671
00677 void
00678 DODSFilter::send_version_info() const
00679 {
00680 do_version(d_cgi_ver, get_dataset_version());
00681 }
00682
00683 #if FILE_METHODS
00684
00695 void
00696 DODSFilter::send_das(FILE *out, DAS &das, const string &anc_location,
00697 bool with_mime_headers) const
00698 {
00699 time_t das_lmt = get_das_last_modified_time(anc_location);
00700 if (is_conditional()
00701 && das_lmt <= get_request_if_modified_since()
00702 && with_mime_headers) {
00703 set_mime_not_modified(out);
00704 }
00705 else {
00706 if (with_mime_headers)
00707 set_mime_text(out, dods_das, d_cgi_ver, x_plain, das_lmt);
00708 das.print(out);
00709 }
00710 fflush(out) ;
00711 }
00712 #endif
00713
00725 void
00726 DODSFilter::send_das(ostream &out, DAS &das, const string &anc_location,
00727 bool with_mime_headers) const
00728 {
00729 time_t das_lmt = get_das_last_modified_time(anc_location);
00730 if (is_conditional()
00731 && das_lmt <= get_request_if_modified_since()
00732 && with_mime_headers) {
00733 set_mime_not_modified(out);
00734 }
00735 else {
00736 if (with_mime_headers)
00737 set_mime_text(out, dods_das, d_cgi_ver, x_plain, das_lmt);
00738 das.print(out);
00739 }
00740 out << flush ;
00741 }
00742
00743 void
00744 DODSFilter::send_das(DAS &das, const string &anc_location,
00745 bool with_mime_headers) const
00746 {
00747 send_das(cout, das, anc_location, with_mime_headers);
00748 }
00749
00750 #if FILE_METHODS
00751
00767 void
00768 DODSFilter::send_dds(FILE *out, DDS &dds, ConstraintEvaluator &eval,
00769 bool constrained,
00770 const string &anc_location,
00771 bool with_mime_headers) const
00772 {
00773
00774 if (constrained)
00775 eval.parse_constraint(d_ce, dds);
00776
00777 if (eval.functional_expression())
00778 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.");
00779
00780 time_t dds_lmt = get_dds_last_modified_time(anc_location);
00781 if (is_conditional()
00782 && dds_lmt <= get_request_if_modified_since()
00783 && with_mime_headers) {
00784 set_mime_not_modified(out);
00785 }
00786 else {
00787 if (with_mime_headers)
00788 set_mime_text(out, dods_dds, d_cgi_ver, x_plain, dds_lmt);
00789 if (constrained)
00790 dds.print_constrained(out);
00791 else
00792 dds.print(out);
00793 }
00794
00795 fflush(out) ;
00796 }
00797 #endif
00798
00815 void
00816 DODSFilter::send_dds(ostream &out, DDS &dds, ConstraintEvaluator &eval,
00817 bool constrained,
00818 const string &anc_location,
00819 bool with_mime_headers) const
00820 {
00821
00822 if (constrained)
00823 eval.parse_constraint(d_ce, dds);
00824
00825 if (eval.functional_expression())
00826 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.");
00827
00828 time_t dds_lmt = get_dds_last_modified_time(anc_location);
00829 if (is_conditional()
00830 && dds_lmt <= get_request_if_modified_since()
00831 && with_mime_headers) {
00832 set_mime_not_modified(out);
00833 }
00834 else {
00835 if (with_mime_headers)
00836 set_mime_text(out, dods_dds, d_cgi_ver, x_plain, dds_lmt);
00837 if (constrained)
00838 dds.print_constrained(out);
00839 else
00840 dds.print(out);
00841 }
00842
00843 out << flush ;
00844 }
00845
00846 void
00847 DODSFilter::send_dds(DDS &dds, ConstraintEvaluator &eval,
00848 bool constrained, const string &anc_location,
00849 bool with_mime_headers) const
00850 {
00851 send_dds(cout, dds, eval, constrained, anc_location, with_mime_headers);
00852 }
00853
00854 #if FILE_METHODS
00855
00856
00857 void
00858 DODSFilter::functional_constraint(BaseType &var, DDS &dds,
00859 ConstraintEvaluator &eval, FILE *out) const
00860 {
00861 fprintf(out, "Dataset {\n");
00862 var.print_decl(out, " ", true, false, true);
00863 fprintf(out, "} function_value;\n");
00864 fprintf(out, "Data:\n");
00865
00866 fflush(out);
00867
00868 XDRFileMarshaller m( out ) ;
00869
00870 try {
00871
00872 var.serialize(eval, dds, m, false);
00873 }
00874 catch (Error &e) {
00875 throw;
00876 }
00877 }
00878 #endif
00879
00880
00881
00882 void
00883 DODSFilter::functional_constraint(BaseType &var, DDS &dds,
00884 ConstraintEvaluator &eval, ostream &out) const
00885 {
00886 out << "Dataset {\n" ;
00887 var.print_decl(out, " ", true, false, true);
00888 out << "} function_value;\n" ;
00889 out << "Data:\n" ;
00890
00891 out << flush ;
00892
00893
00894 XDRStreamMarshaller m( out ) ;
00895
00896 try {
00897
00898 var.serialize(eval, dds, m, false);
00899 }
00900 catch (Error &e) {
00901 throw;
00902 }
00903 }
00904
00905 #if FILE_METHODS
00906 void
00907 DODSFilter::dataset_constraint(DDS & dds, ConstraintEvaluator & eval,
00908 FILE * out, bool ce_eval) const
00909 {
00910
00911 dds.print_constrained(out);
00912 fprintf(out, "Data:\n");
00913 fflush(out);
00914
00915
00916 XDRFileMarshaller m( out ) ;
00917
00918 try {
00919
00920 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
00921 if ((*i)->send_p()) {
00922 DBG(cerr << "Sending " << (*i)->name() << endl);
00923 (*i)->serialize(eval, dds, m, ce_eval);
00924 }
00925 }
00926 catch (Error & e) {
00927 throw;
00928 }
00929 }
00930 #endif
00931
00932 void
00933 DODSFilter::dataset_constraint(DDS & dds, ConstraintEvaluator & eval,
00934 ostream &out, bool ce_eval) const
00935 {
00936
00937 dds.print_constrained(out);
00938 out << "Data:\n" ;
00939 out << flush ;
00940
00941
00942 XDRStreamMarshaller m( out ) ;
00943
00944 try {
00945
00946 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
00947 if ((*i)->send_p()) {
00948 DBG(cerr << "Sending " << (*i)->name() << endl);
00949 (*i)->serialize(eval, dds, m, ce_eval);
00950 }
00951 }
00952 catch (Error & e) {
00953 throw;
00954 }
00955 }
00956
00957 void
00958 DODSFilter::dataset_constraint_ddx(DDS & dds, ConstraintEvaluator & eval,
00959 ostream &out, const string &boundary,
00960 const string &start, bool ce_eval) const
00961 {
00962
00963 set_mime_ddx_boundary(out, boundary, start, dap4_ddx);
00964
00965
00966 uuid_t uu;
00967 uuid_generate(uu);
00968 char uuid[37];
00969 uuid_unparse(uu, &uuid[0]);
00970 char domain[256];
00971 if (getdomainname(domain, 255) != 0 || strlen(domain) == 0)
00972 strncpy(domain, "opendap.org", 255);
00973
00974 string cid = string(&uuid[0]) + "@" + string(&domain[0]);
00975
00976
00977 dds.print_xml(out, true, cid);
00978
00979
00980 set_mime_data_boundary(out, boundary, cid, dap4_data, binary);
00981
00982
00983 XDRStreamMarshaller m( out ) ;
00984
00985 try {
00986
00987 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
00988 if ((*i)->send_p()) {
00989 DBG(cerr << "Sending " << (*i)->name() << endl);
00990 (*i)->serialize(eval, dds, m, ce_eval);
00991 }
00992 }
00993 catch (Error & e) {
00994 throw;
00995 }
00996 }
00997
00998 #if FILE_METHODS
00999
01015 void
01016 DODSFilter::send_data(DDS & dds, ConstraintEvaluator & eval,
01017 FILE * data_stream, const string & anc_location,
01018 bool with_mime_headers) const
01019 {
01020
01021
01022
01023 time_t data_lmt = get_data_last_modified_time(anc_location);
01024 if (is_conditional()
01025 && data_lmt <= get_request_if_modified_since()
01026 && with_mime_headers) {
01027 set_mime_not_modified(data_stream);
01028 return;
01029 }
01030
01031 establish_timeout(data_stream);
01032 dds.set_timeout(d_timeout);
01033
01034 eval.parse_constraint(d_ce, dds);
01035
01036
01037 dds.tag_nested_sequences();
01038
01039
01040
01041
01042 #if 0
01043 if (eval.functional_expression()) {
01044
01045
01046
01047
01048 BaseType *var = eval.eval_function(dds, d_dataset);
01049 if (!var)
01050 throw Error(unknown_error, "Error calling the CE function.");
01051
01052 #if COMPRESSION_FOR_SERVER3
01053 if (with_mime_headers)
01054 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01055 (compress) ? deflate : x_plain, data_lmt);
01056 fflush(data_stream);
01057
01058 int childpid;
01059 if (compress)
01060 data_stream = compressor(data_stream, childpid);
01061 #endif
01062 if (with_mime_headers)
01063 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01064
01065 fflush(data_stream);
01066
01067 functional_constraint(*var, dds, eval, data_stream);
01068 delete var;
01069 var = 0;
01070 }
01071 #endif
01072 if (eval.function_clauses()) {
01073 DDS *fdds = eval.eval_function_clauses(dds);
01074
01075 if (with_mime_headers)
01076 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01077
01078 dataset_constraint(*fdds, eval, data_stream, false);
01079 delete fdds;
01080 }
01081 else {
01082 if (with_mime_headers)
01083 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01084
01085 dataset_constraint(dds, eval, data_stream);
01086 }
01087
01088 fflush(data_stream);
01089 }
01090 #endif
01091
01108 void
01109 DODSFilter::send_data(DDS & dds, ConstraintEvaluator & eval,
01110 ostream & data_stream, const string & anc_location,
01111 bool with_mime_headers) const
01112 {
01113
01114
01115
01116 time_t data_lmt = get_data_last_modified_time(anc_location);
01117 if (is_conditional()
01118 && data_lmt <= get_request_if_modified_since()
01119 && with_mime_headers) {
01120 set_mime_not_modified(data_stream);
01121 return;
01122 }
01123
01124 establish_timeout(data_stream);
01125 dds.set_timeout(d_timeout);
01126
01127 eval.parse_constraint(d_ce, dds);
01128
01129
01130 dds.tag_nested_sequences();
01131
01132
01133
01134
01135 #if 0
01136 if (eval.functional_expression()) {
01137
01138
01139
01140
01141 BaseType *var = eval.eval_function(dds, d_dataset);
01142 if (!var)
01143 throw Error(unknown_error, "Error calling the CE function.");
01144
01145 if (with_mime_headers)
01146 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01147
01148 data_stream << flush ;
01149
01150 functional_constraint(*var, dds, eval, data_stream);
01151 delete var;
01152 var = 0;
01153 }
01154 #endif
01155 if (eval.function_clauses()) {
01156 DDS *fdds = eval.eval_function_clauses(dds);
01157 if (with_mime_headers)
01158 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01159
01160 dataset_constraint(*fdds, eval, data_stream, false);
01161 delete fdds;
01162 }
01163 else {
01164 if (with_mime_headers)
01165 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01166
01167 dataset_constraint(dds, eval, data_stream);
01168 }
01169
01170 data_stream << flush ;
01171 }
01172
01173 #if FILE_METHODS
01174
01184 void
01185 DODSFilter::send_ddx(DDS &dds, ConstraintEvaluator &eval, FILE *out,
01186 bool with_mime_headers) const
01187 {
01188
01189 if (!d_ce.empty())
01190 eval.parse_constraint(d_ce, dds);
01191
01192 if (eval.functional_expression())
01193 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.");
01194
01195 time_t dds_lmt = get_dds_last_modified_time(d_anc_dir);
01196
01197
01198
01199
01200 if (is_conditional() && dds_lmt <= get_request_if_modified_since()
01201 && with_mime_headers) {
01202 set_mime_not_modified(out);
01203 return;
01204 }
01205 else {
01206 if (with_mime_headers)
01207 set_mime_text(out, dap4_ddx, d_cgi_ver, x_plain, dds_lmt);
01208 dds.print_xml(out, !d_ce.empty(), "");
01209 }
01210 }
01211 #endif
01212
01223 void
01224 DODSFilter::send_ddx(DDS &dds, ConstraintEvaluator &eval, ostream &out,
01225 bool with_mime_headers) const
01226 {
01227
01228 if (!d_ce.empty())
01229 eval.parse_constraint(d_ce, dds);
01230
01231 if (eval.functional_expression())
01232 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.");
01233
01234 time_t dds_lmt = get_dds_last_modified_time(d_anc_dir);
01235
01236
01237
01238
01239 if (is_conditional() && dds_lmt <= get_request_if_modified_since()
01240 && with_mime_headers) {
01241 set_mime_not_modified(out);
01242 return;
01243 }
01244 else {
01245 if (with_mime_headers)
01246 set_mime_text(out, dap4_ddx, d_cgi_ver, x_plain, dds_lmt);
01247 dds.print_xml(out, !d_ce.empty(), "");
01248 }
01249 }
01250
01267 void
01268 DODSFilter::send_data_ddx(DDS & dds, ConstraintEvaluator & eval,
01269 ostream & data_stream, const string &start,
01270 const string &boundary, const string & anc_location,
01271 bool with_mime_headers) const
01272 {
01273
01274
01275
01276 time_t data_lmt = get_data_last_modified_time(anc_location);
01277 if (is_conditional()
01278 && data_lmt <= get_request_if_modified_since()
01279 && with_mime_headers) {
01280 set_mime_not_modified(data_stream);
01281 return;
01282 }
01283
01284 establish_timeout(data_stream);
01285 dds.set_timeout(d_timeout);
01286
01287 eval.parse_constraint(d_ce, dds);
01288
01289
01290 dds.tag_nested_sequences();
01291
01292
01293
01294
01295 #if 0
01296 if (eval.functional_expression()) {
01297 BaseType *var = eval.eval_function(dds, d_dataset);
01298 if (!var)
01299 throw Error(unknown_error, "Error calling the CE function.");
01300
01301 if (with_mime_headers)
01302 set_mime_multipart(data_stream, boundary, start, dap4_data_ddx,
01303 d_cgi_ver, x_plain, data_lmt);
01304 data_stream << flush ;
01305 BaseTypeFactory btf;
01306 DDS var_dds(&btf, var->name());
01307 var->set_send_p(true);
01308 var_dds.add_var(var);
01309 dataset_constraint_ddx(var_dds, eval, data_stream, boundary, start);
01310
01311
01312 delete var;
01313 var = 0;
01314 }
01315 #endif
01316 if (eval.function_clauses()) {
01317 DDS *fdds = eval.eval_function_clauses(dds);
01318 if (with_mime_headers)
01319 set_mime_multipart(data_stream, boundary, start, dap4_data_ddx,
01320 d_cgi_ver, x_plain, data_lmt);
01321 data_stream << flush ;
01322 dataset_constraint(*fdds, eval, data_stream, false);
01323 delete fdds;
01324 }
01325 else {
01326 if (with_mime_headers)
01327 set_mime_multipart(data_stream, boundary, start, dap4_data_ddx,
01328 d_cgi_ver, x_plain, data_lmt);
01329 data_stream << flush ;
01330 dataset_constraint_ddx(dds, eval, data_stream, boundary, start);
01331 }
01332
01333 data_stream << flush ;
01334
01335 if (with_mime_headers)
01336 data_stream << CRLF << "--" << boundary << "--" << CRLF;
01337 }
01338
01339 }
01340