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