[Asterisk-Dev] app_voicemail.c rework on static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)

Michael Anderson michael.l.anderson at gmail.com
Tue Oct 4 18:02:27 MST 2005


I had a problem with password changes not being saved to the
voicemail.conf file and traced it to some issues with the
vm_change_password function in app_voicemail.c.  Comments were not
properly being ignored and if they contained '[' ']' characters could
change the currentcontext variable causing the test to fail at line
690.

I have tested the following patch and it seems to work well.  I'm not
sure how to submit the patch (this is my first for OSS) so I'll put it
here for now.

===========================
--- asterisk/apps/app_voicemail.c	2005-10-03 21:24:51.981917024 -0700
+++ app_voicemail.c	2005-10-03 21:25:18.354907720 -0700
@@ -609,7 +609,6 @@
 	char currcontext[256] ="";
 	char tmpin[AST_CONFIG_MAX_PATH];
 	char tmpout[AST_CONFIG_MAX_PATH];
-	char *user, *pass, *rest, *trim, *tempcontext;
 	struct stat statbuf;

 	if (!change_password_realtime(vmu, newpassword))
@@ -635,73 +634,113 @@
 			return;
 	}

-	while (!feof(configin)) {
+  while (!feof(configin)) {
 		/* Read in the line */
 		fgets(inbuf, sizeof(inbuf), configin);
 		linenum++;
 		if (!feof(configin)) {
+			char *user = NULL, *pass = NULL, *rest = NULL, *trim = NULL,
+				*comment = NULL, *tmpctx = NULL, *tmpctxend = NULL;
+			
 			/* Make a backup of it */
 			memcpy(orig, inbuf, sizeof(orig));
-			/* Strip trailing \n and comment */
-			inbuf[strlen(inbuf) - 1] = '\0';
-			user = strchr(inbuf, ';');
-			if (user)
-				*user = '\0';
-			user=inbuf;
-			while (*user < 33)
-				user++;
-			/* check for '[' (opening of context name ) */
-			tempcontext = strchr(user, '[');
-			if (tempcontext) {
-				ast_copy_string(currcontext, tempcontext +1, sizeof(currcontext));
-				/* now check for ']' */
-				tempcontext = strchr(currcontext, ']');
-				if (tempcontext)
-					*tempcontext = '\0';
-				else
-					currcontext[0] = '\0';
-			}
-			pass = strchr(user, '=');
-			if (pass > user) {
-				trim = pass - 1;
-				while (*trim && *trim < 33) {
-					*trim = '\0';
-					trim--;
-				}
-			}
-			if (pass) {
-				*pass = '\0';
-				pass++;
-				if (*pass == '>')
-					pass++;
-				while (*pass && *pass < 33)
-					pass++;
+			
+			/*
+				Read the file line by line, split each line into a comment and
command section
+				only parse the command portion of the line
+			*/
+			if (inbuf[strlen(inbuf) - 1] == '\n')
+				inbuf[strlen(inbuf) - 1] = '\0';
+			comment = strchr(inbuf, ';');
+			if (comment) {
+				*comment = '\0'; // Now inbuf is terminated just before the comment
+				comment++;
 			}
-			if (pass) {
-				rest = strchr(pass,',');
-				if (rest) {
-					*rest = '\0';
-					rest++;
+			
+			if (inbuf[0] != '\0') { // skip over parsing for lines starting
with a comment character and empty lines
+				/* Check for a context, first '[' to first ']' */
+				tmpctx = strchr(inbuf, '[');
+				if (tmpctx) {
+					tmpctxend = strchr(inbuf, ']');
+					if (tmpctxend && (tmpctxend > tmpctx)) {
+						// Valid context
+						memcpy(currcontext, tmpctx + 1, tmpctxend - tmpctx - 1);
+						currcontext[tmpctxend - tmpctx - 1] = '\0';
+					} else {
+						tmpctx = NULL;
+					}
 				}
-			} else
-				rest = NULL;
-
+				
+				if (!tmpctx) {
+					// This isn't a context line, check for MBX => PSWD...
+					user = inbuf;
+					pass = strchr(user, '=');
+					if(pass > user) {
+						/* We have a line in the form of aaaaa=aaaaaa */
+						*pass = '\0';
+						pass++;
+						
+						/* Trim whitespace from user */
+						trim = pass - 2;
+						while (*trim && *trim < 33) {
+							*trim = '\0';
+							trim--;
+						}
+						
+						/* Trim whitespace and '>' from pass */
+						if (*pass == '>') {
+							*pass = '\0';
+							pass++;
+						}
+						while (*pass && *pass < 33) {
+							*pass = '\0';
+							pass++;
+						}
+						
+						/*
+						   Since no whitespace allowed in fields, or more correctly white space
+						   inside the fields is there for a purpose, we can just terminate pass
+						   at the comma or EOL whichever comes first.
+						*/
+						trim = strchr(pass, ',');
+						if (trim) {
+							*trim = '\0';
+							rest = trim + 1;
+						} else {
+							rest = NULL;
+						}
+					} else {
+						user = NULL;
+						pass = NULL;
+						rest = NULL;
+					}
+				}
+			}			
+			
 			/* Compare user, pass AND context */
 			if (user && *user && !strcmp(user, vmu->mailbox) &&
 				 pass && !strcmp(pass, vmu->password) &&
 				 currcontext && *currcontext && !strcmp(currcontext, vmu->context)) {
+				
+				/* Write */
 				/* This is the line */
 				if (rest) {
-					fprintf(configout, "%s => %s,%s\n", vmu->mailbox,newpassword,rest);
+					fprintf(configout, "%s => %s,%s", vmu->mailbox,newpassword,rest);
 				} else {
-					fprintf(configout, "%s => %s\n", vmu->mailbox,newpassword);
+					fprintf(configout, "%s => %s", vmu->mailbox,newpassword);
+				}
+				// If there was a comment on the line print it out
+				if (comment) {
+					fprintf(configout, ";%s\n", comment);
+				} else {
+					fprintf(configout, "\n");
 				}
 			} else {
 				/* Put it back like it was */
-				fprintf(configout, "%s", orig);
+				fprintf(configout, orig);
 			}
 		}
-	}
+  }
 	fclose(configin);
 	fclose(configout);


===========================

--
===========================
Michael Anderson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: app_voicemail.c.patch
Type: application/octet-stream
Size: 4658 bytes
Desc: not available
Url : http://lists.digium.com/pipermail/asterisk-dev/attachments/20051004/d884f7a0/app_voicemail.c.obj


More information about the asterisk-dev mailing list