Asterisk.org: Developer Documentation (28 Oct 2009)

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 }