Merge remaining audit patch (save dlfcn.c)
[asterisk/asterisk.git] / res / res_config_odbc.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Copyright (C) 1999, Mark Spencer
5  *
6  * Mark Spencer <markster@linux-support.net>
7  *
8  * res_config_odbc.c <odbc+odbc plugin for portable configuration engine >
9  * Copyright (C) 2004 Anthony Minessale II <anthmct@yahoo.com>
10  */
11
12 #include <asterisk/file.h>
13 #include <asterisk/logger.h>
14 #include <asterisk/channel.h>
15 #include <asterisk/pbx.h>
16 #include <asterisk/config.h>
17 #include <asterisk/config_pvt.h>
18 #include <asterisk/module.h>
19 #include <asterisk/lock.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <asterisk/res_odbc.h>
24
25 static char *tdesc = "ODBC Configuration";
26 static struct ast_config_reg reg1;
27
28 STANDARD_LOCAL_USER;
29
30 LOCAL_USER_DECL;
31
32 static struct ast_config *config_odbc (char *file, struct ast_config *new_config_s, struct ast_category **new_cat_p, struct ast_variable **new_v_p, int recur
33 #ifdef PRESERVE_COMMENTS
34         , struct ast_comment_struct *acs
35 #endif
36 )
37 {
38         struct ast_config *config, *new;
39         struct ast_variable *v, *cur_v, *new_v;
40         struct ast_category *cur_cat, *new_cat;
41         char table[128] = "";
42         char connection[128] = "";
43         int configured = 0, res = 0;
44         odbc_obj *obj;
45         SQLINTEGER err=0, commented=0, cat_metric=0, var_metric=0, last_cat_metric=0;
46         SQLBIGINT id;
47         char sql[255] = "", filename[128], category[128], var_name[128], var_val[128];
48         SQLSMALLINT rowcount=0;
49         SQLHSTMT stmt;
50         char last[80] = "";
51         int cat_started = 0;
52         int var_started = 0;
53
54         if (new_config_s) {
55                 new = new_config_s;
56                 cat_started++;
57         } else {
58                 new = ast_new_config ();
59         }
60
61         last[0] = '\0';
62
63         if (!file || !strcmp (file, "res_config_odbc.conf"))
64                 return NULL;            // cant configure myself with myself !
65
66         config = ast_load ("res_config_odbc.conf");
67
68         if (config) {
69                 for (v = ast_variable_browse (config, "settings"); v; v = v->next) {
70                         if (!strcmp (v->name, "table")) {
71                                 strncpy(table, v->value, sizeof(table) - 1);
72                                 configured++;
73                         } else if (!strcmp (v->name, "connection")) {
74                                 strncpy(connection, v->value, sizeof(connection) - 1);
75                                 configured++;
76                         }
77                 }
78         ast_destroy (config);
79         }
80
81         if (configured < 2)
82                 return NULL;
83
84         obj = fetch_odbc_obj (connection);
85         if (!obj)
86                 return NULL;
87
88         res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
89
90         SQLBindCol (stmt, 1, SQL_C_ULONG, &id, sizeof (id), &err);
91         SQLBindCol (stmt, 2, SQL_C_ULONG, &cat_metric, sizeof (cat_metric), &err);
92         SQLBindCol (stmt, 3, SQL_C_ULONG, &var_metric, sizeof (var_metric), &err);
93         SQLBindCol (stmt, 4, SQL_C_ULONG, &commented, sizeof (commented), &err);
94         SQLBindCol (stmt, 5, SQL_C_CHAR, &filename, sizeof (filename), &err);
95         SQLBindCol (stmt, 6, SQL_C_CHAR, &category, sizeof (category), &err);
96         SQLBindCol (stmt, 7, SQL_C_CHAR, &var_name, sizeof (var_name), &err);
97         SQLBindCol (stmt, 8, SQL_C_CHAR, &var_val, sizeof (var_val), &err);
98
99         snprintf(sql, sizeof(sql), "select * from %s where filename='%s' and commented=0 order by filename,cat_metric desc,var_metric asc,id", table, file);
100         res = SQLExecDirect (stmt, sql, SQL_NTS);
101
102         if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
103                 ast_log (LOG_WARNING, "SQL select error!\n[%s]\n\n", sql);
104                 return NULL;
105         }
106
107         res = SQLNumResultCols (stmt, &rowcount);
108
109         if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
110                 ast_log (LOG_WARNING, "SQL select error!\n[%s]\n\n", sql);
111                 return NULL;
112         }
113
114         if (rowcount) {
115                 res = SQLFetch (stmt);
116                 cat_started = 0;
117
118                 cur_cat = *new_cat_p;
119                 cur_v = *new_v_p;
120
121                 if (cur_cat)
122                         cat_started = 1;
123                 if (cur_v)
124                         var_started = 1;
125
126                 while (res != SQL_NO_DATA) {
127                         if (!strcmp (var_name, "#include") && recur < MAX_INCLUDE_LEVEL) {
128
129                                 config_odbc (var_val, new, &cur_cat, &cur_v, recur + 1
130 #ifdef PRESERVE_COMMENTS
131                                                         , acs
132 #endif
133                                 );
134                         } else {
135                                 if (strcmp (last, category) || last_cat_metric != cat_metric) {
136                                         strncpy(last, category, sizeof(last) - 1);
137                                         last_cat_metric = cat_metric;
138                                         new_cat = (struct ast_category *) ast_new_category (category);
139
140                                         if (!cat_started) {
141                                                 cat_started++;
142                                                 new->root = new_cat;
143                                                 cur_cat = new->root;
144                                         } else {
145                                                 cur_cat->next = new_cat;
146                                                 cur_cat = cur_cat->next;
147                                         }
148                                         var_started = 0;
149
150                                 }
151
152                                 new_v = ast_new_variable (var_name, var_val);
153
154                                 if (!var_started) {
155                                         var_started++;
156                                         cur_cat->root = new_v;
157                                         cur_v = cur_cat->root;
158                                 } else {
159                                         cur_v->next = new_v;
160                                         cur_v = cur_v->next;
161                                 }
162                         }
163
164                 // next row 
165                         res = SQLFetch (stmt);
166                 }
167
168                 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
169         } else {
170                 ast_log (LOG_NOTICE, "found nothing\n");
171         }
172         return new;
173
174 }
175
176 int unload_module (void)
177 {
178         ast_cust_config_deregister (&reg1);
179         ast_log (LOG_NOTICE, "res_config_odbc unloaded.\n");
180         STANDARD_HANGUP_LOCALUSERS;
181         return 0;
182 }
183
184 int load_module (void)
185 {
186         memset (&reg1, 0, sizeof (struct ast_config_reg));
187         strncpy(reg1.name, "odbc", sizeof(reg1.name) - 1);
188         reg1.func = config_odbc;
189         ast_cust_config_register (&reg1);
190         ast_log (LOG_NOTICE, "res_config_odbc loaded.\n");
191         return 0;
192 }
193
194 char *description (void)
195 {
196         return tdesc;
197 }
198
199 int usecount (void)
200 {
201         /* never unload a config module */
202         return 1;
203 }
204
205 char *key ()
206 {
207         return ASTERISK_GPL_KEY;
208 }