Wed Oct 28 15:47:48 2009

Asterisk developer's documentation


app_hasnewvoicemail.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Changes Copyright (c) 2004 - 2005 Todd Freeman <freeman@andrews.edu>
00005  * 
00006  * 95% based on HasNewVoicemail by:
00007  * 
00008  * Copyright (c) 2003 Tilghman Lesher.  All rights reserved.
00009  * 
00010  * Tilghman Lesher <asterisk-hasnewvoicemail-app@the-tilghman.com>
00011  *
00012  * See http://www.asterisk.org for more information about
00013  * the Asterisk project. Please do not directly contact
00014  * any of the maintainers of this project for assistance;
00015  * the project provides a web site, mailing lists and IRC
00016  * channels for your use.
00017  *
00018  * This program is free software, distributed under the terms of
00019  * the GNU General Public License Version 2. See the LICENSE file
00020  * at the top of the source tree.
00021  */
00022 
00023 /*! \file
00024  *
00025  * \brief HasVoicemail application
00026  *
00027  * \ingroup applications
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: 43924 $")
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    /* If no mailbox, return immediately */
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    /* If no mailbox, return immediately */
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    /* Set the count in the channel variable */
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       /* Branch to the next extension */
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\n");
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 }

Generated on Wed Oct 28 15:47:48 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6