/** * Parse a database URL of form * scheme://[username[:password]@]hostname[:port]/database * * \param id filled id struct * \param url parsed URL * \return 0 if parsing was successful and -1 otherwise */ static int parse_cachedb_url(struct cachedb_id* id, const str* url) { #define SHORTEST_DB_URL "s://" #define SHORTEST_DB_URL_LEN (sizeof(SHORTEST_DB_URL) - 1) enum state { ST_SCHEME, /* Scheme part */ ST_SLASH1, /* First slash */ ST_SLASH1_GRP, /* Group Name or first / */ ST_SLASH2, /* Second slash */ ST_USER_HOST, /* Username or hostname */ ST_PASS_PORT, /* Password or port part */ ST_HOST, /* Hostname part */ ST_PORT, /* Port part */ ST_DB /* Database part */ }; enum state st; unsigned int len, i; char* begin; char* prev_token,*start_host=NULL,*start_prev=NULL,*ptr; prev_token = 0; if (!id || !url || !url->s) { goto err; } len = url->len; if (len < SHORTEST_DB_URL_LEN) { goto err; } LM_DBG("parsing [%.*s]\n",url->len,url->s); /* Initialize all attributes to 0 */ memset(id, 0, sizeof(struct cachedb_id)); st = ST_SCHEME; begin = url->s; if (dupl_string(&id->initial_url,url->s,url->s+url->len) < 0) goto err; for(i = 0; i < len; i++) { switch(st) { case ST_SCHEME: switch(url->s[i]) { case ':': st = ST_SLASH1_GRP; if (dupl_string(&id->scheme, begin, url->s + i) < 0) goto err; begin = url->s+i+1; break; } break; case ST_SLASH1_GRP: switch(url->s[i]) { case ':': st = ST_SLASH1; if (dupl_string(&id->group_name,begin,url->s+i) < 0) goto err; break; case '/': st = ST_SLASH2; break; } break; case ST_SLASH1: switch(url->s[i]) { case '/': st = ST_SLASH2; break; default: goto err; } break; case ST_SLASH2: switch(url->s[i]) { case '/': st = ST_USER_HOST; begin = url->s + i + 1; break; default: goto err; } break; case ST_USER_HOST: switch(url->s[i]) { case '@': st = ST_HOST; if (dupl_string(&id->username, begin, url->s + i) < 0) goto err; begin = url->s + i + 1; break; case ':': st = ST_PASS_PORT; if (dupl_string(&prev_token, begin, url->s + i) < 0) goto err; start_prev = begin; begin = url->s + i + 1; break; case '/': if (dupl_string(&id->host, begin, url->s + i) < 0) goto err; if (url->s+i+1 == url->s + len) { st = ST_DB; break; } if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err; return 0; } break; case ST_PASS_PORT: switch(url->s[i]) { case '@': st = ST_HOST; id->username = prev_token; if (dupl_string(&id->password, begin, url->s + i) < 0) goto err; begin = url->s + i + 1; break; case '/': id->host = prev_token; id->port = str2s(begin, url->s + i - begin, 0); if (url->s+i+1 == url->s + len) { st = ST_DB; break; } if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err; return 0; case ',': st=ST_HOST; start_host=start_prev; id->flags |= CACHEDB_ID_MULTIPLE_HOSTS; break; } break; case ST_HOST: switch(url->s[i]) { case ':': LM_DBG("in host - :\n"); if (id->flags & CACHEDB_ID_MULTIPLE_HOSTS) { LM_DBG("multiple hosts, skipping\n"); break; } st = ST_PORT; if (dupl_string(&id->host, begin, url->s + i) < 0) goto err; start_host = begin; begin = url->s + i + 1; break; case '/': if (id->flags & CACHEDB_ID_MULTIPLE_HOSTS) ptr = start_host; else ptr = begin; if (dupl_string(&id->host, ptr, url->s + i) < 0) goto err; if (url->s+i+1 == url->s + len) { st = ST_DB; break; } if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err; return 0; } break; case ST_PORT: switch(url->s[i]) { case '/': id->port = str2s(begin, url->s + i - begin, 0); if (url->s+i+1 == url->s + len) { st = ST_DB; break; } if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err; return 0; case ',': st = ST_HOST; pkg_free(id->host); id->host=NULL; begin = start_host; id->flags |= CACHEDB_ID_MULTIPLE_HOSTS; break; } case ST_DB: break; } } if (st == ST_USER_HOST && begin == url->s+url->len) { /* Not considered an error - to cope with modules that * offer cacheDB functionality backed up by OpenSIPS mem */ id->flags |= CACHEDB_ID_NO_URL; LM_DBG("Just scheme, no actual url\n"); return 0; } if (st != ST_DB) goto err; return 0; err: if (id && id->initial_url) pkg_free(id->initial_url); if (id && id->scheme) pkg_free(id->scheme); if (id && id->username) pkg_free(id->username); if (id && id->password) pkg_free(id->password); if (id && id->host) pkg_free(id->host); if (id && id->database) pkg_free(id->database); if (prev_token) pkg_free(prev_token); return -1; }
/** * Parse a database URL of form * scheme://[username[:password]@]hostname[:port]/database * * \param id filled id struct * \param url parsed URL * \return 0 if parsing was successful and -1 otherwise */ static int parse_db_url(struct db_id* id, const str* url) { #define SHORTEST_DB_URL "s://a/b" #define SHORTEST_DB_URL_LEN (sizeof(SHORTEST_DB_URL) - 1) enum state { ST_SCHEME, /* Scheme part */ ST_SLASH1, /* First slash */ ST_SLASH2, /* Second slash */ ST_USER_HOST, /* Username or hostname */ ST_PASS_PORT, /* Password or port part */ ST_HOST, /* Hostname part */ ST_PORT, /* Port part */ ST_DB /* Database part */ }; enum state st; unsigned int len, i; const char* begin; char* prev_token; prev_token = 0; if (!id || !url || !url->s) { goto err; } len = url->len; if (len < SHORTEST_DB_URL_LEN) { goto err; } /* Initialize all attributes to 0 */ memset(id, 0, sizeof(struct db_id)); st = ST_SCHEME; begin = url->s; for(i = 0; i < len; i++) { switch(st) { case ST_SCHEME: switch(url->s[i]) { case ':': st = ST_SLASH1; if (dupl_string(&id->scheme, begin, url->s + i) < 0) goto err; break; } break; case ST_SLASH1: switch(url->s[i]) { case '/': st = ST_SLASH2; break; default: goto err; } break; case ST_SLASH2: switch(url->s[i]) { case '/': st = ST_USER_HOST; begin = url->s + i + 1; break; default: goto err; } break; case ST_USER_HOST: switch(url->s[i]) { case '@': st = ST_HOST; if (dupl_string(&id->username, begin, url->s + i) < 0) goto err; begin = url->s + i + 1; break; case ':': st = ST_PASS_PORT; if (dupl_string(&prev_token, begin, url->s + i) < 0) goto err; begin = url->s + i + 1; break; case '/': if (dupl_string(&id->host, begin, url->s + i) < 0) goto err; if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err; return 0; } break; case ST_PASS_PORT: switch(url->s[i]) { case '@': st = ST_HOST; id->username = prev_token; prev_token = 0; if (dupl_string(&id->password, begin, url->s + i) < 0) goto err; begin = url->s + i + 1; break; case '/': id->host = prev_token; prev_token = 0; id->port = str2s(begin, url->s + i - begin, 0); if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err; return 0; } break; case ST_HOST: switch(url->s[i]) { case ':': st = ST_PORT; if (dupl_string(&id->host, begin, url->s + i) < 0) goto err; begin = url->s + i + 1; break; case '/': if (dupl_string(&id->host, begin, url->s + i) < 0) goto err; if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err; return 0; } break; case ST_PORT: switch(url->s[i]) { case '/': id->port = str2s(begin, url->s + i - begin, 0); if (dupl_string(&id->database, url->s + i + 1, url->s + len) < 0) goto err; return 0; } break; case ST_DB: break; } } if (st != ST_DB) goto err; return 0; err: if (!id) goto end; if (id->scheme) pkg_free(id->scheme); if (id->username) pkg_free(id->username); if (id->password) pkg_free(id->password); if (id->host) pkg_free(id->host); if (id->database) pkg_free(id->database); memset(id, 0, sizeof(struct db_id)); if (prev_token) pkg_free(prev_token); end: return -1; }
/** Parses postgres URI of form * //[username[:password]@]hostname[:port]/database * * Returns 0 if parsing was successful and -1 otherwise */ static int parse_postgres_uri(struct pg_uri* res, str* uri) { #define SHORTEST_DB_URL "//a/b" #define SHORTEST_DB_URL_LEN (sizeof(SHORTEST_DB_URL) - 1) enum state { ST_SLASH1, /* First slash */ ST_SLASH2, /* Second slash */ ST_USER_HOST, /* Username or hostname */ ST_PASS_PORT, /* Password or port part */ ST_HOST, /* Hostname part */ ST_PORT, /* Port part */ ST_DB /* Database part */ }; enum state st; int i; const char* begin; char* prev_token; prev_token = 0; if (!res || !uri) { goto err; } if (uri->len < SHORTEST_DB_URL_LEN) { goto err; } st = ST_SLASH1; begin = uri->s; for(i = 0; i < uri->len; i++) { switch(st) { case ST_SLASH1: switch(uri->s[i]) { case '/': st = ST_SLASH2; break; default: goto err; } break; case ST_SLASH2: switch(uri->s[i]) { case '/': st = ST_USER_HOST; begin = uri->s + i + 1; break; default: goto err; } break; case ST_USER_HOST: switch(uri->s[i]) { case '@': st = ST_HOST; if (dupl_string(&res->username, begin, uri->s + i) < 0) goto err; begin = uri->s + i + 1; break; case ':': st = ST_PASS_PORT; if (dupl_string(&prev_token, begin, uri->s + i) < 0) goto err; begin = uri->s + i + 1; break; case '/': if (memchr(uri->s + i + 1, '/', uri->len - i - 1) != NULL) break; if (dupl_string(&res->host, begin, uri->s + i) < 0) goto err; if (dupl_string(&res->database, uri->s + i + 1, uri->s + uri->len) < 0) goto err; return 0; } break; case ST_PASS_PORT: switch(uri->s[i]) { case '@': st = ST_HOST; res->username = prev_token; if (dupl_string(&res->password, begin, uri->s + i) < 0) goto err; begin = uri->s + i + 1; break; case '/': if (memchr(uri->s + i + 1, '/', uri->len - i - 1) != NULL) break; res->host = prev_token; res->port = str2s(begin, uri->s + i - begin, 0); if (dupl_string(&res->database, uri->s + i + 1, uri->s + uri->len) < 0) goto err; return 0; } break; case ST_HOST: switch(uri->s[i]) { case ':': st = ST_PORT; if (dupl_string(&res->host, begin, uri->s + i) < 0) goto err; begin = uri->s + i + 1; break; case '/': if (memchr(uri->s + i + 1, '/', uri->len - i - 1) != NULL) break; if (dupl_string(&res->host, begin, uri->s + i) < 0) goto err; if (dupl_string(&res->database, uri->s + i + 1, uri->s + uri->len) < 0) goto err; return 0; } break; case ST_PORT: switch(uri->s[i]) { case '/': res->port = str2s(begin, uri->s + i - begin, 0); if (dupl_string(&res->database, uri->s + i + 1, uri->s + uri->len) < 0) goto err; return 0; } break; case ST_DB: break; } } if (st != ST_DB) goto err; return 0; err: if (prev_token) pkg_free(prev_token); if (res == NULL) return -1; if (res->username) { pkg_free(res->username); res->username = NULL; } if (res->password) { pkg_free(res->password); res->password = NULL; } if (res->host) { pkg_free(res->host); res->host = NULL; } if (res->database) { pkg_free(res->database); res->database = NULL; } return -1; }
/* * Parse ldap URI of form * //[username[:password]@]hostname[:port] * * Returns 0 if parsing was successful and -1 otherwise */ int parse_ldap_uri(struct ld_uri* res, str* scheme, str* uri) { #define SHORTEST_DB_URL "a" #define SHORTEST_DB_URL_LEN (sizeof(SHORTEST_DB_URL) - 1) enum state { ST_BEGIN, /* First state */ ST_SECTION_ID, /* Config section id */ ST_SLASH2, /* Second slash */ ST_USER_HOST, /* Username or hostname */ ST_PASS_PORT, /* Password or port part */ ST_HOST_PORT /* Hostname and port part */ }; enum state st; int i, ldapurllen; const char* begin; const char* ldapbegin; char* prev_token; struct ld_con_info* cfg_conn_info; char* sport, *puri; int portlen = 0; prev_token = 0; if (!res || !scheme || !uri) { goto err; } if (uri->len < SHORTEST_DB_URL_LEN) { goto err; } st = ST_BEGIN; ldapbegin = begin = uri->s; for(i = 0; i < uri->len && st != ST_SECTION_ID; i++) { switch(st) { case ST_BEGIN: switch(uri->s[i]) { case '/': st = ST_SLASH2; break; default: st = ST_SECTION_ID; } break; case ST_SECTION_ID: break; case ST_SLASH2: switch(uri->s[i]) { case '/': st = ST_USER_HOST; ldapbegin = begin = uri->s + i + 1; break; default: goto err; } break; case ST_USER_HOST: switch(uri->s[i]) { case '@': st = ST_HOST_PORT; if (dupl_string(&res->username, begin, uri->s + i) < 0) goto err; ldapbegin = begin = uri->s + i + 1; break; case ':': st = ST_PASS_PORT; if (dupl_string(&prev_token, begin, uri->s + i) < 0) goto err; begin = uri->s + i + 1; break; } break; case ST_PASS_PORT: switch(uri->s[i]) { case '@': st = ST_HOST_PORT; res->username = prev_token; if (dupl_string(&res->password, begin, uri->s + i) < 0) goto err; ldapbegin = begin = uri->s + i + 1; break; } break; case ST_HOST_PORT: break; } } switch(st) { case ST_PASS_PORT: case ST_USER_HOST: case ST_HOST_PORT: ldapurllen = uri->len - (int)(ldapbegin - uri->s); // +3 for the '://' ldap url snippet res->uri = pkg_malloc(scheme->len + 3 + ldapurllen + 1); if (res->uri== NULL) { ERR("ldap: No memory left\n"); goto err; } memcpy(res->uri, scheme->s, scheme->len); res->uri[scheme->len] = ':'; res->uri[scheme->len + 1] = '/'; res->uri[scheme->len + 2] = '/'; memcpy(res->uri + scheme->len + 3, ldapbegin, ldapurllen); res->uri[scheme->len + 3 + ldapurllen] = '\0'; if (ldap_url_parse(res->uri, &res->ldap_url) != 0) { ERR("ldap: Error while parsing URL '%s'\n", res->uri); goto err; } break; case ST_SECTION_ID: /* the value of uri is the id of the config connection section in this case */ cfg_conn_info = ld_find_conn_info(uri); if (!cfg_conn_info) { ERR("ldap: connection id '%.*s' not found in ldap config\n", uri->len, uri->s); goto err; } ldapurllen = cfg_conn_info->host.len; sport = NULL; if (cfg_conn_info->port) { sport = int2str(cfg_conn_info->port, &portlen); // +1: we need space for ':' host and port delimiter ldapurllen += portlen + 1; } // +3 for the '://' ldap url snippet puri = res->uri = pkg_malloc(scheme->len + 3 + ldapurllen + 1); if (res->uri== NULL) { ERR("ldap: No memory left\n"); goto err; } memcpy(puri, scheme->s, scheme->len); puri += scheme->len; memcpy(puri, "://", strlen("://")); puri+= strlen("://"); memcpy(puri, cfg_conn_info->host.s, cfg_conn_info->host.len); puri+=cfg_conn_info->host.len; if (sport) { *puri++ = ':'; memcpy(puri, sport, portlen); } res->uri[scheme->len + 3 + ldapurllen] = '\0'; if (ldap_url_parse(res->uri, &res->ldap_url) != 0) { ERR("ldap: Error while parsing URL '%s'\n", res->uri); goto err; } if (cfg_conn_info->username.s) { if (!(res->username = pkgstrdup(&cfg_conn_info->username))) { ERR("ldap: No memory left\n"); goto err; } } if (cfg_conn_info->password.s) { if (!(res->password = pkgstrdup(&cfg_conn_info->password))) { ERR("ldap: No memory left\n"); goto err; } } res->authmech = cfg_conn_info->authmech; res->tls = cfg_conn_info->tls; if (cfg_conn_info->ca_list.s) { if (!(res->ca_list = pkgstrdup(&cfg_conn_info->ca_list))) { ERR("ldap: No memory left\n"); goto err; } } if (cfg_conn_info->req_cert.s) { if (!(res->req_cert = pkgstrdup(&cfg_conn_info->req_cert))) { ERR("ldap: No memory left\n"); goto err; } } break; default: goto err; } return 0; err: if (prev_token) pkg_free(prev_token); if (res == NULL) return -1; if (res->username) { pkg_free(res->username); res->username = NULL; } if (res->password) { pkg_free(res->password); res->password = NULL; } if (res->ca_list) { pkg_free(res->ca_list); res->ca_list = NULL; } if (res->req_cert) { pkg_free(res->req_cert); res->req_cert = NULL; } return -1; }
/* * This is the parsing function * The socket grammar should be: * [user [':' password] '@'] ip [':' port] '/' exchange */ static evi_reply_sock* rmq_parse(str socket) { evi_reply_sock *sock = NULL; rmq_params_t *param; unsigned int len, i; const char* begin; str prev_token; enum state { ST_USER_HOST, /* Username or hostname */ ST_PASS_PORT, /* Password or port part */ ST_HOST, /* Hostname part */ ST_PORT, /* Port part */ } st; if (!socket.len || !socket.s) { LM_ERR("no socket specified\n"); return NULL; } sock = shm_malloc(sizeof(evi_reply_sock) + sizeof(rmq_params_t)); if (!sock) { LM_ERR("no more memory for socket\n"); return NULL; } memset(sock, 0, sizeof(evi_reply_sock) + sizeof(rmq_params_t)); param = (rmq_params_t*)(sock + 1); prev_token.s = 0; prev_token.len = 0; /* Initialize all attributes to 0 */ st = ST_USER_HOST; begin = socket.s; len = socket.len; for(i = 0; i < len; i++) { switch(st) { case ST_USER_HOST: switch(socket.s[i]) { case '@': st = ST_HOST; if (dupl_string(¶m->user, begin, socket.s + i)) goto err; begin = socket.s + i + 1; param->flags |= RMQ_PARAM_USER; break; case ':': st = ST_PASS_PORT; if (dupl_string(&prev_token, begin, socket.s + i) < 0) goto err; begin = socket.s + i + 1; break; case '/': if (dupl_string(&sock->address, begin, socket.s + i) < 0) goto err; sock->flags |= EVI_ADDRESS; if (dupl_string(¶m->exchange, socket.s + i + 1, socket.s + len) < 0) goto err; param->flags |= RMQ_PARAM_EXCH; goto success; } break; case ST_PASS_PORT: switch(socket.s[i]) { case '@': st = ST_HOST; param->user.len = prev_token.len; param->user.s = prev_token.s; param->flags |= RMQ_PARAM_USER; prev_token.s = 0; if (dupl_string(¶m->pass, begin, socket.s + i) < 0) goto err; param->flags |= RMQ_PARAM_PASS; begin = socket.s + i + 1; break; case '/': sock->address.len = prev_token.len; sock->address.s = prev_token.s; prev_token.s = 0; sock->flags |= EVI_ADDRESS; sock->port = str2s(begin, socket.s + i - begin, 0); if (!sock->port) { LM_DBG("malformed port: %.*s\n", (int)(socket.s + i - begin), begin); goto err; } sock->flags |= EVI_PORT; if (dupl_string(¶m->exchange, socket.s + i + 1, socket.s + len) < 0) goto err; param->flags |= RMQ_PARAM_EXCH; goto success; } break; case ST_HOST: switch(socket.s[i]) { case ':': st = ST_PORT; if (dupl_string(&sock->address, begin, socket.s + i) < 0) goto err; sock->flags |= EVI_ADDRESS; begin = socket.s + i + 1; break; case '/': if (dupl_string(&sock->address, begin, socket.s + i) < 0) goto err; sock->flags |= EVI_ADDRESS; if (dupl_string(¶m->exchange, socket.s + i + 1, socket.s + len) < 0) goto err; param->flags |= RMQ_PARAM_EXCH; goto success; } break; case ST_PORT: switch(socket.s[i]) { case '/': sock->port = str2s(begin, socket.s + i - begin, 0); if (!sock->port) { LM_DBG("malformed port: %.*s\n", (int)(socket.s + i - begin), begin); goto err; } sock->flags |= EVI_PORT; if (dupl_string(¶m->exchange, socket.s + i + 1, socket.s + len) < 0) goto err; param->flags |= RMQ_PARAM_EXCH; goto success; } break; } } LM_WARN("not implemented %.*s\n", socket.len, socket.s); goto err; success: if (!(sock->flags & EVI_PORT) || !sock->port) { sock->port = RMQ_DEFAULT_PORT; sock->flags |= EVI_PORT; } if (!(param->flags & RMQ_PARAM_USER) || !param->user.s) { param->user.s = param->pass.s = RMQ_DEFAULT_UP; param->user.len = param->pass.len = RMQ_DEFAULT_UP_LEN; param->flags |= RMQ_PARAM_USER|RMQ_PARAM_PASS; } sock->params = param; sock->flags |= EVI_PARAMS | RMQ_FLAG; return sock; err: LM_ERR("error while parsing socket %.*s\n", socket.len, socket.s); if (prev_token.s) shm_free(prev_token.s); rmq_free_param(param); if (sock->address.s) shm_free(sock->address.s); shm_free(sock); return NULL; }
// create an Account object Account::Account(const char* n, const char* id, int b): name(dupl_string(n)), account_id(dupl_string(id)) { balance = b; }
Restaurant::Restaurant(const char* s, int t): name(dupl_string(s)) { tables = t; }