channel: Clear channel flag in error branch.
[asterisk/asterisk.git] / funcs / func_dialplan.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007, Digium, Inc.
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*! \file
18  *
19  * \brief Dialplan group functions check if a dialplan entry exists
20  *
21  * \author Gregory Nietsky AKA irroot <gregory@networksentry.co.za>
22  * \author Russell Bryant <russell@digium.com>
23  * 
24  * \ingroup functions
25  */
26
27 /*** MODULEINFO
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 #include "asterisk/module.h"
34 #include "asterisk/channel.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/app.h"
37
38 /*** DOCUMENTATION
39         <function name="DIALPLAN_EXISTS" language="en_US">
40                 <synopsis>
41                         Checks the existence of a dialplan target.
42                 </synopsis>
43                 <syntax>
44                         <parameter name="context" required="true" />
45                         <parameter name="extension" />
46                         <parameter name="priority" />
47                 </syntax>
48                 <description>
49                         <para>This function returns <literal>1</literal> if the target exits. Otherwise, it returns <literal>0</literal>.</para>
50                 </description>
51         </function>
52         <function name="VALID_EXTEN" language="en_US">
53                 <synopsis>
54                         Determine whether an extension exists or not.
55                 </synopsis>
56                 <syntax>
57                         <parameter name="context">
58                                 <para>Defaults to the current context</para>
59                         </parameter>
60                         <parameter name="extension" required="true" />
61                         <parameter name="priority">
62                                 <para>Priority defaults to <literal>1</literal>.</para>
63                         </parameter>
64                 </syntax>
65                 <description>
66                         <para>Returns a true value if the indicated <replaceable>context</replaceable>,
67                         <replaceable>extension</replaceable>, and <replaceable>priority</replaceable> exist.</para>
68                         <warning><para>This function has been deprecated in favor of the <literal>DIALPLAN_EXISTS()</literal> function</para></warning>
69                 </description>
70         </function>
71  ***/
72
73 static int isexten_function_read(struct ast_channel *chan, const char *cmd, char *data,
74         char *buf, size_t len)
75 {
76         char *parse;
77         AST_DECLARE_APP_ARGS(args,
78                 AST_APP_ARG(context);
79                 AST_APP_ARG(exten);
80                 AST_APP_ARG(priority);
81         );
82
83         strcpy(buf, "0");
84
85         if (ast_strlen_zero(data)) {
86                 ast_log(LOG_ERROR, "DIALPLAN_EXISTS() requires an argument\n");
87                 return -1;
88         }
89
90         parse = ast_strdupa(data);
91         AST_STANDARD_APP_ARGS(args, parse);
92
93         if (!ast_strlen_zero(args.priority)) {
94                 int priority_num;
95                 if (sscanf(args.priority, "%30d", &priority_num) == 1 && priority_num > 0) {
96                         int res;
97                         res = ast_exists_extension(chan, args.context, args.exten, priority_num,
98                                 !chan ? NULL :
99                                 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
100                         if (res)
101                                 strcpy(buf, "1");
102                 } else {
103                         int res;
104                         res = ast_findlabel_extension(chan, args.context, args.exten, args.priority,
105                                 !chan ? NULL :
106                                 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
107                         if (res > 0)
108                                 strcpy(buf, "1");
109                 }
110         } else if (!ast_strlen_zero(args.exten)) {
111                 int res;
112                 res = ast_exists_extension(chan, args.context, args.exten, 1,
113                         !chan ? NULL :
114                         S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
115                 if (res)
116                         strcpy(buf, "1");
117         } else if (!ast_strlen_zero(args.context)) {
118                 if (ast_context_find(args.context))
119                         strcpy(buf, "1");
120         } else {
121                 ast_log(LOG_ERROR, "Invalid arguments provided to DIALPLAN_EXISTS\n");
122                 return -1;
123         }
124
125         return 0;
126 }
127
128 static int acf_isexten_exec(struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen)
129 {
130         int priority_int;
131         AST_DECLARE_APP_ARGS(args,
132                 AST_APP_ARG(context);
133                 AST_APP_ARG(extension);
134                 AST_APP_ARG(priority);
135         );
136
137         if (!chan) {
138                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
139                 return -1;
140         }
141
142         AST_STANDARD_APP_ARGS(args, parse);
143
144         if (ast_strlen_zero(args.context)) {
145                 args.context = ast_strdupa(ast_channel_context(chan));
146         }
147
148         if (ast_strlen_zero(args.extension)) {
149                 ast_log(LOG_WARNING, "Syntax: VALID_EXTEN([<context>],<extension>[,<priority>]) - missing argument <extension>!\n");
150                 return -1;
151         }
152
153         if (ast_strlen_zero(args.priority)) {
154                 priority_int = 1;
155         } else {
156                 priority_int = atoi(args.priority);
157         }
158
159         if (ast_exists_extension(chan, args.context, args.extension, priority_int,
160                 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
161             ast_copy_string(buffer, "1", buflen);
162         } else {
163             ast_copy_string(buffer, "0", buflen);
164         }
165
166         return 0;
167 }
168
169 static struct ast_custom_function isexten_function = {
170         .name = "DIALPLAN_EXISTS",
171         .read = isexten_function_read,
172         .read_max = 2,
173 };
174
175 static struct ast_custom_function acf_isexten = {
176         .name = "VALID_EXTEN",
177         .read = acf_isexten_exec,
178 };
179
180 static int unload_module(void)
181 {
182         int res = ast_custom_function_unregister(&isexten_function);
183         res |= ast_custom_function_unregister(&acf_isexten);
184         return res;
185 }
186
187 static int load_module(void)
188 {
189         int res = ast_custom_function_register(&isexten_function);
190         res |= ast_custom_function_register(&acf_isexten);
191         return res;
192 }
193
194 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Dialplan Context/Extension/Priority Checking Functions",
195         .support_level = AST_MODULE_SUPPORT_CORE,
196         .load = load_module,
197         .unload = unload_module,
198         .load_pri = AST_MODPRI_APP_DEPEND,
199 );