[svn-commits] tilghman: branch 1.4 r127973 - in /branches/1.…

Top Page

Reply to this message
Author: SVN commits to the Digium repositories
Date:  
To: asterisk-commits, svn-commits
Subject: [svn-commits] tilghman: branch 1.4 r127973 - in /branches/1.4: include/asterisk/ main/ pbx/
Author: tilghman
Date: Thu Jul 3 22:30:30 2008
New Revision: 127973

URL: http://svn.digium.com/view/asterisk?view=rev&rev=127973
Log:
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:
branches/1.4/include/asterisk/pbx.h
branches/1.4/main/pbx.c
branches/1.4/pbx/pbx_config.c

Modified: branches/1.4/include/asterisk/pbx.h
URL: http://svn.digium.com/view/asterisk/branches/1.4/include/asterisk/pbx.h?view=diff&rev=127973&r1=127972&r2=127973
==============================================================================
--- branches/1.4/include/asterisk/pbx.h (original)
+++ branches/1.4/include/asterisk/pbx.h Thu Jul 3 22:30:30 2008
@@ -585,7 +585,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.
@@ -598,6 +600,12 @@

int ast_context_remove_extension2(struct ast_context *con, const char *extension,
    int priority, const char *registrar);
+
+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);

/*!
* \brief Add an ignorepat

Modified: branches/1.4/main/pbx.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/main/pbx.c?view=diff&rev=127973&r1=127972&r2=127973
==============================================================================
--- branches/1.4/main/pbx.c (original)
+++ branches/1.4/main/pbx.c Thu Jul 3 22:30:30 2008
@@ -2805,11 +2805,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);
+        ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid, matchcid, registrar);
        ast_unlock_contexts();
    }
    return ret;
@@ -2827,12 +2832,20 @@
*/
int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar)
{
+    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar);
+}
+
+int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar)
+{
    struct ast_exten *exten, *prev_exten = NULL;
    struct ast_exten *peer;
+    struct ast_exten *previous_peer = NULL;
+    struct ast_exten *next_peer = NULL;
+    int found = 0;

    ast_mutex_lock(&con->lock);

-    /* 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)))
@@ -2844,56 +2857,43 @@
        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 */
-            ast_mutex_unlock(&con->lock);
-            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 (!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;
+        }
    }
    ast_mutex_unlock(&con->lock);
-    return 0;
+    return found ? 0 : -1;
}



Modified: branches/1.4/pbx/pbx_config.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/pbx/pbx_config.c?view=diff&rev=127973&r1=127972&r2=127973
==============================================================================
--- branches/1.4/pbx/pbx_config.c (original)
+++ branches/1.4/pbx/pbx_config.c Thu Jul 3 22:30:30 2008
@@ -69,7 +69,7 @@
" Now, you can dial 6123 and talk to Markster :)\n";

static char context_remove_extension_help[] =
-"Usage: dialplan remove extension exten@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";
@@ -207,9 +207,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 */
@@ -225,7 +225,14 @@
            free(e);
            return -1;
        }
-    }
+    }
+    if (cid && (i = strchr(e, '/'))) {
+        *i++ = '\0';
+        *cid = i;
+    } else if (cid) {
+        /* Signal none detected */
+        *cid = NULL;
+    }
    return 0;
}

