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 // Reza Nekovei <rnekovei@intcomm.net> 00010 // 00011 // This library is free software; you can redistribute it and/or 00012 // modify it under the terms of the GNU Lesser General Public 00013 // License as published by the Free Software Foundation; either 00014 // version 2.1 of the License, or (at your option) any later version. 00015 // 00016 // This library is distributed in the hope that it will be useful, 00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 // Lesser General Public License for more details. 00020 // 00021 // You should have received a copy of the GNU Lesser General Public 00022 // License along with this library; if not, write to the Free Software 00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00024 // 00025 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00026 00027 // (c) COPYRIGHT URI/MIT 1994-2001 00028 // Please read the full copyright statement in the file COPYRIGHT_URI. 00029 // 00030 // Authors: 00031 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu> 00032 // reza Reza Nekovei <rnekovei@intcomm.net> 00033 00034 // A few useful routines which are used in CGI programs. 00035 // 00036 // ReZa 9/30/94 00037 00038 #include "config.h" 00039 00040 static char rcsid[] not_used = 00041 {"$Id: cgi_util.cc 20518 2009-03-05 23:39:46Z jimg $" 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> // for access 00059 #include <sys/wait.h> 00060 #else 00061 #include <io.h> 00062 #include <fcntl.h> 00063 #include <process.h> 00064 // Win32 does not define this. 08/21/02 jhrg 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" // This supplies flush_stream for WIN32. 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 // ...not using a const string here to avoid global objects. jhrg 12/23/05 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; // length of string from asctime() 00093 static const int CLUMP_SIZE = 1024; // size of clumps to new in fmakeword() 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) ; // Not sure this is needed. jhrg 12/23/05 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'; // overwrite the \n 00151 } 00152 00153 #if 0 00154 // This was removed because writing these values out 'leaks' system information. 00155 // Since we're not going to write out the script or host, I also removed the 00156 // calls to getenv(). jhrg 8/7/2007 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 // Given a pathname, return just the filename component with any extension 00169 // removed. The new string resides in newly allocated memory; the caller must 00170 // delete it when done using the filename. 00171 // Originally from the netcdf distribution (ver 2.3.2). 00172 // 00173 // *** Change to string class argument and return type. jhrg 00174 // *** Changed so it also removes the#path#of#the#file# from decompressed 00175 // files. rph. 00176 // Returns: A filename, with path and extension information removed. If 00177 // memory for the new name cannot be allocated, does not return! 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 // Return a MIME rfc-822 date. The grammar for this is: 00208 // date-time = [ day "," ] date time ; dd mm yy 00209 // ; hh:mm:ss zzz 00210 // 00211 // day = "Mon" / "Tue" / "Wed" / "Thu" 00212 // / "Fri" / "Sat" / "Sun" 00213 // 00214 // date = 1*2DIGIT month 2DIGIT ; day month year 00215 // ; e.g. 20 Jun 82 00216 // NB: year is 4 digit; see RFC 1123. 11/30/99 jhrg 00217 // 00218 // month = "Jan" / "Feb" / "Mar" / "Apr" 00219 // / "May" / "Jun" / "Jul" / "Aug" 00220 // / "Sep" / "Oct" / "Nov" / "Dec" 00221 // 00222 // time = hour zone ; ANSI and Military 00223 // 00224 // hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] 00225 // ; 00:00:00 - 23:59:59 00226 // 00227 // zone = "UT" / "GMT" ; Universal Time 00228 // ; North American : UT 00229 // / "EST" / "EDT" ; Eastern: - 5/ - 4 00230 // / "CST" / "CDT" ; Central: - 6/ - 5 00231 // / "MST" / "MDT" ; Mountain: - 7/ - 6 00232 // / "PST" / "PDT" ; Pacific: - 8/ - 7 00233 // / 1ALPHA ; Military: Z = UT; 00234 // ; A:-1; (J not used) 00235 // ; M:-12; N:+1; Y:+12 00236 // / ( ("+" / "-") 4DIGIT ) ; Local differential 00237 // ; hours+min. (HHMM) 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 // Send string to set the transfer (mime) type and server version 00289 // Note that the content description filed is used to indicate whether valid 00290 // information of an error message is contained in the document and the 00291 // content-encoding field is used to indicate whether the data is compressed. 00292 // If the data stream is to be compressed, arrange for a compression output 00293 // filter so that all information sent after the header will be compressed. 00294 // 00295 // Returns: false if the compression output filter was to be used but could 00296 // not be started, true otherwise. 00297 00298 static const char *descrip[] = 00299 {"unknown", "dods_das", "dods_dds", "dods_data", 00300 "dods_error", "web_error", "dap4_ddx", "dap4_datax", "dap4_errorx" 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 // Note that Content-Description is from RFC 2045 (MIME, pt 1), not 2616. 00348 // jhrg 12/23/05 00349 fprintf(out, "Content-Description: %s%s", descrip[type], CRLF) ; 00350 if (type == dods_error) // don't cache our error responses. 00351 fprintf(out, "Cache-Control: no-cache%s", CRLF) ; 00352 // Don't write a Content-Encoding header for x-plain since that breaks 00353 // Netscape on NT. jhrg 3/23/97 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 // Note that Content-Description is from RFC 2045 (MIME, pt 1), not 2616. 00401 // jhrg 12/23/05 00402 strm << "Content-Description: " << descrip[type] << CRLF ; 00403 if (type == dods_error) // don't cache our error responses. 00404 strm << "Cache-Control: no-cache" << CRLF ; 00405 // Don't write a Content-Encoding header for x-plain since that breaks 00406 // Netscape on NT. jhrg 3/23/97 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 // See note above about Content-Description header. jhrg 12/23/05 00448 fprintf(out, "Content-Description: %s%s", descrip[type], CRLF) ; 00449 if (type == dods_error) // don't cache our error responses. 00450 fprintf(out, "Cache-Control: no-cache%s", CRLF) ; 00451 // Don't write a Content-Encoding header for x-plain since that breaks 00452 // Netscape on NT. jhrg 3/23/97 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 // See note above about Content-Description header. jhrg 12/23/05 00494 strm << "Content-Description: " << descrip[type] << CRLF ; 00495 if (type == dods_error) // don't cache our error responses. 00496 strm << "Cache-Control: no-cache" << CRLF ; 00497 // Don't write a Content-Encoding header for x-plain since that breaks 00498 // Netscape on NT. jhrg 3/23/97 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 char *s = fgets(tmp, 255, in); 00721 if (s && strncmp(s, 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 // Problem: This code is run with the CWD as the CGI-BIN directory but 00769 // the data are in DocumentRoot (and we don't have the pathname of the 00770 // data relative to DocumentRoot). So the only time this will work is 00771 // when the server is in the same directory as the data. See bug 815. 00772 // 10/08/04 jhrg 00773 ifs.open((name + ".html").c_str()); 00774 00775 // If name.html cannot be opened, look for basename.html 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 } // namespace libdap 00794