7 #ifndef __STDC_FORMAT_MACROS
9 #define __STDC_FORMAT_MACROS
13 #include "cvmfs_config.h"
29 #ifdef CVMFS_NAMESPACE_GUARD
30 namespace CVMFS_NAMESPACE_GUARD {
33 const char b64_table[] = {
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
34 'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
35 'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
36 'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
37 's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'0',
'1',
'2',
38 '3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'};
44 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
45 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
46 -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
47 61, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
48 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1,
49 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
50 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
53 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
54 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
55 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
56 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
57 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
58 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
69 const std::string::value_type b)
const {
70 return std::tolower(a) == std::tolower(b);
80 snprintf(buffer,
sizeof(buffer),
"%" PRId64, value);
81 return string(buffer);
86 snprintf(buffer,
sizeof(buffer),
"%" PRIu64, value);
87 return string(buffer);
92 snprintf(buffer,
sizeof(buffer),
"%02x", value);
93 return string(buffer);
98 snprintf(buffer,
sizeof(buffer),
"%.03f", value);
99 return string(buffer);
108 localtime_r(&seconds, ×tamp);
110 gmtime_r(&seconds, ×tamp);
113 const char *months[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
114 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"};
116 snprintf(buffer,
sizeof(buffer),
"%d %s %d %02d:%02d:%02d", timestamp.tm_mday,
117 months[timestamp.tm_mon], timestamp.tm_year + 1900,
118 timestamp.tm_hour, timestamp.tm_min, timestamp.tm_sec);
120 return string(buffer);
128 const char *months[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
129 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"};
130 const char *day_of_week[] = {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"};
133 time_t now = time(NULL);
134 gmtime_r(&now, ×tamp);
137 snprintf(buffer,
sizeof(buffer),
"%s, %02d %s %d %02d:%02d:%02d %s",
138 day_of_week[timestamp.tm_wday], timestamp.tm_mday,
139 months[timestamp.tm_mon], timestamp.tm_year + 1900,
140 timestamp.tm_hour, timestamp.tm_min, timestamp.tm_sec,
142 return string(buffer);
151 time_t now = time(NULL);
152 gmtime_r(&now, ×tamp);
155 snprintf(buffer,
sizeof(buffer),
"%04d%02d%02dT%02d%02d%02dZ",
156 timestamp.tm_year + 1900,
157 timestamp.tm_mon + 1,
162 return string(buffer);
171 gmtime_r(&when, ×tamp);
174 snprintf(buffer,
sizeof(buffer),
"%04d%02d%02d%02d%02d%02d",
175 timestamp.tm_year + 1900,
176 timestamp.tm_mon + 1,
181 return string(buffer);
187 int64_t msec = value.tv_sec * 1000;
188 msec += value.tv_usec / 1000;
189 snprintf(buffer,
sizeof(buffer),
"%" PRId64
".%03d", msec,
190 static_cast<int>(value.tv_usec % 1000));
191 return string(buffer);
200 unsigned length = iso8601.length();
202 if (length != 20)
return utc_time;
203 if ((iso8601[4] !=
'-') || (iso8601[7] !=
'-') || (iso8601[10] !=
'T') ||
204 (iso8601[13] !=
':') || (iso8601[16] !=
':') || (iso8601[19] !=
'Z')) {
209 memset(&tm_wl, 0,
sizeof(
struct tm));
210 tm_wl.tm_year =
static_cast<int>(
String2Int64(iso8601.substr(0, 4))) - 1900;
211 tm_wl.tm_mon =
static_cast<int>(
String2Int64(iso8601.substr(5, 2))) - 1;
212 tm_wl.tm_mday =
static_cast<int>(
String2Int64(iso8601.substr(8, 2)));
213 tm_wl.tm_hour =
static_cast<int>(
String2Int64(iso8601.substr(11, 2)));
214 tm_wl.tm_min =
static_cast<int>(
String2Int64(iso8601.substr(14, 2)));
215 tm_wl.tm_sec =
static_cast<int>(
String2Int64(iso8601.substr(17, 2)));
216 utc_time = timegm(&tm_wl);
217 if (utc_time < 0)
return 0;
224 sscanf(value.c_str(),
"%" PRId64, &result);
230 if (sscanf(value.c_str(),
"%" PRIu64, &result) == 1) {
248 long long myval = strtoll(value.c_str(), &endptr, 10);
249 if ((value.size() == 0) || (endptr != (value.c_str() + value.size())) ||
264 sscanf(value.c_str(),
"%" PRIu64
" %" PRIu64, a, b);
268 const bool ignore_case) {
269 if (prefix.length() > str.length())
return false;
271 for (
unsigned i = 0, l = prefix.length(); i < l; ++i) {
273 if (toupper(str[i]) != toupper(prefix[i]))
return false;
275 if (str[i] != prefix[i])
return false;
281 bool HasSuffix(
const std::string &str,
const std::string &suffix,
282 const bool ignore_case) {
283 if (suffix.size() > str.size())
return false;
284 const IgnoreCaseComperator icmp;
286 ? std::equal(suffix.rbegin(), suffix.rend(), str.rbegin(), icmp)
287 : std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
295 unsigned max_chunks,
const string &str,
char delim)
297 vector<string> result;
300 if (1 == max_chunks) {
301 result.push_back(str);
306 const unsigned size = str.size();
310 for (i = 0; i <
size; ++i) {
311 if (str[i] == delim) {
312 result.push_back(str.substr(marker, i - marker));
316 if (++chunks == max_chunks)
break;
321 result.push_back(str.substr(marker));
325 string JoinStrings(
const vector<string> &strings,
const string &joint) {
327 const unsigned size = strings.size();
331 for (
unsigned i = 1; i <
size; ++i) result += joint + strings[i];
338 map<char, string> *content) {
341 while (pos < buffer_size) {
342 if (static_cast<char>(buffer[pos]) ==
'\n') {
343 if (line ==
"--")
return;
346 const string tail = (line.length() == 1) ?
"" : line.substr(1);
348 if (line[0] !=
'Z') {
349 (*content)[line[0]] = tail;
351 if (content->find(line[0]) == content->end()) {
352 (*content)[line[0]] = tail;
354 (*content)[line[0]] = (*content)[line[0]] +
"|" + tail;
360 line +=
static_cast<char>(buffer[pos]);
367 int fd = open(filename.c_str(), O_RDONLY);
368 if (fd < 0)
return false;
370 unsigned char buffer[4096];
371 ssize_t num_bytes = read(fd, buffer,
sizeof(buffer));
374 if ((num_bytes <= 0) || (
unsigned(num_bytes) >=
sizeof(buffer)))
return false;
382 while ((pos < text_size) && (text[pos] !=
'\n')) pos++;
383 return string(text, pos);
391 if (ferror(f) && (errno == EINTR)) {
394 }
else if (retval == EOF) {
397 char c =
static_cast<char>(retval);
398 if (c ==
'\n')
break;
401 return (retval != EOF) || !line->empty();
409 retval = read(fd, &c, 1);
413 if ((retval == -1) && (errno == EINTR)) {
419 if (c ==
'\n')
break;
422 return (retval == 1) || !line->empty();
428 string Trim(
const string &raw,
bool trim_newline) {
429 if (raw.empty())
return "";
431 unsigned start_pos = 0;
432 for (; (start_pos < raw.length()) &&
433 (raw[start_pos] ==
' ' || raw[start_pos] ==
'\t' ||
434 (trim_newline && (raw[start_pos] ==
'\n' || raw[start_pos] ==
'\r')));
438 unsigned end_pos = raw.length() - 1;
440 (end_pos >= start_pos) &&
441 (raw[end_pos] ==
' ' || raw[end_pos] ==
'\t' ||
442 (trim_newline && (raw[end_pos] ==
'\n' || raw[end_pos] ==
'\r')));
447 return raw.substr(start_pos, end_pos - start_pos + 1);
451 const std::string& path,
452 const std::string& toTrim,
455 std::string trimmed = path;
456 if (trimmed != toTrim) {
459 (trimmed.size() > toTrim.size()))
461 trimmed = trimmed.substr(toTrim.size());
465 (trimmed.size() > toTrim.size()))
467 trimmed = trimmed.substr(0, trimmed.size() - toTrim.size());
477 string result(mixed_case);
478 for (
unsigned i = 0, l = result.length(); i < l; ++i) {
479 result[i] =
static_cast<char>(toupper(result[i]));
484 string ReplaceAll(
const string &haystack,
const string &needle,
485 const string &replace_by) {
486 string result(haystack);
488 const unsigned needle_size = needle.size();
489 if (needle ==
"")
return result;
491 while ((pos = result.find(needle, pos)) != string::npos)
492 result.replace(pos, needle_size, replace_by);
496 static inline void Base64Block(
const unsigned char input[3],
const char *table,
498 output[0] = table[(input[0] & 0xFD) >> 2];
499 output[1] = table[((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4)];
500 output[2] = table[((input[1] & 0x0F) << 2) | ((input[2] & 0xD0) >> 6)];
501 output[3] = table[input[2] & 0x3F];
506 result.reserve((data.length() + 3) * 4 / 3);
508 const unsigned char *data_ptr =
509 reinterpret_cast<const unsigned char *
>(data.data());
510 const unsigned length = data.length();
511 while (pos + 2 < length) {
512 char encoded_block[4];
514 result.append(encoded_block, 4);
517 if (length % 3 != 0) {
518 unsigned char input[3];
519 input[0] = data_ptr[pos];
520 input[1] = ((length % 3) == 2) ? data_ptr[pos + 1] : 0;
522 char encoded_block[4];
524 result.append(encoded_block, 2);
525 result.push_back(((length % 3) == 2) ? encoded_block[2] :
'=');
526 result.push_back(
'=');
536 string base64 =
Base64(data);
537 for (
unsigned i = 0, l = base64.length(); i < l; ++i) {
538 if (base64[i] ==
'+') {
540 }
else if (base64[i] ==
'/') {
547 static bool Debase64Block(
const unsigned char input[4],
unsigned char output[3])
550 for (
int i = 0; i < 4; ++i) {
552 if (dec[i] < 0)
return false;
555 output[0] = (dec[0] << 2) | (dec[1] >> 4);
556 output[1] = ((dec[1] & 0x0F) << 4) | (dec[2] >> 2);
557 output[2] = ((dec[2] & 0x03) << 6) | dec[3];
564 bool Debase64(
const string &data,
string *decoded) {
566 decoded->reserve((data.length() + 4) * 3 / 4);
568 const unsigned char *data_ptr =
569 reinterpret_cast<const unsigned char *
>(data.data());
570 const unsigned length = data.length();
571 if (length == 0)
return true;
572 if ((length % 4) != 0)
return false;
574 while (pos < length) {
575 unsigned char decoded_block[3];
577 if (!retval)
return false;
578 decoded->append(reinterpret_cast<char *>(decoded_block), 3);
582 for (
int i = 0; i < 2; ++i) {
584 if (data[pos] ==
'=') decoded->erase(decoded->length() - 1);
592 string Tail(
const string &source,
unsigned num_lines) {
593 if (source.empty() || (num_lines == 0))
return "";
595 int l =
static_cast<int>(source.length());
597 for (; i >= 0; --i) {
598 char c = source.data()[i];
600 if (num_lines == 0) {
601 return source.substr(i + 1);
617 char date_and_time[100];
618 time_t t = time(NULL);
619 gmtime_r(&t, &time_ptr);
621 if (!strftime(date_and_time, 100, format.c_str(), &time_ptr)) {
624 std::string timestamp(date_and_time);
628 #ifdef CVMFS_NAMESPACE_GUARD
string GetLineMem(const char *text, const int text_size)
std::string GetGMTimestamp(const std::string &format)
std::string IsoTimestamp()
string Trim(const string &raw, bool trim_newline)
string ReplaceAll(const string &haystack, const string &needle, const string &replace_by)
static void Base64Block(const unsigned char input[3], const char *table, char output[4])
string JoinStrings(const vector< string > &strings, const string &joint)
string Tail(const string &source, unsigned num_lines)
string StringifyTime(const time_t seconds, const bool utc)
string StringifyDouble(const double value)
std::string StringifyUint(const uint64_t value)
bool Debase64(const string &data, string *decoded)
string StringifyByteAsHex(const unsigned char value)
string StringifyBool(const bool value)
bool String2Uint64Parse(const std::string &value, uint64_t *result)
string Base64Url(const string &data)
std::string RfcTimestamp()
int64_t String2Int64(const string &value)
bool GetLineFile(FILE *f, std::string *line)
string ToUpper(const string &mixed_case)
vector< string > SplitString(const string &str, char delim)
bool HasSuffix(const std::string &str, const std::string &suffix, const bool ignore_case)
std::string WhitelistTimestamp(time_t when)
vector< string > SplitStringBounded(unsigned max_chunks, const string &str, char delim)
string StringifyInt(const int64_t value)
bool HasPrefix(const string &str, const string &prefix, const bool ignore_case)
const int const char * format
time_t IsoTimestamp2UtcTime(const std::string &iso8601)
bool GetLineFd(const int fd, std::string *line)
string Base64(const string &data)
uint64_t String2Uint64(const string &value)
bool operator()(const std::string::value_type a, const std::string::value_type b) const
bool ParseKeyvalPath(const string &filename, map< char, string > *content)
std::string TrimString(const std::string &path, const std::string &toTrim, const int trimMode)
static bool Debase64Block(const unsigned char input[4], unsigned char output[3])
string StringifyTimeval(const timeval value)
const int8_t db64_table[]
void ParseKeyvalMem(const unsigned char *buffer, const unsigned buffer_size, map< char, string > *content)
void String2Uint64Pair(const string &value, uint64_t *a, uint64_t *b)