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" 56 #define PATH_INFO_RESPONSE "PathInfo" 58 #define VALID_PATH "validPath" 59 #define REMAINDER "remainder" 60 #define IS_DATA "isData" 61 #define IS_FILE "isFile" 62 #define IS_DIR "isDir" 63 #define IS_ACCESSIBLE "access" 65 #define LMT "lastModified" 67 GatewayPathInfoResponseHandler::GatewayPathInfoResponseHandler(
const string &name) :
72 GatewayPathInfoResponseHandler::~GatewayPathInfoResponseHandler()
89 if (BESISDEBUG(TIMING_LOG)) sw.
start(
"GatewayPathInfoResponseHandler::execute", dhi.
data[REQUEST_ID]);
91 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::execute() - BEGIN" << endl );
93 BESInfo *info = BESInfoList::TheList()->build_info();
96 string container = dhi.
data[CONTAINER];
104 throw BESInternalError(
"Not able to find the default catalog.", __FILE__, __LINE__);
107 string::size_type notslash = container.find_first_not_of(
"/", 0);
108 if (notslash != string::npos) {
109 container = container.substr(notslash);
114 string::size_type slash = container.find_first_of(
"/", 0);
115 if (slash != string::npos) {
116 catname = container.substr(0, slash);
126 if (slash != string::npos) {
127 container = container.substr(slash + 1);
130 notslash = container.find_first_not_of(
"/", 0);
131 if (notslash != string::npos) {
132 container = container.substr(notslash);
140 if (container.empty()) container =
"/";
142 if (container[0] !=
'/') container =
"/" + container;
144 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::execute() - container: " << container << endl );
148 map<string, string> pathInfoAttrs;
149 pathInfoAttrs[PATH] = container;
151 info->begin_tag(PATH_INFO_RESPONSE, &pathInfoAttrs);
153 string validPath, remainder;
154 bool isFile, isDir, canRead;
155 long long size, time;
163 time, canRead, remainder);
170 if (validPath.length() != 0) {
177 string err = (string)
"Failed to find the validPath node " + validPath
178 +
" this should not be possible. Some thing BAD is happening.";
183 list<string> services = entry->get_service_list();
186 if (services.size()) {
187 list<string>::const_iterator si = services.begin();
188 list<string>::const_iterator se = services.end();
189 for (; si != se; si++) {
190 if ((*si) == OPENDAP_SERVICE) isData =
true;
195 map<string, string> validPathAttrs;
196 validPathAttrs[IS_DATA] = isData ?
"true" :
"false";
197 validPathAttrs[IS_FILE] = isFile ?
"true" :
"false";
198 validPathAttrs[IS_DIR] = isDir ?
"true" :
"false";
199 validPathAttrs[IS_ACCESSIBLE] = canRead ?
"true" :
"false";
202 std::ostringstream os_size;
204 validPathAttrs[SIZE] = os_size.str();
207 std::ostringstream os_time;
209 validPathAttrs[LMT] = os_time.str();
211 info->add_tag(VALID_PATH, validPath, &validPathAttrs);
212 info->add_tag(REMAINDER, remainder);
214 info->end_tag(PATH_INFO_RESPONSE);
217 info->end_response();
219 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::execute() - END" << endl );
237 BESInfo *info = dynamic_cast<BESInfo *>(_response);
251 strm << BESIndent::LMarg <<
"GatewayPathInfoResponseHandler::dump - (" << (
void *)
this <<
")" << std::endl;
254 BESIndent::UnIndent();
258 GatewayPathInfoResponseHandler::GatewayPathInfoResponseBuilder(
const string &name)
267 const bool follow_sym_links,
string &validPath,
bool &isFile,
bool &isDir,
long long &size,
268 long long &lastModifiedTime,
bool &canRead,
string &remainder)
271 BESDEBUG(SPI_DEBUG_KEY,
272 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"CatalogRoot: "<< catalog_root << endl);
274 BESDEBUG(SPI_DEBUG_KEY,
275 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"resourceID: "<< resource_path << endl);
280 lastModifiedTime = -1;
283 string rem = resource_path;
289 int (*ye_old_stat_function)(
const char *pathname,
struct stat *buf);
290 if (follow_sym_links) {
291 BESDEBUG(SPI_DEBUG_KEY,
292 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Using 'stat' function (follow_sym_links = true)" << endl);
293 ye_old_stat_function = &stat;
296 BESDEBUG(SPI_DEBUG_KEY,
297 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Using 'lstat' function (follow_sym_links = false)" << endl);
298 ye_old_stat_function = &lstat;
303 if (resource_path ==
"") {
304 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::"<<__func__ <<
"() - The resourceID is empty" << endl);
310 string::size_type dotdot = resource_path.find(
"..");
311 if (dotdot != string::npos) {
312 BESDEBUG(SPI_DEBUG_KEY,
313 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
" ERROR: The resourceID '" << resource_path <<
"' contains the substring '..' This is Forbidden." << endl);
314 string s = (string)
"Invalid node name '" + resource_path +
"' ACCESS IS FORBIDDEN";
324 string fullpath = catalog_root;
333 size_t slash = rem.find(
'/');
334 if (slash == string::npos) {
335 BESDEBUG(SPI_DEBUG_KEY,
336 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Checking final path component: " << rem << endl);
345 rem = rem.substr(slash + 1, rem.length() - slash);
348 BESDEBUG(SPI_DEBUG_KEY,
349 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"validPath: "<< validPath << endl);
350 BESDEBUG(SPI_DEBUG_KEY,
351 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"checking: "<< checking << endl);
352 BESDEBUG(SPI_DEBUG_KEY,
353 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"fullpath: "<< fullpath << endl);
355 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"rem: "<< rem << endl);
357 BESDEBUG(SPI_DEBUG_KEY,
358 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"remainder: "<< remainder << endl);
361 int statret = ye_old_stat_function(fullpath.c_str(), &sb);
365 validPath = checking;
372 char *s_err = strerror(errsv);
373 string error =
"Unable to access node " + checking +
": ";
375 error = error + s_err;
378 error = error +
"unknown access error";
380 BESDEBUG(SPI_DEBUG_KEY,
381 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"error: "<< error <<
" errno: " << errno << endl);
383 BESDEBUG(SPI_DEBUG_KEY,
384 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"remainder: '" << remainder <<
"'" << endl);
388 if (errsv != ENOENT && errsv != ENOTDIR) {
393 size_t s_loc = remainder.find(
'/');
394 if (s_loc == string::npos) {
396 string basename = remainder;
397 bool moreDots =
true;
400 size_t d_loc = basename.find_last_of(
".");
401 if (d_loc != string::npos) {
402 basename = basename.substr(0, d_loc);
403 BESDEBUG(SPI_DEBUG_KEY,
404 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - basename: "<< basename << endl);
406 string candidate_remainder = remainder.substr(basename.length());
407 BESDEBUG(SPI_DEBUG_KEY,
408 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - candidate_remainder: "<< candidate_remainder << endl);
411 BESDEBUG(SPI_DEBUG_KEY,
412 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - candidate_path: "<< candidate_path << endl);
415 BESDEBUG(SPI_DEBUG_KEY,
416 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - full_candidate_path: "<< full_candidate_path << endl);
419 int statret1 = ye_old_stat_function(full_candidate_path.c_str(), &sb1);
420 if (statret1 != -1) {
421 validPath = candidate_path;
422 remainder = candidate_remainder;
427 BESDEBUG(SPI_DEBUG_KEY,
428 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"No dots in remainder: "<< remainder << endl);
434 BESDEBUG(SPI_DEBUG_KEY,
435 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"Remainder has slash pollution: "<< remainder << endl);
441 statret = ye_old_stat_function(fullpath.c_str(), &sb);
442 if (S_ISREG(sb.st_mode)) {
443 BESDEBUG(SPI_DEBUG_KEY,
444 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"'"<< fullpath <<
"' Is regular file." << endl);
448 else if (S_ISDIR(sb.st_mode)) {
449 BESDEBUG(SPI_DEBUG_KEY,
450 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"'"<< fullpath <<
"' Is directory." << endl);
454 else if (S_ISLNK(sb.st_mode)) {
455 BESDEBUG(SPI_DEBUG_KEY,
456 "GatewayPathInfoResponseHandler::"<<__func__ <<
"() - " <<
"'"<< fullpath <<
"' Is symbolic Link." << endl);
457 string error =
"Service not configured to traverse symbolic links as embodied by the node '" + checking
458 +
"' ACCESS IS FORBIDDEN";
465 std::ifstream ifile(fullpath.c_str());
466 canRead = ifile.good();
478 #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) 480 lastModifiedTime = (sb.st_mtimespec.tv_sec * 1000) + (sb.st_mtimespec.tv_nsec / 1000000);
482 lastModifiedTime = sb.st_mtime;
485 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::" << __func__ <<
"() - fullpath: " << fullpath << endl);
486 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::" << __func__ <<
"() - validPath: " << validPath << endl);
487 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::" << __func__ <<
"() - remainder: " << remainder << endl);
488 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::" << __func__ <<
"() - rem: " << rem << endl);
489 BESDEBUG(SPI_DEBUG_KEY,
490 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - isFile: " << (isFile?
"true":
"false") << endl);
491 BESDEBUG(SPI_DEBUG_KEY,
492 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - isDir: " << (isDir?
"true":
"false") << endl);
493 BESDEBUG(SPI_DEBUG_KEY,
494 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - access: " << (canRead?
"true":
"false") << endl);
495 BESDEBUG(SPI_DEBUG_KEY,
"GatewayPathInfoResponseHandler::" << __func__ <<
"() - size: " << size << endl);
496 BESDEBUG(SPI_DEBUG_KEY,
497 "GatewayPathInfoResponseHandler::" << __func__ <<
"() - LMT: " << lastModifiedTime << endl);
void eval_resource_path(const string &resource_path, const string &catalog_root, const bool follow_sym_links, string &validPath, bool &isFile, bool &isDir, long long &size, long long &lastModifiedTime, bool &canRead, string &remainder)
response handler that returns nodes or leaves within the catalog either at the root or at a specified...
exception thrown if inernal error encountered
virtual void dump(ostream &strm) const
dumps information about this object
virtual void transmit(BESTransmitter *transmitter, BESDataHandlerInterface &dhi)=0
transmit the informational object
virtual BESCatalogEntry * show_catalog(const std::string &container, BESCatalogEntry *entry)=0
virtual void transmit(BESTransmitter *transmitter, BESDataHandlerInterface &dhi)
transmit the response object built by the execute command using the specified transmitter object
virtual bool start(string name)
handler object that knows how to create a specific response object
informational response object
virtual std::string default_catalog_name() const
The name of the default catalog.
const std::string & get_root_dir() const
Get the root directory of the catalog.
Catalogs provide a hierarchical organization for data.
error thrown if the BES is not allowed to access the resource requested
Structure storing information used by the BES to handle the request.
map< string, string > data
the map of string data that will be required for the current request.
virtual void execute(BESDataHandlerInterface &dhi)
executes the command 'show catalog|leaves [for <node>];' by returning nodes or leaves at the top leve...
virtual void begin_response(const string &response_name, BESDataHandlerInterface &dhi)
begin the informational response
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual BESCatalog * default_catalog() const
The the default catalog.
virtual BESCatalogUtils * get_catalog_utils() const
Get a pointer to the utilities, customized for this catalog.
static BESCatalogList * TheCatalogList()
Get the singleton BESCatalogList instance.
static string assemblePath(const string &firstPart, const string &secondPart, bool leadingSlash=false, bool trailingSlash=false)
Assemble path fragments making sure that they are separated by a single '/' character.