libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
Connect.cc
Go to the documentation of this file.
1// -*- mode: c++; c-basic-offset:4 -*-
2
3// This file is part of libdap, A C++ implementation of the OPeNDAP Data
4// Access Protocol.
5
6// Copyright (c) 2002,2003 OPeNDAP, Inc.
7// Author: James Gallagher <jgallagher@opendap.org>
8// Dan Holloway <dholloway@gso.uri.edu>
9// Reza Nekovei <reza@intcomm.net>
10//
11// This library is free software; you can redistribute it and/or
12// modify it under the terms of the GNU Lesser General Public
13// License as published by the Free Software Foundation; either
14// version 2.1 of the License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19// Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public
22// License along with this library; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24//
25// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26
27// (c) COPYRIGHT URI/MIT 1994-2002
28// Please read the full copyright statement in the file COPYRIGHT_URI.
29//
30// Authors:
31// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
32// dan Dan Holloway <dholloway@gso.uri.edu>
33// reza Reza Nekovei <reza@intcomm.net>
34
35#include "config.h"
36
37// #define DODS_DEBUG
38#define FILE_UN_MARSHALLER 1
39
40#include <cerrno>
41#include <cstring>
42
43#include <algorithm>
44#include <fstream>
45
46#include "Connect.h"
47#include "DDXParserSAX2.h"
48#include "DataDDS.h"
49#include "HTTPResponse.h"
50#include "RCReader.h"
51#include "debug.h"
52#include "escaping.h"
53#if FILE_UN_MARSHALLER
54#include "XDRFileUnMarshaller.h"
55#else
57#include "fdiostream.h"
58#endif
59#include "mime_util.h"
60
61using std::cerr;
62using std::endl;
63using std::ifstream;
64using std::min;
65using std::ofstream;
66
67namespace libdap {
68
71void Connect::process_data(DataDDS &data, Response *rs) {
72 DBG(cerr << "Entering Connect::process_data" << endl);
73
74 data.set_version(rs->get_version());
75 data.set_protocol(rs->get_protocol());
76
77 DBG(cerr << "Entering process_data: d_stream = " << rs << endl);
78 switch (rs->get_type()) {
79 case dods_error: {
80 Error e;
81 if (!e.parse(rs->get_stream()))
82 throw InternalErr(__FILE__, __LINE__, "Could not parse the Error object returned by the server!");
83 throw e;
84 }
85
86 case web_error:
87 // Web errors (those reported in the return document's MIME header)
88 // are processed by the WWW library.
89 throw InternalErr(
90 __FILE__, __LINE__,
91 "An error was reported by the remote httpd; this should have been processed by HTTPConnect..");
92
93#if 0
94 // This code triggers a security warning from Coverity; since it is not used,
95 // I have removed it. jhrg 5/5/16
96 case dods_data_ddx: {
97 // Parse the DDX; throw an exception on error.
98 DDXParser ddx_parser(data.get_factory());
99
100 // Read the MPM boundary and then read the subsequent headers
101 string boundary = read_multipart_boundary(rs->get_stream());
102 DBG(cerr << "MPM Boundary: " << boundary << endl);
103 read_multipart_headers(rs->get_stream(), "text/xml", dods_ddx);
104
105 // Parse the DDX, reading up to and including the next boundary.
106 // Return the CID for the matching data part
107 string data_cid;
108 ddx_parser.intern_stream(rs->get_stream(), &data, data_cid, boundary);
109
110 // Munge the CID into something we can work with
111 data_cid = cid_to_header_value(data_cid);
112 DBG(cerr << "Data CID: " << data_cid << endl);
113
114 // Read the data part's MPM part headers (boundary was read by
115 // DDXParse::intern)
116 read_multipart_headers(rs->get_stream(), "application/octet-stream", dap4_data, data_cid);
117
118 // Now read the data
119#if FILE_UN_MARSHALLER
120 XDRFileUnMarshaller um(rs->get_stream());
121#else
122 fpistream in ( rs->get_stream() );
123 XDRStreamUnMarshaller um( in );
124#endif
125 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
126 (*i)->deserialize(um, &data);
127 }
128 return;
129 }
130#endif
131
132 case dods_data:
133 default: {
134 // Parse the DDS; throw an exception on error.
135 data.parse(rs->get_stream());
136#if FILE_UN_MARSHALLER
137 XDRFileUnMarshaller um(rs->get_stream());
138#else
139 fpistream in(rs->get_stream());
140 XDRStreamUnMarshaller um(in);
141#endif
142 // Load the DDS with data.
143 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
144 (*i)->deserialize(um, &data);
145 }
146 return;
147 }
148 }
149}
150
153void Connect::process_data(DDS &data, Response *rs) {
154 DBG(cerr << "Entering Connect::process_data" << endl);
155
156 data.set_dap_version(rs->get_protocol());
157
158 DBG(cerr << "Entering process_data: d_stream = " << rs << endl);
159 switch (rs->get_type()) {
160 case dods_error: {
161 Error e;
162 if (!e.parse(rs->get_stream()))
163 throw InternalErr(__FILE__, __LINE__, "Could not parse the Error object returned by the server!");
164 throw e;
165 }
166
167 case web_error:
168 // Web errors (those reported in the return document's MIME header)
169 // are processed by the WWW library.
170 throw InternalErr(
171 __FILE__, __LINE__,
172 "An error was reported by the remote web server; this should have been processed by HTTPConnect.");
173
174#if 0
175 // FIXME: The following case is never used. There is no such response. jhrg 10/20/15
176 // This code triggers a security warning from Coverity; since it is not used,
177 // I have removed it. jhrg 5/5/16
178 case dods_data_ddx: {
179 // Parse the DDX; throw an exception on error.
180 DDXParser ddx_parser(data.get_factory());
181
182 // Read the MPM boundary and then read the subsequent headers
183 string boundary = read_multipart_boundary(rs->get_stream());
184 DBG(cerr << "MPM Boundary: " << boundary << endl);
185 read_multipart_headers(rs->get_stream(), "text/xml", dods_ddx);
186
187 // Parse the DDX, reading up to and including the next boundary.
188 // Return the CID for the matching data part
189 string data_cid;
190 ddx_parser.intern_stream(rs->get_stream(), &data, data_cid, boundary);
191
192 // Munge the CID into something we can work with
193 data_cid = cid_to_header_value(data_cid);
194 DBG(cerr << "Data CID: " << data_cid << endl);
195
196 // Read the data part's MPM part headers (boundary was read by
197 // DDXParse::intern)
198 read_multipart_headers(rs->get_stream(), "application/octet-stream", dap4_data, data_cid);
199
200 // Now read the data
201 XDRFileUnMarshaller um(rs->get_stream());
202 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
203 (*i)->deserialize(um, &data);
204 }
205 return;
206 }
207#endif
208
209 case dods_data:
210 default: {
211 // Parse the DDS; throw an exception on error.
212 data.parse(rs->get_stream());
213
214 XDRFileUnMarshaller um(rs->get_stream());
215
216 // Load the DDS with data.
217 for (DDS::Vars_iter i = data.var_begin(); i != data.var_end(); i++) {
218 (*i)->deserialize(um, &data);
219 }
220
221 return;
222 }
223 }
224}
225
226// Barely a parser... This is used when reading from local sources of DODS
227// Data objects. It simulates the important actions of the libwww MIME header
228// parser. Those actions fill in certain fields in the Connect object. jhrg
229// 5/20/97
230//
231// Make sure that this parser reads from data_source without disturbing the
232// information in data_source that follows the MIME header. Since the DDS
233// (which follows the MIME header) is parsed by a flex/bison scanner/parser,
234// make sure to use I/O calls that will mesh with ANSI C I/O calls. In the
235// old GNU libg++, the C++ calls were synchronized with the C calls, but that
236// may no longer be the case. 5/31/99 jhrg
237
250void Connect::parse_mime(Response *rs) {
251 rs->set_version("dods/0.0"); // initial value; for backward compatibility.
252 rs->set_protocol("2.0");
253
254 FILE *data_source = rs->get_stream();
255 string mime = get_next_mime_header(data_source);
256 while (!mime.empty()) {
257 string header, value;
258 parse_mime_header(mime, header, value);
259
260 // Note that this is an ordered list
261 if (header == "content-description:") {
262 DBG(cout << header << ": " << value << endl);
263 rs->set_type(get_description_type(value));
264 }
265 // Use the value of xdods-server only if no other value has been read
266 else if (header == "xdods-server:" && rs->get_version() == "dods/0.0") {
267 DBG(cout << header << ": " << value << endl);
268 rs->set_version(value);
269 }
270 // This trumps 'xdods-server' and 'server'
271 else if (header == "xopendap-server:") {
272 DBG(cout << header << ": " << value << endl);
273 rs->set_version(value);
274 } else if (header == "xdap:") {
275 DBG(cout << header << ": " << value << endl);
276 rs->set_protocol(value);
277 }
278 // Only look for 'server' if no other header supplies this info.
279 else if (rs->get_version() == "dods/0.0" && header == "server:") {
280 DBG(cout << header << ": " << value << endl);
281 rs->set_version(value);
282 }
283
284 mime = get_next_mime_header(data_source);
285 }
286}
287
288// public mfuncs
289
297Connect::Connect(const string &n, string uname, string password) : d_http(0), d_version("unknown"), d_protocol("2.0") {
298 string name = prune_spaces(n);
299
300 // Figure out if the URL starts with 'http', if so, make sure that we
301 // talk to an instance of HTTPConnect.
302 if (name.find("http") == 0) {
303 DBG(cerr << "Connect: The identifier is an http URL" << endl);
304 d_http = new HTTPConnect(RCReader::instance());
305
306 // Find and store any CE given with the URL.
307 string::size_type dotpos = name.find('?');
308 if (dotpos != name.npos) {
309 _URL = name.substr(0, dotpos);
310 string expr = name.substr(dotpos + 1);
311
312 dotpos = expr.find('&');
313 if (dotpos != expr.npos) {
314 _proj = expr.substr(0, dotpos);
315 _sel = expr.substr(dotpos); // XXX includes '&'
316 } else {
317 _proj = expr;
318 _sel = "";
319 }
320 } else {
321 _URL = name;
322 _proj = "";
323 _sel = "";
324 }
325
326 _local = false;
327 } else {
328 DBG(cerr << "Connect: The identifier is a local data source." << endl);
329
330 d_http = 0;
331 _URL = "";
332 _local = true; // local in this case means non-DAP
333 }
334
335 set_credentials(uname, password);
336}
337
339 DBG2(cerr << "Entering the Connect dtor" << endl);
340
341 if (d_http)
342 delete d_http;
343 d_http = 0;
344
345 DBG2(cerr << "Leaving the Connect dtor" << endl);
346}
347
356 string version_url = _URL + ".ver";
357 if (_proj.length() + _sel.length())
358 version_url = version_url + "?" + id2www_ce(_proj + _sel);
359
360 Response *rs = 0;
361 try {
362 rs = d_http->fetch_url(version_url);
363 } catch (Error &e) {
364 delete rs;
365 rs = 0;
366 throw;
367 }
368
369 d_version = rs->get_version();
370 d_protocol = rs->get_protocol();
371
372 delete rs;
373 rs = 0;
374
375 return d_version;
376}
377
390 string version_url = _URL + ".ver";
391 if (_proj.length() + _sel.length())
392 version_url = version_url + "?" + id2www_ce(_proj + _sel);
393
394 Response *rs = 0;
395 try {
396 rs = d_http->fetch_url(version_url);
397 } catch (Error &e) {
398 delete rs;
399 rs = 0;
400 throw;
401 }
402
403 d_version = rs->get_version();
404 d_protocol = rs->get_protocol();
405
406 delete rs;
407 rs = 0;
408
409 return d_protocol;
410}
411
420 string das_url = _URL + ".das";
421 if (_proj.length() + _sel.length())
422 das_url = das_url + "?" + id2www_ce(_proj + _sel);
423
424 Response *rs = 0;
425 try {
426 rs = d_http->fetch_url(das_url);
427 } catch (Error &e) {
428 delete rs;
429 rs = 0;
430 throw;
431 }
432
433 d_version = rs->get_version();
434 d_protocol = rs->get_protocol();
435
436 switch (rs->get_type()) {
437 case dods_error: {
438 Error e;
439 if (!e.parse(rs->get_stream())) {
440 delete rs;
441 rs = 0;
442 throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
443 }
444 delete rs;
445 rs = 0;
446 throw e;
447 }
448
449 case web_error:
450 // We should never get here; a web error should be picked up read_url
451 // (called by fetch_url) and result in a thrown Error object.
452 break;
453
454 case dods_das:
455 default:
456 // DAS::parse throws an exception on error.
457 try {
458 das.parse(rs->get_stream()); // read and parse the das from a file
459 } catch (Error &e) {
460 delete rs;
461 rs = 0;
462 throw;
463 }
464
465 break;
466 }
467
468 delete rs;
469 rs = 0;
470}
471
483 string use_url = _URL + "?" + _proj + _sel;
484 Response *rs = 0;
485 try {
486 rs = d_http->fetch_url(use_url);
487 } catch (Error &e) {
488 delete rs;
489 rs = 0;
490 throw;
491 }
492
493 d_version = rs->get_version();
494 d_protocol = rs->get_protocol();
495
496 switch (rs->get_type()) {
497 case dods_error: {
498 Error e;
499 if (!e.parse(rs->get_stream())) {
500 delete rs;
501 rs = 0;
502 throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
503 }
504 delete rs;
505 rs = 0;
506 throw e;
507 }
508
509 case web_error:
510 // We should never get here; a web error should be picked up read_url
511 // (called by fetch_url) and result in a thrown Error object.
512 break;
513
514 case dods_das:
515 default:
516 // DAS::parse throws an exception on error.
517 try {
518 das.parse(rs->get_stream()); // read and parse the das from a file
519 } catch (Error &e) {
520 delete rs;
521 rs = 0;
522 throw;
523 }
524
525 break;
526 }
527
528 delete rs;
529 rs = 0;
530}
531
545void Connect::request_dds(DDS &dds, string expr) {
546 string proj, sel;
547 string::size_type dotpos = expr.find('&');
548 if (dotpos != expr.npos) {
549 proj = expr.substr(0, dotpos);
550 sel = expr.substr(dotpos);
551 } else {
552 proj = expr;
553 sel = "";
554 }
555
556 string dds_url = _URL + ".dds" + "?" + id2www_ce(_proj + proj + _sel + sel);
557
558 Response *rs = 0;
559 try {
560 rs = d_http->fetch_url(dds_url);
561 } catch (Error &e) {
562 delete rs;
563 rs = 0;
564 throw;
565 }
566
567 d_version = rs->get_version();
568 d_protocol = rs->get_protocol();
569
570 switch (rs->get_type()) {
571 case dods_error: {
572 Error e;
573 if (!e.parse(rs->get_stream())) {
574 delete rs;
575 rs = 0;
576 throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
577 }
578 delete rs;
579 rs = 0;
580 throw e;
581 }
582
583 case web_error:
584 // We should never get here; a web error should be picked up read_url
585 // (called by fetch_url) and result in a thrown Error object.
586 break;
587
588 case dods_dds:
589 default:
590 // DDS::prase throws an exception on error.
591 try {
592 dds.parse(rs->get_stream()); // read and parse the dds from a file
593 } catch (Error &e) {
594 delete rs;
595 rs = 0;
596 throw;
597 }
598 break;
599 }
600
601 delete rs;
602 rs = 0;
603}
604
622 string use_url = _URL + "?" + _proj + _sel;
623 Response *rs = 0;
624 try {
625 rs = d_http->fetch_url(use_url);
626 } catch (Error &e) {
627 delete rs;
628 rs = 0;
629 throw;
630 }
631
632 d_version = rs->get_version();
633 d_protocol = rs->get_protocol();
634
635 switch (rs->get_type()) {
636 case dods_error: {
637 Error e;
638 if (!e.parse(rs->get_stream())) {
639 delete rs;
640 rs = 0;
641 throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
642 }
643 delete rs;
644 rs = 0;
645 throw e;
646 }
647
648 case web_error:
649 // We should never get here; a web error should be picked up read_url
650 // (called by fetch_url) and result in a thrown Error object.
651 break;
652
653 case dods_dds:
654 default:
655 // DDS::prase throws an exception on error.
656 try {
657 dds.parse(rs->get_stream()); // read and parse the dds from a file
658 } catch (Error &e) {
659 delete rs;
660 rs = 0;
661 throw;
662 }
663 break;
664 }
665
666 delete rs;
667 rs = 0;
668}
669
681void Connect::request_ddx(DDS &dds, string expr) {
682 string proj, sel;
683 string::size_type dotpos = expr.find('&');
684 if (dotpos != expr.npos) {
685 proj = expr.substr(0, dotpos);
686 sel = expr.substr(dotpos);
687 } else {
688 proj = expr;
689 sel = "";
690 }
691
692 string ddx_url = _URL + ".ddx" + "?" + id2www_ce(_proj + proj + _sel + sel);
693
694 Response *rs = 0;
695 try {
696 rs = d_http->fetch_url(ddx_url);
697 } catch (Error &e) {
698 delete rs;
699 throw;
700 }
701
702 d_version = rs->get_version();
703 d_protocol = rs->get_protocol();
704
705 switch (rs->get_type()) {
706 case dods_error: {
707 Error e;
708 if (!e.parse(rs->get_stream())) {
709 delete rs;
710 rs = 0;
711 throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
712 }
713 delete rs;
714 throw e;
715 }
716
717 case web_error:
718 // We should never get here; a web error should be picked up read_url
719 // (called by fetch_url) and result in a thrown Error object.
720 break;
721
722 case dods_ddx:
723 try {
724 string blob;
725
726 DDXParser ddxp(dds.get_factory());
727 ddxp.intern_stream(rs->get_stream(), &dds, blob);
728 } catch (Error &e) {
729 delete rs;
730 throw;
731 }
732 break;
733
734 default:
735 ObjectType ot = rs->get_type();
736 delete rs;
737 throw Error("Invalid response type when requesting a DDX response. Response type: " + long_to_string(ot));
738 }
739
740 delete rs;
741}
742
746 string use_url = _URL + "?" + _proj + _sel;
747
748 Response *rs = 0;
749 try {
750 rs = d_http->fetch_url(use_url);
751 } catch (Error &e) {
752 delete rs;
753 throw;
754 }
755
756 d_version = rs->get_version();
757 d_protocol = rs->get_protocol();
758
759 switch (rs->get_type()) {
760 case dods_error: {
761 Error e;
762 if (!e.parse(rs->get_stream())) {
763 delete rs;
764 throw InternalErr(__FILE__, __LINE__, "Could not parse error returned from server.");
765 }
766 delete rs;
767 throw e;
768 }
769
770 case web_error:
771 // We should never get here; a web error should be picked up read_url
772 // (called by fetch_url) and result in a thrown Error object.
773 delete rs;
774 throw InternalErr(__FILE__, __LINE__, "Web error.");
775
776 case dods_ddx:
777 try {
778 string blob;
779
780 DDXParser ddxp(dds.get_factory());
781 ddxp.intern_stream(rs->get_stream(), &dds, blob);
782 } catch (Error &e) {
783 delete rs;
784 throw;
785 }
786 break;
787
788 default: {
789 ObjectType ot = rs->get_type();
790 delete rs;
791
792 throw Error("Invalid response type when requesting a DDX response. Response type: " + long_to_string(ot));
793 }
794 }
795
796 delete rs;
797}
798
814void Connect::request_data(DataDDS &data, string expr) {
815 string proj, sel;
816 string::size_type dotpos = expr.find('&');
817 if (dotpos != expr.npos) {
818 proj = expr.substr(0, dotpos);
819 sel = expr.substr(dotpos);
820 } else {
821 proj = expr;
822 sel = "";
823 }
824
825 string data_url = _URL + ".dods?" + id2www_ce(_proj + proj + _sel + sel);
826
827 Response *rs = 0;
828 // We need to catch Error exceptions to ensure calling close_output.
829 try {
830 rs = d_http->fetch_url(data_url);
831
832 d_version = rs->get_version();
833 d_protocol = rs->get_protocol();
834
835 process_data(data, rs);
836 delete rs;
837 rs = 0;
838 } catch (Error &e) {
839 delete rs;
840 rs = 0;
841 throw;
842 }
843}
844
863 string use_url = _URL + "?" + _proj + _sel;
864 Response *rs = 0;
865 // We need to catch Error exceptions to ensure calling close_output.
866 try {
867 rs = d_http->fetch_url(use_url);
868
869 d_version = rs->get_version();
870 d_protocol = rs->get_protocol();
871
872 process_data(data, rs);
873 delete rs;
874 rs = 0;
875 } catch (Error &e) {
876 delete rs;
877 rs = 0;
878 throw;
879 }
880}
881
882// FIXME Unused?
883void Connect::request_data_ddx(DataDDS &data, string expr) {
884 string proj, sel;
885 string::size_type dotpos = expr.find('&');
886 if (dotpos != expr.npos) {
887 proj = expr.substr(0, dotpos);
888 sel = expr.substr(dotpos);
889 } else {
890 proj = expr;
891 sel = "";
892 }
893
894 string data_url = _URL + ".dap?" + id2www_ce(_proj + proj + _sel + sel);
895
896 Response *rs = 0;
897 // We need to catch Error exceptions to ensure calling close_output.
898 try {
899 rs = d_http->fetch_url(data_url);
900
901 d_version = rs->get_version();
902 d_protocol = rs->get_protocol();
903
904 process_data(data, rs);
905 delete rs;
906 rs = 0;
907 } catch (Error &e) {
908 delete rs;
909 rs = 0;
910 throw;
911 }
912}
913
914// FIXME Unused?
916 string use_url = _URL + "?" + _proj + _sel;
917 Response *rs = 0;
918 // We need to catch Error exceptions to ensure calling close_output.
919 try {
920 rs = d_http->fetch_url(use_url);
921
922 d_version = rs->get_version();
923 d_protocol = rs->get_protocol();
924
925 process_data(data, rs);
926 delete rs;
927 rs = 0;
928 } catch (Error &e) {
929 delete rs;
930 rs = 0;
931 throw;
932 }
933}
934
947
949 if (!rs)
950 throw InternalErr(__FILE__, __LINE__, "Response object is null.");
951
952 // Read from data_source and parse the MIME headers specific to DAP2/4.
953 parse_mime(rs);
954
955 read_data_no_mime(data, rs);
956}
958 if (!rs)
959 throw InternalErr(__FILE__, __LINE__, "Response object is null.");
960
961 // Read from data_source and parse the MIME headers specific to DAP2/4.
962 parse_mime(rs);
963
964 read_data_no_mime(data, rs);
965}
966
967// This function looks at the input stream and makes its best guess at what
968// lies in store for downstream processing code. Definitely heuristic.
969// Assumptions:
970// #1 The current file position is past any MIME headers (if they were present).
971// #2 We must reset the FILE* position to the start of the DDS or DDX headers
972static void divine_type_information(Response *rs) {
973 // Consume whitespace
974 int c = getc(rs->get_stream());
975 while (!feof(rs->get_stream()) && !ferror(rs->get_stream()) && isspace(c)) {
976 c = getc(rs->get_stream());
977 }
978
979 if (ferror(rs->get_stream()))
980 throw Error("Error reading response type information: " + string(strerror(errno)));
981 if (feof(rs->get_stream()))
982 throw Error("Error reading response type information: Found EOF");
983
984 // The heuristic here is that a DataDDX is a multipart MIME document and
985 // The first non space character found after the headers is the start of
986 // the first part which looks like '--<boundary>' while a DataDDS starts
987 // with a DDS (;Dataset {' ...). I take into account that our parsers have
988 // accepted both 'Dataset' and 'dataset' for a long time.
989 switch (c) {
990 case '-':
992 break;
993 case 'D':
994 case 'd':
995 rs->set_type(dods_data);
996 break;
997 default:
998 throw InternalErr(__FILE__, __LINE__, "Could not determine type of response object in stream.");
999 }
1000
1001 ungetc(c, rs->get_stream());
1002}
1003
1017 if (rs->get_type() == unknown_type)
1018 divine_type_information(rs);
1019
1020 switch (rs->get_type()) {
1021 case dods_data:
1022 d_version = rs->get_version();
1023 d_protocol = rs->get_protocol();
1024 process_data(data, rs);
1025 break;
1026 case dods_data_ddx:
1027 process_data(data, rs);
1028 d_version = rs->get_version();
1029 d_protocol = data.get_protocol();
1030 break;
1031 default:
1032 throw InternalErr(__FILE__, __LINE__, "Should have been a DataDDS or DataDDX.");
1033 }
1034}
1036 if (rs->get_type() == unknown_type)
1037 divine_type_information(rs);
1038
1039 switch (rs->get_type()) {
1040 case dods_data:
1041 d_version = rs->get_version();
1042 d_protocol = rs->get_protocol();
1043 process_data(data, rs);
1044 break;
1045 case dods_data_ddx:
1046 process_data(data, rs);
1047 d_version = rs->get_version();
1048 // TODO should check to see if this hack is a correct replacement
1049 // for get_protocol from DataDDS
1050 d_protocol = data.get_dap_version();
1051 break;
1052 default:
1053 throw InternalErr(__FILE__, __LINE__, "Should have been a DataDDS or DataDDX.");
1054 }
1055}
1056
1057bool Connect::is_local() { return _local; }
1058
1075string Connect::URL(bool ce) {
1076 if (_local)
1077 throw InternalErr(__FILE__, __LINE__, "URL(): This call is only valid for a DAP data source.");
1078
1079 if (ce)
1080 return _URL + "?" + _proj + _sel;
1081 else
1082 return _URL;
1083}
1084
1093string Connect::CE() {
1094 if (_local)
1095 throw InternalErr(__FILE__, __LINE__, "CE(): This call is only valid for a DAP data source.");
1096
1097 return _proj + _sel;
1098}
1099
1105void Connect::set_credentials(string u, string p) {
1106 if (d_http)
1107 d_http->set_credentials(u, p);
1108}
1109
1114 if (d_http)
1115 d_http->set_accept_deflate(deflate);
1116}
1117
1123void Connect::set_xdap_protocol(int major, int minor) {
1124 if (d_http)
1125 d_http->set_xdap_protocol(major, minor);
1126}
1127
1132 if (d_http)
1133 d_http->set_cache_enabled(cache);
1134}
1135
1137 bool status;
1138 DBG(cerr << "Entering is_cache_enabled (" << hex << d_http << dec << ")... ");
1139 if (d_http)
1140 status = d_http->is_cache_enabled();
1141 else
1142 status = false;
1143 DBGN(cerr << "exiting" << endl);
1144 return status;
1145}
1146
1147} // namespace libdap
bool is_cache_enabled()
Definition Connect.cc:1136
virtual void request_dds_url(DDS &dds)
Get the DDS from a server.
Definition Connect.cc:621
virtual string CE()
Get the Connect's constraint expression.
Definition Connect.cc:1093
void set_accept_deflate(bool deflate)
Definition Connect.cc:1113
void set_cache_enabled(bool enabled)
Definition Connect.cc:1131
virtual void request_ddx(DDS &dds, string expr="")
Get the DDX from a server.
Definition Connect.cc:681
virtual void read_data_no_mime(DataDDS &data, Response *rs)
Read data from a file which does not have response MIME headers. This method is a companion to read_d...
Definition Connect.cc:1016
void set_xdap_protocol(int major, int minor)
Definition Connect.cc:1123
virtual string URL(bool CE=true)
Get the object's URL.
Definition Connect.cc:1075
virtual void request_data(DataDDS &data, string expr="")
Get the DAS from a server.
Definition Connect.cc:814
virtual void request_das(DAS &das)
Get the DAS from a server.
Definition Connect.cc:419
void set_credentials(string u, string p)
Set the credentials for responding to challenges while dereferencing URLs.
Definition Connect.cc:1105
virtual void request_ddx_url(DDS &dds)
The 'url' version of request_ddx.
Definition Connect.cc:745
virtual string request_protocol()
Definition Connect.cc:389
virtual void request_data_ddx_url(DataDDS &data)
Definition Connect.cc:915
virtual void request_dds(DDS &dds, string expr="")
Get the DDS from a server.
Definition Connect.cc:545
virtual void request_data_ddx(DataDDS &data, string expr="")
Definition Connect.cc:883
virtual void request_das_url(DAS &das)
Get the DAS from a server.
Definition Connect.cc:482
virtual string request_version()
Definition Connect.cc:355
virtual void request_data_url(DataDDS &data)
Get the DAS from a server.
Definition Connect.cc:862
virtual ~Connect()
Definition Connect.cc:338
virtual void read_data(DataDDS &data, Response *rs)
Read data which is preceded by MIME headers. This method works for both data dds and data ddx respons...
Definition Connect.cc:948
Hold attribute data for a DAP2 dataset.
Definition DAS.h:119
virtual void parse(string fname)
Reads a DAS from the named file.
Definition DAS.cc:213
string get_dap_version() const
Definition DDS.h:256
void parse(string fname)
Parse a DDS from a file with the given d_name.
Definition DDS.cc:740
BaseTypeFactory * get_factory() const
Definition DDS.h:231
std::vector< BaseType * >::iterator Vars_iter
Definition DDS.h:211
void intern_stream(FILE *in, DDS *dds, string &cid, const string &boundary="")
Read the DDX from a stream instead of a file.
Holds a DAP2 DDS.
Definition DataDDS.h:76
string get_protocol() const
Definition DataDDS.h:114
A class for error processing.
Definition Error.h:92
bool parse(FILE *fp)
Parse an Error object.
Definition Error.cc:106
A class for software fault reporting.
Definition InternalErr.h:61
static RCReader * instance()
Definition RCReader.cc:427
virtual std::string get_protocol() const
Definition Response.h:108
virtual void set_type(ObjectType o)
Definition Response.h:118
virtual ObjectType get_type() const
Definition Response.h:106
virtual FILE * get_stream() const
Definition Response.h:103
virtual std::string get_version() const
Definition Response.h:107
#define DBGN(x)
Definition debug.h:59
#define DBG(x)
Definition debug.h:58
#define DBG2(x)
Definition debug.h:74
top level DAP object to house generic methods
Definition AISConnect.cc:30
string read_multipart_boundary(FILE *in, const string &boundary)
Definition mime_util.cc:893
ObjectType get_description_type(const string &value)
Definition mime_util.cc:309
string cid_to_header_value(const string &cid)
string long_to_string(long val, int base)
Definition util.cc:946
void parse_mime_header(const string &header, string &name, string &value)
Definition mime_util.cc:848
string prune_spaces(const string &name)
Definition util.cc:451
void read_multipart_headers(FILE *in, const string &content_type, const ObjectType object_type, const string &cid)
Definition mime_util.cc:935
string id2www_ce(string in, const string &allowable)
Definition escaping.cc:166
ObjectType
The type of object in the stream coming from the data server.
Definition ObjectType.h:57
@ dods_das
Definition ObjectType.h:59
@ dods_data_ddx
Definition ObjectType.h:63
@ dap4_data
Definition ObjectType.h:68
@ unknown_type
Definition ObjectType.h:58
@ dods_error
Definition ObjectType.h:64
@ dods_data
Definition ObjectType.h:61
@ web_error
Definition ObjectType.h:65
@ dods_dds
Definition ObjectType.h:60
@ dods_ddx
Definition ObjectType.h:62
string get_next_mime_header(FILE *in)
Definition mime_util.cc:777