45#include <libdap/BaseType.h>
46#include <libdap/DDS.h>
47#include <libdap/Constructor.h>
48#include <libdap/Array.h>
50using std::istringstream;
56#include "BESForbiddenError.h"
57#include "BESNotFoundError.h"
58#include "BESInternalError.h"
59#include "BESSyntaxUserError.h"
61#include "w10n_utils.h"
66void eval_resource_path(
const string &w10nResourceId,
const string &catalogRoot,
const bool follow_sym_links,
67 string &validPath,
bool &isFile,
bool &isDir,
string &remainder)
70 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - CatalogRoot: "<< catalogRoot << endl);
71 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - w10n resourceID: "<< w10nResourceId << endl);
76 int (*ye_old_stat_function)(
const char *pathname,
struct stat *buf);
77 if (follow_sym_links) {
78 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - Using 'stat' function (follow_sym_links = true)" << endl);
79 ye_old_stat_function = &stat;
82 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - Using 'lstat' function (follow_sym_links = false)" << endl);
83 ye_old_stat_function = &lstat;
88 if (w10nResourceId ==
"") {
89 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - w10n resourceID is empty" << endl);
98 string::size_type dotdot = w10nResourceId.find(
"..");
99 if (dotdot != string::npos) {
100 BESDEBUG(W10N_DEBUG_KEY,
101 "eval_resource_path() - ERROR: w10n resourceID '" << w10nResourceId <<
"' contains the substring '..' This is Forbidden." << endl);
102 string s = (string)
"Invalid node name '" + w10nResourceId +
"' ACCESS IS FORBIDDEN";
103 throw BESForbiddenError(s, __FILE__, __LINE__);
112 string rem = w10nResourceId;
116 if (!rem.empty() && rem[0] ==
'/') rem.erase(0, 1);
121 string fullpath = catalogRoot;
133 size_t slash = rem.find(
'/');
134 if (slash == string::npos) {
135 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - Checking final path component: " << rem << endl);
136 fullpath = fullpath +
"/" + rem;
137 checking = validPath +
"/" + rem;
142 fullpath = fullpath +
"/" + rem.substr(0, slash);
143 checking = validPath +
"/" + rem.substr(0, slash);
144 rem = rem.substr(slash + 1, rem.size() - slash);
147 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - fullpath: "<< fullpath << endl);
148 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - checking: "<< checking << endl);
151 int statret = ye_old_stat_function(fullpath.c_str(), &sb);
157 char *s_err = strerror(errsv);
158 string error =
"Unable to access node " + checking +
": ";
160 error = error + s_err;
163 error = error +
"unknown access error";
165 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - error: "<< error <<
" errno: " << errno << endl);
169 if (errsv == ENOENT || errsv == ENOTDIR) {
170 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - validPath: "<< validPath << endl);
171 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - remainder: "<< remainder << endl);
175 throw BESForbiddenError(error, __FILE__, __LINE__);
179 validPath = checking;
182 if (S_ISREG(sb.st_mode)) {
183 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - '"<< checking <<
"' Is regular file." << endl);
187 else if (S_ISDIR(sb.st_mode)) {
188 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - '"<< checking <<
"' Is directory." << endl);
192 else if (S_ISLNK(sb.st_mode)) {
193 BESDEBUG(W10N_DEBUG_KEY,
"eval_resource_path() - '"<< checking <<
"' Is symbolic Link." << endl);
194 string error =
"Service not configured to traverse symbolic links as embodied by the node '" + checking
195 +
"' ACCESS IS FORBIDDEN";
196 throw BESForbiddenError(error, __FILE__, __LINE__);
202std::string escape_for_json(
const std::string &input)
204 std::stringstream ss;
205 for (
size_t i = 0; i < input.size(); ++i) {
206 if (
unsigned(input[i]) <
'\x20' || input[i] ==
'\\' || input[i] ==
'"') {
207 ss <<
"\\u" << std::setfill(
'0') << std::setw(4) << std::hex << unsigned(input[i]);
216long computeConstrainedShape(libdap::Array *a, std::vector<unsigned int> *shape)
218 BESDEBUG(W10N_DEBUG_KEY,
"w10n::computeConstrainedShape() - BEGIN. Array name: "<< a->name() << endl);
220 libdap::Array::Dim_iter dIt;
225 unsigned int dimSize = 1;
229 BESDEBUG(W10N_DEBUG_KEY,
230 "w10n::computeConstrainedShape() - Array has " << a->dimensions(
true) <<
" dimensions."<< endl);
234 for (dIt = a->dim_begin(); dIt != a->dim_end(); dIt++) {
235 BESDEBUG(W10N_DEBUG_KEY,
236 "w10n::computeConstrainedShape() - Processing dimension '" << a->dimension_name(dIt)<<
"'. (dim# "<< dimNum <<
")"<< endl);
237 start = a->dimension_start(dIt,
true);
238 stride = a->dimension_stride(dIt,
true);
239 stop = a->dimension_stop(dIt,
true);
240 BESDEBUG(W10N_DEBUG_KEY,
241 "w10n::computeConstrainedShape() - start: " << start <<
" stride: " << stride <<
" stop: "<<stop<< endl);
243 dimSize = 1 + ((stop - start) / stride);
244 BESDEBUG(W10N_DEBUG_KEY,
"w10n::computeConstrainedShape() - dimSize: " << dimSize << endl);
246 (*shape)[dimNum++] = dimSize;
247 totalSize *= dimSize;
250 BESDEBUG(W10N_DEBUG_KEY,
"w10n::computeConstrainedShape() - totalSize: " << totalSize << endl);
251 BESDEBUG(W10N_DEBUG_KEY,
"w10n::computeConstrainedShape() - END." << endl);
256void checkConstrainedDDSForW10nDataCompatibility(libdap::DDS *dds)
260 for (libdap::DDS::Vars_iter i = dds->var_begin(); i != dds->var_end(); i++) {
261 libdap::BaseType *bt = (*i);
263 if (bt->is_constructor_type()) {
264 checkConstructorForW10nDataCompatibility((libdap::Constructor *) bt);
266 else if (bt->is_vector_type()) {
267 if (bt->var()->is_constructor_type()) {
268 string msg =
"Arrays of ";
269 msg += bt->type_name() +
" are not supported by the w10n service.";
270 BESDEBUG(W10N_DEBUG_KEY,
271 "w10n::checkConstrainedDDSForW10nDataCompatibility() - ERROR! " << msg << endl);
272 throw BESSyntaxUserError(msg, __FILE__, __LINE__);
279 if (markedCount > 1) {
280 string msg =
"More than one variable in the dataset is projected and that's a no-no for w10n data responses.";
281 BESDEBUG(W10N_DEBUG_KEY,
"w10n::checkConstrainedDDSForW10nDataCompatibility() - ERROR! " << msg << endl);
282 throw BESSyntaxUserError(msg, __FILE__, __LINE__);
286void checkConstructorForW10nDataCompatibility(libdap::Constructor *constructor)
289 for (libdap::Constructor::Vars_iter i = constructor->var_begin(); i != constructor->var_end(); i++) {
290 libdap::BaseType *bt = (*i);
293 if (bt->is_constructor_type()) {
294 checkConstructorForW10nDataCompatibility((libdap::Constructor *) bt);
296 else if (bt->is_vector_type()) {
297 if (bt->var()->is_constructor_type()) {
298 string msg =
"Arrays of ";
299 msg += bt->type_name() +
" are not supported by the w10n service.";
300 BESDEBUG(W10N_DEBUG_KEY,
301 "w10n::checkConstructorForW10nDataCompatibility() - ERROR! " << msg << endl);
302 throw BESSyntaxUserError(msg, __FILE__, __LINE__);
310 if (markedCount > 1) {
312 if (markedCount == constructor->element_count())
313 msg =
"The w10n protocol does not support data responses from nodes. The variable " + constructor->name()
314 +
" is a node variable.";
316 msg =
"More than one child variable of the node variable " + constructor->name()
317 +
" is projected and that's a no-no for w10n data responses.";
318 BESDEBUG(W10N_DEBUG_KEY,
"w10n::checkConstructorForW10nDataCompatibility() - ERROR! " << msg << endl);
319 throw BESSyntaxUserError(msg, __FILE__, __LINE__);
323bool allVariablesMarkedToSend(libdap::DDS *dds)
325 bool allMarked =
true;
327 for (libdap::DDS::Vars_iter vi = dds->var_begin(), ve = dds->var_end(); vi != ve; vi++) {
328 libdap::BaseType *v = *vi;
330 if (v->is_constructor_type()) {
331 allMarked = allMarked && allVariablesMarkedToSend((libdap::Constructor *) v);
333 else if (v->is_vector_type() && v->var()->is_constructor_type()) {
334 allMarked = allMarked && allVariablesMarkedToSend((libdap::Constructor *) v->var());
337 allMarked = allMarked &&
true;
341 allMarked = allMarked &&
false;
348bool allVariablesMarkedToSend(libdap::Constructor *ctor)
350 bool allMarked =
true;
352 libdap::Constructor::Vars_iter vi = ctor->var_begin();
353 libdap::Constructor::Vars_iter ve = ctor->var_end();
354 for (; vi != ve; vi++) {
355 libdap::BaseType *v = *vi;
357 if (v->is_constructor_type()) {
358 allMarked = allMarked && allVariablesMarkedToSend((libdap::Constructor *) v);
360 else if (v->is_vector_type() && v->var()->is_constructor_type()) {
361 allMarked = allMarked && allVariablesMarkedToSend((libdap::Constructor *) v->var());
364 allMarked = allMarked &&
true;
368 allMarked = allMarked &&
false;
static void trim_if_trailing_slash(std::string &value)
If the string ends in a slash, remove it This function works for empty strings (doing nothing)....