]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 372518,372522 via svnmerge from
authorAutomerge script <automerge@asterisk.org>
Thu, 6 Sep 2012 22:24:38 +0000 (22:24 +0000)
committerAutomerge script <automerge@asterisk.org>
Thu, 6 Sep 2012 22:24:38 +0000 (22:24 +0000)
file:///srv/subversion/repos/asterisk/branches/10

................
  r372518 | kmoore | 2012-09-06 16:40:50 -0500 (Thu, 06 Sep 2012) | 14 lines

  Ensure listed queues are not offered for completion

  When using tab-completion for the list of queues on "queue reset stats"
  or "queue reload {all|members|parameters|rules}", the tab-completion
  listing for further queues erroneously listed queues that had already
  been added to the list. The tab-completion listing now only displays
  queues that are not already in the list.

  (closes issue AST-963)
Reported-by: John Bigelow
  ........

  Merged revisions 372517 from http://svn.asterisk.org/svn/asterisk/branches/1.8
................
  r372522 | rmudgett | 2012-09-06 17:10:04 -0500 (Thu, 06 Sep 2012) | 22 lines

  Fix loss of MOH on an ISDN channel when parking a call for the second time.

  Using the AMI redirect action to take an ISDN call out of a parking lot
  causes the MOH state to get confused.  The redirect action does not take
  the call off of hold.  When the call is subsequently parked again, the
  call no longer hears MOH.

  * Make chan_dahdi/sig_pri restart MOH on repeated AST_CONTROL_HOLD frames
  if it is already in a state where it is supposed to be sending MOH.  The
  MOH may have been stopped by other means.  (Such as killing the generator.)

  This simple fix is done rather than making the AMI redirect action post an
  AST_CONTROL_UNHOLD unconditionally when it redirects a channel and thus
  potentially breaking something with an unexpected AST_CONTROL_UNHOLD.

  (closes issue ABE-2873)
  Patches:
        jira_abe_2873_c.3_bier.patch (license #5621) patch uploaded by rmudgett
  ........

  Merged revisions 372521 from https://origsvn.digium.com/svn/asterisk/be/branches/C.3-bier
................

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/10-digiumphones@372549 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_queue.c
channels/sig_pri.c

index 0f7c8c789305c964715513dcca980fe03bd1dc52..e4849ddf8c7ff1b4958dc2c893dea6018aa5fc78 100644 (file)
@@ -7377,17 +7377,97 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
        return CLI_SUCCESS;
 }
 
