28 #include <sys/types.h>
39 #include "ShowPathInfoResponseHandler.h"
43 #include "BESInfoList.h"
46 #include "BESRequestHandlerList.h"
47 #include "BESRequestHandler.h"
49 #include "BESDapNames.h"
50 #include "BESDataNames.h"
51 #include "BESCatalogList.h"
52 #include "BESCatalog.h"
53 #include "BESCatalogEntry.h"
54 #include "BESCatalogUtils.h"
55 #include "BESSyntaxUserError.h"
56 #include "BESForbiddenError.h"
57 #include "BESNotFoundError.h"
58 #include "BESStopWatch.h"
66 #define PATH_INFO_RESPONSE "PathInfo"
68 #define VALID_PATH "validPath"
69 #define REMAINDER "remainder"
70 #define IS_DATA "isData"
71 #define IS_FILE "isFile"
72 #define IS_DIR "isDir"
73 #define IS_ACCESSIBLE "access"
75 #define LMT "lastModified"
77 #define SPI_DEBUG_KEY "show-path-info"
78 #define SHOW_PATH_INFO_RESPONSE_STR "showPathInfo"
80 ShowPathInfoResponseHandler::ShowPathInfoResponseHandler(
const string &name) :
85 ShowPathInfoResponseHandler::~ShowPathInfoResponseHandler()
103 if (BESISDEBUG(TIMING_LOG)) sw.
start(
"ShowPathInfoResponseHandler::execute", dhi.
data[REQUEST_ID]);
105 BESDEBUG(SPI_DEBUG_KEY,
106 "ShowPathInfoResponseHandler::execute() - BEGIN ############################################################## BEGIN" << endl);
108 BESInfo *info = BESInfoList::TheList()->build_info();
109 d_response_object = info;
111 string container = dhi.
data[CONTAINER];
119 throw BESInternalError(
"Not able to find the default catalog.", __FILE__, __LINE__);
122 string::size_type notslash = container.find_first_not_of(
"/", 0);
123 if (notslash != string::npos) {
124 container = container.substr(notslash);
129 string::size_type slash = container.find_first_of(
"/", 0);
130 if (slash != string::npos) {
131 catname = container.substr(0, slash);
141 if (slash != string::npos) {
142 container = container.substr(slash + 1);
145 notslash = container.find_first_not_of(
"/", 0);
146 if (notslash != string::npos) {
147 container = container.substr(notslash);
155 if (container.empty()) container =
"/";
157 if (container[0] !=
'/') container =
"/" + container;
159 BESDEBUG(SPI_DEBUG_KEY,
"ShowPathInfoResponseHandler::execute() - container: " << container << endl);
164 map<string, string> pathInfoAttrs;
165 pathInfoAttrs[PATH] = container;
167 info->begin_tag(PATH_INFO_RESPONSE, &pathInfoAttrs);
169 string validPath, remainder;
170 bool isFile, isDir, canRead;
171 long long size, time;
175 eval_resource_path(container, utils->
get_root_dir(), utils->follow_sym_links(), validPath, isFile, isDir, size,
176 time, canRead, remainder);
183 if (validPath.length() != 0) {
190 string err = (string)
"Failed to find the validPath node " + validPath
191 +
" this should not be possible. Some thing BAD is happening.";
196 list<string> services = entry->get_service_list();
199 if (services.size()) {
200 list<string>::const_iterator si = services.begin();
201 list<string>::const_iterator se = services.end();
202 for (; si != se; si++) {
203 if ((*si) == OPENDAP_SERVICE) isData =
true;
208 map<string, string> validPathAttrs;
209 validPathAttrs[IS_DATA] = isData ?
"true" :
"false";
210 validPathAttrs[IS_FILE] = isFile ?
"true" :
"false";
211 validPathAttrs[IS_DIR] = isDir ?
"true" :
"false";
212 validPathAttrs[IS_ACCESSIBLE] = canRead ?
"true" :
"false";
215 std::ostringstream os_size;
217 validPathAttrs[SIZE] = os_size.str();
220 std::ostringstream os_time;
222 validPathAttrs[LMT] = os_time.str();
224 info->add_tag(VALID_PATH, validPath, &validPathAttrs);
225 info->add_tag(REMAINDER, remainder);
227 info->end_tag(PATH_INFO_RESPONSE);
230 info->end_response();
232 BESDEBUG(SPI_DEBUG_KEY,
"ShowPathInfoResponseHandler::execute() - END" << endl);
248 if (d_response_object) {
263 strm << BESIndent::LMarg <<
"ShowPathInfoResponseHandler::dump - (" << (
void *)
this <<
")" << std::endl;
266 BESIndent::UnIndent();
270 ShowPathInfoResponseHandler::ShowPathInfoResponseBuilder(
const string &name)
278 void ShowPathInfoResponseHandler::eval_resource_path(
const string &resource_path,
const string &catalog_root,
279 const bool follow_sym_links,
string &validPath,
bool &isFile,
bool &isDir,
long long &size,
280 long long &lastModifiedTime,
bool &canRead,
string &remainder)
283 BESDEBUG(SPI_DEBUG_KEY,
284 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"CatalogRoot: "<< catalog_root << endl);
286 BESDEBUG(SPI_DEBUG_KEY,
287 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"resourceID: "<< resource_path << endl);
292 lastModifiedTime = -1;
295 string rem = resource_path;
301 int (*ye_old_stat_function)(
const char *pathname,
struct stat *buf);
302 if (follow_sym_links) {
303 BESDEBUG(SPI_DEBUG_KEY,
304 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Using 'stat' function (follow_sym_links = true)" << endl);
305 ye_old_stat_function = &stat;
308 BESDEBUG(SPI_DEBUG_KEY,
309 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Using 'lstat' function (follow_sym_links = false)" << endl);
310 ye_old_stat_function = &lstat;
315 if (resource_path ==
"") {
316 BESDEBUG(SPI_DEBUG_KEY,
"ShowPathInfoResponseHandler::"<<__func__ <<
"() - The resourceID is empty" << endl);
322 string::size_type dotdot = resource_path.find(
"..");
323 if (dotdot != string::npos) {
324 BESDEBUG(SPI_DEBUG_KEY,
325 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
" ERROR: The resourceID '" << resource_path <<
"' contains the substring '..' This is Forbidden." << endl);
326 string s = (string)
"Invalid node name '" + resource_path +
"' ACCESS IS FORBIDDEN";
337 string fullpath = catalog_root;
346 size_t slash = rem.find(
'/');
347 if (slash == string::npos) {
348 BESDEBUG(SPI_DEBUG_KEY,
349 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Checking final path component: " << rem << endl);
358 rem = rem.substr(slash + 1, rem.length() - slash);
361 BESDEBUG(SPI_DEBUG_KEY,
362 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"validPath: "<< validPath << endl);
363 BESDEBUG(SPI_DEBUG_KEY,
364 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"checking: "<< checking << endl);
365 BESDEBUG(SPI_DEBUG_KEY,
366 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"fullpath: "<< fullpath << endl);
368 BESDEBUG(SPI_DEBUG_KEY,
"ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"rem: "<< rem << endl);
370 BESDEBUG(SPI_DEBUG_KEY,
371 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"remainder: "<< remainder << endl);
374 int statret = ye_old_stat_function(fullpath.c_str(), &sb);
378 validPath = checking;
385 char *s_err = strerror(errsv);
386 string error =
"Unable to access node " + checking +
": ";
388 error = error + s_err;
391 error = error +
"unknown access error";
393 BESDEBUG(SPI_DEBUG_KEY,
394 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"error: "<< error <<
" errno: " << errno << endl);
396 BESDEBUG(SPI_DEBUG_KEY,
397 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"remainder: '" << remainder <<
"'" << endl);
401 if (errsv != ENOENT && errsv != ENOTDIR) {
406 size_t s_loc = remainder.find(
'/');
407 if (s_loc == string::npos) {
409 string basename = remainder;
410 bool moreDots =
true;
413 size_t d_loc = basename.find_last_of(
".");
414 if (d_loc != string::npos) {
415 basename = basename.substr(0, d_loc);
416 BESDEBUG(SPI_DEBUG_KEY,
417 "ShowPathInfoResponseHandler::" << __func__ <<
"() - basename: "<< basename << endl);
419 string candidate_remainder = remainder.substr(basename.length());
420 BESDEBUG(SPI_DEBUG_KEY,
421 "ShowPathInfoResponseHandler::" << __func__ <<
"() - candidate_remainder: "<< candidate_remainder << endl);
424 BESDEBUG(SPI_DEBUG_KEY,
425 "ShowPathInfoResponseHandler::" << __func__ <<
"() - candidate_path: "<< candidate_path << endl);
428 BESDEBUG(SPI_DEBUG_KEY,
429 "ShowPathInfoResponseHandler::" << __func__ <<
"() - full_candidate_path: "<< full_candidate_path << endl);
432 int statret1 = ye_old_stat_function(full_candidate_path.c_str(), &sb1);
433 if (statret1 != -1) {
434 validPath = candidate_path;
435 remainder = candidate_remainder;
440 BESDEBUG(SPI_DEBUG_KEY,
441 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"No dots in remainder: "<< remainder << endl);
447 BESDEBUG(SPI_DEBUG_KEY,
448 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Remainder has slash pollution: "<< remainder << endl);
454 statret = ye_old_stat_function(fullpath.c_str(), &sb);
455 if (S_ISREG(sb.st_mode)) {
456 BESDEBUG(SPI_DEBUG_KEY,
457 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"'"<< fullpath <<
"' Is regular file." << endl);
461 else if (S_ISDIR(sb.st_mode)) {
462 BESDEBUG(SPI_DEBUG_KEY,
463 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"'"<< fullpath <<
"' Is directory." << endl);
467 else if (S_ISLNK(sb.st_mode)) {
468 BESDEBUG(SPI_DEBUG_KEY,
469 "ShowPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"'"<< fullpath <<
"' Is symbolic Link." << endl);
470 string error =
"Service not configured to traverse symbolic links as embodied by the node '" + checking
471 +
"' ACCESS IS FORBIDDEN";
478 std::ifstream ifile(fullpath.c_str());
479 canRead = ifile.good();
492 #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
494 lastModifiedTime = (sb.st_mtimespec.tv_sec * 1000) + (sb.st_mtimespec.tv_nsec / 1000000);
496 lastModifiedTime = sb.st_mtime;
500 BESDEBUG(SPI_DEBUG_KEY,
"ShowPathInfoResponseHandler::" << __func__ <<
"() - fullpath: " << fullpath << endl);
501 BESDEBUG(SPI_DEBUG_KEY,
"ShowPathInfoResponseHandler::" << __func__ <<
"() - validPath: " << validPath << endl);
502 BESDEBUG(SPI_DEBUG_KEY,
"ShowPathInfoResponseHandler::" << __func__ <<
"() - remainder: " << remainder << endl);
503 BESDEBUG(SPI_DEBUG_KEY,
"ShowPathInfoResponseHandler::" << __func__ <<
"() - rem: " << rem << endl);
504 BESDEBUG(SPI_DEBUG_KEY,
505 "ShowPathInfoResponseHandler::" << __func__ <<
"() - isFile: " << (isFile?
"true":
"false") << endl);
506 BESDEBUG(SPI_DEBUG_KEY,
507 "ShowPathInfoResponseHandler::" << __func__ <<
"() - isDir: " << (isDir?
"true":
"false") << endl);
508 BESDEBUG(SPI_DEBUG_KEY,
509 "ShowPathInfoResponseHandler::" << __func__ <<
"() - access: " << (canRead?
"true":
"false") << endl);
510 BESDEBUG(SPI_DEBUG_KEY,
"ShowPathInfoResponseHandler::" << __func__ <<
"() - size: " << size << endl);
511 BESDEBUG(SPI_DEBUG_KEY,
512 "ShowPathInfoResponseHandler::" << __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 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...
virtual void dump(std::ostream &strm) const
dumps information about this object