35 #include "GatewayPathInfoResponseHandler.h"
39 #include "BESInfoList.h"
42 #include "BESRequestHandlerList.h"
43 #include "BESRequestHandler.h"
45 #include "BESDapNames.h"
46 #include "BESDataNames.h"
47 #include "BESCatalogList.h"
48 #include "BESCatalog.h"
49 #include "BESCatalogEntry.h"
50 #include "BESCatalogUtils.h"
51 #include "BESSyntaxUserError.h"
52 #include "BESForbiddenError.h"
53 #include "BESNotFoundError.h"
54 #include "BESStopWatch.h"
62 #define PATH_INFO_RESPONSE "PathInfo"
64 #define VALID_PATH "validPath"
65 #define REMAINDER "remainder"
66 #define IS_DATA "isData"
67 #define IS_FILE "isFile"
68 #define IS_DIR "isDir"
69 #define IS_ACCESSIBLE "access"
71 #define LMT "lastModified"
73 GatewayPathInfoResponseHandler::GatewayPathInfoResponseHandler(
const string &name) :
78 GatewayPathInfoResponseHandler::~GatewayPathInfoResponseHandler()
95 if (BESISDEBUG(TIMING_LOG)) sw.
start(
"GatewayPathInfoResponseHandler::execute", dhi.
data[REQUEST_ID]);
97 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::execute() - BEGIN" << endl );
99 BESInfo *info = BESInfoList::TheList()->build_info();
102 string container = dhi.
data[CONTAINER];
110 throw BESInternalError(
"Not able to find the default catalog.", __FILE__, __LINE__);
113 string::size_type notslash = container.find_first_not_of(
"/", 0);
114 if (notslash != string::npos) {
115 container = container.substr(notslash);
120 string::size_type slash = container.find_first_of(
"/", 0);
121 if (slash != string::npos) {
122 catname = container.substr(0, slash);
132 if (slash != string::npos) {
133 container = container.substr(slash + 1);
136 notslash = container.find_first_not_of(
"/", 0);
137 if (notslash != string::npos) {
138 container = container.substr(notslash);
146 if (container.empty()) container =
"/";
148 if (container[0] !=
'/') container =
"/" + container;
150 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::execute() - container: " << container << endl );
154 map<string, string> pathInfoAttrs;
155 pathInfoAttrs[PATH] = container;
157 info->begin_tag(PATH_INFO_RESPONSE, &pathInfoAttrs);
159 string validPath, remainder;
160 bool isFile, isDir, canRead;
161 long long size, time;
168 eval_resource_path(container, utils->
get_root_dir(), utils->follow_sym_links(), validPath, isFile, isDir, size,
169 time, canRead, remainder);
176 if (validPath.length() != 0) {
183 string err = (string)
"Failed to find the validPath node " + validPath
184 +
" this should not be possible. Some thing BAD is happening.";
189 list<string> services = entry->get_service_list();
192 if (services.size()) {
193 list<string>::const_iterator si = services.begin();
194 list<string>::const_iterator se = services.end();
195 for (; si != se; si++) {
196 if ((*si) == OPENDAP_SERVICE) isData =
true;
201 map<string, string> validPathAttrs;
202 validPathAttrs[IS_DATA] = isData ?
"true" :
"false";
203 validPathAttrs[IS_FILE] = isFile ?
"true" :
"false";
204 validPathAttrs[IS_DIR] = isDir ?
"true" :
"false";
205 validPathAttrs[IS_ACCESSIBLE] = canRead ?
"true" :
"false";
208 std::ostringstream os_size;
210 validPathAttrs[SIZE] = os_size.str();
213 std::ostringstream os_time;
215 validPathAttrs[LMT] = os_time.str();
217 info->add_tag(VALID_PATH, validPath, &validPathAttrs);
218 info->add_tag(REMAINDER, remainder);
220 info->end_tag(PATH_INFO_RESPONSE);
223 info->end_response();
225 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::execute() - END" << endl );
257 strm << BESIndent::LMarg <<
"GatewayPathInfoResponseHandler::dump - (" << (
void *)
this <<
")" << std::endl;
260 BESIndent::UnIndent();
264 GatewayPathInfoResponseHandler::GatewayPathInfoResponseBuilder(
const string &name)
272 void GatewayPathInfoResponseHandler::eval_resource_path(
const string &resource_path,
const string &catalog_root,
273 const bool follow_sym_links,
string &validPath,
bool &isFile,
bool &isDir,
long long &size,
274 long long &lastModifiedTime,
bool &canRead,
string &remainder)
277 BESDEBUG(SPI_DEBUG_KEY,
278 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"CatalogRoot: "<< catalog_root << endl);
280 BESDEBUG(SPI_DEBUG_KEY,
281 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"resourceID: "<< resource_path << endl);
286 lastModifiedTime = -1;
289 string rem = resource_path;
295 int (*ye_old_stat_function)(
const char *pathname,
struct stat *buf);
296 if (follow_sym_links) {
297 BESDEBUG(SPI_DEBUG_KEY,
298 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Using 'stat' function (follow_sym_links = true)" << endl);
299 ye_old_stat_function = &stat;
302 BESDEBUG(SPI_DEBUG_KEY,
303 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Using 'lstat' function (follow_sym_links = false)" << endl);
304 ye_old_stat_function = &lstat;
309 if (resource_path ==
"") {
310 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::"<<__func__ <<
"() - The resourceID is empty" << endl);
316 string::size_type dotdot = resource_path.find(
"..");
317 if (dotdot != string::npos) {
318 BESDEBUG(SPI_DEBUG_KEY,
319 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
" ERROR: The resourceID '" << resource_path <<
"' contains the substring '..' This is Forbidden." << endl);
320 string s = (string)
"Invalid node name '" + resource_path +
"' ACCESS IS FORBIDDEN";
330 string fullpath = catalog_root;
339 size_t slash = rem.find(
'/');
340 if (slash == string::npos) {
341 BESDEBUG(SPI_DEBUG_KEY,
342 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Checking final path component: " << rem << endl);
351 rem = rem.substr(slash + 1, rem.length() - slash);
354 BESDEBUG(SPI_DEBUG_KEY,
355 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"validPath: "<< validPath << endl);
356 BESDEBUG(SPI_DEBUG_KEY,
357 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"checking: "<< checking << endl);
358 BESDEBUG(SPI_DEBUG_KEY,
359 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"fullpath: "<< fullpath << endl);
361 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"rem: "<< rem << endl);
363 BESDEBUG(SPI_DEBUG_KEY,
364 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"remainder: "<< remainder << endl);
367 int statret = ye_old_stat_function(fullpath.c_str(), &sb);
371 validPath = checking;
378 char *s_err = strerror(errsv);
379 string error =
"Unable to access node " + checking +
": ";
381 error = error + s_err;
384 error = error +
"unknown access error";
386 BESDEBUG(SPI_DEBUG_KEY,
387 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"error: "<< error <<
" errno: " << errno << endl);
389 BESDEBUG(SPI_DEBUG_KEY,
390 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"remainder: '" << remainder <<
"'" << endl);
394 if (errsv != ENOENT && errsv != ENOTDIR) {
399 size_t s_loc = remainder.find(
'/');
400 if (s_loc == string::npos) {
402 string basename = remainder;
403 bool moreDots =
true;
406 size_t d_loc = basename.find_last_of(
".");
407 if (d_loc != string::npos) {
408 basename = basename.substr(0, d_loc);
409 BESDEBUG(SPI_DEBUG_KEY,
410 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - basename: "<< basename << endl);
412 string candidate_remainder = remainder.substr(basename.length());
413 BESDEBUG(SPI_DEBUG_KEY,
414 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - candidate_remainder: "<< candidate_remainder << endl);
417 BESDEBUG(SPI_DEBUG_KEY,
418 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - candidate_path: "<< candidate_path << endl);
421 BESDEBUG(SPI_DEBUG_KEY,
422 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - full_candidate_path: "<< full_candidate_path << endl);
425 int statret1 = ye_old_stat_function(full_candidate_path.c_str(), &sb1);
426 if (statret1 != -1) {
427 validPath = candidate_path;
428 remainder = candidate_remainder;
433 BESDEBUG(SPI_DEBUG_KEY,
434 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"No dots in remainder: "<< remainder << endl);
440 BESDEBUG(SPI_DEBUG_KEY,
441 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Remainder has slash pollution: "<< remainder << endl);
447 statret = ye_old_stat_function(fullpath.c_str(), &sb);
448 if (S_ISREG(sb.st_mode)) {
449 BESDEBUG(SPI_DEBUG_KEY,
450 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"'"<< fullpath <<
"' Is regular file." << endl);
454 else if (S_ISDIR(sb.st_mode)) {
455 BESDEBUG(SPI_DEBUG_KEY,
456 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"'"<< fullpath <<
"' Is directory." << endl);
460 else if (S_ISLNK(sb.st_mode)) {
461 BESDEBUG(SPI_DEBUG_KEY,
462 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"'"<< fullpath <<
"' Is symbolic Link." << endl);
463 string error =
"Service not configured to traverse symbolic links as embodied by the node '" + checking
464 +
"' ACCESS IS FORBIDDEN";
471 std::ifstream ifile(fullpath.c_str());
472 canRead = ifile.good();
484 #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
486 lastModifiedTime = (sb.st_mtimespec.tv_sec * 1000) + (sb.st_mtimespec.tv_nsec / 1000000);
488 lastModifiedTime = sb.st_mtime;
491 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::" << __func__ <<
"() - fullpath: " << fullpath << endl);
492 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::" << __func__ <<
"() - validPath: " << validPath << endl);
493 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::" << __func__ <<
"() - remainder: " << remainder << endl);
494 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::" << __func__ <<
"() - rem: " << rem << endl);
495 BESDEBUG(SPI_DEBUG_KEY,
496 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - isFile: " << (isFile?
"true":
"false") << endl);
497 BESDEBUG(SPI_DEBUG_KEY,
498 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - isDir: " << (isDir?
"true":
"false") << endl);
499 BESDEBUG(SPI_DEBUG_KEY,
500 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - access: " << (canRead?
"true":
"false") << endl);
501 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::" << __func__ <<
"() - size: " << size << endl);
502 BESDEBUG(SPI_DEBUG_KEY,
503 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - LMT: " << lastModifiedTime << endl);