-static char *complete_queue(const char *line, const char *word, int pos, int state)
+/*! 
+ * \brief Check if a given word is in a space-delimited list
+ *
+ * \param list Space delimited list of words
+ * \param word The word used to search the list
+ *
+ * \note This function will not return 1 if the word is at the very end of the
+ * list (followed immediately by a \0, not a space) since it is used for
+ * checking tab-completion and a word at the end is still being tab-completed.
+ *
+ * \return Returns 1 if the word is found
+ * \return Returns 0 if the word is not found
+*/
+static int word_in_list(const char *list, const char *word) {
+       int list_len, word_len = strlen(word);
+       const char *find, *end_find, *end_list;
+
+       /* strip whitespace from front */
+       while (isspace(*list)) {
+               list++;
+       }
+
+       while ((find = strstr(list, word))) {
+               /* beginning of find starts inside another word? */
+               if (find != list && *(find - 1) != ' ') {
+                       list = find;
+                       /* strip word from front */
+                       while (!isspace(*list) && *list != '\0') {
+                               list++;
+                       }
+                       /* strip whitespace from front */
+                       while (isspace(*list)) {
+                               list++;
+                       }
+                       continue;
+               }
+
+               /* end of find ends inside another word or at very end of list? */
+               list_len = strlen(list);
+               end_find = find + word_len;
+               end_list = list + list_len;
+               if (end_find == end_list || *end_find != ' ') {
+                       list = find;
+                       /* strip word from front */
+                       while (!isspace(*list) && *list != '\0') {
+                               list++;
+                       }
+                       /* strip whitespace from front */
+                       while (isspace(*list)) {
+                               list++;
+                       }
+                       continue;
+               }
+
+               /* terminating conditions satisfied, word at beginning or separated by ' ' */
+               return 1;
+       }
+       
+       return 0;
+}
+
+/*! 
+ * \brief Check if a given word is in a space-delimited list
+ *
+ * \param line The line as typed not including the current word being completed
+ * \param word The word currently being completed
+ * \param pos The number of completed words in line
+ * \param state The nth desired completion option
+ * \param word_list_offset Offset into the line where the list of queues begins.  If non-zero, queues in the list will not be offered for further completion.
+ *
+ * \return Returns the queue tab-completion for the given word and state
+*/
+static char *complete_queue(const char *line, const char *word, int pos, int state, ptrdiff_t word_list_offset)
 {
        struct call_queue *q;
        char *ret = NULL;
        int which = 0;
        int wordlen = strlen(word);
        struct ao2_iterator queue_iter;
+       const char *word_list = NULL;
+
+       /* for certain commands, already completed items should be left out of
+        * the list */
+       if (word_list_offset && strlen(line) >= word_list_offset) {
+               word_list = line + word_list_offset;
+       }
 
        queue_iter = ao2_iterator_init(queues, 0);
        while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
-               if (!strncasecmp(word, q->name, wordlen) && ++which > state) {
+               if (!strncasecmp(word, q->name, wordlen) && ++which > state
+                       && (!word_list_offset || !word_in_list(word_list, q->name))) {
                        ret = ast_strdup(q->name);
                        queue_t_unref(q, "Done with iterator");
                        break;
@@ -7396,9 +7476,10 @@ static char *complete_queue(const char *line, const char *word, int pos, int sta
        }
        ao2_iterator_destroy(&queue_iter);
 
-       /* Pretend "rules" is always at the end of the queues list since it is
-        * an alternate command that should be tab-completable */
-       if (!ret && which == state && !wordlen) {
+       /* Pretend "rules" is at the end of the queues list in certain
+        * circumstances since it is an alternate command that should be
+        * tab-completable for "queue show" */
+       if (!ret && which == state && !wordlen && !strncmp("queue show", line, 10)) {
                ret = ast_strdup("rules");
        }
 
@@ -7407,8 +7488,9 @@ static char *complete_queue(const char *line, const char *word, int pos, int sta
 
 static char *complete_queue_show(const char *line, const char *word, int pos, int state)
 {
-       if (pos == 2)
-               return complete_queue(line, word, pos, state);
+       if (pos == 2) {
+               return complete_queue(line, word, pos, state, 0);
+       }
        return NULL;
 }
 
@@ -7838,7 +7920,7 @@ static char *complete_queue_add_member(const char *line, const char *word, int p
        case 4: /* only one possible match, "to" */
                return state == 0 ? ast_strdup("to") : NULL;
        case 5: /* <queue> */
-               return complete_queue(line, word, pos, state);
+               return complete_queue(line, word, pos, state, 0);
        case 6: /* only one possible match, "penalty" */
                return state == 0 ? ast_strdup("penalty") : NULL;
        case 7:
@@ -7974,8 +8056,9 @@ static char *complete_queue_remove_member(const char *line, const char *word, in
        if (pos == 4)   /* only one possible match, 'from' */
                return (state == 0 ? ast_strdup("from") : NULL);
 
-       if (pos == 5)   /* No need to duplicate code */
-               return complete_queue(line, word, pos, state);
+       if (pos == 5) {  /* No need to duplicate code */
+               return complete_queue(line, word, pos, state, 0);
+       }
 
        /* here is the case for 3, <member> */
        queue_iter = ao2_iterator_init(queues, 0);
@@ -8059,7 +8142,7 @@ static char *complete_queue_pause_member(const char *line, const char *word, int
        case 4: /* only one possible match, "queue" */
                return state == 0 ? ast_strdup("queue") : NULL;
        case 5: /* <queue> */
-               return complete_queue(line, word, pos, state);
+               return complete_queue(line, word, pos, state, 0);
        case 6: /* "reason" */
                return state == 0 ? ast_strdup("reason") : NULL;
        case 7: /* Can't autocomplete a reason, since it's 100% customizeable */
@@ -8137,7 +8220,7 @@ static char *complete_queue_set_member_penalty(const char *line, const char *wor
                        return NULL;
                }
        case 7:
-               return complete_queue(line, word, pos, state);
+               return complete_queue(line, word, pos, state, 0);
        default:
                return NULL;
        }
@@ -8256,7 +8339,7 @@ static char *handle_queue_reset(struct ast_cli_entry *e, int cmd, struct ast_cli
                        return NULL;
                case CLI_GENERATE:
                        if (a->pos >= 3) {
-                               return complete_queue(a->line, a->word, a->pos, a->n);
+                               return complete_queue(a->line, a->word, a->pos, a->n, 17);
                        } else {
                                return NULL;
                        }
@@ -8305,7 +8388,13 @@ static char *handle_queue_reload(struct ast_cli_entry *e, int cmd, struct ast_cl
                        return NULL;
                case CLI_GENERATE:
                        if (a->pos >= 3) {
-                               return complete_queue(a->line, a->word, a->pos, a->n);
+                               /* find the point at which the list of queue names starts */
+                               const char *command_end = a->line + strlen("queue reload ");
+                               command_end = strchr(command_end, ' ');
+                               if (!command_end) {
+                                       command_end = a->line + strlen(a->line);
+                               }
+                               return complete_queue(a->line, a->word, a->pos, a->n, command_end - a->line);
                        } else {
                                return NULL;
                        }
index 6d95cf8453ebb654ab75a7e8a956c4b1869e8be0..ad8c31452075b6ddd09a744e3ed6880d1224756e 100644 (file)
@@ -4686,6 +4686,12 @@ static enum sig_pri_moh_state sig_pri_moh_fsm_notify(struct ast_channel *chan, s
 
        next_state = pvt->moh_state;
        switch (event) {
+       case SIG_PRI_MOH_EVENT_HOLD:
+               if (strcasecmp(pvt->mohinterpret, "passthrough")) {
+                       /* Restart MOH in case it was stopped by other means. */
+                       ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
+               }
+               break;
        case SIG_PRI_MOH_EVENT_UNHOLD:
                pri_notify(pvt->pri->pri, pvt->call, pvt->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
                /* Fall through */
@@ -4720,6 +4726,10 @@ static enum sig_pri_moh_state sig_pri_moh_fsm_moh(struct ast_channel *chan, stru
 
        next_state = pvt->moh_state;
        switch (event) {
+       case SIG_PRI_MOH_EVENT_HOLD:
+               /* Restart MOH in case it was stopped by other means. */
+               ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
+               break;
        case SIG_PRI_MOH_EVENT_RESET:
        case SIG_PRI_MOH_EVENT_UNHOLD:
                ast_moh_stop(chan);