37#include <sys/resource.h>
60#include "TheBESKeys.h"
63#include "BESForbiddenError.h"
64#include "BESNotFoundError.h"
65#include "BESInternalError.h"
67#include "BESCatalogList.h"
69#include "BESInternalFatalError.h"
70#include "RequestServiceTimer.h"
77#define prolog string("BESUtil::").append(__func__).append("() - ")
79const string BES_KEY_TIMEOUT_CANCEL =
"BES.CancelTimeoutOnSend";
89 if (getrusage(RUSAGE_SELF, &usage) == 0) {
93 return usage.ru_maxrss / 1024;
95 return usage.ru_maxrss;
112 if (!value.empty() && value.back() ==
'/')
125 if (!value.empty() && value[0] ==
'"')
127 if (!value.empty() && value.back() ==
'"')
138 strm <<
"HTTP/1.0 200 OK" << CRLF;
139 strm <<
"XBES-Server: " << PACKAGE_STRING << CRLF;
141 const time_t t = time(0);
142 strm <<
"Date: " << rfc822_date(t).c_str() << CRLF;
143 strm <<
"Last-Modified: " << rfc822_date(t).c_str() << CRLF;
145 strm <<
"Content-Type: text/plain" << CRLF;
147 strm <<
"Content-Description: unknown" << CRLF;
157 strm <<
"HTTP/1.0 200 OK" << CRLF;
158 strm <<
"XBES-Server: " << PACKAGE_STRING << CRLF;
160 const time_t t = time(0);
161 strm <<
"Date: " << rfc822_date(t).c_str() << CRLF;
162 strm <<
"Last-Modified: " << rfc822_date(t).c_str() << CRLF;
164 strm <<
"Content-type: text/html" << CRLF;
166 strm <<
"Content-Description: unknown" << CRLF;
202static const char *days[] = {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat" };
203static const char *months[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec" };
214string BESUtil::rfc822_date(
const time_t t)
220 snprintf(d, 255,
"%s, %02d %s %4d %02d:%02d:%02d GMT", days[stm.tm_wday], stm.tm_mday,
221 months[stm.tm_mon], 1900 + stm.tm_year, stm.tm_hour, stm.tm_min, stm.tm_sec);
226string BESUtil::unhexstring(
const string& s)
230 ss >> std::hex >> val;
232 tmp_str[0] =
static_cast<char>(val);
241 string::size_type i = 0;
243 while ((i = res.find_first_of(escape, i)) != string::npos) {
244 if (except.find(res.substr(i, 3)) != string::npos) {
248 res.replace(i, 3, unhexstring(res.substr(i + 1, 2)));
256 string return_string = s;
257 for (
int j = 0; j < static_cast<int>(return_string.length()); j++) {
258 return_string[j] = (char) tolower(return_string[j]);
261 return return_string;
267 string::size_type index = 0;
271 string::size_type bs = s.find(
'\\', index);
272 if (bs == string::npos) {
273 new_str += s.substr(index, s.length() - index);
277 new_str += s.substr(index, bs - index);
278 new_str += s[bs + 1];
291static void throw_access_error(
const string &pathname,
long error_number)
293 switch(error_number) {
296 string message = string(
"Failed to locate '").append(pathname).append(
"'");
302 string message = string(
"Not allowed to access '").append(pathname).append(
"'");
315bool pathname_contains_symlink(
const string &path,
int search_limit)
321 string pathname = path;
322 if (!pathname.empty() && pathname.back() ==
'/') {
326 bool is_link =
false;
332 int status = lstat(pathname.c_str(), &buf);
334 is_link = S_ISLNK(buf.st_mode);
337 string msg =
"Could not resolve path when testing for symbolic links: ";
338 msg.append(strerror(errno));
339 BESDEBUG(MODULE, prolog << msg << endl);
344 pos = pathname.find_last_of(
'/');
345 if (pos != string::npos)
347 }
while (++i < search_limit && !is_link && pos != string::npos && !pathname.empty());
355 ssize_t len = readlinkat(AT_FDCWD, pathname.c_str(),
nullptr, 0);
362 string msg =
"Could not resolve path when testing for symbolic links: ";
363 msg.append(strerror(errno));
384 if (path ==
"")
return;
386 if (path.find(
"..") != string::npos) {
387 throw_access_error(path, EACCES);
394 string pathname = root;
396 if (pathname.back() !=
'/' && path.front() !=
'/')
397 pathname.append(
"/");
399 pathname.append(path);
400 if (access(pathname.c_str(), R_OK) != 0) {
401 throw_access_error(pathname, errno);
404 if (follow_sym_links ==
false) {
405 auto n = count(path.begin(), path.end(),
'/');
408 if (pathname_contains_symlink(pathname, n)) {
409 throw_access_error(pathname, EACCES);
427 if (base > 36 || base < 2)
432 if (val < 0) *buf++ =
'-';
433 r = ldiv(labs(val), base);
440 *buf++ =
"0123456789abcdefghijklmnopqrstuvwxyz"[(
int) r.rem];
448 string::size_type first = key.find_first_not_of(
" \t\n\r");
449 string::size_type last = key.find_last_not_of(
" \t\n\r");
450 if (first == string::npos)
453 string::size_type num = last - first + 1;
454 string new_key = key.substr(first, num);
460string BESUtil::entity(
char c)
486 string::size_type i = 0;
488 while ((i = in.find_first_of(not_allowed, i)) != string::npos) {
489 in.replace(i, 1, entity(in[i]));
503 string::size_type i = 0;
505 while ((i = in.find(
">", i)) != string::npos)
506 in.replace(i, 4,
">");
509 while ((i = in.find(
"<", i)) != string::npos)
510 in.replace(i, 4,
"<");
513 while ((i = in.find(
"&", i)) != string::npos)
514 in.replace(i, 5,
"&");
517 while ((i = in.find(
"'", i)) != string::npos)
518 in.replace(i, 6,
"'");
521 while ((i = in.find(
""", i)) != string::npos)
522 in.replace(i, 6,
"\"");
542 std::string::size_type start = 0;
543 std::string::size_type qstart = 0;
544 std::string::size_type adelim = 0;
545 std::string::size_type aquote = 0;
549 if (str[start] ==
'"') {
550 bool endquote =
false;
553 aquote = str.find(
'"', qstart);
554 if (aquote == string::npos) {
555 string currval = str.substr(start, str.length() - start);
556 string err =
"BESUtil::explode - No end quote after value " + currval;
561 if (str[aquote - 1] ==
'\\') {
562 if (str[aquote - 2] ==
'\\') {
575 if (str[qstart] != delim && qstart != str.length()) {
576 string currval = str.substr(start, qstart - start);
577 string err =
"BESUtil::explode - No delim after end quote " + currval;
580 if (qstart == str.length()) {
581 adelim = string::npos;
588 adelim = str.find(delim, start);
590 if (adelim == string::npos) {
591 aval = str.substr(start, str.length() - start);
595 aval = str.substr(start, adelim - start);
598 values.push_back(aval);
600 if (start == str.length()) {
601 values.push_back(
"");
620 list<string>::const_iterator i = values.begin();
621 list<string>::const_iterator e = values.end();
624 for (; i != e; i++) {
625 if (!first) result += delim;
626 d = (*i).find(delim);
627 if (d != string::npos && (*i)[0] !=
'"') {
628 string err = (string)
"BESUtil::implode - delimiter exists in value " + (*i);
661 string::size_type colon = url_str.find(
":");
662 if (colon == string::npos) {
663 string err =
"BESUtil::url_explode: missing colon for protocol";
667 url_parts.protocol = url_str.substr(0, colon);
669 if (url_str.substr(colon, 3) !=
"://") {
670 string err =
"BESUtil::url_explode: no :// in the URL";
675 rest = url_str.substr(colon);
677 string::size_type slash = rest.find(
"/");
678 if (slash == string::npos) slash = rest.length();
680 string::size_type at = rest.find(
"@");
681 if ((at != string::npos) && (at < slash)) {
683 string up = rest.substr(0, at);
684 colon = up.find(
":");
685 if (colon != string::npos) {
686 url_parts.uname = up.substr(0, colon);
687 url_parts.psswd = up.substr(colon + 1);
690 url_parts.uname = up;
693 rest = rest.substr(at + 1);
695 slash = rest.find(
"/");
696 if (slash == string::npos) slash = rest.length();
697 colon = rest.find(
":");
698 if ((colon != string::npos) && (colon < slash)) {
700 url_parts.domain = rest.substr(0, colon);
702 rest = rest.substr(colon + 1);
703 slash = rest.find(
"/");
704 if (slash != string::npos) {
705 url_parts.port = rest.substr(0, slash);
706 url_parts.path = rest.substr(slash + 1);
709 url_parts.port = rest;
714 slash = rest.find(
"/");
715 if (slash != string::npos) {
716 url_parts.domain = rest.substr(0, slash);
717 url_parts.path = rest.substr(slash + 1);
720 url_parts.domain = rest;
727 string url = url_parts.protocol +
"://";
728 if (!url_parts.uname.empty()) {
729 url += url_parts.uname;
730 if (!url_parts.psswd.empty()) url +=
":" + url_parts.psswd;
733 url += url_parts.domain;
734 if (!url_parts.port.empty()) url +=
":" + url_parts.port;
735 if (!url_parts.path.empty()) url +=
"/" + url_parts.path;
753 string first = firstPart;
754 string second = secondPart;
755 string sep(1,separator);
759 while (!first.empty() && *first.rbegin() == separator) {
761 first = first.substr(0, first.length() - 1);
764 while (!second.empty() && second[0] == separator) {
772 else if (second.empty()) {
776 newPath = first.append(sep).append(second);
801string BESUtil::assemblePath(
const string &firstPart,
const string &secondPart,
bool leadingSlash,
bool trailingSlash)
803 BESDEBUG(MODULE, prolog <<
"firstPart: '" << firstPart <<
"'" << endl);
804 BESDEBUG(MODULE, prolog <<
"secondPart: '" << secondPart <<
"'" << endl);
808 if (newPath.empty()) {
811 else if (newPath.front() !=
'/') {
812 newPath =
"/" + newPath;
817 if (newPath.empty() || newPath.back() !=
'/') {
822 while (!newPath.empty() && newPath.back() ==
'/')
823 newPath.erase(newPath.length()-1);
826 BESDEBUG(MODULE, prolog <<
"newPath: " << newPath << endl);
836 if (fullString.length() >= ending.length()) {
837 return (0 == fullString.compare(fullString.length() - ending.length(), ending.length(), ending));
869 msg <<
"The submitted request took too long to service.";
897 const string false_str =
"false";
898 const string no_str =
"no";
900 bool cancel_timeout_on_send =
true;
907 if ( value == false_str || value == no_str) cancel_timeout_on_send =
false;
909 BESDEBUG(MODULE, __func__ <<
"() - cancel_timeout_on_send: " << (cancel_timeout_on_send ?
"true" :
"false") << endl);
910 if (cancel_timeout_on_send) {
923 unsigned int replace_count = 0;
924 size_t pos = s.find(find_this);
925 while (pos != string::npos) {
927 s.replace(pos, find_this.size(), replace_with_this);
929 pos = s.find(find_this, pos + replace_with_this.size());
932 return replace_count;
946string BESUtil::normalize_path(
const string &raw_path,
bool leading_separator,
bool trailing_separator,
const string separator )
948 if (separator.length() != 1)
949 throw BESInternalError(
"Path separators must be a single character. The string '" + separator +
"' does not qualify.", __FILE__, __LINE__);
950 char separator_char = separator[0];
951 string double_separator;
952 double_separator = double_separator.append(separator).append(separator);
954 string path(raw_path);
961 if (path == separator) {
964 if (leading_separator) {
965 if (path[0] != separator_char) {
966 path = string(separator).append(path);
970 if (path[0] == separator_char) {
971 path = path.substr(1);
974 if (trailing_separator) {
975 if (*path.rbegin() != separator_char) {
976 path = path.append(separator);
980 if (*path.rbegin() == separator_char) {
981 path = path.substr(0, path.length() - 1);
995 string::size_type lastPos = str.find_first_not_of(delimiters, 0);
997 string::size_type pos = str.find_first_of(delimiters, lastPos);
998 while (string::npos != pos || string::npos != lastPos) {
1000 tokens.push_back(str.substr(lastPos, pos - lastPos));
1002 lastPos = str.find_first_not_of(delimiters, pos);
1004 pos = str.find_first_of(delimiters, lastPos);
1016 return get_time(time(0), use_local_time);
1028 char buf[
sizeof "YYYY-MM-DDTHH:MM:SS zones"];
1038 if (!use_local_time) {
1039 gmtime_r(&the_time, &result);
1040 status = strftime(buf,
sizeof buf,
"%FT%T%Z", &result);
1043 localtime_r(&the_time, &result);
1044 status = strftime(buf,
sizeof buf,
"%FT%T%Z", &result);
1048 ERROR_LOG(prolog +
"Error formatting time value!");
1049 return "date-format-error";
1069 vector<string> tokens;
1071 while (getline(ss, item, delim)) {
1073 if (item.empty() && skip_empty)
1076 tokens.push_back(item);
1082BESCatalog *BESUtil::separateCatalogFromPath(std::string &ppath)
1085 vector<string> path_tokens;
1089 BESDEBUG(MODULE, prolog <<
"Normalized path: " << path << endl);
1094 string use_container = ppath;
1098 if (!path_tokens.empty()) {
1099 BESDEBUG(MODULE,
"First path token: " << path_tokens[0] << endl);
1102 BESDEBUG(MODULE, prolog <<
"Located catalog " << catalog->
get_catalog_name() <<
" from path component" << endl);
1107 BESDEBUG(MODULE, prolog <<
"Modified container/path value to: " << use_container << endl);
1114void ios_state_msg(std::ios &ios_ref, std::stringstream &msg) {
1115 msg <<
" {ios.good()=" << (ios_ref.good() ?
"true" :
"false") <<
"}";
1116 msg <<
" {ios.eof()=" << (ios_ref.eof()?
"true":
"false") <<
"}";
1117 msg <<
" {ios.fail()=" << (ios_ref.fail()?
"true":
"false") <<
"}";
1118 msg <<
" {ios.bad()=" << (ios_ref.bad()?
"true":
"false") <<
"}";
1123#define OUTPUT_FILE_BLOCK_SIZE 4096
1135 msg << prolog <<
"Using ostream: " << (
void *) &o_strm <<
" cout: " << (
void *) &cout << endl;
1136 BESDEBUG(MODULE, msg.str());
1137 INFO_LOG( msg.str());
1139 vector<char> rbuffer(OUTPUT_FILE_BLOCK_SIZE);
1140 std::ifstream i_stream(file_name, std::ios_base::in | std::ios_base::binary);
1143 if(!i_stream.good()){
1145 msg << prolog <<
"Failed to open file " << file_name;
1146 ios_state_msg(i_stream, msg);
1147 BESDEBUG(MODULE, msg.str() << endl);
1154 msg << prolog <<
"Problem with ostream. " << file_name;
1155 ios_state_msg(i_stream, msg);
1156 BESDEBUG(MODULE, msg.str() << endl);
1162 uint64_t tcount = 0;
1163 while (i_stream.good() && o_strm.good()){
1164 i_stream.read(rbuffer.data(), OUTPUT_FILE_BLOCK_SIZE);
1165 o_strm.write(rbuffer.data(), i_stream.gcount());
1166 tcount += i_stream.gcount();
1171 if(i_stream.fail() && !i_stream.eof()){
1173 msg << prolog <<
"There was an ifstream error when reading from: " << file_name;
1174 ios_state_msg(i_stream, msg);
1175 msg <<
" last_lap: " << i_stream.gcount() <<
" bytes";
1176 msg <<
" total_read: " << tcount <<
" bytes";
1177 BESDEBUG(MODULE, msg.str() << endl);
1182 if (!i_stream.eof()){
1184 msg << prolog <<
"Failed to reach EOF on source file: " << file_name;
1185 ios_state_msg(i_stream, msg);
1186 msg <<
" last_lap: " << i_stream.gcount() <<
" bytes";
1187 msg <<
" total_read: " << tcount <<
" bytes";
1188 BESDEBUG(MODULE, msg.str() << endl);
1195 msg << prolog <<
"There was an ostream error during transmit. Transmitted " << tcount <<
" bytes.";
1196 ios_state_msg(o_strm, msg);
1197 auto crntpos = o_strm.tellp();
1198 msg <<
" current_position: " << crntpos << endl;
1199 BESDEBUG(MODULE, msg.str());
1200 ERROR_LOG(msg.str());
1204 msg << prolog <<
"Sent "<< tcount <<
" bytes from file '" << file_name<<
"'. " << endl;
1205 BESDEBUG(MODULE,msg.str());
1206 INFO_LOG(msg.str());
1209uint64_t BESUtil::file_to_stream_helper(
const std::string &file_name, std::ostream &o_strm, uint64_t byteCount){
1212 msg << prolog <<
"Using ostream: " << (
void *) &o_strm <<
" cout: " << (
void *) &cout << endl;
1213 BESDEBUG(MODULE, msg.str());
1214 INFO_LOG( msg.str());
1216 vector<char> rbuffer(OUTPUT_FILE_BLOCK_SIZE);
1217 std::ifstream i_stream(file_name, std::ios_base::in | std::ios_base::binary);
1220 if(!i_stream.good()){
1222 msg << prolog <<
"Failed to open file " << file_name;
1223 ios_state_msg(i_stream, msg);
1224 BESDEBUG(MODULE, msg.str() << endl);
1231 msg << prolog <<
"Problem with ostream. " << file_name;
1232 ios_state_msg(i_stream, msg);
1233 BESDEBUG(MODULE, msg.str() << endl);
1238 i_stream.seekg(byteCount);
1242 while (i_stream.good() && o_strm.good()){
1243 i_stream.read(rbuffer.data(), OUTPUT_FILE_BLOCK_SIZE);
1244 o_strm.write(rbuffer.data(), i_stream.gcount());
1245 BESDEBUG(MODULE,
"i_stream: " << i_stream.gcount() << endl);
1246 byteCount += i_stream.gcount();
1251 if(i_stream.fail() && !i_stream.eof()){
1253 msg << prolog <<
"There was an ifstream error when reading from: " << file_name;
1254 ios_state_msg(i_stream, msg);
1255 msg <<
" last_lap: " << i_stream.gcount() <<
" bytes";
1256 msg <<
" total_read: " << byteCount <<
" bytes";
1257 BESDEBUG(MODULE, msg.str() << endl);
1262 if (!i_stream.eof()){
1264 msg << prolog <<
"Failed to reach EOF on source file: " << file_name;
1265 ios_state_msg(i_stream, msg);
1266 msg <<
" last_lap: " << i_stream.gcount() <<
" bytes";
1267 msg <<
" total_read: " << byteCount <<
" bytes";
1268 BESDEBUG(MODULE, msg.str() << endl);
1275 msg << prolog <<
"There was an ostream error during transmit. Transmitted " << byteCount <<
" bytes.";
1276 ios_state_msg(o_strm, msg);
1277 auto crntpos = o_strm.tellp();
1278 msg <<
" current_position: " << crntpos << endl;
1279 BESDEBUG(MODULE, msg.str());
1280 ERROR_LOG(msg.str());
1284 msg <<
"Sent "<< byteCount <<
" bytes from file '" << file_name<<
"'. " << endl;
1285 BESDEBUG(MODULE,msg.str());
1286 INFO_LOG(msg.str());
1305 msg << prolog <<
"Using ostream: " << (
void *) &o_strm <<
" cout: " << (
void *) &cout << endl;
1306 BESDEBUG(MODULE, msg.str());
1307 INFO_LOG(msg.str());
1309 vector<char> rbuffer(OUTPUT_FILE_BLOCK_SIZE);
1311 std::ifstream i_stream(file_name, std::ios_base::in | std::ios_base::binary);
1313 int fd = open(file_name.c_str(), O_RDONLY | O_NONBLOCK);
1319 BESDEBUG(MODULE,
"Starting transfer" << endl);
1320 uint64_t tcount = 0;
1321 while (!i_stream.bad() && !i_stream.fail() && o_strm.good()) {
1322 if (file_write_done && i_stream.eof()) {
1323 BESDEBUG(MODULE,
"breaking out of loop" << endl);
1327 i_stream.read(rbuffer.data(), OUTPUT_FILE_BLOCK_SIZE);
1330 int status = read(fd, rbuffer.data(), OUTPUT_FILE_BLOCK_SIZE);
1334 else if (status == -1) {
1335 BESDEBUG(MODULE,
"read() call error: " << errno << endl);
1338 o_strm.write(rbuffer.data(), status);
1342 o_strm.write(rbuffer.data(), i_stream.gcount());
1343 tcount += i_stream.gcount();
1344 BESDEBUG(MODULE,
"transfer bytes " << tcount << endl);
1356 msg << prolog <<
"There was an ostream error during transmit. Transmitted " << tcount <<
" bytes.";
1357 ios_state_msg(o_strm, msg);
1358 auto crntpos = o_strm.tellp();
1359 msg <<
" current_position: " << crntpos << endl;
1360 BESDEBUG(MODULE, msg.str());
1361 INFO_LOG(msg.str());
1365 msg <<
"Sent "<< tcount <<
" bytes from file '" << file_name<<
"'. " << endl;
1366 BESDEBUG(MODULE,msg.str());
1367 INFO_LOG(msg.str());
1385void BESUtil::split(
const string &s,
const string &delimiter, vector<uint64_t> &res)
1387 const size_t delim_len = delimiter.length();
1389 size_t pos_start = 0, pos_end;
1391 while ((pos_end = s.find (delimiter, pos_start)) != string::npos) {
1392 res.push_back (stoull(s.substr(pos_start, pos_end - pos_start)));
1393 pos_start = pos_end + delim_len;
1396 res.push_back (stoull(s.substr (pos_start)));
1408void BESUtil::split(
const string &s,
const string &delimiter, vector<string> &res)
1410 const size_t delim_len = delimiter.length();
1412 size_t pos_start = 0, pos_end;
1414 while ((pos_end = s.find (delimiter, pos_start)) != string::npos) {
1415 res.push_back(s.substr(pos_start, pos_end - pos_start));
1416 pos_start = pos_end + delim_len;
1419 res.push_back(s.substr (pos_start));
static BESCatalogList * TheCatalogList()
Get the singleton BESCatalogList instance.
Catalogs provide a hierarchical organization for data.
virtual std::string get_catalog_name() const
Get the name for this catalog.
error thrown if the BES is not allowed to access the resource requested
exception thrown if internal error encountered
exception thrown if an internal error is found and is fatal to the BES
error thrown if the resource requested cannot be found
static std::vector< std::string > split(const std::string &s, char delim='/', bool skip_empty=true)
Splits the string s into the return vector of tokens using the delimiter delim and skipping empty val...
static uint64_t file_to_stream_task(const std::string &file_name, std::atomic< bool > &file_write_done, std::ostream &o_strm)
static void explode(char delim, const std::string &str, std::list< std::string > &values)
static long get_current_memory_usage() noexcept
Get the Resident Set Size in KB.
static void url_explode(const std::string &url_str, BESUtil::url &url_parts)
Given a url, break the url into its different parts.
static bool endsWith(std::string const &fullString, std::string const &ending)
static void tokenize(const std::string &str, std::vector< std::string > &tokens, const std::string &delimiters="/")
static void set_mime_text(std::ostream &strm)
Generate an HTTP 1.0 response header for a text document.
static std::string id2xml(std::string in, const std::string ¬_allowed="><&'\"")
static void conditional_timeout_cancel()
Checks if the timeout alarm should be canceled based on the value of the BES key BES....
static void check_path(const std::string &path, const std::string &root, bool follow_sym_links)
Is the combination of root + path a pathname the BES can/should access?
static void exit_on_request_timeout()
Checks if the timeout alarm should be canceled based on the value of the BES key BES....
static unsigned int replace_all(std::string &s, std::string find_this, std::string replace_with_this)
Operates on the string 's' to replaces every occurrence of the value of the string 'find_this' with t...
static void set_mime_html(std::ostream &strm)
Generate an HTTP 1.0 response header for a html document.
static std::string lowercase(const std::string &s)
static std::string pathConcat(const std::string &firstPart, const std::string &secondPart, char separator='/')
Concatenate path fragments making sure that they are separated by a single '/' character.
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.
static std::string www2id(const std::string &in, const std::string &escape="%", const std::string &except="")
static std::string implode(const std::list< std::string > &values, char delim)
static void trim_if_surrounding_quotes(std::string &value)
Remove double quotes around a string This function will remove a leading and/or trailing double quote...
static void file_to_stream(const std::string &file_name, std::ostream &o_strm)
Copies the contents of the file identified by file_name to the stream o_strm.
static std::string normalize_path(const std::string &path, bool leading_separator, bool trailing_separator, std::string separator="/")
Removes duplicate separators and provides leading and trailing separators as directed.
static std::string xml2id(std::string in)
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)....
static std::string unescape(const std::string &s)
static char * fastpidconverter(char *buf, int base)
static void removeLeadingAndTrailingBlanks(std::string &key)
static std::string get_time(bool use_local_time=false)
static RequestServiceTimer * TheTimer()
Return a pointer to a singleton timer instance. If an instance does not exist it will create and init...
void disable_timeout()
Set the time_out is disabled.
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()