Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:49 2009

## Asterisk developer's documentation

- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- Directories

# callerid.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 1999 - 2005, Digium, Inc.
    00005  *
    00006  * Mark Spencer <markster@digium.com>
    00007  *
    00008  * See http://www.asterisk.org for more information about
    00009  * the Asterisk project. Please do not directly contact
    00010  * any of the maintainers of this project for assistance;
    00011  * the project provides a web site, mailing lists and IRC
    00012  * channels for your use.
    00013  *
    00014  * This program is free software, distributed under the terms of
    00015  * the GNU General Public License Version 2. See the LICENSE file
    00016  * at the top of the source tree.
    00017  */
    00018
    00019 /*! \file
    00020  *
    00021  * \brief CallerID Generation support
    00022  *
    00023  */
    00024
    00025 #include <time.h>
    00026 #include <string.h>
    00027 #include <stdio.h>
    00028 #include <stdlib.h>
    00029 #include <unistd.h>
    00030 #include <math.h>
    00031 #include <ctype.h>
    00032
    00033 #include "asterisk.h"
    00034
    00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 46876 $")
    00036
    00037 #include "asterisk/ulaw.h"
    00038 #include "asterisk/alaw.h"
    00039 #include "asterisk/frame.h"
    00040 #include "asterisk/channel.h"
    00041 #include "asterisk/callerid.h"
    00042 #include "asterisk/logger.h"
    00043 #include "asterisk/fskmodem.h"
    00044 #include "asterisk/utils.h"
    00045
    00046 struct callerid_state {
    00047    fsk_data fskd;
    00048    char rawdata[256];
    00049    short oldstuff[160];
    00050    int oldlen;
    00051    int pos;
    00052    int type;
    00053    int cksum;
    00054    char name[64];
    00055    char number[64];
    00056    int flags;
    00057    int sawflag;
    00058    int len;
    00059 };
    00060
    00061
    00062 float cid_dr[4], cid_di[4];
    00063 float clidsb = 8000.0 / 1200.0;
    00064 float sasdr, sasdi;
    00065 float casdr1, casdi1, casdr2, casdi2;
    00066
    00067 #define CALLERID_SPACE  2200.0      /*!< 2200 hz for "0" */
    00068 #define CALLERID_MARK   1200.0      /*!< 1200 hz for "1" */
    00069 #define SAS_FREQ      440.0
    00070 #define CAS_FREQ1    2130.0
    00071 #define CAS_FREQ2    2750.0
    00072
    00073 #define AST_CALLERID_UNKNOWN  "<unknown>"
    00074
    00075 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)
    00076 {
    00077    int x;
    00078    float t;
    00079    for (x=0;x<len;x++) {
    00080       t = *cr1 * ddr1 - *ci1 * ddi1;
    00081       *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
    00082       *cr1 = t;
    00083       t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
    00084       *cr1 *= t;
    00085       *ci1 *= t;
    00086
    00087       t = *cr2 * ddr2 - *ci2 * ddi2;
    00088       *ci2 = *cr2 * ddi2 + *ci2 * ddr2;
    00089       *cr2 = t;
    00090       t = 2.0 - (*cr2 * *cr2 + *ci2 * *ci2);
    00091       *cr2 *= t;
    00092       *ci2 *= t;
    00093       buf[x] = AST_LIN2X((*cr1 + *cr2) * 2048.0);
    00094    }
    00095 }
    00096
    00097 static inline void gen_tone(unsigned char *buf, int len, int codec, float ddr1, float ddi1, float *cr1, float *ci1)
    00098 {
    00099    int x;
    00100    float t;
    00101    for (x=0;x<len;x++) {
    00102       t = *cr1 * ddr1 - *ci1 * ddi1;
    00103       *ci1 = *cr1 * ddi1 + *ci1 * ddr1;
    00104       *cr1 = t;
    00105       t = 2.0 - (*cr1 * *cr1 + *ci1 * *ci1);
    00106       *cr1 *= t;
    00107       *ci1 *= t;
    00108       buf[x] = AST_LIN2X(*cr1 * 8192.0);
    00109    }
    00110 }
    00111
    00112 /*! \brief Initialize stuff for inverse FFT */
    00113 void callerid_init(void)
    00114 {
    00115    cid_dr[0] = cos(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
    00116    cid_di[0] = sin(CALLERID_SPACE * 2.0 * M_PI / 8000.0);
    00117    cid_dr[1] = cos(CALLERID_MARK * 2.0 * M_PI / 8000.0);
    00118    cid_di[1] = sin(CALLERID_MARK * 2.0 * M_PI / 8000.0);
    00119    sasdr = cos(SAS_FREQ * 2.0 * M_PI / 8000.0);
    00120    sasdi = sin(SAS_FREQ * 2.0 * M_PI / 8000.0);
    00121    casdr1 = cos(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
    00122    casdi1 = sin(CAS_FREQ1 * 2.0 * M_PI / 8000.0);
    00123    casdr2 = cos(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
    00124    casdi2 = sin(CAS_FREQ2 * 2.0 * M_PI / 8000.0);
    00125 }
    00126
    00127 struct callerid_state *callerid_new(int cid_signalling)
    00128 {
    00129    struct callerid_state *cid;
    00130    cid = malloc(sizeof(struct callerid_state));
    00131    if (cid) {
    00132       memset(cid, 0, sizeof(struct callerid_state));
    00133       cid->fskd.spb = 7;      /* 1200 baud */
    00134       cid->fskd.hdlc = 0;     /* Async */
    00135       cid->fskd.nbit = 8;     /* 8 bits */
    00136       cid->fskd.nstop = 1; /* 1 stop bit */
    00137       cid->fskd.paridad = 0;  /* No parity */
    00138       cid->fskd.bw=1;         /* Filter 800 Hz */
    00139       if (cid_signalling == 2) { /* v23 signalling */
    00140          cid->fskd.f_mark_idx =  4; /* 1300 Hz */
    00141          cid->fskd.f_space_idx = 5; /* 2100 Hz */
    00142       } else { /* Bell 202 signalling as default */
    00143          cid->fskd.f_mark_idx =  2; /* 1200 Hz */
    00144          cid->fskd.f_space_idx = 3; /* 2200 Hz */
    00145       }
    00146       cid->fskd.pcola = 0;    /* No clue */
    00147       cid->fskd.cont = 0;        /* Digital PLL reset */
    00148       cid->fskd.x0 = 0.0;
    00149       cid->fskd.state = 0;
    00150       memset(cid->name, 0, sizeof(cid->name));
    00151       memset(cid->number, 0, sizeof(cid->number));
    00152       cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
    00153       cid->pos = 0;
    00154    } else
    00155       ast_log(LOG_WARNING, "Out of memory\n");
    00156    return cid;
    00157 }
    00158
    00159 void callerid_get(struct callerid_state *cid, char **name, char **number, int *flags)
    00160 {
    00161    *flags = cid->flags;
    00162    if (cid->flags & (CID_UNKNOWN_NAME | CID_PRIVATE_NUMBER))
    00163       *name = NULL;
    00164    else
    00165       *name = cid->name;
    00166    if (cid->flags & (CID_UNKNOWN_NUMBER | CID_PRIVATE_NUMBER))
    00167       *number = NULL;
    00168    else
    00169       *number = cid->number;
    00170 }
    00171
    00172 void callerid_get_dtmf(char *cidstring, char *number, int *flags)
    00173 {
    00174    int i;
    00175    int code;
    00176
    00177    /* "Clear" the number-buffer. */
    00178    number[0] = 0;
    00179
    00180    if (strlen(cidstring) < 2) {
    00181       ast_log(LOG_DEBUG, "No cid detected\n");
    00182       *flags = CID_UNKNOWN_NUMBER;
    00183       return;
    00184    }
    00185
    00186    /* Detect protocol and special types */
    00187    if (cidstring[0] == 'B') {
    00188       /* Handle special codes */
    00189       code = atoi(&cidstring[1]);
    00190       if (code == 0)
    00191          *flags = CID_UNKNOWN_NUMBER;
    00192       else if (code == 10)
    00193          *flags = CID_PRIVATE_NUMBER;
    00194       else
    00195          ast_log(LOG_DEBUG, "Unknown DTMF code %d\n", code);
    00196    } else if (cidstring[0] == 'D' && cidstring[2] == '#') {
    00197       /* .DK special code */
    00198       if (cidstring[1] == '1')
    00199          *flags = CID_PRIVATE_NUMBER;
    00200       if (cidstring[1] == '2' || cidstring[1] == '3')
    00201          *flags = CID_UNKNOWN_NUMBER;
    00202    } else if (cidstring[0] == 'D' || cidstring[0] == 'A') {
    00203       /* "Standard" callerid */
    00204       for (i = 1; i < strlen(cidstring); i++ ) {
    00205          if (cidstring[i] == 'C' || cidstring[i] == '#')
    00206             break;
    00207          if (isdigit(cidstring[i]))
    00208             number[i-1] = cidstring[i];
    00209          else
    00210             ast_log(LOG_DEBUG, "Unknown CID digit '%c'\n",
    00211                cidstring[i]);
    00212       }
    00213       number[i-1] = 0;
    00214    } else if (isdigit(cidstring[0])) {
    00215       /* It begins with a digit, so we parse it as a number and hope
    00216        * for the best */
    00217       ast_log(LOG_WARNING, "Couldn't detect start-character. CID "
    00218          "parsing might be unreliable\n");
    00219       for (i = 0; i < strlen(cidstring); i++) {
    00220          if (isdigit(cidstring[i]))
    00221                                 number[i] = cidstring[i];
    00222          else
    00223             break;
    00224       }
    00225       number[i] = 0;
    00226    } else {
    00227       ast_log(LOG_DEBUG, "Unknown CID protocol, start digit '%c'\n",
    00228          cidstring[0]);
    00229       *flags = CID_UNKNOWN_NUMBER;
    00230    }
    00231 }
    00232
    00233 int ast_gen_cas(unsigned char *outbuf, int sendsas, int len, int codec)
    00234 {
    00235    int pos = 0;
    00236    int saslen=2400;
    00237    float cr1 = 1.0;
    00238    float ci1 = 0.0;
    00239    float cr2 = 1.0;
    00240    float ci2 = 0.0;
    00241    if (sendsas) {
    00242       if (len < saslen)
    00243          return -1;
    00244       gen_tone(outbuf, saslen, codec, sasdr, sasdi, &cr1, &ci1);
    00245       len -= saslen;
    00246       pos += saslen;
    00247       cr2 = cr1;
    00248       ci2 = ci1;
    00249    }
    00250    gen_tones(outbuf + pos, len, codec, casdr1, casdi1, casdr2, casdi2, &cr1, &ci1, &cr2, &ci2);
    00251    return 0;
    00252 }
    00253
    00254 int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, int codec)
    00255 {
    00256    int mylen = len;
    00257    int olen;
    00258    int b = 'X';
    00259    int res;
    00260    int x;
    00261    short *buf = malloc(2 * len + cid->oldlen);
    00262    short *obuf = buf;
    00263    if (!buf) {
    00264       ast_log(LOG_WARNING, "Out of memory\n");
    00265       return -1;
    00266    }
    00267    memset(buf, 0, 2 * len + cid->oldlen);
    00268    memcpy(buf, cid->oldstuff, cid->oldlen);
    00269    mylen += cid->oldlen/2;
    00270    for (x=0;x<len;x++)
    00271       buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]);
    00272    while(mylen >= 160) {
    00273       olen = mylen;
    00274       res = fsk_serie(&cid->fskd, buf, &mylen, &b);
    00275       if (mylen < 0) {
    00276          ast_log(LOG_ERROR, "fsk_serie made mylen < 0 (%d)\n", mylen);
    00277          free(obuf);
    00278          return -1;
    00279       }
    00280       buf += (olen - mylen);
    00281       if (res < 0) {
    00282          ast_log(LOG_NOTICE, "fsk_serie failed\n");
    00283          free(obuf);
    00284          return -1;
    00285       }
    00286       if (res == 1) {
    00287          /* Ignore invalid bytes */
    00288          if (b > 0xff)
    00289             continue;
    00290          switch(cid->sawflag) {
    00291          case 0: /* Look for flag */
    00292             if (b == 'U')
    00293                cid->sawflag = 2;
    00294             break;
    00295          case 2: /* Get lead-in */
    00296             if ((b == 0x04) || (b == 0x80)) {
    00297                cid->type = b;
    00298                cid->sawflag = 3;
    00299                cid->cksum = b;
    00300             }
    00301             break;
    00302          case 3:  /* Get length */
    00303             /* Not a lead in.  We're ready  */
    00304             cid->sawflag = 4;
    00305             cid->len = b;
    00306             cid->pos = 0;
    00307             cid->cksum += b;
    00308             break;
    00309          case 4: /* Retrieve message */
    00310             if (cid->pos >= 128) {
    00311                ast_log(LOG_WARNING, "Caller ID too long???\n");
    00312                free(obuf);
    00313                return -1;
    00314             }
    00315             cid->rawdata[cid->pos++] = b;
    00316             cid->len--;
    00317             cid->cksum += b;
    00318             if (!cid->len) {
    00319                cid->rawdata[cid->pos] = '\0';
    00320                cid->sawflag = 5;
    00321             }
    00322             break;
    00323          case 5: /* Check checksum */
    00324             if (b != (256 - (cid->cksum & 0xff))) {
    00325                ast_log(LOG_NOTICE, "Caller*ID failed checksum\n");
    00326                /* Try again */
    00327                cid->sawflag = 0;
    00328                break;
    00329             }
    00330
    00331             cid->number[0] = '\0';
    00332             cid->name[0] = '\0';
    00333             /* If we get this far we're fine.  */
    00334             if (cid->type == 0x80) {
    00335                /* MDMF */
    00336                /* Go through each element and process */
    00337                for (x=0;x< cid->pos;) {
    00338                   switch(cid->rawdata[x++]) {
    00339                   case 1:
    00340                      /* Date */
    00341                      break;
    00342                   case 2: /* Number */
    00343                   case 3: /* Number (for Zebble) */
    00344                   case 4: /* Number */
    00345                      res = cid->rawdata[x];
    00346                      if (res > 32) {
    00347                         ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]);
    00348                         res = 32;
    00349                      }
    00350                      if (ast_strlen_zero(cid->number)) {
    00351                         memcpy(cid->number, cid->rawdata + x + 1, res);
    00352                         /* Null terminate */
    00353                         cid->number[res] = '\0';
    00354                      }
    00355                      break;
    00356                   case 6: /* Stentor Call Qualifier (ie. Long Distance call) */
    00357                      break;
    00358                   case 7: /* Name */
    00359                   case 8: /* Name */
    00360                      res = cid->rawdata[x];
    00361                      if (res > 32) {
    00362                         ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]);
    00363                         res = 32;
    00364                      }
    00365                      memcpy(cid->name, cid->rawdata + x + 1, res);
    00366                      cid->name[res] = '\0';
    00367                      break;
    00368                   case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting  */
    00369                   case 19: /* UK: Network message system status (Number of messages waiting) */
    00370                   case 22: /* Something French */
    00371                      break;
    00372                   default:
    00373                      ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x-1]);
    00374                   }
    00375                   x += cid->rawdata[x];
    00376                   x++;
    00377                }
    00378             } else {
    00379                /* SDMF */
    00380                ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number));
    00381             }
    00382             /* Update flags */
    00383             cid->flags = 0;
    00384             if (!strcmp(cid->number, "P")) {
    00385                strcpy(cid->number, "");
    00386                cid->flags |= CID_PRIVATE_NUMBER;
    00387             } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) {
    00388                strcpy(cid->number, "");
    00389                cid->flags |= CID_UNKNOWN_NUMBER;
    00390             }
    00391             if (!strcmp(cid->name, "P")) {
    00392                strcpy(cid->name, "");
    00393                cid->flags |= CID_PRIVATE_NAME;
    00394             } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) {
    00395                strcpy(cid->name, "");
    00396                cid->flags |= CID_UNKNOWN_NAME;
    00397             }
    00398             free(obuf);
    00399             return 1;
    00400             break;
    00401          default:
    00402             ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag);
    00403          }
    00404       }
    00405    }
    00406    if (mylen) {
    00407       memcpy(cid->oldstuff, buf, mylen * 2);
    00408       cid->oldlen = mylen * 2;
    00409    } else
    00410       cid->oldlen = 0;
    00411    free(obuf);
    00412    return 0;
    00413 }
    00414
    00415 void callerid_free(struct callerid_state *cid)
    00416 {
    00417    free(cid);
    00418 }
    00419
    00420 static int callerid_genmsg(char *msg, int size, char *number, char *name, int flags)
    00421 {
    00422    time_t t;
    00423    struct tm tm;
    00424    char *ptr;
    00425    int res;
    00426    int i,x;
    00427    /* Get the time */
    00428    time(&t);
    00429    localtime_r(&t,&tm);
    00430
    00431    ptr = msg;
    00432
    00433    /* Format time and message header */
    00434    res = snprintf(ptr, size, "\001\010%02d%02d%02d%02d", tm.tm_mon + 1,
    00435             tm.tm_mday, tm.tm_hour, tm.tm_min);
    00436    size -= res;
    00437    ptr += res;
    00438    if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
    00439       /* Indicate number not known */
    00440       res = snprintf(ptr, size, "\004\001O");
    00441       size -= res;
    00442       ptr += res;
    00443    } else if (flags & CID_PRIVATE_NUMBER) {
    00444       /* Indicate number is private */
    00445       res = snprintf(ptr, size, "\004\001P");
    00446       size -= res;
    00447       ptr += res;
    00448    } else {
    00449       /* Send up to 16 digits of number MAX */
    00450       i = strlen(number);
    00451       if (i > 16) i = 16;
    00452       res = snprintf(ptr, size, "\002%c", i);
    00453       size -= res;
    00454       ptr += res;
    00455       for (x=0;x<i;x++)
    00456          ptr[x] = number[x];
    00457       ptr[i] = '\0';
    00458       ptr += i;
    00459       size -= i;
    00460    }
    00461
    00462    if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
    00463       /* Indicate name not known */
    00464       res = snprintf(ptr, size, "\010\001O");
    00465       size -= res;
    00466       ptr += res;
    00467    } else if (flags & CID_PRIVATE_NAME) {
    00468       /* Indicate name is private */
    00469       res = snprintf(ptr, size, "\010\001P");
    00470       size -= res;
    00471       ptr += res;
    00472    } else {
    00473       /* Send up to 16 digits of name MAX */
    00474       i = strlen(name);
    00475       if (i > 16) i = 16;
    00476       res = snprintf(ptr, size, "\007%c", i);
    00477       size -= res;
    00478       ptr += res;
    00479       for (x=0;x<i;x++)
    00480          ptr[x] = name[x];
    00481       ptr[i] = '\0';
    00482       ptr += i;
    00483       size -= i;
    00484    }
    00485    return (ptr - msg);
    00486
    00487 }
    00488
    00489 int vmwi_generate(unsigned char *buf, int active, int mdmf, int codec)
    00490 {
    00491    unsigned char msg[256];
    00492    int len=0;
    00493    int sum;
    00494    int x;
    00495    int bytes = 0;
    00496    float cr = 1.0;
    00497    float ci = 0.0;
    00498    float scont = 0.0;
    00499    if (mdmf) {
    00500       /* MDMF Message waiting */
    00501       msg[len++] = 0x82;
    00502       /* Length is 3 */
    00503       msg[len++] = 3;
    00504       /* IE is "Message Waiting Parameter" */
    00505       msg[len++] = 0xb;
    00506       /* Length of IE is one */
    00507       msg[len++] = 1;
    00508       /* Active or not */
    00509       if (active)
    00510          msg[len++] = 0xff;
    00511       else
    00512          msg[len++] = 0x00;
    00513    } else {
    00514       /* SDMF Message waiting */
    00515       msg[len++] = 0x6;
    00516       /* Length is 3 */
    00517       msg[len++] = 3;
    00518       if (active) {
    00519          msg[len++] = 0x42;
    00520          msg[len++] = 0x42;
    00521          msg[len++] = 0x42;
    00522       } else {
    00523          msg[len++] = 0x6f;
    00524          msg[len++] = 0x6f;
    00525          msg[len++] = 0x6f;
    00526       }
    00527    }
    00528    sum = 0;
    00529    for (x=0;x<len;x++)
    00530       sum += msg[x];
    00531    sum = (256 - (sum & 255));
    00532    msg[len++] = sum;
    00533    /* Wait a half a second */
    00534    for (x=0;x<4000;x++)
    00535       PUT_BYTE(0x7f);
    00536    /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
    00537    for (x=0;x<30;x++)
    00538       PUT_CLID(0x55);
    00539    /* Send 170ms of callerid marks */
    00540    for (x=0;x<170;x++)
    00541       PUT_CLID_MARKMS;
    00542    for (x=0;x<len;x++) {
    00543       PUT_CLID(msg[x]);
    00544    }
    00545    /* Send 50 more ms of marks */
    00546    for (x=0;x<50;x++)
    00547       PUT_CLID_MARKMS;
    00548    return bytes;
    00549 }
    00550
    00551 int callerid_generate(unsigned char *buf, char *number, char *name, int flags, int callwaiting, int codec)
    00552 {
    00553    int bytes=0;
    00554    int x, sum;
    00555    int len;
    00556    /* Initial carriers (real/imaginary) */
    00557    float cr = 1.0;
    00558    float ci = 0.0;
    00559    float scont = 0.0;
    00560    char msg[256];
    00561    len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
    00562    if (!callwaiting) {
    00563       /* Wait a half a second */
    00564       for (x=0;x<4000;x++)
    00565          PUT_BYTE(0x7f);
    00566       /* Transmit 30 0x55's (looks like a square wave) for channel seizure */
    00567       for (x=0;x<30;x++)
    00568          PUT_CLID(0x55);
    00569    }
    00570    /* Send 150ms of callerid marks */
    00571    for (x=0;x<150;x++)
    00572       PUT_CLID_MARKMS;
    00573    /* Send 0x80 indicating MDMF format */
    00574    PUT_CLID(0x80);
    00575    /* Put length of whole message */
    00576    PUT_CLID(len);
    00577    sum = 0x80 + strlen(msg);
    00578    /* Put each character of message and update checksum */
    00579    for (x=0;x<len; x++) {
    00580       PUT_CLID(msg[x]);
    00581       sum += msg[x];
    00582    }
    00583    /* Send 2's compliment of sum */
    00584    PUT_CLID(256 - (sum & 255));
    00585
    00586    /* Send 50 more ms of marks */
    00587    for (x=0;x<50;x++)
    00588       PUT_CLID_MARKMS;
    00589
    00590    return bytes;
    00591 }
    00592
    00593 void ast_shrink_phone_number(char *n)
    00594 {
    00595    int x,y=0;
    00596    int bracketed=0;
    00597    for (x=0;n[x];x++) {
    00598       switch(n[x]) {
    00599       case '[':
    00600          bracketed++;
    00601          n[y++] = n[x];
    00602          break;
    00603       case ']':
    00604          bracketed--;
    00605          n[y++] = n[x];
    00606          break;
    00607       case '-':
    00608          if (bracketed)
    00609             n[y++] = n[x];
    00610          break;
    00611       case '.':
    00612          if (!n[x+1])
    00613             n[y++] = n[x];
    00614          break;
    00615       default:
    00616          if (!strchr("( )", n[x]))
    00617             n[y++] = n[x];
    00618       }
    00619    }
    00620    n[y] = '\0';
    00621 }
    00622
    00623 /*! \brief checks if string consists only of digits and * \# and +
    00624    \return 1 if string is valid AST phone number
    00625    \return 0 if not
    00626 */
    00627 int ast_isphonenumber(char *n)
    00628 {
    00629    int x;
    00630    if (ast_strlen_zero(n))
    00631       return 0;
    00632    for (x=0;n[x];x++)
    00633       if (!strchr("0123456789*#+", n[x]))
    00634          return 0;
    00635    return 1;
    00636 }
    00637
    00638 /*! \brief parse string for caller id information
    00639    \return returns -1 on failure, otherwise 0
    00640 */
    00641 int ast_callerid_parse(char *instr, char **name, char **location)
    00642 {
    00643    char *ns, *ne;
    00644    char *ls, *le;
    00645    char tmp[256];
    00646    /* Try for "name" <location> format or
    00647       name <location> format */
    00648    if ((ls = strchr(instr, '<')) && (le = strchr(ls, '>'))) {
    00649       /* Found the location */
    00650       *le = '\0';
    00651       *ls = '\0';
    00652       *location = ls + 1;
    00653       if ((ns = strchr(instr, '\"')) && (ne = strchr(ns + 1, '\"'))) {
    00654          /* Get name out of quotes */
    00655          *ns = '\0';
    00656          *ne = '\0';
    00657          *name = ns + 1;
    00658          return 0;
    00659       } else {
    00660          /* Just trim off any trailing spaces */
    00661          *name = instr;
    00662          while(!ast_strlen_zero(instr) && (instr[strlen(instr) - 1] < 33))
    00663             instr[strlen(instr) - 1] = '\0';
    00664          /* And leading spaces */
    00665          *name = ast_skip_blanks(*name);
    00666          return 0;
    00667       }
    00668    } else {
    00669       ast_copy_string(tmp, instr, sizeof(tmp));
    00670       ast_shrink_phone_number(tmp);
    00671       if (ast_isphonenumber(tmp)) {
    00672          /* Assume it's just a location */
    00673          *name = NULL;
    00674          *location = instr;
    00675       } else {
    00676          /* Assume it's just a name.  Make sure it's not quoted though */
    00677          *name = instr;
    00678          while(*(*name) && ((*(*name) < 33) || (*(*name) == '\"'))) (*name)++;
    00679          ne = *name + strlen(*name) - 1;
    00680          while((ne > *name) && ((*ne < 33) || (*ne == '\"'))) { *ne = '\0'; ne--; }
    00681          *location = NULL;
    00682       }
    00683       return 0;
    00684    }
    00685    return -1;
    00686 }
    00687
    00688 static int __ast_callerid_generate(unsigned char *buf, char *name, char *number, int callwaiting, int codec)
    00689 {
    00690    if (ast_strlen_zero(name))
    00691       name = NULL;
    00692    if (ast_strlen_zero(number))
    00693       number = NULL;
    00694    return callerid_generate(buf, number, name, 0, callwaiting, codec);
    00695 }
    00696
    00697 int ast_callerid_generate(unsigned char *buf, char *name, char *number, int codec)
    00698 {
    00699    return __ast_callerid_generate(buf, name, number, 0, codec);
    00700 }
    00701
    00702 int ast_callerid_callwaiting_generate(unsigned char *buf, char *name, char *number, int codec)
    00703 {
    00704    return __ast_callerid_generate(buf, name, number, 1, codec);
    00705 }
    00706
    00707 char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
    00708 {
    00709    if (!unknown)
    00710       unknown = "<unknown>";
    00711    if (name && num)
    00712       snprintf(buf, bufsiz, "\"%s\" <%s>", name, num);
    00713    else if (name)
    00714       ast_copy_string(buf, name, bufsiz);
    00715    else if (num)
    00716       ast_copy_string(buf, num, bufsiz);
    00717    else
    00718       ast_copy_string(buf, unknown, bufsiz);
    00719    return buf;
    00720 }
    00721
    00722 int ast_callerid_split(const char *buf, char *name, int namelen, char *num, int numlen)
    00723 {
    00724    char *tmp;
    00725    char *l = NULL, *n = NULL;
    00726    tmp = ast_strdupa(buf);
    00727    if (!tmp) {
    00728       name[0] = '\0';
    00729       num[0] = '\0';
    00730       return -1;
    00731    }
    00732    ast_callerid_parse(tmp, &n, &l);
    00733    if (n)
    00734       ast_copy_string(name, n, namelen);
    00735    else
    00736       name[0] = '\0';
    00737    if (l) {
    00738       ast_shrink_phone_number(l);
    00739       ast_copy_string(num, l, numlen);
    00740    } else
    00741       num[0] = '\0';
    00742    return 0;
    00743 }
    00744
    00745 static struct {
    00746    int val;
    00747    char *name;
    00748    char *description;
    00749 } pres_types[] = {
    00750    {  AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened", "Presentation Allowed, Not Screened"},
    00751    {  AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen", "Presentation Allowed, Passed Screen"},
    00752    {  AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen", "Presentation Allowed, Failed Screen"},
    00753    {  AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed", "Presentation Allowed, Network Number"},
    00754    {  AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "prohib_not_screened", "Presentation Prohibited, Not Screened"},
    00755    {  AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen", "Presentation Prohibited, Passed Screen"},
    00756    {  AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen", "Presentation Prohibited, Failed Screen"},
    00757    {  AST_PRES_PROHIB_NETWORK_NUMBER, "prohib", "Presentation Prohibited, Network Number"},
    00758    {  AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable", "Number Unavailable"},
    00759 };
    00760
    00761 /*! \brief Convert caller ID text code to value
    00762    used in config file parsing
    00763    \param data text string
    00764    \return value AST_PRES_ from callerid.h
    00765 */
    00766 int ast_parse_caller_presentation(const char *data)
    00767 {
    00768    int i;
    00769
    00770    for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
    00771       if (!strcasecmp(pres_types[i].name, data))
    00772          return pres_types[i].val;
    00773    }
    00774
    00775    return -1;
    00776 }
    00777
    00778 /*! \brief Convert caller ID pres value to explanatory string
    00779    \param data value (see callerid.h AST_PRES_ )
    00780    \return string for human presentation
    00781 */
    00782 const char *ast_describe_caller_presentation(int data)
    00783 {
    00784    int i;
    00785
    00786    for (i = 0; i < ((sizeof(pres_types) / sizeof(pres_types[0]))); i++) {
    00787       if (pres_types[i].val == data)
    00788          return pres_types[i].description;
    00789    }
    00790
    00791    return "unknown";
    00792 }