[svn-commits] tilghman: trunk r128027 - in /trunk: ./ include/asterisk/ main/ pbx/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Jul 4 11:06:35 CDT 2008


Author: tilghman
Date: Fri Jul  4 11:06:34 2008
New Revision: 128027

URL: http://svn.digium.com/view/asterisk?view=rev&rev=128027
Log:
Merged revisions 127973 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r127973 | tilghman | 2008-07-03 22:30:30 -0500 (Thu, 03 Jul 2008) | 8 lines

Fix the 'dialplan remove extension' logic, so that it a) works with cidmatch,
and b) completes contexts correctly when the extension is ambiguous.
(closes issue #12980)
 Reported by: licedey
 Patches: 
       20080703__bug12980.diff.txt uploaded by Corydon76 (license 14)
 Tested by: Corydon76

........

Modified:
    trunk/   (props changed)
    trunk/include/asterisk/pbx.h
    trunk/main/pbx.c
    trunk/pbx/pbx_config.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Modified: trunk/include/asterisk/pbx.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/pbx.h?view=diff&rev=128027&r1=128026&r2=128027
==============================================================================
--- trunk/include/asterisk/pbx.h (original)
+++ trunk/include/asterisk/pbx.h Fri Jul  4 11:06:34 2008
@@ -588,7 +588,9 @@
  * 
  * \param context context to remove extension from
  * \param extension which extension to remove
- * \param priority priority of extension to remove
+ * \param priority priority of extension to remove (0 to remove all)
+ * \param callerid NULL to remove all; non-NULL to match a single record per priority
+ * \param matchcid non-zero to match callerid element (if non-NULL); 0 to match default case
  * \param registrar registrar of the extension
  *
  * This function removes an extension from a given context.
@@ -601,6 +603,13 @@
 
 int ast_context_remove_extension2(struct ast_context *con, const char *extension,
 	int priority, const char *registrar, int already_locked);
+
+int ast_context_remove_extension_callerid(const char *context, const char *extension,
+	int priority, const char *callerid, int matchcid, const char *registrar);
+
+int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension,
+	int priority, const char *callerid, int matchcid, const char *registrar,
+	int already_locked);
 
 /*! 
  * \brief Add an ignorepat

Modified: trunk/main/pbx.c
URL: http://svn.digium.com/view/asterisk/trunk/main/pbx.c?view=diff&rev=128027&r1=128026&r2=128027
==============================================================================
--- trunk/main/pbx.c (original)
+++ trunk/main/pbx.c Fri Jul  4 11:06:34 2008
@@ -4003,11 +4003,16 @@
  */
 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
 {
+	return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
+}
+
+int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar)
+{
 	int ret = -1; /* default error return */
 	struct ast_context *c = find_context_locked(context);
 
 	if (c) { /* ... remove extension ... */
-		ret = ast_context_remove_extension2(c, extension, priority, registrar, 1);
+		ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcid, registrar, 1);
 		ast_unlock_contexts();
 	}
 	return ret;
@@ -4025,23 +4030,34 @@
  */
 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
 {
+	return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
+}
+
+int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar, int already_locked)
+{
 	struct ast_exten *exten, *prev_exten = NULL;
 	struct ast_exten *peer;
 	struct ast_exten ex, *exten2, *exten3;
 	char dummy_name[1024];
+	struct ast_exten *previous_peer = NULL;
+	struct ast_exten *next_peer = NULL;
+	int found = 0;
 
 	if (!already_locked)
 		ast_wrlock_context(con);
 
 	/* Handle this is in the new world */
 
+	/* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
+	 * peers, not just those matching the callerid. */
 #ifdef NEED_DEBUG
-	ast_verb(3,"Removing %s/%s/%d from trees, registrar=%s\n", con->name, extension, priority, registrar);
+	ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcid ? "/" : "", matchcid ? callerid : "", registrar);
 #endif
 	/* find this particular extension */
 	ex.exten = dummy_name;
-	ex.matchcid = 0;
-	ast_copy_string(dummy_name,extension, sizeof(dummy_name));
+	ex.matchcid = matchcid;
+	ex.cidmatch = callerid;
+	ast_copy_string(dummy_name, extension, sizeof(dummy_name));
 	exten = ast_hashtab_lookup(con->root_table, &ex);
 	if (exten) {
 		if (priority == 0)
@@ -4070,7 +4086,7 @@
 					if (!exten3)
 						ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_table of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten);
 				}
