Index: trunk/apps/app_authenticate.c
===================================================================
--- trunk/apps/app_authenticate.c	(revision 7432)
+++ trunk/apps/app_authenticate.c	(working copy)
@@ -41,6 +41,7 @@
 #include "asterisk/app.h"
 #include "asterisk/astdb.h"
 #include "asterisk/utils.h"
+#include "asterisk/options.h"
 
 static char *tdesc = "Authentication Application";
 
@@ -49,9 +50,9 @@
 static char *synopsis = "Authenticate a user";
 
 static char *descrip =
-"  Authenticate(password[|options]): This application asks the caller to enter a\n"
-"given password in order to continue dialplan execution. If the password begins\n"
-"with the '/' character, it is interpreted as a file which contains a list of\n"
+"  Authenticate(password[|options[|maxdigits]]): This application asks the caller\n"
+"to enter a given password in order to continue dialplan execution. If the password\n"
+"begins with the '/' character, it is interpreted as a file which contains a list of\n"
 "valid passwords, listed 1 password per line in the file.\n"
 "  When using a database key, the value associated with the key can be anything.\n"
 "Users have three attempts to authenticate before the channel is hung up. If the\n"
@@ -66,6 +67,10 @@
 "         the file. When one of the passwords is matched, the channel will have\n"
 "         its account code set to the corresponding account code in the file.\n"
 "     r - Remove the database key upon successful entry (valid with 'd' only)\n"
+"     maxdigits  - maximum acceptable number of digits. Stops reading after\n"
+"         maxdigits have been entered (without requiring the user to\n"
+"         press the '#' key).\n"
+"         Defaults to 0 - no limit - wait for the user press the '#' key.\n"
 ;
 
 STANDARD_LOCAL_USER;
@@ -77,12 +82,18 @@
 	int res=0;
 	int jump = 0;
 	int retries;
+	int maxdigits;
 	struct localuser *u;
-	char password[256]="";
 	char passwd[256];
-	char *opts;
+	char *parse;
 	char *prompt;
-	
+
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(password);
+		AST_APP_ARG(options);
+		AST_APP_ARG(maxdigits);
+	);
+		
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
 		return -1;
@@ -97,38 +108,54 @@
 			return -1;
 		}
 	}
-	
-	strncpy(password, data, sizeof(password) - 1);
-	opts=strchr(password, '|');
-	if (opts) {
-		*opts = 0;
-		opts++;
-	} else
-		opts = "";
-	if (strchr(opts, 'j'))
+
+        parse = ast_strdupa(data);
+	if (!parse) {
+		ast_log(LOG_ERROR, "Out of memory\n");
+		LOCAL_USER_REMOVE(u);
+		return -1;
+	}
+        AST_STANDARD_APP_ARGS(args, parse);
+
+	if (strchr(args.options, 'j'))
 		jump = 1;
+								
+	if (!ast_strlen_zero(args.maxdigits)) {
+		maxdigits = strtol(args.maxdigits, NULL, 10);
+		if ((maxdigits<1) || (maxdigits>sizeof(passwd)-2))
+                        maxdigits = sizeof(passwd) - 2;
+	} else {
+		maxdigits = sizeof(passwd) - 2;
+	}
+	if(!maxdigits) {
+		/* In case when 0 supplied */
+		maxdigits = sizeof(passwd) - 2;
+	}
+	if(option_debug > 2) {
+		ast_log(LOG_DEBUG, "Accepting a maximum of %d digits.\n", maxdigits);
+	}
 	/* Start asking for password */
 	prompt = "agent-pass";
 	for (retries = 0; retries < 3; retries++) {
-		res = ast_app_getdata(chan, prompt, passwd, sizeof(passwd) - 2, 0);
+		res = ast_app_getdata(chan, prompt, passwd, maxdigits, 0);
 		if (res < 0)
 			break;
 		res = 0;
-		if (password[0] == '/') {
-			if (strchr(opts, 'd')) {
+		if (args.password[0] == '/') {
+			if (strchr(args.options, 'd')) {
 				char tmp[256];
 				/* Compare against a database key */
-				if (!ast_db_get(password + 1, passwd, tmp, sizeof(tmp))) {
+				if (!ast_db_get(args.password + 1, passwd, tmp, sizeof(tmp))) {
 					/* It's a good password */
-					if (strchr(opts, 'r')) {
-						ast_db_del(password + 1, passwd);
+					if (strchr(args.options, 'r')) {
+						ast_db_del(args.password + 1, passwd);
 					}
 					break;
 				}
 			} else {
 				/* Compare against a file */
 				FILE *f;
-				f = fopen(password, "r");
+				f = fopen(args.password, "r");
 				if (f) {
 					char buf[256] = "";
 					char md5passwd[33] = "";
@@ -138,7 +165,7 @@
 						fgets(buf, sizeof(buf), f);
 						if (!feof(f) && !ast_strlen_zero(buf)) {
 							buf[strlen(buf) - 1] = '\0';
-							if (strchr(opts, 'm')) {
+							if (strchr(args.options, 'm')) {
 								md5secret = strchr(buf, ':');
 								if (md5secret == NULL)
 									continue;
@@ -146,13 +173,13 @@
 								md5secret++;
 								ast_md5_hash(md5passwd, passwd);
 								if (!strcmp(md5passwd, md5secret)) {
-									if (strchr(opts, 'a'))
+									if (strchr(args.options, 'a'))
 										ast_cdr_setaccount(chan, buf);
 									break;
 								}
 							} else {
 								if (!strcmp(passwd, buf)) {
-									if (strchr(opts, 'a'))
+									if (strchr(args.options, 'a'))
 										ast_cdr_setaccount(chan, buf);
 									break;
 								}
@@ -161,7 +188,7 @@
 					}
 					fclose(f);
 					if (!ast_strlen_zero(buf)) {
-						if (strchr(opts, 'm')) {
+						if (strchr(args.options, 'm')) {
 							if (md5secret && !strcmp(md5passwd, md5secret))
 								break;
 						} else {
@@ -170,17 +197,17 @@
 						}
 					}
 				} else 
-					ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
+					ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", args.password, strerror(errno));
 			}
 		} else {
 			/* Compare against a fixed password */
-			if (!strcmp(passwd, password)) 
+			if (!strcmp(passwd, args.password)) 
 				break;
 		}
 		prompt="auth-incorrect";
 	}
 	if ((retries < 3) && !res) {
-		if (strchr(opts, 'a') && !strchr(opts, 'm')) 
+		if (strchr(args.options, 'a') && !strchr(args.options, 'm')) 
 			ast_cdr_setaccount(chan, passwd);
 		res = ast_streamfile(chan, "auth-thankyou", chan->language);
 		if (!res)
