Index: app.c =================================================================== RCS file: /usr/cvsroot/asterisk/app.c,v retrieving revision 1.34 diff -u -p -r1.34 app.c --- app.c 26 Oct 2004 02:21:43 -0000 1.34 +++ app.c 16 Nov 2004 15:35:47 -0000 @@ -183,7 +183,7 @@ int ast_app_has_voicemail(const char *ma context++; } else context = "default"; - snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR, context, tmp, folder); + ast_util_vm_dir(fn, sizeof(fn), context, tmp, (char *) folder); dir = opendir(fn); if (!dir) return 0; @@ -240,7 +240,7 @@ int ast_app_messagecount(const char *mai } else context = "default"; if (newmsgs) { - snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp); + ast_util_vm_dir(fn, sizeof(fn), context, tmp, "INBOX"); dir = opendir(fn); if (dir) { while ((de = readdir(dir))) { @@ -253,7 +253,7 @@ int ast_app_messagecount(const char *mai } } if (oldmsgs) { - snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/Old", (char *)ast_config_AST_SPOOL_DIR, context, tmp); + ast_util_vm_dir(fn, sizeof(fn), context, tmp, "Old"); dir = opendir(fn); if (dir) { while ((de = readdir(dir))) { Index: astconf.h =================================================================== RCS file: /usr/cvsroot/asterisk/astconf.h,v retrieving revision 1.1 diff -u -p -r1.1 astconf.h --- astconf.h 30 Jan 2003 15:03:20 -0000 1.1 +++ astconf.h 16 Nov 2004 15:35:47 -0000 @@ -28,5 +28,6 @@ extern char ast_config_AST_KEY_DIR[AST_C extern char ast_config_AST_PID[AST_CONFIG_MAX_PATH]; extern char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH]; extern char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH]; +extern int ast_config_AST_VM_HASH_LEN; #endif Index: asterisk.c =================================================================== RCS file: /usr/cvsroot/asterisk/asterisk.c,v retrieving revision 1.130 diff -u -p -r1.130 asterisk.c --- asterisk.c 11 Nov 2004 14:43:18 -0000 1.130 +++ asterisk.c 16 Nov 2004 15:35:49 -0000 @@ -123,6 +123,7 @@ char ast_config_AST_KEY_DIR[AST_CONFIG_M char ast_config_AST_PID[AST_CONFIG_MAX_PATH]; char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH]; char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH]; +int ast_config_AST_VM_HASH_LEN; static char *_argv[256]; static int shuttingdown = 0; @@ -1512,6 +1513,7 @@ static void ast_readconfig(void) { strncpy((char *)ast_config_AST_PID,AST_PID,sizeof(ast_config_AST_PID)-1); strncpy((char *)ast_config_AST_SOCKET,AST_SOCKET,sizeof(ast_config_AST_SOCKET)-1); strncpy((char *)ast_config_AST_RUN_DIR,AST_RUN_DIR,sizeof(ast_config_AST_RUN_DIR)-1); + ast_config_AST_VM_HASH_LEN = 0; /* no asterisk.conf? no problem, use buildtime config! */ if (!cfg) { @@ -1563,6 +1565,15 @@ static void ast_readconfig(void) { option_cache_record_files = ast_true(v->value); } else if (!strcasecmp(v->name, "record_cache_dir")) { strncpy(record_cache_dir,v->value,AST_CACHE_DIR_LEN); + } else if (!strcasecmp(v->name, "vmhashlen")) { + if (sscanf(v->value, "%d", &ast_config_AST_VM_HASH_LEN) == 1) { + if (ast_config_AST_VM_HASH_LEN < 0) { + ast_config_AST_VM_HASH_LEN = 0; + } + if (ast_config_AST_VM_HASH_LEN > 5) { + ast_config_AST_VM_HASH_LEN = 5; + } + } } v = v->next; } Index: utils.c =================================================================== RCS file: /usr/cvsroot/asterisk/utils.c,v retrieving revision 1.22 diff -u -p -r1.22 utils.c --- utils.c 17 Oct 2004 22:13:05 -0000 1.22 +++ utils.c 16 Nov 2004 15:35:49 -0000 @@ -13,6 +13,7 @@ #define __USE_GNU #endif #include +#include #include #include #include @@ -23,6 +24,7 @@ #include #include #include +#include "astconf.h" #include static char base64[64]; @@ -175,6 +177,38 @@ struct hostent *ast_gethostbyname(const return &hp->hp; } +int ast_util_vm_dir(char *buff, int bufflen, char *context, char *ext, char *mailbox) +{ + char hashpart[11] = "_/_/_/_/_/"; + int numhashchars = 0; + int p = 0; + int extlen = 0; + + if (!buff || !context || !ext || !mailbox) { + return(0); + } + + hashpart[ast_config_AST_VM_HASH_LEN * 2] = '\0'; + + /* Set the number of characters from the end of ext that will be used */ + extlen = strlen(ext); + numhashchars = (ast_config_AST_VM_HASH_LEN > extlen + ? extlen : ast_config_AST_VM_HASH_LEN); + + /* Take characters from end of ext, and put in every-other spot in + * beginning of hashpart IE: ext 12345 --> hashpart 5/4/ + */ + for (p=0; numhashchars > 0; numhashchars--) { + hashpart[p] = ext[extlen - (p/2) - 1]; + hashpart[p + 1] = '/'; + p += 2; + } + + snprintf(buff, bufflen, "%s/voicemail/%s/%s%s/%s", + ast_config_AST_SPOOL_DIR, context, hashpart, ext, mailbox); + + return(strlen(buff)); +} /* This is a regression test for recursive mutexes. test_for_thread_safety() will return 0 if recursive mutex locks are Index: apps/app_directory.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_directory.c,v retrieving revision 1.28 diff -u -p -r1.28 app_directory.c --- apps/app_directory.c 2 Oct 2004 00:58:31 -0000 1.28 +++ apps/app_directory.c 16 Nov 2004 15:35:49 -0000 @@ -135,8 +135,7 @@ static int play_mailbox_owner(struct ast char fn2[256]; /* Check for the VoiceMail2 greeting first */ - snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet", - (char *)ast_config_AST_SPOOL_DIR, context, ext); + ast_util_vm_dir(fn, sizeof(fn), context, ext, "greet"); /* Otherwise, check for an old-style Voicemail greeting */ snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet", Index: apps/app_hasnewvoicemail.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_hasnewvoicemail.c,v retrieving revision 1.10 diff -u -p -r1.10 app_hasnewvoicemail.c --- apps/app_hasnewvoicemail.c 3 Oct 2004 21:23:54 -0000 1.10 +++ apps/app_hasnewvoicemail.c 16 Nov 2004 15:35:50 -0000 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,7 @@ static int hasvoicemail_exec(struct ast_ vmfolder = input; input = temps; } + if ((vmbox = strsep(&input, "@"))) if (input && !ast_strlen_zero(input)) context = input; @@ -108,7 +110,7 @@ static int hasvoicemail_exec(struct ast_ vmfolder++; } else vmfolder = "INBOX"; - snprintf(vmpath,sizeof(vmpath), "%s/voicemail/%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR, context, vmbox, vmfolder); + ast_util_vm_dir(vmpath, sizeof(vmpath), context, vmbox, vmfolder); if (!(vmdir = opendir(vmpath))) { ast_log(LOG_NOTICE, "Voice mailbox %s at %s does not exist\n", vmbox, vmpath); } else { Index: apps/app_voicemail.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_voicemail.c,v retrieving revision 1.172 diff -u -p -r1.172 app_voicemail.c --- apps/app_voicemail.c 13 Nov 2004 16:13:07 -0000 1.172 +++ apps/app_voicemail.c 16 Nov 2004 15:35:55 -0000 @@ -653,11 +653,6 @@ static void vm_change_password_shell(str ast_safe_system(buf); } -static int make_dir(char *dest, int len, char *context, char *ext, char *mailbox) -{ - return snprintf(dest, len, "%s/voicemail/%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR,context, ext, mailbox); -} - static int make_file(char *dest, int len, char *dir, int num) { return snprintf(dest, len, "%s/msg%04d", dir, num); @@ -1068,7 +1063,7 @@ static int invent_message(struct ast_cha { int res; char fn[256]; - snprintf(fn, sizeof(fn), "voicemail/%s/%s/greet", context, ext); + ast_util_vm_dir(fn, sizeof(fn), context, ext, "greet"); if (ast_fileexists(fn, NULL, NULL) > 0) { res = ast_streamfile(chan, fn, chan->language); if (res) @@ -1191,24 +1186,21 @@ static int notify_new_message(struct ast static void copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt) { char fromdir[256], todir[256], frompath[256], topath[256]; + char tmp[512]=""; char *frombox = mbox(imbox); int recipmsgnum; ast_log(LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context); - make_dir(todir, sizeof(todir), recip->context, "", ""); - /* It's easier just to try to make it than to check for its existence */ - if (mkdir(todir, 0700) && (errno != EEXIST)) - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", todir, strerror(errno)); - make_dir(todir, sizeof(todir), recip->context, recip->mailbox, ""); - /* It's easier just to try to make it than to check for its existence */ - if (mkdir(todir, 0700) && (errno != EEXIST)) - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", todir, strerror(errno)); - make_dir(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX"); - if (mkdir(todir, 0700) && (errno != EEXIST)) - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", todir, strerror(errno)); + ast_util_vm_dir(todir, sizeof(todir), + recip->context, recip->mailbox, "INBOX"); + snprintf(tmp, sizeof(tmp), "mkdir -p %s\n", todir); + ast_log(LOG_DEBUG, tmp); + ast_safe_system(tmp); + + ast_util_vm_dir(fromdir, sizeof(fromdir), + vmu->context, vmu->mailbox, frombox); - make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox); make_file(frompath, sizeof(frompath), fromdir, msgnum); recipmsgnum = 0; do { @@ -1293,20 +1285,13 @@ static int leave_voicemail(struct ast_ch else strncpy(ext_context, vmu->context, sizeof(ext_context) - 1); if (busy) - snprintf(prefile, sizeof(prefile), "voicemail/%s/%s/busy", vmu->context, ext); + ast_util_vm_dir(prefile, sizeof(prefile), vmu->context, ext, "busy"); else if (unavail) - snprintf(prefile, sizeof(prefile), "voicemail/%s/%s/unavail", vmu->context, ext); - make_dir(dir, sizeof(dir), vmu->context, "", ""); - /* It's easier just to try to make it than to check for its existence */ - if (mkdir(dir, 0700) && (errno != EEXIST)) - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno)); - make_dir(dir, sizeof(dir), vmu->context, ext, ""); - /* It's easier just to try to make it than to check for its existence */ - if (mkdir(dir, 0700) && (errno != EEXIST)) - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno)); - make_dir(dir, sizeof(dir), vmu->context, ext, "INBOX"); - if (mkdir(dir, 0700) && (errno != EEXIST)) - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno)); + ast_util_vm_dir(prefile, sizeof(prefile), vmu->context, ext, "unavail"); + ast_util_vm_dir(dir, sizeof(dir), vmu->context, ext, "INBOX"); + snprintf(tmp, sizeof(tmp), "mkdir -p %s\n", dir); + ast_log(LOG_DEBUG, tmp); + ast_safe_system(tmp); /* Check current or macro-calling context for special extensions */ if (!ast_strlen_zero(vmu->exit)) { @@ -1569,7 +1554,7 @@ static int save_to_folder(char *dir, int char *dbox = mbox(box); int x; make_file(sfn, sizeof(sfn), dir, msg); - make_dir(ddir, sizeof(ddir), context, username, dbox); + ast_util_vm_dir(ddir, sizeof(ddir), context, username, dbox); mkdir(ddir, 0700); for (x=0;xcontext, vmu->mailbox, "INBOX"); + ast_util_vm_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX"); make_file(fn, sizeof(fn), todir, msgnum); snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context); @@ -2284,7 +2269,8 @@ static int forward_message(struct ast_ch /* if (ast_play_and_wait(chan, "vm-savedto")) break; */ - snprintf(todir, sizeof(todir), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, vmtmp->context, vmtmp->mailbox); + ast_util_vm_dir(todir, sizeof(todir), vmtmp->context, + vmtmp->mailbox, "INBOX"); snprintf(sys, sizeof(sys), "mkdir -p %s\n", todir); snprintf(ext_context, sizeof(ext_context), "%s@%s", vmtmp->mailbox, vmtmp->context); ast_log(LOG_DEBUG, sys); @@ -2463,9 +2449,11 @@ static int play_message_callerid(struct if ((strcmp(cidinternalcontexts[i], context) == 0)) break; } + if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */ if (!res) { - snprintf(prefile, sizeof(prefile), "voicemail/%s/%s/greet", context, callerid); + ast_util_vm_dir(prefile, sizeof(prefile), context, callerid, + "greet"); if (!ast_strlen_zero(prefile)) { /* See if we can find a recorded name for this person instead of their extension number */ if (ast_fileexists(prefile, NULL, NULL) > 0) { @@ -2586,7 +2574,7 @@ static int play_message(struct ast_chann static void open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box) { strncpy(vms->curbox, mbox(box), sizeof(vms->curbox) - 1); - make_dir(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox); + ast_util_vm_dir(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox); vms->lastmsg = count_messages(vms->curdir) - 1; /* @@ -3210,15 +3198,21 @@ static int vm_options(struct ast_channel retries = 0; switch (cmd) { case '1': - snprintf(prefile,sizeof(prefile),"voicemail/%s/%s/unavail",vmu->context, vms->username); + ast_util_vm_dir(prefile, sizeof(prefile), vmu->context, + vms->username, "unavail"); + cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration); break; case '2': - snprintf(prefile,sizeof(prefile),"voicemail/%s/%s/busy",vmu->context, vms->username); + ast_util_vm_dir(prefile, sizeof(prefile), vmu->context, + vms->username, "busy"); + cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration); break; case '3': - snprintf(prefile,sizeof(prefile),"voicemail/%s/%s/greet",vmu->context, vms->username); + ast_util_vm_dir(prefile, sizeof(prefile), vmu->context, + vms->username, "greet"); + cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration); break; case '4': @@ -3522,10 +3516,13 @@ static int vm_execmain(struct ast_channe /* Set language from config to override channel language */ if (vmu->language && !ast_strlen_zero(vmu->language)) strncpy(chan->language, vmu->language, sizeof(chan->language)-1); - snprintf(vms.curdir, sizeof(vms.curdir), "%s/voicemail/%s", (char *)ast_config_AST_SPOOL_DIR, vmu->context); + ast_util_vm_dir(vms.curdir, sizeof(vms.curdir), vmu->context, "", ""); mkdir(vms.curdir, 0700); - snprintf(vms.curdir, sizeof(vms.curdir), "%s/voicemail/%s/%s", (char *)ast_config_AST_SPOOL_DIR, vmu->context, vms.username); + + ast_util_vm_dir(vms.curdir, sizeof(vms.curdir), vmu->context, + vms.username, ""); mkdir(vms.curdir, 0700); + /* Retrieve old and new message counts */ open_mailbox(&vms, vmu, 1); vms.oldmessages = vms.lastmsg + 1; @@ -4053,7 +4050,9 @@ static int handle_show_voicemail_users(i char count[12]; if ((argc == 3) || ((argc == 5) && !strcmp(argv[4],vmu->context))) { - make_dir(dirname, 255, vmu->context, vmu->mailbox, "INBOX"); + ast_util_vm_dir(dirname, sizeof(dirname), vmu->context, + vmu->mailbox, "INBOX"); + if ((vmdir = opendir(dirname))) { /* No matter what the format of VM, there will always be a .txt file for each message. */ while ((vment = readdir(vmdir))) Index: include/asterisk/utils.h =================================================================== RCS file: /usr/cvsroot/asterisk/include/asterisk/utils.h,v retrieving revision 1.10 diff -u -p -r1.10 utils.h --- include/asterisk/utils.h 17 Oct 2004 22:13:05 -0000 1.10 +++ include/asterisk/utils.h 16 Nov 2004 15:35:56 -0000 @@ -42,6 +42,19 @@ extern int ast_utils_init(void); #endif #define inet_ntoa __dont__use__inet_ntoa__use__ast_inet_ntoa__instead__ +/*! + * \brief Create a hashed directory path for voicemail + * \param buff pointer to string to build the directory inside of + * \param bufflen the size of buff above + * \param context pointer to the context name for the mailbox + * \param ext pointer to the username/extension of the mailbox + * \param mailbox pointer the the mailbox name IE: INBOX, etc. + * \return int size of buff when done + * + * Creates a hashed full path name to a given context, extension, mailbox name + */ +extern int ast_util_vm_dir(char *buff, int bufflen, char *context, char *ext, char *mailbox); + #ifdef __linux__ #define ast_pthread_create pthread_create #define ast_strcasestr strcasestr