Index: astconf.h =================================================================== RCS file: /usr/cvsroot/asterisk/Attic/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 May 2005 15:00:51 -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.153 diff -u -p -r1.153 asterisk.c --- asterisk.c 15 May 2005 03:21:51 -0000 1.153 +++ asterisk.c 16 May 2005 15:00:52 -0000 @@ -133,6 +133,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; @@ -1576,6 +1577,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) { @@ -1655,6 +1657,15 @@ static void ast_readconfig(void) { /* Specify cache directory */ } 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; + } + } /* Build transcode paths via SLINEAR, instead of directly */ } else if (!strcasecmp(v->name, "transcode_via_sln")) { option_transcode_slin = ast_true(v->value); Index: utils.c =================================================================== RCS file: /usr/cvsroot/asterisk/utils.c,v retrieving revision 1.44 diff -u -p -r1.44 utils.c --- utils.c 15 May 2005 22:33:01 -0000 1.44 +++ utils.c 16 May 2005 15:00:52 -0000 @@ -13,6 +13,7 @@ #define __USE_GNU #endif #include +#include #include #include #include @@ -23,7 +24,7 @@ #include #include #include - +#include "astconf.h" #include "asterisk/lock.h" #include "asterisk/utils.h" #include "asterisk/io.h" @@ -191,6 +192,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.36 diff -u -p -r1.36 app_directory.c --- apps/app_directory.c 7 May 2005 12:49:36 -0000 1.36 +++ apps/app_directory.c 16 May 2005 15:00:52 -0000 @@ -138,8 +138,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.12 diff -u -p -r1.12 app_hasnewvoicemail.c --- apps/app_hasnewvoicemail.c 21 Apr 2005 06:02:43 -0000 1.12 +++ apps/app_hasnewvoicemail.c 16 May 2005 15:00:52 -0000 @@ -97,6 +97,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 +109,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.214 diff -u -p -r1.214 app_voicemail.c --- apps/app_voicemail.c 16 May 2005 13:36:35 -0000 1.214 +++ apps/app_voicemail.c 16 May 2005 15:00:54 -0000 @@ -651,11 +651,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%s/%s/%s", VM_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); @@ -1730,7 +1725,7 @@ static int invent_message(struct ast_cha { int res; char fn[256]; - snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext); + ast_util_vm_dir(fn, sizeof(fn), context, ext, "greet"); RETRIEVE(fn, -1); if (ast_fileexists(fn, NULL, NULL) > 0) { res = ast_streamfile(chan, fn, chan->language); @@ -1838,7 +1833,7 @@ static int has_voicemail(const char *mai context++; } else context = "default"; - snprintf(fn, sizeof(fn), "%s/%s/%s/%s", VM_SPOOL_DIR, context, tmp, folder); + ast_util_vm_dir(fn, sizeof(fn), context, tmp, (char *) folder); dir = opendir(fn); if (!dir) return 0; @@ -1895,7 +1890,7 @@ static int messagecount(const char *mail } else context = "default"; if (newmsgs) { - snprintf(fn, sizeof(fn), "%s/%s/%s/INBOX", VM_SPOOL_DIR, context, tmp); + ast_util_vm_dir(fn, sizeof(fn), context, tmp, "INBOX"); dir = opendir(fn); if (dir) { while ((de = readdir(dir))) { @@ -1908,7 +1903,7 @@ static int messagecount(const char *mail } } if (oldmsgs) { - snprintf(fn, sizeof(fn), "%s/%s/%s/Old", VM_SPOOL_DIR, context, tmp); + ast_util_vm_dir(fn, sizeof(fn), context, tmp, "Old"); dir = opendir(fn); if (dir) { while ((de = readdir(dir))) { @@ -1928,24 +1923,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); ast_lock_path(topath); recipmsgnum = 0; @@ -2030,25 +2022,20 @@ static int leave_voicemail(struct ast_ch else strncpy(ext_context, vmu->context, sizeof(ext_context) - 1); if (busy) - snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext); + ast_util_vm_dir(prefile, sizeof(prefile), vmu->context, ext, "busy"); else if (unavail) - snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext); - snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext); + ast_util_vm_dir(prefile, sizeof(prefile), vmu->context, ext, "unavail"); + + ast_util_vm_dir(tempfile, sizeof(tempfile), vmu->context, ext, "temp"); RETRIEVE(tempfile, -1); if (ast_fileexists(tempfile, NULL, NULL) > 0) strncpy(prefile, tempfile, sizeof(prefile) - 1); DISPOSE(tempfile, -1); - 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(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)) { @@ -2297,7 +2284,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); ast_lock_path(ddir); 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); @@ -3079,7 +3066,8 @@ static int forward_message(struct ast_ch /* if (ast_play_and_wait(chan, "vm-savedto")) break; */ - snprintf(todir, sizeof(todir), "%s%s/%s/INBOX", VM_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, "%s", sys); @@ -3271,7 +3259,8 @@ static int play_message_callerid(struct } if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */ if (!res) { - snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, 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) { @@ -3402,7 +3391,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; /* @@ -4182,7 +4171,8 @@ static int vm_newuser(struct ast_channel /* If forcename is set, have the user record their name */ if (ast_test_flag(vmu, VM_FORCENAME)) { - snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, 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, NULL); if (cmd < 0 || cmd == 't' || cmd == '#') return cmd; @@ -4190,11 +4180,13 @@ static int vm_newuser(struct ast_channel /* If forcegreetings is set, have the user record their greetings */ if (ast_test_flag(vmu, VM_FORCEGREET)) { - snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, 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, NULL); if (cmd < 0 || cmd == 't' || cmd == '#') return cmd; - snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, 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, NULL); if (cmd < 0 || cmd == 't' || cmd == '#') return cmd; @@ -4228,15 +4220,17 @@ static int vm_options(struct ast_channel retries = 0; switch (cmd) { case '1': - snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, 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, NULL); break; case '2': - snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, 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, NULL); break; case '3': - snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, 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, NULL); break; case '4': @@ -4318,7 +4312,8 @@ static int vm_tempgreeting(struct ast_ch bytes += adsi_voice_mode(buf + bytes, 0); adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); } - snprintf(prefile,sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username); + ast_util_vm_dir(prefile,sizeof(prefile), vmu->context, + vms->username, "temp"); while((cmd >= 0) && (cmd != 't')) { if (cmd) retries = 0; @@ -4679,10 +4674,12 @@ 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/%s", VM_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/%s/%s", VM_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; @@ -5183,7 +5180,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.30 diff -u -p -r1.30 utils.h --- include/asterisk/utils.h 15 May 2005 22:33:02 -0000 1.30 +++ include/asterisk/utils.h 16 May 2005 15:00:55 -0000 @@ -166,6 +166,19 @@ struct ast_realloca { #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); + #define AST_STACKSIZE 256 * 1024 #define ast_pthread_create(a,b,c,d) ast_pthread_create_stack(a,b,c,d,0) extern int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize);