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