diff options
53 files changed, 1254 insertions, 907 deletions
diff --git a/apps/app_chanisavail.c b/apps/app_chanisavail.c index bc1adcc79..556bafd71 100644 --- a/apps/app_chanisavail.c +++ b/apps/app_chanisavail.c @@ -160,13 +160,13 @@ static int chanavail_exec(struct ast_channel *chan, void *data) status = inuse = ast_device_state(trychan); } if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) { - ast_str_append(&tmp_availchan, 0, "%s%s", tmp_availchan->used ? "&" : "", tempchan->name); + ast_str_append(&tmp_availchan, 0, "%s%s", ast_str_strlen(tmp_availchan) ? "&" : "", tempchan->name); snprintf(tmp, sizeof(tmp), "%s/%s", tech, number); - ast_str_append(&tmp_availorig, 0, "%s%s", tmp_availorig->used ? "&" : "", tmp); + ast_str_append(&tmp_availorig, 0, "%s%s", ast_str_strlen(tmp_availorig) ? "&" : "", tmp); snprintf(tmp, sizeof(tmp), "%d", status); - ast_str_append(&tmp_availstat, 0, "%s%s", tmp_availstat->used ? "&" : "", tmp); + ast_str_append(&tmp_availstat, 0, "%s%s", ast_str_strlen(tmp_availstat) ? "&" : "", tmp); ast_hangup(tempchan); tempchan = NULL; @@ -176,16 +176,16 @@ static int chanavail_exec(struct ast_channel *chan, void *data) } } else { snprintf(tmp, sizeof(tmp), "%d", status); - ast_str_append(&tmp_availstat, 0, "%s%s", tmp_availstat->used ? "&" : "", tmp); + ast_str_append(&tmp_availstat, 0, "%s%s", ast_str_strlen(tmp_availstat) ? "&" : "", tmp); } cur = rest; } while (cur); } - pbx_builtin_setvar_helper(chan, "AVAILCHAN", tmp_availchan->str); + pbx_builtin_setvar_helper(chan, "AVAILCHAN", ast_str_buffer(tmp_availchan)); /* Store the originally used channel too */ - pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp_availorig->str); - pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp_availstat->str); + pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", ast_str_buffer(tmp_availorig)); + pbx_builtin_setvar_helper(chan, "AVAILSTATUS", ast_str_buffer(tmp_availstat)); return 0; } diff --git a/apps/app_dumpchan.c b/apps/app_dumpchan.c index d3bf17f6c..c598bee75 100644 --- a/apps/app_dumpchan.c +++ b/apps/app_dumpchan.c @@ -35,6 +35,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/pbx.h" #include "asterisk/module.h" #include "asterisk/channel.h" +#include "asterisk/app.h" /*** DOCUMENTATION <application name="DumpChan" language="en_US"> @@ -148,7 +149,7 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size) static int dumpchan_exec(struct ast_channel *chan, void *data) { - struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX very large! */ + struct ast_str *vars = ast_str_thread_get(&global_app_buf, 16); char info[1024]; int level = 0; static char *line = "================================================================================"; @@ -156,10 +157,11 @@ static int dumpchan_exec(struct ast_channel *chan, void *data) if (!ast_strlen_zero(data)) level = atoi(data); - pbx_builtin_serialize_variables(chan, &vars); - serialize_showchan(chan, info, sizeof(info)); - if (option_verbose >= level) - ast_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n", chan->name, line, info, vars->str, line); + if (option_verbose >= level) { + serialize_showchan(chan, info, sizeof(info)); + pbx_builtin_serialize_variables(chan, &vars); + ast_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n", chan->name, line, info, ast_str_buffer(vars), line); + } return 0; } diff --git a/apps/app_externalivr.c b/apps/app_externalivr.c index 20eda9b43..936a111ac 100644 --- a/apps/app_externalivr.c +++ b/apps/app_externalivr.c @@ -122,8 +122,8 @@ static void send_eivr_event(FILE *handle, const char event, const char *data, ast_str_append(&tmp, 0, ",%s", data); } - fprintf(handle, "%s\n", tmp->str); - ast_debug(1, "sent '%s'\n", tmp->str); + fprintf(handle, "%s\n", ast_str_buffer(tmp)); + ast_debug(1, "sent '%s'\n", ast_str_buffer(tmp)); } static void *gen_alloc(struct ast_channel *chan, void *params) @@ -276,7 +276,7 @@ static void ast_eivr_getvariable(struct ast_channel *chan, char *data, char *out ast_str_append(&newstring, 0, "%s=%s,", variable, value); ast_channel_unlock(chan); - ast_copy_string(outbuf, newstring->str, outbuflen); + ast_copy_string(outbuf, ast_str_buffer(newstring), outbuflen); } } @@ -659,7 +659,8 @@ static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u, continue; if (input[0] == 'P') { - send_eivr_event(eivr_events, 'P', args->str, chan); + struct ast_str *tmp = (struct ast_str *) args; + send_eivr_event(eivr_events, 'P', ast_str_buffer(tmp), chan); } else if ( input[0] == 'T' ) { ast_chan_log(LOG_WARNING, chan, "Answering channel if needed and starting generator\n"); if (chan->_state != AST_STATE_UP) { diff --git a/apps/app_followme.c b/apps/app_followme.c index bce763f29..62a3cb248 100644 --- a/apps/app_followme.c +++ b/apps/app_followme.c @@ -960,9 +960,8 @@ static struct call_followme *find_realtime(const char *name) } /* This one has to exist; it was part of the query */ ordstr = ast_variable_retrieve(cfg, catg, "ordinal"); - ast_str_make_space(&str, strlen(numstr) + 1); - ast_copy_string(str->str, numstr, str->len); - if ((cur = create_followme_number(str->str, timeout, atoi(ordstr)))) { + ast_str_set(&str, 0, "%s", numstr); + if ((cur = create_followme_number(ast_str_buffer(str), timeout, atoi(ordstr)))) { AST_LIST_INSERT_TAIL(&new->numbers, cur, entry); } } diff --git a/apps/app_meetme.c b/apps/app_meetme.c index d22cef3cb..025ad3561 100644 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -1260,7 +1260,7 @@ static char *meetme_show_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ar min = ((now - cnf->start) % 3600) / 60; sec = (now - cnf->start) % 60; if (!concise) { - ast_cli(a->fd, MC_DATA_FORMAT, cnf->confno, cnf->users, cmdline->str, hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static", cnf->locked ? "Yes" : "No"); + ast_cli(a->fd, MC_DATA_FORMAT, cnf->confno, cnf->users, ast_str_buffer(cmdline), hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static", cnf->locked ? "Yes" : "No"); } else { ast_cli(a->fd, "%s!%d!%d!%02d:%02d:%02d!%d!%d\n", cnf->confno, @@ -1345,9 +1345,9 @@ static char *meetme_show_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ar return CLI_SHOWUSAGE; } - ast_debug(1, "Cmdline: %s\n", cmdline->str); + ast_debug(1, "Cmdline: %s\n", ast_str_buffer(cmdline)); - admin_exec(NULL, cmdline->str); + admin_exec(NULL, ast_str_buffer(cmdline)); ast_free(cmdline); return CLI_SUCCESS; @@ -1435,9 +1435,9 @@ static char *meetme_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a return CLI_SHOWUSAGE; } - ast_debug(1, "Cmdline: %s\n", cmdline->str); + ast_debug(1, "Cmdline: %s\n", ast_str_buffer(cmdline)); - admin_exec(NULL, cmdline->str); + admin_exec(NULL, ast_str_buffer(cmdline)); ast_free(cmdline); return CLI_SUCCESS; @@ -4615,7 +4615,7 @@ static void *run_station(void *data) ast_set_flag(&conf_flags, CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION); answer_trunk_chan(trunk_ref->chan); - conf = build_conf(conf_name->str, "", "", 0, 0, 1, trunk_ref->chan); + conf = build_conf(ast_str_buffer(conf_name), "", "", 0, 0, 1, trunk_ref->chan); if (conf) { conf_run(trunk_ref->chan, conf, conf_flags.flags, NULL); dispose_conf(conf); @@ -4625,7 +4625,7 @@ static void *run_station(void *data) if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) { ast_str_append(&conf_name, 0, ",K"); - admin_exec(NULL, conf_name->str); + admin_exec(NULL, ast_str_buffer(conf_name)); trunk_ref->trunk->hold_stations = 0; sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL); } diff --git a/apps/app_queue.c b/apps/app_queue.c index 1863acdaa..70c915160 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -2284,7 +2284,7 @@ static void do_hang(struct callattempt *o) /*! \brief convert "\n" to "\nVariable: " ready for manager to use */ static char *vars2manager(struct ast_channel *chan, char *vars, size_t len) { - struct ast_str *buf = ast_str_alloca(len + 1); + struct ast_str *buf = ast_str_thread_get(&global_app_buf, len + 1); char *tmp; if (pbx_builtin_serialize_variables(chan, &buf)) { @@ -2292,7 +2292,7 @@ static char *vars2manager(struct ast_channel *chan, char *vars, size_t len) /* convert "\n" to "\nVariable: " */ strcpy(vars, "Variable: "); - tmp = buf->str; + tmp = ast_str_buffer(buf); for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) { vars[j] = tmp[i]; @@ -2601,12 +2601,12 @@ static int say_periodic_announcement(struct queue_ent *qe, int ringing) if (qe->parent->randomperiodicannounce) { qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce; } else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce || - ast_strlen_zero(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str)) { + ast_str_strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]) == 0) { qe->last_periodic_announce_sound = 0; } /* play the announcement */ - res = play_file(qe->chan, qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]->str); + res = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound])); if ((res > 0 && !valid_exit(qe, res)) || res < 0) res = 0; @@ -5734,7 +5734,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, char **argv) ast_str_append(&out, 0, ") in '%s' strategy (%ds holdtime), W:%d, C:%d, A:%d, SL:%2.1f%% within %ds", int2strat(q->strategy), q->holdtime, q->weight, q->callscompleted, q->callsabandoned,sl,q->servicelevel); - do_print(s, fd, out->str); + do_print(s, fd, ast_str_buffer(out)); if (!ao2_container_count(q->members)) do_print(s, fd, " No Members"); else { @@ -5759,7 +5759,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, char **argv) mem->calls, (long) (time(NULL) - mem->lastcall)); else ast_str_append(&out, 0, " has taken no calls yet"); - do_print(s, fd, out->str); + do_print(s, fd, ast_str_buffer(out)); ao2_ref(mem, -1); } } @@ -5774,7 +5774,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, char **argv) ast_str_set(&out, 0, " %d. %s (wait: %ld:%2.2ld, prio: %d)", pos++, qe->chan->name, (long) (now - qe->start) / 60, (long) (now - qe->start) % 60, qe->prio); - do_print(s, fd, out->str); + do_print(s, fd, ast_str_buffer(out)); } } do_print(s, fd, ""); /* blank line between entries */ @@ -5795,7 +5795,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, char **argv) ast_str_set(&out, 0, "No such queue: %s.", argv[2]); else ast_str_set(&out, 0, "No queues."); - do_print(s, fd, out->str); + do_print(s, fd, ast_str_buffer(out)); } return CLI_SUCCESS; } diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index f23624fa2..fc2a5244c 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -10196,12 +10196,12 @@ static void free_vm_zones(void) AST_LIST_UNLOCK(&zones); } -static char *substitute_escapes(const char *value) +static const char *substitute_escapes(const char *value) { - char *current, *result; + char *current; /* Add 16 for fudge factor */ - struct ast_str *str = ast_str_create(strlen(value) + 16); + struct ast_str *str = ast_str_thread_get(&global_app_buf, strlen(value) + 16); /* Substitute strings \r, \n, and \t into the appropriate characters */ for (current = (char *) value; *current; current++) { @@ -10235,10 +10235,7 @@ static char *substitute_escapes(const char *value) } } - result = ast_strdup(str->str); - ast_free(str); - - return result; + return ast_str_buffer(str); } static int load_config(int reload) @@ -10858,13 +10855,13 @@ static int load_config(int reload) emailsubject = ast_strdup(val); } if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) { - emailbody = substitute_escapes(val); + emailbody = ast_strdup(substitute_escapes(val)); } if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) { pagersubject = ast_strdup(val); } if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) { - pagerbody = substitute_escapes(val); + pagerbody = ast_strdup(substitute_escapes(val)); } AST_LIST_UNLOCK(&users); ast_config_destroy(cfg); diff --git a/cdr/cdr_adaptive_odbc.c b/cdr/cdr_adaptive_odbc.c index a8665add4..6b9b090f3 100644 --- a/cdr/cdr_adaptive_odbc.c +++ b/cdr/cdr_adaptive_odbc.c @@ -317,8 +317,8 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data) #define LENGTHEN_BUF1(size) \ do { \ /* Lengthen buffer, if necessary */ \ - if (sql->used + size + 1 > sql->len) { \ - if (ast_str_make_space(&sql, ((sql->len + size + 1) / 512 + 1) * 512) != 0) { \ + if (ast_str_strlen(sql) + size + 1 > ast_str_size(sql)) { \ + if (ast_str_make_space(&sql, ((ast_str_size(sql) + size + 1) / 512 + 1) * 512) != 0) { \ ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CDR '%s:%s' failed.\n", tableptr->connection, tableptr->table); \ ast_free(sql); \ ast_free(sql2); \ @@ -330,8 +330,8 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data) #define LENGTHEN_BUF2(size) \ do { \ - if (sql2->used + size + 1 > sql2->len) { \ - if (ast_str_make_space(&sql2, ((sql2->len + size + 3) / 512 + 1) * 512) != 0) { \ + if (ast_str_strlen(sql2) + size + 1 > ast_str_size(sql2)) { \ + if (ast_str_make_space(&sql2, ((ast_str_size(sql2) + size + 3) / 512 + 1) * 512) != 0) { \ ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CDR '%s:%s' failed.\n", tableptr->connection, tableptr->table); \ ast_free(sql); \ ast_free(sql2); \ @@ -368,12 +368,13 @@ static int odbc_log(struct ast_cdr *cdr) } AST_LIST_TRAVERSE(&odbc_tables, tableptr, list) { + int first = 1; ast_str_set(&sql, 0, "INSERT INTO %s (", tableptr->table); ast_str_set(&sql2, 0, " VALUES ("); /* No need to check the connection now; we'll handle any failure in prepare_and_execute */ if (!(obj = ast_odbc_request_obj(tableptr->connection, 0))) { - ast_log(LOG_WARNING, "cdr_adaptive_odbc: Unable to retrieve database handle for '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, sql->str); + ast_log(LOG_WARNING, "cdr_adaptive_odbc: Unable to retrieve database handle for '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, ast_str_buffer(sql)); continue; } @@ -442,11 +443,11 @@ static int odbc_log(struct ast_cdr *cdr) } } - ast_str_append(&sql, 0, "%s,", entry->name); + ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name); LENGTHEN_BUF2(strlen(colptr)); /* Encode value, with escaping */ - ast_str_append(&sql2, 0, "'"); + ast_str_append(&sql2, 0, "%s'", first ? "" : ","); for (tmp = colptr; *tmp; tmp++) { if (*tmp == '\'') { ast_str_append(&sql2, 0, "''"); @@ -456,7 +457,7 @@ static int odbc_log(struct ast_cdr *cdr) ast_str_append(&sql2, 0, "%c", *tmp); } } - ast_str_append(&sql2, 0, "',"); + ast_str_append(&sql2, 0, "'"); break; case SQL_TYPE_DATE: { @@ -469,16 +470,16 @@ static int odbc_log(struct ast_cdr *cdr) (month == 2 && year % 4 == 0 && day > 29) || (month == 2 && year % 4 != 0 && day > 28)) { ast_log(LOG_WARNING, "CDR variable %s is not a valid date ('%s').\n", entry->name, colptr); - break; + continue; } if (year > 0 && year < 100) { year += 2000; } - ast_str_append(&sql, 0, "%s,", entry->name); + ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name); LENGTHEN_BUF2(17); - ast_str_append(&sql2, 0, "{ d '%04d-%02d-%02d' },", year, month, day); + ast_str_append(&sql2, 0, "%s{ d '%04d-%02d-%02d' }", first ? "" : ",", year, month, day); } break; case SQL_TYPE_TIME: @@ -488,12 +489,12 @@ static int odbc_log(struct ast_cdr *cdr) if ((count != 2 && count != 3) || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) { ast_log(LOG_WARNING, "CDR variable %s is not a valid time ('%s').\n", entry->name, colptr); - break; + continue; } - ast_str_append(&sql, 0, "%s,", entry->name); + ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name); LENGTHEN_BUF2(15); - ast_str_append(&sql2, 0, "{ t '%02d:%02d:%02d' },", hour, minute, second); + ast_str_append(&sql2, 0, "%s{ t '%02d:%02d:%02d' }", first ? "" : ",", hour, minute, second); } break; case SQL_TYPE_TIMESTAMP: @@ -511,16 +512,16 @@ static int odbc_log(struct ast_cdr *cdr) (month == 2 && year % 4 != 0 && day > 28) || hour > 23 || minute > 59 || second > 59 || hour < 0 || minute < 0 || second < 0) { ast_log(LOG_WARNING, "CDR variable %s is not a valid timestamp ('%s').\n", entry->name, colptr); - break; + continue; } if (year > 0 && year < 100) { year += 2000; } - ast_str_append(&sql, 0, "%s,", entry->name); + ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name); LENGTHEN_BUF2(26); - ast_str_append(&sql2, 0, "{ ts '%04d-%02d-%02d %02d:%02d:%02d' },", year, month, day, hour, minute, second); + ast_str_append(&sql2, 0, "%s{ ts '%04d-%02d-%02d %02d:%02d:%02d' }", first ? "" : ",", year, month, day, hour, minute, second); } break; case SQL_INTEGER: @@ -528,12 +529,12 @@ static int odbc_log(struct ast_cdr *cdr) int integer = 0; if (sscanf(colptr, "%d", &integer) != 1) { ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); - break; + continue; } - ast_str_append(&sql, 0, "%s,", entry->name); + ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name); LENGTHEN_BUF2(12); - ast_str_append(&sql2, 0, "%d,", integer); + ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", integer); } break; case SQL_BIGINT: @@ -541,12 +542,12 @@ static int odbc_log(struct ast_cdr *cdr) long long integer = 0; if (sscanf(colptr, "%lld", &integer) != 1) { ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); - break; + continue; } - ast_str_append(&sql, 0, "%s,", entry->name); + ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name); LENGTHEN_BUF2(24); - ast_str_append(&sql2, 0, "%lld,", integer); + ast_str_append(&sql2, 0, "%s%lld", first ? "" : ",", integer); } break; case SQL_SMALLINT: @@ -554,12 +555,12 @@ static int odbc_log(struct ast_cdr *cdr) short integer = 0; if (sscanf(colptr, "%hd", &integer) != 1) { ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); - break; + continue; } - ast_str_append(&sql, 0, "%s,", entry->name); + ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name); LENGTHEN_BUF2(6); - ast_str_append(&sql2, 0, "%d,", integer); + ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", integer); } break; case SQL_TINYINT: @@ -567,12 +568,12 @@ static int odbc_log(struct ast_cdr *cdr) char integer = 0; if (sscanf(colptr, "%hhd", &integer) != 1) { ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); - break; + continue; } - ast_str_append(&sql, 0, "%s,", entry->name); + ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name); LENGTHEN_BUF2(4); - ast_str_append(&sql2, 0, "%d,", integer); + ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", integer); } break; case SQL_BIT: @@ -580,14 +581,14 @@ static int odbc_log(struct ast_cdr *cdr) char integer = 0; if (sscanf(colptr, "%hhd", &integer) != 1) { ast_log(LOG_WARNING, "CDR variable %s is not an integer.\n", entry->name); - break; + continue; } if (integer != 0) integer = 1; - ast_str_append(&sql, 0, "%s,", entry->name); + ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name); LENGTHEN_BUF2(2); - ast_str_append(&sql2, 0, "%d,", integer); + ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", integer); } break; case SQL_NUMERIC: @@ -596,12 +597,12 @@ static int odbc_log(struct ast_cdr *cdr) double number = 0.0; if (sscanf(colptr, "%lf", &number) != 1) { ast_log(LOG_WARNING, "CDR variable %s is not an numeric type.\n", entry->name); - break; + continue; } - ast_str_append(&sql, 0, "%s,", entry->name); + ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name); LENGTHEN_BUF2(entry->decimals); - ast_str_append(&sql2, 0, "%*.*lf,", entry->decimals, entry->radix, number); + ast_str_append(&sql2, 0, "%s%*.*lf", first ? "" : ",", entry->decimals, entry->radix, number); } break; case SQL_FLOAT: @@ -611,35 +612,37 @@ static int odbc_log(struct ast_cdr *cdr) double number = 0.0; if (sscanf(colptr, "%lf", &number) != 1) { ast_log(LOG_WARNING, "CDR variable %s is not an numeric type.\n", entry->name); - break; + continue; } - ast_str_append(&sql, 0, "%s,", entry->name); + ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name); LENGTHEN_BUF2(entry->decimals); - ast_str_append(&sql2, 0, "%lf,", number); + ast_str_append(&sql2, 0, "%s%lf", first ? "" : ",", number); } break; default: ast_log(LOG_WARNING, "Column type %d (field '%s:%s:%s') is unsupported at this time.\n", entry->type, tableptr->connection, tableptr->table, entry->name); + continue; } + first = 0; } } /* Concatenate the two constructed buffers */ - LENGTHEN_BUF1(sql2->used); - sql->str[sql->used - 1] = ')'; - sql2->str[sql2->used - 1] = ')'; - ast_str_append(&sql, 0, "%s", sql2->str); + LENGTHEN_BUF1(ast_str_strlen(sql2)); + ast_str_append(&sql, 0, ")"); + ast_str_append(&sql2, 0, ")"); + ast_str_append(&sql, 0, "%s", ast_str_buffer(sql2)); - ast_verb(11, "[%s]\n", sql->str); + ast_verb(11, "[%s]\n", ast_str_buffer(sql)); - stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, sql->str); + stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, ast_str_buffer(sql)); if (stmt) { SQLRowCount(stmt, &rows); SQLFreeHandle(SQL_HANDLE_STMT, stmt); } if (rows == 0) { - ast_log(LOG_WARNING, "cdr_adaptive_odbc: Insert failed on '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, sql->str); + ast_log(LOG_WARNING, "cdr_adaptive_odbc: Insert failed on '%s:%s'. CDR failed: %s\n", tableptr->connection, tableptr->table, ast_str_buffer(sql)); } early_release: ast_odbc_release_obj(obj); @@ -647,11 +650,11 @@ early_release: AST_RWLIST_UNLOCK(&odbc_tables); /* Next time, just allocate buffers that are that big to start with. */ - if (sql->used > maxsize) { - maxsize = sql->used; + if (ast_str_strlen(sql) > maxsize) { + maxsize = ast_str_strlen(sql); } - if (sql2->used > maxsize2) { - maxsize2 = sql2->used; + if (ast_str_strlen(sql2) > maxsize2) { + maxsize2 = ast_str_strlen(sql2); } ast_free(sql); diff --git a/cdr/cdr_manager.c b/cdr/cdr_manager.c index fea808dc6..8a4a43e1f 100644 --- a/cdr/cdr_manager.c +++ b/cdr/cdr_manager.c @@ -95,7 +95,7 @@ static int load_config(int reload) v = ast_variable_browse(cfg, cat); while (v) { if (customfields && !ast_strlen_zero(v->name) && !ast_strlen_zero(v->value)) { - if( (customfields->used + strlen(v->value) + strlen(v->name) + 14) < customfields->len) { + if ((ast_str_strlen(customfields) + strlen(v->value) + strlen(v->name) + 14) < ast_str_size(customfields)) { ast_str_append(&customfields, -1, "%s: ${CDR(%s)}\r\n", v->value, v->name); ast_log(LOG_NOTICE, "Added mapping %s: ${CDR(%s)}\n", v->value, v->name); } else { @@ -145,10 +145,10 @@ static int manager_log(struct ast_cdr *cdr) buf[0] = 0; /* Custom fields handling */ - if (customfields != NULL && customfields->used > 0) { + if (customfields != NULL && ast_str_strlen(customfields)) { memset(&dummy, 0, sizeof(dummy)); dummy.cdr = cdr; - pbx_substitute_variables_helper(&dummy, customfields->str, buf, sizeof(buf) - 1); + pbx_substitute_variables_helper(&dummy, ast_str_buffer(customfields), buf, sizeof(buf) - 1); } manager_event(EVENT_FLAG_CDR, "Cdr", diff --git a/cdr/cdr_pgsql.c b/cdr/cdr_pgsql.c index eddc8187d..34ba9dd0c 100644 --- a/cdr/cdr_pgsql.c +++ b/cdr/cdr_pgsql.c @@ -73,31 +73,31 @@ struct columns { static AST_RWLIST_HEAD_STATIC(psql_columns, columns); -#define LENGTHEN_BUF1(size) \ - do { \ - /* Lengthen buffer, if necessary */ \ - if (sql->used + size + 1 > sql->len) { \ - if (ast_str_make_space(&sql, ((sql->len + size + 1) / 512 + 1) * 512) != 0) { \ +#define LENGTHEN_BUF1(size) \ + do { \ + /* Lengthen buffer, if necessary */ \ + if (ast_str_strlen(sql) + size + 1 > ast_str_size(sql)) { \ + if (ast_str_make_space(&sql, ((ast_str_size(sql) + size + 3) / 512 + 1) * 512) != 0) { \ ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CDR failed.\n"); \ - ast_free(sql); \ - ast_free(sql2); \ - AST_RWLIST_UNLOCK(&psql_columns); \ - return -1; \ - } \ - } \ + ast_free(sql); \ + ast_free(sql2); \ + AST_RWLIST_UNLOCK(&psql_columns); \ + return -1; \ + } \ + } \ } while (0) -#define LENGTHEN_BUF2(size) \ - do { \ - if (sql2->used + size + 1 > sql2->len) { \ - if (ast_str_make_space(&sql2, ((sql2->len + size + 3) / 512 + 1) * 512) != 0) { \ +#define LENGTHEN_BUF2(size) \ + do { \ + if (ast_str_strlen(sql2) + size + 1 > ast_str_size(sql2)) { \ + if (ast_str_make_space(&sql2, ((ast_str_size(sql2) + size + 3) / 512 + 1) * 512) != 0) { \ ast_log(LOG_ERROR, "Unable to allocate sufficient memory. Insert CDR failed.\n"); \ - ast_free(sql); \ - ast_free(sql2); \ - AST_RWLIST_UNLOCK(&psql_columns); \ - return -1; \ - } \ - } \ + ast_free(sql); \ + ast_free(sql2); \ + AST_RWLIST_UNLOCK(&psql_columns); \ + return -1; \ + } \ + } \ } while (0) static int pgsql_log(struct ast_cdr *cdr) @@ -125,7 +125,8 @@ static int pgsql_log(struct ast_cdr *cdr) struct columns *cur; struct ast_str *sql = ast_str_create(maxsize), *sql2 = ast_str_create(maxsize2); char buf[257], escapebuf[513], *value; - + int first = 1; + if (!sql || !sql2) { if (sql) { ast_free(sql); @@ -150,85 +151,86 @@ static int pgsql_log(struct ast_cdr *cdr) if (cur->notnull && !cur->hasdefault) { /* Field is NOT NULL (but no default), must include it anyway */ LENGTHEN_BUF1(strlen(cur->name) + 2); - ast_str_append(&sql, 0, "\"%s\",", cur->name); + ast_str_append(&sql, 0, "%s\"%s\"", first ? "" : ",", cur->name); LENGTHEN_BUF2(3); - ast_str_append(&sql2, 0, "'',"); + ast_str_append(&sql2, 0, "%s''", first ? "" : ","); + first = 0; } continue; } LENGTHEN_BUF1(strlen(cur->name) + 2); - ast_str_append(&sql, 0, "\"%s\",", cur->name); + ast_str_append(&sql, 0, "%s\"%s\"", first ? "" : ",", cur->name); if (strcmp(cur->name, "start") == 0 || strcmp(cur->name, "calldate") == 0) { if (strncmp(cur->type, "int", 3) == 0) { - LENGTHEN_BUF2(12); - ast_str_append(&sql2, 0, "%ld", cdr->start.tv_sec); + LENGTHEN_BUF2(13); + ast_str_append(&sql2, 0, "%s%ld", first ? "" : ",", cdr->start.tv_sec); } else if (strncmp(cur->type, "float", 5) == 0) { - LENGTHEN_BUF2(30); - ast_str_append(&sql2, 0, "%f", (double)cdr->start.tv_sec + (double)cdr->start.tv_usec / 1000000.0); + LENGTHEN_BUF2(31); + ast_str_append(&sql2, 0, "%s%f", first ? "" : ",", (double)cdr->start.tv_sec + (double)cdr->start.tv_usec / 1000000.0); } else { /* char, hopefully */ - LENGTHEN_BUF2(30); + LENGTHEN_BUF2(31); ast_localtime(&cdr->start, &tm, NULL); ast_strftime(buf, sizeof(buf), DATE_FORMAT, &tm); - ast_str_append(&sql2, 0, "%s", buf); + ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", buf); } } else if (strcmp(cur->name, "answer") == 0) { if (strncmp(cur->type, "int", 3) == 0) { - LENGTHEN_BUF2(12); - ast_str_append(&sql2, 0, "%ld", cdr->answer.tv_sec); + LENGTHEN_BUF2(13); + ast_str_append(&sql2, 0, "%s%ld", first ? "" : ",", cdr->answer.tv_sec); } else if (strncmp(cur->type, "float", 5) == 0) { - LENGTHEN_BUF2(30); - ast_str_append(&sql2, 0, "%f", (double)cdr->answer.tv_sec + (double)cdr->answer.tv_usec / 1000000.0); + LENGTHEN_BUF2(31); + ast_str_append(&sql2, 0, "%s%f", first ? "" : ",", (double)cdr->answer.tv_sec + (double)cdr->answer.tv_usec / 1000000.0); } else { /* char, hopefully */ - LENGTHEN_BUF2(30); + LENGTHEN_BUF2(31); ast_localtime(&cdr->start, &tm, NULL); ast_strftime(buf, sizeof(buf), DATE_FORMAT, &tm); - ast_str_append(&sql2, 0, "%s", buf); + ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", buf); } } else if (strcmp(cur->name, "end") == 0) { if (strncmp(cur->type, "int", 3) == 0) { - LENGTHEN_BUF2(12); - ast_str_append(&sql2, 0, "%ld", cdr->end.tv_sec); + LENGTHEN_BUF2(13); + ast_str_append(&sql2, 0, "%s%ld", first ? "" : ",", cdr->end.tv_sec); } else if (strncmp(cur->type, "float", 5) == 0) { - LENGTHEN_BUF2(30); - ast_str_append(&sql2, 0, "%f", (double)cdr->end.tv_sec + (double)cdr->end.tv_usec / 1000000.0); + LENGTHEN_BUF2(31); + ast_str_append(&sql2, 0, "%s%f", first ? "" : ",", (double)cdr->end.tv_sec + (double)cdr->end.tv_usec / 1000000.0); } else { /* char, hopefully */ - LENGTHEN_BUF2(30); + LENGTHEN_BUF2(31); ast_localtime(&cdr->end, &tm, NULL); ast_strftime(buf, sizeof(buf), DATE_FORMAT, &tm); - ast_str_append(&sql2, 0, "%s", buf); + ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", buf); } } else if (strcmp(cur->name, "duration") == 0 || strcmp(cur->name, "billsec") == 0) { if (cur->type[0] == 'i') { /* Get integer, no need to escape anything */ ast_cdr_getvar(cdr, cur->name, &value, buf, sizeof(buf), 0, 0); - LENGTHEN_BUF2(12); - ast_str_append(&sql2, 0, "%s", value); + LENGTHEN_BUF2(13); + ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", value); } else if (strncmp(cur->type, "float", 5) == 0) { struct timeval *when = cur->name[0] == 'd' ? &cdr->start : &cdr->answer; - LENGTHEN_BUF2(30); - ast_str_append(&sql2, 0, "%f", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0); + LENGTHEN_BUF2(31); + ast_str_append(&sql2, 0, "%s%f", first ? "" : ",", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0); } else { /* Char field, probably */ struct timeval *when = cur->name[0] == 'd' ? &cdr->start : &cdr->answer; - LENGTHEN_BUF2(30); - ast_str_append(&sql2, 0, "'%f'", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0); + LENGTHEN_BUF2(31); + ast_str_append(&sql2, 0, "%s'%f'", first ? "" : ",", (double)cdr->end.tv_sec - when->tv_sec + cdr->end.tv_usec / 1000000.0 - when->tv_usec / 1000000.0); } } else if (strcmp(cur->name, "disposition") == 0 || strcmp(cur->name, "amaflags") == 0) { if (strncmp(cur->type, "int", 3) == 0) { /* Integer, no need to escape anything */ ast_cdr_getvar(cdr, cur->name, &value, buf, sizeof(buf), 0, 1); - LENGTHEN_BUF2(12); - ast_str_append(&sql2, 0, "%s", value); + LENGTHEN_BUF2(13); + ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", value); } else { /* Although this is a char field, there are no special characters in the values for these fields */ ast_cdr_getvar(cdr, cur->name, &value, buf, sizeof(buf), 0, 0); - LENGTHEN_BUF2(30); - ast_str_append(&sql2, 0, "'%s'", value); + LENGTHEN_BUF2(31); + ast_str_append(&sql2, 0, "%s'%s'", first ? "" : ",", value); } } else { /* Arbitrary field, could be anything */ @@ -236,20 +238,20 @@ static int pgsql_log(struct ast_cdr *cdr) if (strncmp(cur->type, "int", 3) == 0) { long long whatever; if (value && sscanf(value, "%lld", &whatever) == 1) { - LENGTHEN_BUF2(25); - ast_str_append(&sql2, 0, "%lld", whatever); + LENGTHEN_BUF2(26); + ast_str_append(&sql2, 0, "%s%lld", first ? "" : ",", whatever); } else { - LENGTHEN_BUF2(1); - ast_str_append(&sql2, 0, "0"); + LENGTHEN_BUF2(2); + ast_str_append(&sql2, 0, "%s0", first ? "" : ","); } } else if (strncmp(cur->type, "float", 5) == 0) { long double whatever; if (value && sscanf(value, "%Lf", &whatever) == 1) { - LENGTHEN_BUF2(50); - ast_str_append(&sql2, 0, "%30Lf", whatever); + LENGTHEN_BUF2(51); + ast_str_append(&sql2, 0, "%s%30Lf", first ? "" : ",", whatever); } else { - LENGTHEN_BUF2(1); - ast_str_append(&sql2, 0, "0"); + LENGTHEN_BUF2(2); + ast_str_append(&sql2, 0, "%s0", first ? "" : ","); } /* XXX Might want to handle dates, times, and other misc fields here XXX */ } else { @@ -257,19 +259,16 @@ static int pgsql_log(struct ast_cdr *cdr) PQescapeStringConn(conn, escapebuf, value, strlen(value), NULL); else escapebuf[0] = '\0'; - LENGTHEN_BUF2(strlen(escapebuf) + 2); - ast_str_append(&sql2, 0, "'%s'", escapebuf); + LENGTHEN_BUF2(strlen(escapebuf) + 3); + ast_str_append(&sql2, 0, "%s'%s'", first ? "" : ",", escapebuf); } } - LENGTHEN_BUF2(1); - ast_str_append(&sql2, 0, ","); + first = 0; } AST_RWLIST_UNLOCK(&psql_columns); - LENGTHEN_BUF1(sql2->len); - sql->str[sql->used - 1] = ')'; - sql2->str[sql2->used - 1] = ')'; - ast_str_append(&sql, 0, "%s", sql2->str); - ast_verb(11, "[%s]\n", sql->str); + LENGTHEN_BUF1(ast_str_strlen(sql2) + 2); + ast_str_append(&sql, 0, ")%s)", ast_str_buffer(sql2)); + ast_verb(11, "[%s]\n", ast_str_buffer(sql)); ast_debug(2, "inserting a CDR record.\n"); @@ -297,7 +296,7 @@ static int pgsql_log(struct ast_cdr *cdr) return -1; } } - result = PQexec(conn, sql->str); + result = PQexec(conn, ast_str_buffer(sql)); if (PQresultStatus(result) != PGRES_COMMAND_OK) { pgerror = PQresultErrorMessage(result); ast_log(LOG_ERROR, "Failed to insert call detail record into database!\n"); @@ -308,7 +307,7 @@ static int pgsql_log(struct ast_cdr *cdr) ast_log(LOG_ERROR, "Connection reestablished.\n"); connected = 1; PQclear(result); - result = PQexec(conn, sql->str); + result = PQexec(conn, ast_str_buffer(sql)); if (PQresultStatus(result) != PGRES_COMMAND_OK) { pgerror = PQresultErrorMessage(result); ast_log(LOG_ERROR, "HARD ERROR! Attempted reconnection failed. DROPPING CALL RECORD!\n"); diff --git a/cdr/cdr_sqlite3_custom.c b/cdr/cdr_sqlite3_custom.c index 8541d0888..3bac49550 100644 --- a/cdr/cdr_sqlite3_custom.c +++ b/cdr/cdr_sqlite3_custom.c @@ -101,13 +101,10 @@ static int load_column_config(const char *tmp) ast_free(save); return -1; } - if (!column_string->used) - ast_str_set(&column_string, 0, "%s", escaped); - else - ast_str_append(&column_string, 0, ",%s", escaped); + ast_str_append(&column_string, 0, "%s%s", ast_str_strlen(column_string) ? "," : "", escaped); sqlite3_free(escaped); } - if (!(columns = ast_strdup(column_string->str))) { + if (!(columns = ast_strdup(ast_str_buffer(column_string)))) { ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table); ast_free(column_string); ast_free(save); @@ -158,17 +155,16 @@ static int load_config(int reload) struct ast_variable *mappingvar; const char *tmp; - if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) { - if (reload) - ast_log(LOG_WARNING, "Failed to reload configuration file.\n"); - else - ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n"); + if ((cfg = ast_config_load(config_file, config_flags)) == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { + ast_log(LOG_WARNING, "Failed to %sload configuration file. %s\n", reload ? "re" : "", reload ? "" : "Module not activated."); return -1; - } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) + } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { return 0; + } - if (reload) + if (reload) { free_config(); + } ast_mutex_lock(&lock); @@ -180,17 +176,15 @@ static int load_config(int reload) } /* Mapping must have a table name */ - tmp = ast_variable_retrieve(cfg, "master", "table"); - if (!ast_strlen_zero(tmp)) + if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "master", "table"))) { ast_copy_string(table, tmp, sizeof(table)); - else { + } else { ast_log(LOG_WARNING, "Table name not specified. Assuming cdr.\n"); strcpy(table, "cdr"); } /* Columns */ - tmp = ast_variable_retrieve(cfg, "master", "columns"); - if (load_column_config(tmp)) { + if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) { ast_mutex_unlock(&lock); ast_config_destroy(cfg); free_config(); @@ -198,8 +192,7 @@ static int load_config(int reload) } /* Values */ - tmp = ast_variable_retrieve(cfg, "master", "values"); - if (load_values_config(tmp)) { + if (load_values_config(ast_variable_retrieve(cfg, "master", "values"))) { ast_mutex_unlock(&lock); ast_config_destroy(cfg); free_config(); @@ -230,8 +223,9 @@ static int free_config(void) columns = NULL; } - while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list))) + while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list))) { ast_free(value); + } ast_mutex_unlock(&lock); @@ -253,16 +247,12 @@ static int sqlite3_log(struct ast_cdr *cdr) struct ast_str *value_string = ast_str_create(1024); dummy.cdr = cdr; AST_LIST_TRAVERSE(&sql_values, value, list) { - memset(subst_buf, 0, sizeof(subst_buf)); pbx_substitute_variables_helper(&dummy, value->expression, subst_buf, sizeof(subst_buf) - 1); escaped = sqlite3_mprintf("%q", subst_buf); - if (!value_string->used) - ast_str_append(&value_string, 0, "'%s'", escaped); - else - ast_str_append(&value_string, 0, ",'%s'", escaped); + ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped); sqlite3_free(escaped); } - sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, value_string->str); + sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string)); ast_debug(1, "About to log: %s\n", sql); ast_free(value_string); } @@ -272,8 +262,9 @@ static int sqlite3_log(struct ast_cdr *cdr) /* XXX This seems awful arbitrary... */ for (count = 0; count < 5; count++) { res = sqlite3_exec(db, sql, NULL, NULL, &error); - if (res != SQLITE_BUSY && res != SQLITE_LOCKED) + if (res != SQLITE_BUSY && res != SQLITE_LOCKED) { break; + } usleep(200); } @@ -282,8 +273,9 @@ static int sqlite3_log(struct ast_cdr *cdr) sqlite3_free(error); } - if (sql) + if (sql) { sqlite3_free(sql); + } ast_mutex_unlock(&lock); @@ -313,8 +305,9 @@ static int load_module(void) free_config(); return AST_MODULE_LOAD_DECLINE; } - } else + } else { return AST_MODULE_LOAD_DECLINE; + } /* is the database there? */ snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR); diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index dff85fd7d..b3a728752 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -6102,12 +6102,12 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb else ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); for (x = 0; x < 3; x++) { - if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6)) + if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6)) break; } y++; } while (x < 3); - tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", chan_name->str); + tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name)); if (!tmp) return NULL; tmp->tech = &dahdi_tech; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index f8391cef0..37ae2ca24 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2031,6 +2031,8 @@ static void temp_pvt_cleanup(void *); /*! \brief A per-thread temporary pvt structure */ AST_THREADSTORAGE_CUSTOM(ts_temp_pvt, temp_pvt_init, temp_pvt_cleanup); +AST_THREADSTORAGE(transmit_state_buffer); +AST_THREADSTORAGE(mailbox_buffer); #ifdef LOW_MEMORY static void ts_ast_rtp_destroy(void *); @@ -2261,7 +2263,7 @@ static int reload_config(enum channelreloadreason reason); static int expire_register(const void *data); static void *do_monitor(void *data); static int restart_monitor(void); -static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer); +static char *peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer); /* static int sip_addrcmp(char *name, struct sockaddr_in *sin); Support for peer matching */ static int sip_refer_allocate(struct sip_pvt *p); static void ast_quiet_chan(struct ast_channel *chan); @@ -2707,7 +2709,7 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi } /* Read in headers one line at a time */ - while (req.len < 4 || strncmp((char *)&req.data->str + req.len - 4, "\r\n\r\n", 4)) { + while (req.len < 4 || strncmp(ast_str_buffer(req.data) + req.len - 4, "\r\n\r\n", 4)) { ast_mutex_lock(&tcptls_session->lock); if (!fgets(buf, sizeof(buf), tcptls_session->f)) { ast_mutex_unlock(&tcptls_session->lock); @@ -2716,8 +2718,8 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi ast_mutex_unlock(&tcptls_session->lock); if (me->stop) goto cleanup; - ast_str_append(&req.data, 0, "%s", buf); - req.len = req.data->used; + ast_str_append(&req.data, -1, "%s", buf); + req.len = ast_str_strlen(req.data); } copy_request(&reqcpy, &req); parse_request(&reqcpy); @@ -2733,8 +2735,8 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi if (me->stop) goto cleanup; cl -= strlen(buf); - ast_str_append(&req.data, 0, "%s", buf); - req.len = req.data->used; + ast_str_append(&req.data, -1, "%s", buf); + req.len = ast_str_strlen(req.data); } } /*! \todo XXX If there's no Content-Length or if the content-length and what @@ -3163,21 +3165,24 @@ static int __sip_xmit(struct sip_pvt *p, struct ast_str *data, int len) int res = 0; const struct sockaddr_in *dst = sip_real_dst(p); - ast_debug(2, "Trying to put '%.10s' onto %s socket destined for %s:%d\n", data->str, get_transport_pvt(p), ast_inet_ntoa(dst->sin_addr), htons(dst->sin_port)); + ast_debug(2, "Trying to put '%.10s' onto %s socket destined for %s:%d\n", ast_str_buffer(data), get_transport_pvt(p), ast_inet_ntoa(dst->sin_addr), htons(dst->sin_port)); - if (sip_prepare_socket(p) < 0) + if (sip_prepare_socket(p) < 0) { return XMIT_ERROR; + } - if (p->socket.tcptls_session) + if (p->socket.tcptls_session) { ast_mutex_lock(&p->socket.tcptls_session->lock); + } - if (p->socket.type & SIP_TRANSPORT_UDP) - res = sendto(p->socket.fd, data->str, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in)); - else { - if (p->socket.tcptls_session->f) - res = ast_tcptls_server_write(p->socket.tcptls_session, data->str, len); - else + if (p->socket.type & SIP_TRANSPORT_UDP) { + res = sendto(p->socket.fd, ast_str_buffer(data), len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in)); + } else { + if (p->socket.tcptls_session->f) { + res = ast_tcptls_server_write(p->socket.tcptls_session, ast_str_buffer(data), len); + } else { ast_debug(2, "No p->socket.tcptls_session->f len=%d\n", len); + } } if (p->socket.tcptls_session) @@ -3193,8 +3198,9 @@ static int __sip_xmit(struct sip_pvt *p, struct ast_str *data, int len) res = XMIT_ERROR; /* Don't bother with trying to transmit again */ } } - if (res != len) + if (res != len) { ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s:%d returned %d: %s\n", data, len, ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), res, strerror(errno)); + } return res; } @@ -3354,10 +3360,10 @@ static int retrans_pkt(const void *data) ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n", pkt->retrans, sip_nat_mode(pkt->owner), ast_inet_ntoa(dst->sin_addr), - ntohs(dst->sin_port), pkt->data->str); + ntohs(dst->sin_port), ast_str_buffer(pkt->data)); } - append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data->str); + append_history(pkt->owner, "ReTx", "%d %s", reschedule, ast_str_buffer(pkt->data)); xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen); sip_pvt_unlock(pkt->owner); if (xmitres == XMIT_ERROR) @@ -3472,7 +3478,7 @@ static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, int seqno, int res ast_free(pkt); return AST_FAILURE; } - ast_str_set(&pkt->data, 0, "%s%s", data->str, "\0"); + ast_str_set(&pkt->data, 0, "%s", ast_str_buffer(data)); pkt->packetlen = len; /* copy other parameters from the caller */ pkt->method = sipmethod; @@ -3674,7 +3680,7 @@ static void __sip_pretend_ack(struct sip_pvt *p) return; } cur = p->packets; - method = (cur->method) ? cur->method : find_sip_method(cur->data->str); + method = (cur->method) ? cur->method : find_sip_method(ast_str_buffer(cur->data)); __sip_ack(p, cur->seqno, cur->is_resp, method); } } @@ -3687,7 +3693,7 @@ static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod) for (cur = p->packets; cur; cur = cur->next) { if (cur->seqno == seqno && cur->is_resp == resp && - (cur->is_resp || method_match(sipmethod, cur->data->str))) { + (cur->is_resp || method_match(sipmethod, ast_str_buffer(cur->data)))) { /* this is our baby */ if (cur->retransid > -1) { if (sipdebug) @@ -3716,7 +3722,7 @@ static void add_blank(struct sip_request *req) if (!req->lines) { /* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */ ast_str_append(&req->data, 0, "\r\n"); - req->len = req->data->used; + req->len = ast_str_strlen(req->data); } } @@ -3732,12 +3738,12 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmitty ast_verbose("\n<--- %sTransmitting (%s) to %s:%d --->\n%s\n<------------>\n", reliable ? "Reliably " : "", sip_nat_mode(p), ast_inet_ntoa(dst->sin_addr), - ntohs(dst->sin_port), req->data->str); + ntohs(dst->sin_port), ast_str_buffer(req->data)); } if (p->do_history) { struct sip_request tmp = { .rlPart1 = NULL, }; parse_copy(&tmp, req); - append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), + append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", ast_str_buffer(tmp.data), get_header(&tmp, "CSeq"), (tmp.method == SIP_RESPONSE || tmp.method == SIP_UNKNOWN) ? tmp.rlPart2 : sip_methods[tmp.method].text); ast_free(tmp.data); } @@ -3765,15 +3771,16 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp add_blank(req); if (sip_debug_test_pvt(p)) { - if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)) - ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), req->data->str); - else - ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), req->data->str); + if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)) { + ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), ast_str_buffer(req->data)); + } else { + ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), ast_str_buffer(req->data)); + } } if (p->do_history) { struct sip_request tmp = { .rlPart1 = NULL, }; parse_copy(&tmp, req); - append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), sip_methods[tmp.method].text); + append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", ast_str_buffer(tmp.data), get_header(&tmp, "CSeq"), sip_methods[tmp.method].text); ast_free(tmp.data); } res = (reliable) ? @@ -5504,7 +5511,7 @@ static int sip_hangup(struct ast_channel *ast) sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); /* Start the process if it's not already started */ - if (!p->alreadygone && p->initreq.data && !ast_strlen_zero(p->initreq.data->str)) { + if (!p->alreadygone && p->initreq.data && ast_str_strlen(p->initreq.data)) { if (needcancel) { /* Outgoing call, not up */ if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { /* stop retransmitting an INVITE that has not received a response */ @@ -7017,7 +7024,7 @@ static int lws2sws(char *msgbuf, int len) */ static int parse_request(struct sip_request *req) { - char *c = req->data->str, **dst = req->header; + char *c = ast_str_buffer(req->data), **dst = req->header; int i = 0, lim = SIP_MAX_HEADERS - 1; unsigned int skipping_headers = 0; @@ -7915,7 +7922,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action /* Activate a re-invite */ ast_queue_frame(p->owner, &ast_null_frame); /* Queue Manager Unhold event */ - append_history(p, "Unhold", "%s", req->data->str); + append_history(p, "Unhold", "%s", ast_str_buffer(req->data)); if (sip_cfg.callevents) manager_event(EVENT_FLAG_CALL, "Hold", "Status: Off\r\n" @@ -7937,7 +7944,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action /* Activate a re-invite */ ast_queue_frame(p->owner, &ast_null_frame); /* Queue Manager Hold event */ - append_history(p, "Hold", "%s", req->data->str); + append_history(p, "Hold", "%s", ast_str_buffer(req->data)); if (sip_cfg.callevents && !ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { manager_event(EVENT_FLAG_CALL, "Hold", "Status: On\r\n" @@ -7980,8 +7987,8 @@ static int add_header(struct sip_request *req, const char *var, const char *valu return -1; } - ast_str_append(&req->data, 0, "%s: %s\r\n", var, value); - req->header[req->headers] = req->data->str + req->len; + ast_str_append(&req->data, -1, "%s: %s\r\n", var, value); + req->header[req->headers] = ast_str_buffer(req->data) + req->len; if (sip_cfg.compactheaders) var = find_alias(var, var); @@ -8007,16 +8014,12 @@ static int add_line(struct sip_request *req, const char *line) ast_log(LOG_WARNING, "Out of SIP line space\n"); return -1; } - if (!req->lines) + if (!req->lines) { /* Add extra empty return */ - req->len += ast_str_append(&req->data, 0, "\r\n"); - if (req->len >= sizeof(req->data->str) - 4) { - ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); - return -1; + req->len += ast_str_append(&req->data, -1, "\r\n"); } - req->line[req->lines] = req->data->str + req->len; - ast_str_append(&req->data, 0, "%s", line); - req->len += strlen(req->line[req->lines]); + req->line[req->lines] = ast_str_buffer(req->data) + ast_str_strlen(req->data); + req->len += ast_str_append(&req->data, -1, "%s", line); req->lines++; return 0; } @@ -8080,7 +8083,7 @@ static int copy_via_headers(struct sip_pvt *p, struct sip_request *req, const st /* Find ;rport; (empty request) */ rport = strstr(leftmost, ";rport"); - if (rport && *(rport+6) == '=') + if (rport && *(rport + 6) == '=') rport = NULL; /* We already have a parameter to rport */ /* Check rport if NAT=yes or NAT=rfc3581 (which is the default setting) */ @@ -8232,9 +8235,9 @@ static int init_resp(struct sip_request *resp, const char *msg) resp->method = SIP_RESPONSE; if (!(resp->data = ast_str_create(SIP_MIN_PACKET))) return -1; - resp->header[0] = resp->data->str; - ast_str_set(&resp->data, 0, "SIP/2.0 %s\r\n", msg); - resp->len = strlen(resp->header[0]); + ast_str_set(&resp->data, -1, "SIP/2.0 %s\r\n", msg); + resp->header[0] = ast_str_buffer(resp->data); + resp->len = ast_str_strlen(resp->data); resp->headers++; return 0; } @@ -8247,9 +8250,9 @@ static int init_req(struct sip_request *req, int sipmethod, const char *recip) if (!(req->data = ast_str_create(SIP_MIN_PACKET))) return -1; req->method = sipmethod; - req->header[0] = req->data->str; - ast_str_set(&req->data, 0, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip); - req->len = strlen(req->header[0]); + ast_str_set(&req->data, -1, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip); + req->header[0] = ast_str_buffer(req->data); + req->len = ast_str_strlen(req->data); req->headers++; return 0; } @@ -8896,11 +8899,11 @@ static int add_t38_sdp(struct sip_request *resp, struct sip_pvt *p) ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%d\r\n", x); if (p->t38.jointcapability != T38FAX_UDP_EC_NONE) ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:%s\r\n", (p->t38.jointcapability & T38FAX_UDP_EC_REDUNDANCY) ? "t38UDPRedundancy" : "t38UDPFEC"); - len = m_modem->used + a_modem->used; + len = ast_str_strlen(m_modem) + ast_str_strlen(a_modem); add_header(resp, "Content-Type", "application/sdp"); add_header_contentLength(resp, len); - add_line(resp, m_modem->str); - add_line(resp, a_modem->str); + add_line(resp, ast_str_buffer(m_modem)); + add_line(resp, ast_str_buffer(a_modem)); /* Update lastrtprx when we send our SDP */ p->lastrtprx = p->lastrtptx = time(NULL); @@ -8938,10 +8941,12 @@ static void get_our_media_address(struct sip_pvt *p, int needvideo, { /* First, get our address */ ast_rtp_get_us(p->rtp, sin); - if (p->vrtp) + if (p->vrtp) { ast_rtp_get_us(p->vrtp, vsin); - if (p->trtp) + } + if (p->trtp) { ast_rtp_get_us(p->trtp, tsin); + } /* Now, try to figure out where we want them to send data */ /* Is this a re-invite to move the media out, then use the original offer from caller */ @@ -8991,12 +8996,12 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int struct sockaddr_in tdest = { 0, }; /* SDP fields */ - char *version = "v=0\r\n"; /* Protocol version */ - char subject[256]; /* Subject of the session */ - char owner[256]; /* Session owner/creator */ - char connection[256]; /* Connection data */ - char *session_time = "t=0 0\r\n"; /* Time the session is active */ - char bandwidth[256] = ""; /* Max bitrate */ + char *version = "v=0\r\n"; /* Protocol version */ + char subject[256]; /* Subject of the session */ + char owner[256]; /* Session owner/creator */ + char connection[256]; /* Connection data */ + char *session_time = "t=0 0\r\n"; /* Time the session is active */ + char bandwidth[256] = ""; /* Max bitrate */ char *hold; struct ast_str *m_audio = ast_str_alloca(256); /* Media declaration line for audio */ struct ast_str *m_video = ast_str_alloca(256); /* Media declaration line for video */ @@ -9030,11 +9035,12 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int /* Set RTP Session ID and version */ if (!p->sessionid) { - p->sessionid = (int)ast_random(); + p->sessionid = (int) ast_random(); p->sessionversion = p->sessionid; } else { - if (oldsdp == FALSE) + if (oldsdp == FALSE) { p->sessionversion++; + } } capability = p->jointcapability; @@ -9052,23 +9058,26 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int #endif /* Check if we need audio */ - if (capability & AST_FORMAT_AUDIO_MASK) + if (capability & AST_FORMAT_AUDIO_MASK) { needaudio = TRUE; + } /* Check if we need video in this call */ if ((capability & AST_FORMAT_VIDEO_MASK) && !p->novideo) { if (p->vrtp) { needvideo = TRUE; ast_debug(2, "This call needs video offers!\n"); - } else + } else { ast_debug(2, "This call needs video offers, but there's no video support enabled!\n"); + } } /* Get our media addresses */ get_our_media_address(p, needvideo, &sin, &vsin, &tsin, &dest, &vdest); - if (debug) - ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port)); + if (debug) { + ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port)); + } /* Ok, we need video. Let's add what we need for video and set codecs. Video is handled differently than audio since we can not transcode. */ @@ -9076,30 +9085,36 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int ast_str_append(&m_video, 0, "m=video %d RTP/AVP", ntohs(vdest.sin_port)); /* Build max bitrate string */ - if (p->maxcallbitrate) + if (p->maxcallbitrate) { snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate); - if (debug) - ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vsin.sin_port)); + } + if (debug) { + ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vsin.sin_port)); + } } /* Check if we need text in this call */ if((capability & AST_FORMAT_TEXT_MASK) && !p->notext) { - if (sipdebug_text) + if (sipdebug_text) { ast_verbose("We think we can do text\n"); + } if (p->trtp) { - if (sipdebug_text) + if (sipdebug_text) { ast_verbose("And we have a text rtp object\n"); + } needtext = TRUE; ast_debug(2, "This call needs text offers! \n"); - } else + } else { ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n"); + } } /* Ok, we need text. Let's add what we need for text and set codecs. Text is handled differently than audio since we can not transcode. */ if (needtext) { - if (sipdebug_text) + if (sipdebug_text) { ast_verbose("Lets set up the text sdp\n"); + } /* Determine text destination */ if (p->tredirip.sin_addr.s_addr) { tdest.sin_addr = p->tredirip.sin_addr; @@ -9110,9 +9125,9 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int } ast_str_append(&m_text, 0, "m=text %d RTP/AVP", ntohs(tdest.sin_port)); - if (debug) /* XXX should I use tdest below ? */ + if (debug) { /* XXX should I use tdest below ? */ ast_verbose("Text is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(tsin.sin_port)); - + } } /* Start building generic SDP headers */ @@ -9124,12 +9139,13 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); ast_str_append(&m_audio, 0, "m=audio %d RTP/AVP", ntohs(dest.sin_port)); - if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR) + if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR) { hold = "a=recvonly\r\n"; - else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE) + } else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE) { hold = "a=inactive\r\n"; - else + } else { hold = "a=sendrecv\r\n"; + } /* Now, start adding audio codecs. These are added in this order: - First what was requested by the calling channel @@ -9153,14 +9169,15 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int for (x = 0; x < 32; x++) { int codec; - if (!(codec = ast_codec_pref_index(&p->prefs, x))) - break; - - if (!(capability & codec)) + if (!(codec = ast_codec_pref_index(&p->prefs, x))) { + break; + } + if (!(capability & codec)) { continue; - - if (alreadysent & codec) + } + if (alreadysent & codec) { continue; + } add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec), &m_audio, &a_audio, @@ -9170,67 +9187,85 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int /* Now send any other common audio and video codecs, and non-codec formats: */ for (x = 1; x <= (needtext ? AST_FORMAT_TEXT_MASK : (needvideo ? AST_FORMAT_VIDEO_MASK : AST_FORMAT_AUDIO_MASK)); x <<= 1) { - if (!(capability & x)) /* Codec not requested */ + if (!(capability & x)) { /* Codec not requested */ continue; + } - if (alreadysent & x) /* Already added to SDP */ + if (alreadysent & x) { /* Already added to SDP */ continue; + } - if (x & AST_FORMAT_AUDIO_MASK) + if (x & AST_FORMAT_AUDIO_MASK) { add_codec_to_sdp(p, x, SDP_SAMPLE_RATE(x), &m_audio, &a_audio, debug, &min_audio_packet_size); - else if (x & AST_FORMAT_VIDEO_MASK) + } else if (x & AST_FORMAT_VIDEO_MASK) { add_vcodec_to_sdp(p, x, 90000, &m_video, &a_video, debug, &min_video_packet_size); - else if (x & AST_FORMAT_TEXT_MASK) + } else if (x & AST_FORMAT_TEXT_MASK) { add_tcodec_to_sdp(p, x, 1000, &m_text, &a_text, debug, &min_text_packet_size); + } } /* Now add DTMF RFC2833 telephony-event as a codec */ for (x = 1; x <= AST_RTP_MAX; x <<= 1) { - if (!(p->jointnoncodeccapability & x)) + if (!(p->jointnoncodeccapability & x)) { continue; + } add_noncodec_to_sdp(p, x, 8000, &m_audio, &a_audio, debug); } ast_debug(3, "-- Done with adding codecs to SDP\n"); - if (!p->owner || !ast_internal_timing_enabled(p->owner)) + if (!p->owner || !ast_internal_timing_enabled(p->owner)) { ast_str_append(&a_audio, 0, "a=silenceSupp:off - - - -\r\n"); + } - if (min_audio_packet_size) + if (min_audio_packet_size) { ast_str_append(&a_audio, 0, "a=ptime:%d\r\n", min_audio_packet_size); + } /* XXX don't think you can have ptime for video */ - if (min_video_packet_size) + if (min_video_packet_size) { ast_str_append(&a_video, 0, "a=ptime:%d\r\n", min_video_packet_size); + } /* XXX don't think you can have ptime for text */ - if (min_text_packet_size) + if (min_text_packet_size) { ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size); + } - if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 || - m_text->len - m_text->used < 2 || a_text->len - a_text->used < 2 || - a_audio->len - a_audio->used < 2 || a_video->len - a_video->used < 2) + if ( ast_str_size(m_audio) - ast_str_strlen(m_audio) < 2 || + ast_str_size(m_video) - ast_str_strlen(m_video) < 2 || + ast_str_size(m_text) - ast_str_strlen(m_text) < 2 || + ast_str_size(a_text) - ast_str_strlen(a_text) < 2 || + ast_str_size(a_audio) - ast_str_strlen(a_audio) < 2 || + ast_str_size(a_video) - ast_str_strlen(a_video) < 2) { ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n"); + } - if (needaudio) + if (needaudio) { ast_str_append(&m_audio, 0, "\r\n"); - if (needvideo) + } + if (needvideo) { ast_str_append(&m_video, 0, "\r\n"); - if (needtext) + } + if (needtext) { ast_str_append(&m_text, 0, "\r\n"); + } len = strlen(version) + strlen(subject) + strlen(owner) + strlen(connection) + strlen(session_time); - if (needaudio) - len += m_audio->used + a_audio->used + strlen(hold); - if (needvideo) /* only if video response is appropriate */ - len += m_video->used + a_video->used + strlen(bandwidth) + strlen(hold); - if (needtext) /* only if text response is appropriate */ - len += m_text->used + a_text->used + strlen(hold); + if (needaudio) { + len += ast_str_strlen(m_audio) + ast_str_strlen(a_audio) + strlen(hold); + } + if (needvideo) { /* only if video response is appropriate */ + len += ast_str_strlen(m_video) + ast_str_strlen(a_video) + strlen(bandwidth) + strlen(hold); + } + if (needtext) { /* only if text response is appropriate */ + len += ast_str_strlen(m_text) + ast_str_strlen(a_text) + strlen(hold); + } add_header(resp, "Content-Type", "application/sdp"); add_header_contentLength(resp, len); @@ -9238,22 +9273,23 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int add_line(resp, owner); add_line(resp, subject); add_line(resp, connection); - if (needvideo) /* only if video response is appropriate */ + if (needvideo) { /* only if video response is appropriate */ add_line(resp, bandwidth); + } add_line(resp, session_time); if (needaudio) { - add_line(resp, m_audio->str); - add_line(resp, a_audio->str); + add_line(resp, ast_str_buffer(m_audio)); + add_line(resp, ast_str_buffer(a_audio)); add_line(resp, hold); } if (needvideo) { /* only if video response is appropriate */ - add_line(resp, m_video->str); - add_line(resp, a_video->str); + add_line(resp, ast_str_buffer(m_video)); + add_line(resp, ast_str_buffer(a_video)); add_line(resp, hold); /* Repeat hold for the video stream */ } if (needtext) { /* only if text response is appropriate */ - add_line(resp, m_text->str); - add_line(resp, a_text->str); + add_line(resp, ast_str_buffer(m_text)); + add_line(resp, ast_str_buffer(a_text)); add_line(resp, hold); /* Repeat hold for the text stream */ } @@ -9303,14 +9339,13 @@ static void copy_request(struct sip_request *dst, const struct sip_request *src) * the place and so a memcpy is the only way to accurately copy the string */ - if (!dst->data && !(dst->data = ast_str_create(src->data->used + 1))) + if (!dst->data && !(dst->data = ast_str_create(ast_str_strlen(src->data) + 1))) return; - else if (dst->data->len < src->data->used + 1) - ast_str_make_space(&dst->data, src->data->used + 1); - - memcpy(dst->data->str, src->data->str, src->data->used + 1); - dst->data->used = src->data->used; - offset = ((void *)dst->data->str) - ((void *)src->data->str); + else if (ast_str_size(dst->data) < ast_str_strlen(src->data) + 1) + ast_str_make_space(&dst->data, ast_str_strlen(src->data) + 1); + + ast_str_set(&dst->data, 0, "%s", ast_str_buffer(src->data)); + offset = ((void *)ast_str_buffer(dst->data)) - ((void *)ast_str_buffer(src->data)); /* Now fix pointer arithmetic */ for (x = 0; x < src->headers; x++) dst->header[x] += offset; @@ -9659,7 +9694,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho /* This is the request URI, which is the next hop of the call which may or may not be the destination of the call */ - ast_string_field_set(p, uri, invite->str); + ast_string_field_set(p, uri, ast_str_buffer(invite)); if (!ast_strlen_zero(p->todnid)) { /*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */ @@ -9942,8 +9977,8 @@ static int find_calling_channel(struct ast_channel *c, void *data) { /*! \brief Used in the SUBSCRIBE notification subsystem (RFC3265) */ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout) { - struct ast_str *tmp = ast_str_alloca(4000); - char from[256], to[256]; + struct ast_str *tmp = ast_str_thread_get(&transmit_state_buffer, 4000); + char from[256] = "", to[256] = ""; char *c, *mfrom, *mto; struct sip_request req; char hint[AST_MAX_EXTENSION]; @@ -9953,9 +9988,6 @@ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int tim char *pidfstate = "--"; char *pidfnote= "Ready"; - memset(from, 0, sizeof(from)); - memset(to, 0, sizeof(to)); - switch (state) { case (AST_EXTENSION_RINGING | AST_EXTENSION_INUSE): statestring = (global_notifyringing) ? "early" : "confirmed"; @@ -10145,8 +10177,8 @@ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int tim break; } - add_header_contentLength(&req, tmp->used); - add_line(&req, tmp->str); + add_header_contentLength(&req, ast_str_strlen(tmp)); + add_line(&req, ast_str_buffer(tmp)); p->pendinginvite = p->ocseq; /* Remember that we have a pending NOTIFY in order not to confuse the NOTIFY subsystem */ @@ -10184,8 +10216,8 @@ static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs, add_header(&req, "Subscription-State", "terminated;reason=timeout"); } - add_header_contentLength(&req, out->used); - add_line(&req, out->str); + add_header_contentLength(&req, ast_str_strlen(out)); + add_line(&req, ast_str_buffer(out)); if (!p->initreq.headers) initialize_initreq(p, &req); @@ -11452,7 +11484,7 @@ static enum check_auth_result check_auth(struct sip_pvt *p, struct sip_request * if (res == AST_DYNSTR_BUILD_FAILED) return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */ - c = buf->str; + c = ast_str_buffer(buf); while(c && *(c = ast_skip_blanks(c)) ) { /* lookup for keys */ for (i = keys; i->key != NULL; i++) { @@ -13943,7 +13975,7 @@ static char *sip_qualify_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_a } /*! \brief list peer mailboxes to CLI */ -static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer) +static char *peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer) { struct sip_mailbox *mailbox; @@ -13954,6 +13986,7 @@ static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer S_OR(mailbox->context, ""), AST_LIST_NEXT(mailbox, entry) ? "," : ""); } + return ast_str_buffer(*mailbox_str); } /*! \brief Show one peer in detail (main function) */ @@ -13990,7 +14023,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct } } if (peer && type==0 ) { /* Normal listing */ - struct ast_str *mailbox_str = ast_str_alloca(512); + struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16); ast_cli(fd, "\n\n"); ast_cli(fd, " * Name : %s\n", peer->name); if (realtimepeers) { /* Realtime is enabled */ @@ -14019,8 +14052,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct print_group(fd, peer->callgroup, 0); ast_cli(fd, " Pickupgroup : "); print_group(fd, peer->pickupgroup, 0); - peer_mailboxes_to_str(&mailbox_str, peer); - ast_cli(fd, " Mailbox : %s\n", mailbox_str->str); + ast_cli(fd, " Mailbox : %s\n", peer_mailboxes_to_str(&mailbox_str, peer)); ast_cli(fd, " VM Extension : %s\n", peer->vmexten); ast_cli(fd, " LastMsgsSent : %d/%d\n", (peer->lastmsgssent & 0x7fff0000) >> 16, peer->lastmsgssent & 0xffff); ast_cli(fd, " Call limit : %d\n", peer->call_limit); @@ -14106,7 +14138,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer ptr"); } else if (peer && type == 1) { /* manager listing */ char buffer[256]; - struct ast_str *mailbox_str = ast_str_alloca(512); + struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16); astman_append(s, "Channeltype: SIP\r\n"); astman_append(s, "ObjectName: %s\r\n", peer->name); astman_append(s, "ChanObjectType: peer\r\n"); @@ -14127,8 +14159,7 @@ static char *_sip_show_peer(int type, int fd, struct mansession *s, const struct astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->callgroup)); astman_append(s, "Pickupgroup: "); astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->pickupgroup)); - peer_mailboxes_to_str(&mailbox_str, peer); - astman_append(s, "VoiceMailbox: %s\r\n", mailbox_str->str); + astman_append(s, "VoiceMailbox: %s\r\n", peer_mailboxes_to_str(&mailbox_str, peer)); astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer)); astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent); astman_append(s, "Call-limit: %d\r\n", peer->call_limit); @@ -14695,7 +14726,7 @@ static int show_channels_cb(void *__cur, void *__arg, int flags) arg->numchans++; } if (cur->subscribed != NONE && arg->subscriptions) { - struct ast_str *mailbox_str = ast_str_alloca(512); + struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16); if (cur->subscribed == MWI_NOTIFICATION && cur->relatedpeer) peer_mailboxes_to_str(&mailbox_str, cur->relatedpeer); ast_cli(arg->fd, FORMAT4, ast_inet_ntoa(dst->sin_addr), @@ -14705,7 +14736,7 @@ static int show_channels_cb(void *__cur, void *__arg, int flags) cur->subscribed == MWI_NOTIFICATION ? "--" : cur->subscribeuri, cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate), subscription_type2str(cur->subscribed), - cur->subscribed == MWI_NOTIFICATION ? S_OR(mailbox_str->str, "<none>") : "<none>", + cur->subscribed == MWI_NOTIFICATION ? AS_OR(mailbox_str, "<none>") : "<none>", cur->expiry ); arg->numchans++; @@ -15791,9 +15822,8 @@ static int function_sippeer(struct ast_channel *chan, const char *cmd, char *dat } else if (!strcasecmp(colname, "useragent")) { ast_copy_string(buf, peer->useragent, len); } else if (!strcasecmp(colname, "mailbox")) { - struct ast_str *mailbox_str = ast_str_alloca(512); - peer_mailboxes_to_str(&mailbox_str, peer); - ast_copy_string(buf, mailbox_str->str, len); + struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16); + ast_copy_string(buf, peer_mailboxes_to_str(&mailbox_str, peer), len); } else if (!strcasecmp(colname, "context")) { ast_copy_string(buf, peer->context, len); } else if (!strcasecmp(colname, "expire")) { @@ -18092,12 +18122,12 @@ static int do_magic_pickup(struct ast_channel *channel, const char *extension, c ast_str_set(&str, 0, "%s@%s", extension, context); - ast_debug(2, "About to call Pickup(%s)\n", str->str); + ast_debug(2, "About to call Pickup(%s)\n", ast_str_buffer(str)); /* There is no point in capturing the return value since pickup_exec doesn't return anything meaningful unless the passed data is an empty string (which in our case it will not be) */ - pbx_exec(channel, pickup, str->str); + pbx_exec(channel, pickup, ast_str_buffer(str)); return 0; } @@ -20197,7 +20227,7 @@ static int sipsock_read(int *id, int fd, short events, void *ignore) return 1; } - if (ast_str_set(&req.data, 0, "%s", readbuf) == AST_DYNSTR_BUILD_FAILED) { + if (ast_str_set(&req.data, -1, "%s", readbuf) == AST_DYNSTR_BUILD_FAILED) { return -1; } @@ -20230,11 +20260,11 @@ static int handle_request_do(struct sip_request *req, struct sockaddr_in *sin) if (sip_debug_test_addr(sin)) /* Set the debug flag early on packet level */ req->debug = 1; if (sip_cfg.pedanticsipchecking) - req->len = lws2sws(req->data->str, req->len); /* Fix multiline headers */ + req->len = lws2sws(ast_str_buffer(req->data), req->len); /* Fix multiline headers */ if (req->debug) { ast_verbose("\n<--- SIP read from %s:%s:%d --->\n%s\n<------------->\n", get_transport(req->socket.type), ast_inet_ntoa(sin->sin_addr), - ntohs(sin->sin_port), req->data->str); + ntohs(sin->sin_port), ast_str_buffer(req->data)); } if(parse_request(req) == -1) { /* Bad packet, can't parse */ @@ -20281,7 +20311,7 @@ static int handle_request_do(struct sip_request *req, struct sockaddr_in *sin) p->recv = *sin; if (p->do_history) /* This is a request or response, note what it was for */ - append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), req->rlPart2); + append_history(p, "Rx", "%s / %s / %s", ast_str_buffer(req->data), get_header(req, "CSeq"), req->rlPart2); if (!lockretry) { if (p->owner) @@ -20526,9 +20556,8 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *e } else if (cache_only) { return 0; } else { /* Fall back to manually checking the mailbox */ - struct ast_str *mailbox_str = ast_str_alloca(512); - peer_mailboxes_to_str(&mailbox_str, peer); - ast_app_inboxcount(mailbox_str->str, &newmsgs, &oldmsgs); + struct ast_str *mailbox_str = ast_str_thread_get(&mailbox_buffer, 16); + ast_app_inboxcount(peer_mailboxes_to_str(&mailbox_str, peer), &newmsgs, &oldmsgs); } if (peer->mwipvt) { @@ -21972,7 +22001,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str ast_copy_string(peer->name, v->value, sizeof(peer->name)); else if (realtime && !strcasecmp(v->name, "fullcontact")) { /* Reconstruct field, because realtime separates our value at the ';' */ - if (fullcontact->used > 0) { + if (ast_str_strlen(fullcontact) > 0) { ast_str_append(&fullcontact, 0, ";%s", v->value); } else { ast_str_set(&fullcontact, 0, "%s", v->value); @@ -22254,8 +22283,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str peer->socket.type = default_primary_transport; } - if (fullcontact->used > 0) { - ast_string_field_set(peer, fullcontact, fullcontact->str); + if (ast_str_strlen(fullcontact) > 0) { + ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact)); peer->rt_fromcontact = TRUE; /* We have a hostname in the fullcontact, but if we don't have an * address listed on the entry (or if it's 'dynamic'), then we need to @@ -22264,7 +22293,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str * register once again). */ /* XXX May need to revisit the final argument; does the realtime DB store whether * the original contact was over TLS or not? XXX */ - __set_address_from_contact(fullcontact->str, &peer->addr, 0); + __set_address_from_contact(ast_str_buffer(fullcontact), &peer->addr, 0); } if (srvlookup && peer->dnsmgr == NULL) { diff --git a/channels/iax2-parser.c b/channels/iax2-parser.c index 224a924ce..55c1630e7 100644 --- a/channels/iax2-parser.c +++ b/channels/iax2-parser.c @@ -929,7 +929,7 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen) for (var2 = ies->vars, prev = NULL; var2; prev = var2, var2 = var2->next) { if (strcmp(tmp, var2->name) == 0) { ast_str_set(&str, 0, "%s%s", var2->value, tmp2); - var = ast_variable_new(tmp, str->str, var2->file); + var = ast_variable_new(tmp, ast_str_buffer(str), var2->file); var->next = var2->next; if (prev) { prev->next = var; @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 160097 . +# From configure.ac Revision: 163168 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for asterisk 1.6. # diff --git a/funcs/func_curl.c b/funcs/func_curl.c index 3a936e704..d4f34b850 100644 --- a/funcs/func_curl.c +++ b/funcs/func_curl.c @@ -354,14 +354,11 @@ static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *da register int realsize = size * nmemb; struct ast_str **pstr = (struct ast_str **)data; - ast_debug(3, "Called with data=%p, str=%p, realsize=%d, len=%zu, used=%zu\n", data, *pstr, realsize, (*pstr)->len, (*pstr)->used); + ast_debug(3, "Called with data=%p, str=%p, realsize=%d, len=%zu, used=%zu\n", data, *pstr, realsize, ast_str_size(*pstr), ast_str_strlen(*pstr)); - if (ast_str_make_space(pstr, (((*pstr)->used + realsize + 1) / 512 + 1) * 512 + 230) == 0) { - memcpy(&((*pstr)->str[(*pstr)->used]), ptr, realsize); - (*pstr)->used += realsize; - } + ast_str_append_substr(pstr, 0, ptr, realsize); - ast_debug(3, "Now, len=%zu, used=%zu\n", (*pstr)->len, (*pstr)->used); + ast_debug(3, "Now, len=%zu, used=%zu\n", ast_str_size(*pstr), ast_str_strlen(*pstr)); return realsize; } @@ -467,18 +464,15 @@ static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info, curl_easy_setopt(*curl, CURLOPT_POST, 0); } - if (str->used) { - str->str[str->used] = '\0'; - if (str->str[str->used - 1] == '\n') { - str->str[str->used - 1] = '\0'; - } + if (ast_str_strlen(str)) { + ast_str_trim_blanks(str); - ast_log(LOG_NOTICE, "str='%s'\n", str->str); + ast_debug(3, "str='%s'\n", ast_str_buffer(str)); if (hashcompat) { - char *remainder = str->str; + char *remainder = ast_str_buffer(str); char *piece; - struct ast_str *fields = ast_str_create(str->used / 2); - struct ast_str *values = ast_str_create(str->used / 2); + struct ast_str *fields = ast_str_create(ast_str_strlen(str) / 2); + struct ast_str *values = ast_str_create(ast_str_strlen(str) / 2); int rowcount = 0; while ((piece = strsep(&remainder, "&"))) { char *name = strsep(&piece, "="); @@ -488,12 +482,12 @@ static int acf_curl_exec(struct ast_channel *chan, const char *cmd, char *info, ast_str_append(&values, 0, "%s%s", rowcount ? "," : "", piece); rowcount++; } - pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", fields->str); - ast_copy_string(buf, values->str, len); + pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(fields)); + ast_copy_string(buf, ast_str_buffer(values), len); ast_free(fields); ast_free(values); } else { - ast_copy_string(buf, str->str, len); + ast_copy_string(buf, ast_str_buffer(str), len); } ret = 0; } diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c index 36f530c6a..06ffecc50 100644 --- a/funcs/func_odbc.c +++ b/funcs/func_odbc.c @@ -34,6 +34,7 @@ <use>iodbc</use> ***/ +#define USE_ODBC #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") @@ -46,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/res_odbc.h" #include "asterisk/app.h" #include "asterisk/cli.h" +#include "asterisk/strings.h" /*** DOCUMENTATION <function name="ODBC_FETCH" language="en_US"> @@ -281,8 +283,8 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co /* Additionally set the value as a whole (but push an empty string if value is NULL) */ pbx_builtin_pushvar_helper(chan, "VALUE", value ? value : ""); - pbx_substitute_variables_helper(chan, query->sql_write, buf->str, buf->len - 1); - pbx_substitute_variables_helper(chan, query->sql_insert, insertbuf->str, insertbuf->len - 1); + ast_str_substitute_variables(&buf, 0, chan, query->sql_write); + ast_str_substitute_variables(&insertbuf, 0, chan, query->sql_insert); /* Restore prior values */ for (i = 0; i < args.argc; i++) { @@ -300,7 +302,7 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co if (!ast_strlen_zero(query->writehandle[dsn])) { obj = ast_odbc_request_obj(query->writehandle[dsn], 0); if (obj) - stmt = ast_odbc_direct_execute(obj, generic_execute, buf->str); + stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(buf)); } if (stmt) { status = "SUCCESS"; @@ -309,14 +311,14 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co } } - if (stmt && rows == 0 && !ast_strlen_zero(insertbuf->str)) { + if (stmt && rows == 0 && ast_str_strlen(insertbuf) != 0) { SQLCloseCursor(stmt); SQLFreeHandle(SQL_HANDLE_STMT, stmt); for (dsn = 0; dsn < 5; dsn++) { if (!ast_strlen_zero(query->writehandle[dsn])) { obj = ast_odbc_request_obj(query->writehandle[dsn], 0); if (obj) { - stmt = ast_odbc_direct_execute(obj, generic_execute, insertbuf->str); + stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(insertbuf)); } } if (stmt) { @@ -409,8 +411,7 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha pbx_builtin_pushvar_helper(chan, varname, args.field[x]); } - ast_str_make_space(&sql, strlen(query->sql_read) * 2 + 300); - pbx_substitute_variables_helper(chan, query->sql_read, sql->str, sql->len - 1); + ast_str_substitute_variables(&sql, 0, chan, query->sql_read); /* Restore prior values */ for (x = 0; x < args.argc; x++) { @@ -435,7 +436,7 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha if (!ast_strlen_zero(query->readhandle[dsn])) { obj = ast_odbc_request_obj(query->readhandle[dsn], 0); if (obj) { - stmt = ast_odbc_direct_execute(obj, generic_execute, sql->str); + stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(sql)); } } if (stmt) { @@ -444,7 +445,7 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha } if (!stmt) { - ast_log(LOG_ERROR, "Unable to execute query [%s]\n", sql->str); + ast_log(LOG_ERROR, "Unable to execute query [%s]\n", ast_str_buffer(sql)); if (obj) { ast_odbc_release_obj(obj); } @@ -460,7 +461,7 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha res = SQLNumResultCols(stmt, &colcount); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql->str); + ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", ast_str_buffer(sql)); SQLCloseCursor(stmt); SQLFreeHandle (SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); @@ -478,13 +479,13 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { int res1 = -1; if (res == SQL_NO_DATA) { - ast_verb(4, "Found no rows [%s]\n", sql->str); + ast_verb(4, "Found no rows [%s]\n", ast_str_buffer(sql)); res1 = 0; buf[0] = '\0'; ast_copy_string(rowcount, "0", sizeof(rowcount)); status = "NODATA"; } else { - ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, sql->str); + ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, ast_str_buffer(sql)); status = "FETCHERROR"; } SQLCloseCursor(stmt); @@ -505,6 +506,7 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha for (x = 0; x < colcount; x++) { int i; struct ast_str *coldata = ast_str_thread_get(&coldata_buf, 16); + char *ptrcoldata; if (y == 0) { char colname[256]; @@ -516,30 +518,15 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha snprintf(colname, sizeof(colname), "field%d", x); } - if (coldata->len < maxcol + 1) { - ast_str_make_space(&coldata, maxcol + 1); - } + ast_str_make_space(&coldata, maxcol + 1); - if (colnames->used) { + if (ast_str_strlen(colnames)) { ast_str_append(&colnames, 0, ","); } - ast_str_make_space(&colnames, strlen(colname) * 2 + 1 + colnames->used); - - /* Copy data, encoding '\' and ',' for the argument parser */ - for (i = 0; i < sizeof(colname); i++) { - if (escapecommas && (colname[i] == '\\' || colname[i] == ',')) { - colnames->str[colnames->used++] = '\\'; - } - colnames->str[colnames->used++] = colname[i]; - - if (colname[i] == '\0') { - colnames->used--; - break; - } - } + ast_str_append_escapecommas(&colnames, 0, colname, sizeof(colname)); if (resultset) { - void *tmp = ast_realloc(resultset, sizeof(*resultset) + colnames->used + 1); + void *tmp = ast_realloc(resultset, sizeof(*resultset) + ast_str_strlen(colnames) + 1); if (!tmp) { ast_log(LOG_ERROR, "No space for a new resultset?\n"); ast_free(resultset); @@ -555,12 +542,12 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha return -1; } resultset = tmp; - strcpy((char *)resultset + sizeof(*resultset), colnames->str); + strcpy((char *)resultset + sizeof(*resultset), ast_str_buffer(colnames)); } } buflen = strlen(buf); - res = SQLGetData(stmt, x + 1, SQL_CHAR, coldata->str, coldata->len, &indicator); + res = ast_str_SQLGetData(&coldata, -1, stmt, x + 1, SQL_CHAR, &indicator); if (indicator == SQL_NULL_DATA) { ast_debug(3, "Got NULL data\n"); ast_str_reset(coldata); @@ -568,39 +555,42 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha } if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql->str); + ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", ast_str_buffer(sql)); y = -1; buf[0] = '\0'; goto end_acf_read; } - ast_debug(2, "Got coldata of '%s'\n", coldata->str); - coldata->used = strlen(coldata->str); + ast_debug(2, "Got coldata of '%s'\n", ast_str_buffer(coldata)); + + if (buflen) { + buf[buflen++] = ','; + } /* Copy data, encoding '\' and ',' for the argument parser */ - for (i = 0; i < coldata->used; i++) { - if (escapecommas && (coldata->str[i] == '\\' || coldata->str[i] == ',')) { + ptrcoldata = ast_str_buffer(coldata); + for (i = 0; i < ast_str_strlen(coldata); i++) { + if (escapecommas && (ptrcoldata[i] == '\\' || ptrcoldata[i] == ',')) { buf[buflen++] = '\\'; } - buf[buflen++] = coldata->str[i]; + buf[buflen++] = ptrcoldata[i]; - if (buflen >= len - 2) + if (buflen >= len - 2) { break; + } - if (coldata->str[i] == '\0') + if (ptrcoldata[i] == '\0') { break; + } } - buf[buflen++] = ','; buf[buflen] = '\0'; ast_debug(2, "buf is now set to '%s'\n", buf); } - /* Trim trailing comma */ - buf[buflen - 1] = '\0'; ast_debug(2, "buf is now set to '%s'\n", buf); if (resultset) { - row = ast_calloc(1, sizeof(*row) + buflen); + row = ast_calloc(1, sizeof(*row) + buflen + 1); if (!row) { ast_log(LOG_ERROR, "Unable to allocate space for more rows in this resultset.\n"); status = "MEMERROR"; @@ -612,8 +602,10 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha /* Get next row */ res = SQLFetch(stmt); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - if (res != SQL_NO_DATA) - ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, sql->str); + if (res != SQL_NO_DATA) { + ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, ast_str_buffer(sql)); + } + /* Number of rows in the resultset */ y++; break; } @@ -624,7 +616,7 @@ end_acf_read: snprintf(rowcount, sizeof(rowcount), "%d", y); pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); - pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", colnames->str); + pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(colnames)); if (resultset) { int uid; struct ast_datastore *odbc_store; @@ -1042,8 +1034,7 @@ static char *cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args pbx_builtin_pushvar_helper(chan, varname, args.field[i]); } - /*!\note This does not set sql->used, so don't try to use that value. */ - pbx_substitute_variables_helper(chan, query->sql_read, sql->str, sql->len - 1); + ast_str_substitute_variables(&sql, 0, chan, query->sql_read); ast_channel_free(chan); if (a->argc == 5 && !strcmp(a->argv[4], "exec")) { @@ -1068,7 +1059,7 @@ static char *cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args } ast_debug(1, "Got obj\n"); - if (!(stmt = ast_odbc_direct_execute(obj, generic_execute, sql->str))) { + if (!(stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(sql)))) { ast_odbc_release_obj(obj); continue; } @@ -1077,7 +1068,7 @@ static char *cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args res = SQLNumResultCols(stmt, &colcount); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_cli(a->fd, "SQL Column Count error!\n[%s]\n\n", sql->str); + ast_cli(a->fd, "SQL Column Count error!\n[%s]\n\n", ast_str_buffer(sql)); SQLCloseCursor(stmt); SQLFreeHandle (SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); @@ -1091,10 +1082,10 @@ static char *cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args SQLFreeHandle(SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); if (res == SQL_NO_DATA) { - ast_cli(a->fd, "Returned %d rows. Query executed on handle %d:%s [%s]\n", rows, dsn, query->readhandle[dsn], sql->str); + ast_cli(a->fd, "Returned %d rows. Query executed on handle %d:%s [%s]\n", rows, dsn, query->readhandle[dsn], ast_str_buffer(sql)); break; } else { - ast_cli(a->fd, "Error %d in FETCH [%s]\n", res, sql->str); + ast_cli(a->fd, "Error %d in FETCH [%s]\n", res, ast_str_buffer(sql)); } AST_RWLIST_UNLOCK(&queries); return CLI_SUCCESS; @@ -1106,18 +1097,14 @@ static char *cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args snprintf(colname, sizeof(colname), "field%d", x); } - if (coldata->len < maxcol + 1) { - ast_str_make_space(&coldata, maxcol + 1); - } - - res = SQLGetData(stmt, x + 1, SQL_CHAR, coldata->str, coldata->len, &indicator); + res = ast_str_SQLGetData(&coldata, maxcol, stmt, x + 1, SQL_CHAR, &indicator); if (indicator == SQL_NULL_DATA) { ast_str_set(&coldata, 0, "(nil)"); res = SQL_SUCCESS; } if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_cli(a->fd, "SQL Get Data error %d!\n[%s]\n\n", res, sql->str); + ast_cli(a->fd, "SQL Get Data error %d!\n[%s]\n\n", res, ast_str_buffer(sql)); SQLCloseCursor(stmt); SQLFreeHandle(SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); @@ -1125,7 +1112,7 @@ static char *cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args return CLI_SUCCESS; } - ast_cli(a->fd, "%-20.20s %s\n", colname, coldata->str); + ast_cli(a->fd, "%-20.20s %s\n", colname, ast_str_buffer(coldata)); } /* Get next row */ res = SQLFetch(stmt); @@ -1144,10 +1131,10 @@ static char *cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args ast_odbc_release_obj(obj); if (!executed) { - ast_cli(a->fd, "Failed to execute query. [%s]\n", sql->str); + ast_cli(a->fd, "Failed to execute query. [%s]\n", ast_str_buffer(sql)); } } else { /* No execution, just print out the resulting SQL */ - ast_cli(a->fd, "%s\n", sql->str); + ast_cli(a->fd, "%s\n", ast_str_buffer(sql)); } AST_RWLIST_UNLOCK(&queries); return CLI_SUCCESS; @@ -1250,8 +1237,8 @@ static char *cli_odbc_write(struct ast_cli_entry *e, int cmd, struct ast_cli_arg /* Additionally set the value as a whole (but push an empty string if value is NULL) */ pbx_builtin_pushvar_helper(chan, "VALUE", S_OR(a->argv[4], "")); - pbx_substitute_variables_helper(chan, query->sql_write, sql->str, sql->len - 1); - ast_debug(1, "SQL is %s\n", sql->str); + ast_str_substitute_variables(&sql, 0, chan, query->sql_write); + ast_debug(1, "SQL is %s\n", ast_str_buffer(sql)); ast_channel_free(chan); if (a->argc == 6 && !strcmp(a->argv[5], "exec")) { @@ -1268,7 +1255,7 @@ static char *cli_odbc_write(struct ast_cli_entry *e, int cmd, struct ast_cli_arg if (!(obj = ast_odbc_request_obj(query->writehandle[dsn], 0))) { continue; } - if (!(stmt = ast_odbc_direct_execute(obj, generic_execute, sql->str))) { + if (!(stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(sql)))) { ast_odbc_release_obj(obj); continue; } @@ -1286,7 +1273,7 @@ static char *cli_odbc_write(struct ast_cli_entry *e, int cmd, struct ast_cli_arg ast_cli(a->fd, "Failed to execute query.\n"); } } else { /* No execution, just print out the resulting SQL */ - ast_cli(a->fd, "%s\n", sql->str); + ast_cli(a->fd, "%s\n", ast_str_buffer(sql)); } AST_RWLIST_UNLOCK(&queries); return CLI_SUCCESS; diff --git a/funcs/func_realtime.c b/funcs/func_realtime.c index 17e3a2d2b..065864511 100644 --- a/funcs/func_realtime.c +++ b/funcs/func_realtime.c @@ -141,24 +141,6 @@ AST_THREADSTORAGE(buf1); AST_THREADSTORAGE(buf2); AST_THREADSTORAGE(buf3); -static char *hash_escape(struct ast_str **str, const char *value) -{ - int len; - ast_str_reset(*str); - - if ((*str)->len < (len = strlen(value) * 2 + 1)) { - ast_str_make_space(str, len); - } - for (; *value; value++) { - if (*value == ',' || *value == '\\') { - (*str)->str[(*str)->used++] = '\\'; - } - (*str)->str[(*str)->used++] = *value; - } - (*str)->str[(*str)->used] = '\0'; - return (*str)->str; -} - static int function_realtime_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { struct ast_variable *var, *head; @@ -206,7 +188,7 @@ static int function_realtime_read(struct ast_channel *chan, const char *cmd, cha out = ast_str_alloca(resultslen); for (var = head; var; var = var->next) ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1); - ast_copy_string(buf, out->str, len); + ast_copy_string(buf, ast_str_buffer(out), len); if (chan) ast_autoservice_stop(chan); @@ -303,16 +285,16 @@ static int realtimefield_read(struct ast_channel *chan, const char *cmd, char *d } } else if (which == rthash) { ast_debug(1, "Setting hash key %s to value %s\n", var->name, var->value); - ast_str_append(&fields, 0, "%s%s", first ? "" : ",", hash_escape(&escapebuf, var->name)); - ast_str_append(&values, 0, "%s%s", first ? "" : ",", hash_escape(&escapebuf, var->value)); + ast_str_append(&fields, 0, "%s%s", first ? "" : ",", ast_str_set_escapecommas(&escapebuf, 0, var->name, INT_MAX)); + ast_str_append(&values, 0, "%s%s", first ? "" : ",", ast_str_set_escapecommas(&escapebuf, 0, var->value, INT_MAX)); first = 0; } } ast_variables_destroy(head); if (which == rthash) { - pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", fields->str); - ast_copy_string(buf, values->str, len); + pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(fields)); + ast_copy_string(buf, ast_str_buffer(values), len); } if (chan) { @@ -418,7 +400,7 @@ static int function_realtime_readdestroy(struct ast_channel *chan, const char *c for (var = head; var; var = var->next) { ast_str_append(&out, 0, "%s%s%s%s", var->name, args.delim2, var->value, args.delim1); } - ast_copy_string(buf, out->str, len); + ast_copy_string(buf, ast_str_buffer(out), len); ast_destroy_realtime(args.family, args.fieldmatch, args.value, SENTINEL); diff --git a/funcs/func_strings.c b/funcs/func_strings.c index da7525170..fa43752a4 100644 --- a/funcs/func_strings.c +++ b/funcs/func_strings.c @@ -321,7 +321,7 @@ static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, ch ); const char *orig_list, *ptr; const char *begin, *cur, *next; - int dlen, flen; + int dlen, flen, first = 1; struct ast_str *result = ast_str_thread_get(&result_buf, 16); char *delim; @@ -385,15 +385,12 @@ static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, ch begin += flen + dlen; } else { /* Copy field to output */ - if (result->used) { + if (!first) { ast_str_append(&result, 0, "%s", delim); } - /* Have to do it this way, since we're not null-terminated. */ - strncpy(result->str + result->used, begin, cur - begin); - result->used += cur - begin; - result->str[result->used] = '\0'; - + ast_str_append_substr(&result, 0, begin, cur - begin + 1); + first = 0; begin = cur + dlen; } } while (*cur != '\0'); @@ -401,7 +398,7 @@ static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, ch ast_channel_unlock(chan); } - ast_copy_string(buf, result->str, len); + ast_copy_string(buf, ast_str_buffer(result), len); return 0; } diff --git a/include/asterisk/app.h b/include/asterisk/app.h index 851ad9fa6..79af2313e 100644 --- a/include/asterisk/app.h +++ b/include/asterisk/app.h @@ -23,12 +23,17 @@ #ifndef _ASTERISK_APP_H #define _ASTERISK_APP_H +#include "asterisk/strings.h" +#include "asterisk/threadstorage.h" + struct ast_flags64; #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif +AST_THREADSTORAGE_EXTERNAL(global_app_buf); + /* IVR stuff */ /*! \brief Callback function for IVR diff --git a/include/asterisk/cdr.h b/include/asterisk/cdr.h index 7ece62379..312c2546e 100644 --- a/include/asterisk/cdr.h +++ b/include/asterisk/cdr.h @@ -282,7 +282,7 @@ void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chan); * Changes the value of the last executed app * Returns nothing */ -void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data); +void ast_cdr_setapp(struct ast_cdr *cdr, const char *app, const char *data); /*! * \brief Convert a string to a detail record AMA flag diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h index 3348bb8d7..2bb95930f 100644 --- a/include/asterisk/pbx.h +++ b/include/asterisk/pbx.h @@ -114,11 +114,11 @@ struct ast_switch { }; struct ast_timing { - int hastime; /*!< If time construct exists */ - unsigned int monthmask; /*!< Mask for month */ - unsigned int daymask; /*!< Mask for date */ - unsigned int dowmask; /*!< Mask for day of week (mon-sun) */ - unsigned int minmask[24]; /*!< Mask for minute */ + int hastime; /*!< If time construct exists */ + unsigned int monthmask; /*!< Mask for month */ + unsigned int daymask; /*!< Mask for date */ + unsigned int dowmask; /*!< Mask for day of week (sun-sat) */ + unsigned int minmask[48]; /*!< Mask for minute */ }; int ast_build_timing(struct ast_timing *i, const char *info); @@ -866,6 +866,8 @@ int pbx_builtin_raise_exception(struct ast_channel *chan, void *data); void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count); void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count); +void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used); +void ast_str_substitute_variables(struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *templ); int ast_extension_patmatch(const char *pattern, const char *data); diff --git a/include/asterisk/strings.h b/include/asterisk/strings.h index 43d5bfc41..84782a3ac 100644 --- a/include/asterisk/strings.h +++ b/include/asterisk/strings.h @@ -23,14 +23,17 @@ #ifndef _ASTERISK_STRINGS_H #define _ASTERISK_STRINGS_H +#define DEBUG_OPAQUE + #include <ctype.h> -#include "asterisk/inline_api.h" #include "asterisk/utils.h" #include "asterisk/threadstorage.h" /* You may see casts in this header that may seem useless but they ensure this file is C++ clean */ +#define AS_OR(a,b) ast_str_strlen(a) ? ast_str_buffer(a) : (b) + #ifdef AST_DEVMODE #define ast_strlen_zero(foo) _ast_strlen_zero(foo, __FILE__, __PRETTY_FUNCTION__, __LINE__) static force_inline int _ast_strlen_zero(const char *s, const char *file, const char *function, int line) @@ -202,7 +205,6 @@ void ast_copy_string(char *dst, const char *src, size_t size), } ) - /*! \brief Build a string in a buffer, designed to be called repeatedly @@ -338,13 +340,23 @@ int ast_get_timeval(const char *src, struct timeval *tv, struct timeval _default * struct ast_threadstorage pointer. */ struct ast_str { +#ifdef DEBUG_OPAQUE + size_t len2; + size_t used2; + struct ast_threadstorage *ts2; +#else size_t len; /*!< The current maximum length of the string */ size_t used; /*!< Amount of space used */ struct ast_threadstorage *ts; /*!< What kind of storage is this ? */ +#endif #define DS_MALLOC ((struct ast_threadstorage *)1) #define DS_ALLOCA ((struct ast_threadstorage *)2) #define DS_STATIC ((struct ast_threadstorage *)3) /* not supported yet */ +#ifdef DEBUG_OPAQUE + char str2[0]; +#else char str[0]; /*!< The string buffer */ +#endif }; /*! @@ -366,10 +378,16 @@ struct ast_str * attribute_malloc ast_str_create(size_t init_len), buf = (struct ast_str *)ast_calloc(1, sizeof(*buf) + init_len); if (buf == NULL) return NULL; - + +#ifdef DEBUG_OPAQUE + buf->len2 = init_len; + buf->used2 = 0; + buf->ts2 = DS_MALLOC; +#else buf->len = init_len; buf->used = 0; buf->ts = DS_MALLOC; +#endif return buf; } @@ -382,9 +400,15 @@ AST_INLINE_API( void ast_str_reset(struct ast_str *buf), { if (buf) { +#ifdef DEBUG_OPAQUE + buf->used2 = 0; + if (buf->len2) + buf->str2[0] = '\0'; +#else buf->used = 0; if (buf->len) buf->str[0] = '\0'; +#endif } } ) @@ -398,12 +422,83 @@ void ast_str_trim_blanks(struct ast_str *buf), if (!buf) { return; } +#ifdef DEBUG_OPAQUE + while (buf->used2 && buf->str2[buf->used2 - 1] < 33) { + buf->str2[--(buf->used2)] = '\0'; + } +#else while (buf->used && buf->str[buf->used - 1] < 33) { buf->str[--(buf->used)] = '\0'; } +#endif +} +) + +/*!\brief Returns the current length of the string stored within buf. + * \param A pointer to the ast_str string. + */ +AST_INLINE_API( +size_t ast_str_strlen(struct ast_str *buf), +{ +#ifdef DEBUG_OPAQUE + return buf->used2; +#else + return buf->used; +#endif +} +) + +/*!\brief Returns the current maximum length (without reallocation) of the current buffer. + * \param A pointer to the ast_str string. + */ +AST_INLINE_API( +size_t ast_str_size(struct ast_str *buf), +{ +#ifdef DEBUG_OPAQUE + return buf->len2; +#else + return buf->len; +#endif } ) +/*!\brief Returns the string buffer within the ast_str buf. + * \param A pointer to the ast_str string. + */ +AST_INLINE_API( +attribute_pure char *ast_str_buffer(struct ast_str *buf), +{ +#ifdef DEBUG_OPAQUE + return buf->str2; +#else + return buf->str; +#endif +} +) + +AST_INLINE_API( +char *ast_str_truncate(struct ast_str *buf, size_t len), +{ +#ifdef DEBUG_OPAQUE + if (len < 0) { + buf->used2 += len; + } else { + buf->used2 = len; + } + buf->str2[buf->used2] = '\0'; + return buf->str2; +#else + if (len < 0) { + buf->used += len; + } else { + buf->used = len; + } + buf->str[buf->used] = '\0'; + return buf->str; +#endif +} +) + /* * AST_INLINE_API() is a macro that takes a block of code as an argument. * Using preprocessor #directives in the argument is not supported by all @@ -427,6 +522,23 @@ int _ast_str_make_space(struct ast_str **buf, size_t new_len, const char *file, { struct ast_str *old_buf = *buf; +#ifdef DEBUG_OPAQUE + if (new_len <= (*buf)->len2) + return 0; /* success */ + if ((*buf)->ts2 == DS_ALLOCA || (*buf)->ts2 == DS_STATIC) + return -1; /* cannot extend */ + *buf = (struct ast_str *)__ast_realloc(*buf, new_len + sizeof(struct ast_str), file, lineno, function); + if (*buf == NULL) { + *buf = old_buf; + return -1; + } + if ((*buf)->ts2 != DS_MALLOC) { + pthread_setspecific((*buf)->ts2->key, *buf); + _DB1(__ast_threadstorage_object_replace(old_buf, *buf, new_len + sizeof(struct ast_str));) + } + + (*buf)->len2 = new_len; +#else if (new_len <= (*buf)->len) return 0; /* success */ if ((*buf)->ts == DS_ALLOCA || (*buf)->ts == DS_STATIC) @@ -442,6 +554,7 @@ int _ast_str_make_space(struct ast_str **buf, size_t new_len, const char *file, } (*buf)->len = new_len; +#endif return 0; } ) @@ -452,6 +565,23 @@ int ast_str_make_space(struct ast_str **buf, size_t new_len), { struct ast_str *old_buf = *buf; +#ifdef DEBUG_OPAQUE + if (new_len <= (*buf)->len2) + return 0; /* success */ + if ((*buf)->ts2 == DS_ALLOCA || (*buf)->ts2 == DS_STATIC) + return -1; /* cannot extend */ + *buf = (struct ast_str *)ast_realloc(*buf, new_len + sizeof(struct ast_str)); + if (*buf == NULL) { + *buf = old_buf; + return -1; + } + if ((*buf)->ts2 != DS_MALLOC) { + pthread_setspecific((*buf)->ts2->key, *buf); + _DB1(__ast_threadstorage_object_replace(old_buf, *buf, new_len + sizeof(struct ast_str));) + } + + (*buf)->len2 = new_len; +#else if (new_len <= (*buf)->len) return 0; /* success */ if ((*buf)->ts == DS_ALLOCA || (*buf)->ts == DS_STATIC) @@ -467,11 +597,24 @@ int ast_str_make_space(struct ast_str **buf, size_t new_len), } (*buf)->len = new_len; +#endif return 0; } ) #endif +#ifdef DEBUG_OPAQUE +#define ast_str_alloca(init_len) \ + ({ \ + struct ast_str *__ast_str_buf; \ + __ast_str_buf = alloca(sizeof(*__ast_str_buf) + init_len); \ + __ast_str_buf->len2 = init_len; \ + __ast_str_buf->used2 = 0; \ + __ast_str_buf->ts2 = DS_ALLOCA; \ + __ast_str_buf->str2[0] = '\0'; \ + (__ast_str_buf); \ + }) +#else #define ast_str_alloca(init_len) \ ({ \ struct ast_str *__ast_str_buf; \ @@ -482,6 +625,7 @@ int ast_str_make_space(struct ast_str **buf, size_t new_len), __ast_str_buf->str[0] = '\0'; \ (__ast_str_buf); \ }) +#endif /*! * \brief Retrieve a thread locally stored dynamic string @@ -524,12 +668,20 @@ struct ast_str *ast_str_thread_get(struct ast_threadstorage *ts, buf = (struct ast_str *)ast_threadstorage_get(ts, sizeof(*buf) + init_len); if (buf == NULL) return NULL; - + +#ifdef DEBUG_OPAQUE + if (!buf->len2) { + buf->len2 = init_len; + buf->used2 = 0; + buf->ts2 = ts; + } +#else if (!buf->len) { buf->len = init_len; buf->used = 0; buf->ts = ts; } +#endif return buf; } @@ -544,12 +696,20 @@ struct ast_str *__ast_str_thread_get(struct ast_threadstorage *ts, buf = (struct ast_str *)__ast_threadstorage_get(ts, sizeof(*buf) + init_len, file, function, line); if (buf == NULL) return NULL; - + +#ifdef DEBUG_OPAQUE + if (!buf->len2) { + buf->len2 = init_len; + buf->used2 = 0; + buf->ts2 = ts; + } +#else if (!buf->len) { buf->len = init_len; buf->used = 0; buf->ts = ts; } +#endif return buf; } @@ -599,6 +759,8 @@ enum { */ int __attribute__((format(printf, 4, 0))) __ast_str_helper(struct ast_str **buf, size_t max_len, int append, const char *fmt, va_list ap); +char *__ast_str_helper2(struct ast_str **buf, size_t max_len, + const char *src, size_t maxsrc, int append, int escapecommas); /*! * \brief Set a dynamic string from a va_list @@ -655,6 +817,78 @@ AST_INLINE_API(int __attribute__((format(printf, 3, 0))) ast_str_append_va(struc } ) +/*!\brief Set a dynamic string to a non-NULL terminated substring. */ +AST_INLINE_API(char *ast_str_set_substr(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc), +{ + return __ast_str_helper2(buf, maxlen, src, maxsrc, 0, 0); +} +) + +/*!\brief Append a non-NULL terminated substring to the end of a dynamic string. */ +AST_INLINE_API(char *ast_str_append_substr(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc), +{ + return __ast_str_helper2(buf, maxlen, src, maxsrc, 1, 0); +} +) + +/*!\brief Set a dynamic string to a non-NULL terminated substring, with escaping of commas. */ +AST_INLINE_API(char *ast_str_set_escapecommas(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc), +{ + return __ast_str_helper2(buf, maxlen, src, maxsrc, 0, 1); +} +) + +/*!\brief Append a non-NULL terminated substring to the end of a dynamic string, with escaping of commas. */ +AST_INLINE_API(char *ast_str_append_escapecommas(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc), +{ + return __ast_str_helper2(buf, maxlen, src, maxsrc, 1, 1); +} +) + +/*!\brief Wrapper for SQLGetData to use with dynamic strings + * \param buf Address of the pointer to the ast_str structure. + * \param maxlen The maximum size of the resulting string, or 0 for no limit. + * \param StatementHandle The statement handle from which to retrieve data. + * \param ColumnNumber Column number (1-based offset) for which to retrieve data. + * \param TargetType The SQL constant indicating what kind of data is to be retrieved (usually SQL_CHAR) + * \param StrLen_or_Ind A pointer to a length indicator, specifying the total length of data. + */ +#ifdef USE_ODBC +#include <sql.h> +#include <sqlext.h> +#include <sqltypes.h> + +AST_INLINE_API(SQLRETURN ast_str_SQLGetData(struct ast_str **buf, size_t maxlen, SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLLEN *StrLen_or_Ind), +{ + SQLRETURN res; + if (maxlen == 0) { +#ifdef DEBUG_OPAQUE + if (SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str2, 0, StrLen_or_Ind) == SQL_SUCCESS_WITH_INFO) { + ast_str_make_space(buf, *StrLen_or_Ind + 1); + } + maxlen = (*buf)->len2; + } else if (maxlen > 0) { + ast_str_make_space(buf, maxlen); + } + res = SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str2, maxlen, StrLen_or_Ind); + (*buf)->used2 = *StrLen_or_Ind; +#else + if (SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str, 0, StrLen_or_Ind) == SQL_SUCCESS_WITH_INFO) { + ast_str_make_space(buf, *StrLen_or_Ind + 1); + } + maxlen = (*buf)->len; + } else if (maxlen > 0) { + ast_str_make_space(buf, maxlen); + } + res = SQLGetData(StatementHandle, ColumnNumber, TargetType, (*buf)->str, maxlen, StrLen_or_Ind); + (*buf)->used = *StrLen_or_Ind; +#endif + return res; +} +) +#endif /* defined(USE_ODBC) */ + + /*! * \brief Set a dynamic string using variable arguments * diff --git a/include/asterisk/tcptls.h b/include/asterisk/tcptls.h index 6fb6d4b63..611709cbe 100644 --- a/include/asterisk/tcptls.h +++ b/include/asterisk/tcptls.h @@ -157,6 +157,6 @@ void ast_tcptls_server_stop(struct ast_tcptls_session_args *desc); int ast_ssl_setup(struct ast_tls_config *cfg); HOOK_T ast_tcptls_server_read(struct ast_tcptls_session_instance *ser, void *buf, size_t count); -HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *ser, void *buf, size_t count); +HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *ser, const void *buf, size_t count); #endif /* _ASTERISK_TCPTLS_H */ diff --git a/include/asterisk/threadstorage.h b/include/asterisk/threadstorage.h index cf6d47e32..ab586974f 100644 --- a/include/asterisk/threadstorage.h +++ b/include/asterisk/threadstorage.h @@ -85,7 +85,11 @@ void __ast_threadstorage_object_replace(void *key_old, void *key_new, size_t len * \endcode */ #define AST_THREADSTORAGE(name) \ - AST_THREADSTORAGE_CUSTOM(name, NULL, ast_free_ptr) + AST_THREADSTORAGE_CUSTOM_SCOPE(name, NULL, ast_free_ptr, static) +#define AST_THREADSTORAGE_PUBLIC(name) \ + AST_THREADSTORAGE_CUSTOM_SCOPE(name, NULL, ast_free_ptr,) +#define AST_THREADSTORAGE_EXTERNAL(name) \ + extern struct ast_threadstorage name /*! * \brief Define a thread storage variable, with custom initialization and cleanup @@ -103,10 +107,12 @@ void __ast_threadstorage_object_replace(void *key_old, void *key_new, size_t len * AST_THREADSTORAGE_CUSTOM(my_buf, my_init, my_cleanup); * \endcode */ +#define AST_THREADSTORAGE_CUSTOM(a,b,c) AST_THREADSTORAGE_CUSTOM_SCOPE(a,b,c,static) + #if !defined(DEBUG_THREADLOCALS) -#define AST_THREADSTORAGE_CUSTOM(name, c_init, c_cleanup) \ +#define AST_THREADSTORAGE_CUSTOM_SCOPE(name, c_init, c_cleanup, scope) \ static void __init_##name(void); \ -static struct ast_threadstorage name = { \ +scope struct ast_threadstorage name = { \ .once = THREADSTORAGE_ONCE_INIT, \ .key_init = __init_##name, \ .custom_init = c_init, \ @@ -116,9 +122,9 @@ static void __init_##name(void) \ pthread_key_create(&(name).key, c_cleanup); \ } #else /* defined(DEBUG_THREADLOCALS) */ -#define AST_THREADSTORAGE_CUSTOM(name, c_init, c_cleanup) \ +#define AST_THREADSTORAGE_CUSTOM_SCOPE(name, c_init, c_cleanup, scope) \ static void __init_##name(void); \ -static struct ast_threadstorage name = { \ +scope struct ast_threadstorage name = { \ .once = THREADSTORAGE_ONCE_INIT, \ .key_init = __init_##name, \ .custom_init = c_init, \ diff --git a/main/Makefile b/main/Makefile index 56b964d16..54882f245 100644 --- a/main/Makefile +++ b/main/Makefile @@ -28,7 +28,8 @@ OBJS= tcptls.o io.o sched.o logger.o frame.o loader.o config.o channel.o \ cryptostub.o sha1.o http.o fixedjitterbuf.o abstract_jb.o \ strcompat.o threadstorage.o dial.o event.o adsistub.o audiohook.o \ astobj2.o hashtab.o global_datastores.o version.o \ - features.o taskprocessor.o timing.o datastore.o xml.o xmldoc.o + features.o taskprocessor.o timing.o datastore.o xml.o xmldoc.o \ + strings.o # we need to link in the objects statically, not as a library, because # otherwise modules will not have them available if none of the static diff --git a/main/app.c b/main/app.c index aecbffaf2..d3d3b3784 100644 --- a/main/app.c +++ b/main/app.c @@ -44,6 +44,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/lock.h" #include "asterisk/indications.h" #include "asterisk/linkedlists.h" +#include "asterisk/threadstorage.h" + +AST_THREADSTORAGE_PUBLIC(global_app_buf); + #define MAX_OTHER_FORMATS 10 diff --git a/main/asterisk.c b/main/asterisk.c index c002a4542..8fe421dde 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -2034,7 +2034,7 @@ static char *cli_prompt(EditLine *editline) if (prompt == NULL) { prompt = ast_str_create(100); } else if (!cli_prompt_changes) { - return prompt->str; + return ast_str_buffer(prompt); } else { ast_str_reset(prompt); } @@ -2132,11 +2132,7 @@ static char *cli_prompt(EditLine *editline) } t++; } else { - if (prompt->used + 5 > prompt->len) { - ast_str_make_space(&prompt, prompt->len + 5); - } - prompt->str[prompt->used++] = *t++; - prompt->str[prompt->used] = '\0'; + ast_str_append(&prompt, 0, "%c", *t); } } if (color_used) { @@ -2149,7 +2145,7 @@ static char *cli_prompt(EditLine *editline) ast_str_set(&prompt, 0, "%s", ASTERISK_PROMPT); } - return(prompt->str); + return ast_str_buffer(prompt); } static char **ast_el_strtoarr(char *buf) diff --git a/main/cdr.c b/main/cdr.c index f48ddf38d..991b01a25 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -367,8 +367,7 @@ int ast_cdr_serialize_variables(struct ast_cdr *cdr, struct ast_str **buf, char char workspace[256]; int total = 0, x = 0, i; - (*buf)->used = 0; - (*buf)->str[0] = '\0'; + ast_str_reset(*buf); for (; cdr; cdr = recur ? cdr->next : NULL) { if (++x > 1) @@ -776,7 +775,7 @@ void ast_cdr_setdestchan(struct ast_cdr *cdr, const char *chann) } } -void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data) +void ast_cdr_setapp(struct ast_cdr *cdr, const char *app, const char *data) { for (; cdr; cdr = cdr->next) { diff --git a/main/cli.c b/main/cli.c index 063eeaae2..57f936b09 100644 --- a/main/cli.c +++ b/main/cli.c @@ -110,8 +110,9 @@ void ast_cli(int fd, const char *fmt, ...) res = ast_str_set_va(&buf, 0, fmt, ap); va_end(ap); - if (res != AST_DYNSTR_BUILD_FAILED) - ast_carefulwrite(fd, buf->str, strlen(buf->str), 100); + if (res != AST_DYNSTR_BUILD_FAILED) { + ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100); + } } unsigned int ast_debug_get_by_file(const char *file) @@ -637,9 +638,9 @@ static void print_uptimestr(int fd, struct timeval timeval, const char *prefix, ast_str_append(&out, 0, "%d minute%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec)); } x = timeval.tv_sec; - if (x > 0 || out->used == 0) /* if there is nothing, print 0 seconds */ + if (x > 0 || ast_str_strlen(out) == 0) /* if there is nothing, print 0 seconds */ ast_str_append(&out, 0, "%d second%s ", x, ESS(x)); - ast_cli(fd, "%s: %s\n", prefix, out->str); + ast_cli(fd, "%s: %s\n", prefix, ast_str_buffer(out)); } static struct ast_cli_entry *cli_next(struct ast_cli_entry *e) @@ -1258,7 +1259,7 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar { struct ast_channel *c=NULL; struct timeval now; - struct ast_str *out = ast_str_alloca(2048); + struct ast_str *out = ast_str_thread_get(&global_app_buf, 16); char cdrtime[256]; char nf[256], wf[256], rf[256]; long elapsed_seconds=0; @@ -1347,14 +1348,14 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)")); if (pbx_builtin_serialize_variables(c, &out)) - ast_cli(a->fd," Variables:\n%s\n", out->str); + ast_cli(a->fd," Variables:\n%s\n", ast_str_buffer(out)); if (c->cdr && ast_cdr_serialize_variables(c->cdr, &out, '=', '\n', 1)) - ast_cli(a->fd," CDR Variables:\n%s\n", out->str); + ast_cli(a->fd," CDR Variables:\n%s\n", ast_str_buffer(out)); #ifdef CHANNEL_TRACE trace_enabled = ast_channel_trace_is_enabled(c); ast_cli(a->fd, " Context Trace: %s\n", trace_enabled ? "Enabled" : "Disabled"); if (trace_enabled && ast_channel_trace_serialize(c, &out)) - ast_cli(a->fd, " Trace:\n%s\n", out->str); + ast_cli(a->fd, " Trace:\n%s\n", ast_str_buffer(out)); #endif ast_channel_unlock(c); return CLI_SUCCESS; diff --git a/main/config.c b/main/config.c index 5fad1c51b..33a8ecb7b 100644 --- a/main/config.c +++ b/main/config.c @@ -106,19 +106,23 @@ static void CB_ADD_LEN(struct ast_str **cb, const char *str, int len) static void CB_RESET(struct ast_str *cb, struct ast_str *llb) { - if (cb) - cb->used = 0; - if (llb) - llb->used = 0; + if (cb) { + ast_str_reset(cb); + } + if (llb) { + ast_str_reset(llb); + } } -static struct ast_comment *ALLOC_COMMENT(const struct ast_str *buffer) +static struct ast_comment *ALLOC_COMMENT(struct ast_str *buffer) { struct ast_comment *x = NULL; - if (buffer && buffer->used) - x = ast_calloc(1, sizeof(*x) + buffer->used + 1); - if (x) - strcpy(x->cmt, buffer->str); + if (!buffer || !ast_str_strlen(buffer)) { + return NULL; + } + if ((x = ast_calloc(1, sizeof(*x) + ast_str_strlen(buffer) + 1))) { + strcpy(x->cmt, ast_str_buffer(buffer)); /* SAFE */ + } return x; } @@ -132,20 +136,21 @@ struct inclfile { static int hash_string(const void *obj, const int flags) { - char *str = ((struct inclfile*)obj)->fname; + char *str = ((struct inclfile *) obj)->fname; int total; - for (total=0; *str; str++) { + for (total = 0; *str; str++) { unsigned int tmp = total; total <<= 1; /* multiply by 2 */ total += tmp; /* multiply by 3 */ total <<= 2; /* multiply by 12 */ total += tmp; /* multiply by 13 */ - total += ((unsigned int)(*str)); + total += ((unsigned int) (*str)); } - if (total < 0) + if (total < 0) { total = -total; + } return total; } @@ -1125,7 +1130,8 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, ast_str_set(str, 0, "%s", replace->value); ast_str_append(str, 0, "%s", c); - ast_variable_update(*cat, replace->name, ast_strip((*str)->str), replace->value, object); + ast_str_trim_blanks(*str); + ast_variable_update(*cat, replace->name, ast_skip_blanks(ast_str_buffer(*str)), replace->value, object); } else if (c) { *c = 0; c++; @@ -1320,9 +1326,9 @@ static struct ast_config *config_text_file_load(const char *database, const char while (!feof(f)) { lineno++; if (fgets(buf, sizeof(buf), f)) { - if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && lline_buffer && lline_buffer->used) { - CB_ADD(&comment_buffer, lline_buffer->str); /* add the current lline buffer to the comment buffer */ - lline_buffer->used = 0; /* erase the lline buffer */ + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && lline_buffer && ast_str_strlen(lline_buffer)) { + CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer)); /* add the current lline buffer to the comment buffer */ + ast_str_reset(lline_buffer); /* erase the lline buffer */ } new_buf = buf; @@ -1331,14 +1337,14 @@ static struct ast_config *config_text_file_load(const char *database, const char else process_buf = buf; - if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used && (ast_strlen_zero(buf) || strlen(buf) == strspn(buf," \t\n\r"))) { + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer) && (ast_strlen_zero(buf) || strlen(buf) == strspn(buf," \t\n\r"))) { /* blank line? really? Can we add it to an existing comment and maybe preserve inter- and post- comment spacing? */ CB_ADD(&comment_buffer, "\n"); /* add a newline to the comment buffer */ continue; /* go get a new line, then */ } while ((comment_p = strchr(new_buf, COMMENT_META))) { - if ((comment_p > new_buf) && (*(comment_p-1) == '\\')) { + if ((comment_p > new_buf) && (*(comment_p - 1) == '\\')) { /* Escaped semicolons aren't comments. */ new_buf = comment_p + 1; } else if (comment_p[1] == COMMENT_TAG && comment_p[2] == COMMENT_TAG && (comment_p[3] != '-')) { @@ -1403,30 +1409,30 @@ static struct ast_config *config_text_file_load(const char *database, const char } /* end of file-- anything in a comment buffer? */ if (last_cat) { - if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used ) { - if (lline_buffer && lline_buffer->used) { - CB_ADD(&comment_buffer, lline_buffer->str); /* add the current lline buffer to the comment buffer */ - lline_buffer->used = 0; /* erase the lline buffer */ + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) { + if (lline_buffer && ast_str_strlen(lline_buffer)) { + CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer)); /* add the current lline buffer to the comment buffer */ + ast_str_reset(lline_buffer); /* erase the lline buffer */ } last_cat->trailing = ALLOC_COMMENT(comment_buffer); } } else if (last_var) { - if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used ) { - if (lline_buffer && lline_buffer->used) { - CB_ADD(&comment_buffer, lline_buffer->str); /* add the current lline buffer to the comment buffer */ - lline_buffer->used = 0; /* erase the lline buffer */ + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) { + if (lline_buffer && ast_str_strlen(lline_buffer)) { + CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer)); /* add the current lline buffer to the comment buffer */ + ast_str_reset(lline_buffer); /* erase the lline buffer */ } last_var->trailing = ALLOC_COMMENT(comment_buffer); } } else { - if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used) { - ast_debug(1, "Nothing to attach comments to, discarded: %s\n", comment_buffer->str); + if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) { + ast_debug(1, "Nothing to attach comments to, discarded: %s\n", ast_str_buffer(comment_buffer)); } } if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) CB_RESET(comment_buffer, lline_buffer); - fclose(f); + fclose(f); } while (0); if (comment) { ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment - 1]); diff --git a/main/http.c b/main/http.c index 5c3aa7895..237ad6643 100644 --- a/main/http.c +++ b/main/http.c @@ -755,14 +755,14 @@ static void *httpd_helper_thread(void *data) * append a random variable to your GET request. Ex: 'something.html?r=109987734' */ if (!contentlength) { /* opaque body ? just dump it hoping it is properly formatted */ - fprintf(ser->f, "%s", out->str); + fprintf(ser->f, "%s", ast_str_buffer(out)); } else { - char *tmp = strstr(out->str, "\r\n\r\n"); + char *tmp = strstr(ast_str_buffer(out), "\r\n\r\n"); if (tmp) { fprintf(ser->f, "Content-length: %d\r\n", contentlength); /* first write the header, then the body */ - if (fwrite(out->str, 1, (tmp + 4 - out->str), ser->f) != tmp + 4 - out->str) { + if (fwrite(ast_str_buffer(out), 1, (tmp + 4 - ast_str_buffer(out)), ser->f) != tmp + 4 - ast_str_buffer(out)) { ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); } if (fwrite(tmp + 4, 1, contentlength, ser->f) != contentlength ) { diff --git a/main/logger.c b/main/logger.c index b42a21b19..8a577ed38 100644 --- a/main/logger.c +++ b/main/logger.c @@ -1106,8 +1106,8 @@ void ast_log(int level, const char *file, int line, const char *function, const result = ast_str_set_va(&buf, BUFSIZ, fmt, ap); /* XXX BUFSIZ ? */ va_end(ap); if (result != AST_DYNSTR_BUILD_FAILED) { - term_filter_escapes(buf->str); - fputs(buf->str, stdout); + term_filter_escapes(ast_str_buffer(buf)); + fputs(ast_str_buffer(buf), stdout); } } return; @@ -1140,7 +1140,7 @@ void ast_log(int level, const char *file, int line, const char *function, const return; /* Copy string over */ - strcpy(logmsg->str, buf->str); + strcpy(logmsg->str, ast_str_buffer(buf)); /* Set type to be normal */ logmsg->type = LOGMSG_NORMAL; @@ -1269,7 +1269,7 @@ void __ast_verbose_ap(const char *file, int line, const char *func, const char * if (!(logmsg = ast_calloc(1, sizeof(*logmsg) + res + 1))) return; - strcpy(logmsg->str, buf->str); + strcpy(logmsg->str, ast_str_buffer(buf)); ast_log(__LOG_VERBOSE, file, line, func, "%s", logmsg->str + 1); diff --git a/main/manager.c b/main/manager.c index 47a7f42b9..f3cda9e82 100644 --- a/main/manager.c +++ b/main/manager.c @@ -347,7 +347,7 @@ static char *authority_to_str(int authority, struct ast_str **res) int i; char *sep = ""; - (*res)->used = 0; + ast_str_reset(*res); for (i = 0; i < ARRAY_LEN(perms) - 1; i++) { if (authority & perms[i].num) { ast_str_append(res, 0, "%s%s", sep, perms[i].label); @@ -355,10 +355,10 @@ static char *authority_to_str(int authority, struct ast_str **res) } } - if ((*res)->used == 0) /* replace empty string with something sensible */ + if (ast_str_strlen(*res) == 0) /* replace empty string with something sensible */ ast_str_append(res, 0, "<none>"); - return (*res)->str; + return ast_str_buffer(*res); } /*! Tells you if smallstr exists inside bigstr @@ -950,10 +950,11 @@ void astman_append(struct mansession *s, const char *fmt, ...) ast_str_set_va(&buf, 0, fmt, ap); va_end(ap); - if (s->f != NULL) - send_string(s, buf->str); - else + if (s->f != NULL) { + send_string(s, ast_str_buffer(buf)); + } else { ast_verbose("fd == -1 in astman_append, should not happen\n"); + } } /*! \note NOTE: XXX this comment is unclear and possibly wrong. @@ -1525,11 +1526,12 @@ static int action_createconfig(struct mansession *s, const struct message *m) ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR); ast_str_append(&filepath, 0, "%s", fn); - if ((fd = open(filepath->str, O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) { + if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) { close(fd); astman_send_ack(s, m, "New configuration file created successfully"); - } else + } else { astman_send_error(s, m, strerror(errno)); + } return 0; } @@ -1939,7 +1941,7 @@ static int action_status(struct mansession *s, const struct message *m) c->accountcode, c->_state, ast_state2str(c->_state), c->context, - c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, str->str, idText); + c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText); } else { astman_append(s, "Event: Status\r\n" @@ -1958,7 +1960,7 @@ static int action_status(struct mansession *s, const struct message *m) S_OR(c->cid.cid_num, "<unknown>"), S_OR(c->cid.cid_name, "<unknown>"), c->accountcode, - ast_state2str(c->_state), bridge, c->uniqueid, str->str, idText); + ast_state2str(c->_state), bridge, c->uniqueid, ast_str_buffer(str), idText); } ast_channel_unlock(c); if (!all) @@ -3268,7 +3270,7 @@ int __manager_event(int category, const char *event, ast_str_append(&buf, 0, "\r\n"); - append_event(buf->str, category); + append_event(ast_str_buffer(buf), category); /* Wake up any sleeping sessions */ AST_LIST_LOCK(&sessions); @@ -3289,7 +3291,7 @@ int __manager_event(int category, const char *event, AST_RWLIST_RDLOCK(&manager_hooks); AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) { - hook->helper(category, event, buf->str); + hook->helper(category, event, ast_str_buffer(buf)); } AST_RWLIST_UNLOCK(&manager_hooks); diff --git a/main/pbx.c b/main/pbx.c index 37ab4db7e..8fb1393ea 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -1504,7 +1504,7 @@ void log_match_char_tree(struct match_char *node, char *prefix) ast_str_set(&my_prefix, 0, "%s+ ", prefix); if (node->next_char) - log_match_char_tree(node->next_char, my_prefix->str); + log_match_char_tree(node->next_char, ast_str_buffer(my_prefix)); if (node->alt_char) log_match_char_tree(node->alt_char, prefix); @@ -1533,7 +1533,7 @@ static void cli_match_char_tree(struct match_char *node, char *prefix, int fd) ast_str_set(&my_prefix, 0, "%s+ ", prefix); if (node->next_char) - cli_match_char_tree(node->next_char, my_prefix->str, fd); + cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd); if (node->alt_char) cli_match_char_tree(node->alt_char, prefix, fd); @@ -2525,8 +2525,8 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, break; } else if (eval) { /* Substitute variables now */ - pbx_substitute_variables_helper(chan, osw, tmpdata->str, tmpdata->len); - datap = tmpdata->str; + pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); + datap = ast_str_buffer(tmpdata); } else { datap = osw; } @@ -2695,7 +2695,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, ast_log(LOG_WARNING, "Can't evaluate switch?!"); continue; } - pbx_substitute_variables_helper(chan, sw->data, tmpdata->str, tmpdata->len); + pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata)); } /* equivalent of extension_match_core() at the switch level */ @@ -2705,7 +2705,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, aswf = asw->matchmore; else /* action == E_MATCH */ aswf = asw->exists; - datap = sw->eval ? tmpdata->str : sw->data; + datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data; if (!aswf) res = 0; else { @@ -3351,11 +3351,11 @@ int ast_func_write(struct ast_channel *chan, const char *function, const char *v return -1; } -static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count) +void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used) { /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */ char *cp4; - const char *tmp, *whereweare; + const char *tmp, *whereweare, *orig_cp2 = cp2; int length, offset, offset2, isfunction; char *workspace = NULL; char *ltmp = NULL, *var = NULL; @@ -3435,10 +3435,11 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v /* Substitute if necessary */ if (needsub) { + size_t used; if (!ltmp) ltmp = alloca(VAR_BUF_SIZE); - pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); + pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); vars = ltmp; } else { vars = var; @@ -3522,10 +3523,11 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v /* Substitute if necessary */ if (needsub) { + size_t used; if (!ltmp) ltmp = alloca(VAR_BUF_SIZE); - pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1); + pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used); vars = ltmp; } else { vars = var; @@ -3541,16 +3543,19 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v } } } + *used = cp2 - orig_cp2; } void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count) { - pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count); + size_t used; + pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used); } void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count) { - pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count); + size_t used; + pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used); } static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e) @@ -3725,7 +3730,7 @@ static int ast_extension_state2(struct ast_exten *e) ast_str_set(&hint, 0, "%s", ast_get_extension_app(e)); - rest = hint->str; /* One or more devices separated with a & character */ + rest = ast_str_buffer(hint); /* One or more devices separated with a & character */ while ( (cur = strsep(&rest, "&")) ) ast_devstate_aggregate_add(&agg, ast_device_state(cur)); @@ -6089,8 +6094,8 @@ static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cl } pbx_builtin_serialize_variables(chan, &vars); - if (vars->str) { - ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], vars->str); + if (ast_str_strlen(vars)) { + ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars)); } ast_channel_unlock(chan); return CLI_SUCCESS; @@ -6637,15 +6642,20 @@ static int lookup_name(const char *s, char *const names[], int max) { int i; - if (names) { + if (names && *s > '9') { for (i = 0; names[i]; i++) { - if (!strcasecmp(s, names[i])) - return i+1; + if (!strcasecmp(s, names[i])) { + return i; + } } - } else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { - return i; } - return 0; /* error return */ + + /* Allow months and weekdays to be specified as numbers, as well */ + if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) { + /* What the array offset would have been: "1" would be at offset 0 */ + return i - 1; + } + return -1; /* error return */ } /*! \brief helper function to return a range up to max (7, 12, 31 respectively). @@ -6653,131 +6663,104 @@ static int lookup_name(const char *s, char *const names[], int max) */ static unsigned get_range(char *src, int max, char *const names[], const char *msg) { - int s, e; /* start and ending position */ + int start, end; /* start and ending position */ unsigned int mask = 0; + char *part; /* Check for whole range */ if (ast_strlen_zero(src) || !strcmp(src, "*")) { - s = 0; - e = max - 1; - } else { + return (1 << max) - 1; + } + + while ((part = strsep(&src, "&"))) { /* Get start and ending position */ - char *c = strchr(src, '-'); - if (c) - *c++ = '\0'; + char *endpart = strchr(part, '-'); + if (endpart) { + *endpart++ = '\0'; + } /* Find the start */ - s = lookup_name(src, names, max); - if (!s) { - ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src); - return 0; + if ((start = lookup_name(part, names, max)) < 0) { + ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part); + continue; } - s--; - if (c) { /* find end of range */ - e = lookup_name(c, names, max); - if (!e) { - ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c); - return 0; + if (endpart) { /* find end of range */ + if ((end = lookup_name(endpart, names, max)) < 0) { + ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart); + continue; } - e--; - } else - e = s; - } - /* Fill the mask. Remember that ranges are cyclic */ - mask = 1 << e; /* initialize with last element */ - while (s != e) { - if (s >= max) { - s = 0; - mask |= (1 << s); } else { - mask |= (1 << s); - s++; + end = start; + } + /* Fill the mask. Remember that ranges are cyclic */ + mask |= (1 << end); /* initialize with last element */ + while (start != end) { + if (start >= max) { + start = 0; + } + mask |= (1 << start); + start++; } } return mask; } -/*! \brief store a bitmask of valid times, one bit each 2 minute */ +/*! \brief store a bitmask of valid times, one bit each 1 minute */ static void get_timerange(struct ast_timing *i, char *times) { - char *e; + char *endpart, *part; int x; - int s1, s2; - int e1, e2; - /* int cth, ctm; */ + int st_h, st_m; + int endh, endm; + int minute_start, minute_end; /* start disabling all times, fill the fields with 0's, as they may contain garbage */ memset(i->minmask, 0, sizeof(i->minmask)); - /* 2-minutes per bit, since the mask has only 32 bits :( */ + /* 1-minute per bit */ /* Star is all times */ if (ast_strlen_zero(times) || !strcmp(times, "*")) { - for (x = 0; x < 24; x++) + /* 48, because each hour takes 2 integers; 30 bits each */ + for (x = 0; x < 48; x++) { i->minmask[x] = 0x3fffffff; /* 30 bits */ + } return; } /* Otherwise expect a range */ - e = strchr(times, '-'); - if (!e) { - ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n"); - return; - } - *e++ = '\0'; - /* XXX why skip non digits ? */ - while (*e && !isdigit(*e)) - e++; - if (!*e) { - ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n"); - return; - } - if (sscanf(times, "%d:%d", &s1, &s2) != 2) { - ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times); - return; - } - if (sscanf(e, "%d:%d", &e1, &e2) != 2) { - ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e); - return; - } - /* XXX this needs to be optimized */ -#if 1 - s1 = s1 * 30 + s2/2; - if ((s1 < 0) || (s1 >= 24*30)) { - ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times); - return; - } - e1 = e1 * 30 + e2/2; - if ((e1 < 0) || (e1 >= 24*30)) { - ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e); - return; - } - /* Go through the time and enable each appropriate bit */ - for (x=s1;x != e1;x = (x + 1) % (24 * 30)) { - i->minmask[x/30] |= (1 << (x % 30)); - } - /* Do the last one */ - i->minmask[x/30] |= (1 << (x % 30)); -#else - for (cth = 0; cth < 24; cth++) { - /* Initialize masks to blank */ - i->minmask[cth] = 0; - for (ctm = 0; ctm < 30; ctm++) { - if ( - /* First hour with more than one hour */ - (((cth == s1) && (ctm >= s2)) && - ((cth < e1))) - /* Only one hour */ - || (((cth == s1) && (ctm >= s2)) && - ((cth == e1) && (ctm <= e2))) - /* In between first and last hours (more than 2 hours) */ - || ((cth > s1) && - (cth < e1)) - /* Last hour with more than one hour */ - || ((cth > s1) && - ((cth == e1) && (ctm <= e2))) - ) - i->minmask[cth] |= (1 << (ctm / 2)); + while ((part = strsep(×, "&"))) { + if (!(endpart = strchr(part, '-'))) { + if (sscanf(part, "%d:%d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { + ast_log(LOG_WARNING, "%s isn't a valid time.\n", part); + continue; + } + i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30)); + continue; + } + *endpart++ = '\0'; + /* why skip non digits? Mostly to skip spaces */ + while (*endpart && !isdigit(*endpart)) { + endpart++; + } + if (!*endpart) { + ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part); + continue; + } + if (sscanf(part, "%d:%d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) { + ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part); + continue; + } + if (sscanf(endpart, "%d:%d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) { + ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart); + continue; } + minute_start = st_h * 60 + st_m; + minute_end = endh * 60 + endm; + /* Go through the time and enable each appropriate bit */ + for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) { + i->minmask[x / 30] |= (1 << (x % 30)); + } + /* Do the last one */ + i->minmask[x / 30] |= (1 << (x % 30)); } -#endif /* All done */ return; } @@ -6865,7 +6848,7 @@ int ast_check_timing(const struct ast_timing *i) /* Now the tough part, we calculate if it fits in the right time based on min/hour */ - if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2)))) + if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min)))) return 0; /* If we got this far, then we're good */ @@ -8662,8 +8645,7 @@ int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **b if (!chan) return 0; - (*buf)->used = 0; - (*buf)->str[0] = '\0'; + ast_str_reset(*buf); ast_channel_lock(chan); diff --git a/main/strings.c b/main/strings.c new file mode 100644 index 000000000..1fd1cac54 --- /dev/null +++ b/main/strings.c @@ -0,0 +1,219 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2008, Digium, Inc. + * + * Tilghman Lesher <tlesher@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of +* the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief String manipulation API + * + * \author Tilghman Lesher <tilghman@digium.com> + */ + +/*** MAKEOPTS +<category name="MENUSELECT_CFLAGS" displayname="Compiler Flags" positive_output="yes" remove_on_change=".lastclean"> + <member name="DEBUG_OPAQUE" displayname="Change ast_str internals to detect improper usage"> + <defaultenabled>yes</defaultenabled> + </member> +</category> + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/strings.h" +#include "asterisk/pbx.h" + +/*! + * core handler for dynamic strings. + * This is not meant to be called directly, but rather through the + * various wrapper macros + * ast_str_set(...) + * ast_str_append(...) + * ast_str_set_va(...) + * ast_str_append_va(...) + */ + +int __ast_str_helper(struct ast_str **buf, size_t max_len, + int append, const char *fmt, va_list ap) +{ + int res, need; +#ifdef DEBUG_OPAQUE + int offset = (append && (*buf)->len2) ? (*buf)->used2 : 0; +#else + int offset = (append && (*buf)->len) ? (*buf)->used : 0; +#endif + va_list aq; + + do { + if (max_len < 0) { +#ifdef DEBUG_OPAQUE + max_len = (*buf)->len2; /* don't exceed the allocated space */ +#else + max_len = (*buf)->len; /* don't exceed the allocated space */ +#endif + } + /* + * Ask vsnprintf how much space we need. Remember that vsnprintf + * does not count the final '\0' so we must add 1. + */ + va_copy(aq, ap); +#ifdef DEBUG_OPAQUE + res = vsnprintf((*buf)->str2 + offset, (*buf)->len2 - offset, fmt, aq); +#else + res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, aq); +#endif + + need = res + offset + 1; + /* + * If there is not enough space and we are below the max length, + * reallocate the buffer and return a message telling to retry. + */ +#ifdef DEBUG_OPAQUE + if (need > (*buf)->len2 && (max_len == 0 || (*buf)->len2 < max_len) ) { +#else + if (need > (*buf)->len && (max_len == 0 || (*buf)->len < max_len) ) { +#endif + if (max_len && max_len < need) { /* truncate as needed */ + need = max_len; + } else if (max_len == 0) { /* if unbounded, give more room for next time */ + need += 16 + need / 4; + } + if (0) { /* debugging */ +#ifdef DEBUG_OPAQUE + ast_verbose("extend from %d to %d\n", (int)(*buf)->len2, need); +#else + ast_verbose("extend from %d to %d\n", (int)(*buf)->len, need); +#endif + } + if (ast_str_make_space(buf, need)) { +#ifdef DEBUG_OPAQUE + ast_verbose("failed to extend from %d to %d\n", (int)(*buf)->len2, need); +#else + ast_verbose("failed to extend from %d to %d\n", (int)(*buf)->len, need); +#endif + return AST_DYNSTR_BUILD_FAILED; + } +#ifdef DEBUG_OPAQUE + (*buf)->str2[offset] = '\0'; /* Truncate the partial write. */ +#else + (*buf)->str[offset] = '\0'; /* Truncate the partial write. */ +#endif + + /* Restart va_copy before calling vsnprintf() again. */ + va_end(aq); + continue; + } + break; + } while (1); + /* update space used, keep in mind the truncation */ +#ifdef DEBUG_OPAQUE + (*buf)->used2 = (res + offset > (*buf)->len2) ? (*buf)->len2 : res + offset; +#else + (*buf)->used = (res + offset > (*buf)->len) ? (*buf)->len : res + offset; +#endif + + return res; +} + +void ast_str_substitute_variables(struct ast_str **buf, size_t maxlen, struct ast_channel *chan, const char *template) +{ + int first = 1; +#ifdef DEBUG_OPAQUE + do { + ast_str_make_space(buf, maxlen ? maxlen : + (first ? strlen(template) * 2 : (*buf)->len2 * 2)); + pbx_substitute_variables_helper_full(chan, NULL, template, (*buf)->str2, (*buf)->len2 - 1, &((*buf)->used2)); + first = 0; + } while (maxlen == 0 && (*buf)->len2 - 5 < (*buf)->used2); +#else + do { + ast_str_make_space(buf, maxlen ? maxlen : + (first ? strlen(template) * 2 : (*buf)->len * 2)); + pbx_substitute_variables_helper_full(chan, NULL, template, (*buf)->str, (*buf)->len - 1, &((*buf)->used)); + first = 0; + } while (maxlen == 0 && (*buf)->len - 5 < (*buf)->used); +#endif +} + +char *__ast_str_helper2(struct ast_str **buf, size_t maxlen, const char *src, size_t maxsrc, int append, int escapecommas) +{ + int dynamic = 0; +#ifdef DEBUG_OPAQUE + char *ptr = append ? &((*buf)->str2[(*buf)->used2]) : (*buf)->str2; +#else + char *ptr = append ? &((*buf)->str[(*buf)->used]) : (*buf)->str; +#endif + + if (!maxlen) { + dynamic = 1; +#ifdef DEBUG_OPAQUE + maxlen = (*buf)->len2; +#else + maxlen = (*buf)->len; +#endif + } + + while (*src && maxsrc && maxlen && (!escapecommas || (maxlen - 1))) { + if (escapecommas && (*src == '\\' || *src == ',')) { + *ptr++ = '\\'; + maxlen--; +#ifdef DEBUG_OPAQUE + (*buf)->used2++; +#else + (*buf)->used++; +#endif + } + *ptr++ = *src++; + maxsrc--; + maxlen--; +#ifdef DEBUG_OPAQUE + (*buf)->used2++; +#else + (*buf)->used++; +#endif + if (dynamic && (!maxlen || (escapecommas && !(maxlen - 1)))) { +#ifdef DEBUG_OPAQUE + size_t old = (*buf)->len2; + if (ast_str_make_space(buf, (*buf)->len2 * 2)) { + /* If the buffer can't be extended, end it. */ + break; + } +#else + size_t old = (*buf)->len; + if (ast_str_make_space(buf, (*buf)->len * 2)) { + /* If the buffer can't be extended, end it. */ + break; + } +#endif + /* What we extended the buffer by */ + maxlen = old; + } + } + if (__builtin_expect(!(maxsrc && maxlen), 0)) { + ptr--; + } + *ptr = '\0'; +#ifdef DEBUG_OPAQUE + (*buf)->used2--; + return (*buf)->str2; +#else + (*buf)->used--; + return (*buf)->str; +#endif +} + diff --git a/main/tcptls.c b/main/tcptls.c index b93c53bae..b1c615aea 100644 --- a/main/tcptls.c +++ b/main/tcptls.c @@ -97,7 +97,7 @@ HOOK_T ast_tcptls_server_read(struct ast_tcptls_session_instance *tcptls_session return read(tcptls_session->fd, buf, count); } -HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_session, void *buf, size_t count) +HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_session, const void *buf, size_t count) { if (tcptls_session->fd == -1) { ast_log(LOG_ERROR, "server_write called with an fd of -1\n"); diff --git a/main/translate.c b/main/translate.c index 35c1968df..5d4fd0ace 100644 --- a/main/translate.c +++ b/main/translate.c @@ -598,7 +598,7 @@ static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, } } ast_str_append(&out, -1, "\n"); - ast_cli(a->fd, "%s", out->str); + ast_cli(a->fd, "%s", ast_str_buffer(out)); } AST_RWLIST_UNLOCK(&translators); return CLI_SUCCESS; diff --git a/main/utils.c b/main/utils.c index 71a4dcc00..6651f9281 100644 --- a/main/utils.c +++ b/main/utils.c @@ -1587,66 +1587,6 @@ int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed) return -1; } -/*! - * core handler for dynamic strings. - * This is not meant to be called directly, but rather through the - * various wrapper macros - * ast_str_set(...) - * ast_str_append(...) - * ast_str_set_va(...) - * ast_str_append_va(...) - */ - -int __ast_str_helper(struct ast_str **buf, size_t max_len, - int append, const char *fmt, va_list ap) -{ - int res, need; - int offset = (append && (*buf)->len) ? (*buf)->used : 0; - va_list aq; - - do { - if (max_len < 0) { - max_len = (*buf)->len; /* don't exceed the allocated space */ - } - /* - * Ask vsnprintf how much space we need. Remember that vsnprintf - * does not count the final '\0' so we must add 1. - */ - va_copy(aq, ap); - res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, aq); - - need = res + offset + 1; - /* - * If there is not enough space and we are below the max length, - * reallocate the buffer and return a message telling to retry. - */ - if (need > (*buf)->len && (max_len == 0 || (*buf)->len < max_len) ) { - if (max_len && max_len < need) { /* truncate as needed */ - need = max_len; - } else if (max_len == 0) { /* if unbounded, give more room for next time */ - need += 16 + need / 4; - } - if (0) { /* debugging */ - ast_verbose("extend from %d to %d\n", (int)(*buf)->len, need); - } - if (ast_str_make_space(buf, need)) { - ast_verbose("failed to extend from %d to %d\n", (int)(*buf)->len, need); - return AST_DYNSTR_BUILD_FAILED; - } - (*buf)->str[offset] = '\0'; /* Truncate the partial write. */ - - /* Restart va_copy before calling vsnprintf() again. */ - va_end(aq); - continue; - } - break; - } while (1); - /* update space used, keep in mind the truncation */ - (*buf)->used = (res + offset > (*buf)->len) ? (*buf)->len : res + offset; - - return res; -} - void ast_enable_packet_fragmentation(int sock) { #if defined(HAVE_IP_MTU_DISCOVER) diff --git a/main/xmldoc.c b/main/xmldoc.c index 3185a3a56..1cd3a0909 100644 --- a/main/xmldoc.c +++ b/main/xmldoc.c @@ -268,8 +268,7 @@ static char *xmldoc_string_wrap(const char *text, int columns, int maxdiff) backspace = xmldoc_foundspace_backward(text, i, maxdiff); if (backspace) { needtobreak = 1; - tmp->used -= backspace; - tmp->str[tmp->used] = '\0'; + ast_str_truncate(tmp, -backspace); i -= backspace + 1; continue; } @@ -300,7 +299,7 @@ static char *xmldoc_string_wrap(const char *text, int columns, int maxdiff) ast_str_append(&tmp, 0, "%c", text[i]); } - ret = ast_strdup(tmp->str); + ret = ast_strdup(ast_str_buffer(tmp)); ast_free(tmp); return ret; @@ -403,7 +402,7 @@ char *ast_xmldoc_printable(const char *bwinput, int withcolors) } /* Wrap the text, notice that string wrap will avoid cutting an ESC sequence. */ - wrapped = xmldoc_string_wrap(colorized->str, xmldoc_text_columns, xmldoc_max_diff); + wrapped = xmldoc_string_wrap(ast_str_buffer(colorized), xmldoc_text_columns, xmldoc_max_diff); ast_free(colorized); @@ -881,7 +880,7 @@ static char *xmldoc_parse_cmd_enumlist(struct ast_xml_node *fixnode) ast_str_append(¶mname, 0, "}"); - ret = ast_strdup(paramname->str); + ret = ast_strdup(ast_str_buffer(paramname)); ast_free(paramname); return ret; @@ -978,7 +977,7 @@ static char *xmldoc_get_syntax_cmd(struct ast_xml_node *fixnode, const char *nam } /* return a common string. */ - ret = ast_strdup(syntax->str); + ret = ast_strdup(ast_str_buffer(syntax)); ast_free(syntax); return ret; @@ -1084,9 +1083,9 @@ static int xmldoc_parse_para(struct ast_xml_node *node, const char *tabs, const if (tmpstr) { if (strcasecmp(ast_xml_node_get_name(tmp), "text")) { ast_str_append(buffer, 0, "<%s>%s</%s>", ast_xml_node_get_name(tmp), - tmpstr->str, ast_xml_node_get_name(tmp)); + ast_str_buffer(tmpstr), ast_xml_node_get_name(tmp)); } else { - ast_str_append(buffer, 0, "%s", tmpstr->str); + ast_str_append(buffer, 0, "%s", ast_str_buffer(tmpstr)); } ast_free(tmpstr); ret = 2; @@ -1245,8 +1244,8 @@ static int xmldoc_parse_variable(struct ast_xml_node *node, const char *tabs, st /* Cleanup text. */ xmldoc_string_cleanup(tmptext, &cleanstr, 1); ast_xml_free_text(tmptext); - if (cleanstr && cleanstr->used > 0) { - ast_str_append(buffer, 0, ":%s", cleanstr->str); + if (cleanstr && ast_str_strlen(cleanstr) > 0) { + ast_str_append(buffer, 0, ":%s", ast_str_buffer(cleanstr)); } ast_free(cleanstr); } @@ -1381,7 +1380,7 @@ char *ast_xmldoc_build_seealso(const char *type, const char *name) ast_xml_free_text(content); } - output = ast_strdup(outputstr->str); + output = ast_strdup(ast_str_buffer(outputstr)); ast_free(outputstr); return output; @@ -1631,13 +1630,13 @@ char *ast_xmldoc_build_arguments(const char *type, const char *name) xmldoc_parse_parameter(node, "", &ret); } - if (ret->used > 0) { + if (ast_str_strlen(ret) > 0) { /* remove last '\n' */ - if (ret->str[ret->used - 1] == '\n') { - ret->str[ret->used - 1] = '\0'; - ret->used--; + char *buf = ast_str_buffer(ret); + if (buf[ast_str_strlen(ret) - 1] == '\n') { + ast_str_truncate(ret, -1); } - retstr = ast_strdup(ret->str); + retstr = ast_strdup(ast_str_buffer(ret)); } ast_free(ret); @@ -1677,9 +1676,9 @@ static struct ast_str *xmldoc_get_formatted(struct ast_xml_node *node, int raw_o } /* remove last '\n' */ /* XXX Don't modify ast_str internals manually */ - if (ret->str[ret->used-1] == '\n') { - ret->str[ret->used-1] = '\0'; - ret->used--; + tmpstr = ast_str_buffer(ret); + if (tmpstr[ast_str_strlen(ret) - 1] == '\n') { + ast_str_truncate(ret, -1); } } return ret; @@ -1720,8 +1719,8 @@ static char *xmldoc_build_field(const char *type, const char *name, const char * } formatted = xmldoc_get_formatted(node, raw, raw); - if (formatted->used > 0) { - ret = ast_strdup(formatted->str); + if (ast_str_strlen(formatted) > 0) { + ret = ast_strdup(ast_str_buffer(formatted)); } ast_free(formatted); diff --git a/res/res_agi.c b/res/res_agi.c index cfdd48e39..bda3e79a4 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -377,13 +377,13 @@ int ast_agi_send(int fd, struct ast_channel *chan, char *fmt, ...) if (agidebug) { if (chan) { - ast_verbose("<%s>AGI Tx >> %s", chan->name, buf->str); + ast_verbose("<%s>AGI Tx >> %s", chan->name, ast_str_buffer(buf)); } else { - ast_verbose("AGI Tx >> %s", buf->str); + ast_verbose("AGI Tx >> %s", ast_str_buffer(buf)); } } - return ast_carefulwrite(fd, buf->str, buf->used, 100); + return ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100); } /* linked list of AGI commands ready to be executed by Async AGI */ diff --git a/res/res_clialiases.c b/res/res_clialiases.c index 1ea302401..156212f6b 100644 --- a/res/res_clialiases.c +++ b/res/res_clialiases.c @@ -101,7 +101,7 @@ static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_ if (!ast_strlen_zero(a->word)) { struct ast_str *real_cmd = ast_str_alloca(strlen(alias->real_cmd) + strlen(line) + 1); ast_str_append(&real_cmd, 0, "%s%s", alias->real_cmd, line); - generator = ast_cli_generator(real_cmd->str, a->word, a->n); + generator = ast_cli_generator(ast_str_buffer(real_cmd), a->word, a->n); } else { generator = ast_cli_generator(alias->real_cmd, a->word, a->n); } @@ -121,7 +121,7 @@ static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_ ast_str_append(&real_cmd, 0, " %s", a->argv[i - 1]); } - ast_cli_command(a->fd, real_cmd->str); + ast_cli_command(a->fd, ast_str_buffer(real_cmd)); } else { ast_cli_command(a->fd, alias->real_cmd); } diff --git a/res/res_config_curl.c b/res/res_config_curl.c index b159c768d..1d259c845 100644 --- a/res/res_config_curl.c +++ b/res/res_config_curl.c @@ -88,7 +88,7 @@ static struct ast_variable *realtime_curl(const char *url, const char *unused, v va_end(ap); ast_str_append(&query, 0, ")}"); - pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize); + pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize); /* Remove any trailing newline characters */ if ((stringp = strchr(buffer, '\r')) || (stringp = strchr(buffer, '\n'))) @@ -170,7 +170,7 @@ static struct ast_config *realtime_multi_curl(const char *url, const char *unuse ast_str_append(&query, 0, ")}"); /* Do the CURL query */ - pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize); + pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize); if (!(cfg = ast_config_new())) goto exit_multi; @@ -258,7 +258,7 @@ static int update_curl(const char *url, const char *unused, const char *keyfield va_end(ap); ast_str_append(&query, 0, ")}"); - pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize); + pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize); /* Line oriented output */ stringp = buffer; @@ -321,7 +321,7 @@ static int update2_curl(const char *url, const char *unused, va_list ap) ast_str_append(&query, 0, ")}"); /* TODO: Make proxies work */ - pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize); + pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize); /* Line oriented output */ stringp = buffer; @@ -385,7 +385,7 @@ static int store_curl(const char *url, const char *unused, va_list ap) va_end(ap); ast_str_append(&query, 0, ")}"); - pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize); + pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize); stringp = buffer; while (*stringp <= ' ') @@ -452,7 +452,7 @@ static int destroy_curl(const char *url, const char *unused, const char *keyfiel va_end(ap); ast_str_append(&query, 0, ")}"); - pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize); + pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize); /* Line oriented output */ stringp = buffer; @@ -511,7 +511,7 @@ static int require_curl(const char *url, const char *unused, va_list ap) va_end(ap); ast_str_append(&query, 0, ")}"); - pbx_substitute_variables_helper(NULL, query->str, buffer, sizeof(buffer)); + pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, sizeof(buffer)); return atoi(buffer); } @@ -544,7 +544,7 @@ static struct ast_config *config_curl(const char *url, const char *unused, const ast_str_set(&query, 0, "${CURL(%s/static?file=%s)}", url, buf1); /* Do the CURL query */ - pbx_substitute_variables_helper(NULL, query->str, buffer, bufsize); + pbx_substitute_variables_helper(NULL, ast_str_buffer(query), buffer, bufsize); /* Line oriented output */ stringp = buffer; diff --git a/res/res_config_ldap.c b/res/res_config_ldap.c index 8fbfef897..7ff9015f2 100644 --- a/res/res_config_ldap.c +++ b/res/res_config_ldap.c @@ -789,7 +789,7 @@ static struct ast_variable **realtime_ldap_base_ap(unsigned int *entries_count_p do { /* freeing ldap_result further down */ result = ldap_search_ext_s(ldapConn, clean_basedn, - LDAP_SCOPE_SUBTREE, filter->str, NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, + LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &ldap_result_msg); if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) { ast_log(LOG_DEBUG, "Failed to query database. Try %d/10\n", @@ -808,7 +808,7 @@ static struct ast_variable **realtime_ldap_base_ap(unsigned int *entries_count_p if (result != LDAP_SUCCESS) { ast_log(LOG_WARNING, "Failed to query database. Check debug for more info.\n"); - ast_log(LOG_WARNING, "Query: %s\n", filter->str); + ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter)); ast_log(LOG_WARNING, "Query Failed because: %s\n", ldap_err2string(result)); } else { /* this is where we create the variables from the search result @@ -818,7 +818,7 @@ static struct ast_variable **realtime_ldap_base_ap(unsigned int *entries_count_p vars = realtime_ldap_result_to_vars(table_config, ldap_result_msg, entries_count_ptr); } else { ast_debug(1, "Could not find any entry matching %s in base dn %s.\n", - filter->str, clean_basedn); + ast_str_buffer(filter), clean_basedn); } ldap_msgfree(ldap_result_msg); @@ -1246,7 +1246,7 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a do { /* freeing ldap_result further down */ result = ldap_search_ext_s(ldapConn, clean_basedn, - LDAP_SCOPE_SUBTREE, filter->str, NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, + LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &ldap_result_msg); if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) { ast_log(LOG_WARNING, "Failed to query database. Try %d/3\n", @@ -1266,7 +1266,7 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a if (result != LDAP_SUCCESS) { ast_log(LOG_WARNING, "Failed to query directory. Check debug for more info.\n"); - ast_log(LOG_WARNING, "Query: %s\n", filter->str); + ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter)); ast_log(LOG_WARNING, "Query Failed because: %s\n", ldap_err2string(result)); @@ -1433,7 +1433,7 @@ static int update2_ldap(const char *basedn, const char *table_name, va_list ap) do { /* freeing ldap_result further down */ result = ldap_search_ext_s(ldapConn, clean_basedn, - LDAP_SCOPE_SUBTREE, filter->str, NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, + LDAP_SCOPE_SUBTREE, ast_str_buffer(filter), NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &ldap_result_msg); if (result != LDAP_SUCCESS && is_ldap_connect_error(result)) { ast_log(LOG_WARNING, "Failed to query database. Try %d/3\n", @@ -1453,7 +1453,7 @@ static int update2_ldap(const char *basedn, const char *table_name, va_list ap) if (result != LDAP_SUCCESS) { ast_log(LOG_WARNING, "Failed to query directory. Check debug for more info.\n"); - ast_log(LOG_WARNING, "Query: %s\n", filter->str); + ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter)); ast_log(LOG_WARNING, "Query Failed because: %s\n", ldap_err2string(result)); diff --git a/res/res_config_odbc.c b/res/res_config_odbc.c index a815a9de9..8de431475 100644 --- a/res/res_config_odbc.c +++ b/res/res_config_odbc.c @@ -555,9 +555,9 @@ static SQLHSTMT update2_prepare(struct odbc_obj *obj, void *data) /* Done with the table metadata */ ast_odbc_release_table(tableptr); - res = SQLPrepare(stmt, (unsigned char *)sql->str, SQL_NTS); + res = SQLPrepare(stmt, (unsigned char *)ast_str_buffer(sql), SQL_NTS); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql->str); + ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", ast_str_buffer(sql)); SQLFreeHandle(SQL_HANDLE_STMT, stmt); return NULL; } @@ -606,7 +606,7 @@ static int update2_odbc(const char *database, const char *table, va_list ap) if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { /* Since only a single thread can access this memory, we can retrieve what would otherwise be lost. */ sql = ast_str_thread_get(&sql_buf, 16); - ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n", sql->str); + ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n", ast_str_buffer(sql)); return -1; } diff --git a/res/res_config_pgsql.c b/res/res_config_pgsql.c index a22f03a6d..877901243 100644 --- a/res/res_config_pgsql.c +++ b/res/res_config_pgsql.c @@ -94,10 +94,10 @@ static struct ast_cli_entry cli_realtime[] = { #define ESCAPE_STRING(buffer, stringname) \ do { \ int len; \ - if ((len = strlen(stringname)) > (buffer->len - 1) / 2) { \ + if ((len = strlen(stringname)) > (ast_str_size(buffer) - 1) / 2) { \ ast_str_make_space(&buffer, len * 2 + 1); \ } \ - PQescapeStringConn(pgsqlConn, buffer->str, stringname, len, &pgresult); \ + PQescapeStringConn(pgsqlConn, ast_str_buffer(buffer), stringname, len, &pgresult); \ } while (0) static void destroy_table(struct tables *table) @@ -137,7 +137,7 @@ static struct tables *find_table(const char *tablename) /* Not found, scan the table */ ast_str_set(&sql, 0, "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod FROM pg_class c, pg_type t, pg_attribute a LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid AND d.adnum = a.attnum WHERE c.oid = a.attrelid AND a.atttypid = t.oid AND (a.attnum > 0) AND c.relname = '%s' ORDER BY c.relname, attnum", tablename); - result = PQexec(pgsqlConn, sql->str); + result = PQexec(pgsqlConn, ast_str_buffer(sql)); ast_debug(1, "Query of table structure complete. Now retrieving results.\n"); if (PQresultStatus(result) != PGRES_TUPLES_OK) { pgerror = PQresultErrorMessage(result); @@ -260,7 +260,7 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab return NULL; } - ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", tablename, newparam, op, escapebuf->str); + ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", tablename, newparam, op, ast_str_buffer(escapebuf)); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); if (!strchr(newparam, ' ')) @@ -275,7 +275,7 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab return NULL; } - ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, escapebuf->str); + ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, ast_str_buffer(escapebuf)); } va_end(ap); @@ -286,10 +286,10 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab return NULL; } - if (!(result = PQexec(pgsqlConn, sql->str))) { + if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", tablename, database); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return NULL; @@ -300,7 +300,7 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", tablename, database); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); @@ -308,7 +308,7 @@ static struct ast_variable *realtime_pgsql(const char *database, const char *tab } } - ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql->str); + ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, ast_str_buffer(sql)); if ((num_rows = PQntuples(result)) > 0) { int i = 0; @@ -410,7 +410,7 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char return NULL; } - ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, escapebuf->str); + ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, ast_str_buffer(escapebuf)); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); if (!strchr(newparam, ' ')) @@ -425,7 +425,7 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char return NULL; } - ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, escapebuf->str); + ast_str_append(&sql, 0, " AND %s%s '%s'", newparam, op, ast_str_buffer(escapebuf)); } if (initfield) { @@ -441,10 +441,10 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char return NULL; } - if (!(result = PQexec(pgsqlConn, sql->str))) { + if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query %s@%s. Check debug for more info.\n", table, database); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return NULL; @@ -455,7 +455,7 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query %s@%s. Check debug for more info.\n", table, database); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); @@ -463,7 +463,7 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char } } - ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql->str); + ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, ast_str_buffer(sql)); if ((num_rows = PQntuples(result)) > 0) { int numFields = PQnfields(result); @@ -570,7 +570,7 @@ static int update_pgsql(const char *database, const char *tablename, const char release_table(table); return -1; } - ast_str_set(&sql, 0, "UPDATE %s SET %s = '%s'", tablename, newparam, escapebuf->str); + ast_str_set(&sql, 0, "UPDATE %s SET %s = '%s'", tablename, newparam, ast_str_buffer(escapebuf)); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); @@ -588,7 +588,7 @@ static int update_pgsql(const char *database, const char *tablename, const char return -1; } - ast_str_append(&sql, 0, ", %s = '%s'", newparam, escapebuf->str); + ast_str_append(&sql, 0, ", %s = '%s'", newparam, ast_str_buffer(escapebuf)); } va_end(ap); release_table(table); @@ -600,9 +600,9 @@ static int update_pgsql(const char *database, const char *tablename, const char return -1; } - ast_str_append(&sql, 0, " WHERE %s = '%s'", keyfield, escapebuf->str); + ast_str_append(&sql, 0, " WHERE %s = '%s'", keyfield, ast_str_buffer(escapebuf)); - ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", ast_str_buffer(sql)); /* We now have our complete statement; Lets connect to the server and execute it. */ ast_mutex_lock(&pgsql_lock); @@ -611,10 +611,10 @@ static int update_pgsql(const char *database, const char *tablename, const char return -1; } - if (!(result = PQexec(pgsqlConn, sql->str))) { + if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); ast_free(sql); @@ -626,7 +626,7 @@ static int update_pgsql(const char *database, const char *tablename, const char && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); @@ -696,7 +696,7 @@ static int update2_pgsql(const char *database, const char *tablename, va_list ap ast_free(sql); return -1; } - ast_str_append(&where, 0, "%s %s='%s'", first ? "" : " AND", newparam, escapebuf->str); + ast_str_append(&where, 0, "%s %s='%s'", first ? "" : " AND", newparam, ast_str_buffer(escapebuf)); first = 0; } @@ -730,13 +730,13 @@ static int update2_pgsql(const char *database, const char *tablename, va_list ap return -1; } - ast_str_append(&sql, 0, "%s %s='%s'", first ? "" : ",", newparam, escapebuf->str); + ast_str_append(&sql, 0, "%s %s='%s'", first ? "" : ",", newparam, ast_str_buffer(escapebuf)); } release_table(table); - ast_str_append(&sql, 0, " %s", where->str); + ast_str_append(&sql, 0, " %s", ast_str_buffer(where)); - ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", ast_str_buffer(sql)); /* We now have our complete statement; connect to the server and execute it. */ ast_mutex_lock(&pgsql_lock); @@ -745,10 +745,10 @@ static int update2_pgsql(const char *database, const char *tablename, va_list ap return -1; } - if (!(result = PQexec(pgsqlConn, sql->str))) { + if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return -1; @@ -759,7 +759,7 @@ static int update2_pgsql(const char *database, const char *tablename, va_list ap && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); @@ -823,25 +823,25 @@ static int store_pgsql(const char *database, const char *table, va_list ap) /* 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 */ ESCAPE_STRING(buf, newparam); - ast_str_set(&sql1, 0, "INSERT INTO %s (%s", table, buf->str); + ast_str_set(&sql1, 0, "INSERT INTO %s (%s", table, ast_str_buffer(buf)); ESCAPE_STRING(buf, newval); - ast_str_set(&sql2, 0, ") VALUES ('%s'", buf->str); + ast_str_set(&sql2, 0, ") VALUES ('%s'", ast_str_buffer(buf)); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); ESCAPE_STRING(buf, newparam); - ast_str_append(&sql1, 0, ", %s", buf->str); + ast_str_append(&sql1, 0, ", %s", ast_str_buffer(buf)); ESCAPE_STRING(buf, newval); - ast_str_append(&sql2, 0, ", '%s'", buf->str); + ast_str_append(&sql2, 0, ", '%s'", ast_str_buffer(buf)); } va_end(ap); - ast_str_append(&sql1, 0, "%s)", sql2->str); + ast_str_append(&sql1, 0, "%s)", ast_str_buffer(sql2)); - ast_debug(1, "PostgreSQL RealTime: Insert SQL: %s\n", sql1->str); + ast_debug(1, "PostgreSQL RealTime: Insert SQL: %s\n", ast_str_buffer(sql1)); - if (!(result = PQexec(pgsqlConn, sql1->str))) { + if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql1)))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql1->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql1)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return -1; @@ -852,7 +852,7 @@ static int store_pgsql(const char *database, const char *table, va_list ap) && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql1->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql1)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); @@ -918,21 +918,21 @@ static int destroy_pgsql(const char *database, const char *table, const char *ke ESCAPE_STRING(buf1, keyfield); ESCAPE_STRING(buf2, lookup); - ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s = '%s'", table, buf1->str, buf2->str); + ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s = '%s'", table, ast_str_buffer(buf1), ast_str_buffer(buf2)); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); ESCAPE_STRING(buf1, newparam); ESCAPE_STRING(buf2, newval); - ast_str_append(&sql, 0, " AND %s = '%s'", buf1->str, buf2->str); + ast_str_append(&sql, 0, " AND %s = '%s'", ast_str_buffer(buf1), ast_str_buffer(buf2)); } va_end(ap); - ast_debug(1, "PostgreSQL RealTime: Delete SQL: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Delete SQL: %s\n", ast_str_buffer(sql)); - if (!(result = PQexec(pgsqlConn, sql->str))) { + if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return -1; @@ -943,7 +943,7 @@ static int destroy_pgsql(const char *database, const char *table, const char *ke && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); @@ -992,7 +992,7 @@ static struct ast_config *config_pgsql(const char *database, const char *table, "WHERE filename='%s' and commented=0" "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ", table, file); - ast_debug(1, "PostgreSQL RealTime: Static SQL: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Static SQL: %s\n", ast_str_buffer(sql)); /* We now have our complete statement; Lets connect to the server and execute it. */ ast_mutex_lock(&pgsql_lock); @@ -1001,10 +1001,10 @@ static struct ast_config *config_pgsql(const char *database, const char *table, return NULL; } - if (!(result = PQexec(pgsqlConn, sql->str))) { + if (!(result = PQexec(pgsqlConn, ast_str_buffer(sql)))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query '%s@%s'. Check debug for more info.\n", table, database); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return NULL; @@ -1015,7 +1015,7 @@ static struct ast_config *config_pgsql(const char *database, const char *table, && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql->str); + ast_debug(1, "PostgreSQL RealTime: Query: %s\n", ast_str_buffer(sql)); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); @@ -1163,16 +1163,16 @@ static int require_pgsql(const char *database, const char *tablename, va_list ap ast_mutex_lock(&pgsql_lock); if (!pgsql_reconnect(database)) { ast_mutex_unlock(&pgsql_lock); - ast_log(LOG_ERROR, "Unable to add column: %s\n", sql->str); + ast_log(LOG_ERROR, "Unable to add column: %s\n", ast_str_buffer(sql)); ast_free(sql); continue; } ast_debug(1, "About to run ALTER query on table '%s' to add column '%s'\n", tablename, elm); - result = PQexec(pgsqlConn, sql->str); + result = PQexec(pgsqlConn, ast_str_buffer(sql)); ast_debug(1, "Finished running ALTER query on table '%s'\n", tablename); if (PQresultStatus(result) != PGRES_COMMAND_OK) { - ast_log(LOG_ERROR, "Unable to add column: %s\n", sql->str); + ast_log(LOG_ERROR, "Unable to add column: %s\n", ast_str_buffer(sql)); } PQclear(result); ast_mutex_unlock(&pgsql_lock); @@ -1399,9 +1399,9 @@ static int pgsql_reconnect(const char *database) if (!ast_strlen_zero(dbpass)) ast_str_append(&connInfo, 0, " password=%s", dbpass); - ast_debug(1, "%u connInfo=%s\n", (unsigned int)connInfo->len, connInfo->str); - pgsqlConn = PQconnectdb(connInfo->str); - ast_debug(1, "%u connInfo=%s\n", (unsigned int)connInfo->len, connInfo->str); + ast_debug(1, "%u connInfo=%s\n", (unsigned int)ast_str_size(connInfo), ast_str_buffer(connInfo)); + pgsqlConn = PQconnectdb(ast_str_buffer(connInfo)); + ast_debug(1, "%u connInfo=%s\n", (unsigned int)ast_str_size(connInfo), ast_str_buffer(connInfo)); ast_free(connInfo); connInfo = NULL; diff --git a/res/res_config_sqlite.c b/res/res_config_sqlite.c index 756de0cd5..114aa803b 100644 --- a/res/res_config_sqlite.c +++ b/res/res_config_sqlite.c @@ -789,6 +789,7 @@ static int cdr_handler(struct ast_cdr *cdr) struct sqlite_cache_tables *tbl = find_table(cdr_table); struct sqlite_cache_columns *col; struct ast_str *sql1 = ast_str_create(160), *sql2 = ast_str_create(16); + int first = 1; if (!tbl) { ast_log(LOG_WARNING, "No such table: %s\n", cdr_table); @@ -805,33 +806,31 @@ static int cdr_handler(struct ast_cdr *cdr) continue; } if (sscanf(tmp, "%d", &scannum) == 1) { - ast_str_append(&sql1, 0, "%s,", col->name); - ast_str_append(&sql2, 0, "%d,", scannum); + ast_str_append(&sql1, 0, "%s%s", first ? "" : ",", col->name); + ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", scannum); } } else { ast_cdr_getvar(cdr, col->name, &tmp, workspace, sizeof(workspace), 0, 0); if (!tmp) { continue; } - ast_str_append(&sql1, 0, "%s,", col->name); + ast_str_append(&sql1, 0, "%s%s", first ? "" : ",", col->name); tmp = sqlite_mprintf("%Q", tmp); - ast_str_append(&sql2, 0, "%s,", tmp); + ast_str_append(&sql2, 0, "%s%s", first ? "" : ",", tmp); sqlite_freemem(tmp); } } release_table(tbl); - sql1->str[--sql1->used] = '\0'; - sql2->str[--sql2->used] = '\0'; - ast_str_append(&sql1, 0, "%s)", sql2->str); + ast_str_append(&sql1, 0, "%s)", ast_str_buffer(sql2)); ast_free(sql2); - ast_debug(1, "SQL query: %s\n", sql1->str); + ast_debug(1, "SQL query: %s\n", ast_str_buffer(sql1)); ast_mutex_lock(&mutex); RES_CONFIG_SQLITE_BEGIN - error = sqlite_exec(db, sql1->str, NULL, NULL, &errormsg); + error = sqlite_exec(db, ast_str_buffer(sql1), NULL, NULL, &errormsg); RES_CONFIG_SQLITE_END(error) ast_mutex_unlock(&mutex); @@ -1413,13 +1412,13 @@ static int realtime_update2_handler(const char *database, const char *table, first = 0; } - ast_str_append(&sql, 0, " %s", where->str); - ast_debug(1, "SQL query: %s\n", sql->str); + ast_str_append(&sql, 0, " %s", ast_str_buffer(where)); + ast_debug(1, "SQL query: %s\n", ast_str_buffer(sql)); ast_mutex_lock(&mutex); RES_CONFIG_SQLITE_BEGIN - error = sqlite_exec(db, sql->str, NULL, NULL, &errormsg); + error = sqlite_exec(db, ast_str_buffer(sql), NULL, NULL, &errormsg); RES_CONFIG_SQLITE_END(error) if (!error) { diff --git a/res/res_http_post.c b/res/res_http_post.c index 4a3156720..26daf7ad8 100644 --- a/res/res_http_post.c +++ b/res/res_http_post.c @@ -390,7 +390,7 @@ static struct ast_str *http_post_callback(struct ast_tcptls_session_instance *se NULL, "The was an error parsing the request."); } - if (!(message_count = process_message(message, post_dir->str))) { + if (!(message_count = process_message(message, ast_str_buffer(post_dir)))) { ast_log(LOG_ERROR, "Invalid MIME data, found no parts!\n"); g_object_unref(message); return ast_http_error((*status = 400), diff --git a/utils/Makefile b/utils/Makefile index 3a280dcad..a9067802c 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -77,7 +77,7 @@ clean: rm -f *.s *.i rm -f md5.c strcompat.c ast_expr2.c ast_expr2f.c pbx_ael.c pval.c hashtab.c rm -f aelparse.c aelbison.c conf2ael - rm -f utils.c threadstorage.c sha1.c astobj2.c hashtest2 hashtest refcounter + rm -f utils.c strings.c threadstorage.c sha1.c astobj2.c hashtest2 hashtest refcounter md5.c: $(ASTTOPDIR)/main/md5.c $(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@" @@ -149,6 +149,11 @@ utils.c: $(ASTTOPDIR)/main/utils.c $(CMD_PREFIX) cp "$<" "$@" utils.o: ASTCFLAGS+=-DSTANDALONE +strings.c: $(ASTTOPDIR)/main/strings.c + $(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@" + $(CMD_PREFIX) cp "$<" "$@" +strings.o: ASTCFLAGS+=-DSTANDALONE + sha1.c: $(ASTTOPDIR)/main/sha1.c $(ECHO_PREFIX) echo " [CP] $(subst $(ASTTOPDIR)/,,$<) -> $@" $(CMD_PREFIX) cp "$<" "$@" @@ -160,12 +165,12 @@ threadstorage.c: $(ASTTOPDIR)/main/threadstorage.c threadstorage.o: ASTCFLAGS+=-DSTANDALONE hashtest2.o: ASTCFLAGS+=-O0 -DSTANDALONE -hashtest2: hashtest2.o md5.o utils.o astobj2.o sha1.o strcompat.o threadstorage.o clicompat.o +hashtest2: hashtest2.o md5.o utils.o strings.o astobj2.o sha1.o strcompat.o threadstorage.o clicompat.o -hashtest: hashtest.o md5.o hashtab.o utils.o sha1.o strcompat.o threadstorage.o clicompat.o +hashtest: hashtest.o md5.o hashtab.o utils.o strings.o sha1.o strcompat.o threadstorage.o clicompat.o hashtest.o: ASTCFLAGS+=-O0 -DSTANDALONE -refcounter: refcounter.o md5.o hashtab.o utils.o sha1.o strcompat.o threadstorage.o clicompat.o +refcounter: refcounter.o md5.o hashtab.o utils.o strings.o sha1.o strcompat.o threadstorage.o clicompat.o refcounter.o: ASTCFLAGS+=-O0 -DSTANDALONE extconf.o: extconf.c diff --git a/utils/check_expr.c b/utils/check_expr.c index ab1cee19a..1d3fcfd0e 100644 --- a/utils/check_expr.c +++ b/utils/check_expr.c @@ -27,57 +27,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define AST_API_MODULE 1 #include "asterisk/lock.h" -#include "asterisk/strings.h" - -/* I included this from utils.c, so as not to have everything in that .c - file included */ -/*! - * core handler for dynamic strings. - * This is not meant to be called directly, but rather through the - * various wrapper macros - * ast_str_set(...) - * ast_str_append(...) - * ast_str_set_va(...) - * ast_str_append_va(...) - */ -int __attribute__((format(printf, 4, 0))) __ast_str_helper(struct ast_str **buf, size_t max_len, - int append, const char *fmt, va_list ap) -{ - int res, need; - int offset = (append && (*buf)->len) ? (*buf)->used : 0; - - if (max_len < 0) - max_len = (*buf)->len; /* don't exceed the allocated space */ - /* - * Ask vsnprintf how much space we need. Remember that vsnprintf - * does not count the final '\0' so we must add 1. - */ - res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, ap); - - need = res + offset + 1; - /* - * If there is not enough space and we are below the max length, - * reallocate the buffer and return a message telling to retry. - */ - if (need > (*buf)->len && (max_len == 0 || (*buf)->len < max_len) ) { - if (max_len && max_len < need) /* truncate as needed */ - need = max_len; - else if (max_len == 0) /* if unbounded, give more room for next time */ - need += 16 + need/4; - if (ast_str_make_space(buf, need)) { - return AST_DYNSTR_BUILD_FAILED; - } - (*buf)->str[offset] = '\0'; /* Truncate the partial write. */ - - /* va_end() and va_start() must be done before calling - * vsnprintf() again. */ - return AST_DYNSTR_BUILD_RETRY; - } - /* update space used, keep in mind the truncation */ - (*buf)->used = (res + offset > (*buf)->len) ? (*buf)->len : res + offset; - - return res; -} #ifndef DEBUG_THREADS enum ast_lock_type { AST_MUTEX, diff --git a/utils/hashtest.c b/utils/hashtest.c index 7ff7a55b2..16c5e1d9b 100644 --- a/utils/hashtest.c +++ b/utils/hashtest.c @@ -50,6 +50,11 @@ int64_t ast_mark(int prof_id, int x) } #endif +void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used); +void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used) +{ +} + struct ht_element { char *key; diff --git a/utils/hashtest2.c b/utils/hashtest2.c index 3b0c62699..a9fdf661b 100644 --- a/utils/hashtest2.c +++ b/utils/hashtest2.c @@ -59,6 +59,11 @@ struct ht_element char *val; }; +char *pbx_substitute_variables_helper_full(struct ast_channel *chan, struct varshead *head, const char *cp1, char *cp2, int maxlen, size_t *used); +char *pbx_substitute_variables_helper_full(struct ast_channel *chan, struct varshead *head, const char *cp1, char *cp2, int maxlen, size_t *used) +{ + return NULL; +} static int hash_string(const void *obj, const int flags) { diff --git a/utils/refcounter.c b/utils/refcounter.c index 4712c26b6..ddd5055d0 100644 --- a/utils/refcounter.c +++ b/utils/refcounter.c @@ -69,6 +69,11 @@ struct rc_obj /* short for refcounted object */ struct rc_hist *last; }; +void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used); +void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used) +{ +} + static unsigned int hashtab_hash_rc(const void *obj) { const struct rc_obj *rc = obj; |