[asterisk-commits] oej: branch oej/minivoicemail r54597 - /team/oej/minivoicemail/apps/app_minivm.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Thu Feb 15 07:19:15 MST 2007


Author: oej
Date: Thu Feb 15 08:19:15 2007
New Revision: 54597

URL: http://svn.digium.com/view/asterisk?view=rev&rev=54597
Log:
Splitting up into two application, one for playing prompts and one for
recording/sending e-mail


Modified:
    team/oej/minivoicemail/apps/app_minivm.c

Modified: team/oej/minivoicemail/apps/app_minivm.c
URL: http://svn.digium.com/view/asterisk/team/oej/minivoicemail/apps/app_minivm.c?view=diff&rev=54597&r1=54596&r2=54597
==============================================================================
--- team/oej/minivoicemail/apps/app_minivm.c (original)
+++ team/oej/minivoicemail/apps/app_minivm.c Thu Feb 15 08:19:15 2007
@@ -155,7 +155,8 @@
 static char MVM_SPOOL_DIR[AST_CONFIG_MAX_PATH];
 
 static char *tdesc = "Mini VoiceMail (A minimal Voicemail e-mail System)";
-static char *app = "MiniVM";		 /* Leave a message */
+static char *app = "MiniVM";		 	/* Leave a message */
+static char *app_greet = "MiniVMgreet";		/* Play voicemail prompts */
 
 enum {
 	OPT_SILENT =	   (1 << 0),
@@ -637,6 +638,7 @@
 	return 0;
 }
 
+static struct minivm_user *mvm_user_alloc(void);
 
 /*! \brief Allocate new vm user and set default values */
 static struct minivm_user *mvm_user_alloc()
@@ -662,6 +664,11 @@
 	struct minivm_user *vmu = NULL, *cur;
 
 	ast_mutex_lock(&minivmlock);
+
+	if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
+		ast_log(LOG_NOTICE, "No username or domain? \n");
+		return NULL;
+	}
 
 	AST_LIST_LOCK(&minivm_accounts);
 	AST_LIST_TRAVERSE(&minivm_accounts, cur, list) {
@@ -746,6 +753,7 @@
 {
 	FILE *p = NULL;
 	int pfd;
+	char email[256];
 	char date[256];
 	char host[MAXHOSTNAMELEN];
 	char who[256];
@@ -761,10 +769,11 @@
 	char *passdata2;
 	struct ast_channel *ast;
 
-	if (vmu && ast_strlen_zero(vmu->email)) {
-		ast_log(LOG_WARNING, "E-mail address missing for mailbox [%s].  E-mail will not be sent.\n", vmu->username);
-		return(0);
-	}
+	if (vmu && !ast_strlen_zero(vmu->email)) {
+		ast_copy_string(email, vmu->email, sizeof(email));	
+	} else
+		snprintf(email, sizeof(email), "%s@%s", vmu->username, vmu->domain);
+
 	if (!strcmp(format, "wav49"))
 		format = "WAV";
 
@@ -861,14 +870,12 @@
 	fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>\n", msgnum, (unsigned int)rand(), mailbox, getpid(), host);
 	fprintf(p, "MIME-Version: 1.0\n");
 
-	if (attach_user_voicemail) {
-		/* Something unique. */
-		snprintf(bound, sizeof(bound), "voicemail_%d%s%d%d", msgnum, mailbox, getpid(), (unsigned int)rand());
-
-		fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
-
-		fprintf(p, "--%s\n", bound);
-	}
+	/* Something unique. */
+	snprintf(bound, sizeof(bound), "voicemail_%d%s%d%d", msgnum, mailbox, getpid(), (unsigned int)rand());
+
+	fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
+
+	fprintf(p, "--%s\n", bound);
 	fprintf(p, "Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", global_charset);
 	if (emailbody) {
 		char *passdata;
@@ -885,22 +892,20 @@
 			"want to check it when you get a chance.  Thanks!\n\n\t\t\t\t--Asterisk\n\n", vmu->fullname, 
 			dur, msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
 	}
-	if (attach_user_voicemail) {
-		/* Eww. We want formats to tell us their own MIME type */
-		char *ctype = "audio/x-";
-		if (!strcasecmp(format, "ogg"))
-			ctype = "application/";
-		
-		fprintf(p, "--%s\n", bound);
-		fprintf(p, "Content-Type: %s%s; name=\"msg%04d.%s\"\n", ctype, format, msgnum, format);
-		fprintf(p, "Content-Transfer-Encoding: base64\n");
-		fprintf(p, "Content-Description: Voicemail sound attachment.\n");
-		fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.%s\"\n\n", msgnum, format);
-
-		snprintf(fname, sizeof(fname), "%s.%s", attach, format);
-		base_encode(fname, p);
-		fprintf(p, "\n\n--%s--\n.\n", bound);
-	}
+	/* Eww. We want formats to tell us their own MIME type */
+	char *ctype = "audio/x-";
+	if (!strcasecmp(format, "ogg"))
+		ctype = "application/";
+	
+	fprintf(p, "--%s\n", bound);
+	fprintf(p, "Content-Type: %s%s; name=\"msg%04d.%s\"\n", ctype, format, msgnum, format);
+	fprintf(p, "Content-Transfer-Encoding: base64\n");
+	fprintf(p, "Content-Description: Voicemail sound attachment.\n");
+	fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.%s\"\n\n", msgnum, format);
+
+	snprintf(fname, sizeof(fname), "%s.%s", attach, format);
+	base_encode(fname, p);
+	fprintf(p, "\n\n--%s--\n.\n", bound);
 	fclose(p);
 	snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", global_mailcmd, tmp, tmp);
 	ast_safe_system(tmp2);
