More ast_strlen_zero changes
[asterisk/asterisk.git] / apps / app_enumlookup.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Time of day - Report the time of day
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <asterisk/lock.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/options.h>
20 #include <asterisk/config.h>
21 #include <asterisk/module.h>
22 #include <asterisk/enum.h>
23 #include <asterisk/utils.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29
30 #include <pthread.h>
31
32
33 static char *tdesc = "ENUM Lookup";
34
35 static char *app = "EnumLookup";
36
37 static char *synopsis = "Lookup number in ENUM";
38
39 static char *descrip = 
40 "  EnumLookup(exten):  Looks up an extension via ENUM and sets\n"
41 "the variable 'ENUM'. For VoIP URIs this variable will \n"
42 "look like 'TECHNOLOGY/URI' with the appropriate technology.\n"
43 "Returns -1 on hangup, or 0 on completion regardless of whether the \n"
44 "lookup was successful. \n"
45 "Currently, the enumservices SIP, H323, IAX, IAX2 and TEL are recognized. \n"
46 "A good SIP, H323, IAX or IAX2 entry will result in normal priority handling, \n"
47 "whereas a good TEL entry will increase the priority by 51 (if existing).\n"
48 "If the lookup was *not* successful and there exists a priority n + 101,\n"
49 "then that priority will be taken next.\n" ;
50
51 #define ENUM_CONFIG "enum.conf"
52
53 static char h323driver[80];
54 #define H323DRIVERDEFAULT "H323"
55
56 STANDARD_LOCAL_USER;
57
58 LOCAL_USER_DECL;
59
60 static int enumlookup_exec(struct ast_channel *chan, void *data)
61 {
62         int res=0;
63         char tech[80];
64         char dest[80];
65         char tmp[256];
66         char *c,*t;
67         struct localuser *u;
68         if (!data || ast_strlen_zero(data)) {
69                 ast_log(LOG_WARNING, "EnumLookup requires an argument (extension)\n");
70                 res = 1;
71         }
72         LOCAL_USER_ADD(u);
73         if (!res) {
74                 res = ast_get_enum(chan, data, dest, sizeof(dest), tech, sizeof(tech));
75                 printf("ENUM got '%d'\n", res);
76         }
77         LOCAL_USER_REMOVE(u);
78         /* Parse it out */
79         if (res > 0) {
80                 if (!strcasecmp(tech, "SIP")) {
81                         c = dest;
82                         if (!strncmp(c, "sip:", 4))
83                                 c += 4;
84                         snprintf(tmp, sizeof(tmp), "SIP/%s", c);
85                         pbx_builtin_setvar_helper(chan, "ENUM", tmp);
86                 } else if (!strcasecmp(tech, "h323")) {
87                         c = dest;
88                         if (!strncmp(c, "h323:", 5))
89                                 c += 5;
90                         snprintf(tmp, sizeof(tmp), "%s/%s", h323driver, c);
91 /* do a s!;.*!! on the H323 URI */
92                         t = strchr(c,';');
93                         if (t) 
94                                 *t = 0;
95                         pbx_builtin_setvar_helper(chan, "ENUM", tmp);
96                 } else if (!strcasecmp(tech, "iax")) {
97                         c = dest;
98                         if (!strncmp(c, "iax:", 4))
99                                 c += 4;
100                         snprintf(tmp, sizeof(tmp), "IAX/%s", c);
101                         pbx_builtin_setvar_helper(chan, "ENUM", tmp);
102                 } else if (!strcasecmp(tech, "iax2")) {
103                         c = dest;
104                         if (!strncmp(c, "iax2:", 5))
105                                 c += 5;
106                         snprintf(tmp, sizeof(tmp), "IAX2/%s", c);
107                         pbx_builtin_setvar_helper(chan, "ENUM", tmp);
108                 } else if (!strcasecmp(tech, "tel")) {
109                         c = dest;
110                         if (!strncmp(c, "tel:", 4))
111                                 c += 4;
112
113                         if (c[0] != '+') {
114                                 ast_log(LOG_NOTICE, "tel: uri must start with a \"+\" (got '%s')\n", c);
115                                 res = 0;
116                         } else {
117 /* now copy over the number, skipping all non-digits and stop at ; or NULL */
118                                 t = tmp;        
119                                 while( *c && (*c != ';') && (t - tmp < (sizeof(tmp) - 1))) {
120                                         if (isdigit(*c))
121                                                 *t++ = *c;
122                                         c++;
123                                 }
124                                 *t = 0;
125                                 pbx_builtin_setvar_helper(chan, "ENUM", tmp);
126                                 ast_log(LOG_NOTICE, "tel: ENUM set to \"%s\"\n", tmp);
127                                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 51, chan->callerid))
128                                         chan->priority += 50;
129                                 else
130                                         res = 0;
131                         }
132                 } else if (!ast_strlen_zero(tech)) {
133                         ast_log(LOG_NOTICE, "Don't know how to handle technology '%s'\n", tech);
134                         res = 0;
135                 }
136         }
137         if (!res) {
138                 /* Look for a "busy" place */
139                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
140                         chan->priority += 100;
141         } else if (res > 0)
142                 res = 0;
143         return res;
144 }
145
146 static int load_config(void)
147 {
148         struct ast_config *cfg;
149         char *s;
150
151         cfg = ast_load(ENUM_CONFIG);
152         if (cfg) {
153                 if (!(s=ast_variable_retrieve(cfg, "general", "h323driver"))) {
154                         strcpy(h323driver, H323DRIVERDEFAULT);
155                 } else {
156                         strcpy(h323driver, s);
157                 }
158                 ast_destroy(cfg);
159                 return 0;
160         }
161         ast_log(LOG_NOTICE, "No ENUM Config file, using defaults\n");
162         return 0;
163 }
164
165
166 int unload_module(void)
167 {
168         STANDARD_HANGUP_LOCALUSERS;
169         return ast_unregister_application(app);
170 }
171
172 int load_module(void)
173 {
174         int res;
175         res = ast_register_application(app, enumlookup_exec, synopsis, descrip);
176         if (res)
177                 return(res);
178         if ((res=load_config())) {
179                 return(res);
180         }
181         return(0);
182 }
183
184 int reload(void)
185 {
186         return(load_config());
187 }
188
189
190 char *description(void)
191 {
192         return tdesc;
193 }
194
195 int usecount(void)
196 {
197         int res;
198         STANDARD_USECOUNT(res);
199         return res;
200 }
201
202 char *key()
203 {
204         return ASTERISK_GPL_KEY;
205 }
206