00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "config.h"
00039
00040 static char rcsid[] not_used =
00041 {"$Id: cgi_util.cc 18798 2008-05-31 02:26:22Z pwest $"
00042 };
00043
00044 #include <cstring>
00045 #include <cstdio>
00046 #include <ctype.h>
00047
00048 #ifndef TM_IN_SYS_TIME
00049 #include <time.h>
00050 #else
00051 #include <sys/time.h>
00052 #endif
00053
00054 #include <sys/types.h>
00055 #include <sys/stat.h>
00056
00057 #ifndef WIN32
00058 #include <unistd.h>
00059 #include <sys/wait.h>
00060 #else
00061 #include <io.h>
00062 #include <fcntl.h>
00063 #include <process.h>
00064
00065 #define F_OK 0
00066 #endif
00067
00068 #include <iostream>
00069 #include <sstream>
00070 #include <fstream>
00071 #include <string>
00072
00073 #include "cgi_util.h"
00074 #include "Ancillary.h"
00075 #include "util.h"
00076 #include "debug.h"
00077
00078
00079 #ifdef WIN32
00080 #define FILE_DELIMITER '\\'
00081 #else // default to unix
00082 #define FILE_DELIMITER '/'
00083 #endif
00084
00085
00086 #define CRLF "\r\n" // Change here and in expr-test.cc.
00087
00088 using namespace std;
00089
00090 namespace libdap {
00091
00092 static const int TimLen = 26;
00093 static const int CLUMP_SIZE = 1024;
00094
00108 bool
00109 do_version(const string &script_ver, const string &dataset_ver)
00110 {
00111 fprintf(stdout, "HTTP/1.0 200 OK%s", CRLF) ;
00112 fprintf(stdout, "XDODS-Server: %s%s", DVR, CRLF) ;
00113 fprintf(stdout, "XOPeNDAP-Server: %s%s", DVR, CRLF) ;
00114 fprintf(stdout, "XDAP: %s%s", DAP_PROTOCOL_VERSION, CRLF) ;
00115 fprintf(stdout, "Content-Type: text/plain%s", CRLF) ;
00116 fprintf(stdout, CRLF) ;
00117
00118 fprintf(stdout, "Core software version: %s%s", DVR, CRLF) ;
00119
00120 if (script_ver != "")
00121 fprintf(stdout, "Server Script Revision: %s%s", script_ver.c_str(), CRLF) ;
00122
00123 if (dataset_ver != "")
00124 fprintf(stdout, "Dataset version: %s%s", dataset_ver.c_str(), CRLF) ;
00125
00126 fflush(stdout) ;
00127
00128 return true;
00129 }
00130
00140 void
00141 ErrMsgT(const string &Msgt)
00142 {
00143 time_t TimBin;
00144 char TimStr[TimLen];
00145
00146 if (time(&TimBin) == (time_t) - 1)
00147 strncpy(TimStr, "time() error ", TimLen-1);
00148 else {
00149 strncpy(TimStr, ctime(&TimBin), TimLen-1);
00150 TimStr[TimLen - 2] = '\0';
00151 }
00152
00153 #if 0
00154
00155
00156
00157 const char *host_or_addr = getenv("REMOTE_HOST") ? getenv("REMOTE_HOST") :
00158 getenv("REMOTE_ADDR") ? getenv("REMOTE_ADDR") : "local (a non-CGI run)";
00159 const char *script = getenv("SCRIPT_NAME") ? getenv("SCRIPT_NAME") :
00160 "OPeNDAP server";
00161
00162 cerr << "[" << TimStr << "] CGI: " << script << " failed for "
00163 << host_or_addr << ": " << Msgt << endl;
00164 #endif
00165 cerr << "[" << TimStr << "] DAP server error: " << Msgt << endl;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00189 string
00190 name_path(const string &path)
00191 {
00192 if (path == "")
00193 return string("");
00194
00195 string::size_type delim = path.find_last_of(FILE_DELIMITER);
00196 string::size_type pound = path.find_last_of("#");
00197 string new_path;
00198
00199 if (pound != string::npos)
00200 new_path = path.substr(pound + 1);
00201 else
00202 new_path = path.substr(delim + 1);
00203
00204 return new_path;
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 static const char *days[] =
00240 {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
00241 };
00242 static const char *months[] =
00243 {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
00244 "Aug", "Sep", "Oct", "Nov", "Dec"
00245 };
00246
00247 #ifdef _MSC_VER
00248 #define snprintf sprintf_s
00249 #endif
00250
00258 string
00259 rfc822_date(const time_t t)
00260 {
00261 struct tm *stm = gmtime(&t);
00262 char d[256];
00263
00264 snprintf(d, 255, "%s, %02d %s %4d %02d:%02d:%02d GMT", days[stm->tm_wday],
00265 stm->tm_mday, months[stm->tm_mon],
00266 1900 + stm->tm_year,
00267 stm->tm_hour, stm->tm_min, stm->tm_sec);
00268 d[255] = '\0';
00269 return string(d);
00270 }
00271
00277 time_t
00278 last_modified_time(const string &name)
00279 {
00280 struct stat m;
00281
00282 if (stat(name.c_str(), &m) == 0 && (S_IFREG & m.st_mode))
00283 return m.st_mtime;
00284 else
00285 return time(0);
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 static const char *descrip[] =
00299 {"unknown", "dods_das", "dods_dds", "dods_data",
00300 "dods_error", "web_error", "dap4_ddx"
00301 };
00302 static const char *encoding[] =
00303 {"unknown", "deflate", "x-plain"
00304 };
00305
00318 void
00319 set_mime_text(FILE *out, ObjectType type, const string &ver,
00320 EncodingType enc, const time_t last_modified)
00321 {
00322 fprintf(out, "HTTP/1.0 200 OK%s", CRLF) ;
00323 if (ver == "") {
00324 fprintf(out, "XDODS-Server: %s%s", DVR, CRLF) ;
00325 fprintf(out, "XOPeNDAP-Server: %s%s", DVR, CRLF) ;
00326 }
00327 else {
00328 fprintf(out, "XDODS-Server: %s%s", ver.c_str(), CRLF) ;
00329 fprintf(out, "XOPeNDAP-Server: %s%s", ver.c_str(), CRLF) ;
00330 }
00331 fprintf(out, "XDAP: %s%s", DAP_PROTOCOL_VERSION, CRLF) ;
00332
00333 const time_t t = time(0);
00334 fprintf(out, "Date: %s%s", rfc822_date(t).c_str(), CRLF) ;
00335
00336 fprintf(out, "Last-Modified: ") ;
00337 if (last_modified > 0)
00338 fprintf(out, "%s%s", rfc822_date(last_modified).c_str(), CRLF) ;
00339 else
00340 fprintf(out, "%s%s", rfc822_date(t).c_str(), CRLF) ;
00341
00342 if (type == dap4_ddx)
00343 fprintf(out, "Content-Type: text/xml%s", CRLF) ;
00344 else
00345 fprintf(out, "Content-Type: text/plain%s", CRLF) ;
00346
00347
00348
00349 fprintf(out, "Content-Description: %s%s", descrip[type], CRLF) ;
00350 if (type == dods_error)
00351 fprintf(out, "Cache-Control: no-cache%s", CRLF) ;
00352
00353
00354 if (enc != x_plain)
00355 fprintf(out, "Content-Encoding: %s%s", encoding[enc], CRLF) ;
00356 fprintf(out, CRLF) ;
00357 }
00358
00371 void
00372 set_mime_text(ostream &strm, ObjectType type, const string &ver,
00373 EncodingType enc, const time_t last_modified)
00374 {
00375 strm << "HTTP/1.0 200 OK" << CRLF ;
00376 if (ver == "") {
00377 strm << "XDODS-Server: " << DVR << CRLF ;
00378 strm << "XOPeNDAP-Server: " << DVR << CRLF ;
00379 }
00380 else {
00381 strm << "XDODS-Server: " << ver.c_str() << CRLF ;
00382 strm << "XOPeNDAP-Server: " << ver.c_str() << CRLF ;
00383 }
00384 strm << "XDAP: " << DAP_PROTOCOL_VERSION << CRLF ;
00385
00386 const time_t t = time(0);
00387 strm << "Date: " << rfc822_date(t).c_str() << CRLF ;
00388
00389 strm << "Last-Modified: " ;
00390 if (last_modified > 0)
00391 strm << rfc822_date(last_modified).c_str() << CRLF ;
00392 else
00393 strm << rfc822_date(t).c_str() << CRLF ;
00394
00395 if (type == dap4_ddx)
00396 strm << "Content-Type: text/xml" << CRLF ;
00397 else
00398 strm << "Content-Type: text/plain" << CRLF ;
00399
00400
00401
00402 strm << "Content-Description: " << descrip[type] << CRLF ;
00403 if (type == dods_error)
00404 strm << "Cache-Control: no-cache" << CRLF ;
00405
00406
00407 if (enc != x_plain)
00408 strm << "Content-Encoding: " << encoding[enc] << CRLF ;
00409 strm << CRLF ;
00410 }
00411
00422 void
00423 set_mime_html(FILE *out, ObjectType type, const string &ver,
00424 EncodingType enc, const time_t last_modified)
00425 {
00426 fprintf(out, "HTTP/1.0 200 OK%s", CRLF) ;
00427 if (ver == "") {
00428 fprintf(out, "XDODS-Server: %s%s", DVR, CRLF) ;
00429 fprintf(out, "XOPeNDAP-Server: %s%s", DVR, CRLF) ;
00430 }
00431 else {
00432 fprintf(out, "XDODS-Server: %s%s", ver.c_str(), CRLF) ;
00433 fprintf(out, "XOPeNDAP-Server: %s%s", ver.c_str(), CRLF) ;
00434 }
00435 fprintf(out, "XDAP: %s%s", DAP_PROTOCOL_VERSION, CRLF) ;
00436
00437 const time_t t = time(0);
00438 fprintf(out, "Date: %s%s", rfc822_date(t).c_str(), CRLF) ;
00439
00440 fprintf(out, "Last-Modified: ") ;
00441 if (last_modified > 0)
00442 fprintf(out, "%s%s", rfc822_date(last_modified).c_str(), CRLF) ;
00443 else
00444 fprintf(out, "%s%s", rfc822_date(t).c_str(), CRLF) ;
00445
00446 fprintf(out, "Content-type: text/html%s", CRLF) ;
00447
00448 fprintf(out, "Content-Description: %s%s", descrip[type], CRLF) ;
00449 if (type == dods_error)
00450 fprintf(out, "Cache-Control: no-cache%s", CRLF) ;
00451
00452
00453 if (enc != x_plain)
00454 fprintf(out, "Content-Encoding: %s%s", encoding[enc], CRLF) ;
00455 fprintf(out, CRLF) ;
00456 }
00457
00468 void
00469 set_mime_html(ostream &strm, ObjectType type, const string &ver,
00470 EncodingType enc, const time_t last_modified)
00471 {
00472 strm << "HTTP/1.0 200 OK" << CRLF ;
00473 if (ver == "") {
00474 strm << "XDODS-Server: " << DVR << CRLF ;
00475 strm << "XOPeNDAP-Server: " << DVR << CRLF ;
00476 }
00477 else {
00478 strm << "XDODS-Server: " << ver.c_str() << CRLF ;
00479 strm << "XOPeNDAP-Server: " << ver.c_str() << CRLF ;
00480 }
00481 strm << "XDAP: " << DAP_PROTOCOL_VERSION << CRLF ;
00482
00483 const time_t t = time(0);
00484 strm << "Date: " << rfc822_date(t).c_str() << CRLF ;
00485
00486 strm << "Last-Modified: " ;
00487 if (last_modified > 0)
00488 strm << rfc822_date(last_modified).c_str() << CRLF ;
00489 else
00490 strm << rfc822_date(t).c_str() << CRLF ;
00491
00492 strm << "Content-type: text/html" << CRLF ;
00493
00494 strm << "Content-Description: " << descrip[type] << CRLF ;
00495 if (type == dods_error)
00496 strm << "Cache-Control: no-cache" << CRLF ;
00497
00498
00499 if (enc != x_plain)
00500 strm << "Content-Encoding: " << encoding[enc] << CRLF ;
00501 strm << CRLF ;
00502 }
00503
00517 void
00518 set_mime_binary(FILE *out, ObjectType type, const string &ver,
00519 EncodingType enc, const time_t last_modified)
00520 {
00521 fprintf(out, "HTTP/1.0 200 OK%s", CRLF) ;
00522 if (ver == "") {
00523 fprintf(out, "XDODS-Server: %s%s", DVR, CRLF) ;
00524 fprintf(out, "XOPeNDAP-Server: %s%s", DVR, CRLF) ;
00525 }
00526 else {
00527 fprintf(out, "XDODS-Server: %s%s", ver.c_str(), CRLF) ;
00528 fprintf(out, "XOPeNDAP-Server: %s%s", ver.c_str(), CRLF) ;
00529 }
00530 fprintf(out, "XDAP: %s%s", DAP_PROTOCOL_VERSION, CRLF) ;
00531
00532 const time_t t = time(0);
00533 fprintf(out, "Date: %s%s", rfc822_date(t).c_str(), CRLF) ;
00534
00535 fprintf(out, "Last-Modified: ") ;
00536 if (last_modified > 0)
00537 fprintf(out, "%s%s", rfc822_date(last_modified).c_str(), CRLF) ;
00538 else
00539 fprintf(out, "%s%s", rfc822_date(t).c_str(), CRLF) ;
00540
00541 fprintf(out, "Content-Type: application/octet-stream%s", CRLF) ;
00542 fprintf(out, "Content-Description: %s%s", descrip[type], CRLF) ;
00543 if (enc != x_plain)
00544 fprintf(out, "Content-Encoding: %s%s", encoding[enc], CRLF) ;
00545
00546 fprintf(out, CRLF) ;
00547 }
00548
00562 void
00563 set_mime_binary(ostream &strm, ObjectType type, const string &ver,
00564 EncodingType enc, const time_t last_modified)
00565 {
00566 strm << "HTTP/1.0 200 OK" << CRLF ;
00567 if (ver == "") {
00568 strm << "XDODS-Server: " << DVR << CRLF ;
00569 strm << "XOPeNDAP-Server: " << DVR << CRLF ;
00570 }
00571 else {
00572 strm << "XDODS-Server: " << ver.c_str() << CRLF ;
00573 strm << "XOPeNDAP-Server: " << ver.c_str() << CRLF ;
00574 }
00575 strm << "XDAP: " << DAP_PROTOCOL_VERSION << CRLF ;
00576
00577 const time_t t = time(0);
00578 strm << "Date: " << rfc822_date(t).c_str() << CRLF ;
00579
00580 strm << "Last-Modified: " ;
00581 if (last_modified > 0)
00582 strm << rfc822_date(last_modified).c_str() << CRLF ;
00583 else
00584 strm << rfc822_date(t).c_str() << CRLF ;
00585
00586 strm << "Content-Type: application/octet-stream" << CRLF ;
00587 strm << "Content-Description: " << descrip[type] << CRLF ;
00588 if (enc != x_plain)
00589 strm << "Content-Encoding: " << encoding[enc] << CRLF ;
00590
00591 strm << CRLF ;
00592 }
00593
00594
00601 void
00602 set_mime_error(FILE *out, int code, const string &reason,
00603 const string &version)
00604 {
00605 fprintf(out, "HTTP/1.0 %d %s%s", code, reason.c_str(), CRLF) ;
00606 if (version == "") {
00607 fprintf(out, "XDODS-Server: %s%s", DVR, CRLF) ;
00608 fprintf(out, "XOPeNDAP-Server: %s%s", DVR, CRLF) ;
00609 }
00610 else {
00611 fprintf(out, "XDODS-Server: %s%s", version.c_str(), CRLF) ;
00612 fprintf(out, "XOPeNDAP-Server: %s%s", version.c_str(), CRLF) ;
00613 }
00614 fprintf(out, "XDAP: %s%s", DAP_PROTOCOL_VERSION, CRLF) ;
00615
00616 const time_t t = time(0);
00617 fprintf(out, "Date: %s%s", rfc822_date(t).c_str(), CRLF) ;
00618 fprintf(out, "Cache-Control: no-cache%s", CRLF) ;
00619 fprintf(out, CRLF) ;
00620 }
00621
00628 void
00629 set_mime_error(ostream &strm, int code, const string &reason,
00630 const string &version)
00631 {
00632 strm << "HTTP/1.0 " << code << " " << reason.c_str() << CRLF ;
00633 if (version == "") {
00634 strm << "XDODS-Server: " << DVR << CRLF ;
00635 strm << "XOPeNDAP-Server: " << DVR << CRLF ;
00636 }
00637 else {
00638 strm << "XDODS-Server: " << version.c_str() << CRLF ;
00639 strm << "XOPeNDAP-Server: " << version.c_str() << CRLF ;
00640 }
00641 strm << "XDAP: " << DAP_PROTOCOL_VERSION << CRLF ;
00642
00643 const time_t t = time(0);
00644 strm << "Date: " << rfc822_date(t).c_str() << CRLF ;
00645 strm << "Cache-Control: no-cache" << CRLF ;
00646 strm << CRLF ;
00647 }
00648
00649
00656 void
00657 set_mime_not_modified(FILE *out)
00658 {
00659 fprintf(out, "HTTP/1.0 304 NOT MODIFIED%s", CRLF) ;
00660 const time_t t = time(0);
00661 fprintf(out, "Date: %s%s", rfc822_date(t).c_str(), CRLF) ;
00662 fprintf(out, CRLF) ;
00663 }
00664
00671 void
00672 set_mime_not_modified(ostream &strm)
00673 {
00674 strm << "HTTP/1.0 304 NOT MODIFIED" << CRLF ;
00675 const time_t t = time(0);
00676 strm << "Date: " << rfc822_date(t).c_str() << CRLF ;
00677 strm << CRLF ;
00678 }
00679
00688 bool
00689 found_override(string name, string &doc)
00690 {
00691 ifstream ifs((name + ".ovr").c_str());
00692 if (!ifs)
00693 return false;
00694
00695 char tmp[256];
00696 doc = "";
00697 while (!ifs.eof()) {
00698 ifs.getline(tmp, 255);
00699 strcat(tmp, "\n");
00700 doc += tmp;
00701 }
00702
00703 ifs.close();
00704 return true;
00705 }
00706
00715 bool
00716 remove_mime_header(FILE *in)
00717 {
00718 char tmp[256];
00719 while (!feof(in)) {
00720 fgets(tmp, 255, in);
00721 if (strncmp(&tmp[0], CRLF, 2) == 0)
00722 return true;
00723 }
00724
00725 return false;
00726 }
00727
00728
00751 string
00752 get_user_supplied_docs(string name, string cgi)
00753 {
00754 char tmp[256];
00755 ostringstream oss;
00756 ifstream ifs((cgi + ".html").c_str());
00757
00758 if (ifs) {
00759 while (!ifs.eof()) {
00760 ifs.getline(tmp, 255);
00761 oss << tmp << "\n";
00762 }
00763 ifs.close();
00764
00765 oss << "<hr>";
00766 }
00767
00768
00769
00770
00771
00772
00773 ifs.open((name + ".html").c_str());
00774
00775
00776 if (!ifs) {
00777 string new_name = Ancillary::find_group_ancillary_file(name, ".html");
00778 if (new_name != "")
00779 ifs.open(new_name.c_str());
00780 }
00781
00782 if (ifs) {
00783 while (!ifs.eof()) {
00784 ifs.getline(tmp, 255);
00785 oss << tmp << "\n";
00786 }
00787 ifs.close();
00788 }
00789
00790 return oss.str();
00791 }
00792
00793 }
00794