@@ -1075,10 +1080,8 @@
 				if (option_verbose > 2)
 					ast_verbose(VERBOSE_PREFIX_3 "Recording the message\n");
 			}
-			if (recorded && outsidecaller) {
- 				cmd = ast_play_and_wait(chan, SOUND_INTRO);
+			if (recorded && outsidecaller) 
  				cmd = ast_play_and_wait(chan, "beep");
- 			}
  			recorded = 1;
  			/* After an attempt has been made to record message, we have to take care of INTRO and beep for incoming messages, but not for greetings */
 			if (record_gain)
@@ -1088,35 +1091,13 @@
 			cmd = ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, global_silencethreshold, global_maxsilence, unlockdir, acceptdtmf, canceldtmf);
 			if (record_gain)
 				ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
- 			if (cmd == -1) {
+ 			if (cmd == -1) 
  			/* User has hung up, no options to give */
  				return cmd;
-			}
- 			if (cmd == '0') {
+ 			if (cmd == '0')
  				break;
- 			} else if (cmd == '*') {
+ 			else if (cmd == '*')
  				break;
- 			} 
-#if 0			
- 			else if (vmu->review && (*duration < 5)) {
- 				/* Message is too short */
- 				if (option_verbose > 2)
-					ast_verbose(VERBOSE_PREFIX_3 "Message too short\n");
-				cmd = ast_play_and_wait(chan, "vm-tooshort");
- 				cmd = vm_delete(recordfile);
- 				break;
- 			}
- 			else if (vmu->review && (cmd == 2 && *duration < (global_maxsilence + 3))) {
- 				/* Message is all silence */
- 				if (option_verbose > 2)
-					ast_verbose(VERBOSE_PREFIX_3 "Nothing recorded\n");
- 				cmd = vm_delete(recordfile);
-				cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
-				if (!cmd)
- 					cmd = ast_play_and_wait(chan, "vm-speakup");
- 				break;
- 			}
-#endif
  			else {
  				/* If all is well, a message exists */
  				message_exists = 1;
@@ -1133,20 +1114,6 @@
 		case '#':
  			cmd = ast_play_and_wait(chan, "vm-sorry");
  			break;
-#if 0 
-/*  XXX Commented out for the moment because of the dangers of deleting
-    a message while recording (can put the message numbers out of sync) */
- 		case '*':
- 			/* Cancel recording, delete message, offer to take another message*/
- 			cmd = ast_play_and_wait(chan, "vm-deleted");
- 			cmd = vm_delete(recordfile);
- 			if (outsidecaller) {
- 				res = vm_exec(chan, NULL);
- 				return res;
- 			}
- 			else
- 				return 1;
-#endif
  		case '0':
 			if(!ast_test_flag(vmu, MVM_OPERATOR)) {
  				cmd = ast_play_and_wait(chan, "vm-sorry");
@@ -1174,8 +1141,7 @@
 				return cmd;
  			if (message_exists) {
  				cmd = ast_play_and_wait(chan, "vm-review");
- 			}
- 			else {
+ 			} else {
  				cmd = ast_play_and_wait(chan, "vm-torerecord");
  				if (!cmd)
  					cmd = ast_waitfordigit(chan, 600);
@@ -1186,10 +1152,6 @@
  				if (!cmd)
  					cmd = ast_waitfordigit(chan, 600);
  			}
-#if 0
-			if (!cmd)
- 				cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
-#endif
  			if (!cmd)
  				cmd = ast_waitfordigit(chan, 6000);
  			if (!cmd) {
@@ -1265,7 +1227,7 @@
 }
 
  
-/*! \brief Leave voicemail message, store into file prepared for sending e-mail 
+/*! \brief Record voicemail message, store into file prepared for sending e-mail 
 */
 static int leave_voicemail(struct ast_channel *chan, char *username, struct leave_vm_options *options)
 {
@@ -1275,19 +1237,12 @@
 	int res = 0, txtdes;
 	int msgnum;
 	int duration = 0;
-	int ausemacro = 0;
-	int ousemacro = 0;
-	int ouseexten = 0;
 	char date[256];
 	char dir[PATH_MAX], tmpdir[PATH_MAX];
-	char dest[PATH_MAX];
 	char fn[PATH_MAX];
-	char prefile[PATH_MAX] = "";
-	char tempfile[PATH_MAX] = "";
 	char ext_context[256] = "";
 	char fmt[80];
 	char *domain;
-	char ecodes[16] = "#";
 	char tmp[256] = "", *tmpptr;
 	struct minivm_user *vmu;
 	struct minivm_user svm;
@@ -1323,126 +1278,6 @@
 	else
 		ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
 
-	if (ast_test_flag(options, OPT_BUSY_GREETING)) {
-		res = create_dirpath(dest, sizeof(dest), vmu->domain, username, "busy");
-		snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", MVM_SPOOL_DIR, vmu->domain, username);
-	} else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
-		res = create_dirpath(dest, sizeof(dest), vmu->domain, username, "unavail");
-		snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", MVM_SPOOL_DIR, vmu->domain, username);
-	}
-	snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", MVM_SPOOL_DIR, vmu->domain, username);
-	if (!(res = create_dirpath(dest, sizeof(dest), vmu->domain, username, "temp"))) {
-		ast_log(LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
-		return -1;
-	}
-
-	/* Play the message */
-	if (ast_fileexists(tempfile, NULL, NULL) > 0)
-		ast_copy_string(prefile, tempfile, sizeof(prefile));
-
-	/* It's easier just to try to make it than to check for its existence */
-	create_dirpath(tmpdir, sizeof(tmpdir), vmu->domain, username, "tmp");
-
-	/* Check current or macro-calling context for special extensions */
-	if (ast_test_flag(vmu, MVM_OPERATOR)) {
-		if (!ast_strlen_zero(vmu->exit)) {
-			if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
-				strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
-				ouseexten = 1;
-			}
-		} else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
-			strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
-			ouseexten = 1;
-		}
-		else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
-			strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
-			ousemacro = 1;
-		}
-	}
-
-	if (!ast_strlen_zero(vmu->exit)) {
-		if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
-			strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
-	} else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
-		strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
-	else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
-		strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
-		ausemacro = 1;
-	}
-
-	/* Play the beginning intro if desired */
-	if (!ast_strlen_zero(prefile)) {
-		if (ast_fileexists(prefile, NULL, NULL) > 0) {
-			if (ast_streamfile(chan, prefile, chan->language) > -1) 
-				res = ast_waitstream(chan, ecodes);
-		} else {
-			if (option_debug > 1)
-				ast_log(LOG_DEBUG, "%s doesn't exist, doing what we can\n", prefile);
-			res = invent_message(chan, vmu->domain, username, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
-		}
-		if (res < 0) {
-			if (option_debug > 1)
-				ast_log(LOG_DEBUG, "Hang up during prefile playback\n");
-			free_user(vmu);
-			pbx_builtin_setvar_helper(chan, "MINIVMSTATUS", "FAILED");
-			return -1;
-		}
-	}
-	if (res == '#') {
-		/* On a '#' we skip the instructions */
-		ast_set_flag(options, OPT_SILENT);
-		res = 0;
-	}
-	if (!res && !ast_test_flag(options, OPT_SILENT)) {
-		res = ast_streamfile(chan, SOUND_INTRO, chan->language);
-		if (!res)
-			res = ast_waitstream(chan, ecodes);
-		if (res == '#') {
-			ast_set_flag(options, OPT_SILENT);
-			res = 0;
-		}
-	}
-	if (res > 0)
-		ast_stopstream(chan);
-	/* Check for a '*' here in case the caller wants to escape from voicemail to something
-	   other than the operator -- an automated attendant or mailbox login for example */
-	if (res == '*') {
-		chan->exten[0] = 'a';
-		chan->exten[1] = '\0';
-		if (!ast_strlen_zero(vmu->exit)) {
-			ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
-		} else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
-			ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
-		}
-		chan->priority = 0;
-		free_user(vmu);
-		pbx_builtin_setvar_helper(chan, "MINIVMSTATUS", "USEREXIT");
-		return 0;
-	}
-
-	/* Check for a '0' here */
-	if (res == '0') {
-	transfer:
-		if(ouseexten || ousemacro) {
-			chan->exten[0] = 'o';
-			chan->exten[1] = '\0';
-			if (!ast_strlen_zero(vmu->exit)) {
-				ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
-			} else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
-				ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
-			}
-			ast_play_and_wait(chan, "transfer");
-			chan->priority = 0;
-			free_user(vmu);
-			pbx_builtin_setvar_helper(chan, "MINIVMSTATUS", "USEREXIT");
-		}
-		return 0;
-	}
-	if (res < 0) {
-		free_user(vmu);
-		pbx_builtin_setvar_helper(chan, "MINIVMSTATUS", "FAILED");
-		return -1;
-	}
 	/* The meat of recording the message...  All the announcements and beeps have been played*/
 	if (ast_strlen_zero(vmu->format))
 		ast_copy_string(fmt, default_vmformat, sizeof(fmt));
