diff --git a/medmysql.c b/medmysql.c index d9bf0f1..3ae6301 100644 --- a/medmysql.c +++ b/medmysql.c @@ -414,8 +414,35 @@ void medmysql_cleanup() medmysql_handler_close(&stats_handler); } +static void medmysql_buf_escape(MYSQL *m, size_t *buflen, const char *str, char *orig_dest, + size_t sql_buffer_size) +{ + size_t str_len = strlen(str); + char *dest = orig_dest; + + // verify buffer space requirements: string itself * 2, quotes '', optional "_latin1", null + if (*buflen + str_len * 2 + 2 + 7 + 1 >= sql_buffer_size) + abort(); + + if (!g_utf8_validate(str, str_len, NULL)) { + // force the string as latin1 + memcpy(dest, "_latin1'", 8); + dest += 8; + } + else + *dest++ = '\''; + + size_t esc_len = mysql_real_escape_string(m, dest, str, str_len); + dest += esc_len; + + *dest++ = '\''; + *dest = '\0'; + + *buflen += dest - orig_dest; +} + #define BUFPRINT(x...) buflen += sprintf(sql_buffer + buflen, x); if (buflen >= sql_buffer_size) abort() -#define BUFESCAPE(x) buflen += mysql_real_escape_string(med_handler->m, sql_buffer + buflen, x, strlen(x)); if (buflen >= sql_buffer_size) abort() +#define BUFESCAPE(x) medmysql_buf_escape(med_handler->m, &buflen, x, sql_buffer + buflen, sql_buffer_size) /**********************************************************************/ int medmysql_insert_records(med_entry_t *records, uint64_t count, const char *table) @@ -444,23 +471,23 @@ int medmysql_insert_records(med_entry_t *records, uint64_t count, const char *ta if (!e->redis) continue; - BUFPRINT("('"); + BUFPRINT("("); BUFESCAPE(e->sip_code); - BUFPRINT("','"); + BUFPRINT(","); BUFESCAPE(e->sip_reason); - BUFPRINT("','"); + BUFPRINT(","); BUFESCAPE(e->sip_method); - BUFPRINT("','"); + BUFPRINT(","); BUFESCAPE(e->callid); - BUFPRINT("','"); + BUFPRINT(","); BUFESCAPE(e->timestamp); - BUFPRINT("','%f','", e->unix_timestamp); + BUFPRINT(",'%f',", e->unix_timestamp); BUFESCAPE(e->src_leg); - BUFPRINT("','"); + BUFPRINT(","); BUFESCAPE(e->dst_leg); - BUFPRINT("','"); + BUFPRINT(","); BUFESCAPE(e->branch_id); - BUFPRINT("'),"); + BUFPRINT("),"); entries++; } @@ -706,7 +733,7 @@ int medmysql_delete_entries(const char *callid, struct medmysql_batches *batches } #define CDRPRINT(x) batches->cdrs.len += sprintf(batches->cdrs.str + batches->cdrs.len, x) -#define CDRESCAPE(x) batches->cdrs.len += mysql_real_escape_string(med_handler->m, batches->cdrs.str + batches->cdrs.len, x, strlen(x)) +#define CDRESCAPE(x) medmysql_buf_escape(med_handler->m, &batches->cdrs.len, x, batches->cdrs.str + batches->cdrs.len, PACKET_SIZE) /**********************************************************************/ static int medmysql_tag_record(GQueue *q, unsigned long cdr_id, unsigned long provider_id, @@ -801,67 +828,67 @@ int medmysql_insert_cdrs(cdr_entry_t *entries, uint64_t count, struct medmysql_b snprintf(str_source_accid, sizeof(str_source_accid), "%llu", (long long unsigned int) e->source_account_id); snprintf(str_dest_accid, sizeof(str_dest_accid), "%llu", (long long unsigned int) e->destination_account_id); - CDRPRINT("(NULL, now(), '"); + CDRPRINT("(NULL, now(), "); CDRESCAPE(e->source_user_id); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->source_provider_id); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->source_ext_subscriber_id); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->source_ext_contract_id); - CDRPRINT("',"); + CDRPRINT(","); CDRESCAPE(str_source_accid); - CDRPRINT(",'"); + CDRPRINT(","); CDRESCAPE(e->source_user); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->source_domain); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->source_cli); - CDRPRINT("',"); + CDRPRINT(","); CDRESCAPE(str_source_clir); - CDRPRINT(",'"); + CDRPRINT(","); CDRESCAPE(e->source_ip); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->destination_user_id); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->destination_provider_id); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->destination_ext_subscriber_id); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->destination_ext_contract_id); - CDRPRINT("',"); + CDRPRINT(","); CDRESCAPE(str_dest_accid); - CDRPRINT(",'"); + CDRPRINT(","); CDRESCAPE(e->destination_user); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->destination_domain); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->destination_user_in); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->destination_domain_in); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->destination_dialed); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->peer_auth_user); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->peer_auth_realm); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->call_type); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->call_status); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->call_code); - CDRPRINT("',"); + CDRPRINT(","); CDRESCAPE(str_init_time); CDRPRINT(","); CDRESCAPE(str_start_time); CDRPRINT(","); CDRESCAPE(str_duration); - CDRPRINT(",'"); + CDRPRINT(","); CDRESCAPE(e->call_id); - CDRPRINT("',"); + CDRPRINT(","); CDRESCAPE(str_source_carrier_cost); CDRPRINT(","); CDRESCAPE(str_source_reseller_cost); @@ -879,9 +906,8 @@ int medmysql_insert_cdrs(cdr_entry_t *entries, uint64_t count, struct medmysql_b { if(strnlen(e->source_gpp[gpp], sizeof(e->source_gpp[gpp])) > 0) { - CDRPRINT(",'"); + CDRPRINT(","); CDRESCAPE(e->source_gpp[gpp]); - CDRPRINT("'"); } else { @@ -892,9 +918,8 @@ int medmysql_insert_cdrs(cdr_entry_t *entries, uint64_t count, struct medmysql_b { if(strnlen(e->destination_gpp[gpp], sizeof(e->destination_gpp[gpp])) > 0) { - CDRPRINT(",'"); + CDRPRINT(","); CDRESCAPE(e->destination_gpp[gpp]); - CDRPRINT("'"); } else { @@ -902,21 +927,19 @@ int medmysql_insert_cdrs(cdr_entry_t *entries, uint64_t count, struct medmysql_b } } - CDRPRINT(",'"); + CDRPRINT(","); CDRESCAPE(e->source_lnp_prefix); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->destination_lnp_prefix); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->source_user_out); - CDRPRINT("','"); + CDRPRINT(","); CDRESCAPE(e->destination_user_out); - CDRPRINT("'"); if(strnlen(e->source_lnp_type, sizeof(e->source_lnp_type)) > 0) { - CDRPRINT(",'"); + CDRPRINT(","); CDRESCAPE(e->source_lnp_type); - CDRPRINT("'"); } else { @@ -925,9 +948,8 @@ int medmysql_insert_cdrs(cdr_entry_t *entries, uint64_t count, struct medmysql_b if(strnlen(e->destination_lnp_type, sizeof(e->destination_lnp_type)) > 0) { - CDRPRINT(",'"); + CDRPRINT(","); CDRESCAPE(e->destination_lnp_type); - CDRPRINT("'"); } else { @@ -1299,7 +1321,7 @@ static int medmysql_flush_med_str(struct medmysql_str *str, const medmysql_batch str->str[str->len] = '\0'; L_DEBUG("SQL flush med str\n"); - L_DEBUG("SQL: %.*s\n", str->len, str->str); + L_DEBUG("SQL: %.*s\n", (int) str->len, str->str); if (def->sql_finish_string) str->len += sprintf(str->str + str->len, "%s", def->sql_finish_string); diff --git a/medmysql.h b/medmysql.h index 6d5aca5..57cd393 100644 --- a/medmysql.h +++ b/medmysql.h @@ -12,7 +12,7 @@ struct medmysql_str { char str[PACKET_SIZE]; - unsigned int len; + size_t len; }; struct medmysql_batches {