30 #include "third_party/omaha/omaha/base/security/b64.h"
37 inline static int HexToChar(
int c) {
38 const int l = tolower(c);
39 return isdigit(l) ? l -
'0' : l -
'W';
42 static char ToUpper(
char c) {
44 return static_cast<char>(toupper(c));
47 static bool LessI(
char c1,
char c2) {
48 return toupper(c1) < toupper(c2);
51 static bool EqualI(
char c1,
char c2) {
52 return toupper(c1) == toupper(c2);
58 static const char alphabet[] =
59 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
62 const size_t length = str.length();
64 size_t dest_length = (length / 3U) * 4U;
66 const size_t overflow = length % 3U;
69 dest_length += overflow + 1U;
72 const size_t padding_length = (4U - (dest_length % 4U)) % 4U;
73 dest_length += padding_length;
76 dest.reserve(dest_length);
77 for (
size_t source_pos = 0U; source_pos <
length; source_pos += 3) {
78 const uint8 octet_a = str[source_pos];
79 const uint8 octet_b =
static_cast<uint8
>(
80 source_pos + 1 >= length ? 0 : str[source_pos + 1]);
81 const uint8 octet_c =
static_cast<uint8
>(
82 source_pos + 2 >= length ? 0 : str[source_pos + 2]);
85 dest.push_back(alphabet[octet_a >> 2]);
88 dest.push_back(alphabet[((octet_a & 0x3) << 4) | (octet_b >> 4)]);
91 if (source_pos + 1U < length)
92 dest.push_back(alphabet[(octet_b & 0xf) << 2 | (octet_c >> 6)]);
94 if (source_pos + 2U < length)
95 dest.push_back(alphabet[octet_c & 0x3f]);
97 for (
size_t i = 0; i < padding_length; ++i)
106 const size_t length = str.length();
109 for (
size_t i = 0; i <
length; ++i) {
145 out.append(1, str[i]);
153 const size_t length = str.length();
156 for (
size_t i = 0; i <
length; ++i) {
162 out.append(1, str[i]);
169 template <
typename Alloc>
171 const std::string&
str,
const std::string& delimiters,
172 std::vector<std::string, Alloc>* strings) {
176 size_t start_pos = str.find_first_not_of(delimiters, end_pos);
177 if (start_pos == std::string::npos)
181 end_pos = str.find_first_of(delimiters, start_pos);
183 strings->push_back(str.substr(start_pos, end_pos - start_pos));
188 const std::string&
str,
const std::string& delimiters) {
189 std::vector<std::string> strings;
195 const std::string&
str,
const std::string& delimiters,
203 const std::string&
str,
const std::string& delimiters) {
204 std::vector<std::string> strings;
207 const size_t length = str.length();
208 while (end_pos != std::string::npos && end_pos < length) {
209 const size_t start_pos = end_pos;
211 end_pos = str.find_first_of(delimiters, start_pos);
213 strings.push_back(str.substr(start_pos, end_pos - start_pos));
216 if (end_pos != std::string::npos)
224 const size_t count = str.size();
225 for (
size_t i = 0; i < count; ++i) {
227 decoded.push_back(
' ');
228 }
else if (i + 2U < count) {
229 const int c1 =
static_cast<int>(str[i + 1]);
230 const int c2 =
static_cast<int>(str[i + 2]);
231 if (str[i] ==
'%' && isxdigit(c1) && isxdigit(c2)) {
232 const char c =
static_cast<char>((HexToChar(c1) << 4) | HexToChar(c2));
233 decoded.push_back(c);
236 decoded.push_back(str[i]);
239 decoded.push_back(str[i]);
248 static const char* kUnescaped =
"._-$,;~()";
250 static const char* kHexDigits =
"0123456789abcdef";
253 encoded.reserve(str.length() * 3);
254 const size_t length = str.length();
255 for (
size_t i = 0; i <
length; ++i) {
256 if (isalnum(str[i]) || strchr(kUnescaped, str[i]) != NULL) {
257 encoded.push_back(str[i]);
259 encoded.push_back(
'%');
260 encoded.push_back(kHexDigits[static_cast<uint8>(str[i]) >> 4]);
261 encoded.push_back(kHexDigits[static_cast<uint8>(str[i]) & 0xf]);
268 const std::string& s0,
const std::string& s1,
269 size_t* first_different_index, std::string* line0, std::string* line1,
270 std::string* context0, std::string* context1) {
274 const std::vector<std::string> v0 =
SplitString(s0,
"\n");
275 const std::vector<std::string> v1 =
SplitString(s1,
"\n");
276 const size_t num_lines = std::min(v0.size(), v1.size());
277 size_t bad_index = num_lines;
278 for (
size_t i = 0; i < num_lines; ++i) {
279 if (v0[i] != v1[i]) {
289 if (bad_index >= num_lines && v0.size() == v1.size())
291 if (first_different_index)
292 *first_different_index = bad_index;
294 *line0 = bad_index < v0.size() ? v0[bad_index] : std::string(
"<missing>");
296 *line1 = bad_index < v1.size() ? v1[bad_index] : std::string(
"<missing>");
299 if (context0 || context1) {
300 static const size_t kContextLines = 5;
301 const size_t context_start =
302 bad_index - std::min(kContextLines, bad_index);
304 std::ostringstream
str;
305 const size_t context_end =
306 std::min(v0.size(), bad_index + kContextLines + 1U);
307 for (
size_t i = context_start; i < context_end; ++i) {
308 str << std::setfill(
' ') << std::setw(5) << i <<
": ";
309 str << v0[i] <<
"\n";
311 *context0 = str.str();
314 std::ostringstream
str;
315 const size_t context_end =
316 std::min(v1.size(), bad_index + kContextLines + 1U);
317 for (
size_t i = context_start; i < context_end; ++i) {
318 str << std::setfill(
' ') << std::setw(5) << i <<
": ";
319 str << v1[i] <<
"\n";
321 *context1 = str.str();
330 std::istringstream stream(str);
336 const std::string& str1,
const std::string& str2) {
337 if (std::lexicographical_compare(str1.begin(), str1.end(),
338 str2.begin(), str2.end(), LessI))
340 else if (str1.size() == str2.size() &&
341 std::equal(str1.begin(), str1.end(), str2.begin(), EqualI))
348 const std::string& start) {
349 return !start.empty() && start.length() <= target.length() &&
350 std::equal(start.begin(), start.end(), target.begin(), EqualI);
354 const std::string& end) {
355 return !end.empty() && end.length() <= target.length() &&
356 std::equal(end.rbegin(), end.rend(), target.rbegin(), EqualI);
360 const std::string& target,
const std::string& substr) {
361 if (substr.empty()) {
364 std::string target_upper(target.length(), 0);
365 std::string substr_upper(substr.length(), 0);
366 std::transform(target.begin(), target.end(), target_upper.begin(), ToUpper);
367 std::transform(substr.begin(), substr.end(), substr_upper.begin(), ToUpper);
368 size_t result = target_upper.find(substr_upper);
369 if (result == std::string::npos) {
372 return static_cast<int>(result);
381 std::string encoded =
str;
382 size_t length = encoded.length();
384 while (eq != 0 && encoded[eq - 1] ==
'=') {
388 for (
size_t i = 0; i < eq; ++i) {
389 if (encoded[i] ==
'+')
391 else if (encoded[i] ==
'/')
397 const size_t buffer_length = encoded.length();
399 char* result =
reinterpret_cast<char*
>(alloca(buffer_length));
400 int decoded_length = B64_decode(encoded.c_str(),
401 reinterpret_cast<uint8*
>(result),
402 static_cast<int>(buffer_length));
403 if (decoded_length == -1) {
408 return std::string(result, decoded_length);
412 const size_t length = input.size();
415 const size_t buffer_length = ((length + 2U) / 3U) * 4U + 1;
417 char*
buffer =
reinterpret_cast<char*
>(alloca(buffer_length));
418 B64_encode(reinterpret_cast<const uint8*>(input.data()),
419 static_cast<int>(input.size()), buffer,
420 static_cast<int>(buffer_length));
421 return std::string(buffer);
ION_API int CompareCaseInsensitive(const std::string &str1, const std::string &str2)
Case-insensitive comparison of str1 and str2.
void SplitStringHelper(const std::string &str, const std::string &delimiters, std::vector< std::string, Alloc > *strings)
ION_API bool EndsWithCaseInsensitive(const std::string &target, const std::string &end)
Returns whether target ends with end (case-insensitive).
std::vector< std::string > ION_API SplitString(const std::string &str, const std::string &delimiters)
Splits a string into a vector of substrings, given a set of delimiter characters (expressed as a stri...
ION_API std::string WebSafeBase64Encode(const std::string &input)
Encodes a byte array using RFC 4648 base64url ('-' and '_' for 62 and 63, respectively, and no padding).
std::string ION_API EscapeNewlines(const std::string &str)
Returns a string with all newlines replaced by "\\n".
std::string ION_API EscapeString(const std::string &str)
Returns an escaped version of the passed string.
int32 ION_API StringToInt32(const std::string &str)
Extracts and returns an integral value from str.
ION_API std::string UrlDecodeString(const std::string &str)
Returns a decoded version of a URL-encoded string.
Copyright 2016 Google Inc.
#define DCHECK_EQ(val1, val2)
std::string ION_API MimeBase64EncodeString(const std::string &str)
Returns a mime base-64 encoded version of the passed string.
bool ION_API AreMultiLineStringsEqual(const std::string &s0, const std::string &s1, size_t *first_different_index, std::string *line0, std::string *line1, std::string *context0, std::string *context1)
This function can be useful for comparing multi-line strings in tests.
std::vector< std::string > ION_API SplitStringWithoutSkipping(const std::string &str, const std::string &delimiters)
Splits a string into a vector of substrings, given a set of delimiter characters (expressed as a stri...
ION_API bool StartsWithCaseInsensitive(const std::string &target, const std::string &start)
Returns whether target begins with start (case-insensitive).
ION_API std::string UrlEncodeString(const std::string &str)
Returns a URL-encoded version of a string.
ION_API int FindCaseInsensitive(const std::string &target, const std::string &substr)
Case-insensitive version of std::string find.
ION_API std::string WebSafeBase64Decode(const std::string &str)
Decodes a Base64 encoded string.
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
This class can be used in place of std::vector to allow an Ion Allocator to be used for memory alloca...