@@ -1481,11 +1316,18 @@
 	/* Store information */
 	txt = fdopen(txtdes, "w+");
 	if (txt) {
+		struct tm tm;
+		time_t now;
+		char timebuf[30];
 		get_date(date, sizeof(date));
+		now = time(NULL);
+		//ast_localtime(&now, &tm, the_zone ? the_zone->timezone : NULL);
+		ast_localtime(&now, &tm, NULL);
+		strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm);
 		
 		fprintf(txt, 
-			/* "Mailbox:domain:macrocontext:exten:priority:callerchan:callerid:origdate:origtime:category:duration" */
-			"%s:%s:%s:%s:%s:%s:%d:%s:%d:%s\n",
+			/* "Mailbox:domain:macrocontext:exten:priority:callerchan:callerid:origdate:origtime:duration" */
+			"%s:%s:%s:%s:%d:%s:%s:%s:%s:%s\n",
 			username,
 			chan->context,
 			chan->macrocontext, 
@@ -1493,7 +1335,8 @@
 			chan->priority,
 			chan->name,
 			ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
-			date, (long)time(NULL),
+			date, 
+			timebuf,
 			"durationholder"); 
 	} else
 		ast_log(LOG_WARNING, "Error opening text file for output\n");
@@ -1544,9 +1387,7 @@
 		}
 	}
 
