more ast_copy_string conversions
[asterisk/asterisk.git] / callerid.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * CallerID Generation support 
5  * 
6  * Copyright (C) 2001 - 2005, Digium, Inc.
7  *
8  * Mark Spencer <markster@digium.com>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License.
12  *
13  * Includes code and algorithms from the Zapata library.
14  *
15  */
16
17 #include <time.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <math.h>
23 #include <ctype.h>
24
25 #include "asterisk.h"
26
27 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
28
29 #include "asterisk/ulaw.h"
30 #include "asterisk/alaw.h"
31 #include "asterisk/frame.h"
32 #include "asterisk/channel.h"
33 #include "asterisk/callerid.h"
34 #include "asterisk/logger.h"
35 #include "asterisk/fskmodem.h"
36 #include "asterisk/utils.h"
37
38 struct callerid_state {
39         fsk_data fskd;
40         char rawdata[256];
41         short oldstuff[160];
42         int oldlen;
43         int pos;
44         int type;
45         int cksum;
46         char name[64];
47         char number[64];
48         int flags;
49         int sawflag;
50         int len;
51 };
52
53
54 float cid_dr[4], cid_di[4];
55 float clidsb = 8000.0 / 1200.0;
56 float sasdr, sasdi;
57 float casdr1, casdi1, casdr2, casdi2;
58
59 #define CALLERID_SPACE  2200.0          /* 2200 hz for "0" */
60 #define CALLERID_MARK   1200.0          /* 1200 hz for "1" */
61 #define SAS_FREQ                 440.0
62 #define CAS_FREQ1               2130.0
63 #define CAS_FREQ2               2750.0
64
65 static inline void gen_tones(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float ddr2, float ddi2, float *cr1, float *ci1, float *cr2, float *ci2)
66 {
67         int x;
68         float t;
69         for (x=0;x<len;x++) {
70                 t = *cr1 * ddr1 - *ci1 * ddi1;
71                 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
72                 *cr1 = t;
73                 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
74                 *cr1 *= t;
75                 *ci1 *= t;      
76
77                 t = *cr2 * ddr2 - *ci2 * ddi2;
78                 *ci2 = *cr2 * ddi2 + *ci2 * ddr2;
79                 *cr2 = t;
80                 t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
81                 *cr2 *= t;
82                 *ci2 *= t;      
83                 buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
84         }
85 }
86
87 static inline void gen_tone(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float *cr1, float *ci1)
88 {
89         int x;
90         float t;
91         for (x=0;x<len;x++) {
92                 t = *cr1 * ddr1 - *ci1 * ddi1;
93                 *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
94                 *cr1 = t;
95                 t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
96                 *cr1 *= t;
97                 *ci1 *= t;      
98                 buf[x] = AST_LIN2X(*cr1 * 8192.0);
99         }
100 }
101
102 void callerid_init(void)
103 {
104         /* Initialize stuff for inverse FFT */
105         cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
106         cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
107         cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
108         cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
109         sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
110         sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
111         casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
112         casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
113         casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
114         casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
115 }
116
117 struct callerid_state *callerid_new(int cid_signalling)
118 {
119         struct callerid_state *cid;
120         cid = malloc(sizeof(struct callerid_state));
121         if (cid) {
122                 memset(cid, 0, sizeof(struct callerid_state));
123                 cid->fskd.spb = 7;              /* 1200 baud */
124                 cid->fskd.hdlc = 0;             /* Async */
125                 cid->fskd.nbit = 8;             /* 8 bits */
126                 cid->fskd.nstop = 1;    /* 1 stop bit */
127                 cid->fskd.paridad = 0;  /* No parity */
128                 cid->fskd.bw=1;                 /* Filter 800 Hz */
129                 if (cid_signalling == 2) { /* v23 signalling */
130                         cid->fskd.f_mark_idx =  4;      /* 1300 Hz */
131                         cid->fskd.f_space_idx = 5;      /* 2100 Hz */
132                 } else { /* Bell 202 signalling as default */ 
133                         cid->fskd.f_mark_idx =  2;      /* 1200 Hz */
134                         cid->fskd.f_space_idx = 3;      /* 2200 Hz */
135                 }
136                 cid->fskd.pcola = 0;            /* No clue */
137                 cid->fskd.cont = 0;                     /* Digital PLL reset */
138                 cid->fskd.x0 = 0.0;
139                 cid->fskd.state = 0;
140                 memset(cid->name, 0, sizeof(cid->name));
141                 memset(cid->number, 0, sizeof(cid->number));
142                 cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
143                 cid->pos = 0;
144         } else
145                 ast_log(LOG_WARNING, "Out of memory\n");
146         return cid;
147 }
148
149 void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
150 {
151         *flags = cid->flags;
152         if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NUMBER))
153                 *name = NULL;
154         else
155                 *name = cid->name;
156         if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
157                 *number = NULL;
158         else
159                 *number = cid->number;
160 }
161
162 void callerid_get_dtmf(char *cidstring, char *number, int *flags)
163 {
164         int i;
165         int code;
166
167         /* "Clear" the number-buffer. */
168         number[0] = 0;
169
170         if (strlen(cidstring) < 2) {
171                 ast_log(LOG_DEBUG, "No cid detected\n");
172                 *flags = CID_UNKNOWN_NUMBER;
173                 return;
174         }
175         
176         /* Detect protocol and special types */
177         if (cidstring[0] == 'B') {
178                 /* Handle special codes */
179                 code = atoi(&cidstring[1]);
180                 if (code == 0)
181                         *flags = CID_UNKNOWN_NUMBER;
182                 else if (code == 10) 
183                         *flags = CID_PRIVATE_NUMBER;
184                 else
185                         ast_log(LOG_DEBUG, "Unknown DTMF code %d\n", code);
186         } else if (cidstring[0] == 'D' && cidstring[2] == '#') {
187                 /* .DK special code */
188                 if (cidstring[1] == '1')
189                         *flags = CID_PRIVATE_NUMBER;
190                 if (cidstring[1] == '2' || cidstring[1] == '3')
191                         *flags = CID_UNKNOWN_NUMBER;
192         } else if (cidstring[0] == 'D' || cidstring[0] == 'A') {
193                 /* "Standard" callerid */
194                 for (i = 1; i < strlen(cidstring); i++ ) {
195                         if (cidstring[i] == 'C' || cidstring[i] == '#')
196                                 break;
197                         if (isdigit(cidstring[i]))
198                                 number[i-1] = cidstring[i];
199                         else
200                                 ast_log(LOG_DEBUG, "Unknown CID digit '%c'\n",
201                                         cidstring[i]);
202                 }
203                 number[i-1] = 0;
204         } else if (isdigit(cidstring[0])) {
205                 /* It begins with a digit, so we parse it as a number and hope
206                  * for the best */
207                 ast_log(LOG_WARNING, "Couldn't detect start-character. CID "
208                         "parsing might be unreliable\n");
209                 for (i = 0; i < strlen(cidstring); i++) {
210                         if (isdigit(cidstring[i]))
211                                 number[i] = cidstring[i];
212                         else
213                                 break;
214                 }
215                 number[i] = 0;
216         } else {
217                 ast_log(LOG_DEBUG, "Unknown CID protocol, start digit '%c'\n", 
218                         cidstring[0]);
219                 *flags = CID_UNKNOWN_NUMBER;
220         }
221 }
222
223 int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec)
224 {
225         int pos = 0;
226         int saslen=2400;
227         float cr1 = 1.0;
228         float ci1 = 0.0;
229         float cr2 = 1.0;
230         float ci2 = 0.0;
231         if (sendsas) {
232                 if (len < saslen)
233                         return -1;
234                 gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
235                 len -= saslen;
236                 pos += saslen;
237                 cr2 = cr1;
238                 ci2 = ci1;
239         }
240         gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
241         return 0;
242 }
243
244 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
245 {
246         int mylen = len;
247         int olen;
248         int b = 'X';
249         int res;
250         int x;
251         short *buf = malloc(2 * len + cid->oldlen);
252         short *obuf = buf;
253         if (!buf) {
254                 ast_log(LOG_WARNING, "Out of memory\n");
255                 return -1;
256         }
257         memset(buf, 0, 2 * len + cid->oldlen);
258         memcpy(buf, cid->oldstuff, cid->oldlen);
259         mylen += cid->oldlen/2;
260         for (x=0;x<len;x++) 
261                 buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
262         while(mylen >= 160) {
263                 olen = mylen;
264                 res = fsk_serie(&cid->fskd, buf, &mylen, &b);
265                 if (mylen < 0) {
266                         ast_log(LOG_ERROR, "fsk_serie made mylen < 0 (%d)\n", mylen);
267                         return -1;
268                 }
269                 buf += (olen - mylen);
270                 if (res < 0) {
271                         ast_log(LOG_NOTICE, "fsk_serie failed\n");
272                         return -1;
273                 }
274                 if (res == 1) {
275                         /* Ignore invalid bytes */
276                         if (b > 0xff)
277                                 continue;
278                         switch(cid->sawflag) {
279                         case 0: /* Look for flag */
280                                 if (b == 'U')
281                                         cid->sawflag = 2;
282                                 break;
283                         case 2: /* Get lead-in */
284                                 if ((b == 0x04) || (b == 0x80)) {
285                                         cid->type = b;
286                                         cid->sawflag = 3;
287                                         cid->cksum = b;
288                                 }
289                                 break;
290                         case 3: /* Get length */
291                                 /* Not a lead in.  We're ready  */
292                                 cid->sawflag = 4;
293                                 cid->len = b;
294                                 cid->pos = 0;
295                                 cid->cksum += b;
296                                 break;
297                         case 4: /* Retrieve message */
298                                 if (cid->pos >= 128) {
299                                         ast_log(LOG_WARNING, "Caller ID too long???\n");
300                                         return -1;
301                                 }
302                                 cid->rawdata[cid->pos++] = b;
303                                 cid->len--;
304                                 cid->cksum += b;
305                                 if (!cid->len) {
306                                         cid->rawdata[cid->pos] = '\0';
307                                         cid->sawflag = 5;
308                                 }
309                                 break;
310                         case 5: /* Check checksum */
311                                 if (b != (256 - (cid->cksum & 0xff))) {
312                                         ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
313                                         /* Try again */
314                                         cid->sawflag = 0;
315                                         break;
316                                 }
317                 
318                                 cid->number[0] = '\0';
319                                 cid->name[0] = '\0';
320                                 /* If we get this far we're fine.  */
321                                 if (cid->type == 0x80) {
322                                         /* MDMF */
323                                         /* Go through each element and process */
324                                         for (x=0;x< cid->pos;) {
325                                                 switch(cid->rawdata[x++]) {
326                                                 case 1:
327                                                         /* Date */
328                                                         break;
329                                                 case 2: /* Number */
330                                                 case 3: /* Number (for Zebble) */
331                                                 case 4: /* Number */
332                                                         res = cid->rawdata[x];
333                                                         if (res > 32) {
334                                                                 ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
335                                                                 res = 32; 
336                                                         }
337                                                         if (ast_strlen_zero(cid->number)) {
338                                                                 memcpy(cid->number, cid->rawdata + x + 1, res);
339                                                                 /* Null terminate */
340                                                                 cid->number[res] = '\0';
341                                                         }
342                                                         break;
343                                                 case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
344                                                         break;
345                                                 case 7: /* Name */
346                                                 case 8: /* Name */
347                                                         res = cid->rawdata[x];
348                                                         if (res > 32) {
349                                                                 ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
350                                                                 res = 32; 
351                                                         }
352                                                         memcpy(cid->name, cid->rawdata + x + 1, res);
353                                                         cid->name[res] = '\0';
354                                                         break;
355                                                 case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting  */
356                                                 case 19: /* UK: Network message system status (Number of messages waiting) */
357                                                 case 22: /* Something French */
358                                                         break;
359                                                 default:
360                                                         ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
361                                                 }
362                                                 x += cid->rawdata[x];
363                                                 x++;
364                                         }
365                                 } else {
366                                         /* SDMF */
367                                         ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
368                                 }
369                                 /* Update flags */
370                                 cid->flags = 0;
371                                 if (!strcmp(cid->number, "P")) {
372                                         strcpy(cid->number, "");
373                                         cid->flags |= CID_PRIVATE_NUMBER;
374                                 } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
375                                         strcpy(cid->number, "");
376                                         cid->flags |= CID_UNKNOWN_NUMBER;
377                                 }
378                                 if (!strcmp(cid->name, "P")) {
379                                         strcpy(cid->name, "");
380                                         cid->flags |= CID_PRIVATE_NAME;
381                                 } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
382                                         strcpy(cid->name, "");
383                                         cid->flags |= CID_UNKNOWN_NAME;
384                                 }
385                                 return 1;
386                                 break;
387                         default:
388                                 ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
389                         }
390                 }
391         }
392         if (mylen) {
393                 memcpy(cid->oldstuff, buf, mylen * 2);
394                 cid->oldlen = mylen * 2;
395         } else
396                 cid->oldlen = 0;
397         free(obuf);
398         return 0;
399 }
400
401 void callerid_free(struct callerid_state *cid)
402 {
403         free(cid);
404 }
405
406 static int callerid_genmsg(char *msg, int size, char *number, char *name, int flags)
407 {
408         time_t t;
409         struct tm tm;
410         char *ptr;
411         int res;
412         int i,x;
413         /* Get the time */
414         time(&t);
415         localtime_r(&t,&tm);
416         
417         ptr = msg;
418         
419         /* Format time and message header */
420         res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
421                                 tm.tm_mday, tm.tm_hour, tm.tm_min);
422         size -= res;
423         ptr += res;
424         if (!number || ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
425                 /* Indicate number not known */
426                 res = snprintf(ptr, size, "\004\001O");
427                 size -= res;
428                 ptr += res;
429         } else if (flags & CID_PRIVATE_NUMBER) {
430                 /* Indicate number is private */
431                 res = snprintf(ptr, size, "\004\001P");
432                 size -= res;
433                 ptr += res;
434         } else {
435                 /* Send up to 16 digits of number MAX */
436                 i = strlen(number);
437                 if (i > 16) i = 16;
438                 res = snprintf(ptr, size, "\002%c", i);
439                 size -= res;
440                 ptr += res;
441                 for (x=0;x<i;x++)
442                         ptr[x] = number[x];
443                 ptr[i] = '\0';
444                 ptr += i;
445                 size -= i;
446         }
447
448         if (!name || ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
449                 /* Indicate name not known */
450                 res = snprintf(ptr, size, "\010\001O");
451                 size -= res;
452                 ptr += res;
453         } else if (flags & CID_PRIVATE_NAME) {
454                 /* Indicate name is private */
455                 res = snprintf(ptr, size, "\010\001P");
456                 size -= res;
457                 ptr += res;
458         } else {
459                 /* Send up to 16 digits of name MAX */
460                 i = strlen(name);
461                 if (i > 16) i = 16;
462                 res = snprintf(ptr, size, "\007%c", i);
463                 size -= res;
464                 ptr += res;
465                 for (x=0;x<i;x++)
466                         ptr[x] = name[x];
467                 ptr[i] = '\0';
468                 ptr += i;
469                 size -= i;
470         }
471         return (ptr - msg);
472         
473 }
474
475 int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
476 {
477         unsigned char msg[256];
478         int len=0;
479         int sum;
480         int x;
481         int bytes = 0;
482         float cr = 1.0;
483         float ci = 0.0;
484         float scont = 0.0;
485         if (mdmf) {
486                 /* MDMF Message waiting */
487                 msg[len++] = 0x82;
488                 /* Length is 3 */
489                 msg[len++] = 3;
490                 /* IE is "Message Waiting Parameter" */
491                 msg[len++] = 0xb;
492                 /* Length of IE is one */
493                 msg[len++] = 1;
494                 /* Active or not */
495                 if (active)
496                         msg[len++] = 0xff;
497                 else
498                         msg[len++] = 0x00;
499         } else {
500                 /* SDMF Message waiting */
501                 msg[len++] = 0x6;
502                 /* Length is 3 */
503                 msg[len++] = 3;
504                 if (active) {
505                         msg[len++] = 0x42;
506                         msg[len++] = 0x42;
507                         msg[len++] = 0x42;
508                 } else {
509                         msg[len++] = 0x6f;
510                         msg[len++] = 0x6f;
511                         msg[len++] = 0x6f;
512                 }
513         }
514         sum = 0;
515         for (x=0;x<len;x++)
516                 sum += msg[x];
517         sum = (256 - (sum & 255));
518         msg[len++] = sum;
519         /* Wait a half a second */
520         for (x=0;x<4000;x++)
521                 PUT_BYTE(0x7f);
522         /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
523         for (x=0;x<30;x++)
524                 PUT_CLID(0x55);
525         /* Send 170ms of callerid marks */
526         for (x=0;x<170;x++)
527                 PUT_CLID_MARKMS;
528         for (x=0;x<len;x++) {
529                 PUT_CLID(msg[x]);
530         }
531         /* Send 50 more ms of marks */
532         for (x=0;x<50;x++)
533                 PUT_CLID_MARKMS;
534         return bytes;
535 }
536
537 int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting, int codec)
538 {
539         int bytes=0;
540         int x, sum;
541         int len;
542         /* Initial carriers (real/imaginary) */
543         float cr = 1.0;
544         float ci = 0.0;
545         float scont = 0.0;
546         unsigned char msg[256];
547         len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
548         if (!callwaiting) {
549                 /* Wait a half a second */
550                 for (x=0;x<4000;x++)
551                         PUT_BYTE(0x7f);
552                 /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
553                 for (x=0;x<30;x++)
554                         PUT_CLID(0x55);
555         }
556         /* Send 150ms of callerid marks */
557         for (x=0;x<150;x++)
558                 PUT_CLID_MARKMS;
559         /* Send 0x80 indicating MDMF format */
560         PUT_CLID(0x80);
561         /* Put length of whole message */
562         PUT_CLID(len);
563         sum = 0x80 + strlen(msg);
564         /* Put each character of message and update checksum */
565         for (x=0;x<len; x++) {
566                 PUT_CLID(msg[x]);
567                 sum += msg[x];
568         }
569         /* Send 2's compliment of sum */
570         PUT_CLID(256 - (sum & 255));
571
572         /* Send 50 more ms of marks */
573         for (x=0;x<50;x++)
574                 PUT_CLID_MARKMS;
575         
576         return bytes;
577 }
578
579 void ast_shrink_phone_number(char *n)
580 {
581         int x,y=0;
582         int bracketed=0;
583         for (x=0;n[x];x++) {
584                 switch(n[x]) {
585                 case '[':
586                         bracketed++;
587                         n[y++] = n[x];
588                         break;
589                 case ']':
590                         bracketed--;
591                         n[y++] = n[x];
592                         break;
593                 case '-':
594                         if (bracketed)
595                                 n[y++] = n[x];
596                         break;
597                 case '.':
598                         if (!n[x+1])
599                                 n[y++] = n[x];
600                         break;
601                 default:
602                         if (!strchr("( )", n[x]))
603                                 n[y++] = n[x];
604                 }
605         }
606         n[y] = '\0';
607 }
608
609 int ast_isphonenumber(char *n)
610 {
611         int x;
612         if (!n || ast_strlen_zero(n))
613                 return 0;
614         for (x=0;n[x];x++)
615                 if (!strchr("0123456789*#+", n[x]))
616                         return 0;
617         return 1;
618 }
619
620 int ast_callerid_parse(char *instr, char **name, char **location)
621 {
622         char *ns, *ne;
623         char *ls, *le;
624         char tmp[256];
625         /* Try for "name" <location> format or 
626            name <location> format */
627         if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
628                 /* Found the location */
629                 *le = '\0';
630                 *ls = '\0';
631                 *location = ls + 1;
632                 if ((ns = strchr(instr, '\"')) && (ne = strchr(ns + 1, '\"'))) {
633                         /* Get name out of quotes */
634                         *ns = '\0';
635                         *ne = '\0';
636                         *name = ns + 1;
637                         return 0;
638                 } else {
639                         /* Just trim off any trailing spaces */
640                         *name = instr;
641                         while(!ast_strlen_zero(instr) && (instr[strlen(instr) - 1] < 33))
642                                 instr[strlen(instr) - 1] = '\0';
643                         /* And leading spaces */
644                         while(**name && (**name < 33))
645                                 (*name)++;
646                         return 0;
647                 }
648         } else {
649                 ast_copy_string(tmp, instr, sizeof(tmp));
650                 ast_shrink_phone_number(tmp);
651                 if (ast_isphonenumber(tmp)) {
652                         /* Assume it's just a location */
653                         *name = NULL;
654                         *location = instr;
655                 } else {
656                         /* Assume it's just a name.  Make sure it's not quoted though */
657                         *name = instr;
658                         while(*(*name) && ((*(*name) < 33) || (*(*name) == '\"'))) (*name)++;
659                         ne = *name + strlen(*name) - 1;
660                         while((ne > *name) && ((*ne < 33) || (*ne == '\"'))) { *ne = '\0'; ne--; }
661                         *location = NULL;
662                 }
663                 return 0;
664         }
665         return -1;
666 }
667
668 static int __ast_callerid_generate(unsigned char *buf, char *name, char *number, int callwaiting, int codec)
669 {
670         if (name && ast_strlen_zero(name))
671                 name = NULL;
672         if (number && ast_strlen_zero(number))
673                 number = NULL;
674         return callerid_generate(buf, number, name, 0, callwaiting, codec);
675 }
676
677 int ast_callerid_generate(unsigned char *buf, char *name, char *number, int codec)
678 {
679         return __ast_callerid_generate(buf, name, number, 0, codec);
680 }
681
682 int ast_callerid_callwaiting_generate(unsigned char *buf, char *name, char *number, int codec)
683 {
684         return __ast_callerid_generate(buf, name, number, 1, codec);
685 }
686
687 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
688 {
689         if (!unknown)
690                 unknown = "<unknown>";
691         if (name && num)
692                 snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
693         else if (name) 
694                 ast_copy_string(buf, name, bufsiz);
695         else if (num)
696                 ast_copy_string(buf, num, bufsiz);
697         else
698                 ast_copy_string(buf, unknown, bufsiz);
699         return buf;
700 }
701 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
702 {
703         char *tmp;
704         char *l = NULL, *n = NULL;
705         tmp = ast_strdupa(buf);
706         if (!tmp) {
707                 name[0] = '\0';
708                 num[0] = '\0';
709                 return -1;
710         }
711         ast_callerid_parse(tmp, &n, &l);
712         if (n)
713                 ast_copy_string(name, n, namelen);
714         else
715                 name[0] = '\0';
716         if (l) {
717                 ast_shrink_phone_number(l);
718                 ast_copy_string(num, l, numlen);
719         } else
720                 num[0] = '\0';
721         return 0;
722 }
723
724 static struct {
725         int val;
726         char *name;
727         char *description;
728 } pres_types[] = {
729         {  AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
730         {  AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
731         {  AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
732         {  AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
733         {  AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
734         {  AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
735         {  AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
736         {  AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
737         {  AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
738 };
739
740 int ast_parse_caller_presentation(const char *data)
741 {
742         int i;
743
744         for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
745                 if (!strcasecmp(pres_types[i].name, data))
746                         return pres_types[i].val;
747         }
748
749         return -1;
750 }
751
752 const char *ast_describe_caller_presentation(int data)
753 {
754         int i;
755
756         for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
757                 if (pres_types[i].val == data)
758                         return pres_types[i].description;
759         }
760
761         return "unknown";
762 }