SIP channel name uniqueness
[asterisk/asterisk.git] / funcs / func_callerid.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999-2006, 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 Caller ID related dialplan functions
20  *
21  * \ingroup functions
22  */
23
24 #include "asterisk.h"
25
26 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
27
28 #include "asterisk/module.h"
29 #include "asterisk/channel.h"
30 #include "asterisk/pbx.h"
31 #include "asterisk/utils.h"
32 #include "asterisk/app.h"
33 #include "asterisk/callerid.h"
34
35 /*** DOCUMENTATION
36         <function name="CALLERID" language="en_US">
37                 <synopsis>
38                         Gets or sets Caller*ID data on the channel.
39                 </synopsis>
40                 <syntax>
41                         <parameter name="datatype" required="true">
42                                 <para>The allowable datatypes are:</para>
43                                 <enumlist>
44                                         <enum name="all" />
45                                         <enum name="num" />
46                                         <enum name="name" />
47                                         <enum name="ANI" />
48                                         <enum name="DNID" />
49                                         <enum name="RDNIS" />
50                                         <enum name="pres" />
51                                         <enum name="ton" />
52                                         <enum name="subaddr[-valid]|[-type]|[-odd]">
53                                                 <para>ISDN Calling Subaddress</para>
54                                         </enum>
55                                         <enum name="dnid-subaddr[-valid]|[-type]|[-odd]">
56                                                 <para>ISDN Called Subaddress</para>
57                                         </enum>
58                                 </enumlist>
59                         </parameter>
60                         <parameter name="CID">
61                                 <para>Optional Caller*ID</para>
62                         </parameter>
63                 </syntax>
64                 <description>
65                         <para>Gets or sets Caller*ID data on the channel. Uses channel callerid by default or optional
66                         callerid, if specified.</para>
67                 </description>
68         </function>
69         <function name="CALLERPRES" language="en_US">
70                 <synopsis>
71                         Gets or sets Caller*ID presentation on the channel.
72                 </synopsis>
73                 <syntax />
74                 <description>
75                         <para>Gets or sets Caller*ID presentation on the channel. The following values
76                         are valid:</para>
77                         <enumlist>
78                                 <enum name="allowed_not_screened">
79                                         <para>Presentation Allowed, Not Screened.</para>
80                                 </enum>
81                                 <enum name="allowed_passed_screen">
82                                         <para>Presentation Allowed, Passed Screen.</para>
83                                 </enum>
84                                 <enum name="allowed_failed_screen">
85                                         <para>Presentation Allowed, Failed Screen.</para>
86                                 </enum>
87                                 <enum name="allowed">
88                                         <para>Presentation Allowed, Network Number.</para>
89                                 </enum>
90                                 <enum name="prohib_not_screened">
91                                         <para>Presentation Prohibited, Not Screened.</para>
92                                 </enum>
93                                 <enum name="prohib_passed_screen">
94                                         <para>Presentation Prohibited, Passed Screen.</para>
95                                 </enum>
96                                 <enum name="prohib_failed_screen">
97                                         <para>Presentation Prohibited, Failed Screen.</para>
98                                 </enum>
99                                 <enum name="prohib">
100                                         <para>Presentation Prohibited, Network Number.</para>
101                                 </enum>
102                                 <enum name="unavailable">
103                                         <para>Number Unavailable.</para>
104                                 </enum>
105                         </enumlist>
106                 </description>
107         </function>
108  ***/
109
110 static int callerpres_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
111 {
112         ast_copy_string(buf, ast_named_caller_presentation(chan->cid.cid_pres), len);
113         return 0;
114 }
115
116 static int callerpres_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
117 {
118         int pres = ast_parse_caller_presentation(value);
119         if (pres < 0)
120                 ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show function CALLERPRES')\n", value);
121         else
122                 chan->cid.cid_pres = pres;
123         return 0;
124 }
125
126 static int callerid_read(struct ast_channel *chan, const char *cmd, char *data,
127                          char *buf, size_t len)
128 {
129         char *opt = data;
130
131         /* Ensure that the buffer is empty */
132         *buf = 0;
133
134         if (!chan)
135                 return -1;
136
137         if (strchr(opt, ',')) {
138                 char name[80], num[80];
139
140                 data = strsep(&opt, ",");
141                 ast_callerid_split(opt, name, sizeof(name), num, sizeof(num));
142
143                 if (!strncasecmp("all", data, 3)) {
144                         snprintf(buf, len, "\"%s\" <%s>", name, num);
145                 } else if (!strncasecmp("name", data, 4)) {
146                         ast_copy_string(buf, name, len);
147                 } else if (!strncasecmp("num", data, 3)) {
148                         /* also matches "number" */
149                         ast_copy_string(buf, num, len);
150                 } else {
151                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
152                 }
153         } else {
154                 ast_channel_lock(chan);
155
156                 if (!strncasecmp("all", data, 3)) {
157                         snprintf(buf, len, "\"%s\" <%s>",
158                                 S_OR(chan->cid.cid_name, ""),
159                                 S_OR(chan->cid.cid_num, ""));
160                 } else if (!strncasecmp("name", data, 4)) {
161                         if (chan->cid.cid_name) {
162                                 ast_copy_string(buf, chan->cid.cid_name, len);
163                         }
164                 } else if (!strncasecmp("num", data, 3)) {
165                         /* also matches "number" */
166                         if (chan->cid.cid_num) {
167                                 ast_copy_string(buf, chan->cid.cid_num, len);
168                         }
169                 } else if (!strncasecmp("ani", data, 3)) {
170                         if (!strncasecmp(data + 3, "2", 1)) {
171                                 snprintf(buf, len, "%d", chan->cid.cid_ani2);
172                         } else if (chan->cid.cid_ani) {
173                                 ast_copy_string(buf, chan->cid.cid_ani, len);
174                         }
175                 } else if (!strncasecmp("dnid", data, 4)) {
176                         /* Called parties info */
177
178                         /* also matches dnid-subaddr-valid, dnid-subaddr-type, dnid-subaddr-odd, dnid-subaddr */
179                         if (!strncasecmp(data + 4 ,"-subaddr", 8)) {
180                                 if (!strncasecmp(data + 12 ,"-valid", 6)) {             /* dnid-subaddr-valid */
181                                         snprintf(buf, len, "%d", chan->cid.dialed_subaddress.valid);
182                                 } else if (!strncasecmp(data + 12 ,"-type", 5)) {       /* dnid-subaddr-type */
183                                         snprintf(buf, len, "%d", chan->cid.dialed_subaddress.type);
184                                 } else if (!strncasecmp(data + 12 ,"-odd", 4)) {        /* dnid-subaddr-odd */
185                                         snprintf(buf, len, "%d", chan->cid.dialed_subaddress.odd_even_indicator);
186                                 } else {                                                /* dnid-subaddr */
187                                         if (chan->cid.dialed_subaddress.str) {
188                                                 ast_copy_string(buf, chan->cid.dialed_subaddress.str, len);
189                                         }
190                                 }
191                         } else {                                                        /* dnid */
192                                 if (chan->cid.cid_dnid) {
193                                         ast_copy_string(buf, chan->cid.cid_dnid, len);
194                                 }
195                         }
196                 } else if (!strncasecmp("subaddr", data, 7)) {
197                         /* Calling parties info */
198
199                         /* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
200                         if (!strncasecmp(data + 7 ,"-valid", 6)) {              /* subaddr-valid */
201                                 snprintf(buf, len, "%d", chan->cid.subaddress.valid);
202                         } else if (!strncasecmp(data + 7 ,"-type", 5)) {        /* subaddr-type */
203                                 snprintf(buf, len, "%d", chan->cid.subaddress.type);
204                         } else if (!strncasecmp(data + 7 ,"-odd", 4)) {         /* subaddr-odd */
205                                 snprintf(buf, len, "%d", chan->cid.subaddress.odd_even_indicator);
206                         } else {                                                /* subaddr */
207                                 if (chan->cid.subaddress.str) {
208                                         ast_copy_string(buf, chan->cid.subaddress.str, len);
209                                 }
210                         }
211                 } else if (!strncasecmp("rdnis", data, 5)) {
212                         if (chan->cid.cid_rdnis) {
213                                 ast_copy_string(buf, chan->cid.cid_rdnis, len);
214                         }
215                 } else if (!strncasecmp("pres", data, 4)) {
216                         ast_copy_string(buf, ast_named_caller_presentation(chan->cid.cid_pres), len);
217                 } else if (!strncasecmp("ton", data, 3)) {
218                         snprintf(buf, len, "%d", chan->cid.cid_ton);
219                 } else {
220                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
221                 }
222
223                 ast_channel_unlock(chan);
224         }
225
226         return 0;
227 }
228
229 static int callerid_write(struct ast_channel *chan, const char *cmd, char *data,
230                           const char *value)
231 {
232         if (!value || !chan)
233                 return -1;
234
235         value = ast_skip_blanks(value);
236
237         if (!strncasecmp("all", data, 3)) {
238                 char name[256];
239                 char num[256];
240
241                 ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
242                 ast_set_callerid(chan, num, name, num);
243                 if (chan->cdr) {
244                         ast_cdr_setcid(chan->cdr, chan);
245                 }
246         } else if (!strncasecmp("name", data, 4)) {
247                 ast_set_callerid(chan, NULL, value, NULL);
248                 if (chan->cdr) {
249                         ast_cdr_setcid(chan->cdr, chan);
250                 }
251         } else if (!strncasecmp("num", data, 3)) {
252                 /* also matches "number" */
253                 ast_set_callerid(chan, value, NULL, NULL);
254                 if (chan->cdr) {
255                         ast_cdr_setcid(chan->cdr, chan);
256                 }
257         } else if (!strncasecmp("ani", data, 3)) {
258                 if (!strncasecmp(data + 3, "2", 1)) {
259                         chan->cid.cid_ani2 = atoi(value);
260                 } else {
261                         ast_set_callerid(chan, NULL, NULL, value);
262                 }
263                 if (chan->cdr) {
264                         ast_cdr_setcid(chan->cdr, chan);
265                 }
266         } else if (!strncasecmp("dnid", data, 4)) {
267                 ast_channel_lock(chan);
268                 /* also matches dnid-subaddr-valid, dnid-subaddr-type, dnid-subaddr-odd, dnid-subaddr */
269                 if (!strncasecmp(data + 4 ,"-subaddr", 8)) {
270                         if (!strncasecmp(data + 12 ,"-valid", 6)) {             /* dnid-subaddr-valid */
271                                 chan->cid.dialed_subaddress.valid = atoi(value) ? 1 : 0;
272                         } else if (!strncasecmp(data + 12 ,"-type", 5)) {       /* dnid-subaddr-type */
273                                 chan->cid.dialed_subaddress.type = atoi(value) ? 2 : 0;
274                         } else if (!strncasecmp(data + 12 ,"-odd", 4)) {        /* dnid-subaddr-odd */
275                                 chan->cid.dialed_subaddress.odd_even_indicator = atoi(value) ? 1 : 0;
276                         } else {                                                /* dnid-subaddr */
277                                 if (chan->cid.dialed_subaddress.str) {
278                                         ast_free(chan->cid.dialed_subaddress.str);
279                                 }
280                                 chan->cid.dialed_subaddress.str = ast_strdup(value);
281                         }
282                 } else {                                                        /* dnid */
283                         if (chan->cid.cid_dnid) {
284                                 ast_free(chan->cid.cid_dnid);
285                         }
286                         chan->cid.cid_dnid = ast_strdup(value);
287                 }
288
289                 if (chan->cdr) {
290                         ast_cdr_setcid(chan->cdr, chan);
291                 }
292                 ast_channel_unlock(chan);
293         } else if (!strncasecmp("subaddr", data, 7)) {
294                 ast_channel_lock(chan);
295                 /* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
296                 if (!strncasecmp(data + 7 ,"-valid", 6)) {              /* subaddr-valid */
297                         chan->cid.subaddress.valid = atoi(value) ? 1 : 0;
298                 } else if (!strncasecmp(data + 7 ,"-type", 5)) {        /* subaddr-type */
299                         chan->cid.subaddress.type = atoi(value) ? 2 : 0;
300                 } else if (!strncasecmp(data + 7 ,"-odd", 4)) {         /* subaddr-odd */
301                         chan->cid.subaddress.odd_even_indicator = atoi(value) ? 1 : 0;
302                 } else {                                                /* subaddr */
303                         if (chan->cid.subaddress.str) {
304                                 ast_free(chan->cid.subaddress.str);
305                         }
306                         chan->cid.subaddress.str = ast_strdup(value);
307                 }
308                 if (chan->cdr) {
309                         ast_cdr_setcid(chan->cdr, chan);
310                 }
311                 ast_channel_unlock(chan);
312         } else if (!strncasecmp("rdnis", data, 5)) {
313                 ast_channel_lock(chan);
314                 if (chan->cid.cid_rdnis) {
315                         ast_free(chan->cid.cid_rdnis);
316                 }
317                 chan->cid.cid_rdnis = ast_strdup(value);
318                 if (chan->cdr) {
319                         ast_cdr_setcid(chan->cdr, chan);
320                 }
321                 ast_channel_unlock(chan);
322         } else if (!strncasecmp("pres", data, 4)) {
323                 int i;
324                 char *val;
325
326                 val = ast_strdupa(value);
327                 ast_trim_blanks(val);
328
329                 if ((val[0] >= '0') && (val[0] <= '9')) {
330                         i = atoi(val);
331                 } else {
332                         i = ast_parse_caller_presentation(val);
333                 }
334
335                 if (i < 0) {
336                         ast_log(LOG_ERROR, "Unknown calling number presentation '%s', value unchanged\n", val);
337                 } else {
338                         chan->cid.cid_pres = i;
339                 }
340         } else if (!strncasecmp("ton", data, 3)) {
341                 chan->cid.cid_ton = atoi(value);
342         } else {
343                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
344         }
345
346         return 0;
347 }
348
349 static struct ast_custom_function callerid_function = {
350         .name = "CALLERID",
351         .read = callerid_read,
352         .read_max = 256,
353         .write = callerid_write,
354 };
355
356 static struct ast_custom_function callerpres_function = {
357         .name = "CALLERPRES",
358         .read = callerpres_read,
359         .read_max = 50,
360         .write = callerpres_write,
361 };
362
363 static int unload_module(void)
364 {
365         int res = ast_custom_function_unregister(&callerpres_function);
366         res |= ast_custom_function_unregister(&callerid_function);
367         return res;
368 }
369
370 static int load_module(void)
371 {
372         int res = ast_custom_function_register(&callerpres_function);
373         res |= ast_custom_function_register(&callerid_function);
374         return res;
375 }
376
377 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Caller ID related dialplan functions");