libdap++ Updated for version 3.8.2
|
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 #define FILE_METHODS 1 00041 00042 static char rcsid[] not_used = 00043 { "$Id: Connect.cc 22703 2010-05-11 18:10:01Z jimg $" 00044 }; 00045 00046 #include <cstring> 00047 #include <fstream> 00048 #include <algorithm> 00049 00050 #include "debug.h" 00051 #include "DataDDS.h" 00052 #include "Connect.h" 00053 #include "escaping.h" 00054 #include "RCReader.h" 00055 #include "DDXParserSAX2.h" 00056 #if FILE_METHODS 00057 #include "XDRFileUnMarshaller.h" 00058 #else 00059 #include "fdiostream.h" 00060 #include "XDRStreamUnMarshaller.h" 00061 #endif 00062 #include "mime_util.h" 00063 00064 using std::cerr; 00065 using std::endl; 00066 using std::ifstream; 00067 using std::ofstream; 00068 using std::min; 00069 00070 namespace libdap { 00071 00074 void 00075 Connect::process_data(DataDDS &data, Response *rs) 00076 { 00077 DBG(cerr << "Entering Connect::process_data" << endl); 00078 00079 data.set_version(rs->get_version()); 00080 data.set_protocol(rs->get_protocol()); 00081 00082 DBG(cerr << "Entering process_data: d_stream = " << rs << endl); 00083 switch (rs->get_type()) { 00084 case dods_error: { 00085 Error e; 00086 if (!e.parse(rs->get_stream())) 00087 throw InternalErr(__FILE__, __LINE__, 00088 "Could not parse the Error object returned by the server!"); 00089 throw e; 00090 } 00091 00092 case web_error: 00093 // Web errors (those reported in the return document's MIME header) 00094 // are processed by the WWW library. 00095 throw InternalErr(__FILE__, __LINE__, "An error was reported by the remote httpd; this should have been processed by HTTPConnect.."); 00096 00097 case dap4_data_ddx: { 00098 // Parse the DDX; throw an exception on error. 00099 DDXParser ddx_parser(data.get_factory()); 00100 00101 // Read the MPM boundary and then read the subsequent headers 00102 string boundary = read_multipart_boundary(rs->get_stream()); 00103 DBG(cerr << "MPM Boundary: " << boundary << endl); 00104 read_multipart_headers(rs->get_stream(), "text/xml", dap4_ddx); 00105 00106 // Parse the DDX, reading up to and including the next boundary. 00107 // Return the CID for the matching data part 00108 string data_cid; 00109 ddx_parser.intern_stream(rs->get_stream(), &data, data_cid, boundary); 00110 00111 // Munge the CID into something we can work with 00112 data_cid = cid_to_header_value(data_cid); 00113 DBG(cerr << "Data CID: " << data_cid << endl); 00114 00115 // Read the data part's MPM part headers (boundary was read by 00116 // DDXParse::intern) 00117 read_multipart_headers(rs->get_stream(), 00118 "application/octet-stream", dap4_data, data_cid); 00119 00120 // Now read the data 00121 #if FILE_METHODS 00122 XDRFileUnMarshaller um( rs->get_stream() ) ; 00123 #else 00124 fpistream in ( rs->get_stream() ); 00125 XDRStreamUnMarshaller um( in ) ; 00126 #endif 00127 try { 00128 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); 00129 i++) { 00130 (*i)->deserialize(um, &data); 00131 } 00132 } 00133 catch (Error &e) { 00134 throw e; 00135 } 00136 00137 return; 00138 } 00139 00140 case dods_data: 00141 default: { 00142 // Parse the DDS; throw an exception on error. 00143 data.parse(rs->get_stream()); 00144 #if FILE_METHODS 00145 XDRFileUnMarshaller um( rs->get_stream() ) ; 00146 #else 00147 fpistream in ( rs->get_stream() ); 00148 XDRStreamUnMarshaller um( in ) ; 00149 #endif 00150 // Load the DDS with data. 00151 try { 00152 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); 00153 i++) { 00154 (*i)->deserialize(um, &data); 00155 } 00156 } 00157 catch (Error &e) { 00158 throw e; 00159 } 00160 00161 return; 00162 } 00163 } 00164 } 00165 00166 // Barely a parser... This is used when reading from local sources of DODS 00167 // Data objects. It simulates the important actions of the libwww MIME header 00168 // parser. Those actions fill in certain fields in the Connect object. jhrg 00169 // 5/20/97 00170 // 00171 // Make sure that this parser reads from data_source without disturbing the 00172 // information in data_source that follows the MIME header. Since the DDS 00173 // (which follows the MIME header) is parsed by a flex/bison scanner/parser, 00174 // make sure to use I/O calls that will mesh with ANSI C I/O calls. In the 00175 // old GNU libg++, the C++ calls were synchronized with the C calls, but that 00176 // may no longer be the case. 5/31/99 jhrg 00177 00187 void 00188 Connect::parse_mime(Response *rs) 00189 { 00190 rs->set_version("dods/0.0"); // initial value; for backward compatibility. 00191 rs->set_protocol("2.0"); 00192 00193 FILE *data_source = rs->get_stream(); 00194 string mime = get_next_mime_header(data_source); 00195 while (!mime.empty()) { 00196 string header, value; 00197 parse_mime_header(mime, header, value); 00198 00199 // Note that this is an ordered list 00200 if (header == "content-description:") { 00201 DBG(cout << header << ": " << value << endl); 00202 rs->set_type(get_description_type(value)); 00203 } 00204 // Use the value of xdods-server only if no other value has been read 00205 else if (header == "xdods-server:" 00206 && rs->get_version() == "dods/0.0") { 00207 DBG(cout << header << ": " << value << endl); 00208 rs->set_version(value); 00209 } 00210 // This trumps 'xdods-server' and 'server' 00211 else if (header == "xopendap-server:") { 00212 DBG(cout << header << ": " << value << endl); 00213 rs->set_version(value); 00214 } 00215 else if (header == "xdap:") { 00216 DBG(cout << header << ": " << value << endl); 00217 rs->set_protocol(value); 00218 } 00219 // Only look for 'server' if no other header supplies this info. 00220 else if (rs->get_version() == "dods/0.0" && header == "server:") { 00221 DBG(cout << header << ": " << value << endl); 00222 rs->set_version(value); 00223 } 00224 00225 mime = get_next_mime_header(data_source); 00226 } 00227 } 00228 00229 // public mfuncs 00230 00238 Connect::Connect(const string &n, string uname, string password) 00239 throw(Error, InternalErr) 00240 : d_http(0), d_version("unknown"), d_protocol("2.0") 00241 { 00242 string name = prune_spaces(n); 00243 00244 // Figure out if the URL starts with 'http', if so, make sure that we 00245 // talk to an instance of HTTPConnect. 00246 if (name.find("http") == 0) { 00247 DBG(cerr << "Connect: The identifier is an http URL" << endl); 00248 d_http = new HTTPConnect(RCReader::instance()); 00249 00250 // Find and store any CE given with the URL. 00251 string::size_type dotpos = name.find('?'); 00252 if (dotpos != name.npos) { 00253 _URL = name.substr(0, dotpos); 00254 string expr = name.substr(dotpos + 1); 00255 00256 dotpos = expr.find('&'); 00257 if (dotpos != expr.npos) { 00258 _proj = expr.substr(0, dotpos); 00259 _sel = expr.substr(dotpos); // XXX includes '&' 00260 } 00261 else { 00262 _proj = expr; 00263 _sel = ""; 00264 } 00265 } 00266 else { 00267 _URL = name; 00268 _proj = ""; 00269 _sel = ""; 00270 } 00271 00272 _local = false; 00273 } 00274 else { 00275 DBG(cerr << "Connect: The identifier is a local data source." << endl); 00276 00277 d_http = 0; 00278 _URL = ""; 00279 _local = true; // local in this case means non-DAP 00280 } 00281 00282 set_credentials(uname, password); 00283 } 00284 00285 Connect::~Connect() 00286 { 00287 DBG2(cerr << "Entering the Connect dtor" << endl); 00288 00289 if (d_http) 00290 delete d_http; d_http = 0; 00291 00292 DBG2(cerr << "Leaving the Connect dtor" << endl); 00293 } 00294 00302 string 00303 Connect::request_version() 00304 { 00305 string version_url = _URL + ".ver"; 00306 if (_proj.length() + _sel.length()) 00307 version_url = version_url + "?" + id2www_ce(_proj + _sel); 00308 00309 Response *rs = 0; 00310 try { 00311 rs = d_http->fetch_url(version_url); 00312 } 00313 catch (Error &e) { 00314 delete rs; rs = 0; 00315 throw e; 00316 } 00317 00318 d_version = rs->get_version(); 00319 d_protocol = rs->get_protocol(); 00320 00321 delete rs; rs = 0; 00322 00323 return d_version; 00324 } 00325 00337 string 00338 Connect::request_protocol() 00339 { 00340 string version_url = _URL + ".ver"; 00341 if (_proj.length() + _sel.length()) 00342 version_url = version_url + "?" + id2www_ce(_proj + _sel); 00343 00344 Response *rs = 0; 00345 try { 00346 rs = d_http->fetch_url(version_url); 00347 } 00348 catch (Error &e) { 00349 delete rs; rs = 0; 00350 throw e; 00351 } 00352 00353 d_version = rs->get_version(); 00354 d_protocol = rs->get_protocol(); 00355 00356 delete rs; rs = 0; 00357 00358 return d_protocol; 00359 } 00360 00368 void 00369 Connect::request_das(DAS &das) 00370 { 00371 string das_url = _URL + ".das"; 00372 if (_proj.length() + _sel.length()) 00373 das_url = das_url + "?" + id2www_ce(_proj + _sel); 00374 00375 Response *rs = 0; 00376 try { 00377 rs = d_http->fetch_url(das_url); 00378 } 00379 catch (Error &e) { 00380 delete rs; rs = 0; 00381 throw e; 00382 } 00383 00384 d_version = rs->get_version(); 00385 d_protocol = rs->get_protocol(); 00386 00387 switch (rs->get_type()) { 00388 case dods_error: { 00389 Error e; 00390 if (!e.parse(rs->get_stream())) { 00391 throw InternalErr(__FILE__, __LINE__, 00392 "Could not parse error returned from server."); 00393 break; 00394 } 00395 throw e; 00396 break; 00397 } 00398 00399 case web_error: 00400 // We should never get here; a web error should be picked up read_url 00401 // (called by fetch_url) and result in a thrown Error object. 00402 break; 00403 00404 case dods_das: 00405 default: 00406 // DAS::parse throws an exception on error. 00407 try { 00408 das.parse(rs->get_stream()); // read and parse the das from a file 00409 } 00410 catch (Error &e) { 00411 delete rs; rs = 0; 00412 throw e; 00413 } 00414 00415 break; 00416 } 00417 00418 delete rs; rs = 0; 00419 } 00420 00431 void 00432 Connect::request_das_url(DAS &das) 00433 { 00434 string use_url = _URL + "?" + _proj + _sel ; 00435 Response *rs = 0; 00436 try { 00437 rs = d_http->fetch_url(use_url); 00438 } 00439 catch (Error &e) { 00440 delete rs; rs = 0; 00441 throw e; 00442 } 00443 00444 d_version = rs->get_version(); 00445 d_protocol = rs->get_protocol(); 00446 00447 switch (rs->get_type()) { 00448 case dods_error: { 00449 Error e; 00450 if (!e.parse(rs->get_stream())) { 00451 throw InternalErr(__FILE__, __LINE__, 00452 "Could not parse error returned from server."); 00453 break; 00454 } 00455 throw e; 00456 break; 00457 } 00458 00459 case web_error: 00460 // We should never get here; a web error should be picked up read_url 00461 // (called by fetch_url) and result in a thrown Error object. 00462 break; 00463 00464 case dods_das: 00465 default: 00466 // DAS::parse throws an exception on error. 00467 try { 00468 das.parse(rs->get_stream()); // read and parse the das from a file 00469 } 00470 catch (Error &e) { 00471 delete rs; rs = 0; 00472 throw e; 00473 } 00474 00475 break; 00476 } 00477 00478 delete rs; rs = 0; 00479 } 00480 00494 void 00495 Connect::request_dds(DDS &dds, string expr) 00496 { 00497 string proj, sel; 00498 string::size_type dotpos = expr.find('&'); 00499 if (dotpos != expr.npos) { 00500 proj = expr.substr(0, dotpos); 00501 sel = expr.substr(dotpos); 00502 } 00503 else { 00504 proj = expr; 00505 sel = ""; 00506 } 00507 00508 string dds_url = _URL + ".dds" + "?" 00509 + id2www_ce(_proj + proj + _sel + sel); 00510 00511 Response *rs = 0; 00512 try { 00513 rs = d_http->fetch_url(dds_url); 00514 } 00515 catch (Error &e) { 00516 delete rs; rs = 0; 00517 throw e; 00518 } 00519 00520 d_version = rs->get_version(); 00521 d_protocol = rs->get_protocol(); 00522 00523 switch (rs->get_type()) { 00524 case dods_error: { 00525 Error e; 00526 if (!e.parse(rs->get_stream())) { 00527 throw InternalErr(__FILE__, __LINE__, 00528 "Could not parse error returned from server."); 00529 break; 00530 } 00531 throw e; 00532 break; 00533 } 00534 00535 case web_error: 00536 // We should never get here; a web error should be picked up read_url 00537 // (called by fetch_url) and result in a thrown Error object. 00538 break; 00539 00540 case dods_dds: 00541 default: 00542 // DDS::prase throws an exception on error. 00543 try { 00544 dds.parse(rs->get_stream()); // read and parse the dds from a file 00545 } 00546 catch (Error &e) { 00547 delete rs; rs = 0; 00548 throw e; 00549 } 00550 break; 00551 } 00552 00553 delete rs; rs = 0; 00554 } 00555 00572 void 00573 Connect::request_dds_url(DDS &dds) 00574 { 00575 string use_url = _URL + "?" + _proj + _sel ; 00576 Response *rs = 0; 00577 try { 00578 rs = d_http->fetch_url(use_url); 00579 } 00580 catch (Error &e) { 00581 delete rs; rs = 0; 00582 throw e; 00583 } 00584 00585 d_version = rs->get_version(); 00586 d_protocol = rs->get_protocol(); 00587 00588 switch (rs->get_type()) { 00589 case dods_error: { 00590 Error e; 00591 if (!e.parse(rs->get_stream())) { 00592 throw InternalErr(__FILE__, __LINE__, 00593 "Could not parse error returned from server."); 00594 break; 00595 } 00596 throw e; 00597 break; 00598 } 00599 00600 case web_error: 00601 // We should never get here; a web error should be picked up read_url 00602 // (called by fetch_url) and result in a thrown Error object. 00603 break; 00604 00605 case dods_dds: 00606 default: 00607 // DDS::prase throws an exception on error. 00608 try { 00609 dds.parse(rs->get_stream()); // read and parse the dds from a file 00610 } 00611 catch (Error &e) { 00612 delete rs; rs = 0; 00613 throw e; 00614 } 00615 break; 00616 } 00617 00618 delete rs; rs = 0; 00619 } 00620 00632 void 00633 Connect::request_ddx(DDS &dds, string expr) 00634 { 00635 string proj, sel; 00636 string::size_type dotpos = expr.find('&'); 00637 if (dotpos != expr.npos) { 00638 proj = expr.substr(0, dotpos); 00639 sel = expr.substr(dotpos); 00640 } 00641 else { 00642 proj = expr; 00643 sel = ""; 00644 } 00645 00646 string ddx_url = _URL + ".ddx" + "?" 00647 + id2www_ce(_proj + proj + _sel + sel); 00648 00649 Response *rs = 0; 00650 try { 00651 rs = d_http->fetch_url(ddx_url); 00652 } 00653 catch (Error &e) { 00654 delete rs; rs = 0; 00655 throw e; 00656 } 00657 00658 d_version = rs->get_version(); 00659 d_protocol = rs->get_protocol(); 00660 00661 switch (rs->get_type()) { 00662 case dods_error: { 00663 Error e; 00664 if (!e.parse(rs->get_stream())) { 00665 throw InternalErr(__FILE__, __LINE__, 00666 "Could not parse error returned from server."); 00667 break; 00668 } 00669 throw e; 00670 break; 00671 } 00672 00673 case web_error: 00674 // We should never get here; a web error should be picked up read_url 00675 // (called by fetch_url) and result in a thrown Error object. 00676 break; 00677 00678 case dap4_ddx: 00679 case dods_ddx: 00680 try { 00681 string blob; 00682 00683 DDXParser ddxp(dds.get_factory()); 00684 ddxp.intern_stream(rs->get_stream(), &dds, blob); 00685 } 00686 catch (Error &e) { 00687 delete rs; rs = 0; 00688 throw e; 00689 } 00690 break; 00691 00692 default: 00693 throw Error("The site did not return a valid response (it lacked the\n\ 00694 expected content description header value of 'dap4-ddx' and\n\ 00695 instead returned '" + long_to_string(rs->get_type()) + "').\n\ 00696 This may indicate that the server at the site is not correctly\n\ 00697 configured, or that the URL has changed."); 00698 } 00699 00700 delete rs; rs = 0; 00701 } 00702 00705 void 00706 Connect::request_ddx_url(DDS &dds) 00707 { 00708 string use_url = _URL + "?" + _proj + _sel ; 00709 00710 Response *rs = 0; 00711 try { 00712 rs = d_http->fetch_url(use_url); 00713 } 00714 catch (Error &e) { 00715 delete rs; rs = 0; 00716 throw e; 00717 } 00718 00719 d_version = rs->get_version(); 00720 d_protocol = rs->get_protocol(); 00721 00722 switch (rs->get_type()) { 00723 case dods_error: { 00724 Error e; 00725 if (!e.parse(rs->get_stream())) { 00726 throw InternalErr(__FILE__, __LINE__, 00727 "Could not parse error returned from server."); 00728 break; 00729 } 00730 throw e; 00731 break; 00732 } 00733 00734 case web_error: 00735 // We should never get here; a web error should be picked up read_url 00736 // (called by fetch_url) and result in a thrown Error object. 00737 break; 00738 00739 case dap4_ddx: 00740 case dods_ddx: 00741 try { 00742 string blob; 00743 00744 DDXParser ddxp(dds.get_factory()); 00745 ddxp.intern_stream(rs->get_stream(), &dds, blob); 00746 } 00747 catch (Error &e) { 00748 delete rs; rs = 0; 00749 throw e; 00750 } 00751 break; 00752 00753 default: 00754 throw Error("The site did not return a valid response (it lacked the\n\ 00755 expected content description header value of 'dap4-ddx' and\n\ 00756 instead returned '" + long_to_string(rs->get_type()) + "').\n\ 00757 This may indicate that the server at the site is not correctly\n\ 00758 configured, or that the URL has changed."); 00759 } 00760 00761 delete rs; rs = 0; 00762 } 00763 00779 void 00780 Connect::request_data(DataDDS &data, string expr) 00781 { 00782 string proj, sel; 00783 string::size_type dotpos = expr.find('&'); 00784 if (dotpos != expr.npos) { 00785 proj = expr.substr(0, dotpos); 00786 sel = expr.substr(dotpos); 00787 } 00788 else { 00789 proj = expr; 00790 sel = ""; 00791 } 00792 00793 string data_url = _URL + ".dods?" 00794 + id2www_ce(_proj + proj + _sel + sel); 00795 00796 Response *rs = 0; 00797 // We need to catch Error exceptions to ensure calling close_output. 00798 try { 00799 rs = d_http->fetch_url(data_url); 00800 00801 d_version = rs->get_version(); 00802 d_protocol = rs->get_protocol(); 00803 00804 process_data(data, rs); 00805 delete rs; rs = 0; 00806 } 00807 catch (Error &e) { 00808 delete rs; rs = 0; 00809 throw e; 00810 } 00811 } 00812 00830 void 00831 Connect::request_data_url(DataDDS &data) 00832 { 00833 string use_url = _URL + "?" + _proj + _sel ; 00834 Response *rs = 0; 00835 // We need to catch Error exceptions to ensure calling close_output. 00836 try { 00837 rs = d_http->fetch_url(use_url); 00838 00839 d_version = rs->get_version(); 00840 d_protocol = rs->get_protocol(); 00841 00842 process_data(data, rs); 00843 delete rs; rs = 0; 00844 } 00845 catch (Error &e) { 00846 delete rs; rs = 0; 00847 throw e; 00848 } 00849 } 00850 00851 void 00852 Connect::request_data_ddx(DataDDS &data, string expr) 00853 { 00854 string proj, sel; 00855 string::size_type dotpos = expr.find('&'); 00856 if (dotpos != expr.npos) { 00857 proj = expr.substr(0, dotpos); 00858 sel = expr.substr(dotpos); 00859 } 00860 else { 00861 proj = expr; 00862 sel = ""; 00863 } 00864 00865 string data_url = _URL + ".dap?" 00866 + id2www_ce(_proj + proj + _sel + sel); 00867 00868 Response *rs = 0; 00869 // We need to catch Error exceptions to ensure calling close_output. 00870 try { 00871 rs = d_http->fetch_url(data_url); 00872 00873 d_version = rs->get_version(); 00874 d_protocol = rs->get_protocol(); 00875 00876 process_data(data, rs); 00877 delete rs; rs = 0; 00878 } 00879 catch (Error &e) { 00880 delete rs; rs = 0; 00881 throw e; 00882 } 00883 } 00884 00885 void 00886 Connect::request_data_ddx_url(DataDDS &data) 00887 { 00888 string use_url = _URL + "?" + _proj + _sel ; 00889 Response *rs = 0; 00890 // We need to catch Error exceptions to ensure calling close_output. 00891 try { 00892 rs = d_http->fetch_url(use_url); 00893 00894 d_version = rs->get_version(); 00895 d_protocol = rs->get_protocol(); 00896 00897 process_data(data, rs); 00898 delete rs; rs = 0; 00899 } 00900 catch (Error &e) { 00901 delete rs; rs = 0; 00902 throw e; 00903 } 00904 } 00905 00919 void 00920 Connect::read_data(DataDDS &data, Response *rs) 00921 { 00922 if (!rs) 00923 throw InternalErr(__FILE__, __LINE__, "Response object is null."); 00924 00925 // Read from data_source and parse the MIME headers specific to DAP2/4. 00926 parse_mime(rs); 00927 00928 read_data_no_mime(data, rs); 00929 } 00930 00931 // This function looks at the input stream and makes its best guess at what 00932 // lies in store for downstream processing code. Definitely heuristic. 00933 // Assumptions: 00934 // #1 The current file position is past any MIME headers (if they were present). 00935 // #2 We must reset the FILE* position to the start of the DDS or DDX headers 00936 static void 00937 divine_type_information(Response *rs) 00938 { 00939 // Consume whitespace 00940 char c = getc(rs->get_stream()); 00941 while (isspace(c)) { 00942 c = getc(rs->get_stream()); 00943 } 00944 00945 // The heuristic here is that a DataDDX is a multipart MIME document and 00946 // The first non space character found after the headers is the start of 00947 // the first part which looks like '--<boundary>' while a DataDDS starts 00948 // with a DDS (;Dataset {' ...). I take into account that our parsers have 00949 // accepted both 'Dataset' and 'dataset' for a long time. 00950 switch (c) { 00951 case '-': 00952 rs->set_type(dap4_data_ddx); 00953 break; 00954 case 'D': 00955 case 'd': 00956 rs->set_type(dods_data); 00957 break; 00958 default: 00959 throw InternalErr(__FILE__, __LINE__, "Could not determine type of response object in stream."); 00960 } 00961 00962 ungetc(c, rs->get_stream()); 00963 } 00964 00977 void 00978 Connect::read_data_no_mime(DataDDS &data, Response *rs) 00979 { 00980 if (rs->get_type() == unknown_type) 00981 divine_type_information(rs); 00982 00983 switch (rs->get_type()) { 00984 case dods_data: 00985 d_version = rs->get_version(); 00986 d_protocol = rs->get_protocol(); 00987 process_data(data, rs); 00988 break; 00989 case dap4_data_ddx: 00990 process_data(data, rs); 00991 d_version = rs->get_version(); 00992 d_protocol = data.get_protocol(); 00993 break; 00994 default: 00995 throw InternalErr(__FILE__, __LINE__, "Should have been a DataDDS or DataDDX."); 00996 } 00997 } 00998 00999 bool 01000 Connect::is_local() 01001 { 01002 return _local; 01003 } 01004 01021 string 01022 Connect::URL(bool ce) 01023 { 01024 if (_local) 01025 throw InternalErr(__FILE__, __LINE__, 01026 "URL(): This call is only valid for a DAP data source."); 01027 01028 if (ce) 01029 return _URL + "?" + _proj + _sel; 01030 else 01031 return _URL; 01032 } 01033 01042 string 01043 Connect::CE() 01044 { 01045 if (_local) 01046 throw InternalErr(__FILE__, __LINE__, 01047 "CE(): This call is only valid for a DAP data source."); 01048 01049 return _proj + _sel; 01050 } 01051 01057 void 01058 Connect::set_credentials(string u, string p) 01059 { 01060 if (d_http) 01061 d_http->set_credentials(u, p); 01062 } 01063 01067 void 01068 Connect::set_accept_deflate(bool deflate) 01069 { 01070 if (d_http) 01071 d_http->set_accept_deflate(deflate); 01072 } 01073 01079 void 01080 Connect::set_xdap_protocol(int major, int minor) 01081 { 01082 if (d_http) 01083 d_http->set_xdap_protocol(major, minor); 01084 } 01085 01089 void 01090 Connect::set_cache_enabled(bool cache) 01091 { 01092 if (d_http) 01093 d_http->set_cache_enabled(cache); 01094 } 01095 01096 bool 01097 Connect::is_cache_enabled() 01098 { 01099 bool status; 01100 DBG(cerr << "Entering is_cache_enabled (" << hex << d_http << dec 01101 << ")... "); 01102 if (d_http) 01103 status = d_http->is_cache_enabled(); 01104 else 01105 status = false; 01106 DBGN(cerr << "exiting" << endl); 01107 return status; 01108 } 01109 01110 } // namespace libdap