Connect.cc

Go to the documentation of this file.
00001 
00002 // -*- mode: c++; c-basic-offset:4 -*-
00003 
00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00005 // Access Protocol.
00006 
00007 // Copyright (c) 2002,2003 OPeNDAP, Inc.
00008 // Author: James Gallagher <jgallagher@opendap.org>
00009 //         Dan Holloway <dholloway@gso.uri.edu>
00010 //         Reza Nekovei <reza@intcomm.net>
00011 //
00012 // This library is free software; you can redistribute it and/or
00013 // modify it under the terms of the GNU Lesser General Public
00014 // License as published by the Free Software Foundation; either
00015 // version 2.1 of the License, or (at your option) any later version.
00016 //
00017 // This library is distributed in the hope that it will be useful,
00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020 // Lesser General Public License for more details.
00021 //
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License along with this library; if not, write to the Free Software
00024 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 //
00026 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00027 
00028 // (c) COPYRIGHT URI/MIT 1994-2002
00029 // Please read the full copyright statement in the file COPYRIGHT_URI.
00030 //
00031 // Authors:
00032 //      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
00033 //      dan             Dan Holloway <dholloway@gso.uri.edu>
00034 //      reza            Reza Nekovei <reza@intcomm.net>
00035 
00036 
00037 #include "config.h"
00038 
00039 //#define DODS_DEBUG
00040 
00041 static char rcsid[] not_used =
00042     { "$Id: Connect.cc 17002 2007-08-27 19:16:51Z pwest $"
00043     };
00044 
00045 #include <stdio.h>
00046 #ifndef WIN32
00047 #include <unistd.h>
00048 #endif
00049 
00050 #include <fstream>
00051 #include <algorithm>
00052 
00053 #include "debug.h"
00054 #include "DataDDS.h"
00055 #include "Connect.h"
00056 #include "escaping.h"
00057 #include "RCReader.h"
00058 #include "DDXParser.h"
00059 #include "XDRFileUnMarshaller.h"
00060 
00061 using std::cerr;
00062 using std::endl;
00063 using std::ifstream;
00064 using std::ofstream;
00065 using std::min;
00066 
00067 extern ObjectType get_type(const string &value);
00068 
00071 void
00072 Connect::process_data(DataDDS &data, Response *rs)
00073 {
00074     DBG(cerr << "Entering Connect::process_data" << endl);
00075 
00076     // Use the implementation and protocol versions from the Response object
00077     // since the copies in Connect might go away. Regardless, we must keep the
00078     // Response object alive until we no longer need the stream, since
00079     // destroying it will close the stream. So, might as well use it for the
00080     // version info too...
00081     data.set_version(rs->get_version());
00082     data.set_protocol(rs->get_protocol());
00083 
00084     DBG(cerr << "Entering process_data: d_stream = " << rs << endl);
00085     switch (rs->get_type()) {
00086     case dods_error: {
00087             Error e;
00088             if (!e.parse(rs->get_stream()))
00089                 throw InternalErr(__FILE__, __LINE__,
00090                                   "Could not parse the Error object returned by the server!");
00091             throw e;
00092         }
00093 
00094     case web_error:
00095         // Web errors (those reported in the return document's MIME header)
00096         // are processed by the WWW library.
00097         throw InternalErr(__FILE__, __LINE__, "An error was reported by the remote httpd; this should have been processed by HTTPConnect..");
00098 
00099     case dods_data:
00100     default: {
00101             // Parse the DDS; throw an exception on error.
00102             data.parse(rs->get_stream());
00103             XDRFileUnMarshaller um( rs->get_stream() ) ;
00104 
00105             // Load the DDS with data.
00106             try {
00107                 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end();
00108                      i++) {
00109                     (*i)->deserialize(um, &data);
00110                 }
00111             }
00112             catch (Error &e) {
00113                 throw e;
00114             }
00115 
00116             return;
00117         }
00118 
00119 #if 0
00120         // According to the spec (DAP 2), servers MUST return the dods_data
00121         // Content-Type. But, many older servers do not do this, so the
00122         // default case is not to throw an error, but to treat the response
00123         // as data... See bug 706. 03/22/04 jhrg
00124     default:
00125         throw Error("The site did not return a valid response (it lacked the\nexpected content description header value of 'dods_data').\nThis may indicate that the server at the site is not correctly\nconfigured, or that the URL has changed.");
00126 #endif
00127     }
00128 }
00129 
00130 // This function returns the ObjectType value that matches the given string.
00131 ObjectType
00132 get_type(const string &value)
00133 {
00134     if (value == "dods_das")
00135         return dods_das;
00136     else if (value == "dods_dds")
00137         return dods_dds;
00138     else if (value == "dods_data")
00139         return dods_data;
00140     else if (value == "dods_error")
00141         return dods_error;
00142     else if (value == "web_error")
00143         return web_error;
00144     else
00145         return unknown_type;
00146 }
00147 
00148 // Barely a parser... This is used when reading from local sources of DODS
00149 // Data objects. It simulates the important actions of the libwww MIME header
00150 // parser. Those actions fill in certain fields in the Connect object. jhrg
00151 // 5/20/97
00152 //
00153 // Make sure that this parser reads from data_source without disturbing the
00154 // information in data_source that follows the MIME header. Since the DDS
00155 // (which follows the MIME header) is parsed by a flex/bison scanner/parser,
00156 // make sure to use I/O calls that will mesh with ANSI C I/O calls. In the
00157 // old GNU libg++, the C++ calls were synchronized with the C calls, but that
00158 // may no longer be the case. 5/31/99 jhrg
00159 
00169 void
00170 Connect::parse_mime(/*FILE *data_source, */Response *rs)
00171 {
00172     rs->set_version("dods/0.0"); // initial value; for backward compat.
00173     rs->set_protocol("2.0");
00174 
00175     // If the first line does not start with HTTP, XDODS or XDAP, assume
00176     // there's no MIME header here and return without reading anymore
00177     FILE *data_source = rs->get_stream();
00178 
00179     char line[256];
00180     fgets(line, 255, data_source);
00181 
00182     int slen = strlen(line);
00183     slen = min(slen, 256); // use min to limit slen to 256 (fortify)
00184     line[slen - 1] = '\0'; // remove the newline
00185     if (line[slen - 2] == '\r') // ...and the preceding carriage return
00186         line[slen - 2] = '\0';
00187 
00188     while (line[0] != '\0') {
00189         char h[256], v[256];
00190         sscanf(line, "%s %s\n", h, v);
00191         string header = h;
00192         string value = v;
00193         downcase(header);
00194         downcase(value);
00195 
00196         if (header == "content-description:") {
00197             DBG(cout << header << ": " << value << endl);
00198             rs->set_type(get_type(value));
00199         }
00200         else if (header == "xdods-server:"
00201                  && rs->get_version() == "dods/0.0") {
00202             DBG(cout << header << ": " << value << endl);
00203             rs->set_version(value);
00204         }
00205         else if (header == "xopendap-server:") {
00206             DBG(cout << header << ": " << value << endl);
00207             rs->set_version(value);
00208         }
00209         else if (header == "xdap:") {
00210             DBG(cout << header << ": " << value << endl);
00211             rs->set_protocol(value);
00212         }
00213         else if (rs->get_version() == "dods/0.0" && header == "server:") {
00214             DBG(cout << header << ": " << value << endl);
00215             rs->set_version(value);
00216         }
00217 
00218         fgets(line, 255, data_source);
00219         slen = strlen(line);
00220         slen = min(slen, 256); // use min to limit slen to 256
00221         line[slen - 1] = '\0';
00222         if (line[slen - 2] == '\r')
00223             line[slen - 2] = '\0';
00224     }
00225 }
00226 
00227 // public mfuncs
00228 
00236 Connect::Connect(const string &n, string uname, string password)
00237 throw(Error, InternalErr)
00238         : d_http(0), d_version("unknown"), d_protocol("2.0")
00239 {
00240     string name = prune_spaces(n);
00241 
00242     // Figure out if the URL starts with 'http', if so, make sure that we
00243     // talk to an instance of HTTPConnect.
00244     if (name.find("http") == 0) {
00245         DBG(cerr << "Connect: The identifier is an http URL" << endl);
00246         d_http = new HTTPConnect(RCReader::instance());
00247 
00248         // Find and store any CE given with the URL.
00249         string::size_type dotpos = name.find('?');
00250         if (dotpos != name.npos) {
00251             _URL = name.substr(0, dotpos);
00252             string expr = name.substr(dotpos + 1);
00253 
00254             dotpos = expr.find('&');
00255             if (dotpos != expr.npos) {
00256                 _proj = expr.substr(0, dotpos);
00257                 _sel = expr.substr(dotpos); // XXX includes '&'
00258             }
00259             else {
00260                 _proj = expr;
00261                 _sel = "";
00262             }
00263         }
00264         else {
00265             _URL = name;
00266             _proj = "";
00267             _sel = "";
00268         }
00269 
00270         _local = false;
00271     }
00272     else {
00273         DBG(cerr << "Connect: The identifier is a local data source." << endl);
00274 
00275         d_http = 0;
00276         _URL = "";
00277         _local = true;  // local in this case means non-DAP
00278     }
00279 
00280     set_credentials(uname, password);
00281 }
00282 
00283 Connect::~Connect()
00284 {
00285     DBG2(cerr << "Entering the Connect dtor" << endl);
00286 
00287     if (d_http)
00288         delete d_http; d_http = 0;
00289 
00290     DBG2(cerr << "Leaving the Connect dtor" << endl);
00291 }
00292 
00300 string
00301 Connect::request_version()
00302 {
00303     string version_url = _URL + ".ver";
00304     if (_proj.length() + _sel.length())
00305         version_url = version_url + "?" + id2www_ce(_proj + _sel);
00306 
00307     Response *rs = 0;
00308     try {
00309         rs = d_http->fetch_url(version_url);
00310     }
00311     catch (Error &e) {
00312         delete rs; rs = 0;
00313         throw e;
00314     }
00315 
00316     d_version = rs->get_version();
00317     d_protocol = rs->get_protocol();
00318     delete rs; rs = 0;
00319 
00320     return d_version;
00321 }
00322 
00330 string
00331 Connect::request_protocol()
00332 {
00333     string version_url = _URL + ".ver";
00334     if (_proj.length() + _sel.length())
00335         version_url = version_url + "?" + id2www_ce(_proj + _sel);
00336 
00337     Response *rs = 0;
00338     try {
00339         rs = d_http->fetch_url(version_url);
00340     }
00341     catch (Error &e) {
00342         delete rs; rs = 0;
00343         throw e;
00344     }
00345 
00346     d_version = rs->get_version();
00347     d_protocol = rs->get_protocol();
00348     delete rs; rs = 0;
00349 
00350     return d_protocol;
00351 }
00352 
00360 void
00361 Connect::request_das(DAS &das)
00362 {
00363     string das_url = _URL + ".das";
00364     if (_proj.length() + _sel.length())
00365         das_url = das_url + "?" + id2www_ce(_proj + _sel);
00366 
00367     Response *rs = 0;
00368     try {
00369         rs = d_http->fetch_url(das_url);
00370     }
00371     catch (Error &e) {
00372         delete rs; rs = 0;
00373         throw e;
00374     }
00375 
00376     d_version = rs->get_version();
00377     d_protocol = rs->get_protocol();
00378 
00379     switch (rs->get_type()) {
00380     case dods_error: {
00381             Error e;
00382             if (!e.parse(rs->get_stream())) {
00383                 throw InternalErr(__FILE__, __LINE__,
00384                                   "Could not parse error returned from server.");
00385                 break;
00386             }
00387             throw e;
00388             break;
00389         }
00390 
00391     case web_error:
00392         // We should never get here; a web error should be picked up read_url
00393         // (called by fetch_url) and result in a thrown Error object.
00394         break;
00395 
00396     case dods_das:
00397     default:
00398         // DAS::parse throws an exception on error.
00399         try {
00400             das.parse(rs->get_stream()); // read and parse the das from a file
00401         }
00402         catch (Error &e) {
00403             delete rs; rs = 0;
00404             throw e;
00405         }
00406 
00407         break;
00408 
00409 #if 0
00410         // See the comment in process_data() and bug 706. 03/22/04 jhrg
00411     default:
00412         throw Error("The site did not return a valid response (it lacked the\nexpected content description header value of 'dods_das').\nThis may indicate that the server at the site is not correctly\nconfigured, or that the URL has changed.");
00413 #endif
00414     }
00415 
00416     delete rs; rs = 0;
00417 }
00418 
00429 void
00430 Connect::request_das_url(DAS &das)
00431 {
00432     string use_url = _URL + "?" + _proj + _sel ;
00433     Response *rs = 0;
00434     try {
00435         rs = d_http->fetch_url(use_url);
00436     }
00437     catch (Error &e) {
00438         delete rs; rs = 0;
00439         throw e;
00440     }
00441 
00442     d_version = rs->get_version();
00443     d_protocol = rs->get_protocol();
00444 
00445     switch (rs->get_type()) {
00446     case dods_error: {
00447             Error e;
00448             if (!e.parse(rs->get_stream())) {
00449                 throw InternalErr(__FILE__, __LINE__,
00450                                   "Could not parse error returned from server.");
00451                 break;
00452             }
00453             throw e;
00454             break;
00455         }
00456 
00457     case web_error:
00458         // We should never get here; a web error should be picked up read_url
00459         // (called by fetch_url) and result in a thrown Error object.
00460         break;
00461 
00462     case dods_das:
00463     default:
00464         // DAS::parse throws an exception on error.
00465         try {
00466             das.parse(rs->get_stream()); // read and parse the das from a file
00467         }
00468         catch (Error &e) {
00469             delete rs; rs = 0;
00470             throw e;
00471         }
00472 
00473         break;
00474     }
00475 
00476     delete rs; rs = 0;
00477 }
00478 
00492 void
00493 Connect::request_dds(DDS &dds, string expr)
00494 {
00495     string proj, sel;
00496     string::size_type dotpos = expr.find('&');
00497     if (dotpos != expr.npos) {
00498         proj = expr.substr(0, dotpos);
00499         sel = expr.substr(dotpos);
00500     }
00501     else {
00502         proj = expr;
00503         sel = "";
00504     }
00505 
00506     string dds_url = _URL + ".dds" + "?"
00507                      + id2www_ce(_proj + proj + _sel + sel);
00508 
00509     Response *rs = 0;
00510     try {
00511         rs = d_http->fetch_url(dds_url);
00512     }
00513     catch (Error &e) {
00514         delete rs; rs = 0;
00515         throw e;
00516     }
00517 
00518     d_version = rs->get_version();
00519     d_protocol = rs->get_protocol();
00520 
00521     switch (rs->get_type()) {
00522     case dods_error: {
00523             Error e;
00524             if (!e.parse(rs->get_stream())) {
00525                 throw InternalErr(__FILE__, __LINE__,
00526                                   "Could not parse error returned from server.");
00527                 break;
00528             }
00529             throw e;
00530             break;
00531         }
00532 
00533     case web_error:
00534         // We should never get here; a web error should be picked up read_url
00535         // (called by fetch_url) and result in a thrown Error object.
00536         break;
00537 
00538     case dods_dds:
00539     default:
00540         // DDS::prase throws an exception on error.
00541         try {
00542             dds.parse(rs->get_stream()); // read and parse the dds from a file
00543         }
00544         catch (Error &e) {
00545             delete rs; rs = 0;
00546             throw e;
00547         }
00548         break;
00549 
00550 #if 0
00551         // See the comment in process_data() and bug 706. 03/22/04 jhrg
00552     default:
00553         throw Error("The site did not return a valid response (it lacked the\nexpected content description header value of 'dods_dds').\nThis may indicate that the server at the site is not correctly\nconfigured, or that the URL has changed.");
00554 #endif
00555     }
00556 
00557     delete rs; rs = 0;
00558 }
00559 
00576 void
00577 Connect::request_dds_url(DDS &dds)
00578 {
00579     string use_url = _URL + "?" + _proj + _sel ;
00580     Response *rs = 0;
00581     try {
00582         rs = d_http->fetch_url(use_url);
00583     }
00584     catch (Error &e) {
00585         delete rs; rs = 0;
00586         throw e;
00587     }
00588 
00589     d_version = rs->get_version();
00590     d_protocol = rs->get_protocol();
00591 
00592     switch (rs->get_type()) {
00593     case dods_error: {
00594             Error e;
00595             if (!e.parse(rs->get_stream())) {
00596                 throw InternalErr(__FILE__, __LINE__,
00597                                   "Could not parse error returned from server.");
00598                 break;
00599             }
00600             throw e;
00601             break;
00602         }
00603 
00604     case web_error:
00605         // We should never get here; a web error should be picked up read_url
00606         // (called by fetch_url) and result in a thrown Error object.
00607         break;
00608 
00609     case dods_dds:
00610     default:
00611         // DDS::prase throws an exception on error.
00612         try {
00613             dds.parse(rs->get_stream()); // read and parse the dds from a file
00614         }
00615         catch (Error &e) {
00616             delete rs; rs = 0;
00617             throw e;
00618         }
00619         break;
00620     }
00621 
00622     delete rs; rs = 0;
00623 }
00624 
00636 void
00637 Connect::request_ddx(DDS &dds, string expr)
00638 {
00639     string proj, sel;
00640     string::size_type dotpos = expr.find('&');
00641     if (dotpos != expr.npos) {
00642         proj = expr.substr(0, dotpos);
00643         sel = expr.substr(dotpos);
00644     }
00645     else {
00646         proj = expr;
00647         sel = "";
00648     }
00649 
00650     string ddx_url = _URL + ".ddx" + "?"
00651                      + id2www_ce(_proj + proj + _sel + sel);
00652 
00653     Response *rs = 0;
00654     try {
00655         rs = d_http->fetch_url(ddx_url);
00656     }
00657     catch (Error &e) {
00658         delete rs; rs = 0;
00659         throw e;
00660     }
00661 
00662     d_version = rs->get_version();
00663     d_protocol = rs->get_protocol();
00664 
00665     switch (rs->get_type()) {
00666     case dods_error: {
00667             Error e;
00668             if (!e.parse(rs->get_stream())) {
00669                 throw InternalErr(__FILE__, __LINE__,
00670                                   "Could not parse error returned from server.");
00671                 break;
00672             }
00673             throw e;
00674             break;
00675         }
00676 
00677     case web_error:
00678         // We should never get here; a web error should be picked up read_url
00679         // (called by fetch_url) and result in a thrown Error object.
00680         break;
00681 
00682     case dap4_ddx:
00683     default:
00684         // DDS::prase throws an exception on error.
00685         try {
00686             string blob;
00687             DDXParser ddxp(dds.get_factory());
00688             ddxp.intern_stream(rs->get_stream(), &dds, &blob);
00689 #if 0
00690             dds.parse(rs->get_stream()); // read and parse the dds from a file
00691 #endif
00692         }
00693         catch (Error &e) {
00694             delete rs; rs = 0;
00695             throw e;
00696         }
00697         break;
00698 
00699 #if 0
00700         // See the comment in process_data() and bug 706. 03/22/04 jhrg
00701     default:
00702         throw Error("The site did not return a valid response (it lacked the\nexpected content description header value of 'dods_ddx').\nThis may indicate that the server at the site is not correctly\nconfigured, or that the URL has changed.");
00703 #endif
00704     }
00705 
00706     delete rs; rs = 0;
00707 }
00708 
00711 void
00712 Connect::request_ddx_url(DDS &dds)
00713 {
00714     string use_url = _URL + "?" + _proj + _sel ;
00715 
00716     Response *rs = 0;
00717     try {
00718         rs = d_http->fetch_url(use_url);
00719     }
00720     catch (Error &e) {
00721         delete rs; rs = 0;
00722         throw e;
00723     }
00724 
00725     d_version = rs->get_version();
00726     d_protocol = rs->get_protocol();
00727 
00728     switch (rs->get_type()) {
00729     case dods_error: {
00730             Error e;
00731             if (!e.parse(rs->get_stream())) {
00732                 throw InternalErr(__FILE__, __LINE__,
00733                                   "Could not parse error returned from server.");
00734                 break;
00735             }
00736             throw e;
00737             break;
00738         }
00739 
00740     case web_error:
00741         // We should never get here; a web error should be picked up read_url
00742         // (called by fetch_url) and result in a thrown Error object.
00743         break;
00744 
00745     case dap4_ddx:
00746     default:
00747         // DDS::prase throws an exception on error.
00748         try {
00749             dds.parse(rs->get_stream()); // read and parse the dds from a file
00750         }
00751         catch (Error &e) {
00752             delete rs; rs = 0;
00753             throw e;
00754         }
00755         break;
00756 
00757 #if 0
00758         // See the comment in process_data() and bug 706. 03/22/04 jhrg
00759     default:
00760         throw Error("The site did not return a valid response (it lacked the\nexpected content description header value of 'dods_ddx').\nThis may indicate that the server at the site is not correctly\nconfigured, or that the URL has changed.");
00761 #endif
00762     }
00763 
00764     delete rs; rs = 0;
00765 }
00766 
00782 void
00783 Connect::request_data(DataDDS &data, string expr)
00784 {
00785     string proj, sel;
00786     string::size_type dotpos = expr.find('&');
00787     if (dotpos != expr.npos) {
00788         proj = expr.substr(0, dotpos);
00789         sel = expr.substr(dotpos);
00790     }
00791     else {
00792         proj = expr;
00793         sel = "";
00794     }
00795 
00796     string data_url = _URL + ".dods?"
00797                       + id2www_ce(_proj + proj + _sel + sel);
00798 
00799     Response *rs = 0;
00800     // We need to catch Error exceptions to ensure calling close_output.
00801     try {
00802         rs = d_http->fetch_url(data_url);
00803         d_version = rs->get_version();
00804         d_protocol = rs->get_protocol();
00805 
00806         process_data(data, rs);
00807         delete rs; rs = 0;
00808     }
00809     catch (Error &e) {
00810         delete rs; rs = 0;
00811         throw e;
00812     }
00813 }
00814 
00832 void
00833 Connect::request_data_url(DataDDS &data)
00834 {
00835     string use_url = _URL + "?" + _proj + _sel ;
00836     Response *rs = 0;
00837     // We need to catch Error exceptions to ensure calling close_output.
00838     try {
00839         rs = d_http->fetch_url(use_url);
00840         d_version = rs->get_version();
00841         d_protocol = rs->get_protocol();
00842 
00843         process_data(data, rs);
00844         delete rs; rs = 0;
00845     }
00846     catch (Error &e) {
00847         delete rs; rs = 0;
00848         throw e;
00849     }
00850 }
00851 
00852 
00869 void
00870 Connect::read_data(DataDDS &data, Response *rs)
00871 {
00872     if (!rs)
00873         throw InternalErr(__FILE__, __LINE__, "Response object is null.");
00874 
00875     // Read from data_source and parse the MIME headers specific to DAP2.
00876     parse_mime(rs);
00877 
00878     read_data_no_mime(data, rs);
00879 }
00880 
00889 void
00890 Connect::read_data_no_mime(DataDDS &data, Response *rs)
00891 {
00892     d_version = rs->get_version();
00893     d_protocol = rs->get_protocol();
00894 
00895     process_data(data, rs);
00896 }
00897 
00898 bool
00899 Connect::is_local()
00900 {
00901     return _local;
00902 }
00903 
00920 string
00921 Connect::URL(bool ce)
00922 {
00923     if (_local)
00924         throw InternalErr(__FILE__, __LINE__,
00925                           "URL(): This call is only valid for a DAP2 data source.");
00926 
00927     if (ce)
00928         return _URL + "?" + _proj + _sel;
00929     else
00930         return _URL;
00931 }
00932 
00941 string
00942 Connect::CE()
00943 {
00944     if (_local)
00945         throw InternalErr(__FILE__, __LINE__,
00946                           "CE(): This call is only valid for a DAP2 data source.");
00947 
00948     return _proj + _sel;
00949 }
00950 
00956 void
00957 Connect::set_credentials(string u, string p)
00958 {
00959     if (d_http)
00960         d_http->set_credentials(u, p);
00961 }
00962 
00966 void
00967 Connect::set_accept_deflate(bool deflate)
00968 {
00969     if (d_http)
00970         d_http->set_accept_deflate(deflate);
00971 }
00972 
00976 void
00977 Connect::set_cache_enabled(bool cache)
00978 {
00979     if (d_http)
00980         d_http->set_cache_enabled(cache);
00981 }
00982 
00983 bool
00984 Connect::is_cache_enabled()
00985 {
00986     bool status;
00987     DBG(cerr << "Entering is_cache_enabled (" << hex << d_http << dec
00988         << ")... ");
00989     if (d_http)
00990         status = d_http->is_cache_enabled();
00991     else
00992         status = false;
00993     DBGN(cerr << "exiting" << endl);
00994     return status;
00995 }

Generated on Wed Jan 2 04:13:16 2008 for libdap++ by  doxygen 1.5.4