]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
pbx: Add variable substitution API for extensions
authorNaveen Albert <asterisk@phreaknet.org>
Mon, 15 Nov 2021 21:08:11 +0000 (21:08 +0000)
committerFriendly Automation <jenkins2@gerrit.asterisk.org>
Mon, 13 Dec 2021 17:18:04 +0000 (11:18 -0600)
Currently, variable substitution involving dialplan
extensions is quite clunky since it entails obtaining
the current dialplan location, backing it up, storing
the desired variables for substitution on the channel,
performing substitution, then restoring the original
location.

In addition to being clunky, things could also go wrong
if an async goto were to occur and change the dialplan
location during a substitution.

Fundamentally, there's no reason it needs to be done this
way, so new API is added to allow for directly passing in
the dialplan location for the purposes of variable
substitution so we don't need to mess with the channel
information anymore. Existing API is not changed.

ASTERISK-29745 #close

Change-Id: I23273bf27fa0efb64a606eebf9aa8e2f41a065e4

include/asterisk/pbx.h
main/pbx.c
main/pbx_variables.c

index 55a5b9f4c8ba0f3407d0d68bb4f71d4e4aa27c13..f5f0691869ad7a39dbb2940bdd8b5446d38f9b66 100644 (file)
@@ -1272,6 +1272,22 @@ const char *ast_get_extension_cidmatch(struct ast_exten *e);
 const char *ast_get_extension_app(struct ast_exten *e);
 const char *ast_get_extension_label(struct ast_exten *e);
 void *ast_get_extension_app_data(struct ast_exten *e);
+
+/*!
+ * \brief Fill a string buffer with the data at a dialplan extension
+ *
+ * \param buf String buffer
+ * \param bufsize Size of buf
+ * \param c Channel
+ * \param context Dialplan context
+ * \param exten Dialplan extension
+ * \param priority Dialplan priority
+ *
+ * \retval -1 Failed to obtain extension data
+ * \retval 0 Successfully obtained extension data
+ */
+int ast_get_extension_data(char *buf, int bufsize, struct ast_channel *c,
+       const char *context, const char *exten, int priority);
 /*! @} */
 
 /*! @name Registrar info functions ... */
@@ -1395,6 +1411,11 @@ int pbx_builtin_raise_exception(struct ast_channel *chan, const char *data);
 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count);
 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count);
 void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used);
+
+/*!
+ * \brief Substitutes variables, similar to pbx_substitute_variables_helper_full, but allows passing the context, extension, and priority in.
+ */
+void pbx_substitute_variables_helper_full_location(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used, char *context, char *exten, int pri);
 /*! @} */
 
 /*! @name Substitution routines, using dynamic string buffers
index 2ed1dd15cae7d1ed4377e463b3147d2b0cf2618b..07cf8e7567d914f70550810898faeb09f91b6220 100644 (file)
@@ -8602,6 +8602,27 @@ void *ast_get_extension_app_data(struct ast_exten *e)
        return e ? e->data : NULL;
 }
 
+int ast_get_extension_data(char *buf, int bufsize, struct ast_channel *c,
+       const char *context, const char *exten, int priority)
+{
+       struct ast_exten *e;
+       struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
+       ast_rdlock_contexts();
+       e = pbx_find_extension(c, NULL, &q, context, exten, priority, NULL, "", E_MATCH);
+       if (e) {
+               if (buf) {
+                       const char *tmp = ast_get_extension_app_data(e);
+                       if (tmp) {
+                               ast_copy_string(buf, tmp, bufsize);
+                       }
+               }
+               ast_unlock_contexts();
+               return 0;
+       }
+       ast_unlock_contexts();
+       return -1;
+}
+
 /*
  * Walking functions ...
  */
index 91b5bbb2b451a0cf38cb73e97e01d72f24968b51..b6c0dd8d53b66aaf099785411a7566c71244578d 100644 (file)
@@ -624,6 +624,11 @@ void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen,
 }
 
 void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
+{
+       pbx_substitute_variables_helper_full_location(c, headp, cp1, cp2, count, used, NULL, NULL, 0);
+}
+
+void pbx_substitute_variables_helper_full_location(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used, char *context, char *exten, int pri)
 {
        /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
        const char *whereweare;
@@ -759,7 +764,16 @@ void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead
                                ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
                        } else {
                                /* Retrieve variable value */
-                               pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
+                               /* For dialplan location, if we were told what to substitute explicitly, use that instead */
+                               if (exten && !strcmp(vars, "EXTEN")) {
+                                       ast_copy_string(workspace, exten, VAR_BUF_SIZE);
+                               } else if (context && !strcmp(vars, "CONTEXT")) {
+                                       ast_copy_string(workspace, context, VAR_BUF_SIZE);
+                               } else if (pri && !strcmp(vars, "PRIORITY")) {
+                                       snprintf(workspace, VAR_BUF_SIZE, "%d", pri);
+                               } else {
+                                       pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
+                               }
                        }
                        if (cp4) {
                                cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);