app_mysql.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2004, Constantine Filin and Christos Ricudis
00005  *
00006  * Christos Ricudis <ricudis@itc.auth.gr>
00007  * Constantine Filin <cf@intermedia.net>
00008  *
00009  * See http://www.asterisk.org for more information about
00010  * the Asterisk project. Please do not directly contact
00011  * any of the maintainers of this project for assistance;
00012  * the project provides a web site, mailing lists and IRC
00013  * channels for your use.
00014  *
00015  * This program is free software, distributed under the terms of
00016  * the GNU General Public License Version 2. See the LICENSE file
00017  * at the top of the source tree.
00018  */
00019 
00020 /*!
00021  * \file
00022  * \brief MYSQL dialplan application
00023  * \ingroup applications
00024  */
00025 
00026 /*! \li \ref app_mysql.c uses the configuration file \ref app_mysql.conf
00027  * \addtogroup configuration_file Configuration Files
00028  */
00029 
00030 /*! 
00031  * \page app_mysql.conf app_mysql.conf
00032  * \verbinclude app_mysql.conf.sample
00033  */
00034 
00035 /*** MODULEINFO
00036    <depend>mysqlclient</depend>
00037    <defaultenabled>no</defaultenabled>
00038    <support_level>deprecated</support_level>
00039    <replacement>func_odbc</replacement>
00040  ***/
00041 
00042 #include "asterisk.h"
00043 
00044 #include <mysql/mysql.h>
00045 
00046 #include "asterisk/file.h"
00047 #include "asterisk/logger.h"
00048 #include "asterisk/channel.h"
00049 #include "asterisk/pbx.h"
00050 #include "asterisk/module.h"
00051 #include "asterisk/linkedlists.h"
00052 #include "asterisk/chanvars.h"
00053 #include "asterisk/lock.h"
00054 #include "asterisk/options.h"
00055 #include "asterisk/app.h"
00056 #include "asterisk/config.h"
00057 
00058 #define EXTRA_LOG 0
00059 
00060 enum { NULLSTRING, NULLVALUE, EMPTYSTRING } nullvalue = NULLSTRING;
00061 
00062 static const char app[] = "MYSQL";
00063 
00064 static const char synopsis[] = "Do several mySQLy things";
00065 
00066 static const char descrip[] =
00067 "MYSQL():  Do several mySQLy things\n"
00068 "Syntax:\n"
00069 "  MYSQL(Set timeout <num>)\n"
00070 "    Set the connection timeout, in seconds.\n"
00071 "  MYSQL(Connect connid dhhost[:dbport] dbuser dbpass dbname [dbcharset])\n"
00072 "    Connects to a database.  Arguments contain standard MySQL parameters\n"
00073 "    passed to function mysql_real_connect.  Optional parameter dbcharset\n"
00074 "    defaults to 'latin1'.  Connection identifer returned in ${connid}\n"
00075 "  MYSQL(Query resultid ${connid} query-string)\n"
00076 "    Executes standard MySQL query contained in query-string using established\n"
00077 "    connection identified by ${connid}. Result of query is stored in ${resultid}.\n"
00078 "  MYSQL(Nextresult resultid ${connid}\n"
00079 "    If last query returned more than one result set, it stores the next\n"
00080 "    result set in ${resultid}. It's useful with stored procedures\n"
00081 "  MYSQL(Fetch fetchid ${resultid} var1 var2 ... varN)\n"
00082 "    Fetches a single row from a result set contained in ${result_identifier}.\n"
00083 "    Assigns returned fields to ${var1} ... ${varn}.  ${fetchid} is set TRUE\n"
00084 "    if additional rows exist in result set.\n"
00085 "  MYSQL(Clear ${resultid})\n"
00086 "    Frees memory and datastructures associated with result set.\n"
00087 "  MYSQL(Disconnect ${connid})\n"
00088 "    Disconnects from named connection to MySQL.\n"
00089 "  On exit, always returns 0. Sets MYSQL_STATUS to 0 on success and -1 on error.\n";
00090 
00091 /*
00092 EXAMPLES OF USE :
00093 
00094 exten => s,2,MYSQL(Connect connid localhost asterisk mypass credit utf8)
00095 exten => s,3,MYSQL(Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${CALLERIDNUM})
00096 exten => s,4,MYSQL(Fetch fetchid ${resultid} datavar1 datavar2)
00097 exten => s,5,GotoIf(${fetchid}?6:8)
00098 exten => s,6,Festival("User ${datavar1} currently has credit balance of ${datavar2} dollars.")
00099 exten => s,7,Goto(s,4)
00100 exten => s,8,MYSQL(Clear ${resultid})
00101 exten => s,9,MYSQL(Disconnect ${connid})
00102 */
00103 
00104 AST_MUTEX_DEFINE_STATIC(_mysql_mutex);
00105 
00106 #define MYSQL_CONFIG "app_mysql.conf"
00107 #define MYSQL_CONFIG_OLD "mysql.conf"
00108 #define AST_MYSQL_ID_DUMMY   0
00109 #define AST_MYSQL_ID_CONNID  1
00110 #define AST_MYSQL_ID_RESID   2
00111 #define AST_MYSQL_ID_FETCHID 3
00112 
00113 static int autoclear = 0;
00114 
00115 static void mysql_ds_destroy(void *data);
00116 static void mysql_ds_fixup(void *data, struct ast_channel *oldchan, struct ast_channel *newchan);
00117 
00118 static const struct ast_datastore_info mysql_ds_info = {
00119    .type = "APP_ADDON_SQL_MYSQL",
00120    .destroy = mysql_ds_destroy,
00121    .chan_fixup = mysql_ds_fixup,
00122 };
00123 
00124 struct ast_MYSQL_id {
00125    struct ast_channel *owner;
00126    int identifier_type; /* 0=dummy, 1=connid, 2=resultid */
00127    int identifier;
00128    void *data;
00129    AST_LIST_ENTRY(ast_MYSQL_id) entries;
00130 } *ast_MYSQL_id;
00131 
00132 AST_LIST_HEAD(MYSQLidshead,ast_MYSQL_id) _mysql_ids_head;
00133 
00134 static void mysql_ds_destroy(void *data)
00135 {
00136    /* Destroy any IDs owned by the channel */
00137    struct ast_MYSQL_id *i;
00138    if (AST_LIST_LOCK(&_mysql_ids_head)) {
00139       ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
00140    } else {
00141       AST_LIST_TRAVERSE_SAFE_BEGIN(&_mysql_ids_head, i, entries) {
00142          if (i->owner == data) {
00143             AST_LIST_REMOVE_CURRENT(entries);
00144             if (i->identifier_type == AST_MYSQL_ID_CONNID) {
00145                /* Drop connection */
00146                mysql_close(i->data);
00147             } else if (i->identifier_type == AST_MYSQL_ID_RESID) {
00148                /* Drop result */
00149                mysql_free_result(i->data);
00150             }
00151             ast_free(i);
00152          }
00153       }
00154       AST_LIST_TRAVERSE_SAFE_END
00155       AST_LIST_UNLOCK(&_mysql_ids_head);
00156    }
00157 }
00158 
00159 static void mysql_ds_fixup(void *data, struct ast_channel *oldchan, struct ast_channel *newchan)
00160 {
00161    /* Destroy any IDs owned by the channel */
00162    struct ast_MYSQL_id *i;
00163    if (AST_LIST_LOCK(&_mysql_ids_head)) {
00164       ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
00165    } else {
00166       AST_LIST_TRAVERSE_SAFE_BEGIN(&_mysql_ids_head, i, entries) {
00167          if (i->owner == data) {
00168             AST_LIST_REMOVE_CURRENT(entries);
00169             if (i->identifier_type == AST_MYSQL_ID_CONNID) {
00170                /* Drop connection */
00171                mysql_close(i->data);
00172             } else if (i->identifier_type == AST_MYSQL_ID_RESID) {
00173                /* Drop result */
00174                mysql_free_result(i->data);
00175             }
00176             ast_free(i);
00177          }
00178       }
00179       AST_LIST_TRAVERSE_SAFE_END
00180       AST_LIST_UNLOCK(&_mysql_ids_head);
00181    }
00182 }
00183 
00184 /* helpful procs */
00185 static void *find_identifier(int identifier, int identifier_type)
00186 {
00187    struct MYSQLidshead *headp = &_mysql_ids_head;
00188    struct ast_MYSQL_id *i;
00189    void *res=NULL;
00190    int found=0;
00191 
00192    if (AST_LIST_LOCK(headp)) {
00193       ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
00194    } else {
00195       AST_LIST_TRAVERSE(headp, i, entries) {
00196          if ((i->identifier == identifier) && (i->identifier_type == identifier_type)) {
00197             found = 1;
00198             res = i->data;
00199             break;
00200          }
00201       }
00202       if (!found) {
00203          ast_log(LOG_WARNING, "Identifier %d, identifier_type %d not found in identifier list\n", identifier, identifier_type);
00204       }
00205       AST_LIST_UNLOCK(headp);
00206    }
00207 
00208    return res;
00209 }
00210 
00211 static int add_identifier(struct ast_channel *chan, int identifier_type, void *data)
00212 {
00213    struct ast_MYSQL_id *i = NULL, *j = NULL;
00214    struct MYSQLidshead *headp = &_mysql_ids_head;
00215    int maxidentifier = 0;
00216 
00217    if (AST_LIST_LOCK(headp)) {
00218       ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
00219       return -1;
00220    } else {
00221       i = ast_malloc(sizeof(*i));
00222       AST_LIST_TRAVERSE(headp, j, entries) {
00223          if (j->identifier > maxidentifier) {
00224             maxidentifier = j->identifier;
00225          }
00226       }
00227       i->identifier = maxidentifier + 1;
00228       i->identifier_type = identifier_type;
00229       i->data = data;
00230       i->owner = chan;
00231       AST_LIST_INSERT_HEAD(headp, i, entries);
00232       AST_LIST_UNLOCK(headp);
00233    }
00234    return i->identifier;
00235 }
00236 
00237 static int del_identifier(int identifier, int identifier_type)
00238 {
00239    struct ast_MYSQL_id *i;
00240    struct MYSQLidshead *headp = &_mysql_ids_head;
00241    int found = 0;
00242 
00243    if (AST_LIST_LOCK(headp)) {
00244       ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
00245    } else {
00246       AST_LIST_TRAVERSE(headp, i, entries) {
00247          if ((i->identifier == identifier) &&
00248              (i->identifier_type == identifier_type)) {
00249             AST_LIST_REMOVE(headp, i, entries);
00250             ast_free(i);
00251             found = 1;
00252             break;
00253          }
00254       }
00255       AST_LIST_UNLOCK(headp);
00256    }
00257 
00258    if (found == 0) {
00259       ast_log(LOG_WARNING, "Could not find identifier %d, identifier_type %d in list to delete\n", identifier, identifier_type);
00260       return -1;
00261    } else {
00262       return 0;
00263    }
00264 }
00265 
00266 static int set_asterisk_int(struct ast_channel *chan, char *varname, int id)
00267 {
00268    if (id >= 0) {
00269       char s[12] = "";
00270       snprintf(s, sizeof(s), "%d", id);
00271       ast_debug(5, "MYSQL: setting var '%s' to value '%s'\n", varname, s);
00272       pbx_builtin_setvar_helper(chan, varname, s);
00273    }
00274    return id;
00275 }
00276 
00277 static int add_identifier_and_set_asterisk_int(struct ast_channel *chan, char *varname, int identifier_type, void *data)
00278 {
00279    return set_asterisk_int(chan, varname, add_identifier(chan, identifier_type, data));
00280 }
00281 
00282 static int safe_scan_int(char **data, char *delim, int def)
00283 {
00284    char *end;
00285    int res = def;
00286    char *s = strsep(data, delim);
00287    if (s) {
00288       res = strtol(s, &end, 10);
00289       if (*end)
00290          res = def;  /* not an integer */
00291    }
00292    return res;
00293 }
00294 
00295 static int aMYSQL_set(struct ast_channel *chan, const char *data)
00296 {
00297    char *var, *tmp, *parse;
00298    AST_DECLARE_APP_ARGS(args,
00299       AST_APP_ARG(set);
00300       AST_APP_ARG(variable);
00301       AST_APP_ARG(value);
00302    );
00303 
00304    parse = ast_strdupa(data);
00305    AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
00306 
00307    if (args.argc == 3) {
00308       var = ast_alloca(6 + strlen(args.variable) + 1);
00309       sprintf(var, "MYSQL_%s", args.variable);
00310 
00311       /* Make the parameter case-insensitive */
00312       for (tmp = var + 6; *tmp; tmp++)
00313          *tmp = toupper(*tmp);
00314 
00315       pbx_builtin_setvar_helper(chan, var, args.value);
00316    }
00317    return 0;
00318 }
00319 
00320 /* MYSQL operations */
00321 static int aMYSQL_connect(struct ast_channel *chan, const char *data)
00322 {
00323    AST_DECLARE_APP_ARGS(args,
00324       AST_APP_ARG(connect);
00325       AST_APP_ARG(connid);
00326       AST_APP_ARG(dbhost);
00327       AST_APP_ARG(dbuser);
00328       AST_APP_ARG(dbpass);
00329       AST_APP_ARG(dbname);
00330       AST_APP_ARG(dbcharset);
00331    );
00332    MYSQL *mysql;
00333    int timeout;
00334    const char *ctimeout;
00335    unsigned int port = 0;
00336    char *port_str;
00337    char *parse = ast_strdupa(data);
00338  
00339    AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
00340 
00341    if (args.argc < 6) {
00342       ast_log(LOG_WARNING, "MYSQL_connect is missing some arguments\n");
00343       return -1;
00344    }
00345 
00346    if (!(mysql = mysql_init(NULL))) {
00347       ast_log(LOG_WARNING, "mysql_init returned NULL\n");
00348       return -1;
00349    }
00350 
00351    ctimeout = pbx_builtin_getvar_helper(chan, "MYSQL_TIMEOUT");
00352    if (ctimeout && sscanf(ctimeout, "%30d", &timeout) == 1) {
00353       mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&timeout);
00354    }
00355    if(args.dbcharset && strlen(args.dbcharset) > 2){
00356       char set_names[255];
00357       char statement[512];
00358       snprintf(set_names, sizeof(set_names), "SET NAMES %s", args.dbcharset);
00359       mysql_real_escape_string(mysql, statement, set_names, sizeof(set_names));
00360       mysql_options(mysql, MYSQL_INIT_COMMAND, set_names);
00361       mysql_options(mysql, MYSQL_SET_CHARSET_NAME, args.dbcharset);
00362    }
00363 
00364    if ((port_str = strchr(args.dbhost, ':'))) {
00365       *port_str++ = '\0';
00366       if (sscanf(port_str, "%u", &port) != 1) {
00367          ast_log(LOG_WARNING, "Invalid port: '%s'\n", port_str);
00368          port = 0;
00369       }
00370    }
00371 
00372    if (!mysql_real_connect(mysql, args.dbhost, args.dbuser, args.dbpass, args.dbname, port, NULL,
00373 #ifdef CLIENT_MULTI_STATEMENTS
00374          CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS
00375 #elif defined(CLIENT_MULTI_QUERIES)
00376          CLIENT_MULTI_QUERIES
00377 #else
00378          0
00379 #endif
00380       )) {
00381       ast_log(LOG_WARNING, "mysql_real_connect(mysql,%s,%s,dbpass,%s,...) failed(%d): %s\n",
00382             args.dbhost, args.dbuser, args.dbname, mysql_errno(mysql), mysql_error(mysql));
00383       return -1;
00384    }
00385 
00386    add_identifier_and_set_asterisk_int(chan, args.connid, AST_MYSQL_ID_CONNID, mysql);
00387    return 0;
00388 }
00389 
00390 static int aMYSQL_query(struct ast_channel *chan, const char *data)
00391 {
00392    AST_DECLARE_APP_ARGS(args,
00393       AST_APP_ARG(query);
00394       AST_APP_ARG(resultid);
00395       AST_APP_ARG(connid);
00396       AST_APP_ARG(sql);
00397    );
00398    MYSQL       *mysql;
00399    MYSQL_RES   *mysqlres;
00400    int connid;
00401    int mysql_query_res;
00402    char *parse = ast_strdupa(data);
00403 
00404    AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
00405 
00406    if (args.argc != 4 || (connid = atoi(args.connid)) == 0) {
00407       ast_log(LOG_WARNING, "missing some arguments\n");
00408       return -1;
00409    }
00410 
00411    if (!(mysql = find_identifier(connid, AST_MYSQL_ID_CONNID))) {
00412       ast_log(LOG_WARNING, "Invalid connection identifier %s passed in aMYSQL_query\n", args.connid);
00413       return -1;
00414    }
00415 
00416    if ((mysql_query_res = mysql_query(mysql, args.sql)) != 0) {
00417       ast_log(LOG_WARNING, "aMYSQL_query: mysql_query failed. Error: %s\n", mysql_error(mysql));
00418       return -1;
00419    }
00420 
00421    if ((mysqlres = mysql_store_result(mysql))) {
00422       add_identifier_and_set_asterisk_int(chan, args.resultid, AST_MYSQL_ID_RESID, mysqlres);
00423       return 0;
00424    } else if (!mysql_field_count(mysql)) {
00425       return 0;
00426    } else
00427       ast_log(LOG_WARNING, "mysql_store_result() failed on query %s\n", args.sql);
00428 
00429    return -1;
00430 }
00431 
00432 static int aMYSQL_nextresult(struct ast_channel *chan, const char *data)
00433 {
00434    MYSQL       *mysql;
00435    MYSQL_RES   *mysqlres;
00436    AST_DECLARE_APP_ARGS(args,
00437       AST_APP_ARG(nextresult);
00438       AST_APP_ARG(resultid);
00439       AST_APP_ARG(connid);
00440    );
00441    int connid = -1;
00442    char *parse = ast_strdupa(data);
00443 
00444    AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
00445    sscanf(args.connid, "%30d", &connid);
00446 
00447    if (args.argc != 3 || connid <= 0) {
00448       ast_log(LOG_WARNING, "missing some arguments\n");
00449       return -1;
00450    }
00451 
00452    if (!(mysql = find_identifier(connid, AST_MYSQL_ID_CONNID))) {
00453       ast_log(LOG_WARNING, "Invalid connection identifier %d passed in aMYSQL_query\n", connid);
00454       return -1;
00455    }
00456 
00457    if (mysql_more_results(mysql)) {
00458       mysql_next_result(mysql);
00459       if ((mysqlres = mysql_store_result(mysql))) {
00460          add_identifier_and_set_asterisk_int(chan, args.resultid, AST_MYSQL_ID_RESID, mysqlres);
00461          return 0;
00462       } else if (!mysql_field_count(mysql)) {
00463          return 0;
00464       } else
00465          ast_log(LOG_WARNING, "mysql_store_result() failed on storing next_result\n");
00466    } else
00467       ast_log(LOG_WARNING, "mysql_more_results() result set has no more results\n");
00468 
00469    return 0;
00470 }
00471 
00472 
00473 static int aMYSQL_fetch(struct ast_channel *chan, const char *data)
00474 {
00475    MYSQL_RES *mysqlres;
00476    MYSQL_ROW mysqlrow;
00477    AST_DECLARE_APP_ARGS(args,
00478       AST_APP_ARG(fetch);
00479       AST_APP_ARG(resultvar);
00480       AST_APP_ARG(fetchid);
00481       AST_APP_ARG(vars);
00482    );
00483    char *s5, *parse;
00484    int resultid = -1, numFields, j;
00485 
00486    parse = ast_strdupa(data);
00487    AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
00488    sscanf(args.fetchid, "%30d", &resultid);
00489 
00490    if (args.resultvar && (resultid >= 0) ) {
00491       if ((mysqlres = find_identifier(resultid, AST_MYSQL_ID_RESID)) != NULL) {
00492          /* Grab the next row */
00493          if ((mysqlrow = mysql_fetch_row(mysqlres)) != NULL) {
00494             numFields = mysql_num_fields(mysqlres);
00495             for (j = 0; j < numFields; j++) {
00496                s5 = strsep(&args.vars, " ");
00497                if (s5 == NULL) {
00498                   ast_log(LOG_WARNING, "ast_MYSQL_fetch: More fields (%d) than variables (%d)\n", numFields, j);
00499                   break;
00500                }
00501 
00502                pbx_builtin_setvar_helper(chan, s5, mysqlrow[j] ? mysqlrow[j] :
00503                   nullvalue == NULLSTRING ? "NULL" :
00504                   nullvalue == EMPTYSTRING ? "" :
00505                   NULL);
00506             }
00507             ast_debug(5, "ast_MYSQL_fetch: numFields=%d\n", numFields);
00508             set_asterisk_int(chan, args.resultvar, 1); /* try more rows */
00509          } else {
00510             ast_debug(5, "ast_MYSQL_fetch : EOF\n");
00511             set_asterisk_int(chan, args.resultvar, 0); /* no more rows */
00512          }
00513          return 0;
00514       } else {
00515          set_asterisk_int(chan, args.resultvar, 0);
00516          ast_log(LOG_WARNING, "aMYSQL_fetch: Invalid result identifier %d passed\n", resultid);
00517       }
00518    } else {
00519       ast_log(LOG_WARNING, "aMYSQL_fetch: missing some arguments\n");
00520    }
00521 
00522    return -1;
00523 }
00524 
00525 static int aMYSQL_clear(struct ast_channel *chan, const char *data)
00526 {
00527    MYSQL_RES *mysqlres;
00528 
00529    int id;
00530    char *parse = ast_strdupa(data);
00531    strsep(&parse, " "); /* eat the first token, we already know it :P */
00532    id = safe_scan_int(&parse, " \n", -1);
00533    if ((mysqlres = find_identifier(id, AST_MYSQL_ID_RESID)) == NULL) {
00534       ast_log(LOG_WARNING, "Invalid result identifier %d passed in aMYSQL_clear\n", id);
00535    } else {
00536       mysql_free_result(mysqlres);
00537       del_identifier(id, AST_MYSQL_ID_RESID);
00538    }
00539 
00540    return 0;
00541 }
00542 
00543 static int aMYSQL_disconnect(struct ast_channel *chan, const char *data)
00544 {
00545    MYSQL *mysql;
00546    int id;
00547    char *parse = ast_strdupa(data);
00548    strsep(&parse, " "); /* eat the first token, we already know it :P */
00549 
00550    id = safe_scan_int(&parse, " \n", -1);
00551    if ((mysql = find_identifier(id, AST_MYSQL_ID_CONNID)) == NULL) {
00552       ast_log(LOG_WARNING, "Invalid connection identifier %d passed in aMYSQL_disconnect\n", id);
00553    } else {
00554       mysql_close(mysql);
00555       del_identifier(id, AST_MYSQL_ID_CONNID);
00556    }
00557 
00558    return 0;
00559 }
00560 
00561 static int MYSQL_exec(struct ast_channel *chan, const char *data)
00562 {
00563    int result;
00564    char sresult[10];
00565 
00566    ast_debug(5, "MYSQL: data=%s\n", data);
00567 
00568    if (!data) {
00569       ast_log(LOG_WARNING, "MYSQL requires an argument (see manual)\n");
00570       return -1;
00571    }
00572 
00573    result = 0;
00574 
00575    if (autoclear) {
00576       struct ast_datastore *mysql_store = NULL;
00577 
00578       ast_channel_lock(chan);
00579       mysql_store = ast_channel_datastore_find(chan, &mysql_ds_info, NULL);
00580       if (!mysql_store) {
00581          if (!(mysql_store = ast_datastore_alloc(&mysql_ds_info, NULL))) {
00582             ast_log(LOG_WARNING, "Unable to allocate new datastore.\n");
00583          } else {
00584             mysql_store->data = chan;
00585             ast_channel_datastore_add(chan, mysql_store);
00586          }
00587       }
00588       ast_channel_unlock(chan);
00589    }
00590    ast_mutex_lock(&_mysql_mutex);
00591 
00592    if (strncasecmp("connect", data, strlen("connect")) == 0) {
00593       result = aMYSQL_connect(chan, data);
00594    } else if (strncasecmp("query", data, strlen("query")) == 0) {
00595       result = aMYSQL_query(chan, data);
00596    } else if (strncasecmp("nextresult", data, strlen("nextresult")) == 0) {
00597       result = aMYSQL_nextresult(chan, data);
00598    } else if (strncasecmp("fetch", data, strlen("fetch")) == 0) {
00599       result = aMYSQL_fetch(chan, data);
00600    } else if (strncasecmp("clear", data, strlen("clear")) == 0) {
00601       result = aMYSQL_clear(chan, data);
00602    } else if (strncasecmp("disconnect", data, strlen("disconnect")) == 0) {
00603       result = aMYSQL_disconnect(chan, data);
00604    } else if (strncasecmp("set", data, 3) == 0) {
00605       result = aMYSQL_set(chan, data);
00606    } else {
00607       ast_log(LOG_WARNING, "Unknown argument to MYSQL application : %s\n", data);
00608       result = -1;
00609    }
00610 
00611    ast_mutex_unlock(&_mysql_mutex);
00612 
00613    snprintf(sresult, sizeof(sresult), "%d", result);
00614    pbx_builtin_setvar_helper(chan, "MYSQL_STATUS", sresult);
00615    return 0;
00616 }
00617 
00618 static int unload_module(void)
00619 {
00620    return ast_unregister_application(app);
00621 }
00622 
00623 /*!
00624  * \brief Load the module
00625  *
00626  * Module loading including tests for configuration or dependencies.
00627  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
00628  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
00629  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the 
00630  * configuration file or other non-critical problem return 
00631  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
00632  */
00633 static int load_module(void)
00634 {
00635    struct MYSQLidshead *headp = &_mysql_ids_head;
00636    struct ast_flags config_flags = { 0 };
00637    struct ast_config *cfg = ast_config_load(MYSQL_CONFIG, config_flags);
00638    const char *temp;
00639 
00640    if (!cfg) {
00641       /* Backwards compatibility ftw */
00642       cfg = ast_config_load(MYSQL_CONFIG_OLD, config_flags);
00643    }
00644 
00645    if (cfg) {
00646       if ((temp = ast_variable_retrieve(cfg, "general", "nullvalue"))) {
00647          if (!strcasecmp(temp, "nullstring")) {
00648             nullvalue = NULLSTRING;
00649          } else if (!strcasecmp(temp, "emptystring")) {
00650             nullvalue = EMPTYSTRING;
00651          } else if (!strcasecmp(temp, "null")) {
00652             nullvalue = NULLVALUE;
00653          } else {
00654             ast_log(LOG_WARNING, "Illegal value for 'nullvalue': '%s' (must be 'nullstring', 'null', or 'emptystring')\n", temp);
00655          }
00656       }
00657       if ((temp = ast_variable_retrieve(cfg, "general", "autoclear")) && ast_true(temp)) {
00658          autoclear = 1;
00659       }
00660       ast_config_destroy(cfg);
00661    }
00662 
00663    AST_LIST_HEAD_INIT(headp);
00664    return ast_register_application(app, MYSQL_exec, synopsis, descrip);
00665 }
00666 
00667 AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Simple Mysql Interface");
00668 

Generated on Thu Apr 16 06:27:10 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6