@@ -478,7 +485,7 @@
static int handle_context_remove_extension_deprecated(int fd, int argc, char *argv[])
{
    int removing_priority = 0;
-    char *exten, *context;
+    char *exten, *context, *cid;
    int ret = RESULT_FAILURE;

    if (argc != 4 && argc != 3) return RESULT_SHOWUSAGE;
@@ -516,7 +523,7 @@
    /*
     * Format exten@context checking ...
     */
-    if (split_ec(argv[2], &exten, &context))
+    if (split_ec(argv[2], &exten, &context, &cid))
        return RESULT_FAILURE; /* XXX malloc failure */
    if ((!strlen(exten)) || (!(strlen(context)))) {
        ast_cli(fd, "Missing extension or context name in second argument '%s'\n",
@@ -525,7 +532,9 @@
        return RESULT_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(fd, "Whole extension %s@%s removed\n",
                exten, context);
@@ -545,7 +554,7 @@
static int handle_context_remove_extension(int fd, int argc, char *argv[])
{
    int removing_priority = 0;
-    char *exten, *context;
+    char *exten, *context, *cid;
    int ret = RESULT_FAILURE;

    if (argc != 5 && argc != 4) return RESULT_SHOWUSAGE;
@@ -583,7 +592,7 @@
    /*
     * Format exten@context checking ...
     */
-    if (split_ec(argv[3], &exten, &context))
+    if (split_ec(argv[3], &exten, &context, &cid))
        return RESULT_FAILURE; /* XXX malloc failure */
    if ((!strlen(exten)) || (!(strlen(context)))) {
        ast_cli(fd, "Missing extension or context name in third argument '%s'\n",
@@ -592,7 +601,9 @@
        return RESULT_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(fd, "Whole extension %s@%s removed\n",
                exten, context);
@@ -675,13 +686,14 @@
    word = word2;
#endif

-    if (pos == 2) { /* 'remove extension _X_' (exten@context ... */
+    if (pos == 2) { /* 'remove extension _X_' (exten/cid@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(word, &exten, &context);
+        int lcid = 0; /* length of cid */
+
+        lc = split_ec(word, &exten, &context, &cid);
#ifdef BROKEN_READLINE
        free(word2);
#endif
@@ -689,6 +701,7 @@
            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");
@@ -702,11 +715,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 > state) { /* n-th match */
-                    /* If there is an extension then return exten@context. XXX otherwise ? */
-                    if (exten)
-                        asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c));
-                    break;
+                if ( !strchr(word, '/') ||
+                        (!strchr(word, '@') && partial_match(ast_get_extension_cidmatch(e), cid, lcid)) ||
+                        (strchr(word, '@') && !strcmp(ast_get_extension_cidmatch(e), cid))) {
+                    if ( ((strchr(word, '/') || strchr(word, '@')) && !strcmp(ast_get_extension_name(e), exten)) ||
+                         (!strchr(word, '/') && !strchr(word, '@') && partial_match(ast_get_extension_name(e), exten, le))) { /* n-th match */
+                        if (++which > state) {
+                            /* If there is an extension then return exten@context. */
+                            if (ast_get_extension_matchcid(e) && (!strchr(word, '@') || strchr(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(word, '/')) {
+                                asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c));
+                                break;
+                            }
+                        }
+                    }
                }
            }
            if (e)    /* got a match */
@@ -718,11 +742,11 @@
        if (exten)
            free(exten);
    } else if (pos == 3) { /* '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(line, 2); /* skip 'remove' 'extension' */
-        int i = split_ec(s, &exten, &context);    /* parse ext@context */
+        int i = split_ec(s, &exten, &context, &cid);    /* parse ext@context */

        if (i)    /* error */
            goto error3;
@@ -732,6 +756,7 @@
            *p = '\0';
        le = strlen(exten);
        lc = strlen(context);
+        lcid = strlen(cid);
        len = strlen(word);
        if (le == 0 || lc == 0)
            goto error3;
@@ -754,6 +779,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 ? */
@@ -799,18 +827,21 @@

    if (pos == 3) { /* 'dialplan remove extension _X_' (exten@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(word, &exten, &context);
+        int lcid = 0; /* length of cid */
+
+        lc = split_ec(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");
@@ -824,27 +855,41 @@
            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 > state) { /* n-th match */
-                    /* If there is an extension then return exten@context. XXX otherwise ? */
-                    if (exten)
-                        asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c));
-                    break;
+                if ( !strchr(word, '/') ||
+                        (!strchr(word, '@') && partial_match(ast_get_extension_cidmatch(e), cid, lcid)) ||
+                        (strchr(word, '@') && !strcmp(ast_get_extension_cidmatch(e), cid))) {
+                    if ( ((strchr(word, '/') || strchr(word, '@')) && !strcmp(ast_get_extension_name(e), exten)) ||
+                         (!strchr(word, '/') && !strchr(word, '@') && partial_match(ast_get_extension_name(e), exten, le))) { /* n-th match */
+                        if (++which > state) {
+                            /* If there is an extension then return exten@context. */
+                            if (ast_get_extension_matchcid(e) && (!strchr(word, '@') || strchr(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(word, '/')) {
+                                asprintf(&ret, "%s@%s", ast_get_extension_name(e), ast_get_context_name(c));
+                                break;
+                            }
+                        }
+                    }
                }
            }
            if (e)    /* got a match */
                break;
        }
+#ifdef BROKEN_READLINE
+        free(word2);
+#endif

        ast_unlock_contexts();
    error2:
        if (exten)
            free(exten);
    } else if (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(line, 3); /* skip 'dialplan' 'remove' 'extension' */
-        int i = split_ec(s, &exten, &context);    /* parse ext@context */
+        int i = split_ec(s, &exten, &context, &cid);    /* parse ext@context */

        if (i)    /* error */
            goto error3;
@@ -854,6 +899,7 @@
            *p = '\0';
        le = strlen(exten);
        lc = strlen(context);
+        lcid = cid ? strlen(cid) : -1;
        len = strlen(word);
        if (le == 0 || lc == 0)
            goto error3;
@@ -876,6 +922,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 ? */


_______________________________________________
--Bandwidth and Colocation Provided by http://www.api-digital.com--


svn-commits mailing list
To UNSUBSCRIBE or update options visit:
http://lists.digium.com/mailman/listinfo/svn-commits