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 19948 2008-12-03 23:51:12Z 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
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
00609
00621 void
00622 DODSFilter::establish_timeout(FILE *stream) const
00623 {
00624 #ifndef WIN32
00625 if (d_timeout > 0) {
00626 SignalHandler *sh = SignalHandler::instance();
00627 EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler(stream));
00628 delete old_eh;
00629 alarm(d_timeout);
00630 }
00631 #endif
00632 }
00633
00634
00635
00636 void
00637 DODSFilter::establish_timeout(ostream &stream) const
00638 {
00639 #ifndef WIN32
00640 if (d_timeout > 0) {
00641 SignalHandler *sh = SignalHandler::instance();
00642 EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler(stream));
00643 delete old_eh;
00644 alarm(d_timeout);
00645 }
00646 #endif
00647 }
00648
00649
00659 void
00660 DODSFilter::read_ancillary_das(DAS &das, const string &anc_location) const
00661 {
00662 Ancillary::read_ancillary_das( das, d_dataset,
00663 (anc_location == "") ? d_anc_dir : anc_location,
00664 d_anc_file);
00665 }
00666
00676 void
00677 DODSFilter::read_ancillary_dds(DDS &dds, const string &anc_location) const
00678 {
00679 Ancillary::read_ancillary_dds( dds, d_dataset,
00680 (anc_location == "") ? d_anc_dir : anc_location,
00681 d_anc_file);
00682 }
00683
00684 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.";
00685
00695 void
00696 DODSFilter::print_usage() const
00697 {
00698
00699 ErrMsgT(usage.c_str());
00700
00701 throw Error(unknown_error, emessage);
00702 }
00703
00709 void
00710 DODSFilter::send_version_info() const
00711 {
00712 do_version(d_cgi_ver, get_dataset_version());
00713 }
00714
00715
00727 void
00728 DODSFilter::send_das(FILE *out, DAS &das, const string &anc_location,
00729 bool with_mime_headers) const
00730 {
00731 time_t das_lmt = get_das_last_modified_time(anc_location);
00732 if (is_conditional()
00733 && das_lmt <= get_request_if_modified_since()
00734 && with_mime_headers) {
00735 set_mime_not_modified(out);
00736 }
00737 else {
00738 if (with_mime_headers)
00739 set_mime_text(out, dods_das, d_cgi_ver, x_plain, das_lmt);
00740 das.print(out);
00741 }
00742 fflush(out) ;
00743 }
00744
00756 void
00757 DODSFilter::send_das(ostream &out, DAS &das, const string &anc_location,
00758 bool with_mime_headers) const
00759 {
00760 time_t das_lmt = get_das_last_modified_time(anc_location);
00761 if (is_conditional()
00762 && das_lmt <= get_request_if_modified_since()
00763 && with_mime_headers) {
00764 set_mime_not_modified(out);
00765 }
00766 else {
00767 if (with_mime_headers)
00768 set_mime_text(out, dods_das, d_cgi_ver, x_plain, das_lmt);
00769 das.print(out);
00770 }
00771 out << flush ;
00772 }
00773
00774 void
00775 DODSFilter::send_das(DAS &das, const string &anc_location,
00776 bool with_mime_headers) const
00777 {
00778 send_das(cout, das, anc_location, with_mime_headers);
00779 }
00780
00781
00798 void
00799 DODSFilter::send_dds(FILE *out, DDS &dds, ConstraintEvaluator &eval,
00800 bool constrained,
00801 const string &anc_location,
00802 bool with_mime_headers) const
00803 {
00804
00805 if (constrained)
00806 eval.parse_constraint(d_ce, dds);
00807
00808 if (eval.functional_expression())
00809 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.");
00810
00811 time_t dds_lmt = get_dds_last_modified_time(anc_location);
00812 if (is_conditional()
00813 && dds_lmt <= get_request_if_modified_since()
00814 && with_mime_headers) {
00815 set_mime_not_modified(out);
00816 }
00817 else {
00818 if (with_mime_headers)
00819 set_mime_text(out, dods_dds, d_cgi_ver, x_plain, dds_lmt);
00820 if (constrained)
00821 dds.print_constrained(out);
00822 else
00823 dds.print(out);
00824 }
00825
00826 fflush(out) ;
00827 }
00828
00845 void
00846 DODSFilter::send_dds(ostream &out, DDS &dds, ConstraintEvaluator &eval,
00847 bool constrained,
00848 const string &anc_location,
00849 bool with_mime_headers) const
00850 {
00851
00852 if (constrained)
00853 eval.parse_constraint(d_ce, dds);
00854
00855 if (eval.functional_expression())
00856 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.");
00857
00858 time_t dds_lmt = get_dds_last_modified_time(anc_location);
00859 if (is_conditional()
00860 && dds_lmt <= get_request_if_modified_since()
00861 && with_mime_headers) {
00862 set_mime_not_modified(out);
00863 }
00864 else {
00865 if (with_mime_headers)
00866 set_mime_text(out, dods_dds, d_cgi_ver, x_plain, dds_lmt);
00867 if (constrained)
00868 dds.print_constrained(out);
00869 else
00870 dds.print(out);
00871 }
00872
00873 out << flush ;
00874 }
00875
00876 void
00877 DODSFilter::send_dds(DDS &dds, ConstraintEvaluator &eval,
00878 bool constrained, const string &anc_location,
00879 bool with_mime_headers) const
00880 {
00881 send_dds(cout, dds, eval, constrained, anc_location, with_mime_headers);
00882 }
00883
00884
00885
00886
00887 void
00888 DODSFilter::functional_constraint(BaseType &var, DDS &dds,
00889 ConstraintEvaluator &eval, FILE *out) const
00890 {
00891 fprintf(out, "Dataset {\n");
00892 var.print_decl(out, " ", true, false, true);
00893 fprintf(out, "} function_value;\n");
00894 fprintf(out, "Data:\n");
00895
00896 fflush(out);
00897
00898
00899 XDRFileMarshaller m( out ) ;
00900
00901 try {
00902
00903 var.serialize(eval, dds, m, false);
00904 }
00905 catch (Error &e) {
00906 throw;
00907 }
00908 }
00909
00910
00911
00912 void
00913 DODSFilter::functional_constraint(BaseType &var, DDS &dds,
00914 ConstraintEvaluator &eval, ostream &out) const
00915 {
00916 out << "Dataset {\n" ;
00917 var.print_decl(out, " ", true, false, true);
00918 out << "} function_value;\n" ;
00919 out << "Data:\n" ;
00920
00921 out << flush ;
00922
00923
00924 XDRStreamMarshaller m( out ) ;
00925
00926 try {
00927
00928 var.serialize(eval, dds, m, false);
00929 }
00930 catch (Error &e) {
00931 throw;
00932 }
00933 }
00934
00935 void
00936 DODSFilter::dataset_constraint(DDS & dds, ConstraintEvaluator & eval,
00937 FILE * out) const
00938 {
00939
00940 dds.print_constrained(out);
00941 fprintf(out, "Data:\n");
00942 fflush(out);
00943
00944
00945 XDRFileMarshaller m( out ) ;
00946
00947 try {
00948
00949 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
00950 if ((*i)->send_p()) {
00951 DBG(cerr << "Sending " << (*i)->name() << endl);
00952 (*i)->serialize(eval, dds, m, true);
00953 }
00954 }
00955 catch (Error & e) {
00956 throw;
00957 }
00958 }
00959
00960
00961 void
00962 DODSFilter::dataset_constraint(DDS & dds, ConstraintEvaluator & eval,
00963 ostream &out) const
00964 {
00965
00966 dds.print_constrained(out);
00967 out << "Data:\n" ;
00968 out << flush ;
00969
00970
00971 XDRStreamMarshaller m( out ) ;
00972
00973 try {
00974
00975 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
00976 if ((*i)->send_p()) {
00977 DBG(cerr << "Sending " << (*i)->name() << endl);
00978 (*i)->serialize(eval, dds, m, true);
00979 }
00980 }
00981 catch (Error & e) {
00982 throw;
00983 }
00984 }
00985
01002 void
01003 DODSFilter::send_data(DDS & dds, ConstraintEvaluator & eval,
01004 FILE * data_stream, const string & anc_location,
01005 bool with_mime_headers) const
01006 {
01007
01008
01009
01010 time_t data_lmt = get_data_last_modified_time(anc_location);
01011 if (is_conditional()
01012 && data_lmt <= get_request_if_modified_since()
01013 && with_mime_headers) {
01014 set_mime_not_modified(data_stream);
01015 return;
01016 }
01017
01018 establish_timeout(data_stream);
01019 dds.set_timeout(d_timeout);
01020
01021 eval.parse_constraint(d_ce, dds);
01022
01023
01024 dds.tag_nested_sequences();
01025
01026
01027 #if COMPRESSION_FOR_SERVER3
01028 bool compress = d_comp && deflate_exists();
01029 #endif
01030
01031
01032 if (eval.functional_expression()) {
01033
01034
01035
01036
01037 BaseType *var = eval.eval_function(dds, d_dataset);
01038 if (!var)
01039 throw Error(unknown_error, "Error calling the CE function.");
01040
01041 #if COMPRESSION_FOR_SERVER3
01042 if (with_mime_headers)
01043 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01044 (compress) ? deflate : x_plain, data_lmt);
01045 fflush(data_stream);
01046
01047 int childpid;
01048 if (compress)
01049 data_stream = compressor(data_stream, childpid);
01050 #endif
01051 if (with_mime_headers)
01052 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01053
01054 fflush(data_stream);
01055
01056 functional_constraint(*var, dds, eval, data_stream);
01057 delete var;
01058 var = 0;
01059 }
01060 else {
01061 #if COMPRESSION_FOR_SERVER3
01062 if (with_mime_headers)
01063 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01064 (compress) ? deflate : x_plain, data_lmt);
01065 fflush(data_stream);
01066
01067 int childpid;
01068 if (compress)
01069 data_stream = compressor(data_stream, childpid);
01070 #endif
01071 if (with_mime_headers)
01072 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01073
01074 dataset_constraint(dds, eval, data_stream);
01075 }
01076
01077 fflush(data_stream);
01078 }
01079
01096 void
01097 DODSFilter::send_data(DDS & dds, ConstraintEvaluator & eval,
01098 ostream & data_stream, const string & anc_location,
01099 bool with_mime_headers) const
01100 {
01101
01102
01103
01104 time_t data_lmt = get_data_last_modified_time(anc_location);
01105 if (is_conditional()
01106 && data_lmt <= get_request_if_modified_since()
01107 && with_mime_headers) {
01108 set_mime_not_modified(data_stream);
01109 return;
01110 }
01111
01112 establish_timeout(data_stream);
01113 dds.set_timeout(d_timeout);
01114
01115 eval.parse_constraint(d_ce, dds);
01116
01117
01118 dds.tag_nested_sequences();
01119
01120
01121 #if COMPRESSION_FOR_SERVER3
01122 bool compress = d_comp && deflate_exists();
01123 #endif
01124
01125
01126 if (eval.functional_expression()) {
01127
01128
01129
01130
01131 BaseType *var = eval.eval_function(dds, d_dataset);
01132 if (!var)
01133 throw Error(unknown_error, "Error calling the CE function.");
01134
01135 #if COMPRESSION_FOR_SERVER3
01136 if (with_mime_headers)
01137 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01138 (compress) ? deflate : x_plain, data_lmt);
01139 data_stream << flush ;
01140
01141 int childpid;
01142 if (compress)
01143 data_stream = compressor(data_stream, childpid);
01144 #endif
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 else {
01155 #if COMPRESSION_FOR_SERVER3
01156 if (with_mime_headers)
01157 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01158 (compress) ? deflate : x_plain, data_lmt);
01159 data_stream << flush ;
01160
01161 int childpid;
01162 if (compress)
01163 data_stream = compressor(data_stream, childpid);
01164 #endif
01165 if (with_mime_headers)
01166 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01167
01168 dataset_constraint(dds, eval, data_stream);
01169 }
01170
01171 data_stream << flush ;
01172 }
01173
01174
01185 void
01186 DODSFilter::send_ddx(DDS &dds, ConstraintEvaluator &eval, FILE *out,
01187 bool with_mime_headers) const
01188 {
01189
01190 if (!d_ce.empty())
01191 eval.parse_constraint(d_ce, dds);
01192
01193 if (eval.functional_expression())
01194 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.");
01195
01196 time_t dds_lmt = get_dds_last_modified_time(d_anc_dir);
01197
01198
01199
01200
01201 if (is_conditional() && dds_lmt <= get_request_if_modified_since()
01202 && with_mime_headers) {
01203 set_mime_not_modified(out);
01204 return;
01205 }
01206 else {
01207 if (with_mime_headers)
01208 set_mime_text(out, dap4_ddx, d_cgi_ver, x_plain, dds_lmt);
01209 dds.print_xml(out, !d_ce.empty(), d_url + ".blob?" + d_ce);
01210 }
01211 }
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(), d_url + ".blob?" + d_ce);
01248 }
01249 }
01250
01255 void
01256 DODSFilter::send_blob(DDS &, FILE *, bool)
01257 {
01258 #if 0
01259
01260 bool compress = d_comp && deflate_exists();
01261 time_t data_lmt = get_data_last_modified_time(d_anc_dir);
01262
01263
01264
01265
01266 if (is_conditional() && data_lmt <= get_request_if_modified_since()
01267 && with_mime_headers) {
01268 set_mime_not_modified(out);
01269 return;
01270 }
01271
01272 dds.parse_constraint(d_ce);
01273
01274
01275 if (dds.functional_expression()) {
01276 BaseType *var = dds.eval_function(d_dataset);
01277 if (!var)
01278 throw Error("Error calling the CE function.");
01279
01280 if (with_mime_headers)
01281 set_mime_binary(out, dods_data, d_cgi_ver,
01282 (compress) ? deflate : x_plain, data_lmt);
01283
01284 FILE *comp_sink;
01285 XDR *xdr_sink;
01286 int childpid = get_sinks(out, compress, &comp_sink, &xdr_sink);
01287
01288
01289 if (!var->serialize(d_dataset, dds, xdr_sink, false))
01290 throw Error("Could not send the function result.");
01291
01292 clean_sinks(childpid, compress, xdr_sink, comp_sink);
01293 }
01294 else {
01295 if (with_mime_headers)
01296 set_mime_binary(out, dods_data, d_cgi_ver,
01297 (compress) ? deflate : x_plain, data_lmt);
01298
01299 FILE *comp_sink;
01300 XDR *xdr_sink;
01301 int childpid = get_sinks(out, compress, &comp_sink, &xdr_sink);
01302
01303 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
01304 if ((*i)->send_p())
01305 if (!(*i)->serialize(d_dataset, dds, xdr_sink, true))
01306 throw Error(string("Could not serialize variable '")
01307 + (*i)->name() + string("'."));
01308
01309 clean_sinks(childpid, compress, xdr_sink, comp_sink);
01310 }
01311 #endif
01312 }
01313
01314 }
01315