75#define FUNCTION_CACHE "/tmp/dap_functions_cache/"
76#define FUNCTION_CACHE_PREFIX "f"
78#define FUNCTION_CACHE_SIZE 20000
96 d_dap4_btp_func_expr =
"";
114 DBG(cerr <<
"the FUNCTION_CACHE directory (" <<
FUNCTION_CACHE <<
") exists" << endl);
118 DBG(cerr <<
"the FUNCTION_CACHE directory (" <<
FUNCTION_CACHE <<
") does not exist - not caching" << endl);
125 _setmode(_fileno(stdout), _O_BINARY);
136string D4ResponseBuilder::get_ce()
const
143 d_dap4ce =
www2id(_ce,
"%",
"%20");
154string D4ResponseBuilder::get_dataset_name()
const
176int D4ResponseBuilder::get_timeout()
const
226 string btp_function_ce =
"";
227 string::size_type pos = 0;
228 DBG(cerr <<
"ce: " <<
ce << endl);
230 string::size_type first_paren =
ce.find(
"(", pos);
231 string::size_type closing_paren =
ce.find(
")", pos);
232 while (first_paren != string::npos && closing_paren != string::npos) {
234 string name =
ce.substr(pos, first_paren-pos);
235 DBG(cerr <<
"name: " << name << endl);
240 if (!btp_function_ce.empty())
241 btp_function_ce +=
",";
242 btp_function_ce +=
ce.substr(pos, closing_paren+1-pos);
243 ce.erase(pos, closing_paren+1-pos);
248 pos = closing_paren + 1;
250 if (pos <
ce.length() &&
ce.at(pos) ==
',')
254 first_paren =
ce.find(
"(", pos);
255 closing_paren =
ce.find(
")", pos);
258 DBG(cerr <<
"Modified constraint: " <<
ce << endl);
259 DBG(cerr <<
"BTP Function part: " << btp_function_ce << endl);
262 d_dap4_btp_func_expr = btp_function_ce;
273build_cache_file_name(
const string &dataset,
const string &ce)
275 DBG(cerr <<
"build_cache_file_name: dataset: " << dataset <<
", ce: " << ce << endl);
277 string name = dataset +
"#" + ce;
278 string::size_type pos = name.find_first_of(
"/(),\"\'");
279 while (pos != string::npos) {
280 name.replace(pos, 1,
"#", 1);
281 pos = name.find_first_of(
"/()\"\'");
284 DBG(cerr <<
"build_cache_file_name: name: " << name << endl);
290static bool cached_data_ddx_exists(
const string &cache_file_name)
292 ifstream icache_file(cache_file_name.c_str());
294 return !icache_file.fail() && !icache_file.bad() && !icache_file.eof();
311 off_t entry_size = 0;
312 time_t entry_time = 0;
314 if (stat(cache_file_name.c_str(), &buf) == 0) {
315 entry_size = buf.st_size;
316 entry_time = buf.st_mtime;
325 time_t dataset_time = entry_time;
326 if (stat(
d_dataset.c_str(), &buf) == 0) {
327 dataset_time = buf.st_mtime;
335 if (dataset_time > entry_time)
357 DBG(cerr <<
"Found function(s) in CE: " << d_dap4_btp_func_expr << endl);
365 string cache_file_name =
d_cache->get_cache_file_name(build_cache_file_name(
d_dataset, d_dap4_btp_func_expr),
false);
373 d_cache->purge_file(cache_file_name);
375 if (
d_cache->get_read_lock(cache_file_name, fd)) {
376 DBG(cerr <<
"function ce - cached hit: " << cache_file_name << endl );
383 if (
d_cache->create_and_lock(cache_file_name, fd)) {
384 DBG(cerr <<
"function ce - caching " << cache_file_name << endl );
396 d_cache->exclusive_to_shared_lock(fd);
401 unsigned long long size =
d_cache->update_cache_info(cache_file_name);
402 if (
d_cache->cache_too_big(size))
403 d_cache->update_and_purge(cache_file_name);
407 else if (
d_cache->get_read_lock(cache_file_name, fd)) {
408 DBG(cerr <<
"function ce - cached hit: " << cache_file_name << endl );
412 throw InternalErr(__FILE__, __LINE__,
"Cache error during function invocation.");
416 DBG(cerr <<
"caught exception, unlocking cache and re-throw." << endl );
422 cache_token = cache_file_name;
439void D4ResponseBuilder::send_das(ostream &out,
DAS &das,
bool with_mime_headers)
const
441 if (with_mime_headers)
466void D4ResponseBuilder::send_das(ostream &out, DDS &dds, ConstraintEvaluator &eval,
bool constrained,
bool with_mime_headers)
473 if (with_mime_headers)
487 if (!d_dap4_btp_func_expr.empty()) {
489 DBG(cerr <<
"Found function(s) in CE: " << d_dap4_btp_func_expr << endl);
492 BaseTypeFactory factory;
497 string cache_file_name =
d_cache->get_cache_file_name(build_cache_file_name(
d_dataset, d_dap4_btp_func_expr),
false);
505 d_cache->purge_file(cache_file_name);
507 if (
d_cache->get_read_lock(cache_file_name, fd)) {
508 DBG(cerr <<
"function ce - cached hit: " << cache_file_name << endl );
509 fdds = get_cached_dap2_data_ddx(cache_file_name, &factory);
515 if (
d_cache->create_and_lock(cache_file_name, fd)) {
516 DBG(cerr <<
"function ce - caching " << cache_file_name << endl );
518 eval.parse_constraint(d_dap4_btp_func_expr, dds);
519 fdds = eval.eval_function_clauses(dds);
528 d_cache->exclusive_to_shared_lock(fd);
533 unsigned long long size =
d_cache->update_cache_info(cache_file_name);
534 if (
d_cache->cache_too_big(size))
535 d_cache->update_and_purge(cache_file_name);
537 else if (
d_cache->get_read_lock(cache_file_name, fd)) {
538 DBG(cerr <<
"function ce - cached hit: " << cache_file_name << endl );
539 fdds = get_cached_dap2_data_ddx(cache_file_name, &factory);
542 throw InternalErr(__FILE__, __LINE__,
"Cache error during function invocation.");
546 DBG(cerr <<
"caught exception, unlocking cache and re-throw." << endl );
553 string cache_token =
"";
556 DBG(cerr <<
"Using the cache for the server function CE" << endl);
560 DBG(cerr <<
"Cache not found; (re)calculating" << endl);
561 eval.parse_constraint(d_dap4_btp_func_expr, dds);
562 fdds = eval.eval_function_clauses(dds);
565 if (with_mime_headers)
568 fdds->print_das(out);
571 d_cache->unlock_and_close(cache_token);
576 DBG(cerr <<
"Simple constraint" << endl);
578 eval.parse_constraint(d_dap4ce, dds);
580 if (with_mime_headers)
607 bool with_mime_headers)
610 if (with_mime_headers)
628 if (!d_dap4_btp_func_expr.empty()) {
630 DBG(cerr <<
"Found function(s) in CE: " << d_dap4_btp_func_expr << endl);
638 string cache_file_name =
d_cache->get_cache_file_name(build_cache_file_name(
d_dataset, d_dap4_btp_func_expr),
false);
646 d_cache->purge_file(cache_file_name);
648 if (
d_cache->get_read_lock(cache_file_name, fd)) {
649 DBG(cerr <<
"function ce - cached hit: " << cache_file_name << endl );
650 fdds = get_cached_dap2_data_ddx(cache_file_name, &factory);
655 if (
d_cache->create_and_lock(cache_file_name, fd)) {
656 DBG(cerr <<
"function ce - caching " << cache_file_name << endl );
668 d_cache->exclusive_to_shared_lock(fd);
673 unsigned long long size =
d_cache->update_cache_info(cache_file_name);
674 if (
d_cache->cache_too_big(size))
675 d_cache->update_and_purge(cache_file_name);
677 else if (
d_cache->get_read_lock(cache_file_name, fd)) {
678 DBG(cerr <<
"function ce - cached hit: " << cache_file_name << endl );
679 fdds = get_cached_dap2_data_ddx(cache_file_name, &factory);
682 throw InternalErr(__FILE__, __LINE__,
"Cache error during function invocation.");
686 DBG(cerr <<
"caught exception, unlocking cache and re-throw." << endl );
692 string cache_token =
"";
696 DBG(cerr <<
"Using the cache for the server function CE" << endl);
700 DBG(cerr <<
"Cache not found; (re)calculating" << endl);
714 if (with_mime_headers)
720 d_cache->unlock_and_close(cache_token);
725 DBG(cerr <<
"Simple constraint" << endl);
729 if (with_mime_headers)
744 DBG(cerr <<
"Inside dataset_constraint" << endl);
760 if ((*i)->send_p()) {
761 DBG(cerr <<
"Sending " << (*i)->name() << endl);
766 (*i)->serialize(eval, dds, m, ce_eval);
769 cerr << (*i)->name() <<
": " << m.
get_checksum() << endl;
771 (*i)->serialize(eval, dds, m, ce_eval);
784 const string &boundary,
const string &start,
bool ce_eval)
793 uuid_unparse(uu, uuid.data());
795 if (getdomainname(domain, 255) != 0 || strlen(domain) == 0)
796 strncpy(domain,
"opendap.org", 255);
798 string cid = string(uuid.data()) +
"@" + string(domain.data());
821 if ((*i)->send_p()) {
822 DBG(cerr <<
"Sending " << (*i)->name() << endl);
828 (*i)->serialize(eval, dds, m, ce_eval);
854 bool with_mime_headers)
867 +
"KB is too large; requests for this user are limited to "
879 if (!d_dap4_btp_func_expr.empty()) {
880 DBG(cerr <<
"Found function(s) in CE: " << d_dap4_btp_func_expr << endl);
888 string cache_file_name =
d_cache->get_cache_file_name(build_cache_file_name(
d_dataset, d_dap4_btp_func_expr),
false);
896 d_cache->purge_file(cache_file_name);
898 if (
d_cache->get_read_lock(cache_file_name, fd)) {
899 DBG(cerr <<
"function ce - cached hit: " << cache_file_name << endl );
900 fdds = get_cached_dap2_data_ddx(cache_file_name, &factory);
905 if (
d_cache->create_and_lock(cache_file_name, fd)) {
906 DBG(cerr <<
"function ce - caching " << cache_file_name << endl );
920 d_cache->exclusive_to_shared_lock(fd);
925 unsigned long long size =
d_cache->update_cache_info(cache_file_name);
926 if (
d_cache->cache_too_big(size))
927 d_cache->update_and_purge(cache_file_name);
929 else if (
d_cache->get_read_lock(cache_file_name, fd)) {
930 DBG(cerr <<
"function ce - cached hit: " << cache_file_name << endl );
931 fdds = get_cached_dap2_data_ddx(cache_file_name, &factory);
934 throw InternalErr(__FILE__, __LINE__,
"Cache error during function invocation.");
938 DBG(cerr <<
"caught exception, unlocking cache and re-throw." << endl );
948 if (cached_data_ddx_exists(cache_file_name)) {
949 fdds = get_cached_dap2_data_ddx(cache_file_name, &factory);
952 DBG(cerr <<
"Reading cache for " <<
d_dataset +
"?" + d_dap4_btp_func_expr << endl);
955 fdds =
new DDS(&factory);
964 throw Error(
"The input source: " + cache_file_name +
" could not be opened");
972 for( ; i != e; i++ ) {
990 ofstream ocache_file(cache_file_name.c_str());
992 DBG(cerr <<
"Caching " <<
d_dataset +
"?" + d_dap4_btp_func_expr << endl);
998 string cache_token =
"";
1002 DBG(cerr <<
"Using the cache for the server function CE" << endl);
1006 DBG(cerr <<
"Cache not found; (re)calculating" << endl);
1011 DBG(cerr <<
"Intermediate DDS: " << endl);
1014 DBG(cerr <<
"Parsing remaining CE: " << d_dap4ce << endl);
1029 +
"KB is too large; requests for this user are limited to "
1034 if (with_mime_headers)
1037 DBG(cerr <<
"About to call dataset_constraint" << endl);
1041 d_cache->unlock_and_close(cache_token);
1046 DBG(cerr <<
"Simple constraint" << endl);
1054 +
"KB is too large; requests for this user are limited to "
1059 if (with_mime_headers)
1071 if (with_mime_headers)
1074 serialize_dap2_data_dds(data_stream, *fdds, eval,
false);
1078 if (with_mime_headers)
1081 serialize_dap2_data_dds(data_stream, dds, eval);
1085 data_stream << flush;
1109 if (!d_dap4ce.empty())
1114 "Function calls can only be used with data requests. To see the structure of the underlying data source, reissue the URL without the function.");
1116 if (with_mime_headers)
1143 const string &boundary,
bool with_mime_headers)
1153 +
"KB is too large; requests for this user are limited to "
1168 if (with_mime_headers)
1170 data_stream << flush;
1180 if (with_mime_headers)
1182 data_stream << flush;
1186 data_stream << flush;
1188 if (with_mime_headers)
1189 data_stream <<
CRLF <<
"--" << boundary <<
"--" <<
CRLF;
1207 if (!d_dap4ce.empty())
1213 "Function calls can only be used with data requests. To see the structure of the underlying data source, reissue the URL without the function.");
1233 DBG(cerr <<
"Caching " <<
d_dataset +
"?" + d_dap4_btp_func_expr << endl);
1235 ofstream data_stream(cache_file_name.c_str());
1238 string start=
"dataddx_cache_start", boundary=
"dataddx_cache_boundary";
1243 data_stream << flush;
1256 data_stream << flush;
1258 data_stream <<
CRLF <<
"--" << boundary <<
"--" <<
CRLF;
1259 data_stream.close();
1284 while (!mime.empty()) {
1286 string header, value;
1297 DBG(cerr <<
"MPM Boundary: " << boundary << endl);
1308 DBG(cerr <<
"Data CID: " << data_cid << endl);
1318 (*i)->deserialize(um, fdds);
1328 DBG(cerr <<
"Reading cache for " <<
d_dataset +
"?" + d_dap4_btp_func_expr << endl);
1330 DDS *fdds =
new DDS(factory);
1339 throw Error(
"The input source: " + cache_file_name +
" could not be opened");
1345 FILE *data = fopen( cache_file_name.c_str(),
"r" );
1354 for( ; i != e; i++ ) {
1388 throw InternalErr(__FILE__, __LINE__,
"ResponseBuilder::send_dap4_data: Not implemented");
1412 if ((*i)->send_p()) {
1413 DBG(cerr <<
"Sending " << (*i)->name() << endl);
1418 (*i)->serialize(eval, dds, m,
true);
1427static const char *descrip[] = {
"unknown",
"dods_das",
"dods_dds",
"dods_data",
"dods_error",
"web_error",
"dap4-ddx",
1428 "dap4-data",
"dap4-error",
"dap4-data-ddx",
"dods_ddx" };
1429static const char *encoding[] = {
"unknown",
"deflate",
"x-plain",
"gzip",
"binary" };
1447 const string &protocol)
const
1449 strm <<
"HTTP/1.0 200 OK" <<
CRLF;
1451 strm <<
"XDODS-Server: " <<
DVR<<
CRLF;
1452 strm <<
"XOPeNDAP-Server: " <<
DVR<<
CRLF;
1457 strm <<
"XDAP: " << protocol <<
CRLF;
1459 const time_t t = time(0);
1462 strm <<
"Last-Modified: ";
1463 if (last_modified > 0)
1469 strm <<
"Content-Type: text/xml" <<
CRLF;
1471 strm <<
"Content-Type: text/plain" <<
CRLF;
1475 strm <<
"Content-Description: " << descrip[type] <<
CRLF;
1477 strm <<
"Cache-Control: no-cache" <<
CRLF;
1481 strm <<
"Content-Encoding: " << encoding[enc] <<
CRLF;
1496 const string &protocol)
const
1498 strm <<
"HTTP/1.0 200 OK" <<
CRLF;
1500 strm <<
"XDODS-Server: " <<
DVR<<
CRLF;
1501 strm <<
"XOPeNDAP-Server: " <<
DVR<<
CRLF;
1506 strm <<
"XDAP: " << protocol <<
CRLF;
1508 const time_t t = time(0);
1511 strm <<
"Last-Modified: ";
1512 if (last_modified > 0)
1517 strm <<
"Content-type: text/html" <<
CRLF;
1519 strm <<
"Content-Description: " << descrip[type] <<
CRLF;
1521 strm <<
"Cache-Control: no-cache" <<
CRLF;
1525 strm <<
"Content-Encoding: " << encoding[enc] <<
CRLF;
1543 const string &protocol)
const
1545 strm <<
"HTTP/1.0 200 OK" <<
CRLF;
1547 strm <<
"XDODS-Server: " <<
DVR<<
CRLF;
1548 strm <<
"XOPeNDAP-Server: " <<
DVR<<
CRLF;
1553 strm <<
"XDAP: " << protocol <<
CRLF;
1555 const time_t t = time(0);
1558 strm <<
"Last-Modified: ";
1559 if (last_modified > 0)
1564 strm <<
"Content-Type: application/octet-stream" <<
CRLF;
1565 strm <<
"Content-Description: " << descrip[type] <<
CRLF;
1567 strm <<
"Content-Encoding: " << encoding[enc] <<
CRLF;
1575 const time_t last_modified,
const string &protocol,
const string &url)
const
1577 strm <<
"HTTP/1.1 200 OK" <<
CRLF;
1579 const time_t t = time(0);
1582 strm <<
"Last-Modified: ";
1583 if (last_modified > 0)
1588 strm <<
"Content-Type: multipart/related; boundary=" << boundary <<
"; start=\"<" << start
1589 <<
">\"; type=\"text/xml\"" <<
CRLF;
1593 strm <<
"Content-Description: " << descrip[type] <<
";";
1595 strm <<
" url=\"" << url <<
"\"" <<
CRLF;
1600 strm <<
"Content-Encoding: " << encoding[enc] <<
CRLF;
1605 strm <<
"X-DAP: " << protocol <<
CRLF;
1607 strm <<
"X-OPeNDAP-Server: " <<
DVR<<
CRLF;
1614 strm <<
"--" << boundary <<
CRLF;
1615 strm <<
"Content-Type: text/xml; charset=UTF-8" <<
CRLF;
1616 strm <<
"Content-Transfer-Encoding: binary" <<
CRLF;
1617 strm <<
"Content-Description: ddx" <<
CRLF;
1618 strm <<
"Content-Id: <" << cid <<
">" <<
CRLF;
1624 const string &endian,
unsigned long long len)
const
1626 strm <<
"--" << boundary <<
CRLF;
1627 strm <<
"Content-Type: application/x-dap-" << endian <<
"-endian" <<
CRLF;
1628 strm <<
"Content-Transfer-Encoding: binary" <<
CRLF;
1629 strm <<
"Content-Description: data" <<
CRLF;
1630 strm <<
"Content-Id: <" << cid <<
">" <<
CRLF;
1631 strm <<
"Content-Length: " << len <<
CRLF;
1644 strm <<
"HTTP/1.0 " << code <<
" " << reason.c_str() <<
CRLF;
1646 strm <<
"XDODS-Server: " <<
DVR<<
CRLF;
1647 strm <<
"X-OPeNDAP-Server: " <<
DVR<<
CRLF;
1652 strm <<
"X-DAP: " << protocol <<
CRLF;
1654 const time_t t = time(0);
1656 strm <<
"Cache-Control: no-cache" <<
CRLF;
#define FUNCTION_CACHE_SIZE
#define FUNCTION_CACHE_PREFIX
static void read_ancillary_das(DAS &das, const string &pathname, const string &dir="", const string &file="")
The basic data type for the DODS DAP types.
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Holds information about the link from a DAP2 client to a dataset.
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...
Evaluate a constraint expression.
bool find_function(const std::string &name, bool_func *f) const
Find a Boolean function with a given name in the function list.
void parse_constraint(const std::string &constraint, DDS &dds)
Parse the constraint expression given the current DDS.
bool function_clauses()
Does the current constraint expression contain function clauses.
DDS * eval_function_clauses(DDS &dds)
Evaluate a function-valued constraint expression that contains several function calls.
bool functional_expression()
Does the current constraint expression return a BaseType pointer? This method does not evaluate the c...
void set_mime_ddx_boundary(ostream &out, const string &boundary, const string &start) const
virtual void cache_data_ddx(const string &cache_file_name, DDS &dds)
Cache data.
virtual void set_ce(const string &ce)
void set_timeout(int t=0)
virtual ~D4ResponseBuilder()
int d_timeout
The BTP functions, extracted from the CE.
string d_default_protocol
Response timeout after N seconds.
virtual string ce() const
void set_mime_binary(ostream &out, ObjectType type=unknown_type, EncodingType enc=x_plain, const time_t last_modified=0, const string &protocol="") const
virtual bool is_valid(const string &cache_file_name)
virtual void dataset_constraint_ddx(ostream &out, DDS &dds, ConstraintEvaluator &eval, const string &boundary, const string &start, bool ce_eval=true)
virtual void remove_timeout() const
void set_mime_data_boundary(ostream &out, const string &boundary, const string &cid, const string &endian, unsigned long long len) const
virtual void send_data(ostream &data_stream, DDS &dds, ConstraintEvaluator &eval, bool with_mime_headers=true)
Transmit data.
void set_mime_error(ostream &out, int code=404, const string &reason="Dataset not found", const string &protocol="") const
virtual void establish_timeout(ostream &stream) const
virtual DDS * read_cached_dataset(DDS &dds, ConstraintEvaluator &eval, string &cache_token)
void set_mime_html(ostream &out, ObjectType type=unknown_type, EncodingType enc=x_plain, const time_t last_modified=0, const string &protocol="") const
virtual void split_ce(ConstraintEvaluator &eval, const string &expr="")
void set_mime_text(ostream &out, ObjectType type=unknown_type, EncodingType enc=x_plain, const time_t last_modified=0, const string &protocol="") const
virtual void send_data_ddx(ostream &data_stream, DDS &dds, ConstraintEvaluator &eval, const string &start, const string &boundary, bool with_mime_headers=true)
Transmit data.
virtual void send_ddx(ostream &out, DDS &dds, ConstraintEvaluator &eval, bool with_mime_headers=true)
virtual DDS * get_cached_data_ddx(const string &cache_file_name, BaseTypeFactory *factory)
virtual void dataset_constraint(ostream &out, DDS &dds, ConstraintEvaluator &eval, bool ce_eval=true)
virtual void set_dataset_name(const string &ds)
virtual void send_dds(ostream &out, DDS &dds, ConstraintEvaluator &eval, bool constrained=false, bool with_mime_headers=true)
Transmit a DDS.
DAPCache3 * d_cache
Version string for the library's default protocol version.
void set_mime_multipart(ostream &out, const string &boundary, const string &start, ObjectType type=unknown_type, EncodingType enc=x_plain, const time_t last_modified=0, const string &protocol="", const string &url="") const
virtual void read_data_from_cache(FILE *data, DDS *fdds)
Marshaller that knows how to marshal/serialize dap data objects to a C++ iostream using DAP4's receiv...
virtual void put_checksum()
Write the checksum Write the checksum for the data sent since the last call to reset_checksum() to th...
virtual void reset_checksum()
virtual string get_checksum()
static DAPCache3 * get_instance()
Hold attribute data for a DAP2 dataset.
virtual void print(FILE *out, bool dereference=false)
void set_dataset_name(const string &n)
void mark_all(bool state)
void print_dmr(ostream &out, bool constrained)
Print the DAP4 DMR object using a DDS.
string get_dap_version() const
virtual void transfer_attributes(DAS *das)
void print(FILE *out)
Print the entire DDS to the specified file.
int get_request_size(bool constrained)
Get the estimated response size in bytes.
BaseTypeFactory * set_factory(BaseTypeFactory *factory)
void tag_nested_sequences()
Traverse DDS, set Sequence leaf nodes.
BaseTypeFactory * get_factory() const
void print_constrained(FILE *out)
Print a constrained DDS to the specified file.
Vars_iter var_end()
Return an iterator.
void set_dap_version(const string &version_string="2.0")
std::vector< BaseType * >::iterator Vars_iter
void print_xml_writer(ostream &out, bool constrained, const string &blob="")
long get_response_limit()
Get the maximum response size, in bytes. Zero indicates no limit.
void intern_stream(FILE *in, DDS *dds, string &cid, const string &boundary="")
Read the DDX from a stream instead of a file.
A class for error processing.
A class for software fault reporting.
virtual FILE * get_stream() const
static EventHandler * register_handler(int signum, EventHandler *eh, bool ignore_by_default=false)
static SignalHandler * instance()
unmarshaller that knows how to unmarshall/deserialize dap objects using XDR from a file
Marshaller that knows how serialize dap data objects to a C++ iostream using XDR.
#define DAP_PROTOCOL_VERSION
top level DAP object to house generic methods
string read_multipart_boundary(FILE *in, const string &boundary)
string cid_to_header_value(const string &cid)
string long_to_string(long val, int base)
string www2id(const string &in, const string &escape, const string &except)
void parse_mime_header(const string &header, string &name, string &value)
time_t last_modified_time(const string &name)
string name_path(const string &path)
Returns the filename portion of a pathname.
bool dir_exists(const string &dir)
void read_multipart_headers(FILE *in, const string &content_type, const ObjectType object_type, const string &cid)
EncodingType
The type of encoding used on the current stream.
string rfc822_date(const time_t t)
ObjectType
The type of object in the stream coming from the data server.
string get_next_mime_header(FILE *in)