static void mongoc_uri_parse_tags (mongoc_uri_t *uri, /* IN */ const char *str) /* IN */ { const char *end_keyval; const char *end_key; bson_t b; char *keyval; char *key; bson_init(&b); again: if ((keyval = scan_to_unichar(str, ',', "", &end_keyval))) { if ((key = scan_to_unichar(keyval, ':', "", &end_key))) { bson_append_utf8(&b, key, -1, end_key + 1, -1); bson_free(key); } bson_free(keyval); str = end_keyval + 1; goto again; } else { if ((key = scan_to_unichar(str, ':', "", &end_key))) { bson_append_utf8(&b, key, -1, end_key + 1, -1); bson_free(key); } } mongoc_read_prefs_add_tag(uri->read_prefs, &b); bson_destroy(&b); }
static bool mongoc_uri_parse_auth_mechanism_properties (mongoc_uri_t *uri, const char *str) { char *field; char *value; const char *end_scan; bson_t properties; bson_init(&properties); /* build up the properties document */ while ((field = scan_to_unichar(str, ':', "&", &end_scan))) { str = end_scan + 1; if (!(value = scan_to_unichar(str, ',', ":&", &end_scan))) { value = bson_strdup(str); str = ""; } else { str = end_scan + 1; } bson_append_utf8(&properties, field, -1, value, -1); bson_free(field); bson_free(value); } /* append our auth properties to our credentials */ bson_append_document(&uri->credentials, "mechanismProperties", -1, (const bson_t *)&properties); return true; }
static void mongoc_uri_parse_read_prefs (mongoc_uri_t *uri, const char *str) { const char *end_keyval; const char *end_key; bson_t b; char *keyval; char *key; char keystr[32]; int i; bson_init(&b); again: if ((keyval = scan_to_unichar(str, ',', &end_keyval))) { if ((key = scan_to_unichar(keyval, ':', &end_key))) { bson_append_utf8(&b, key, -1, end_key + 1, -1); bson_free(key); } bson_free(keyval); str = end_keyval + 1; goto again; } else { if ((key = scan_to_unichar(str, ':', &end_key))) { bson_append_utf8(&b, key, -1, end_key + 1, -1); bson_free(key); } } i = bson_count_keys(&uri->read_prefs); snprintf(keystr, sizeof keystr, "%u", i); bson_append_document(&uri->read_prefs, keystr, -1, &b); bson_destroy(&b); }
static bool mongoc_uri_parse_userpass (mongoc_uri_t *uri, const char *str, const char **end) { bool ret = false; const char *end_userpass; const char *end_user; char *s; if ((s = scan_to_unichar(str, '@', "", &end_userpass))) { if ((uri->username = scan_to_unichar(s, ':', "", &end_user))) { uri->password = bson_strdup(end_user + 1); } else { uri->username = bson_strndup(str, end_userpass - str); uri->password = NULL; } mongoc_uri_do_unescape(&uri->username); mongoc_uri_do_unescape(&uri->password); *end = end_userpass + 1; bson_free(s); ret = true; } else { ret = true; } return ret; }
static bool mongoc_uri_parse_host6 (mongoc_uri_t *uri, const char *str) { uint16_t port = MONGOC_DEFAULT_PORT; const char *portstr; const char *end_host; char *hostname; if ((portstr = strrchr (str, ':')) && !strstr (portstr, "]")) { if (!mongoc_uri_parse_port(&port, portstr + 1)) { return false; } } hostname = scan_to_unichar (str + 1, ']', "", &end_host); mongoc_uri_do_unescape (&hostname); if (!hostname) { return false; } mongoc_uri_append_host (uri, hostname, port); bson_free (hostname); return true; }
bool mongoc_uri_parse_host (mongoc_uri_t *uri, const char *str) { uint16_t port; const char *end_host; char *hostname; if (*str == '[' && strchr (str, ']')) { return mongoc_uri_parse_host6 (uri, str); } if ((hostname = scan_to_unichar(str, ':', "?/,", &end_host))) { end_host++; if (!mongoc_uri_parse_port(&port, end_host)) { bson_free (hostname); return false; } } else { hostname = bson_strdup(str); port = MONGOC_DEFAULT_PORT; } mongoc_uri_do_unescape(&hostname); if (!hostname) { /* invalid */ bson_free (hostname); return false; } mongoc_uri_append_host(uri, hostname, port); bson_free(hostname); return true; }
static bool mongoc_uri_parse_host (mongoc_uri_t *uri, const char *str) { uint16_t port; const char *end_host; char *hostname; if (*str == '[' && strchr (str, ']')) { return mongoc_uri_parse_host6 (uri, str); } if ((hostname = scan_to_unichar(str, ':', &end_host))) { end_host++; if (!isdigit(*end_host)) { bson_free(hostname); return false; } #ifdef _MSC_VER sscanf_s (end_host, "%hu", &port); #else sscanf (end_host, "%hu", &port); #endif } else { hostname = bson_strdup(str); port = MONGOC_DEFAULT_PORT; } mongoc_uri_do_unescape(&hostname); mongoc_uri_append_host(uri, hostname, port); bson_free(hostname); return true; }
static bool mongoc_uri_parse_host6 (mongoc_uri_t *uri, const char *str) { uint16_t port = 27017; const char *portstr; const char *end_host; char *hostname; if ((portstr = strrchr (str, ':')) && !strstr (portstr, "]")) { #ifdef _MSC_VER sscanf_s (portstr, ":%hu", &port); #else sscanf (portstr, ":%hu", &port); #endif } hostname = scan_to_unichar (str + 1, ']', &end_host); mongoc_uri_do_unescape (&hostname); mongoc_uri_append_host (uri, hostname, port); bson_free (hostname); return true; }
static bson_bool_t mongoc_uri_parse_host (mongoc_uri_t *uri, const char *str) { bson_uint16_t port; const char *end_host; char *hostname; if ((hostname = scan_to_unichar(str, ':', &end_host))) { end_host++; if (!isdigit(*end_host)) { bson_free(hostname); return FALSE; } sscanf(end_host, "%hu", &port); } else { hostname = bson_strdup(str); port = MONGOC_DEFAULT_PORT; } mongoc_uri_do_unescape(&hostname); mongoc_uri_append_host(uri, hostname, port); bson_free(hostname); return TRUE; }
static bool mongoc_uri_parse_option (mongoc_uri_t *uri, const char *str) { int32_t v_int; const char *end_key; char *key; char *value; if (!(key = scan_to_unichar(str, '=', &end_key))) { return false; } value = bson_strdup(end_key + 1); mongoc_uri_do_unescape(&value); if (!strcasecmp(key, "connecttimeoutms") || !strcasecmp(key, "sockettimeoutms") || !strcasecmp(key, "maxpoolsize") || !strcasecmp(key, "minpoolsize") || !strcasecmp(key, "maxidletimems") || !strcasecmp(key, "waitqueuemultiple") || !strcasecmp(key, "waitqueuetimeoutms") || !strcasecmp(key, "wtimeoutms")) { v_int = strtol(value, NULL, 10); bson_append_int32(&uri->options, key, -1, v_int); } else if (!strcasecmp(key, "w")) { if (*value == '-' || isdigit(*value)) { v_int = strtol (value, NULL, 10); BSON_APPEND_INT32 (&uri->options, "w", v_int); } else if (0 == strcasecmp (value, "majority")) { BSON_APPEND_UTF8 (&uri->options, "w", "majority"); } else if (*value) { BSON_APPEND_UTF8 (&uri->options, "W", value); } } else if (!strcasecmp(key, "canonicalizeHostname") || !strcasecmp(key, "journal") || !strcasecmp(key, "safe") || !strcasecmp(key, "slaveok") || !strcasecmp(key, "ssl")) { bson_append_bool (&uri->options, key, -1, (0 == strcasecmp (value, "true")) || (0 == strcasecmp (value, "t")) || (0 == strcmp (value, "1"))); } else if (!strcasecmp(key, "readpreferencetags")) { mongoc_uri_parse_tags(uri, value, &uri->read_prefs); } else { bson_append_utf8(&uri->options, key, -1, value, -1); } bson_free(key); bson_free(value); return true; }
static bson_bool_t mongoc_uri_parse_option (mongoc_uri_t *uri, const char *str) { bson_int32_t v_int; const char *end_key; char *key; char *value; if (!(key = scan_to_unichar(str, '=', &end_key))) { return FALSE; } value = strdup(end_key + 1); mongoc_uri_do_unescape(&value); if (!strcasecmp(key, "connecttimeoutms") || !strcasecmp(key, "sockettimeoutms") || !strcasecmp(key, "maxpoolsize") || !strcasecmp(key, "minpoolsize") || !strcasecmp(key, "maxidletimems") || !strcasecmp(key, "waitqueuemultiple") || !strcasecmp(key, "waitqueuetimeoutms") || !strcasecmp(key, "wtimeoutms")) { v_int = strtol(value, NULL, 10); bson_append_int32(&uri->options, key, -1, v_int); } else if (!strcasecmp(key, "w")) { if (*value == '-' || isdigit(*value)) { v_int = strtol(value, NULL, 10); bson_append_int32(&uri->options, key, -1, v_int); } else { bson_append_utf8(&uri->options, key, -1, value, -1); } } else if (!strcasecmp(key, "journal") || !strcasecmp(key, "slaveok") || !strcasecmp(key, "ssl")) { bson_append_bool(&uri->options, key, -1, !strcmp(value, "true")); } else if (!strcasecmp(key, "readpreferencetags")) { mongoc_uri_parse_read_prefs(uri, value); } else { bson_append_utf8(&uri->options, key, -1, value, -1); } bson_free(key); bson_free(value); return TRUE; }
static bool mongoc_uri_parse_database (mongoc_uri_t *uri, const char *str, const char **end) { const char *end_database; if ((uri->database = scan_to_unichar(str, '?', &end_database))) { *end = end_database; } else if (*str) { uri->database = bson_strdup(str); *end = str + strlen(str); } mongoc_uri_do_unescape(&uri->database); return true; }
bool _mongoc_host_list_from_string (mongoc_host_list_t *host_list, const char *host_and_port) { uint16_t port; const char *end_host; char *hostname = NULL; bson_return_val_if_fail(host_list, false); bson_return_val_if_fail(host_and_port, false); memset(host_list, 0, sizeof *host_list); if ((hostname = scan_to_unichar(host_and_port, ':', &end_host))) { end_host++; if (!isdigit(*end_host)) { bson_free(hostname); return false; } #ifdef _MSC_VER sscanf_s (end_host, "%hu", &port); #else sscanf (end_host, "%hu", &port); #endif } else { hostname = bson_strdup(host_and_port); port = MONGOC_DEFAULT_PORT; } bson_strncpy (host_list->host_and_port, host_and_port, sizeof host_list->host_and_port - 1); bson_strncpy (host_list->host, hostname, sizeof host_list->host - 1); host_list->port = port; host_list->family = AF_INET; bson_free(hostname); return true; }
bson_bool_t _mongoc_host_list_from_string (mongoc_host_list_t *host_list, const char *host_and_port) { bson_uint16_t port; const char *end_host; char *hostname = NULL; bson_return_val_if_fail(host_list, FALSE); bson_return_val_if_fail(host_and_port, FALSE); memset(host_list, 0, sizeof *host_list); if ((hostname = scan_to_unichar(host_and_port, ':', &end_host))) { end_host++; if (!isdigit(*end_host)) { bson_free(hostname); return FALSE; } sscanf(end_host, "%hu", &port); } else { hostname = bson_strdup(host_and_port); port = MONGOC_DEFAULT_PORT; } strncpy(host_list->host_and_port, host_and_port, sizeof host_list->host_and_port - 1); host_list->host_and_port[sizeof host_list->host_and_port-1] = '\0'; strncpy(host_list->host, hostname, sizeof host_list->host - 1); host_list->host[sizeof host_list->host-1] = '\0'; host_list->port = port; host_list->family = AF_INET; bson_free(hostname); return TRUE; }
static bool mongoc_uri_parse_options (mongoc_uri_t *uri, const char *str) { const char *end_option; char *option; again: if ((option = scan_to_unichar(str, '&', "", &end_option))) { if (!mongoc_uri_parse_option(uri, option)) { bson_free(option); return false; } bson_free(option); str = end_option + 1; goto again; } else if (*str) { if (!mongoc_uri_parse_option(uri, str)) { return false; } } return true; }
static bool mongoc_uri_parse_option (mongoc_uri_t *uri, const char *str) { int32_t v_int; const char *end_key; char *key = NULL; char *value = NULL; bool ret = false; if (!(key = scan_to_unichar(str, '=', "", &end_key))) { goto CLEANUP; } value = bson_strdup(end_key + 1); mongoc_uri_do_unescape(&value); if (!value) { /* do_unescape detected invalid UTF-8 and freed value */ goto CLEANUP; } if (mongoc_uri_option_is_int32(key)) { v_int = (int) strtol (value, NULL, 10); BSON_APPEND_INT32 (&uri->options, key, v_int); } else if (!strcasecmp(key, "w")) { if (*value == '-' || isdigit(*value)) { v_int = (int) strtol (value, NULL, 10); BSON_APPEND_INT32 (&uri->options, "w", v_int); } else if (0 == strcasecmp (value, "majority")) { BSON_APPEND_UTF8 (&uri->options, "w", "majority"); } else if (*value) { BSON_APPEND_UTF8 (&uri->options, "w", value); } } else if (mongoc_uri_option_is_bool(key)) { bson_append_bool (&uri->options, key, -1, (0 == strcasecmp (value, "true")) || (0 == strcasecmp (value, "t")) || (0 == strcmp (value, "1"))); } else if (!strcasecmp(key, "readpreferencetags")) { mongoc_uri_parse_tags(uri, value); } else if (!strcasecmp(key, "authmechanism") || !strcasecmp(key, "authsource")) { bson_append_utf8(&uri->credentials, key, -1, value, -1); } else if (!strcasecmp(key, "readconcernlevel")) { mongoc_read_concern_set_level (uri->read_concern, value); } else if (!strcasecmp(key, "authmechanismproperties")) { if (!mongoc_uri_parse_auth_mechanism_properties(uri, value)) { goto CLEANUP; } #ifdef MONGOC_EXPERIMENTAL_FEATURES } else if (!strcasecmp (key, "appname")) { if (!mongoc_uri_set_appname (uri, value)) { MONGOC_WARNING ("Cannot set appname: %s is invalid", value); goto CLEANUP; } #endif } else { bson_append_utf8(&uri->options, key, -1, value, -1); } ret = true; CLEANUP: bson_free(key); bson_free(value); return ret; }
static bool mongoc_uri_parse_hosts (mongoc_uri_t *uri, const char *str, const char **end) { bool ret = false; const char *end_hostport; const char *sock; const char *tmp; char *s; /* * Parsing the series of hosts is a lot more complicated than you might * imagine. This is due to some characters being both separators as well as * valid characters within the "hostname". In particularly, we can have file * paths to specify paths to UNIX domain sockets. We impose the restriction * that they must be suffixed with ".sock" to simplify the parsing. * * You can separate hosts and file system paths to UNIX domain sockets with * ",". * * When you reach a "/" or "?" that is not part of a file-system path, we * have completed our parsing of hosts. */ again: if (((*str == '/') && (sock = strstr(str, ".sock"))) && (!(tmp = strstr(str, ",")) || (tmp > sock)) && (!(tmp = strstr(str, "?")) || (tmp > sock))) { s = bson_strndup(str, sock + 5 - str); if (!mongoc_uri_parse_host(uri, s)) { bson_free(s); return false; } bson_free(s); str = sock + 5; ret = true; if (*str == ',') { str++; goto again; } } else if ((s = scan_to_unichar(str, ',', "/", &end_hostport))) { if (!mongoc_uri_parse_host(uri, s)) { bson_free(s); return false; } bson_free(s); str = end_hostport + 1; ret = true; goto again; } else if ((s = scan_to_unichar(str, '/', "", &end_hostport)) || (s = scan_to_unichar(str, '?', "", &end_hostport))) { if (!mongoc_uri_parse_host(uri, s)) { bson_free(s); return false; } bson_free(s); *end = end_hostport; return true; } else if (*str) { if (!mongoc_uri_parse_host(uri, str)) { return false; } *end = str + strlen(str); return true; } return ret; }