00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <string.h>
00033 #include <unistd.h>
00034 #include <dirent.h>
00035 #include <sys/types.h>
00036
00037 #include "asterisk.h"
00038
00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 28257 $")
00040
00041 #include "asterisk/file.h"
00042 #include "asterisk/logger.h"
00043 #include "asterisk/channel.h"
00044 #include "asterisk/pbx.h"
00045 #include "asterisk/module.h"
00046 #include "asterisk/lock.h"
00047 #include "asterisk/utils.h"
00048 #include "asterisk/app.h"
00049 #include "asterisk/options.h"
00050 #ifdef USE_ODBC_STORAGE
00051 #include "asterisk/res_odbc.h"
00052
00053 static char odbc_database[80];
00054 static char odbc_table[80];
00055 #endif
00056
00057 static char *tdesc = "Indicator for whether a voice mailbox has messages in a given folder.";
00058 static char *app_hasvoicemail = "HasVoicemail";
00059 static char *hasvoicemail_synopsis = "Conditionally branches to priority + 101 with the right options set";
00060 static char *hasvoicemail_descrip =
00061 "HasVoicemail(vmbox[/folder][@context][|varname[|options]])\n"
00062 " Optionally sets <varname> to the number of messages in that folder."
00063 " Assumes folder of INBOX if not specified.\n"
00064 " The option string may contain zero or the following character:\n"
00065 " 'j' -- jump to priority n+101, if there is voicemail in the folder indicated.\n"
00066 " This application sets the following channel variable upon completion:\n"
00067 " HASVMSTATUS The result of the voicemail check returned as a text string as follows\n"
00068 " <# of messages in the folder, 0 for NONE>\n";
00069
00070 static char *app_hasnewvoicemail = "HasNewVoicemail";
00071 static char *hasnewvoicemail_synopsis = "Conditionally branches to priority + 101 with the right options set";
00072 static char *hasnewvoicemail_descrip =
00073 "HasNewVoicemail(vmbox[/folder][@context][|varname[|options]])\n"
00074 "Assumes folder 'INBOX' if folder is not specified. Optionally sets <varname> to the number of messages\n"
00075 "in that folder.\n"
00076 " The option string may contain zero of the following character:\n"
00077 " 'j' -- jump to priority n+101, if there is new voicemail in folder 'folder' or INBOX\n"
00078 " This application sets the following channel variable upon completion:\n"
00079 " HASVMSTATUS The result of the new voicemail check returned as a text string as follows\n"
00080 " <# of messages in the folder, 0 for NONE>\n";
00081
00082 STANDARD_LOCAL_USER;
00083
00084 LOCAL_USER_DECL;
00085
00086 #ifdef USE_ODBC_STORAGE
00087 static int hasvoicemail_internal(const char *context, const char *mailbox, const char *folder)
00088 {
00089 int nummsgs = 0;
00090 int res;
00091 SQLHSTMT stmt;
00092 char sql[256];
00093 char rowdata[20];
00094
00095 if (!folder)
00096 folder = "INBOX";
00097
00098 if (ast_strlen_zero(mailbox))
00099 return 0;
00100 if (ast_strlen_zero(context))
00101 context = "default";
00102
00103 odbc_obj *obj;
00104 obj = fetch_odbc_obj(odbc_database, 0);
00105 if (obj) {
00106 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
00107 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00108 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00109 goto yuck;
00110 }
00111 snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s/voicemail/%s/%s/%s'", odbc_table, ast_config_AST_SPOOL_DIR, context, mailbox, folder);
00112 res = SQLPrepare(stmt, sql, SQL_NTS);
00113 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00114 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
00115 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00116 goto yuck;
00117 }
00118 res = odbc_smart_execute(obj, stmt);
00119 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00120 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
00121 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00122 goto yuck;
00123 }
00124 res = SQLFetch(stmt);
00125 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00126 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
00127 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00128 goto yuck;
00129 }
00130 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
00131 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00132 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00133 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00134 goto yuck;
00135 }
00136 nummsgs = atoi(rowdata);
00137 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00138 } else
00139 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
00140
00141 yuck:
00142 return nummsgs;
00143 }
00144
00145 #else
00146
00147 static int hasvoicemail_internal(const char *context, const char *mailbox, const char *folder)
00148 {
00149 DIR *dir;
00150 struct dirent *de;
00151 char fn[256];
00152 int count = 0;
00153
00154 if (ast_strlen_zero(folder))
00155 folder = "INBOX";
00156 if (ast_strlen_zero(context))
00157 context = "default";
00158
00159 if (ast_strlen_zero(mailbox))
00160 return 0;
00161 snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/%s", ast_config_AST_SPOOL_DIR, context, mailbox, folder);
00162 dir = opendir(fn);
00163 if (!dir)
00164 return 0;
00165 while ((de = readdir(dir))) {
00166 if (!strncasecmp(de->d_name, "msg", 3) && !strcasecmp(de->d_name + 8, "txt"))
00167 count++;
00168 }
00169 closedir(dir);
00170 return count;
00171 }
00172 #endif
00173
00174 static int hasvoicemail_exec(struct ast_channel *chan, void *data)
00175 {
00176 struct localuser *u;
00177 char *input, *varname = NULL, *vmbox, *context = "default";
00178 char *vmfolder;
00179 int vmcount = 0;
00180 static int dep_warning = 0;
00181 int priority_jump = 0;
00182 char tmp[12];
00183 AST_DECLARE_APP_ARGS(args,
00184 AST_APP_ARG(vmbox);
00185 AST_APP_ARG(varname);
00186 AST_APP_ARG(options);
00187 );
00188
00189 if (!dep_warning) {
00190 ast_log(LOG_WARNING, "The applications HasVoicemail and HasNewVoicemail have been deprecated. Please use the VMCOUNT() function instead.\n");
00191 dep_warning = 1;
00192 }
00193
00194 if (!data) {
00195 ast_log(LOG_WARNING, "HasVoicemail requires an argument (vm-box[/folder][@context][|varname[|options]])\n");
00196 return -1;
00197 }
00198
00199 LOCAL_USER_ADD(u);
00200
00201 input = ast_strdupa((char *)data);
00202 if (! input) {
00203 ast_log(LOG_ERROR, "Out of memory error\n");
00204 LOCAL_USER_REMOVE(u);
00205 return -1;
00206 }
00207
00208 AST_STANDARD_APP_ARGS(args, input);
00209
00210 if ((vmbox = strsep(&args.vmbox, "@")))
00211 if (!ast_strlen_zero(args.vmbox))
00212 context = args.vmbox;
00213 if (!vmbox)
00214 vmbox = args.vmbox;
00215
00216 vmfolder = strchr(vmbox, '/');
00217 if (vmfolder) {
00218 *vmfolder = '\0';
00219 vmfolder++;
00220 } else {
00221 vmfolder = "INBOX";
00222 }
00223
00224 if (args.options) {
00225 if (strchr(args.options, 'j'))
00226 priority_jump = 1;
00227 }
00228
00229 vmcount = hasvoicemail_internal(context, vmbox, vmfolder);
00230
00231 if (varname) {
00232 snprintf(tmp, sizeof(tmp), "%d", vmcount);
00233 pbx_builtin_setvar_helper(chan, varname, tmp);
00234 }
00235
00236 if (vmcount > 0) {
00237
00238 if (priority_jump || option_priority_jumping) {
00239 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
00240 ast_log(LOG_WARNING, "VM box %s@%s has new voicemail, but extension %s, priority %d doesn't exist\n", vmbox, context, chan->exten, chan->priority + 101);
00241 }
00242 }
00243
00244 snprintf(tmp, sizeof(tmp), "%d", vmcount);
00245 pbx_builtin_setvar_helper(chan, "HASVMSTATUS", tmp);
00246
00247 LOCAL_USER_REMOVE(u);
00248
00249 return 0;
00250 }
00251
00252 static char *acf_vmcount_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
00253 {
00254 struct localuser *u;
00255 char *args, *context, *box, *folder;
00256
00257 LOCAL_USER_ACF_ADD(u);
00258
00259 buf[0] = '\0';
00260
00261 args = ast_strdupa(data);
00262 if (!args) {
00263 ast_log(LOG_ERROR, "Out of memory");
00264 LOCAL_USER_REMOVE(u);
00265 return buf;
00266 }
00267
00268 box = strsep(&args, "|");
00269 if (strchr(box, '@')) {
00270 context = box;
00271 box = strsep(&context, "@");
00272 } else {
00273 context = "default";
00274 }
00275
00276 if (args) {
00277 folder = args;
00278 } else {
00279 folder = "INBOX";
00280 }
00281
00282 snprintf(buf, len, "%d", hasvoicemail_internal(context, box, folder));
00283
00284 LOCAL_USER_REMOVE(u);
00285
00286 return buf;
00287 }
00288
00289 struct ast_custom_function acf_vmcount = {
00290 .name = "VMCOUNT",
00291 .synopsis = "Counts the voicemail in a specified mailbox",
00292 .syntax = "VMCOUNT(vmbox[@context][|folder])",
00293 .desc =
00294 " context - defaults to \"default\"\n"
00295 " folder - defaults to \"INBOX\"\n",
00296 .read = acf_vmcount_exec,
00297 };
00298
00299 static int load_config(void)
00300 {
00301 #ifdef USE_ODBC_STORAGE
00302 struct ast_config *cfg;
00303 char *tmp;
00304 cfg = ast_config_load("voicemail.conf");
00305 if (cfg) {
00306 if (! (tmp = ast_variable_retrieve(cfg, "general", "odbcstorage")))
00307 tmp = "asterisk";
00308 ast_copy_string(odbc_database, tmp, sizeof(odbc_database));
00309
00310 if (! (tmp = ast_variable_retrieve(cfg, "general", "odbctable")))
00311 tmp = "voicemessages";
00312 ast_copy_string(odbc_table, tmp, sizeof(odbc_table));
00313 ast_config_destroy(cfg);
00314 }
00315 #endif
00316 return 0;
00317 }
00318
00319 int reload(void)
00320 {
00321 return load_config();
00322 }
00323
00324 int unload_module(void)
00325 {
00326 int res;
00327
00328 res = ast_custom_function_unregister(&acf_vmcount);
00329 res |= ast_unregister_application(app_hasvoicemail);
00330 res |= ast_unregister_application(app_hasnewvoicemail);
00331
00332 STANDARD_HANGUP_LOCALUSERS;
00333
00334 return res;
00335 }
00336
00337 int load_module(void)
00338 {
00339 int res;
00340 load_config();
00341 res = ast_custom_function_register(&acf_vmcount);
00342 res |= ast_register_application(app_hasvoicemail, hasvoicemail_exec, hasvoicemail_synopsis, hasvoicemail_descrip);
00343 res |= ast_register_application(app_hasnewvoicemail, hasvoicemail_exec, hasnewvoicemail_synopsis, hasnewvoicemail_descrip);
00344
00345 return res;
00346 }
00347
00348 char *description(void)
00349 {
00350 return tdesc;
00351 }
00352
00353 int usecount(void)
00354 {
00355 int res;
00356 STANDARD_USECOUNT(res);
00357 return res;
00358 }
00359
00360 char *key()
00361 {
00362 return ASTERISK_GPL_KEY;
00363 }