char * mongoc_uri_unescape (const char *escaped_string) { bson_unichar_t c; bson_string_t *str; unsigned int hex = 0; const char *ptr; const char *end; size_t len; BSON_ASSERT (escaped_string); len = strlen(escaped_string); /* * Double check that this is a UTF-8 valid string. Bail out if necessary. */ if (!bson_utf8_validate(escaped_string, len, false)) { MONGOC_WARNING("%s(): escaped_string contains invalid UTF-8", BSON_FUNC); return NULL; } ptr = escaped_string; end = ptr + len; str = bson_string_new(NULL); for (; *ptr; ptr = bson_utf8_next_char(ptr)) { c = bson_utf8_get_char(ptr); switch (c) { case '%': if (((end - ptr) < 2) || !isxdigit(ptr[1]) || !isxdigit(ptr[2]) || #ifdef _MSC_VER (1 != sscanf_s(&ptr[1], "%02x", &hex)) || #else (1 != sscanf(&ptr[1], "%02x", &hex)) || #endif !isprint(hex)) { bson_string_free(str, true); return NULL; } bson_string_append_c(str, hex); ptr += 2; break; default: bson_string_append_unichar(str, c); break; } } return bson_string_free(str, false); }
static void test_bson_utf8_validate (void) { static const unsigned char test1[] = {0xe2, 0x82, 0xac, ' ', 0xe2, 0x82, 0xac, ' ', 0xe2, 0x82, 0xac, 0}; static const unsigned char test2[] = {0xc0, 0x80, 0}; assert(bson_utf8_validate("asdf", 4, false)); assert(bson_utf8_validate("asdf", 4, true)); assert(bson_utf8_validate("asdf", 5, true)); assert(!bson_utf8_validate("asdf", 5, false)); assert(bson_utf8_validate((const char *)test1, 11, true)); assert(bson_utf8_validate((const char *)test1, 11, false)); assert(bson_utf8_validate((const char *)test1, 12, true)); assert(!bson_utf8_validate((const char *)test1, 12, false)); assert(bson_utf8_validate((const char *)test2, 2, true)); }
static void test_bson_utf8_validate (void) { static const char test1[] = {0xe2, 0x82, 0xac, ' ', 0xe2, 0x82, 0xac, ' ', 0xe2, 0x82, 0xac, 0}; assert(bson_utf8_validate("asdf", 4, FALSE)); assert(bson_utf8_validate("asdf", 4, TRUE)); assert(bson_utf8_validate("asdf", 5, TRUE)); assert(!bson_utf8_validate("asdf", 5, FALSE)); assert(bson_utf8_validate(test1, 11, TRUE)); assert(bson_utf8_validate(test1, 11, FALSE)); assert(bson_utf8_validate(test1, 12, TRUE)); assert(!bson_utf8_validate(test1, 12, FALSE)); }
static void test_bson_utf8_non_shortest (void) { static const char *tests[] = { "\xE0\x80\x80" , /* Non-shortest form representation of U+0000 */ "\xF0\x80\x80\x80", /* Non-shortest form representation of U+0000 */ "\xE0\x83\xBF" , /* Non-shortest form representation of U+00FF */ "\xF0\x80\x83\xBF", /* Non-shortest form representation of U+00FF */ "\xF0\x80\xA3\x80", /* Non-shortest form representation of U+08C0 */ NULL }; static const char *valid_tests[] = { "\xC0\x80" , /* Non-shortest form representation of U+0000. * This is how \0 should be encoded. Special casing * to allow for use in things like strlen(). */ NULL }; int i; for (i = 0; tests [i]; i++) { if (bson_utf8_validate (tests [i], strlen (tests [i]), false)) { fprintf (stderr, "non-shortest form failure, test %d\n", i); assert (false); } } for (i = 0; valid_tests [i]; i++) { if (!bson_utf8_validate (valid_tests [i], strlen (valid_tests [i]), false)) { fprintf (stderr, "non-shortest form failure, valid_tests %d\n", i); assert (false); } } }
bool mongoc_uri_set_auth_source (mongoc_uri_t *uri, const char *value) { size_t len; BSON_ASSERT (value); len = strlen(value); if (!bson_utf8_validate (value, len, false)) { return false; } mongoc_uri_bson_append_or_replace_key (&uri->credentials, "authSource", value); return true; }
bool mongoc_uri_set_appname (mongoc_uri_t *uri, const char *value) { BSON_ASSERT (value); if (!bson_utf8_validate (value, strlen (value), false)) { return false; } if (!_mongoc_metadata_appname_is_valid (value)) { return false; } mongoc_uri_bson_append_or_replace_key (&uri->options, "appname", value); return true; }
bool mongoc_uri_set_database (mongoc_uri_t *uri, const char *database) { size_t len; BSON_ASSERT (database); len = strlen(database); if (!bson_utf8_validate (database, len, false)) { return false; } if (uri->database) { bson_free (uri->database); } uri->database = bson_strdup(database); return true; }
bool mongoc_uri_set_password (mongoc_uri_t *uri, const char *password) { size_t len; BSON_ASSERT (password); len = strlen(password); if (!bson_utf8_validate (password, len, false)) { return false; } if (uri->password) { bson_free (uri->password); } uri->password = bson_strdup (password); return true; }
bool mongoc_uri_set_username (mongoc_uri_t *uri, const char *username) { size_t len; BSON_ASSERT (username); len = strlen(username); if (!bson_utf8_validate (username, len, false)) { return false; } if (uri->username) { bson_free (uri->username); } uri->username = bson_strdup (username); return true; }
bool mongoc_uri_set_option_as_utf8(mongoc_uri_t *uri, const char *option, const char *value) { size_t len; BSON_ASSERT (option); len = strlen(value); if (!bson_utf8_validate (value, len, false)) { return false; } if (!mongoc_uri_option_is_utf8 (option)) { return false; } mongoc_uri_bson_append_or_replace_key (&uri->options, option, value); return true; }