42 {
"$Id: mime_util.cc 24869 2011-08-24 23:17:41Z jimg $"
49 #ifndef TM_IN_SYS_TIME
55 #include <sys/types.h>
80 #define FILE_DELIMITER '\\'
81 #else // default to unix
82 #define FILE_DELIMITER '/'
86 #define CRLF "\r\n" // Change here, expr-test.cc, in DODSFilter and ResponseBuilder
102 if (stat(name.c_str(), &m) == 0 && (S_IFREG & m.st_mode))
139 static const char *days[] =
140 {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
142 static const char *months[] =
143 {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
144 "Aug",
"Sep",
"Oct",
"Nov",
"Dec"
148 #define snprintf sprintf_s
161 struct tm *stm = gmtime(&t);
164 snprintf(d, 255,
"%s, %02d %s %4d %02d:%02d:%02d GMT", days[stm->tm_wday],
165 stm->tm_mday, months[stm->tm_mon],
167 stm->tm_hour, stm->tm_min, stm->tm_sec);
172 static const int TimLen = 26;
173 static const int CLUMP_SIZE = 1024;
189 do_version(
const string &script_ver,
const string &dataset_ver)
191 fprintf(stdout,
"HTTP/1.0 200 OK%s",
CRLF) ;
192 fprintf(stdout,
"XDODS-Server: %s%s",
DVR,
CRLF) ;
193 fprintf(stdout,
"XOPeNDAP-Server: %s%s",
DVR,
CRLF) ;
195 fprintf(stdout,
"Content-Type: text/plain%s",
CRLF) ;
196 fprintf(stdout,
CRLF) ;
198 fprintf(stdout,
"Core software version: %s%s",
DVR,
CRLF) ;
200 if (script_ver !=
"")
201 fprintf(stdout,
"Server Script Revision: %s%s", script_ver.c_str(),
CRLF) ;
203 if (dataset_ver !=
"")
204 fprintf(stdout,
"Dataset version: %s%s", dataset_ver.c_str(),
CRLF) ;
227 if (time(&TimBin) == (time_t) - 1)
228 strncpy(TimStr,
"time() error ", TimLen-1);
230 strncpy(TimStr, ctime(&TimBin), TimLen-1);
231 TimStr[TimLen - 2] =
'\0';
234 cerr <<
"[" << TimStr <<
"] DAP server error: " << Msgt << endl;
265 string::size_type pound = path.find_last_of(
"#");
268 if (pound != string::npos)
269 new_path = path.substr(pound + 1);
271 new_path = path.substr(delim + 1);
286 static const char *descrip[] =
287 {
"unknown",
"dods_das",
"dods_dds",
"dods_data",
288 "dods_error",
"web_error",
"dap4-ddx",
"dap4-data",
"dap4-error",
289 "dap4-data-ddx",
"dods_ddx"
291 static const char *encoding[] =
292 {
"unknown",
"deflate",
"x-plain",
"gzip",
"binary"
303 if ((value ==
"dods_das") | (value ==
"dods-das"))
305 else if ((value ==
"dods_dds") | (value ==
"dods-dds"))
307 else if ((value ==
"dods_data") | (value ==
"dods-data"))
309 else if ((value ==
"dods_error") | (value ==
"dods-error"))
311 else if ((value ==
"web_error") | (value ==
"web-error"))
313 else if ((value ==
"dap4_ddx") | (value ==
"dap4-ddx"))
315 else if ((value ==
"dap4_data") | (value ==
"dap4-data"))
317 else if ((value ==
"dap4_error") | (value ==
"dap4-error"))
319 else if ((value ==
"dap4_data_ddx") | (value ==
"dap4-data-ddx"))
321 else if ((value ==
"dods_ddx") | (value ==
"dods-ddx"))
335 if ((value ==
"dods_das") | (value ==
"dods-das"))
337 else if ((value ==
"dods_dds") | (value ==
"dods-dds"))
339 else if ((value ==
"dods_data") | (value ==
"dods-data"))
341 else if ((value ==
"dods_error") | (value ==
"dods-error"))
343 else if ((value ==
"web_error") | (value ==
"web-error"))
345 else if ((value ==
"dods_ddx") | (value ==
"dods-ddx"))
347 else if ((value ==
"dap4_ddx") | (value ==
"dap4-ddx"))
349 else if ((value ==
"dap4_data") | (value ==
"dap4-data"))
351 else if ((value ==
"dap4_error") | (value ==
"dap4-error"))
353 else if ((value ==
"dap4_data_ddx") | (value ==
"dap4-data-ddx"))
355 else if ((value ==
"dods_ddx") | (value ==
"dods-ddx"))
379 fprintf(out,
"HTTP/1.0 200 OK%s",
CRLF) ;
381 fprintf(out,
"XDODS-Server: %s%s",
DVR,
CRLF) ;
382 fprintf(out,
"XOPeNDAP-Server: %s%s",
DVR,
CRLF) ;
385 fprintf(out,
"XDODS-Server: %s%s", ver.c_str(),
CRLF) ;
386 fprintf(out,
"XOPeNDAP-Server: %s%s", ver.c_str(),
CRLF) ;
390 const time_t t = time(0);
393 fprintf(out,
"Last-Modified: ") ;
394 if (last_modified > 0)
400 fprintf(out,
"Content-Type: text/xml%s",
CRLF) ;
402 fprintf(out,
"Content-Type: text/plain%s",
CRLF) ;
406 fprintf(out,
"Content-Description: %s%s", descrip[type],
CRLF) ;
408 fprintf(out,
"Cache-Control: no-cache%s",
CRLF) ;
412 fprintf(out,
"Content-Encoding: %s%s", encoding[enc],
CRLF) ;
434 strm <<
"HTTP/1.0 200 OK" <<
CRLF ;
436 strm <<
"XDODS-Server: " <<
DVR <<
CRLF ;
437 strm <<
"XOPeNDAP-Server: " <<
DVR <<
CRLF ;
440 strm <<
"XDODS-Server: " << ver.c_str() <<
CRLF ;
441 strm <<
"XOPeNDAP-Server: " << ver.c_str() <<
CRLF ;
445 const time_t t = time(0);
448 strm <<
"Last-Modified: " ;
449 if (last_modified > 0)
455 strm <<
"Content-Type: text/xml" <<
CRLF ;
457 strm <<
"Content-Type: text/plain" <<
CRLF ;
461 strm <<
"Content-Description: " << descrip[type] <<
CRLF ;
463 strm <<
"Cache-Control: no-cache" <<
CRLF ;
467 strm <<
"Content-Encoding: " << encoding[enc] <<
CRLF ;
487 fprintf(out,
"HTTP/1.0 200 OK%s",
CRLF) ;
489 fprintf(out,
"XDODS-Server: %s%s",
DVR,
CRLF) ;
490 fprintf(out,
"XOPeNDAP-Server: %s%s",
DVR,
CRLF) ;
493 fprintf(out,
"XDODS-Server: %s%s", ver.c_str(),
CRLF) ;
494 fprintf(out,
"XOPeNDAP-Server: %s%s", ver.c_str(),
CRLF) ;
498 const time_t t = time(0);
501 fprintf(out,
"Last-Modified: ") ;
502 if (last_modified > 0)
507 fprintf(out,
"Content-type: text/html%s",
CRLF) ;
509 fprintf(out,
"Content-Description: %s%s", descrip[type],
CRLF) ;
511 fprintf(out,
"Cache-Control: no-cache%s",
CRLF) ;
515 fprintf(out,
"Content-Encoding: %s%s", encoding[enc],
CRLF) ;
535 strm <<
"HTTP/1.0 200 OK" <<
CRLF ;
537 strm <<
"XDODS-Server: " <<
DVR <<
CRLF ;
538 strm <<
"XOPeNDAP-Server: " <<
DVR <<
CRLF ;
541 strm <<
"XDODS-Server: " << ver.c_str() <<
CRLF ;
542 strm <<
"XOPeNDAP-Server: " << ver.c_str() <<
CRLF ;
546 const time_t t = time(0);
549 strm <<
"Last-Modified: " ;
550 if (last_modified > 0)
555 strm <<
"Content-type: text/html" <<
CRLF ;
557 strm <<
"Content-Description: " << descrip[type] <<
CRLF ;
559 strm <<
"Cache-Control: no-cache" <<
CRLF ;
563 strm <<
"Content-Encoding: " << encoding[enc] <<
CRLF ;
586 fprintf(out,
"HTTP/1.0 200 OK%s",
CRLF) ;
588 fprintf(out,
"XDODS-Server: %s%s",
DVR,
CRLF) ;
589 fprintf(out,
"XOPeNDAP-Server: %s%s",
DVR,
CRLF) ;
592 fprintf(out,
"XDODS-Server: %s%s", ver.c_str(),
CRLF) ;
593 fprintf(out,
"XOPeNDAP-Server: %s%s", ver.c_str(),
CRLF) ;
597 const time_t t = time(0);
600 fprintf(out,
"Last-Modified: ") ;
601 if (last_modified > 0)
606 fprintf(out,
"Content-Type: application/octet-stream%s",
CRLF) ;
607 fprintf(out,
"Content-Description: %s%s", descrip[type],
CRLF) ;
609 fprintf(out,
"Content-Encoding: %s%s", encoding[enc],
CRLF) ;
633 strm <<
"HTTP/1.0 200 OK" <<
CRLF ;
635 strm <<
"XDODS-Server: " <<
DVR <<
CRLF ;
636 strm <<
"XOPeNDAP-Server: " <<
DVR <<
CRLF ;
639 strm <<
"XDODS-Server: " << ver.c_str() <<
CRLF ;
640 strm <<
"XOPeNDAP-Server: " << ver.c_str() <<
CRLF ;
644 const time_t t = time(0);
647 strm <<
"Last-Modified: " ;
648 if (last_modified > 0)
653 strm <<
"Content-Type: application/octet-stream" <<
CRLF ;
654 strm <<
"Content-Description: " << descrip[type] <<
CRLF ;
656 strm <<
"Content-Encoding: " << encoding[enc] <<
CRLF ;
664 const time_t last_modified)
666 strm <<
"HTTP/1.0 200 OK" <<
CRLF ;
668 strm <<
"XDODS-Server: " <<
DVR <<
CRLF ;
669 strm <<
"XOPeNDAP-Server: " <<
DVR <<
CRLF ;
672 strm <<
"XDODS-Server: " << version.c_str() <<
CRLF ;
673 strm <<
"XOPeNDAP-Server: " << version.c_str() <<
CRLF ;
677 const time_t t = time(0);
680 strm <<
"Last-Modified: " ;
681 if (last_modified > 0)
686 strm <<
"Content-Type: Multipart/Related; boundary=" << boundary
687 <<
"; start=\"<" << start <<
">\"; type=\"Text/xml\"" <<
CRLF ;
688 strm <<
"Content-Description: " << descrip[type] <<
CRLF ;
690 strm <<
"Content-Encoding: " << encoding[enc] <<
CRLF ;
698 strm <<
"--" << boundary <<
CRLF;
699 strm <<
"Content-Type: Text/xml; charset=iso-8859-1" <<
CRLF;
700 strm <<
"Content-Id: <" << cid <<
">" <<
CRLF;
701 strm <<
"Content-Description: " << descrip[type] <<
CRLF ;
703 strm <<
"Content-Encoding: " << encoding[enc] <<
CRLF ;
711 strm <<
"--" << boundary <<
CRLF;
712 strm <<
"Content-Type: application/octet-stream" <<
CRLF;
713 strm <<
"Content-Id: <" << cid <<
">" <<
CRLF;
714 strm <<
"Content-Description: " << descrip[type] <<
CRLF ;
716 strm <<
"Content-Encoding: " << encoding[enc] <<
CRLF ;
744 && (strncmp(line,
CRLF, 2) == 0 || line[0] ==
'\n'))
748 line[slen - 1] =
'\0';
749 if (line[slen - 2] ==
'\r')
750 line[slen - 2] =
'\0';
755 throw Error(
"I expected to find a MIME header, but got EOF instead.");
767 istringstream iss(header);
770 iss.getline(s, 1023,
':');
773 iss.ignore(1023,
' ');
774 iss.getline(s, 1023);
794 if (strlen(line) < 2 || !(line[0] ==
'-' && line[1] ==
'-'))
797 return strncmp(line, boundary.c_str(), boundary.length()) == 0;
816 if ((!boundary.empty() &&
is_boundary(boundary_line.c_str(), boundary))
817 || boundary_line.find(
"--") != 0)
819 "The DAP4 data response document is broken - missing or malformed boundary.");
821 return boundary_line;
845 const ObjectType object_type,
const string &cid)
847 bool ct =
false, cd =
false, ci =
false;
850 while (!header.empty()) {
854 if (name ==
"content-type") {
856 if (value.find(content_type) == string::npos)
857 throw Error(
"Content-Type for this part of a DAP4 data response must be " + content_type +
".");
859 else if (name ==
"content-description") {
862 throw Error(
"Content-Description for this part of a DAP4 data response must be dap4-ddx or dap4-data-ddx");
864 else if (name ==
"content-id") {
866 if (!cid.empty() && value != cid)
867 throw Error(
"Content-Id mismatch. Expected: " + cid
868 +
", but got: " + value);
874 if (!(ct && cd && ci))
875 throw Error(
"The DAP4 data response document is broken - missing header.");
887 string::size_type offset = cid.find(
"cid:");
889 throw Error(
"expected CID to start with 'cid:'");
892 value.append(cid.substr(offset + 4));
912 fprintf(out,
"HTTP/1.0 %d %s%s", code, reason.c_str(),
CRLF) ;
914 fprintf(out,
"XDODS-Server: %s%s",
DVR,
CRLF) ;
915 fprintf(out,
"XOPeNDAP-Server: %s%s",
DVR,
CRLF) ;
918 fprintf(out,
"XDODS-Server: %s%s", version.c_str(),
CRLF) ;
919 fprintf(out,
"XOPeNDAP-Server: %s%s", version.c_str(),
CRLF) ;
923 const time_t t = time(0);
925 fprintf(out,
"Cache-Control: no-cache%s",
CRLF) ;
942 strm <<
"HTTP/1.0 " << code <<
" " << reason.c_str() <<
CRLF ;
944 strm <<
"XDODS-Server: " <<
DVR <<
CRLF ;
945 strm <<
"XOPeNDAP-Server: " <<
DVR <<
CRLF ;
948 strm <<
"XDODS-Server: " << version.c_str() <<
CRLF ;
949 strm <<
"XOPeNDAP-Server: " << version.c_str() <<
CRLF ;
953 const time_t t = time(0);
955 strm <<
"Cache-Control: no-cache" <<
CRLF ;
970 fprintf(out,
"HTTP/1.0 304 NOT MODIFIED%s",
CRLF) ;
971 const time_t t = time(0);
987 strm <<
"HTTP/1.0 304 NOT MODIFIED" <<
CRLF ;
988 const time_t t = time(0);
1005 ifstream ifs((name +
".ovr").c_str());
1011 while (!ifs.eof()) {
1012 ifs.getline(tmp, 255);
1035 char *s = fgets(tmp, 255, in);
1036 if (s && strncmp(s,
CRLF, 2) == 0)