Merge "res_pjsip: Fix mwi_subscribe_replaces_unsolicited type mismatch"
[asterisk/asterisk.git] / addons / res_config_mysql.c
index bf38a4e..edd9385 100644 (file)
@@ -33,7 +33,6 @@
 #include <sys/stat.h>
 
 #include <mysql/mysql.h>
-#include <mysql/mysql_version.h>
 #include <mysql/errmsg.h>
 
 #include "asterisk/channel.h"
@@ -303,6 +302,11 @@ static char *decode_chunk(char *chunk)
        return orig;
 }
 
+#define IS_SQL_LIKE_CLAUSE(x) ((x) && ast_ends_with(x, " LIKE"))
+
+/* MySQL requires us to escape the escape... yo dawg */
+static char *ESCAPE_CLAUSE = " ESCAPE '\\\\'";
+
 static struct ast_variable *realtime_mysql(const char *database, const char *table, const struct ast_variable *rt_fields)
 {
        struct mysql_conn *dbh;
@@ -315,6 +319,7 @@ static struct ast_variable *realtime_mysql(const char *database, const char *tab
        char *stringp;
        char *chunk;
        char *op;
+       char *escape = "";
        const struct ast_variable *field = rt_fields;
        struct ast_variable *var=NULL, *prev=NULL;
 
@@ -345,20 +350,29 @@ static struct ast_variable *realtime_mysql(const char *database, const char *tab
        /* Create the first part of the query using the first parameter/value pairs we just extracted
           If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
 
-       if (!strchr(field->name, ' ')) 
-               op = " ="; 
-       else 
+       if (!strchr(field->name, ' ')) {
+               op = " =";
+       } else {
                op = "";
+               if (IS_SQL_LIKE_CLAUSE(field->name)) {
+                       escape = ESCAPE_CLAUSE;
+               }
+       }
 
        ESCAPE_STRING(buf, field->value);
-       ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", table, field->name, op, ast_str_buffer(buf));
+       ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'%s", table, field->name, op, ast_str_buffer(buf), escape);
        while ((field = field->next)) {
-               if (!strchr(field->name, ' ')) 
-                       op = " ="; 
-               else
+               escape = "";
+               if (!strchr(field->name, ' ')) {
+                       op = " =";
+               } else {
                        op = "";
+                       if (IS_SQL_LIKE_CLAUSE(field->name)) {
+                               escape = ESCAPE_CLAUSE;
+                       }
+               }
                ESCAPE_STRING(buf, field->value);
-               ast_str_append(&sql, 0, " AND %s%s '%s'", field->name, op, ast_str_buffer(buf));
+               ast_str_append(&sql, 0, " AND %s%s '%s'%s", field->name, op, ast_str_buffer(buf), escape);
        }
 
        ast_debug(1, "MySQL RealTime: Retrieve SQL: %s\n", ast_str_buffer(sql));
@@ -416,6 +430,7 @@ static struct ast_config *realtime_multi_mysql(const char *database, const char
        char *stringp;
        char *chunk;
        char *op;
+       char *escape = "";
        const struct ast_variable *field = rt_fields;
        struct ast_variable *var = NULL;
        struct ast_config *cfg = NULL;
@@ -431,7 +446,7 @@ static struct ast_config *realtime_multi_mysql(const char *database, const char
                release_database(dbh);
                return NULL;
        }
-       
+
        if (!(cfg = ast_config_new())) {
                /* If I can't alloc memory at this point, why bother doing anything else? */
                ast_log(LOG_WARNING, "Out of memory!\n");
@@ -462,17 +477,29 @@ static struct ast_config *realtime_multi_mysql(const char *database, const char
        /* Create the first part of the query using the first parameter/value pairs we just extracted
           If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
 
-       if (!strchr(field->name, ' '))
+       if (!strchr(field->name, ' ')) {
                op = " =";
-       else
+       } else {
                op = "";
+               if (IS_SQL_LIKE_CLAUSE(field->name)) {
+                       escape = ESCAPE_CLAUSE;
+               }
+       }
 
        ESCAPE_STRING(buf, field->value);
-       ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", table, field->name, op, ast_str_buffer(buf));
+       ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'%s", table, field->name, op, ast_str_buffer(buf), escape);
        while ((field = field->next)) {
-               if (!strchr(field->name, ' ')) op = " ="; else op = "";
+               escape = "";
+               if (!strchr(field->name, ' ')) {
+                       op = " =";
+               } else {
+                       op = "";
+                       if (IS_SQL_LIKE_CLAUSE(field->name)) {
+                               escape = ESCAPE_CLAUSE;
+                       }
+               }
                ESCAPE_STRING(buf, field->value);
-               ast_str_append(&sql, 0, " AND %s%s '%s'", field->name, op, ast_str_buffer(buf));
+               ast_str_append(&sql, 0, " AND %s%s '%s'%s", field->name, op, ast_str_buffer(buf), escape);
        }
 
        if (initfield) {
@@ -495,9 +522,8 @@ static struct ast_config *realtime_multi_mysql(const char *database, const char
 
                while ((row = mysql_fetch_row(result))) {
                        var = NULL;
-                       cat = ast_category_new("", "", -1);
+                       cat = ast_category_new_anonymous();
                        if (!cat) {
-                               ast_log(LOG_WARNING, "Out of memory!\n");
                                continue;
                        }
                        for (i = 0; i < numFields; i++) {
@@ -722,7 +748,7 @@ static int update2_mysql(const char *database, const char *tablename, const stru
 
        return (int)numrows;
 }
+
 static int store_mysql(const char *database, const char *table, const struct ast_variable *rt_fields)
 {
        struct mysql_conn *dbh;
@@ -846,7 +872,7 @@ static int destroy_mysql(const char *database, const char *table, const char *ke
 
        return (int)numrows;
 }
+
 static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags config_flags, const char *unused, const char *who_asked)
 {
        struct mysql_conn *dbh;
@@ -906,8 +932,8 @@ static struct ast_config *config_mysql(const char *database, const char *table,
                        }
 
                        if (strcmp(last, row[0]) || last_cat_metric != atoi(row[3])) {
-                               if (!(cur_cat = ast_category_new(row[0], "", -1))) {
-                                       ast_log(LOG_WARNING, "Out of memory!\n");
+                               cur_cat = ast_category_new_dynamic(row[0]);
+                               if (!cur_cat) {
                                        break;
                                }
                                strcpy(last, row[0]);
@@ -1533,5 +1559,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "MySQL RealTime Config
        .unload = unload_module,
        .reload = reload,
        .load_pri = AST_MODPRI_REALTIME_DRIVER,
+       .requires = "extconfig",
 );
-