Added 'extern' flag to interface.conf.
[lcr.git] / extension.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** PBX4Linux                                                                 **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** reading and writing files for extensions                                  **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13
14 /* extension */
15
16 const char *ext_rights[] = {
17         "none",
18         "internal",
19         "local",
20         "national",
21         "international",
22         NULL
23 };
24
25 const char *ext_yesno[] = {
26         "no",
27         "yes",
28         NULL
29 };
30
31
32 /* read extension
33  *
34  * reads extension from given extension number and fills structure
35  */
36 int read_extension(struct extension *ext, char *num)
37 {
38         FILE *fp=NULL;
39         char number[32];
40         char filename[256];
41         char *p;
42         char option[32];
43         char param[256],param2[256];
44         unsigned int line,i;
45         char buffer[1024];
46         int last_in_count = 0, last_out_count = 0;
47
48         /* save number, so &ext and ext.number can be given as parameters - without overwriting itself */
49         SCPY(number, num);
50         
51         if (number[0] == '\0')
52                 return(0);
53
54         SPRINT(filename, "%s/%s/settings", EXTENSION_DATA, number);
55
56         if (!(fp = fopen(filename, "r"))) {
57                 printf("the given extension doesn't exist: \"%s\"\n", filename);
58                 PDEBUG(DEBUG_CONFIG, "the given extension doesn't exist: \"%s\"\n", filename);
59                 return(0);
60         }
61
62         /* default values */
63         memset(ext, 0, sizeof(struct extension));
64         SCPY(ext->number, number);
65 //      ********** NOTE: also change value in apppbx constructor
66         ext->rights = 4; /* international */
67         ext->cfnr_delay = 20;
68         ext->vbox_codec = CODEC_MONO;
69
70         line=0;
71         while((fgets(buffer, sizeof(buffer), fp))) {
72                 line++;
73                 buffer[sizeof(buffer)-1] = '\0';
74                 if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
75                 p = buffer;
76
77                 while(*p <= 32) { /* skip spaces */
78                         if (*p == 0)
79                                 break;
80                         p++;
81                 }
82                 if (*p==0 || *p=='#') /* ignore comments and empty line */
83                         continue;
84
85                 option[0]=0;
86                 i=0; /* read option */
87                 while(*p > 32) {
88                         if (i+1 >= sizeof(option)) {
89                                 PERROR_RUNTIME("Error in %s (line %d): option too long.\n",filename,line);
90                                 break;
91                         }
92                         option[i+1] = '\0';
93                         option[i++] = *p++;
94                 }
95
96                 while(*p <= 32) { /* skip spaces */
97                         if (*p == 0)
98                                 break;
99                         p++;
100                 }
101
102                 param[0]=0;
103                 param2[0]=0;
104                 if (*p!=0 && *p!='#') { /* param */
105                         i=0; /* read param */
106                         while(*p > 32) {
107                                 if (i+1 >= sizeof(param)) {
108                                         PERROR_RUNTIME("Error in %s (line %d): param too long.\n",filename,line);
109                                         break;
110                                 }
111                                 param[i+1] = '\0';
112                                 param[i++] = *p++;
113                         }
114
115                         while(*p <= 32) { /* skip spaces */
116                                 if (*p == 0)
117                                         break;
118                                 p++;
119                         }
120
121                         if (*p!=0 && *p!='#') { /* param2 */
122                                 i=0; /* read param2 */
123                                 while(*p >= 32) {
124                                         if (i+1 >= sizeof(param2)) {
125                                                 PERROR_RUNTIME("Error in %s (line %d): param too long.\n",filename,line);
126                                                 break;
127                                         }
128                                         param2[i+1] = '\0';
129                                         param2[i++] = *p++;
130                                 }
131                         }
132                 }
133
134                 /* at this point we have option and param */
135
136                 /* check option */
137                 if (!strcmp(option,"name")) {
138                         SCPY(ext->name, param);
139                         if (param2[0]) {
140                                 SCAT(ext->name, (char *)" ");
141                                 SCAT(ext->name, param2);
142                         }
143
144                         PDEBUG(DEBUG_CONFIG, "name of extension: %s\n",param);
145                 } else
146                 if (!strcmp(option,"prefix")) {
147                         SCPY(ext->prefix, param);
148
149                         PDEBUG(DEBUG_CONFIG, "dial prefix on pickup: %s\n",param);
150                 } else
151                 if (!strcmp(option,"next")) {
152                         SCPY(ext->next, param);
153
154                         PDEBUG(DEBUG_CONFIG, "dial next on pickup: %s\n",param);
155                 } else
156                 if (!strcmp(option,"alarm")) {
157                         SCPY(ext->alarm, param);
158
159                         PDEBUG(DEBUG_CONFIG, "alarm message (if prefix): %s\n",param);
160                 } else
161                 if (!strcmp(option,"cfu")) {
162                         SCPY(ext->cfu, param);
163
164                         PDEBUG(DEBUG_CONFIG, "call forward unconditional: %s\n",param);
165                 } else
166                 if (!strcmp(option,"cfb")) {
167                         SCPY(ext->cfb, param);
168
169                         PDEBUG(DEBUG_CONFIG, "call forward when busy: %s\n",param);
170                 } else
171                 if (!strcmp(option,"cfnr")) {
172                         SCPY(ext->cfnr, param);
173
174                         PDEBUG(DEBUG_CONFIG, "call forward on no response: %s\n",param);
175                 } else
176                 if (!strcmp(option,"cfnr_delay")) {
177                         ext->cfnr_delay = atoi(param);
178                         if (ext->cfnr_delay < 0)
179                                 ext->cfnr_delay = 1;
180
181                         PDEBUG(DEBUG_CONFIG, "call forward no response delay: %d\n",ext->cfnr_delay);
182                 } else
183                 if (!strcmp(option,"cfp")) {
184                         SCPY(ext->cfp, param);
185
186                         PDEBUG(DEBUG_CONFIG, "call forward parallel: %s\n",param);
187                 } else
188                 if (!strcmp(option,"change_forward")) {
189                         i=0;
190                         while(ext_yesno[i]) {
191                                 if (!strcasecmp(param,ext_yesno[i]))
192                                         break;
193                                 i++;
194                         }
195                         if (ext_yesno[i]) {
196                                 ext->change_forward = i;
197                                 PDEBUG(DEBUG_CONFIG, "allow the change of forwarding: %s\n", ext_yesno[i]);
198                         } else {
199                                 PDEBUG(DEBUG_CONFIG, "unknown parameter for change_forward: %s\n", param);
200                         }
201                 } else
202                 if (!strcmp(option,"interfaces")) {
203                         SCPY(ext->interfaces, param);
204
205                         PDEBUG(DEBUG_CONFIG, "interfaces to ring calls to extension: %s %s\n",param,param2);
206                 } else
207                 if (!strcmp(option,"callerid")) {
208                         ext->callerid_present = INFO_PRESENT_ALLOWED;
209                         if (!strncasecmp(param2, "anonymous", 9))
210                                 ext->callerid_present = INFO_PRESENT_RESTRICTED;
211                         if (!strncasecmp(param, "non", 3)) {
212                                 ext->callerid[0] = '\0';
213                                 ext->callerid_present = INFO_PRESENT_NOTAVAIL;
214                                 ext->callerid_type = INFO_NTYPE_UNKNOWN;
215                                 PDEBUG(DEBUG_CONFIG, "caller id: ID NOT AVAILABLE\n");
216                         } else
217                         switch(param[0]) {
218                                 case 'i':
219                                 case 'I':
220                                 ext->callerid_type = INFO_NTYPE_INTERNATIONAL;
221                                 SCPY(ext->callerid, param+1);
222                                 PDEBUG(DEBUG_CONFIG, "caller id: %s INTERNATIONAL\n",param+1);
223                                 break;
224                                 case 'n':
225                                 case 'N':
226                                 ext->callerid_type = INFO_NTYPE_NATIONAL;
227                                 SCPY(ext->callerid, param+1);
228                                 PDEBUG(DEBUG_CONFIG, "caller id: %s NATIONAL\n",param+1);
229                                 break;
230                                 case 's':
231                                 case 'S':
232                                 ext->callerid_type = INFO_NTYPE_SUBSCRIBER;
233                                 SCPY(ext->callerid, param+1);
234                                 PDEBUG(DEBUG_CONFIG, "caller id: %s SUBSCRIBER\n",param+1);
235                                 break;
236                                 default:
237                                 ext->callerid_type = INFO_NTYPE_UNKNOWN;
238                                 SCPY(ext->callerid, param);
239                                 PDEBUG(DEBUG_CONFIG, "caller id: %s UNKNOWN\n",param);
240                         }
241                         ext->callerid[sizeof(ext->callerid)-1] = 0;
242                 } else
243                 if (!strcmp(option,"id_next_call")) {
244                         ext->id_next_call_present = INFO_PRESENT_ALLOWED;
245                         if (!strncasecmp(param2, "anonymous", 9))
246                                 ext->id_next_call_present = INFO_PRESENT_RESTRICTED;
247                         if (param[0] == '\0') {
248                                 ext->id_next_call_present = -1;
249                                 PDEBUG(DEBUG_CONFIG, "id next call: no id for next call\n");
250                         } else
251                         if (!strncasecmp(param, "none", 3)) {
252                                 ext->id_next_call[0] = '\0';
253                                 ext->id_next_call_present = INFO_PRESENT_NOTAVAIL;
254                                 ext->id_next_call_type = INFO_NTYPE_UNKNOWN;
255                                 PDEBUG(DEBUG_CONFIG, "id next call: ID NOT AVAILABLE\n");
256                         } else
257                         switch(param[0]) {
258                                 case 'i':
259                                 case 'I':
260                                 ext->id_next_call_type = INFO_NTYPE_INTERNATIONAL;
261                                 SCPY(ext->id_next_call, param+1);
262                                 PDEBUG(DEBUG_CONFIG, "id next call: %s INTERNATIONAL\n",param+1);
263                                 break;
264                                 case 'n':
265                                 case 'N':
266                                 ext->id_next_call_type = INFO_NTYPE_NATIONAL;
267                                 SCPY(ext->id_next_call, param+1);
268                                 PDEBUG(DEBUG_CONFIG, "id next call: %s NATIONAL\n",param+1);
269                                 break;
270                                 case 's':
271                                 case 'S':
272                                 ext->id_next_call_type = INFO_NTYPE_SUBSCRIBER;
273                                 SCPY(ext->id_next_call, param+1);
274                                 PDEBUG(DEBUG_CONFIG, "id next call: %s SUBSCRIBER\n",param+1);
275                                 break;
276                                 default:
277                                 ext->id_next_call_type = INFO_NTYPE_UNKNOWN;
278                                 SCPY(ext->id_next_call, param);
279                                 PDEBUG(DEBUG_CONFIG, "id next call: %s UNKNOWN\n",param);
280                         }
281
282
283
284                 } else
285                 if (!strcmp(option,"change_callerid")) {
286                         i=0;
287                         while(ext_yesno[i]) {
288                                 if (!strcasecmp(param,ext_yesno[i]))
289                                         break;
290                                 i++;
291                         }
292                         if (ext_yesno[i]) {
293                                 ext->change_callerid = i;
294                                 PDEBUG(DEBUG_CONFIG, "allow the change of caller id: %s\n", ext_yesno[i]);
295                         } else {
296                                 PDEBUG(DEBUG_CONFIG, "unknown parameter for change_callerid: %s\n", param);
297                         }
298                 } else
299                 if (!strcmp(option,"anon-ignore")) {
300                         i=0;
301                         while(ext_yesno[i]) {
302                                 if (!strcasecmp(param,ext_yesno[i]))
303                                         break;
304                                 i++;
305                         }
306                         if (ext_yesno[i]) {
307                                 ext->anon_ignore = i;
308                                 PDEBUG(DEBUG_CONFIG, "ignore restriction of CLIP & COLP %s\n", ext_yesno[i]);
309                         } else {
310                                 PDEBUG(DEBUG_CONFIG, "unknown parameter given anon-ignore: %s\n", param);
311                         }
312                 } else
313                 if (!strcmp(option,"clip")) {
314                         if (!strcasecmp(param, "hide"))
315                                 ext->clip = CLIP_HIDE;
316                         else
317                                 ext->clip = CLIP_ASIS;
318
319                         PDEBUG(DEBUG_CONFIG, "clip: %d\n",ext->clip);
320                 } else
321                 if (!strcmp(option,"colp")) {
322                         if (!strcasecmp(param, "hide"))
323                                 ext->colp = COLP_HIDE;
324                         else if (!strcasecmp(param, "force"))
325                                 ext->colp = COLP_FORCE;
326                         else
327                                 ext->colp = COLP_ASIS;
328
329                         PDEBUG(DEBUG_CONFIG, "colp: %d\n",ext->colp);
330                 } else
331                 if (!strcmp(option,"clip_prefix")) {
332                         SCPY(ext->clip_prefix, param);
333
334                         PDEBUG(DEBUG_CONFIG, "clip prefix: %s\n",param);
335                 } else
336                 if (!strcmp(option,"keypad")) {
337                         i=0;
338                         while(ext_yesno[i]) {
339                                 if (!strcasecmp(param,ext_yesno[i]))
340                                         break;
341                                 i++;
342                         }
343                         if (ext_yesno[i]) {
344                                 ext->keypad = i;
345                                 PDEBUG(DEBUG_CONFIG, "use keypad to do call control %s\n", ext_yesno[i]);
346                         } else {
347                                 PDEBUG(DEBUG_CONFIG, "unknown parameter given keypad: %s\n", param);
348                         }
349                 } else
350                 if (!strcmp(option,"rights")) {
351                         i=0;
352                         while(ext_rights[i]) {
353                                 if (!strcasecmp(param,ext_rights[i]))
354                                         break;
355                                 i++;
356                         }
357                         if (ext_rights[i]) {
358                                 ext->rights = i;
359                                 PDEBUG(DEBUG_CONFIG, "rights to dial: %s\n", ext_rights[i]);
360                         } else {
361                                 PDEBUG(DEBUG_CONFIG, "given rights unknown: %s\n", param);
362                         }
363                 } else
364                 if (!strcmp(option,"delete_ext")) {
365                         i=0;
366                         while(ext_yesno[i]) {
367                                 if (!strcasecmp(param,ext_yesno[i]))
368                                         break;
369                                 i++;
370                         }
371                         if (ext_yesno[i]) {
372                                 ext->delete_ext = i;
373                                 PDEBUG(DEBUG_CONFIG, "enables the delete key function for external calls: %s\n", ext_yesno[i]);
374                         } else {
375                                 PDEBUG(DEBUG_CONFIG, "unknown parameter given delete: %s\n", param);
376                         }
377                 } else
378                 if (!strcmp(option,"noknocking")) {
379                         i=0;
380                         while(ext_yesno[i]) {
381                                 if (!strcasecmp(param,ext_yesno[i]))
382                                         break;
383                                 i++;
384                         }
385                         if (ext_yesno[i]) {
386                                 ext->noknocking = i;
387                                 PDEBUG(DEBUG_CONFIG, "noknocking %s\n", ext_yesno[i]);
388                         } else {
389                                 PDEBUG(DEBUG_CONFIG, "given noknocking param unknown: %s\n", param);
390                         }
391                 } else
392                 if (!strcmp(option,"rx_gain")
393                  || !strcmp(option,"rxvol")) {
394                         ext->rx_gain = atoi(param);
395                         if (ext->rx_gain<-8 || ext->rx_gain>8)
396                                 ext->rx_gain = 0;
397
398                         PDEBUG(DEBUG_CONFIG, "receive volume: %d\n",ext->rx_gain);
399                 } else
400                 if (!strcmp(option,"tx_gain")
401                  || !strcmp(option,"txvol")) {
402                         ext->tx_gain = atoi(param);
403                         if (ext->tx_gain<-8 || ext->tx_gain>8)
404                                 ext->tx_gain = 0;
405
406                         PDEBUG(DEBUG_CONFIG, "transmit volume: %d\n",ext->tx_gain);
407                 } else
408                 if (!strcmp(option,"own_setup")) {
409                         i=0;
410                         while(ext_yesno[i]) {
411                                 if (!strcasecmp(param,ext_yesno[i]))
412                                         break;
413                                 i++;
414                         }
415                         if (ext_yesno[i]) {
416                                 ext->own_setup = i;
417                                 PDEBUG(DEBUG_CONFIG, "own_setup %s\n", ext_yesno[i]);
418                         } else {
419                                 PDEBUG(DEBUG_CONFIG, "given own_setup param unknown: %s\n", param);
420                         }
421                 } else
422                 if (!strcmp(option,"own_proceeding")) {
423                         i=0;
424                         while(ext_yesno[i]) {
425                                 if (!strcasecmp(param,ext_yesno[i]))
426                                         break;
427                                 i++;
428                         }
429                         if (ext_yesno[i]) {
430                                 ext->own_proceeding = i;
431                                 PDEBUG(DEBUG_CONFIG, "own_proceeding %s\n", ext_yesno[i]);
432                         } else {
433                                 PDEBUG(DEBUG_CONFIG, "given own_proceeding param unknown: %s\n", param);
434                         }
435                 } else
436                 if (!strcmp(option,"own_alerting")) {
437                         i=0;
438                         while(ext_yesno[i]) {
439                                 if (!strcasecmp(param,ext_yesno[i]))
440                                         break;
441                                 i++;
442                         }
443                         if (ext_yesno[i]) {
444                                 ext->own_alerting = i;
445                                 PDEBUG(DEBUG_CONFIG, "own_alerting %s\n", ext_yesno[i]);
446                         } else {
447                                 PDEBUG(DEBUG_CONFIG, "given own_alerting param unknown: %s\n", param);
448                         }
449                 } else
450                 if (!strcmp(option,"own_cause")) {
451                         i=0;
452                         while(ext_yesno[i]) {
453                                 if (!strcasecmp(param,ext_yesno[i]))
454                                         break;
455                                 i++;
456                         }
457                         if (ext_yesno[i]) {
458                                 ext->own_cause = i;
459                                 PDEBUG(DEBUG_CONFIG, "own_cause %s\n", ext_yesno[i]);
460                         } else {
461                                 PDEBUG(DEBUG_CONFIG, "given own_cause param unknown: %s\n", param);
462                         }
463                 } else
464                 if (!strcmp(option,"facility")) {
465                         i=0;
466                         while(ext_yesno[i]) {
467                                 if (!strcasecmp(param,ext_yesno[i]))
468                                         break;
469                                 i++;
470                         }
471                         if (ext_yesno[i]) {
472                                 ext->facility = i;
473                                 PDEBUG(DEBUG_CONFIG, "facility %s\n", ext_yesno[i]);
474                         } else {
475                                 PDEBUG(DEBUG_CONFIG, "given facility param unknown: %s\n", param);
476                         }
477                 } else
478                 if (!strcmp(option,"display_cause")) {
479                         if (!strcasecmp(param, "german"))
480                                 ext->display_cause = DISPLAY_CAUSE_GERMAN;
481                         else if (!strcasecmp(param, "english"))
482                                 ext->display_cause = DISPLAY_CAUSE_ENGLISH;
483                         else if (!strcasecmp(param, "german-location"))
484                                 ext->display_cause = DISPLAY_LOCATION_GERMAN;
485                         else if (!strcasecmp(param, "english-location"))
486                                 ext->display_cause = DISPLAY_LOCATION_ENGLISH;
487                         else if (!strcasecmp(param, "number"))
488                                 ext->display_cause = DISPLAY_CAUSE_NUMBER;
489                         else
490                                 ext->display_cause = DISPLAY_CAUSE_NONE;
491
492                         PDEBUG(DEBUG_CONFIG, "display cause: %d\n",ext->display_cause);
493                 } else
494 #if 0
495                 if (!strcmp(option,"display_ext")) {
496                         if (!strcasecmp(param, "number"))
497                                 ext->display_ext = DISPLAY_CID_NUMBER;
498                         else if (!strcasecmp(param, "abbrev"))
499                                 ext->display_ext = DISPLAY_CID_ABBREVIATION;
500                         else if (!strcasecmp(param, "name"))
501                                 ext->display_ext = DISPLAY_CID_NAME;
502                         else if (!strcasecmp(param, "number-name"))
503                                 ext->display_ext = DISPLAY_CID_NUMBER_NAME;
504                         else if (!strcasecmp(param, "name-number"))
505                                 ext->display_ext = DISPLAY_CID_NAME_NUMBER;
506                         else if (!strcasecmp(param, "abbrev-number"))
507                                 ext->display_ext = DISPLAY_CID_ABBREV_NUMBER;
508                         else if (!strcasecmp(param, "abbrev-name"))
509                                 ext->display_ext = DISPLAY_CID_ABBREV_NAME;
510                         else if (!strcasecmp(param, "abbrev-name-number"))
511                                 ext->display_ext = DISPLAY_CID_ABBREV_NAME_NUMBER;
512                         else if (!strcasecmp(param, "abbrev-number-name"))
513                                 ext->display_ext = DISPLAY_CID_ABBREV_NUMBER_NAME;
514                         else
515                                 ext->display_ext = DISPLAY_CID_ASIS;
516
517                         PDEBUG(DEBUG_CONFIG, "display ext: %d\n",ext->display_ext);
518                 } else
519 #endif
520                 if (!strcmp(option,"display_ext")) {
521                         i=0;
522                         while(ext_yesno[i]) {
523                                 if (!strcasecmp(param,ext_yesno[i]))
524                                         break;
525                                 i++;
526                         }
527                         if (ext_yesno[i]) {
528                                 ext->display_ext = i;
529                                 PDEBUG(DEBUG_CONFIG, "display ext %s\n", ext_yesno[i]);
530                         } else {
531                                 PDEBUG(DEBUG_CONFIG, "given display_ext param unknown: %s\n", param);
532                         }
533                 } else
534                 if (!strcmp(option,"display_int")) {
535                         i=0;
536                         while(ext_yesno[i]) {
537                                 if (!strcasecmp(param,ext_yesno[i]))
538                                         break;
539                                 i++;
540                         }
541                         if (ext_yesno[i]) {
542                                 ext->display_int = i;
543                                 PDEBUG(DEBUG_CONFIG, "display int %s\n", ext_yesno[i]);
544                         } else {
545                                 PDEBUG(DEBUG_CONFIG, "given display_int param unknown: %s\n", param);
546                         }
547                 } else
548                 if (!strcmp(option,"display_fake")) {
549                         i=0;
550                         while(ext_yesno[i]) {
551                                 if (!strcasecmp(param,ext_yesno[i]))
552                                         break;
553                                 i++;
554                         }
555                         if (ext_yesno[i]) {
556                                 ext->display_fake = i;
557                                 PDEBUG(DEBUG_CONFIG, "display fake caller ids %s\n", ext_yesno[i]);
558                         } else {
559                                 PDEBUG(DEBUG_CONFIG, "given display_fake param unknown: %s\n", param);
560                         }
561                 } else
562                 if (!strcmp(option,"display_anon")) {
563                         i=0;
564                         while(ext_yesno[i]) {
565                                 if (!strcasecmp(param,ext_yesno[i]))
566                                         break;
567                                 i++;
568                         }
569                         if (ext_yesno[i]) {
570                                 ext->display_anon = i;
571                                 PDEBUG(DEBUG_CONFIG, "display anonymouse ids %s\n", ext_yesno[i]);
572                         } else {
573                                 PDEBUG(DEBUG_CONFIG, "given display_anon param unknown: %s\n", param);
574                         }
575                 } else
576                 if (!strcmp(option,"display_menu")) {
577                         i=0;
578                         while(ext_yesno[i]) {
579                                 if (!strcasecmp(param,ext_yesno[i]))
580                                         break;
581                                 i++;
582                         }
583                         if (ext_yesno[i]) {
584                                 ext->display_menu = i;
585                                 PDEBUG(DEBUG_CONFIG, "display menu %s\n", ext_yesno[i]);
586                         } else {
587                                 PDEBUG(DEBUG_CONFIG, "given display_menu param unknown: %s\n", param);
588                         }
589                 } else
590                 if (!strcmp(option,"display_dialing")) {
591                         i=0;
592                         while(ext_yesno[i]) {
593                                 if (!strcasecmp(param,ext_yesno[i]))
594                                         break;
595                                 i++;
596                         }
597                         if (ext_yesno[i]) {
598                                 ext->display_dialing = i;
599                                 PDEBUG(DEBUG_CONFIG, "display dialing %s\n", ext_yesno[i]);
600                         } else {
601                                 PDEBUG(DEBUG_CONFIG, "given display_dialing param unknown: %s\n", param);
602                         }
603                 } else
604                 if (!strcmp(option,"display_name")) {
605                         i=0;
606                         while(ext_yesno[i]) {
607                                 if (!strcasecmp(param,ext_yesno[i]))
608                                         break;
609                                 i++;
610                         }
611                         if (ext_yesno[i]) {
612                                 ext->display_name = i;
613                                 PDEBUG(DEBUG_CONFIG, "display name %s\n", ext_yesno[i]);
614                         } else {
615                                 PDEBUG(DEBUG_CONFIG, "given display_name param unknown: %s\n", param);
616                         }
617                 } else
618                 if (!strcmp(option,"tones_dir")) {
619                         if (param[strlen(param)-1] == '/')
620                                 param[strlen(param)-1]=0;
621                         SCPY(ext->tones_dir, param);
622
623                         PDEBUG(DEBUG_CONFIG, "directory of tones: %s\n",param);
624                 } else
625                 if (!strcmp(option,"record")) {
626                         if (!strcasecmp(param, "mono"))
627                                 ext->record = CODEC_MONO;
628                         else if (!strcasecmp(param, "stereo"))
629                                 ext->record = CODEC_STEREO;
630                         else if (!strcasecmp(param, "8bit"))
631                                 ext->record = CODEC_8BIT;
632                         else if (!strcasecmp(param, "law"))
633                                 ext->record = CODEC_LAW;
634                         else
635                                 ext->record = CODEC_OFF;
636                         PDEBUG(DEBUG_CONFIG, "given record param: %s\n", param);
637                 } else
638                 if (!strcmp(option,"password")) {
639                         SCPY(ext->password, param);
640
641                         PDEBUG(DEBUG_CONFIG, "password: %s\n",param);
642                 } else
643                 if (!strcmp(option,"vbox_mode")) {
644                         if (!strcasecmp(param, "parallel"))
645                                 ext->vbox_mode = VBOX_MODE_PARALLEL;
646                         else if (!strcasecmp(param, "announcement"))
647                                 ext->vbox_mode = VBOX_MODE_ANNOUNCEMENT;
648                         else
649                                 ext->vbox_mode = VBOX_MODE_NORMAL;
650                         PDEBUG(DEBUG_CONFIG, "given vbox mode: %s\n", param);
651                 } else
652                 if (!strcmp(option,"vbox_codec")) {
653                         if (!strcasecmp(param, "stereo"))
654                                 ext->vbox_codec = CODEC_STEREO;
655                         else if (!strcasecmp(param, "8bit"))
656                                 ext->vbox_codec = CODEC_8BIT;
657                         else if (!strcasecmp(param, "law"))
658                                 ext->vbox_codec = CODEC_LAW;
659                         else
660                                 ext->vbox_codec = CODEC_MONO;
661                         PDEBUG(DEBUG_CONFIG, "given record param: %s\n", param);
662                 } else
663                 if (!strcmp(option,"vbox_time")) {
664                         ext->vbox_time = atoi(param);
665                         if (ext->vbox_time < 0)
666                                 ext->vbox_time = 0;
667
668                         PDEBUG(DEBUG_CONFIG, "vbox time to record: %d\n",ext->vbox_time);
669                 } else
670                 if (!strcmp(option,"vbox_display")) {
671                         if (!strcasecmp(param, "detailed")
672                          || !strcasecmp(param, "detailled"))
673                                 ext->vbox_display = VBOX_DISPLAY_DETAILED;
674                         else if (!strcasecmp(param, "off"))
675                                 ext->vbox_display = VBOX_DISPLAY_OFF;
676                         else
677                                 ext->vbox_display = VBOX_DISPLAY_BRIEF;
678                         PDEBUG(DEBUG_CONFIG, "given vbox mode: %s\n", param);
679                 } else
680                 if (!strcmp(option,"vbox_language")) {
681                         if (!strcasecmp(param, "german"))
682                                 ext->vbox_language = VBOX_LANGUAGE_GERMAN;
683                         else
684                                 ext->vbox_language = VBOX_LANGUAGE_ENGLISH;
685                         PDEBUG(DEBUG_CONFIG, "given vbox mode: %s\n", param);
686                 } else
687                 if (!strcmp(option,"vbox_email")) {
688                         SCPY(ext->vbox_email, param);
689                         PDEBUG(DEBUG_CONFIG, "given vbox email: %s\n", param);
690                 } else
691                 if (!strcmp(option,"vbox_email_file")) {
692                         i=0;
693                         while(ext_yesno[i]) {
694                                 if (!strcasecmp(param,ext_yesno[i]))
695                                         break;
696                                 i++;
697                         }
698                         if (ext_yesno[i]) {
699                                 ext->vbox_email_file = i;
700                                 PDEBUG(DEBUG_CONFIG, "attach audio file %s\n", ext_yesno[i]);
701                         } else {
702                                 PDEBUG(DEBUG_CONFIG, "given vbox_email_file param unknown: %s\n", param);
703                         }
704                 } else
705                 if (!strcmp(option,"vbox_free")) {
706                         i=0;
707                         while(ext_yesno[i]) {
708                                 if (!strcasecmp(param,ext_yesno[i]))
709                                         break;
710                                 i++;
711                         }
712                         if (ext_yesno[i]) {
713                                 ext->vbox_free = i;
714                                 PDEBUG(DEBUG_CONFIG, "vbox_free %s\n", ext_yesno[i]);
715                         } else {
716                                 PDEBUG(DEBUG_CONFIG, "given vbox_free param unknown: %s\n", param);
717                         }
718                 } else
719                 if (!strcmp(option,"last_in")) {
720                         if (param[0] && last_in_count<MAX_REMEMBER) {
721                                 SCPY(ext->last_in[last_in_count], param);
722                                 last_in_count++;
723                         }
724                         PDEBUG(DEBUG_CONFIG, "last_in dialed number: %s\n",param);
725                 } else
726                 if (!strcmp(option,"last_out")) {
727                         if (param[0] && last_out_count<MAX_REMEMBER) {
728                                 SCPY(ext->last_out[last_out_count], param);
729                                 last_out_count++;
730                         }
731                         PDEBUG(DEBUG_CONFIG, "last_out dialed number: %s\n",param);
732                 } else
733                 if (!strcmp(option,"datacall")) {
734                         i=0;
735                         while(ext_yesno[i]) {
736                                 if (!strcasecmp(param,ext_yesno[i]))
737                                         break;
738                                 i++;
739                         }
740                         if (ext_yesno[i]) {
741                                 ext->datacall = i;
742                                 PDEBUG(DEBUG_CONFIG, "datacall %s\n", ext_yesno[i]);
743                         } else {
744                                 PDEBUG(DEBUG_CONFIG, "given datacall param unknown: %s\n", param);
745                         }
746                 } else
747                 if (!strcmp(option,"seconds")) {
748                         i=0;
749                         while(ext_yesno[i]) {
750                                 if (!strcasecmp(param,ext_yesno[i]))
751                                         break;
752                                 i++;
753                         }
754                         if (ext_yesno[i]) {
755                                 ext->no_seconds = 1-i;
756                                 PDEBUG(DEBUG_CONFIG, "seconds %s\n", ext_yesno[i]);
757                         } else {
758                                 PDEBUG(DEBUG_CONFIG, "unknown param for seconds: %s\n", param);
759                         }
760                 } else {
761                         PERROR_RUNTIME("Error in %s (line %d): wrong option keyword %s.\n",filename,line,option);
762                 }
763         }
764
765         if (fp) fclose(fp);
766         return(1);
767 }
768
769
770 /* write extension
771  *
772  * writes extension for given extension number from structure
773  */
774 int write_extension(struct extension *ext, char *number)
775 {
776         FILE *fp=NULL;
777         char filename[256];
778         int i;
779
780         if (number[0] == '\0')
781                 return(0);
782
783         SPRINT(filename, "%s/%s/settings", EXTENSION_DATA, number);
784
785         if (!(fp = fopen(filename, "w"))) {
786                 PERROR("Cannot open settings: \"%s\"\n", filename);
787                 return(0);
788         }
789
790         fprintf(fp,"# Settings of extension %s\n\n", number);
791
792         fprintf(fp,"# Name of extension:\n");
793         fprintf(fp,"name            %s\n\n",ext->name);
794
795         fprintf(fp,"# Predialed prefix after pick-up of the phone\n");
796         fprintf(fp,"prefix          %s\n\n",ext->prefix);
797
798         fprintf(fp,"# Next prefix to dial pick-up of the phone\n");
799         fprintf(fp,"# This will be cleared on hangup.\n");
800         fprintf(fp,"next            %s\n\n",ext->next);
801
802 //      fprintf(fp,"# Set up alarm message after prefix is dialed and connection is established\n");
803 //      fprintf(fp,"alarm           %s\n\n",ext->alarm);
804
805         fprintf(fp,"# Interface(s) to ring on calls to extension (as named in interface.conf)\n");
806         fprintf(fp,"# Seperate multiple interfaces by using komma without spaces\n");
807         fprintf(fp,"# Example: Int would ring on the interface with the name \"Int\"\n");
808         fprintf(fp,"#          Int1,Int2 would ring incoming calls on both interfaces Int1 and Int2.\n");
809         fprintf(fp,"interfaces      %s\n\n",ext->interfaces);
810
811         fprintf(fp,"# Call Forward Unconditional (CFU)\n");
812         fprintf(fp,"# No port will be called, CFB, CFNR and CFP is ignored.\n");
813         fprintf(fp,"# Use keyword \"vbox\" to forward call directly to answering machine.\n");
814         fprintf(fp,"cfu             %s\n\n",ext->cfu);
815
816         fprintf(fp,"# Call Forward when Busy (CFB)\n");
817         fprintf(fp,"# If the extension is in use at least once, this forward is done.\n");
818         fprintf(fp,"# In case of busy line, CFNR and CFP is ignored.\n");
819         fprintf(fp,"# Use keyword \"vbox\" to forward call to answering machine when busy.\n");
820         fprintf(fp,"cfb             %s\n\n",ext->cfb);
821
822         fprintf(fp,"# Call Forward on No Response (CFNR)\n");
823         fprintf(fp,"# If noone answers, the call is forwarded, ports and CFP will be released.\n");
824         fprintf(fp,"# The default delay is 20 seconds.\n");
825         fprintf(fp,"# Use keyword \"vbox\" to forward call to answering machine on no response.\n");
826         fprintf(fp,"cfnr            %s\n",ext->cfnr);
827         fprintf(fp,"cfnr_delay      %d\n\n",ext->cfnr_delay);
828
829         fprintf(fp,"# Call Forward Parallel (CFP)\n");
830         fprintf(fp,"# Call will ring on the forwarded number, simulaniousely with the ports.\n");
831         fprintf(fp,"cfp             %s\n\n",ext->cfp);
832
833         fprintf(fp,"# Allow user to change call forwarding.\n");
834         fprintf(fp,"change_forward  %s\n\n", ext_yesno[ext->change_forward]);
835
836         fprintf(fp,"# Caller id\n# This must be one of the following:\n");
837         fprintf(fp,"# <number> (as dialed from your local area)\n");
838         fprintf(fp,"# <number> anonymous (will only be shown to emergency phones)\n");
839         fprintf(fp,"# none (no number available at all)\n");
840         fprintf(fp,"# by default the number is of type UNKNOWN (for MULTIPOINT lines)\n");
841         fprintf(fp,"# if your caller id is not screened on outgoing calls use one of the following:\n");
842         fprintf(fp,"# use prefix 'i' for TYPE INTERNATIONAL (i<county code><areacode+number>)\n");
843         fprintf(fp,"# use prefix 'n' for TYPE NATIONAL (n<areacode+number>)\n");
844         fprintf(fp,"# use prefix 's' for TYPE SUBSCRIBER (s<local number>)\n");
845         if (ext->callerid_present == INFO_PRESENT_NOTAVAIL)
846                 fprintf(fp,"callerid        none\n\n");
847         else {
848                 switch(ext->callerid_type) {
849                         case INFO_NTYPE_INTERNATIONAL:
850                         fprintf(fp,"callerid        i%s%s\n\n",ext->callerid, (ext->callerid_present==INFO_PRESENT_RESTRICTED)?" anonymous":"");
851                         break;
852                         case INFO_NTYPE_NATIONAL:
853                         fprintf(fp,"callerid        n%s%s\n\n",ext->callerid, (ext->callerid_present==INFO_PRESENT_RESTRICTED)?" anonymous":"");
854                         break;
855                         case INFO_NTYPE_SUBSCRIBER:
856                         fprintf(fp,"callerid        s%s%s\n\n",ext->callerid, (ext->callerid_present==INFO_PRESENT_RESTRICTED)?" anonymous":"");
857                         break;
858                         default:
859                         fprintf(fp,"callerid        %s%s\n\n",ext->callerid, (ext->callerid_present==INFO_PRESENT_RESTRICTED)?" anonymous":"");
860                 }
861         }
862
863         fprintf(fp,"# Caller id for next call (see caller id)\n");
864         if (ext->id_next_call_present < 0)
865                 fprintf(fp,"id_next_call    \n\n");
866         else if (ext->id_next_call_present == INFO_PRESENT_NOTAVAIL)
867                 fprintf(fp,"id_next_call    none\n\n");
868         else {
869                 switch(ext->id_next_call_type) {
870                         case INFO_NTYPE_INTERNATIONAL:
871                         fprintf(fp,"id_next_call    i%s%s\n\n",ext->id_next_call, (ext->id_next_call_present==INFO_PRESENT_RESTRICTED)?" anonymous":"");
872                         break;
873                         case INFO_NTYPE_NATIONAL:
874                         fprintf(fp,"id_next_call    n%s%s\n\n",ext->id_next_call, (ext->id_next_call_present==INFO_PRESENT_RESTRICTED)?" anonymous":"");
875                         break;
876                         case INFO_NTYPE_SUBSCRIBER:
877                         fprintf(fp,"id_next_call    s%s%s\n\n",ext->id_next_call, (ext->id_next_call_present==INFO_PRESENT_RESTRICTED)?" anonymous":"");
878                         break;
879                         default:
880                         fprintf(fp,"id_next_call    %s%s\n\n",ext->id_next_call, (ext->id_next_call_present==INFO_PRESENT_RESTRICTED)?" anonymous":"");
881                 }
882         }
883
884         fprintf(fp,"# Allow user to change caller ID.\n");
885         fprintf(fp,"change_callerid %s\n\n", ext_yesno[ext->change_callerid]);
886
887         fprintf(fp,"# Caller Line Identification Presentation (CLIP)\n");
888         fprintf(fp,"# clip (asis|hide)\n");
889         fprintf(fp,"# asis: On forwarded calls the CLIP is used as presented by the calling party.\n");
890         fprintf(fp,"# hide: Always use extension's caller id, even on forwared calls.\n");
891         switch(ext->clip) {
892                 case CLIP_HIDE:
893                 fprintf(fp,"clip            hide\n\n");
894                 break;
895                 default:
896                 fprintf(fp,"clip            asis\n\n");
897         }
898
899         fprintf(fp,"# Connected Line Identification Presentation (COLP)\n");
900         fprintf(fp,"# colp (asis|hide|force)\n");
901         fprintf(fp,"# asis: Provides colp as defined by the extension's caller id.\n");
902         fprintf(fp,"#       On forwarded calls the COLP is used as presented by the called party.\n");
903         fprintf(fp,"# hide: Always use extension's caller id, even on forwared calls.\n");
904         fprintf(fp,"# force: If COLP is not presented by forwarded calls the dialed number is used.\n");
905         switch(ext->colp) {
906                 case COLP_HIDE:
907                 fprintf(fp,"colp            hide\n\n");
908                 break;
909                 case COLP_FORCE:
910                 fprintf(fp,"colp            force\n\n");
911                 break;
912                 default:
913                 fprintf(fp,"colp            asis\n\n");
914         }
915
916         fprintf(fp,"# CLIP Prefix\n");
917         fprintf(fp,"# Adds a prefix to incoming caller IDs, so telephones will be able to respond\n");
918         fprintf(fp,"# to unanswered calls from their list. The prefix must be the digit(s) to get\n");
919         fprintf(fp,"# an external line. The caller ID will then be extendet so that they can be\n");
920         fprintf(fp,"# dialed from internal telephones. Many telephones have this feature, but some\n");
921         fprintf(fp,"# don't.\n");
922         fprintf(fp,"clip_prefix     %s\n\n",ext->clip_prefix);
923
924         fprintf(fp,"# Keypad control\n");
925         fprintf(fp,"# If supported by telephone, pressing a key on the keypad will not result in\n");
926         fprintf(fp,"# DTMF tone, but the digit is transmitted via D-channel diaing info.\n");
927         fprintf(fp,"keypad          %s\n\n",(ext->keypad)?"yes":"no");
928
929         fprintf(fp,"# Ignore restriction of COLP and CLIP\n");
930         fprintf(fp,"# In this case even restricted numbers are presented to this extension.\n");
931         fprintf(fp,"# This also works for incoming external anonymous calls IF:\n");
932         fprintf(fp,"# You have the CLIRIGN feature like POLICE or equivalent.\n");
933         fprintf(fp,"anon-ignore     %s\n\n",(ext->anon_ignore)?"yes":"no");
934
935         fprintf(fp,"# Dialing rights (none|internal|local|national|international)\n");
936         fprintf(fp,"rights          %s\n\n",ext_rights[ext->rights]);
937
938         fprintf(fp,"# Delete function for external calls. '*' will delete the last digit, '#' will\n");
939         fprintf(fp,"# delete the complete number. Also enable 'display_dialing' to see on the\n");
940         fprintf(fp,"# display what actually happens.\n");
941         fprintf(fp,"delete_ext      %s\n\n",ext_yesno[ext->delete_ext]);
942
943         fprintf(fp,"# If noknocking is enabled, the caller will get a busy message when the\n");
944         fprintf(fp,"# extension is doing at least one call.\n");
945         fprintf(fp,"noknocking      %s\n\n",ext_yesno[ext->noknocking]);
946
947         fprintf(fp,"# Transmit volume (-8 .. 8)\n");
948         fprintf(fp,"# 0 = normal\n");
949         fprintf(fp,"# 1 = double, 2 = quadrupel, 8 = 256 times (amplitude)\n");
950         fprintf(fp,"# -1 = half, -2 = quarter, 8 = 1/256th (amplitude)\n");
951         fprintf(fp,"# Audio data is limited to the maximum value when exceeds limit.\n");
952         fprintf(fp,"tx_gain          %d\n\n",ext->tx_gain);
953
954         fprintf(fp,"# Receive volume (-8 .. 8)\n");
955         fprintf(fp,"# (see tx_gain)\n");
956         fprintf(fp,"rx_gain          %d\n\n",ext->rx_gain);
957
958
959         fprintf(fp,"# Force to use tones and announcements generated by the pbx.\n");
960         fprintf(fp,"# For internal calls always own tones are used. You may specify own tones for\n");
961         fprintf(fp,"# different call states:\n");
962         fprintf(fp,"# own_setup (dialtone and during dialing)\n");
963         fprintf(fp,"# own_proceeding (call in poceeding state)\n");
964         fprintf(fp,"# own_alerting (call is ringing)\n");
965         fprintf(fp,"# own_cause (when the call gets disconnected or failed to be completed)\n");
966         fprintf(fp,"own_setup       %s\n",ext_yesno[ext->own_setup]);
967         fprintf(fp,"own_proceeding  %s\n",ext_yesno[ext->own_proceeding]);
968         fprintf(fp,"own_alerting    %s\n",ext_yesno[ext->own_alerting]);
969         fprintf(fp,"own_cause       %s\n\n",ext_yesno[ext->own_cause]);
970
971         fprintf(fp,"# Allow facility information to be transfered to the telephone.\n");
972         fprintf(fp,"# This is equired to receive advice of charge.\n");
973         fprintf(fp,"facility        %s\n\n",ext_yesno[ext->facility]);
974
975         fprintf(fp,"# Display clear causes using display messages (Q.850)\n# This must be one of the following:\n");
976         fprintf(fp,"# none (no displaying of clear causes)\n");
977         fprintf(fp,"# english (display cause text in english)\n");
978         fprintf(fp,"# german (display cause text in german)\n");
979         fprintf(fp,"# number (display cause number only)\n");
980         fprintf(fp,"# english-location (display cause text in english and location)\n");
981         fprintf(fp,"# german-location (display cause text in german and location)\n");
982         switch(ext->display_cause) {
983                 case DISPLAY_CAUSE_ENGLISH:
984                 fprintf(fp,"display_cause   english\n\n");
985                 break;
986                 case DISPLAY_CAUSE_GERMAN:
987                 fprintf(fp,"display_cause   german\n\n");
988                 break;
989                 case DISPLAY_LOCATION_ENGLISH:
990                 fprintf(fp,"display_cause   english-location\n\n");
991                 break;
992                 case DISPLAY_LOCATION_GERMAN:
993                 fprintf(fp,"display_cause   german-location\n\n");
994                 break;
995                 case DISPLAY_CAUSE_NUMBER:
996                 fprintf(fp,"display_cause   number\n\n");
997                 break;
998                 default:
999                 fprintf(fp,"display_cause   none\n\n");
1000         }
1001
1002         fprintf(fp,"# Display external caller ids using display override (yes or no)\n");
1003         fprintf(fp,"# example: \"15551212\"\n");
1004         fprintf(fp,"display_ext     %s\n\n",(ext->display_ext)?"yes":"no");
1005
1006         fprintf(fp,"# Display internal caller ids using display override (yes or no)\n");
1007         fprintf(fp,"# example: \"200 (int)\"\n");
1008         fprintf(fp,"display_int     %s\n\n",(ext->display_int)?"yes":"no");
1009
1010         fprintf(fp,"# Display if calls are anonymous using display override (yes or no)\n");
1011         fprintf(fp,"# This makes only sense if the anon-ignore feature is enabled.\n");
1012         fprintf(fp,"# example: \"15551212 anon\"\n");
1013         fprintf(fp,"display_anon    %s\n\n",(ext->display_anon)?"yes":"no");
1014
1015         fprintf(fp,"# Display fake caller ids using display override (yes or no)\n");
1016         fprintf(fp,"# If the caller uses \"clip no screening\", you will see if the number is\n");
1017         fprintf(fp,"# real or fake\n");
1018         fprintf(fp,"# example: \"15551212 fake\"\n");
1019         fprintf(fp,"display_fake    %s\n\n",(ext->display_fake)?"yes":"no");
1020
1021         fprintf(fp,"# Display caller's name if available. (yes or no)\n");
1022         fprintf(fp,"# example: \"15551212 Axel\"\n");
1023         fprintf(fp,"display_name    %s\n\n",(ext->display_name)?"yes":"no");
1024
1025         fprintf(fp,"# Display menu when '*' and '#' is pressed. The menu shows all prefixes for\n");
1026         fprintf(fp,"# internal dialing by pressing '*' for previous prefix and '#' for next prefix.\n");
1027         fprintf(fp,"# Also the dialed prefix is show on display. (yes or no)\n");
1028         fprintf(fp,"display_menu    %s\n\n",(ext->display_menu)?"yes":"no");
1029
1030         fprintf(fp,"# Display digits as they are interpreted by pbx. (yes or no)\n");
1031         fprintf(fp,"display_dialing %s\n\n",(ext->display_dialing)?"yes":"no");
1032
1033         fprintf(fp,"# Tones directory for announcements and patterns\n");
1034         fprintf(fp,"# Enter nothing for default tones as selected by options.conf or interface.conf.\n");
1035         fprintf(fp,"tones_dir       %s\n\n",ext->tones_dir);
1036
1037         fprintf(fp,"# Record calls to extension's directory. The file is written as wave.\n");
1038         fprintf(fp,"# This must be one of the following:\n");
1039         fprintf(fp,"# off (no recording)\n");
1040         fprintf(fp,"# mono (records wave 16 bit mono, 128kbits/s)\n");
1041         fprintf(fp,"# stereo (records wave 32 bit stereo, 256kbits/s)\n");
1042         fprintf(fp,"# 8bit (records wave 8 bit mono, 64kbits/s)\n");
1043         fprintf(fp,"# law (records xLaw encoded, as specified in options.conf, 64kbps/s)\n");
1044         switch(ext->record) {
1045                 case CODEC_MONO:
1046                 fprintf(fp,"record          mono\n\n");
1047                 break;
1048                 case CODEC_STEREO:
1049                 fprintf(fp,"record          stereo\n\n");
1050                 break;
1051                 case CODEC_8BIT:
1052                 fprintf(fp,"record          8bit\n\n");
1053                 break;
1054                 case CODEC_LAW:
1055                 fprintf(fp,"record          law\n\n");
1056                 break;
1057                 default:
1058                 fprintf(fp,"record          off\n\n");
1059         }
1060
1061         fprintf(fp,"# Password for callback and login\n");
1062         fprintf(fp,"# Enter nothing if callback and login should not be possible.\n");
1063         fprintf(fp,"password        %s\n\n",ext->password);
1064
1065         fprintf(fp,"# The Answering Machine. Enter the mode of answering machine.\n");
1066         fprintf(fp,"# This must be one of the following:\n");
1067         fprintf(fp,"# normal (plays announcement and records after that)\n");
1068         fprintf(fp,"# parallel (plays announcement and records also DURING announcement.)\n");
1069         fprintf(fp,"# announcement (just plays announcement and hangs up)\n");
1070         switch(ext->vbox_mode) {
1071                 case VBOX_MODE_PARALLEL:
1072                 fprintf(fp,"vbox_mode       parallel\n\n");
1073                 break;
1074                 case VBOX_MODE_ANNOUNCEMENT:
1075                 fprintf(fp,"vbox_mode       announcement\n\n");
1076                 break;
1077                 default:
1078                 fprintf(fp,"vbox_mode       normal\n\n");
1079         }
1080
1081         fprintf(fp,"# The Answering Machine. Enter the type of codec for recording.\n");
1082         fprintf(fp,"# This must be one of the following:\n");
1083         fprintf(fp,"# law (alaw/ulas codec, as specified in options.conf)\n");
1084         fprintf(fp,"# mono (16 bit mono wave file)\n");
1085         fprintf(fp,"# stereo (16 bit stereo wave file)\n");
1086         fprintf(fp,"# 8bit (8 bit mono wave file)\n");
1087         switch(ext->vbox_codec) {
1088                 case CODEC_LAW:
1089                 fprintf(fp,"vbox_codec      law\n\n");
1090                 break;
1091                 case CODEC_STEREO:
1092                 fprintf(fp,"vbox_codec      stereo\n\n");
1093                 break;
1094                 case CODEC_8BIT:
1095                 fprintf(fp,"vbox_codec      8bit\n\n");
1096                 break;
1097                 default:
1098                 fprintf(fp,"vbox_codec      mono\n\n");
1099         }
1100
1101         fprintf(fp,"# The Answering Machine. Enter maximum time to record after announcement.\n");
1102         fprintf(fp,"# Leave empty, enter \"infinite\" or give time in seconds.\n");
1103         fprintf(fp,"# Enter nothing if callback and login should not be possible.\n");
1104         if (ext->vbox_time)
1105                 fprintf(fp,"vbox_time       %d\n\n",ext->vbox_time);
1106         else
1107                 fprintf(fp,"vbox_time       infinite\n\n");
1108
1109         fprintf(fp,"# The Answering Machine. Enter mode for display current state.\n");
1110         fprintf(fp,"# This must be one of the following:\n");
1111         fprintf(fp,"# brief (displays brief information, for small displays)\n");
1112         fprintf(fp,"# detailed (displays detailed information, for larger displays)\n");
1113         fprintf(fp,"# off (don't display anything)\n");
1114         switch(ext->vbox_display) {
1115                 case VBOX_DISPLAY_OFF:
1116                 fprintf(fp,"vbox_display    off\n\n");
1117                 break;
1118                 case VBOX_DISPLAY_DETAILED:
1119                 fprintf(fp,"vbox_display    detailed\n\n");
1120                 break;
1121                 default:
1122                 fprintf(fp,"vbox_display    brief\n\n");
1123         }
1124
1125         fprintf(fp,"# The Answering Machine. Enter type of language: \"english\" or \"german\"\n");
1126         fprintf(fp,"# Display information of the menu, will be provided as specified.\n");
1127         fprintf(fp,"# The menu's voice is located in \"vbox_english\" and \"vbox_german\".\n");
1128         if (ext->vbox_language)
1129                 fprintf(fp,"vbox_language   german\n\n");
1130         else
1131                 fprintf(fp,"vbox_language   english\n\n");
1132
1133         fprintf(fp,"# The Answering Machine. Enter email to send incoming messages to:\n");
1134         fprintf(fp,"# All incoming message will be send to the given address.\n");
1135         fprintf(fp,"# The audio file is attached if \"vbox_email_file\" is 'yes'\n");
1136         fprintf(fp,"vbox_email      %s\n", ext->vbox_email);
1137         fprintf(fp,"vbox_email_file %s\n\n",ext_yesno[ext->vbox_email_file]);
1138
1139         fprintf(fp,"# If audio path is connected prior answering of a call, say 'yes'\n");
1140         fprintf(fp,"# will cause the call to be billed after playing the announcement. (yes or no)\n");
1141         fprintf(fp,"vbox_free       %s\n\n",(ext->vbox_free)?"yes":"no");
1142
1143         fprintf(fp,"# Accept incoming data calls as it would be an audio call.\n");
1144         fprintf(fp,"datacall        %s\n\n",ext_yesno[ext->datacall]);
1145
1146         fprintf(fp,"# Include seconds (time) in the connect message. (Should be always enabled.)\n");
1147         fprintf(fp,"seconds         %s\n\n",ext_yesno[1-ext->no_seconds]);
1148
1149         fprintf(fp,"# Last outgoing and incoming numbers (including prefix)\n");
1150         i = 0;
1151         while(i < MAX_REMEMBER) {
1152                 if (ext->last_out[i][0])
1153                         fprintf(fp,"last_out        %s\n",ext->last_out[i]);
1154                 i++;
1155         }
1156         i = 0;
1157         while(i < MAX_REMEMBER) {
1158                 if (ext->last_in[i][0])
1159                         fprintf(fp,"last_in         %s\n",ext->last_in[i]);
1160                 i++;
1161         }
1162         fprintf(fp,"\n");
1163
1164
1165         if (fp) fclose(fp);
1166         return(1);
1167 }
1168
1169
1170 /* write log for extension
1171  *
1172  */
1173 int write_log(char *number, char *callerid, char *calledid, time_t start, time_t stop, int aoce, int cause, int location)
1174 {
1175         const char *mon[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
1176         FILE *fp=NULL;
1177         char filename[256];
1178         struct tm *tm;
1179
1180         if (callerid[0] == '\0')
1181                 callerid = (char *)"<unknown>";
1182
1183         SPRINT(filename, "%s/%s/log", EXTENSION_DATA, number);
1184
1185         if (!(fp = fopen(filename, "a"))) {
1186                 PERROR("Cannot open log: \"%s\"\n", filename);
1187                 return(0);
1188         }
1189
1190         tm = localtime(&start);
1191         fprintf(fp,"%s %2d %04d %02d:%02d:%02d %s", mon[tm->tm_mon], tm->tm_mday, tm->tm_year+1900, tm->tm_hour, tm->tm_min, tm->tm_sec, number);
1192         if (stop)
1193                 fprintf(fp," %2ld:%02d:%02d", (stop-start)/3600, (((unsigned int)(stop-start))/60)%60, ((unsigned int)(stop-start))%60);
1194         else
1195                 fprintf(fp," --:--:--");
1196         fprintf(fp," %s -> %s", callerid, calledid);
1197         if (cause >= 1 && cause <=127 && location>=0 && location<=15)
1198                 fprintf(fp," (cause=%d '%s' location=%d '%s')", cause, isdn_cause[cause].german, location, isdn_location[location].german);
1199         fprintf(fp,"\n");
1200
1201         if (fp) fclose(fp);
1202         return(1);
1203 }
1204
1205
1206 /* parse phonebook
1207  *
1208  * reads phone book of extextension and compares the given elements which
1209  * are: abreviation, phone number, name (name is not compared)
1210  * on success a 1 is returned and the pointers of elements are set to the
1211  * result.
1212  */
1213 int parse_phonebook(char *number, char **abbrev_pointer, char **phone_pointer, char **name_pointer)
1214 {
1215         FILE *fp=NULL;
1216         char filename[256];
1217         char *p;
1218         static char abbrev[32], phone[256], name[256];
1219         unsigned int line,i;
1220         char buffer[1024];
1221         int found = 0, found_if_more_digits = 0;
1222
1223         SPRINT(filename, "%s/%s/phonebook", EXTENSION_DATA, number);
1224
1225         if (!(fp = fopen(filename, "r"))) {
1226                 PERROR("Cannot open phonebook: \"%s\"\n", filename);
1227                 return(0);
1228         }
1229
1230         line=0;
1231         while((fgets(buffer, sizeof(buffer), fp))) {
1232                 line++;
1233                 buffer[sizeof(buffer)-1] = '\0';
1234                 if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
1235                 p = buffer;
1236
1237                 while(*p <= 32) { /* skip spaces */
1238                         if (*p == 0)
1239                                 break;
1240                         p++;
1241                 }
1242                 if (*p==0 || *p=='#') /* ignore comments and empty line */
1243                         continue;
1244
1245                 abbrev[0]=0;
1246                 phone[0]=0;
1247                 name[0]=0;
1248
1249                 i=0; /* read abbrev */
1250                 while(*p > 32) {
1251                         if (i+1 >= sizeof(abbrev)) {
1252                                 PERROR_RUNTIME("Error in %s (line %d): abbrev too long.\n",filename,line);
1253                                 break;
1254                         }
1255                         abbrev[i+1] = '\0';
1256                         abbrev[i++] = *p++;
1257                 }
1258
1259                 while(*p <= 32) { /* skip spaces */
1260                         if (*p == 0)
1261                                 break;
1262                         p++;
1263                 }
1264
1265                 if (*p!=0 && *p!='#') { /* phone */
1266                         i=0; /* read phone */
1267                         while(*p > 32) {
1268                                 if (i+1 >= sizeof(phone)) {
1269                                         PERROR_RUNTIME("Error in %s (line %d): phone too long.\n",filename,line);
1270                                         break;
1271                                 }
1272                                 phone[i+1] = '\0';
1273                                 phone[i++] = *p++;
1274                         }
1275                         while(*p <= 32) { /* skip spaces */
1276                                 if (*p == 0)
1277                                         break;
1278                                 p++;
1279                         }
1280                 }
1281
1282                 if (*p!=0 && *p!='#') { /* name */
1283                         i=0; /* read name */
1284                         while(*p > 0) {
1285                                 if (i+1 >= sizeof(name)) {
1286                                         PERROR_RUNTIME("Error in %s (line %d): name too long.\n",filename,line);
1287                                         break;
1288                                 }
1289                                 name[i+1] = '\0';
1290                                 name[i++] = *p++;
1291                         }
1292                 }
1293
1294                 if (*abbrev_pointer) {
1295                         if (!strncmp(*abbrev_pointer, abbrev, strlen(*abbrev_pointer))) {
1296                                 /* may match if abbreviation is longer */
1297                                 found_if_more_digits = 1;
1298                         }
1299                         if (!!strcasecmp(*abbrev_pointer, abbrev))
1300                                 continue;
1301                 }
1302                 if (*phone_pointer)
1303                         if (!!strcasecmp(*phone_pointer, phone))
1304                                 continue;
1305                 if (*name_pointer)
1306                         if (!!strcasecmp(*name_pointer, name))
1307                                 continue;
1308
1309                 found = 1;
1310                 break; /* found entry */
1311         }
1312
1313         if (fp) fclose(fp);
1314
1315         if (found) {
1316                 *abbrev_pointer = abbrev;
1317                 *phone_pointer = phone;
1318                 *name_pointer = name;
1319         }
1320
1321         if (found == 0) {
1322                 if (found_if_more_digits)
1323                         found = -1;
1324         }
1325         return(found);
1326 }
1327
1328 /* parsing secrets file
1329  *
1330  * 'number' specifies the externsion number, not the caller id
1331  * 'remote_id' specifies the dialed number, or the caller id for incoming calls
1332  * the result is the auth, crypt and key string, and 1 is returned.
1333  * on failure or not matching number, the 0 is returned
1334  */
1335 int parse_secrets(char *number, char *remote_id, char **auth_pointer, char **crypt_pointer, char **key_pointer)
1336 {
1337         FILE *fp=NULL;
1338         char filename[256];
1339         char *p;
1340         char remote[128];
1341         static char auth[64], crypt[64], key[4096];
1342         unsigned int line,i;
1343         char buffer[4096];
1344         int found = 0;
1345
1346         SPRINT(filename, "%s/%s/secrets", EXTENSION_DATA, number);
1347
1348         if (!(fp = fopen(filename, "r"))) {
1349                 PERROR("Cannot open secrets: \"%s\"\n", filename);
1350                 return(0);
1351         }
1352
1353         line=0;
1354         while((fgets(buffer, sizeof(buffer), fp))) {
1355                 line++;
1356                 buffer[sizeof(buffer)-1] = '\0';
1357                 if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
1358                 p = buffer;
1359
1360                 while(*p <= 32) { /* skip spaces */
1361                         if (*p == 0)
1362                                 break;
1363                         p++;
1364                 }
1365                 if (*p==0 || *p=='#') /* ignore comments and empty line */
1366                         continue;
1367
1368                 remote[0]=0;
1369                 auth[0]=0;
1370                 crypt[0]=0;
1371                 key[0]=0;
1372
1373                 i=0; /* read auth */
1374                 while(*p > 32) {
1375                         if (i+1 >= sizeof(remote)) {
1376                                 PERROR_RUNTIME("Error in %s (line %d): remote too long.\n",filename,line);
1377                                 break;
1378                         }
1379                         remote[i+1] = '\0';
1380                         remote[i++] = *p++;
1381                 }
1382
1383                 while(*p <= 32) { /* skip spaces */
1384                         if (*p == 0)
1385                                 break;
1386                         p++;
1387                 }
1388
1389                 if (*p!=0 && *p!='#') { /* auth */
1390                         i=0; /* read auth */
1391                         while(*p > 32) {
1392                                 if (i+1 >= sizeof(auth)) {
1393                                         PERROR_RUNTIME("Error in %s (line %d): auth too long.\n",filename,line);
1394                                         break;
1395                                 }
1396                                 auth[i+1] = '\0';
1397                                 auth[i++] = *p++;
1398                         }
1399                         while(*p <= 32) { /* skip spaces */
1400                                 if (*p == 0)
1401                                         break;
1402                                 p++;
1403                         }
1404                 }
1405
1406                 if (*p!=0 && *p!='#') { /* crypt */
1407                         i=0; /* read crypt */
1408                         while(*p > 32) {
1409                                 if (i+1 >= sizeof(crypt)) {
1410                                         PERROR_RUNTIME("Error in %s (line %d): crypt too long.\n",filename,line);
1411                                         break;
1412                                 }
1413                                 crypt[i+1] = '\0';
1414                                 crypt[i++] = *p++;
1415                         }
1416                         while(*p <= 32) { /* skip spaces */
1417                                 if (*p == 0)
1418                                         break;
1419                                 p++;
1420                         }
1421                 }
1422
1423                 if (*p!=0 && *p!='#') { /* key */
1424                         i=0; /* read key */
1425                         while(*p > 0) {
1426                                 if (i+1 >= sizeof(key)) {
1427                                         PERROR_RUNTIME("Error in %s (line %d): key too long.\n",filename,line);
1428                                         break;
1429                                 }
1430                                 key[i+1] = '\0';
1431                                 key[i++] = *p++;
1432                         }
1433                 }
1434 //printf("COMPARING: '%s' with '%s' %s %s %s\n", remote_id, remote, auth, crypt, key);
1435
1436                 if (!!strcasecmp(remote, remote_id))
1437                         continue;
1438
1439                 found = 1;
1440                 break; /* found entry */
1441         }
1442
1443         if (fp) fclose(fp);
1444
1445         if (found) {
1446                 *auth_pointer = auth;
1447                 *crypt_pointer = crypt;
1448                 *key_pointer = key;
1449         }
1450
1451         return(found);
1452 }
1453
1454 /* parse directory
1455  *
1456  * the caller id is given and the name is returned. if the name is not found,
1457  * NULL is returned.
1458  * on success a 1 is returned and the pointers of elements are set to the
1459  * result.
1460  */
1461 char *parse_directory(char *number, int type)
1462 {
1463         FILE *fp=NULL;
1464         char filename[256];
1465         char *p;
1466         static char phone[32], name[64];
1467         unsigned int line,i;
1468         char buffer[256];
1469         int found = 0;
1470
1471         SPRINT(filename, "%s/directory.list", CONFIG_DATA);
1472
1473         if (!(fp = fopen(filename, "r"))) {
1474                 PERROR("Cannot open directory: \"%s\"\n", filename);
1475                 return(NULL);
1476         }
1477
1478         line=0;
1479         while((fgets(buffer, sizeof(buffer), fp))) {
1480                 line++;
1481                 buffer[sizeof(buffer)-1] = '\0';
1482                 if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
1483                 p = buffer;
1484
1485                 while(*p <= 32) { /* skip spaces */
1486                         if (*p == 0)
1487                                 break;
1488                         p++;
1489                 }
1490                 if (*p==0 || *p=='#') /* ignore comments and empty line */
1491                         continue;
1492
1493                 phone[0]=0;
1494                 name[0]=0;
1495
1496                 i=0; /* read number */
1497                 while(*p > 32) {
1498                         if (i+1 >= sizeof(phone)) {
1499                                 PERROR_RUNTIME("Error in %s (line %d): number too long.\n",filename,line);
1500                                 break;
1501                         }
1502                         phone[i+1] = '\0';
1503                         phone[i++] = *p++;
1504                 }
1505
1506                 while(*p <= 32) { /* skip spaces */
1507                         if (*p == 0)
1508                                 break;
1509                         p++;
1510                 }
1511
1512                 i=0; /* read name */
1513                 while(*p >= 32) {
1514                         if (i+1 >= sizeof(name)) {
1515                                 PERROR_RUNTIME("Error in %s (line %d): name too long.\n",filename,line);
1516                                 break;
1517                         }
1518                         name[i+1] = '\0';
1519                         name[i++] = *p++;
1520                 }
1521
1522                 if (phone[0] == 'i') {
1523                         if (type != INFO_NTYPE_INTERNATIONAL)
1524                                 continue;
1525                         if (!strcmp(number, phone+1)) {
1526                                 found = 1;
1527                                 break;
1528                         }
1529                         continue;
1530                 }
1531                 if (phone[0] == 'n') {
1532                         if (type != INFO_NTYPE_NATIONAL)
1533                                 continue;
1534                         if (!strcmp(number, phone+1)) {
1535                                 found = 1;
1536                                 break;
1537                         }
1538                         continue;
1539                 }
1540                 if (phone[0] == 's') {
1541                         if (type==INFO_NTYPE_NATIONAL || type==INFO_NTYPE_INTERNATIONAL)
1542                                 continue;
1543                         if (!strcmp(number, phone+1)) {
1544                                 found = 1;
1545                                 break;
1546                         }
1547                         continue;
1548                 }
1549                 if (!strncmp(phone, options.international, strlen(options.international))) {
1550                         if (type != INFO_NTYPE_INTERNATIONAL)
1551                                 continue;
1552                         if (!strcmp(number, phone+strlen(options.international))) {
1553                                 found = 1;
1554                                 break;
1555                         }
1556                         continue;
1557                 }
1558                 if (!options.national[0]) { /* no national prefix */
1559                         if (type == INFO_NTYPE_INTERNATIONAL)
1560                                 continue;
1561                         if (!strcmp(number, phone)) {
1562                                 found = 1;
1563                                 break;
1564                         }
1565                         continue;
1566                 }
1567                 if (!strncmp(phone, options.national, strlen(options.national))) {
1568                         if (type != INFO_NTYPE_NATIONAL)
1569                                 continue;
1570                         if (!strcmp(number, phone+strlen(options.national))) {
1571                                 found = 1;
1572                                 break;
1573                         }
1574                         continue;
1575                 }
1576                 if (type==INFO_NTYPE_NATIONAL || type==INFO_NTYPE_INTERNATIONAL)
1577                         continue;
1578                 if (!strcmp(number, phone)) {
1579                         found = 1;
1580                         break;
1581                 }
1582         }
1583
1584         if (fp) fclose(fp);
1585
1586         if (found)
1587                 return(name);
1588         else
1589                 return(NULL);
1590 }
1591
1592 /* parse callbackauth
1593  *
1594  * searches for the given caller id and returns 1 == true or 0 == false
1595  */
1596 int parse_callbackauth(char *number, struct caller_info *callerinfo)
1597 {
1598         FILE *fp = NULL;
1599         char filename[256];
1600         char *p;
1601         unsigned int line,i;
1602         char buffer[256];
1603         static char caller_type[32], caller_id[64];
1604         int found = 0;
1605
1606         SPRINT(filename, "%s/%s/callbackauth", EXTENSION_DATA, number);
1607
1608         if (!(fp = fopen(filename, "r"))) {
1609                 PDEBUG(DEBUG_EPOINT, "Cannot open callbackauth: \"%s\"\n", filename);
1610                 return(0);
1611         }
1612
1613         line=0;
1614         while((fgets(buffer, sizeof(buffer), fp))) {
1615                 line++;
1616                 buffer[sizeof(buffer)-1] = '\0';
1617                 if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
1618                 p = buffer;
1619
1620                 while(*p <= 32) { /* skip spaces */
1621                         if (*p == 0)
1622                                 break;
1623                         p++;
1624                 }
1625                 if (*p==0 || *p=='#') /* ignore comments and empty line */
1626                         continue;
1627
1628                 caller_type[0]=0;
1629                 caller_id[0]=0;
1630
1631                 i=0; /* read caller_type */
1632                 while(*p > 32) {
1633                         if (i+1 >= sizeof(caller_type)) {
1634                                 PERROR_RUNTIME("Error in %s (line %d): caller_type too long.\n",filename,line);
1635                                 break;
1636                         }
1637                         caller_type[i+1] = '\0';
1638                         caller_type[i++] = *p++;
1639                 }
1640
1641                 while(*p <= 32) { /* skip spaces */
1642                         if (*p == 0)
1643                                 break;
1644                         p++;
1645                 }
1646
1647                 if (*p!=0 && *p!='#') { /* caller_id */
1648                         i=0; /* read caller_id */
1649                         while(*p > 32) {
1650                                 if (i+1 >= sizeof(caller_id)) {
1651                                         PERROR_RUNTIME("Error in %s (line %d): caller_id too long.\n",filename,line);
1652                                         break;
1653                                 }
1654                                 caller_id[i+1] = '\0';
1655                                 caller_id[i++] = *p++;
1656                         }
1657                         // ignoring more
1658                 }
1659
1660                 if (caller_type[0]=='\0' && caller_id[0]=='\0')
1661                         continue;
1662
1663                 if (atoi(caller_type) != callerinfo->ntype)
1664                         continue;
1665
1666                 if (!!strcmp(caller_id, callerinfo->id))
1667                         continue;
1668
1669                 found = 1;
1670                 break; /* found entry */
1671         }
1672
1673         if (fp) fclose(fp);
1674
1675         if (found)
1676                 return(1);
1677         return(0);
1678 }
1679
1680
1681 /* append line to callbackauth
1682  *
1683  */
1684 void append_callbackauth(char *number, struct caller_info *callerinfo)
1685 {
1686         FILE *fp = NULL;
1687         char filename[256];
1688
1689         SPRINT(filename, "%s/%s/callbackauth", EXTENSION_DATA, number);
1690
1691         if (callerinfo->id[0]=='\0') {
1692                 PERROR("caller has no id.\n");
1693                 return;
1694         }
1695         if (!(fp = fopen(filename, "a"))) {
1696                 PERROR("Cannot open callbackauth: \"%s\"\n", filename);
1697                 return;
1698         }
1699
1700         fprintf(fp, "%6d  %s\n", callerinfo->ntype, callerinfo->id);
1701
1702         fclose(fp);
1703
1704 }
1705
1706