-	if (res == '0') {
-		goto transfer;
-	} else if (res > 0)
+	if (res > 0)
 		res = 0;
 
 	if (duration < global_vmminmessage)
@@ -1560,6 +1401,218 @@
 	return res;
 }
 
+/*! \brief Play voicemail prompts - either generic or user specific */
+static int minivm_prompt_exec(struct ast_channel *chan, void *data)
+{
+	struct localuser *u;
+	struct leave_vm_options leave_options;
+	int argc;
+	char *argv[2];
+	struct ast_flags flags = { 0 };
+	char *opts[OPT_ARG_ARRAY_SIZE];
+	int res = 0;
+	int ausemacro = 0;
+	int ousemacro = 0;
+	int ouseexten = 0;
+	char tmp[PATH_MAX];
+	char tmpdir[PATH_MAX];
+	char dest[PATH_MAX];
+	char prefile[PATH_MAX] = "";
+	char tempfile[PATH_MAX] = "";
+	char ext_context[256] = "";
+	char *domain;
+	char ecodes[16] = "#";
+	char *tmpptr;
+	struct minivm_user *vmu;
+	struct minivm_user svm;
+	char *username = argv[0];
+	
+	LOCAL_USER_ADD(u);
+
+	/* Answer channel if it's not already answered */
+	if (chan->_state != AST_STATE_UP)
+		ast_answer(chan);
+
+	if (ast_strlen_zero(data))  {
+		ast_log(LOG_ERROR, "Minivm needs at least an account argument \n");
+		LOCAL_USER_REMOVE(u);
+		return -1;
+	}
+	tmpptr = ast_strdupa((char *)data);
+	if (!tmpptr) {
+		ast_log(LOG_ERROR, "Out of memory\n");
+		LOCAL_USER_REMOVE(u);
+		return -1;
+	}
+	argc = ast_app_separate_args(tmpptr, '|', argv, sizeof(argv) / sizeof(argv[0]));
+	if (argc == 2) {
+		if (ast_app_parse_options(minivm_app_options, &flags, opts, argv[1])) {
+			LOCAL_USER_REMOVE(u);
+			return -1;
+		}
+		ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_PRIORITY_JUMP);
+	}
+
+	ast_copy_string(tmp, argv[0], sizeof(tmp));
+	username = tmp;
+	domain = strchr(tmp, '@');
+	if (domain) {
+		*domain = '\0';
+		domain++;
+	} 
+	if (ast_strlen_zero(domain) || ast_strlen_zero(username)) {
+		ast_log(LOG_ERROR, "Need username at domain as argument. Sorry. Argument 0 %s\n", argv[0]);
+		LOCAL_USER_REMOVE(u);
+		return -1;
+	}
+	if (option_debug)
+		ast_log(LOG_DEBUG, "Trying to find prompts for user %s in domain %s\n", username, domain);
+
+	if (!(vmu = find_user(&svm, domain, username))) {
+		/* We could not find user, let's exit */
+		ast_log(LOG_WARNING, "No entry in voicemail config file for '%s@%s'\n", username, domain);
+		if (ast_test_flag(&leave_options, OPT_PRIORITY_JUMP) || option_priority_jumping)
+			ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
+		pbx_builtin_setvar_helper(chan, "MINIVMGREETSTATUS", "FAILED");
+		return res;
+	}
+
+	/* Setup pre-file if appropriate */
+	if (strcmp(vmu->domain, "localhost"))
+		snprintf(ext_context, sizeof(ext_context), "%s@%s", username, vmu->domain);
+	else
+		ast_copy_string(ext_context, vmu->domain, sizeof(ext_context));
+
+	if (ast_test_flag(&leave_options, OPT_BUSY_GREETING)) {
+		res = create_dirpath(dest, sizeof(dest), vmu->domain, username, "busy");
+		snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", MVM_SPOOL_DIR, vmu->domain, username);
+	} else if (ast_test_flag(&leave_options, OPT_UNAVAIL_GREETING)) {
+		res = create_dirpath(dest, sizeof(dest), vmu->domain, username, "unavail");
+		snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", MVM_SPOOL_DIR, vmu->domain, username);
+	}
+	snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", MVM_SPOOL_DIR, vmu->domain, username);
+	if (!(res = create_dirpath(dest, sizeof(dest), vmu->domain, username, "temp"))) {
+		ast_log(LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
+		return -1;
+	}
+
+	/* Play the message */
+	if (ast_fileexists(tempfile, NULL, NULL) > 0)
+		ast_copy_string(prefile, tempfile, sizeof(prefile));
+
+	/* It's easier just to try to make it than to check for its existence */
+	create_dirpath(tmpdir, sizeof(tmpdir), vmu->domain, username, "tmp");
+
+	/* Check current or macro-calling context for special extensions */
+	if (ast_test_flag(vmu, MVM_OPERATOR)) {
+		if (!ast_strlen_zero(vmu->exit)) {
+			if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
+				strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
+				ouseexten = 1;
+			}
+		} else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
+			strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
+			ouseexten = 1;
+		}
+		else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
+			strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
+			ousemacro = 1;
+		}
+	}
+
+	if (!ast_strlen_zero(vmu->exit)) {
+		if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
+			strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
+	} else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
+		strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
+	else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
+		strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
+		ausemacro = 1;
+	}
+
+	/* Play the beginning intro if desired */
+	if (!ast_strlen_zero(prefile)) {
+		if (ast_fileexists(prefile, NULL, NULL) > 0) {
+			if (ast_streamfile(chan, prefile, chan->language) > -1) 
+				res = ast_waitstream(chan, ecodes);
+		} else {
+			if (option_debug > 1)
+				ast_log(LOG_DEBUG, "%s doesn't exist, doing what we can\n", prefile);
+			res = invent_message(chan, vmu->domain, username, ast_test_flag(&leave_options, OPT_BUSY_GREETING), ecodes);
+		}
+		if (res < 0) {
+			if (option_debug > 1)
+				ast_log(LOG_DEBUG, "Hang up during prefile playback\n");
+			free_user(vmu);
+			pbx_builtin_setvar_helper(chan, "MINIVMGREETSTATUS", "FAILED");
+			return -1;
+		}
+	}
+	if (res == '#') {
+		/* On a '#' we skip the instructions */
+		ast_set_flag(&leave_options, OPT_SILENT);
+		res = 0;
+	}
+	if (!res && !ast_test_flag(&leave_options, OPT_SILENT)) {
+		res = ast_streamfile(chan, SOUND_INTRO, chan->language);
+		if (!res)
+			res = ast_waitstream(chan, ecodes);
+		if (res == '#') {
+			ast_set_flag(&leave_options, OPT_SILENT);
+			res = 0;
+		}
+	}
+	if (res > 0)
+		ast_stopstream(chan);
+	/* Check for a '*' here in case the caller wants to escape from voicemail to something
+	   other than the operator -- an automated attendant or mailbox login for example */
+	if (res == '*') {
+		chan->exten[0] = 'a';
+		chan->exten[1] = '\0';
+		if (!ast_strlen_zero(vmu->exit)) {
+			ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
+		} else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
+			ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
+		}
+		chan->priority = 0;
+		free_user(vmu);
+		pbx_builtin_setvar_helper(chan, "MINIVMGREETSTATUS", "USEREXIT");
+		return 0;
+	}
+
+	/* Check for a '0' here */
+	if (res == '0') {
+		if(ouseexten || ousemacro) {
+			chan->exten[0] = 'o';
+			chan->exten[1] = '\0';
+			if (!ast_strlen_zero(vmu->exit)) {
+				ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
+			} else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
+				ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
+			}
+			ast_play_and_wait(chan, "transfer");
+			chan->priority = 0;
+			free_user(vmu);
+			pbx_builtin_setvar_helper(chan, "MINIVMGREETSTATUS", "USEREXIT");
+		}
+		return 0;
+	}
+	if (res < 0) {
+		free_user(vmu);
+		pbx_builtin_setvar_helper(chan, "MINIVMGREETSTATUS", "FAILED");
+		return -1;
+	}
+
+	pbx_builtin_setvar_helper(chan, "MINIVMGREETSTATUS", "SUCCESS");
+
+	/* Ok, we're ready to rock and roll. Return to dialplan */
+	LOCAL_USER_REMOVE(u);
+
+	return res;
+
+}
+
+/*! \brief Dialplan core function */
 static int minivm_exec(struct ast_channel *chan, void *data)
 {
 	int res = 0;
@@ -1604,29 +1657,10 @@
 				ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
 				LOCAL_USER_REMOVE(u);
 				return -1;
-			} else {
+			} else 
 				leave_options.record_gain = (signed char) gain;