-				
+			
 				exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
 				if (!exten3)
 					ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_table of context %s, extension %s!\n", priority, con->name, exten2->exten);
@@ -4108,9 +4124,8 @@
 		log_match_char_tree(con->pattern_tree, " ");
 	}
 #endif
-	
-
-	/* scan the extension list to find matching extension-registrar */
+
+	/* scan the extension list to find first matching extension-registrar */
 	for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
 		if (!strcmp(exten->exten, extension) &&
 			(!registrar || !strcmp(exten->registrar, registrar)))
@@ -4123,66 +4138,44 @@
 		return -1;
 	}
 
-	/* should we free all peers in this extension? (priority == 0)? */
-	if (priority == 0) {
-		/* remove this extension from context list */
-		if (prev_exten)
-			prev_exten->next = exten->next;
-		else
-			con->root = exten->next;
-
-		/* fire out all peers */
-		while ( (peer = exten) ) {
-			exten = peer->peer; /* prepare for next entry */
+	/* scan the priority list to remove extension with exten->priority == priority */
+	for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
+			peer && !strcmp(peer->exten, extension);
+			peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
+		if ((priority == 0 || peer->priority == priority) &&
+				(!callerid || !matchcid || (matchcid && !strcmp(peer->cidmatch, callerid))) &&
+				(!registrar || !strcmp(peer->registrar, registrar) )) {
+			found = 1;
+
+			/* we are first priority extension? */
+			if (!previous_peer) {
+				/*
+				 * We are first in the priority chain, so must update the extension chain.
+				 * The next node is either the next priority or the next extension
+				 */
+				struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
+
+				if (!prev_exten) {	/* change the root... */
+					con->root = next_node;
+				} else {
+					prev_exten->next = next_node; /* unlink */
+				}
+				if (peer->peer)	{ /* update the new head of the pri list */
+					peer->peer->next = peer->next;
+				}
+			} else { /* easy, we are not first priority in extension */
+				previous_peer->peer = peer->peer;
+			}
+
+			/* now, free whole priority extension */
 			destroy_exten(peer);
-		}
-	} else {
-		/* scan the priority list to remove extension with exten->priority == priority */
-		struct ast_exten *previous_peer = NULL;
-
-		for (peer = exten; peer; previous_peer = peer, peer = peer->peer) {
-			if (peer->priority == priority &&
-					(!registrar || !strcmp(peer->registrar, registrar) ))
-				break; /* found our priority */
-		}
-		if (!peer) { /* not found */
-			if (!already_locked)
-				ast_unlock_context(con);
-			return -1;
-		}
-		/* we are first priority extension? */
-		if (!previous_peer) {
-			/*
-			 * We are first in the priority chain, so must update the extension chain.
-			 * The next node is either the next priority or the next extension
-			 */
-			struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
-			if (next_node && next_node == peer->peer) {
-				next_node->peer_table = exten->peer_table; /* move the priority hash tabs over */
-				exten->peer_table = 0;
-				next_node->peer_label_table = exten->peer_label_table;
-				exten->peer_label_table = 0;
-			}
-			if (!prev_exten) {	/* change the root... */
-				con->root = next_node;
-			} else {
-				prev_exten->next = next_node; /* unlink */
-			}
-			if (peer->peer)	{ /* XXX update the new head of the pri list */
-				peer->peer->next = peer->next;
-			}
-			
-		} else { /* easy, we are not first priority in extension */
-			previous_peer->peer = peer->peer;
-		}
-
-		/* now, free whole priority extension */
-		destroy_exten(peer);
-		/* XXX should we return -1 ? */
+		} else {
+			previous_peer = peer;
+		}
 	}
 	if (!already_locked)
 		ast_unlock_context(con);
-	return 0;
+	return found ? 0 : -1;
 }
 
 

