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 18798 2008-05-31 02:26:22Z pwest $"
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
00059 #include <GetOpt.h>
00060
00061 #include "DAS.h"
00062 #include "DDS.h"
00063 #include "debug.h"
00064 #include "cgi_util.h"
00065 #include "Ancillary.h"
00066 #include "util.h"
00067 #include "escaping.h"
00068 #include "DODSFilter.h"
00069 #include "XDRFileMarshaller.h"
00070 #include "XDRStreamMarshaller.h"
00071 #include "InternalErr.h"
00072 #ifndef WIN32
00073 #include "SignalHandler.h"
00074 #include "EventHandler.h"
00075 #include "AlarmHandler.h"
00076 #endif
00077
00078 using namespace std;
00079
00080 namespace libdap {
00081
00082 const string usage =
00083 "Usage: <handler name> -o <response> -u <url> [options ...] [data set]\n\
00084 \n\
00085 options: -o <response>: DAS, DDS, DataDDS, DDX, BLOB or Version (Required)\n\
00086 -u <url>: The complete URL minus the CE (required for DDX)\n\
00087 -c: Compress the response using the deflate algorithm.\n\
00088 -e <expr>: When returning a DataDDS, use <expr> as the constraint.\n\
00089 -v <version>: Use <version> as the version number\n\
00090 -d <dir>: Look for ancillary file in <dir> (deprecated).\n\
00091 -f <file>: Look for ancillary data in <file> (deprecated).\n\
00092 -r <dir>: Use <dir> as a cache directory\n\
00093 -l <time>: Conditional request; if data source is unchanged since\n\
00094 <time>, return an HTTP 304 response.\n\
00095 -t <seconds>: Timeout the handler after <seconds>.\n\
00096 -h: This message.";
00097
00098 #if 0
00099
00100
00101
00102 #ifdef WIN32
00103 #define WAITPID(pid) while(_cwait(NULL, pid, NULL) > 0)
00104 #else
00105 #define WAITPID(pid) while(waitpid(pid, 0, 0) > 0)
00106 #endif
00107 #endif
00108
00173 DODSFilter::DODSFilter(int argc, char *argv[]) throw(Error)
00174 {
00175 initialize(argc, argv);
00176
00177 DBG(cerr << "d_comp: " << d_comp << endl);
00178 DBG(cerr << "d_ce: " << d_ce << endl);
00179 DBG(cerr << "d_cgi_ver: " << d_cgi_ver << endl);
00180 DBG(cerr << "d_response: " << d_response << endl);
00181 DBG(cerr << "d_anc_dir: " << d_anc_dir << endl);
00182 DBG(cerr << "d_anc_file: " << d_anc_file << endl);
00183 DBG(cerr << "d_cache_dir: " << d_cache_dir << endl);
00184 DBG(cerr << "d_conditional_request: " << d_conditional_request << endl);
00185 DBG(cerr << "d_if_modified_since: " << d_if_modified_since << endl);
00186 DBG(cerr << "d_url: " << d_url << endl);
00187 DBG(cerr << "d_timeout: " << d_timeout << endl);
00188 }
00189
00190 DODSFilter::~DODSFilter()
00191 {
00192 }
00193
00196 void
00197 DODSFilter::initialize()
00198 {
00199
00200
00201 d_comp = false;
00202 d_bad_options = false;
00203 d_conditional_request = false;
00204 d_dataset = "";
00205 d_ce = "";
00206 d_cgi_ver = "";
00207 d_anc_dir = "";
00208 d_anc_file = "";
00209 d_cache_dir = "";
00210 d_response = Unknown_Response;;
00211 d_anc_das_lmt = 0;
00212 d_anc_dds_lmt = 0;
00213 d_if_modified_since = -1;
00214 d_url = "";
00215 d_program_name = "Unknown";
00216 d_timeout = 0;
00217
00218 #ifdef WIN32
00219
00220
00221
00222 _setmode(_fileno(stdout), _O_BINARY);
00223 #endif
00224 }
00225
00237 void
00238 DODSFilter::initialize(int argc, char *argv[])
00239 {
00240 initialize();
00241
00242 d_program_name = argv[0];
00243
00244
00245 int next_arg = process_options(argc, argv);
00246
00247
00248
00249
00250 if (next_arg < argc) {
00251 d_dataset = argv[next_arg];
00252 d_dataset = www2id(d_dataset, "%", "%20");
00253 }
00254 else if (get_response() != Version_Response)
00255 print_usage();
00256 }
00257
00266 int
00267 DODSFilter::process_options(int argc, char *argv[])
00268 {
00269 DBG(cerr << "Entering process_options... ");
00270
00271 int option_char;
00272 GetOpt getopt (argc, argv, "ce: v: d: f: r: l: o: u: t: ");
00273
00274 while ((option_char = getopt()) != EOF) {
00275 switch (option_char) {
00276 case 'c': d_comp = true; break;
00277 case 'e': set_ce(getopt.optarg); break;
00278 case 'v': set_cgi_version(getopt.optarg); break;
00279 case 'd': d_anc_dir = getopt.optarg; break;
00280 case 'f': d_anc_file = getopt.optarg; break;
00281 case 'r': d_cache_dir = getopt.optarg; break;
00282 case 'o': set_response(getopt.optarg); break;
00283 case 'u': set_URL(getopt.optarg); break;
00284 case 't': d_timeout = atoi(getopt.optarg); break;
00285 case 'l':
00286 d_conditional_request = true;
00287 d_if_modified_since
00288 = static_cast<time_t>(strtol(getopt.optarg, NULL, 10));
00289 break;
00290 case 'h': print_usage(); exit(1);
00291 default: print_usage();
00292 }
00293 }
00294
00295 DBGN(cerr << "exiting." << endl);
00296
00297 return getopt.optind;
00298 }
00299
00304 bool
00305 DODSFilter::is_conditional() const
00306 {
00307 return d_conditional_request;
00308 }
00309
00323 void
00324 DODSFilter::set_cgi_version(string version)
00325 {
00326 d_cgi_ver = version;
00327 }
00328
00334 string
00335 DODSFilter::get_cgi_version() const
00336 {
00337 return d_cgi_ver;
00338 }
00339
00346 string
00347 DODSFilter::get_ce() const
00348 {
00349 return d_ce;
00350 }
00351
00352 void
00353 DODSFilter::set_ce(string _ce)
00354 {
00355 d_ce = www2id(_ce, "%", "%20");
00356 }
00357
00366 string
00367 DODSFilter::get_dataset_name() const
00368 {
00369 return d_dataset;
00370 }
00371
00372 void
00373 DODSFilter::set_dataset_name(const string ds)
00374 {
00375 d_dataset = www2id(ds, "%", "%20");
00376 }
00377
00381 string
00382 DODSFilter::get_URL() const
00383 {
00384 return d_url;
00385 }
00386
00389 void
00390 DODSFilter::set_URL(const string &url)
00391 {
00392 if (url.find('?') != url.npos)
00393 print_usage();
00394
00395 d_url = url;
00396 }
00397
00405 string
00406 DODSFilter::get_dataset_version() const
00407 {
00408 return "";
00409 }
00410
00417 void DODSFilter::set_response(const string &r)
00418 {
00419 if (r == "DAS" || r == "das") {
00420 d_response = DAS_Response;
00421 d_action = "das" ;
00422 }
00423 else if (r == "DDS" || r == "dds") {
00424 d_response = DDS_Response;
00425 d_action = "dds" ;
00426 }
00427 else if (r == "DataDDS" || r == "dods") {
00428 d_response = DataDDS_Response;
00429 d_action = "dods" ;
00430 }
00431 else if (r == "DDX" || r == "ddx") {
00432 d_response = DDX_Response;
00433 d_action = "ddx" ;
00434 }
00435 else if (r == "Version") {
00436 d_response = Version_Response;
00437 d_action = "version" ;
00438 }
00439 else
00440 print_usage();
00441 }
00442
00444 DODSFilter::Response
00445 DODSFilter::get_response() const
00446 {
00447 return d_response;
00448 }
00449
00451 string DODSFilter::get_action() const
00452 {
00453 return d_action;
00454 }
00455
00476 time_t
00477 DODSFilter::get_dataset_last_modified_time() const
00478 {
00479 return last_modified_time(d_dataset);
00480 }
00481
00491 time_t
00492 DODSFilter::get_das_last_modified_time(const string &anc_location) const
00493 {
00494 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location="
00495 << anc_location << "call faf(das) d_dataset=" << d_dataset
00496 << " d_anc_file=" << d_anc_file << endl);
00497
00498 string name
00499 = Ancillary::find_ancillary_file(d_dataset, "das",
00500 (anc_location == "") ? d_anc_dir : anc_location,
00501 d_anc_file);
00502
00503 return max((name != "") ? last_modified_time(name) : 0,
00504 get_dataset_last_modified_time());
00505 }
00506
00514 time_t
00515 DODSFilter::get_dds_last_modified_time(const string &anc_location) const
00516 {
00517 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location="
00518 << anc_location << "call faf(dds) d_dataset=" << d_dataset
00519 << " d_anc_file=" << d_anc_file << endl);
00520
00521 string name
00522 = Ancillary::find_ancillary_file(d_dataset, "dds",
00523 (anc_location == "") ? d_anc_dir : anc_location,
00524 d_anc_file);
00525
00526 return max((name != "") ? last_modified_time(name) : 0,
00527 get_dataset_last_modified_time());
00528 }
00529
00543 time_t
00544 DODSFilter::get_data_last_modified_time(const string &anc_location) const
00545 {
00546 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location="
00547 << anc_location << "call faf(both) d_dataset=" << d_dataset
00548 << " d_anc_file=" << d_anc_file << endl);
00549
00550 string dds_name
00551 = Ancillary::find_ancillary_file(d_dataset, "dds",
00552 (anc_location == "") ? d_anc_dir : anc_location,
00553 d_anc_file);
00554 string das_name
00555 = Ancillary::find_ancillary_file(d_dataset, "das",
00556 (anc_location == "") ? d_anc_dir : anc_location,
00557 d_anc_file);
00558
00559 time_t m = max((das_name != "") ? last_modified_time(das_name) : (time_t)0,
00560 (dds_name != "") ? last_modified_time(dds_name) : (time_t)0);
00561
00562 time_t n = get_dataset_last_modified_time();
00563
00564 return max(m, n);
00565 }
00566
00574 time_t
00575 DODSFilter::get_request_if_modified_since() const
00576 {
00577 return d_if_modified_since;
00578 }
00579
00586 string
00587 DODSFilter::get_cache_dir() const
00588 {
00589 return d_cache_dir;
00590 }
00591
00596 void
00597 DODSFilter::set_timeout(int t)
00598 {
00599 d_timeout = t;
00600 }
00601
00603 int
00604 DODSFilter::get_timeout() const
00605 {
00606 return d_timeout;
00607 }
00608
00620 void
00621 DODSFilter::establish_timeout(FILE *stream) const
00622 {
00623 #ifndef WIN32
00624 if (d_timeout > 0) {
00625 SignalHandler *sh = SignalHandler::instance();
00626 EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler(stream));
00627 delete old_eh;
00628 alarm(d_timeout);
00629 }
00630 #endif
00631 }
00632
00633
00634 void
00635 DODSFilter::establish_timeout(ostream &stream) const
00636 {
00637 #ifndef WIN32
00638 if (d_timeout > 0) {
00639 SignalHandler *sh = SignalHandler::instance();
00640 EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler(stream));
00641 delete old_eh;
00642 alarm(d_timeout);
00643 }
00644 #endif
00645 }
00646
00647
00657 void
00658 DODSFilter::read_ancillary_das(DAS &das, const string &anc_location) const
00659 {
00660 Ancillary::read_ancillary_das( das, d_dataset,
00661 (anc_location == "") ? d_anc_dir : anc_location,
00662 d_anc_file);
00663 }
00664
00674 void
00675 DODSFilter::read_ancillary_dds(DDS &dds, const string &anc_location) const
00676 {
00677 Ancillary::read_ancillary_dds( dds, d_dataset,
00678 (anc_location == "") ? d_anc_dir : anc_location,
00679 d_anc_file);
00680 }
00681
00682 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.";
00683
00693 void
00694 DODSFilter::print_usage() const
00695 {
00696
00697 ErrMsgT(usage.c_str());
00698
00699 throw Error(unknown_error, emessage);
00700 }
00701
00707 void
00708 DODSFilter::send_version_info() const
00709 {
00710 do_version(d_cgi_ver, get_dataset_version());
00711 }
00712
00724 void
00725 DODSFilter::send_das(FILE *out, DAS &das, const string &anc_location,
00726 bool with_mime_headers) const
00727 {
00728 time_t das_lmt = get_das_last_modified_time(anc_location);
00729 if (is_conditional()
00730 && das_lmt <= get_request_if_modified_since()
00731 && with_mime_headers) {
00732 set_mime_not_modified(out);
00733 }
00734 else {
00735 if (with_mime_headers)
00736 set_mime_text(out, dods_das, d_cgi_ver, x_plain, das_lmt);
00737 das.print(out);
00738 }
00739 fflush(out) ;
00740 }
00741
00753 void
00754 DODSFilter::send_das(ostream &out, DAS &das, const string &anc_location,
00755 bool with_mime_headers) const
00756 {
00757 time_t das_lmt = get_das_last_modified_time(anc_location);
00758 if (is_conditional()
00759 && das_lmt <= get_request_if_modified_since()
00760 && with_mime_headers) {
00761 set_mime_not_modified(out);
00762 }
00763 else {
00764 if (with_mime_headers)
00765 set_mime_text(out, dods_das, d_cgi_ver, x_plain, das_lmt);
00766 das.print(out);
00767 }
00768 out << flush ;
00769 }
00770
00771 void
00772 DODSFilter::send_das(DAS &das, const string &anc_location,
00773 bool with_mime_headers) const
00774 {
00775 send_das(stdout, das, anc_location, with_mime_headers);
00776 }
00777
00794 void
00795 DODSFilter::send_dds(FILE *out, DDS &dds, ConstraintEvaluator &eval,
00796 bool constrained,
00797 const string &anc_location,
00798 bool with_mime_headers) const
00799 {
00800
00801 if (constrained)
00802 eval.parse_constraint(d_ce, dds);
00803
00804 if (eval.functional_expression())
00805 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.");
00806
00807 time_t dds_lmt = get_dds_last_modified_time(anc_location);
00808 if (is_conditional()
00809 && dds_lmt <= get_request_if_modified_since()
00810 && with_mime_headers) {
00811 set_mime_not_modified(out);
00812 }
00813 else {
00814 if (with_mime_headers)
00815 set_mime_text(out, dods_dds, d_cgi_ver, x_plain, dds_lmt);
00816 if (constrained)
00817 dds.print_constrained(out);
00818 else
00819 dds.print(out);
00820 }
00821
00822 fflush(out) ;
00823 }
00824
00841 void
00842 DODSFilter::send_dds(ostream &out, DDS &dds, ConstraintEvaluator &eval,
00843 bool constrained,
00844 const string &anc_location,
00845 bool with_mime_headers) const
00846 {
00847
00848 if (constrained)
00849 eval.parse_constraint(d_ce, dds);
00850
00851 if (eval.functional_expression())
00852 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.");
00853
00854 time_t dds_lmt = get_dds_last_modified_time(anc_location);
00855 if (is_conditional()
00856 && dds_lmt <= get_request_if_modified_since()
00857 && with_mime_headers) {
00858 set_mime_not_modified(out);
00859 }
00860 else {
00861 if (with_mime_headers)
00862 set_mime_text(out, dods_dds, d_cgi_ver, x_plain, dds_lmt);
00863 if (constrained)
00864 dds.print_constrained(out);
00865 else
00866 dds.print(out);
00867 }
00868
00869 out << flush ;
00870 }
00871
00872 void
00873 DODSFilter::send_dds(DDS &dds, ConstraintEvaluator &eval,
00874 bool constrained, const string &anc_location,
00875 bool with_mime_headers) const
00876 {
00877 send_dds(stdout, dds, eval, constrained, anc_location, with_mime_headers);
00878 }
00879
00880
00881
00882 void
00883 DODSFilter::functional_constraint(BaseType &var, DDS &dds,
00884 ConstraintEvaluator &eval, FILE *out) const
00885 {
00886 fprintf(out, "Dataset {\n");
00887 var.print_decl(out, " ", true, false, true);
00888 fprintf(out, "} function_value;\n");
00889 fprintf(out, "Data:\n");
00890
00891 fflush(out);
00892
00893
00894 XDRFileMarshaller m( out ) ;
00895
00896 try {
00897
00898 var.serialize(d_dataset, eval, dds, m, false);
00899 }
00900 catch (Error &e) {
00901 throw;
00902 }
00903 }
00904
00905
00906
00907 void
00908 DODSFilter::functional_constraint(BaseType &var, DDS &dds,
00909 ConstraintEvaluator &eval, ostream &out) const
00910 {
00911 out << "Dataset {\n" ;
00912 var.print_decl(out, " ", true, false, true);
00913 out << "} function_value;\n" ;
00914 out << "Data:\n" ;
00915
00916 out << flush ;
00917
00918
00919 XDRStreamMarshaller m( out ) ;
00920
00921 try {
00922
00923 var.serialize(d_dataset, eval, dds, m, false);
00924 }
00925 catch (Error &e) {
00926 throw;
00927 }
00928 }
00929
00930 void
00931 DODSFilter::dataset_constraint(DDS & dds, ConstraintEvaluator & eval,
00932 FILE * out) const
00933 {
00934
00935 dds.print_constrained(out);
00936 fprintf(out, "Data:\n");
00937 fflush(out);
00938
00939
00940 XDRFileMarshaller m( out ) ;
00941
00942 try {
00943
00944 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
00945 if ((*i)->send_p()) {
00946 DBG(cerr << "Sending " << (*i)->name() << endl);
00947 (*i)->serialize(d_dataset, eval, dds, m, true);
00948 }
00949 }
00950 catch (Error & e) {
00951 throw;
00952 }
00953 }
00954
00955 void
00956 DODSFilter::dataset_constraint(DDS & dds, ConstraintEvaluator & eval,
00957 ostream &out) const
00958 {
00959
00960 dds.print_constrained(out);
00961 out << "Data:\n" ;
00962 out << flush ;
00963
00964
00965 XDRStreamMarshaller m( out ) ;
00966
00967 try {
00968
00969 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
00970 if ((*i)->send_p()) {
00971 DBG(cerr << "Sending " << (*i)->name() << endl);
00972 (*i)->serialize(d_dataset, eval, dds, m, true);
00973 }
00974 }
00975 catch (Error & e) {
00976 throw;
00977 }
00978 }
00979
00996 void
00997 DODSFilter::send_data(DDS & dds, ConstraintEvaluator & eval,
00998 FILE * data_stream, const string & anc_location,
00999 bool with_mime_headers) const
01000 {
01001
01002
01003
01004 time_t data_lmt = get_data_last_modified_time(anc_location);
01005 if (is_conditional()
01006 && data_lmt <= get_request_if_modified_since()
01007 && with_mime_headers) {
01008 set_mime_not_modified(data_stream);
01009 return;
01010 }
01011
01012 establish_timeout(data_stream);
01013 dds.set_timeout(d_timeout);
01014
01015 eval.parse_constraint(d_ce, dds);
01016
01017
01018 dds.tag_nested_sequences();
01019
01020
01021 #if COMPRESSION_FOR_SERVER3
01022 bool compress = d_comp && deflate_exists();
01023 #endif
01024
01025
01026 if (eval.functional_expression()) {
01027
01028
01029
01030
01031 BaseType *var = eval.eval_function(dds, d_dataset);
01032 if (!var)
01033 throw Error(unknown_error, "Error calling the CE function.");
01034
01035 #if COMPRESSION_FOR_SERVER3
01036 if (with_mime_headers)
01037 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01038 (compress) ? deflate : x_plain, data_lmt);
01039 fflush(data_stream);
01040
01041 int childpid;
01042 if (compress)
01043 data_stream = compressor(data_stream, childpid);
01044 #endif
01045 if (with_mime_headers)
01046 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01047
01048 fflush(data_stream);
01049
01050 functional_constraint(*var, dds, eval, data_stream);
01051 delete var;
01052 var = 0;
01053 }
01054 else {
01055 #if COMPRESSION_FOR_SERVER3
01056 if (with_mime_headers)
01057 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01058 (compress) ? deflate : x_plain, data_lmt);
01059 fflush(data_stream);
01060
01061 int childpid;
01062 if (compress)
01063 data_stream = compressor(data_stream, childpid);
01064 #endif
01065 if (with_mime_headers)
01066 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01067
01068 dataset_constraint(dds, eval, data_stream);
01069 }
01070
01071 fflush(data_stream);
01072 }
01073
01090 void
01091 DODSFilter::send_data(DDS & dds, ConstraintEvaluator & eval,
01092 ostream & data_stream, const string & anc_location,
01093 bool with_mime_headers) const
01094 {
01095
01096
01097
01098 time_t data_lmt = get_data_last_modified_time(anc_location);
01099 if (is_conditional()
01100 && data_lmt <= get_request_if_modified_since()
01101 && with_mime_headers) {
01102 set_mime_not_modified(data_stream);
01103 return;
01104 }
01105
01106 establish_timeout(data_stream);
01107 dds.set_timeout(d_timeout);
01108
01109 eval.parse_constraint(d_ce, dds);
01110
01111
01112 dds.tag_nested_sequences();
01113
01114
01115 #if COMPRESSION_FOR_SERVER3
01116 bool compress = d_comp && deflate_exists();
01117 #endif
01118
01119
01120 if (eval.functional_expression()) {
01121
01122
01123
01124
01125 BaseType *var = eval.eval_function(dds, d_dataset);
01126 if (!var)
01127 throw Error(unknown_error, "Error calling the CE function.");
01128
01129 #if COMPRESSION_FOR_SERVER3
01130 if (with_mime_headers)
01131 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01132 (compress) ? deflate : x_plain, data_lmt);
01133 data_stream << flush ;
01134
01135 int childpid;
01136 if (compress)
01137 data_stream = compressor(data_stream, childpid);
01138 #endif
01139 if (with_mime_headers)
01140 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01141
01142 data_stream << flush ;
01143
01144 functional_constraint(*var, dds, eval, data_stream);
01145 delete var;
01146 var = 0;
01147 }
01148 else {
01149 #if COMPRESSION_FOR_SERVER3
01150 if (with_mime_headers)
01151 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01152 (compress) ? deflate : x_plain, data_lmt);
01153 data_stream << flush ;
01154
01155 int childpid;
01156 if (compress)
01157 data_stream = compressor(data_stream, childpid);
01158 #endif
01159 if (with_mime_headers)
01160 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01161
01162 dataset_constraint(dds, eval, data_stream);
01163 }
01164
01165 data_stream << flush ;
01166 }
01167
01178 void
01179 DODSFilter::send_ddx(DDS &dds, ConstraintEvaluator &eval, FILE *out,
01180 bool with_mime_headers) const
01181 {
01182
01183 if (!d_ce.empty())
01184 eval.parse_constraint(d_ce, dds);
01185
01186 if (eval.functional_expression())
01187 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.");
01188
01189 time_t dds_lmt = get_dds_last_modified_time(d_anc_dir);
01190
01191
01192
01193
01194 if (is_conditional() && dds_lmt <= get_request_if_modified_since()
01195 && with_mime_headers) {
01196 set_mime_not_modified(out);
01197 return;
01198 }
01199 else {
01200 if (with_mime_headers)
01201 set_mime_text(out, dap4_ddx, d_cgi_ver, x_plain, dds_lmt);
01202 dds.print_xml(out, !d_ce.empty(), d_url + ".blob?" + d_ce);
01203 }
01204 }
01205
01216 void
01217 DODSFilter::send_ddx(DDS &dds, ConstraintEvaluator &eval, ostream &out,
01218 bool with_mime_headers) const
01219 {
01220
01221 if (!d_ce.empty())
01222 eval.parse_constraint(d_ce, dds);
01223
01224 if (eval.functional_expression())
01225 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.");
01226
01227 time_t dds_lmt = get_dds_last_modified_time(d_anc_dir);
01228
01229
01230
01231
01232 if (is_conditional() && dds_lmt <= get_request_if_modified_since()
01233 && with_mime_headers) {
01234 set_mime_not_modified(out);
01235 return;
01236 }
01237 else {
01238 if (with_mime_headers)
01239 set_mime_text(out, dap4_ddx, d_cgi_ver, x_plain, dds_lmt);
01240 dds.print_xml(out, !d_ce.empty(), d_url + ".blob?" + d_ce);
01241 }
01242 }
01243
01248 void
01249 DODSFilter::send_blob(DDS &, FILE *, bool)
01250 {
01251 #if 0
01252
01253 bool compress = d_comp && deflate_exists();
01254 time_t data_lmt = get_data_last_modified_time(d_anc_dir);
01255
01256
01257
01258
01259 if (is_conditional() && data_lmt <= get_request_if_modified_since()
01260 && with_mime_headers) {
01261 set_mime_not_modified(out);
01262 return;
01263 }
01264
01265 dds.parse_constraint(d_ce);
01266
01267
01268 if (dds.functional_expression()) {
01269 BaseType *var = dds.eval_function(d_dataset);
01270 if (!var)
01271 throw Error("Error calling the CE function.");
01272
01273 if (with_mime_headers)
01274 set_mime_binary(out, dods_data, d_cgi_ver,
01275 (compress) ? deflate : x_plain, data_lmt);
01276
01277 FILE *comp_sink;
01278 XDR *xdr_sink;
01279 int childpid = get_sinks(out, compress, &comp_sink, &xdr_sink);
01280
01281
01282 if (!var->serialize(d_dataset, dds, xdr_sink, false))
01283 throw Error("Could not send the function result.");
01284
01285 clean_sinks(childpid, compress, xdr_sink, comp_sink);
01286 }
01287 else {
01288 if (with_mime_headers)
01289 set_mime_binary(out, dods_data, d_cgi_ver,
01290 (compress) ? deflate : x_plain, data_lmt);
01291
01292 FILE *comp_sink;
01293 XDR *xdr_sink;
01294 int childpid = get_sinks(out, compress, &comp_sink, &xdr_sink);
01295
01296 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
01297 if ((*i)->send_p())
01298 if (!(*i)->serialize(d_dataset, dds, xdr_sink, true))
01299 throw Error(string("Could not serialize variable '")
01300 + (*i)->name() + string("'."));
01301
01302 clean_sinks(childpid, compress, xdr_sink, comp_sink);
01303 }
01304 #endif
01305 }
01306
01307 }
01308