The changes for trunk are less extensive, but include
[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 <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/types.h>
32
33 #include "asterisk/module.h"
34 #include "asterisk/channel.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/logger.h"
37 #include "asterisk/utils.h"
38 #include "asterisk/app.h"
39 #include "asterisk/options.h"
40 #include "asterisk/callerid.h"
41
42 static int callerid_read(struct ast_channel *chan, const char *cmd, char *data,
43                          char *buf, size_t len)
44 {
45         char *opt = data;
46
47         /* XXX we are not always clearing the buffer. Is this correct ? */
48         if (strchr(opt, '|')) {
49                 char name[80], num[80];
50
51                 data = strsep(&opt, "|");
52                 ast_callerid_split(opt, name, sizeof(name), num, sizeof(num));
53
54                 if (!strncasecmp("all", data, 3)) {
55                         snprintf(buf, len, "\"%s\" <%s>", name, num);
56                 } else if (!strncasecmp("name", data, 4)) {
57                         ast_copy_string(buf, name, len);
58                 } else if (!strncasecmp("num", data, 3)) {
59                         ast_copy_string(buf, num, len);
60                 } else {
61                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
62                 }
63         } else {
64                 if (!strncasecmp("all", data, 3)) {
65                         snprintf(buf, len, "\"%s\" <%s>",
66                                  S_OR(chan->cid.cid_name, ""),
67                                  S_OR(chan->cid.cid_num, ""));
68                 } else if (!strncasecmp("name", data, 4)) {
69                         if (chan->cid.cid_name) {
70                                 ast_copy_string(buf, chan->cid.cid_name, len);
71                         }
72                 } else if (!strncasecmp("num", data, 3)) {
73                         if (chan->cid.cid_num) {
74                                 ast_copy_string(buf, chan->cid.cid_num, len);
75                         }
76                 } else if (!strncasecmp("ani", data, 3)) {
77                         if (chan->cid.cid_ani) {
78                                 ast_copy_string(buf, chan->cid.cid_ani, len);
79                         }
80                 } else if (!strncasecmp("dnid", data, 4)) {
81                         if (chan->cid.cid_dnid) {
82                                 ast_copy_string(buf, chan->cid.cid_dnid, len);
83                         }
84                 } else if (!strncasecmp("rdnis", data, 5)) {
85                         if (chan->cid.cid_rdnis) {
86                                 ast_copy_string(buf, chan->cid.cid_rdnis, len);
87                         }
88                 } else if (!strncasecmp("pres", data, 4)) {
89                         ast_copy_string(buf, ast_named_caller_presentation(chan->cid.cid_pres), len);
90                 } else if (!strncasecmp("ton", data, 3)) {
91                         snprintf(buf, len, "%d", chan->cid.cid_ton);
92                 } else {
93                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
94                 }
95         }
96
97         return 0;
98 }
99
100 static int callerid_write(struct ast_channel *chan, const char *cmd, char *data,
101                           const char *value)
102 {
103         if (!value)
104                 return -1;
105
106         if (!strncasecmp("all", data, 3)) {
107                 char name[256];
108                 char num[256];
109
110                 if (!ast_callerid_split(value, name, sizeof(name), num, sizeof(num)))
111                         ast_set_callerid(chan, num, name, num);
112         } else if (!strncasecmp("name", data, 4)) {
113                 ast_set_callerid(chan, NULL, value, NULL);
114         } else if (!strncasecmp("num", data, 3)) { 
115                 ast_set_callerid(chan, value, NULL, NULL);
116         } else if (!strncasecmp("ani", data, 3)) {
117                 ast_set_callerid(chan, NULL, NULL, value);
118         } else if (!strncasecmp("dnid", data, 4)) {
119                 /* do we need to lock chan here? */
120                 if (chan->cid.cid_dnid)
121                         free(chan->cid.cid_dnid);
122                 chan->cid.cid_dnid = ast_strdup(value);
123         } else if (!strncasecmp("rdnis", data, 5)) {
124                 /* do we need to lock chan here? */
125                 if (chan->cid.cid_rdnis)
126                         free(chan->cid.cid_rdnis);
127                 chan->cid.cid_rdnis = ast_strdup(value);
128         } else if (!strncasecmp("pres", data, 4)) {
129                 int i;
130                 char *s, *val;
131
132                 /* Strip leading spaces */
133                 while ((value[0] == '\t') || (value[0] == ' '))
134                         ++value;
135
136                 val = ast_strdupa(value);
137
138                 /* Strip trailing spaces */
139                 s = val + strlen(val);
140                 while ((s != val) && ((s[-1] == '\t') || (s[-1] == ' ')))
141                         --s;
142                 *s = '\0';
143
144                 if ((val[0] >= '0') && (val[0] <= '9'))
145                         i = atoi(val);
146                 else
147                         i = ast_parse_caller_presentation(val);
148
149                 if (i < 0)
150                         ast_log(LOG_ERROR, "Unknown calling number presentation '%s', value unchanged\n", val);
151                 else
152                         chan->cid.cid_pres = i;
153         } else if (!strncasecmp("ton", data, 3)) {
154                 int i = atoi(value);
155                 chan->cid.cid_ton = i;
156         } else {
157                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
158         }
159
160         return 0;
161 }
162
163 static struct ast_custom_function callerid_function = {
164         .name = "CALLERID",
165         .synopsis = "Gets or sets Caller*ID data on the channel.",
166         .syntax = "CALLERID(datatype[,<optional-CID>])",
167         .desc =
168                 "Gets or sets Caller*ID data on the channel.  The allowable datatypes\n"
169                 "are \"all\", \"name\", \"num\", \"ANI\", \"DNID\", \"RDNIS\", \"pres\",\n"
170                 "and \"ton\".\n"
171                 "Uses channel callerid by default or optional callerid, if specified.\n",
172         .read = callerid_read,
173         .write = callerid_write,
174 };
175
176 static int unload_module(void)
177 {
178         return ast_custom_function_unregister(&callerid_function);
179 }
180
181 static int load_module(void)
182 {
183         return ast_custom_function_register(&callerid_function);
184 }
185
186 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Caller ID related dialplan function");