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 18315 2008-03-03 20:14:44Z 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 "util.h"
00066 #include "escaping.h"
00067 #include "DODSFilter.h"
00068 #include "XDRFileMarshaller.h"
00069 #include "XDRStreamMarshaller.h"
00070 #include "InternalErr.h"
00071 #ifndef WIN32
00072 #include "SignalHandler.h"
00073 #include "EventHandler.h"
00074 #include "AlarmHandler.h"
00075 #endif
00076
00077 using namespace std;
00078
00079 namespace libdap {
00080
00081 const string usage =
00082 "Usage: <handler name> -o <response> -u <url> [options ...] [data set]\n\
00083 \n\
00084 options: -o <response>: DAS, DDS, DataDDS, DDX, BLOB or Version (Required)\n\
00085 -u <url>: The complete URL minus the CE (required for DDX)\n\
00086 -c: Compress the response using the deflate algorithm.\n\
00087 -e <expr>: When returning a DataDDS, use <expr> as the constraint.\n\
00088 -v <version>: Use <version> as the version number\n\
00089 -d <dir>: Look for ancillary file in <dir> (deprecated).\n\
00090 -f <file>: Look for ancillary data in <file> (deprecated).\n\
00091 -r <dir>: Use <dir> as a cache directory\n\
00092 -l <time>: Conditional request; if data source is unchanged since\n\
00093 <time>, return an HTTP 304 response.\n\
00094 -t <seconds>: Timeout the handler after <seconds>.\n\
00095 -h: This message.";
00096
00097 #if 0
00098
00099
00100
00101 #ifdef WIN32
00102 #define WAITPID(pid) while(_cwait(NULL, pid, NULL) > 0)
00103 #else
00104 #define WAITPID(pid) while(waitpid(pid, 0, 0) > 0)
00105 #endif
00106 #endif
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 == "Version") {
00435 d_response = Version_Response;
00436 d_action = "version" ;
00437 }
00438 else
00439 print_usage();
00440 }
00441
00443 DODSFilter::Response
00444 DODSFilter::get_response() const
00445 {
00446 return d_response;
00447 }
00448
00450 string DODSFilter::get_action() const
00451 {
00452 return d_action;
00453 }
00454
00475 time_t
00476 DODSFilter::get_dataset_last_modified_time() const
00477 {
00478 return last_modified_time(d_dataset);
00479 }
00480
00490 time_t
00491 DODSFilter::get_das_last_modified_time(const string &anc_location) const
00492 {
00493 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location="
00494 << anc_location << "call faf(das) d_dataset=" << d_dataset
00495 << " d_anc_file=" << d_anc_file << endl);
00496
00497 string name
00498 = find_ancillary_file(d_dataset, "das",
00499 (anc_location == "") ? d_anc_dir : anc_location,
00500 d_anc_file);
00501
00502 return max((name != "") ? last_modified_time(name) : 0,
00503 get_dataset_last_modified_time());
00504 }
00505
00513 time_t
00514 DODSFilter::get_dds_last_modified_time(const string &anc_location) const
00515 {
00516 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location="
00517 << anc_location << "call faf(dds) d_dataset=" << d_dataset
00518 << " d_anc_file=" << d_anc_file << endl);
00519
00520 string name
00521 = find_ancillary_file(d_dataset, "dds",
00522 (anc_location == "") ? d_anc_dir : anc_location,
00523 d_anc_file);
00524
00525 return max((name != "") ? last_modified_time(name) : 0,
00526 get_dataset_last_modified_time());
00527 }
00528
00542 time_t
00543 DODSFilter::get_data_last_modified_time(const string &anc_location) const
00544 {
00545 DBG(cerr << "DODSFilter::get_das_last_modified_time(anc_location="
00546 << anc_location << "call faf(both) d_dataset=" << d_dataset
00547 << " d_anc_file=" << d_anc_file << endl);
00548
00549 string dds_name
00550 = find_ancillary_file(d_dataset, "dds",
00551 (anc_location == "") ? d_anc_dir : anc_location,
00552 d_anc_file);
00553 string das_name
00554 = find_ancillary_file(d_dataset, "das",
00555 (anc_location == "") ? d_anc_dir : anc_location,
00556 d_anc_file);
00557
00558 time_t m = max((das_name != "") ? last_modified_time(das_name) : (time_t)0,
00559 (dds_name != "") ? last_modified_time(dds_name) : (time_t)0);
00560
00561 time_t n = get_dataset_last_modified_time();
00562
00563 return max(m, n);
00564 }
00565
00573 time_t
00574 DODSFilter::get_request_if_modified_since() const
00575 {
00576 return d_if_modified_since;
00577 }
00578
00585 string
00586 DODSFilter::get_cache_dir() const
00587 {
00588 return d_cache_dir;
00589 }
00590
00595 void
00596 DODSFilter::set_timeout(int t)
00597 {
00598 d_timeout = t;
00599 }
00600
00602 int
00603 DODSFilter::get_timeout() const
00604 {
00605 return d_timeout;
00606 }
00607
00619 void
00620 DODSFilter::establish_timeout(FILE *stream) const
00621 {
00622 #ifndef WIN32
00623 if (d_timeout > 0) {
00624 SignalHandler *sh = SignalHandler::instance();
00625 EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler(stream));
00626 delete old_eh;
00627 alarm(d_timeout);
00628 }
00629 #endif
00630 }
00631
00632
00633 void
00634 DODSFilter::establish_timeout(ostream &stream) const
00635 {
00636 #ifndef WIN32
00637 if (d_timeout > 0) {
00638 SignalHandler *sh = SignalHandler::instance();
00639 EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler(stream));
00640 delete old_eh;
00641 alarm(d_timeout);
00642 }
00643 #endif
00644 }
00645
00646
00656 void
00657 DODSFilter::read_ancillary_das(DAS &das, const string &anc_location) const
00658 {
00659 string name = find_ancillary_file(d_dataset, "das",
00660 (anc_location == "") ? d_anc_dir : anc_location,
00661 d_anc_file);
00662
00663 FILE *in = fopen(name.c_str(), "r");
00664 if (in) {
00665 das.parse(in);
00666 int res = fclose(in) ;
00667 if (res) {
00668 DBG(cerr << "DODSFilter::read_ancillary_das - Failed to close file " << (void *)in << endl ;) ;
00669 }
00670 }
00671 }
00672
00682 void
00683 DODSFilter::read_ancillary_dds(DDS &dds, const string &anc_location) const
00684 {
00685 string name = find_ancillary_file(d_dataset, "dds",
00686 (anc_location == "") ? d_anc_dir : anc_location,
00687 d_anc_file);
00688 FILE *in = fopen(name.c_str(), "r");
00689 if (in) {
00690 dds.parse(in);
00691 int res = fclose(in) ;
00692 if (res) {
00693 DBG(cerr << "DODSFilter::read_ancillary_dds - Failed to close " << (void *)in << endl ;) ;
00694 }
00695 }
00696 }
00697
00698 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.";
00699
00709 void
00710 DODSFilter::print_usage() const
00711 {
00712
00713 ErrMsgT(usage.c_str());
00714
00715 throw Error(unknown_error, emessage);
00716 }
00717
00723 void
00724 DODSFilter::send_version_info() const
00725 {
00726 do_version(d_cgi_ver, get_dataset_version());
00727 }
00728
00740 void
00741 DODSFilter::send_das(FILE *out, DAS &das, const string &anc_location,
00742 bool with_mime_headers) const
00743 {
00744 time_t das_lmt = get_das_last_modified_time(anc_location);
00745 if (is_conditional()
00746 && das_lmt <= get_request_if_modified_since()
00747 && with_mime_headers) {
00748 set_mime_not_modified(out);
00749 }
00750 else {
00751 if (with_mime_headers)
00752 set_mime_text(out, dods_das, d_cgi_ver, x_plain, das_lmt);
00753 das.print(out);
00754 }
00755 fflush(out) ;
00756 }
00757
00769 void
00770 DODSFilter::send_das(ostream &out, DAS &das, const string &anc_location,
00771 bool with_mime_headers) const
00772 {
00773 time_t das_lmt = get_das_last_modified_time(anc_location);
00774 if (is_conditional()
00775 && das_lmt <= get_request_if_modified_since()
00776 && with_mime_headers) {
00777 set_mime_not_modified(out);
00778 }
00779 else {
00780 if (with_mime_headers)
00781 set_mime_text(out, dods_das, d_cgi_ver, x_plain, das_lmt);
00782 das.print(out);
00783 }
00784 out << flush ;
00785 }
00786
00787 void
00788 DODSFilter::send_das(DAS &das, const string &anc_location,
00789 bool with_mime_headers) const
00790 {
00791 send_das(stdout, das, anc_location, with_mime_headers);
00792 }
00793
00810 void
00811 DODSFilter::send_dds(FILE *out, DDS &dds, ConstraintEvaluator &eval,
00812 bool constrained,
00813 const string &anc_location,
00814 bool with_mime_headers) const
00815 {
00816
00817 if (constrained)
00818 eval.parse_constraint(d_ce, dds);
00819
00820 if (eval.functional_expression())
00821 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.");
00822
00823 time_t dds_lmt = get_dds_last_modified_time(anc_location);
00824 if (is_conditional()
00825 && dds_lmt <= get_request_if_modified_since()
00826 && with_mime_headers) {
00827 set_mime_not_modified(out);
00828 }
00829 else {
00830 if (with_mime_headers)
00831 set_mime_text(out, dods_dds, d_cgi_ver, x_plain, dds_lmt);
00832 if (constrained)
00833 dds.print_constrained(out);
00834 else
00835 dds.print(out);
00836 }
00837
00838 fflush(out) ;
00839 }
00840
00857 void
00858 DODSFilter::send_dds(ostream &out, DDS &dds, ConstraintEvaluator &eval,
00859 bool constrained,
00860 const string &anc_location,
00861 bool with_mime_headers) const
00862 {
00863
00864 if (constrained)
00865 eval.parse_constraint(d_ce, dds);
00866
00867 if (eval.functional_expression())
00868 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.");
00869
00870 time_t dds_lmt = get_dds_last_modified_time(anc_location);
00871 if (is_conditional()
00872 && dds_lmt <= get_request_if_modified_since()
00873 && with_mime_headers) {
00874 set_mime_not_modified(out);
00875 }
00876 else {
00877 if (with_mime_headers)
00878 set_mime_text(out, dods_dds, d_cgi_ver, x_plain, dds_lmt);
00879 if (constrained)
00880 dds.print_constrained(out);
00881 else
00882 dds.print(out);
00883 }
00884
00885 out << flush ;
00886 }
00887
00888 void
00889 DODSFilter::send_dds(DDS &dds, ConstraintEvaluator &eval,
00890 bool constrained, const string &anc_location,
00891 bool with_mime_headers) const
00892 {
00893 send_dds(stdout, dds, eval, constrained, anc_location, with_mime_headers);
00894 }
00895
00896
00897
00898 void
00899 DODSFilter::functional_constraint(BaseType &var, DDS &dds,
00900 ConstraintEvaluator &eval, FILE *out) const
00901 {
00902 fprintf(out, "Dataset {\n");
00903 var.print_decl(out, " ", true, false, true);
00904 fprintf(out, "} function_value;\n");
00905 fprintf(out, "Data:\n");
00906
00907 fflush(out);
00908
00909
00910 XDRFileMarshaller m( out ) ;
00911
00912 try {
00913
00914 var.serialize(d_dataset, eval, dds, m, false);
00915 }
00916 catch (Error &e) {
00917 throw;
00918 }
00919 }
00920
00921
00922
00923 void
00924 DODSFilter::functional_constraint(BaseType &var, DDS &dds,
00925 ConstraintEvaluator &eval, ostream &out) const
00926 {
00927 out << "Dataset {\n" ;
00928 var.print_decl(out, " ", true, false, true);
00929 out << "} function_value;\n" ;
00930 out << "Data:\n" ;
00931
00932 out << flush ;
00933
00934
00935 XDRStreamMarshaller m( out ) ;
00936
00937 try {
00938
00939 var.serialize(d_dataset, eval, dds, m, false);
00940 }
00941 catch (Error &e) {
00942 throw;
00943 }
00944 }
00945
00946 void
00947 DODSFilter::dataset_constraint(DDS & dds, ConstraintEvaluator & eval,
00948 FILE * out) const
00949 {
00950
00951 dds.print_constrained(out);
00952 fprintf(out, "Data:\n");
00953 fflush(out);
00954
00955
00956 XDRFileMarshaller m( out ) ;
00957
00958 try {
00959
00960 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
00961 if ((*i)->send_p()) {
00962 DBG(cerr << "Sending " << (*i)->name() << endl);
00963 (*i)->serialize(d_dataset, eval, dds, m, true);
00964 }
00965 }
00966 catch (Error & e) {
00967 throw;
00968 }
00969 }
00970
00971 void
00972 DODSFilter::dataset_constraint(DDS & dds, ConstraintEvaluator & eval,
00973 ostream &out) const
00974 {
00975
00976 dds.print_constrained(out);
00977 out << "Data:\n" ;
00978 out << flush ;
00979
00980
00981 XDRStreamMarshaller m( out ) ;
00982
00983 try {
00984
00985 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
00986 if ((*i)->send_p()) {
00987 DBG(cerr << "Sending " << (*i)->name() << endl);
00988 (*i)->serialize(d_dataset, eval, dds, m, true);
00989 }
00990 }
00991 catch (Error & e) {
00992 throw;
00993 }
00994 }
00995
01012 void
01013 DODSFilter::send_data(DDS & dds, ConstraintEvaluator & eval,
01014 FILE * data_stream, const string & anc_location,
01015 bool with_mime_headers) const
01016 {
01017
01018
01019
01020 time_t data_lmt = get_data_last_modified_time(anc_location);
01021 if (is_conditional()
01022 && data_lmt <= get_request_if_modified_since()
01023 && with_mime_headers) {
01024 set_mime_not_modified(data_stream);
01025 return;
01026 }
01027
01028 establish_timeout(data_stream);
01029 dds.set_timeout(d_timeout);
01030
01031 eval.parse_constraint(d_ce, dds);
01032
01033
01034 dds.tag_nested_sequences();
01035
01036
01037 #if COMPRESSION_FOR_SERVER3
01038 bool compress = d_comp && deflate_exists();
01039 #endif
01040
01041
01042 if (eval.functional_expression()) {
01043
01044
01045
01046
01047 BaseType *var = eval.eval_function(dds, d_dataset);
01048 if (!var)
01049 throw Error(unknown_error, "Error calling the CE function.");
01050
01051 #if COMPRESSION_FOR_SERVER3
01052 if (with_mime_headers)
01053 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01054 (compress) ? deflate : x_plain, data_lmt);
01055 fflush(data_stream);
01056
01057 int childpid;
01058 if (compress)
01059 data_stream = compressor(data_stream, childpid);
01060 #endif
01061 if (with_mime_headers)
01062 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01063
01064 fflush(data_stream);
01065
01066 functional_constraint(*var, dds, eval, data_stream);
01067 delete var;
01068 var = 0;
01069 }
01070 else {
01071 #if COMPRESSION_FOR_SERVER3
01072 if (with_mime_headers)
01073 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01074 (compress) ? deflate : x_plain, data_lmt);
01075 fflush(data_stream);
01076
01077 int childpid;
01078 if (compress)
01079 data_stream = compressor(data_stream, childpid);
01080 #endif
01081 if (with_mime_headers)
01082 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01083
01084 dataset_constraint(dds, eval, data_stream);
01085 }
01086
01087 fflush(data_stream);
01088 }
01089
01106 void
01107 DODSFilter::send_data(DDS & dds, ConstraintEvaluator & eval,
01108 ostream & data_stream, const string & anc_location,
01109 bool with_mime_headers) const
01110 {
01111
01112
01113
01114 time_t data_lmt = get_data_last_modified_time(anc_location);
01115 if (is_conditional()
01116 && data_lmt <= get_request_if_modified_since()
01117 && with_mime_headers) {
01118 set_mime_not_modified(data_stream);
01119 return;
01120 }
01121
01122 establish_timeout(data_stream);
01123 dds.set_timeout(d_timeout);
01124
01125 eval.parse_constraint(d_ce, dds);
01126
01127
01128 dds.tag_nested_sequences();
01129
01130
01131 #if COMPRESSION_FOR_SERVER3
01132 bool compress = d_comp && deflate_exists();
01133 #endif
01134
01135
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 COMPRESSION_FOR_SERVER3
01146 if (with_mime_headers)
01147 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01148 (compress) ? deflate : x_plain, data_lmt);
01149 data_stream << flush ;
01150
01151 int childpid;
01152 if (compress)
01153 data_stream = compressor(data_stream, childpid);
01154 #endif
01155 if (with_mime_headers)
01156 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01157
01158 data_stream << flush ;
01159
01160 functional_constraint(*var, dds, eval, data_stream);
01161 delete var;
01162 var = 0;
01163 }
01164 else {
01165 #if COMPRESSION_FOR_SERVER3
01166 if (with_mime_headers)
01167 set_mime_binary(data_stream, dods_data, d_cgi_ver,
01168 (compress) ? deflate : x_plain, data_lmt);
01169 data_stream << flush ;
01170
01171 int childpid;
01172 if (compress)
01173 data_stream = compressor(data_stream, childpid);
01174 #endif
01175 if (with_mime_headers)
01176 set_mime_binary(data_stream, dods_data, d_cgi_ver, x_plain, data_lmt);
01177
01178 dataset_constraint(dds, eval, data_stream);
01179 }
01180
01181 data_stream << flush ;
01182 }
01183
01194 void
01195 DODSFilter::send_ddx(DDS &dds, ConstraintEvaluator &eval, FILE *out,
01196 bool with_mime_headers) const
01197 {
01198
01199 if (!d_ce.empty())
01200 eval.parse_constraint(d_ce, dds);
01201
01202 if (eval.functional_expression())
01203 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.");
01204
01205 time_t dds_lmt = get_dds_last_modified_time(d_anc_dir);
01206
01207
01208
01209
01210 if (is_conditional() && dds_lmt <= get_request_if_modified_since()
01211 && with_mime_headers) {
01212 set_mime_not_modified(out);
01213 return;
01214 }
01215 else {
01216 if (with_mime_headers)
01217 set_mime_text(out, dap4_ddx, d_cgi_ver, x_plain, dds_lmt);
01218 dds.print_xml(out, !d_ce.empty(), d_url + ".blob?" + d_ce);
01219 }
01220 }
01221
01232 void
01233 DODSFilter::send_ddx(DDS &dds, ConstraintEvaluator &eval, ostream &out,
01234 bool with_mime_headers) const
01235 {
01236
01237 if (!d_ce.empty())
01238 eval.parse_constraint(d_ce, dds);
01239
01240 if (eval.functional_expression())
01241 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.");
01242
01243 time_t dds_lmt = get_dds_last_modified_time(d_anc_dir);
01244
01245
01246
01247
01248 if (is_conditional() && dds_lmt <= get_request_if_modified_since()
01249 && with_mime_headers) {
01250 set_mime_not_modified(out);
01251 return;
01252 }
01253 else {
01254 if (with_mime_headers)
01255 set_mime_text(out, dap4_ddx, d_cgi_ver, x_plain, dds_lmt);
01256 dds.print_xml(out, !d_ce.empty(), d_url + ".blob?" + d_ce);
01257 }
01258 }
01259
01264 void
01265 DODSFilter::send_blob(DDS &, FILE *, bool)
01266 {
01267 #if 0
01268
01269 bool compress = d_comp && deflate_exists();
01270 time_t data_lmt = get_data_last_modified_time(d_anc_dir);
01271
01272
01273
01274
01275 if (is_conditional() && data_lmt <= get_request_if_modified_since()
01276 && with_mime_headers) {
01277 set_mime_not_modified(out);
01278 return;
01279 }
01280
01281 dds.parse_constraint(d_ce);
01282
01283
01284 if (dds.functional_expression()) {
01285 BaseType *var = dds.eval_function(d_dataset);
01286 if (!var)
01287 throw Error("Error calling the CE function.");
01288
01289 if (with_mime_headers)
01290 set_mime_binary(out, dods_data, d_cgi_ver,
01291 (compress) ? deflate : x_plain, data_lmt);
01292
01293 FILE *comp_sink;
01294 XDR *xdr_sink;
01295 int childpid = get_sinks(out, compress, &comp_sink, &xdr_sink);
01296
01297
01298 if (!var->serialize(d_dataset, dds, xdr_sink, false))
01299 throw Error("Could not send the function result.");
01300
01301 clean_sinks(childpid, compress, xdr_sink, comp_sink);
01302 }
01303 else {
01304 if (with_mime_headers)
01305 set_mime_binary(out, dods_data, d_cgi_ver,
01306 (compress) ? deflate : x_plain, data_lmt);
01307
01308 FILE *comp_sink;
01309 XDR *xdr_sink;
01310 int childpid = get_sinks(out, compress, &comp_sink, &xdr_sink);
01311
01312 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++)
01313 if ((*i)->send_p())
01314 if (!(*i)->serialize(d_dataset, dds, xdr_sink, true))
01315 throw Error(string("Could not serialize variable '")
01316 + (*i)->name() + string("'."));
01317
01318 clean_sinks(childpid, compress, xdr_sink, comp_sink);
01319 }
01320 #endif
01321 }
01322
01323 }
01324