Modified: trunk/pbx/pbx_config.c
URL: http://svn.digium.com/view/asterisk/trunk/pbx/pbx_config.c?view=diff&rev=128027&r1=128026&r2=128027
==============================================================================
--- trunk/pbx/pbx_config.c (original)
+++ trunk/pbx/pbx_config.c Fri Jul  4 11:06:34 2008
@@ -149,9 +149,9 @@
 /*! \brief split extension\@context in two parts, return -1 on error.
  * The return string is malloc'ed and pointed by *ext
  */
-static int split_ec(const char *src, char **ext, char ** const ctx)
-{
-	char *c, *e = ast_strdup(src); /* now src is not used anymore */
+static int split_ec(const char *src, char **ext, char ** const ctx, char ** const cid)
+{
+	char *i, *c, *e = ast_strdup(src); /* now src is not used anymore */
 
 	if (e == NULL)
 		return -1;	/* malloc error */
@@ -167,7 +167,14 @@
 			free(e);
 			return -1;
 		}
-	} 
+	}
+	if (cid && (i = strchr(e, '/'))) {
+		*i++ = '\0';
+		*cid = i;
+	} else if (cid) {
+		/* Signal none detected */
+		*cid = NULL;
+	}
 	return 0;
 }
 
@@ -298,14 +305,14 @@
 static char *handle_cli_dialplan_remove_extension(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int removing_priority = 0;
-	char *exten, *context;
+	char *exten, *context, *cid;
 	char *ret = CLI_FAILURE;
 
 	switch (cmd) {
 	case CLI_INIT:
 		e->command = "dialplan remove extension";
 		e->usage =
-			"Usage: dialplan remove extension exten at context [priority]\n"
+			"Usage: dialplan remove extension exten[/cid]@context [priority]\n"
 			"       Remove an extension from a given context. If a priority\n"
 			"       is given, only that specific priority from the given extension\n"
 			"       will be removed.\n";
@@ -350,7 +357,7 @@
 	/*
 	 * Format exten at context checking ...
 	 */
-	if (split_ec(a->argv[3], &exten, &context))
+	if (split_ec(a->argv[3], &exten, &context, &cid))
 		return CLI_FAILURE; /* XXX malloc failure */
 	if ((!strlen(exten)) || (!(strlen(context)))) {
 		ast_cli(a->fd, "Missing extension or context name in third argument '%s'\n",
@@ -359,7 +366,9 @@
 		return CLI_FAILURE;
 	}
 
-	if (!ast_context_remove_extension(context, exten, removing_priority, registrar)) {
+	if (!ast_context_remove_extension_callerid(context, exten, removing_priority,
+			/* Do NOT substitute S_OR; it is NOT the same thing */
+			cid ? cid : (removing_priority ? "" : NULL), cid ? 1 : 0, registrar)) {
 		if (!removing_priority)
 			ast_cli(a->fd, "Whole extension %s@%s removed\n",
 				exten, context);
@@ -369,7 +378,11 @@
 			
 		ret = CLI_SUCCESS;
 	} else {
-		ast_cli(a->fd, "Failed to remove extension %s@%s\n", exten, context);
+		if (cid) {
+			ast_cli(a->fd, "Failed to remove extension %s/%s@%s\n", exten, cid, context);
+		} else {
+			ast_cli(a->fd, "Failed to remove extension %s@%s\n", exten, context);
+		}
 		ret = CLI_FAILURE;
 	}
 	free(exten);
@@ -381,15 +394,15 @@
 #ifdef BROKEN_READLINE
 /*
  * There is one funny thing, when you have word like 300@ and you hit
- * <tab>, you arguments will like as your word is '300 ', so it '@'
- * characters acts sometimes as word delimiter and sometimes as a part
- * of word
+ * <tab>, you arguments will act as your word is '300 ', so the '@'
+ * character acts sometimes as a word delimiter and sometimes as a part
+ * of a word.
  *
- * This fix function, allocates new word variable and store here every
- * time xxx at yyy always as one word and correct pos is set too
+ * This fix function allocates a new word variable and stores it every
+ * time as xxx at yyy. The correct pos is set, too.
  *
- * It's ugly, I know, but I'm waiting for Mark suggestion if upper is
- * bug or feature ...
+ * It's ugly, I know, but I'm waiting for Mark's suggestion if the
+ * previous is a bug or a feature ...
  */
 static int fix_complete_args(const char *line, char **word, int *pos)
 {
@@ -443,18 +456,21 @@
 
 	if (a->pos == 3) { /* 'dialplan remove extension _X_' (exten at context ... */
 		struct ast_context *c = NULL;
-		char *context = NULL, *exten = NULL;
+		char *context = NULL, *exten = NULL, *cid = NULL;
 		int le = 0;	/* length of extension */
 		int lc = 0;	/* length of context */
-
-		lc = split_ec(a->word, &exten, &context);
+		int lcid = 0; /* length of cid */
+
+		lc = split_ec(a->word, &exten, &context, &cid);
+		if (lc)	{ /* error */
 #ifdef BROKEN_READLINE
-		free(word2);
+			free(word2);
 #endif
-		if (lc)	/* error */
-			return NULL;
+			return NULL;
+		}
 		le = strlen(exten);
 		lc = strlen(context);
+		lcid = cid ? strlen(cid) : -1;
 
 		if (ast_rdlock_contexts()) {
 			ast_log(LOG_ERROR, "Failed to lock context list\n");
@@ -468,11 +484,22 @@
 			if (!partial_match(ast_get_context_name(c), context, lc))
 				continue;	/* context not matched */
 			while ( (e = ast_walk_context_extensions(c, e)) ) { /* try to complete extensions ... */
-				if ( partial_match(ast_get_extension_name(e), exten, le) && ++which > a->n) { /* n-th match */
-					/* If there is an extension then return exten at context. XXX otherwise ? */
-					if (exten)
-						asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c));
-					break;
+				if ( !strchr(a->word, '/') ||
+						(!strchr(a->word, '@') && partial_match(ast_get_extension_cidmatch(e), cid, lcid)) ||
+						(strchr(a->word, '@') && !strcmp(ast_get_extension_cidmatch(e), cid))) {
+					if ( ((strchr(a->word, '/') || strchr(a->word, '@')) && !strcmp(ast_get_extension_name(e), exten)) ||
+						 (!strchr(a->word, '/') && !strchr(a->word, '@') && partial_match(ast_get_extension_name(e), exten, le))) { /* n-th match */
+						if (++which > a->n) {
+							/* If there is an extension then return exten at context. */
+							if (ast_get_extension_matchcid(e) && (!strchr(a->word, '@') || strchr(a->word, '/'))) {
+								asprintf(&ret, "%s/%s@%s", ast_get_extension_name(e), ast_get_extension_cidmatch(e), ast_get_context_name(c));
+								break;
+							} else if (!ast_get_extension_matchcid(e) && !strchr(a->word, '/')) {
+								asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c));
+								break;
+							}
+						}
+					}
 				}
 			}
 			if (e)	/* got a match */
@@ -484,11 +511,11 @@
 		if (exten)
 			free(exten);
 	} else if (a->pos == 4) { /* 'dialplan remove extension EXT _X_' (priority) */
-		char *exten = NULL, *context, *p;
+		char *exten = NULL, *context, *cid, *p;
 		struct ast_context *c;
-		int le, lc, len;
+		int le, lc, lcid, len;
 		const char *s = skip_words(a->line, 3); /* skip 'dialplan' 'remove' 'extension' */
-		int i = split_ec(s, &exten, &context);	/* parse ext at context */
+		int i = split_ec(s, &exten, &context, &cid);	/* parse ext at context */
 
 		if (i)	/* error */
 			goto error3;
@@ -498,6 +525,7 @@
 			*p = '\0';
 		le = strlen(exten);
 		lc = strlen(context);
+		lcid = strlen(cid);
 		len = strlen(a->word);
 		if (le == 0 || lc == 0)
 			goto error3;
@@ -520,6 +548,9 @@
 				struct ast_exten *priority;
 				char buffer[10];
 
+				if (cid && strcmp(ast_get_extension_cidmatch(e), cid) != 0) {
+					continue;
+				}
 				if (strcmp(ast_get_extension_name(e), exten) != 0)
 					continue;
 				/* XXX lock e ? */
@@ -537,10 +568,10 @@
 	error3:
 		if (exten)
 			free(exten);
+	}
 #ifdef BROKEN_READLINE
-		free(word2);
+	free(word2);
 #endif
-	}
 	return ret; 
 }
 




More information about the svn-commits mailing list