-			}
-		}
-	} else {
-		/* old style options parsing */
-		while (*argv[0]) {
-			if (*argv[0] == 's') {
-				ast_set_flag(&leave_options, OPT_SILENT);
-				argv[0]++;
-			} else if (*argv[0] == 'b') {
-				ast_set_flag(&leave_options, OPT_BUSY_GREETING);
-				argv[0]++;
-			} else if (*argv[0] == 'u') {
-				ast_set_flag(&leave_options, OPT_UNAVAIL_GREETING);
-				argv[0]++;
-			} else if (*argv[0] == 'j') {
-				ast_set_flag(&leave_options, OPT_PRIORITY_JUMP);
-				argv[0]++;
-			} else 
-				break;
-		}
-	}
+		}
+	} 
 
 	/* Now run the appliation and good luck to you! */
 	res = leave_voicemail(chan, argv[0], &leave_options);
@@ -1640,6 +1674,7 @@
 		pbx_builtin_setvar_helper(chan, "MINIVMSTATUS", "FAILED");
 		res = 0;
 	}
+	pbx_builtin_setvar_helper(chan, "MINIVMSTATUS", "SUCCESS");
 	
 	LOCAL_USER_REMOVE(u);
 
@@ -2030,6 +2065,7 @@
 	int res;
 	
 	res = ast_unregister_application(app);
+	res = ast_unregister_application(app_greet);
 	//res |= ast_cli_unregister(&show_voicemail_users_cli);
 	//res |= ast_cli_unregister(&show_voicemail_zones_cli);
 	ast_uninstall_vm_functions();
@@ -2044,13 +2080,20 @@
 	"If you don't understand it, don't use it. Read the source.\n"
 	"Syntax: minivm(username at domain[,options])\n"
 	"If there's no user account for that address, a temporary account will\n"
-	"be used with default options.\n";
+	"be used with default options.\n\n";
+
+char *synopsis_vm_greet = "Play voicemail prompts";
+char *descrip_vm_greet = "No documentation. This is a professional application.\n"
+	"If you don't understand it, don't use it. Read the source.\n"
+	"Syntax: minivm_greet(username at domain[,options])\n"
+	"Plays default prompts or user specific prompts.\n\n";
 
 /*! \brief Load mini voicemail module */
 int load_module(void)
 {
 	int res;
 	res = ast_register_application(app, minivm_exec, synopsis_vm, descrip_vm);
+	res = ast_register_application(app_greet, minivm_prompt_exec, synopsis_vm_greet, descrip_vm_greet);
 
 	if (res)
 		return(res);



More information about the asterisk-commits mailing list