static struct ast_config *realtime_sorcery_multi(const char *database, const char *table, const struct ast_variable *fields) { struct ast_config *objects; char *object_id = NULL; if (!(objects = ast_config_new())) { return NULL; } while ((object_id = ast_category_browse(realtime_objects, object_id))) { struct ast_category *object; if (!realtime_is_object_matching(object_id, fields)) { continue; } if (!(object = ast_category_new("", "", 0))) { ast_config_destroy(objects); return NULL; } ast_variable_append(object, ast_variables_dup(ast_category_root(realtime_objects, object_id))); ast_category_append(objects, object); } return objects; }
static struct ast_config *realtime_directory(char *context) { struct ast_config *cfg; struct ast_config *rtdata; struct ast_category *cat; struct ast_variable *var; char *mailbox; char *fullname; char *hidefromdir; char tmp[100]; /* Load flat file config. */ cfg = ast_config_load(VOICEMAIL_CONFIG); if (!cfg) { /* Loading config failed. */ ast_log(LOG_WARNING, "Loading config failed.\n"); return NULL; } /* Get realtime entries, categorized by their mailbox number and present in the requested context */ rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, NULL); /* if there are no results, just return the entries from the config file */ if (!rtdata) return cfg; /* Does the context exist within the config file? If not, make one */ cat = ast_category_get(cfg, context); if (!cat) { cat = ast_category_new(context); if (!cat) { ast_log(LOG_WARNING, "Out of memory\n"); ast_config_destroy(cfg); return NULL; } ast_category_append(cfg, cat); } mailbox = ast_category_browse(rtdata, NULL); while (mailbox) { fullname = ast_variable_retrieve(rtdata, mailbox, "fullname"); hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir"); snprintf(tmp, sizeof(tmp), "no-password,%s,hidefromdir=%s", fullname ? fullname : "", hidefromdir ? hidefromdir : "no"); var = ast_variable_new(mailbox, tmp); if (var) ast_variable_append(cat, var); else ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox); mailbox = ast_category_browse(rtdata, mailbox); } ast_config_destroy(rtdata); return cfg; }
static int realtime_sorcery_store(const char *database, const char *table, const struct ast_variable *fields) { /* The key field is explicit within res_sorcery_realtime */ const struct ast_variable *keyfield = realtime_find_variable(fields, "id"); struct ast_category *object; if (!keyfield || ast_category_exist(realtime_objects, keyfield->value, NULL) || !(object = ast_category_new(keyfield->value, "", 0))) { return -1; } ast_variable_append(object, ast_variables_dup((struct ast_variable*)fields)); ast_category_append(realtime_objects, object); return 1; }
static int realtime_sorcery_update(const char *database, const char *table, const char *keyfield, const char *entity, const struct ast_variable *fields) { struct ast_category *object, *found; if (!(found = ast_category_get(realtime_objects, entity, NULL))) { return 0; } else if (!(object = ast_category_new(entity, "", 0))) { return -1; } ast_category_delete(realtime_objects, found); ast_variable_append(object, ast_variables_dup((struct ast_variable*)fields)); ast_variable_append(object, ast_variable_new(keyfield, entity, "")); ast_category_append(realtime_objects, object); return 1; }
/*! * \brief Build ast_config struct from above definitions * * \retval NULL Failed to build the config * \retval non-NULL An ast_config struct populated with data */ static struct ast_config *build_cfg(void) { struct ast_config *cfg; struct association *cat_iter; struct pair *var_iter; size_t i; size_t j; cfg = ast_config_new(); if (!cfg) { goto fail; } for (i = 0; i < ARRAY_LEN(categories); ++i) { struct ast_category *cat; cat_iter = &categories[i]; cat = ast_category_new(cat_iter->category, "", 999999); if (!cat) { goto fail; } ast_category_append(cfg, cat); for (j = 0; j < ARRAY_LEN(cat_iter->vars); ++j) { struct ast_variable *var; var_iter = &cat_iter->vars[j]; var = ast_variable_new(var_iter->name, var_iter->val, ""); if (!var) { goto fail; } ast_variable_append(cat, var); } } return cfg; fail: ast_config_destroy(cfg); return NULL; }
static struct ast_config *config_sqlite(const char *database, const char *table, const char *file, struct ast_config *cfg) { struct ast_variable *new_v, *v; struct ast_category *cur_cat; char ttable[ARRAY_SIZE]; int configured = 0, res = 0; sqlite3_stmt *stmt = NULL;; int cat_metric=0, last_cat_metric=0; char sql[ARRAY_SIZE]; char last[ARRAY_SIZE] = ""; char path[ARRAY_SIZE]; sqlite3 *db; int running=0; int i=0; struct ast_config *config; /* if the data was not passed from extconfig.conf then get it from sqlite.conf */ if(!database || ast_strlen_zero(database)) { if (!file || !strcmp (file, "res_sqlite.conf")) return NULL; // cant configure myself with myself ! config = ast_config_load ("res_sqlite.conf"); if (config) { for (v = ast_variable_browse (config, "config"); v; v = v->next) { if (!strcmp (v->name, "table")) { strncpy (ttable, v->value, sizeof (ttable)); configured++; } else if (!strcmp (v->name, "dbfile")) { pick_path(v->value,path,ARRAY_SIZE); configured++; } } ast_config_destroy (config); } } else { pick_path((char *)database,path,ARRAY_SIZE); strncpy (ttable, table, sizeof (ttable)); configured = 2; } if (configured < 2) return NULL; db=open_db(path); if (!db) return NULL; sprintf (sql, "select * from %s where filename='%s' and commented=0 order by filename,cat_metric desc,var_metric asc,id", ttable, file); res = sqlite3_prepare(db,sql,0,&stmt,0); if (res) { ast_log (LOG_WARNING, "SQL select error [%s]!\n[%s]\n\n",sqlite3_errmsg(db), sql); return NULL; } cur_cat = ast_config_get_current_category(cfg); /* 0 id int 1 cat_metric int not null default 0, 2 var_metric int not null default 0, 3 commented int not null default 0, 4 filename varchar(128) not null, 5 category varchar(128) not null default 'default', 6 var_name varchar(128) not null, 7 var_val varchar(128) not null */ running = 1; while (running) { res = sqlite3_step(stmt); running = 1; switch( res ){ case SQLITE_DONE: running = 0 ; break; case SQLITE_BUSY: sleep(2); running = 2; break ; case SQLITE_ERROR: running = 0; break; case SQLITE_MISUSE: running = 0; break; case SQLITE_ROW: default: break; } if (!running) break; if (running == 2) continue; if(option_verbose > 4) for(i=0;i<8;i++){ ast_verbose(VERBOSE_PREFIX_3"SQLite Config: %d=%s\n",i,sqlite3_column_text(stmt,i)); } if (strcmp (last, sqlite3_column_text(stmt,5)) || last_cat_metric != cat_metric) { cur_cat = ast_category_new((char *)sqlite3_column_text(stmt,5)); if (!cur_cat) { ast_log(LOG_WARNING, "Out of memory!\n"); break; } strcpy (last, sqlite3_column_text(stmt,5)); last_cat_metric = cat_metric; ast_category_append(cfg, cur_cat); } new_v = ast_variable_new ((char *)sqlite3_column_text(stmt,6), (char *)sqlite3_column_text(stmt,7)); ast_variable_append(cur_cat, new_v); } if ((sqlite3_finalize(stmt))) ast_log(LOG_ERROR,"ERROR: %s\n",sqlite3_errmsg(db)); return cfg; }
static struct ast_config *config_pgsql(const char *database, const char *table, const char *file, struct ast_config *cfg, int withcomments) { PGresult *result = NULL; long num_rows; struct ast_variable *new_v; struct ast_category *cur_cat = NULL; char sqlbuf[1024] = ""; char *sql; size_t sqlleft = sizeof(sqlbuf); char last[80] = ""; int last_cat_metric = 0; last[0] = '\0'; if (!file || !strcmp(file, RES_CONFIG_PGSQL_CONF)) { ast_log(LOG_WARNING, "Postgresql RealTime: Cannot configure myself.\n"); return NULL; } ast_build_string(&sql, &sqlleft, "SELECT category, var_name, var_val, cat_metric FROM %s ", table); ast_build_string(&sql, &sqlleft, "WHERE filename='%s' and commented=0", file); ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name "); ast_log(LOG_DEBUG, "Postgresql RealTime: Static SQL: %s\n", sqlbuf); /* We now have our complete statement; Lets connect to the server and execute it. */ ast_mutex_lock(&pgsql_lock); if (!pgsql_reconnect(database)) { ast_mutex_unlock(&pgsql_lock); return NULL; } if (!(result = PQexec(pgsqlConn, sqlbuf))) { ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return NULL; } else { ExecStatusType result_status = PQresultStatus(result); if (result_status != PGRES_COMMAND_OK && result_status != PGRES_TUPLES_OK && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); return NULL; } } if ((num_rows = PQntuples(result)) > 0) { int rowIndex = 0; ast_log(LOG_DEBUG, "Postgresql RealTime: Found %ld rows.\n", num_rows); for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { char *field_category = PQgetvalue(result, rowIndex, 0); char *field_var_name = PQgetvalue(result, rowIndex, 1); char *field_var_val = PQgetvalue(result, rowIndex, 2); char *field_cat_metric = PQgetvalue(result, rowIndex, 3); if (!strcmp(field_var_name, "#include")) { if (!ast_config_internal_load(field_var_val, cfg, 0)) { PQclear(result); ast_mutex_unlock(&pgsql_lock); return NULL; } continue; } if (strcmp(last, field_category) || last_cat_metric != atoi(field_cat_metric)) { cur_cat = ast_category_new(field_category); if (!cur_cat) break; strcpy(last, field_category); last_cat_metric = atoi(field_cat_metric); ast_category_append(cfg, cur_cat); } new_v = ast_variable_new(field_var_name, field_var_val); ast_variable_append(cur_cat, new_v); } } else { ast_log(LOG_WARNING, "Postgresql RealTime: Could not find config '%s' in database.\n", file); } PQclear(result); ast_mutex_unlock(&pgsql_lock); return cfg; }
static struct ast_config *realtime_multi_pgsql(const char *database, const char *table, va_list ap) { PGresult *result = NULL; int num_rows = 0; char sql[256]; const char *initfield = NULL; char *stringp; char *chunk; char *op; const char *newparam, *newval; struct ast_realloca ra; struct ast_variable *var = NULL; struct ast_config *cfg = NULL; struct ast_category *cat = NULL; if (!table) { ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n"); return NULL; } memset(&ra, 0, sizeof(ra)); if (!(cfg = ast_config_new())) return NULL; /* Get the first parameter and first value in our list of passed paramater/value pairs */ newparam = va_arg(ap, const char *); newval = va_arg(ap, const char *); if (!newparam || !newval) { ast_log(LOG_WARNING, "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; }; return NULL; } initfield = ast_strdupa(newparam); if ((op = strchr(initfield, ' '))) { *op = '\0'; } /* Create the first part of the query using the first parameter/value pairs we just extracted If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ if (!strchr(newparam, ' ')) op = " ="; else op = ""; snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); if (!strchr(newparam, ' ')) op = " ="; else op = ""; snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval); } if (initfield) { snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield); } va_end(ap); /* We now have our complete statement; Lets connect to the server and execute it. */ ast_mutex_lock(&pgsql_lock); if (!pgsql_reconnect(database)) { ast_mutex_unlock(&pgsql_lock); return NULL; } if (!(result = PQexec(pgsqlConn, sql))) { ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return NULL; } else { ExecStatusType result_status = PQresultStatus(result); if (result_status != PGRES_COMMAND_OK && result_status != PGRES_TUPLES_OK && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); return NULL; } } ast_log(LOG_DEBUG, "2Postgresql RealTime: Result=%p Query: %s\n", result, sql); if ((num_rows = PQntuples(result)) > 0) { int numFields = PQnfields(result); int i = 0; int rowIndex = 0; char **fieldnames = NULL; ast_log(LOG_DEBUG, "Postgresql RealTime: Found %d rows.\n", num_rows); if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) { ast_mutex_unlock(&pgsql_lock); PQclear(result); return NULL; } for (i = 0; i < numFields; i++) fieldnames[i] = PQfname(result, i); for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { var = NULL; if (!(cat = ast_category_new(""))) continue; for (i = 0; i < numFields; i++) { stringp = PQgetvalue(result, rowIndex, i); while (stringp) { chunk = strsep(&stringp, ";"); if (chunk && !ast_strlen_zero(ast_strip(chunk))) { if (initfield && !strcmp(initfield, fieldnames[i])) { ast_category_rename(cat, chunk); } var = ast_variable_new(fieldnames[i], chunk); ast_variable_append(cat, var); } } } ast_category_append(cfg, cat); } free(fieldnames); } else { ast_log(LOG_WARNING, "Postgresql RealTime: Could not find any rows in table %s.\n", table); } ast_mutex_unlock(&pgsql_lock); PQclear(result); return cfg; }
static struct ast_config *config_curl(const char *url, const char *unused, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *sugg_incl, const char *who_asked) { struct ast_str *query, *buffer; char buf1[200]; char *stringp, *line, *pair, *key; int last_cat_metric = -1, cat_metric = -1; struct ast_category *cat = NULL; char *cur_cat = ""; char *category = "", *var_name = "", *var_val = ""; struct ast_flags loader_flags = { 0 }; if (!ast_custom_function_find("CURL")) { ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n"); return NULL; } if (!(query = ast_str_thread_get(&query_buf, 100))) { return NULL; } if (!(buffer = ast_str_thread_get(&result_buf, 16))) { return NULL; } ast_uri_encode(file, buf1, sizeof(buf1), ast_uri_http); ast_str_set(&query, 0, "${CURL(%s/static?file=%s)}", url, buf1); /* Do the CURL query */ ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query)); /* Line oriented output */ stringp = ast_str_buffer(buffer); cat = ast_config_get_current_category(cfg); while ((line = strsep(&stringp, "\r\n"))) { if (ast_strlen_zero(line)) { continue; } while ((pair = strsep(&line, "&"))) { key = strsep(&pair, "="); ast_uri_decode(key, ast_uri_http); if (pair) { ast_uri_decode(pair, ast_uri_http); } if (!strcasecmp(key, "category")) { category = S_OR(pair, ""); } else if (!strcasecmp(key, "var_name")) { var_name = S_OR(pair, ""); } else if (!strcasecmp(key, "var_val")) { var_val = S_OR(pair, ""); } else if (!strcasecmp(key, "cat_metric")) { cat_metric = pair ? atoi(pair) : 0; } } if (!strcmp(var_name, "#include")) { if (!ast_config_internal_load(var_val, cfg, loader_flags, "", who_asked)) return NULL; } if (!cat || strcmp(category, cur_cat) || last_cat_metric != cat_metric) { if (!(cat = ast_category_new(category, "", 99999))) break; cur_cat = category; last_cat_metric = cat_metric; ast_category_append(cfg, cat); } ast_variable_append(cat, ast_variable_new(var_name, var_val, "")); } return cfg; }
/*! * \brief Excute an Select query and return ast_config list * \param url * \param unused * \param fields list containing one or more field/operator/value set. * * \retval struct ast_config pointer on success * \retval NULL on failure */ static struct ast_config *realtime_multi_curl(const char *url, const char *unused, const struct ast_variable *fields) { struct ast_str *query, *buffer; char buf1[256], buf2[256]; const struct ast_variable *field; char *stringp, *line, *pair, *key, *initfield = NULL; int start = 1; struct ast_variable *var = NULL; struct ast_config *cfg = NULL; struct ast_category *cat = NULL; if (!ast_custom_function_find("CURL")) { ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n"); return NULL; } if (!(query = ast_str_thread_get(&query_buf, 16))) { return NULL; } if (!(buffer = ast_str_thread_get(&result_buf, 16))) { return NULL; } ast_str_set(&query, 0, "${CURL(%s/multi,", url); for (field = fields; field; field = field->next) { if (start) { char *op; initfield = ast_strdupa(field->name); if ((op = strchr(initfield, ' '))) *op = '\0'; } ast_uri_encode(field->name, buf1, sizeof(buf1), ast_uri_http); ast_uri_encode(field->value, buf2, sizeof(buf2), ast_uri_http); ast_str_append(&query, 0, "%s%s=%s", !start ? "&" : "", buf1, buf2); start = 0; } ast_str_append(&query, 0, ")}"); /* Do the CURL query */ ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query)); if (!(cfg = ast_config_new())) { return NULL; } /* Line oriented output */ stringp = ast_str_buffer(buffer); while ((line = strsep(&stringp, "\r\n"))) { if (ast_strlen_zero(line)) { continue; } if (!(cat = ast_category_new("", "", 99999))) { continue; } while ((pair = strsep(&line, "&"))) { key = strsep(&pair, "="); ast_uri_decode(key, ast_uri_http); if (pair) { ast_uri_decode(pair, ast_uri_http); } if (!strcasecmp(key, initfield) && pair) { ast_category_rename(cat, pair); } if (!ast_strlen_zero(key)) { var = ast_variable_new(key, S_OR(pair, ""), ""); ast_variable_append(cat, var); } } ast_category_append(cfg, cat); } return cfg; }
/*! * \brief Excute an Select query and return ast_config list * \param url * \param unused * \param ap list containing one or more field/operator/value set. * * \retval struct ast_config pointer on success * \retval NULL on failure */ static struct ast_config *realtime_multi_curl(const char *url, const char *unused, va_list ap) { struct ast_str *query; char buf1[200], buf2[200]; const char *newparam, *newval; char *stringp, *line, *pair, *key, *initfield = NULL; int i; const int EncodeSpecialChars = 1, bufsize = 256000; struct ast_variable *var=NULL; struct ast_config *cfg=NULL; struct ast_category *cat=NULL; char *buffer; if (!ast_custom_function_find("CURL")) { ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n"); return NULL; } if (!(query = ast_str_create(1000))) return NULL; if (!(buffer = ast_malloc(bufsize))) { ast_free(query); return NULL; } ast_str_set(&query, 0, "${CURL(%s/multi,", url); for (i = 0; (newparam = va_arg(ap, const char *)); i++) { newval = va_arg(ap, const char *); if (i == 0) { char *op; initfield = ast_strdupa(newparam); if ((op = strchr(initfield, ' '))) *op = '\0'; } ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars); ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars); ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2); } va_end(ap); ast_str_append(&query, 0, ")}"); /* Do the CURL query */ pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize); if (!(cfg = ast_config_new())) goto exit_multi; /* Line oriented output */ stringp = buffer; while ((line = strsep(&stringp, "\r\n"))) { if (ast_strlen_zero(line)) continue; if (!(cat = ast_category_new("", "", 99999))) continue; while ((pair = strsep(&line, "&"))) { key = strsep(&pair, "="); ast_uri_decode(key); if (pair) ast_uri_decode(pair); if (!strcasecmp(key, initfield) && pair) ast_category_rename(cat, pair); if (!ast_strlen_zero(key)) { var = ast_variable_new(key, S_OR(pair, ""), ""); ast_variable_append(cat, var); } } ast_category_append(cfg, cat); } exit_multi: ast_free(buffer); ast_free(query); return cfg; }