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);
virtual std::string default_catalog_name() const
The name of the default catalog.
static BESCatalogList * TheCatalogList()
Get the singleton BESCatalogList instance.
virtual BESCatalog * default_catalog() const
The the default catalog.
const std::string & get_root_dir() const
Get the root directory of the catalog.
Catalogs provide a hierarchical organization for data.
virtual BESCatalogEntry * show_catalog(const std::string &container, BESCatalogEntry *entry)=0
virtual BESCatalogUtils * get_catalog_utils() const
Get a pointer to the utilities, customized for this catalog.
Structure storing information used by the BES to handle the request.
std::map< std::string, std::string > data
the map of string data that will be required for the current request.
error thrown if the BES is not allowed to access the resource requested
informational response object
virtual void transmit(BESTransmitter *transmitter, BESDataHandlerInterface &dhi)=0
transmit the informational object
virtual void begin_response(const std::string &response_name, BESDataHandlerInterface &dhi)
begin the informational response
exception thrown if internal error encountered
handler object that knows how to create a specific response object
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual bool start(std::string name)
static std::string assemblePath(const std::string &firstPart, const std::string &secondPart, bool leadingSlash=false, bool trailingSlash=false)
Assemble path fragments making sure that they are separated by a single '/' character.
response handler that returns nodes or leaves within the catalog either at the root or at a specified...
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual void transmit(BESTransmitter *transmitter, BESDataHandlerInterface &dhi)
transmit the response object built by the execute command using the specified transmitter object
virtual void execute(BESDataHandlerInterface &dhi)
executes the command 'show catalog|leaves [for <node>];' by returning nodes or leaves at the top leve...