Mon Jun 27 16:50:53 2011

Asterisk developer's documentation


func_callerid.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999-2010, Digium, Inc.
00005  *
00006  * See http://www.asterisk.org for more information about
00007  * the Asterisk project. Please do not directly contact
00008  * any of the maintainers of this project for assistance;
00009  * the project provides a web site, mailing lists and IRC
00010  * channels for your use.
00011  *
00012  * This program is free software, distributed under the terms of
00013  * the GNU General Public License Version 2. See the LICENSE file
00014  * at the top of the source tree.
00015  */
00016 
00017 /*! \file
00018  *
00019  * \brief Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)
00020  *
00021  * \ingroup functions
00022  *
00023  * See Also:
00024  * \arg \ref AstCREDITS
00025  */
00026 
00027 #include "asterisk.h"
00028 
00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 276393 $")
00030 
00031 #include "asterisk/module.h"
00032 #include "asterisk/channel.h"
00033 #include "asterisk/pbx.h"
00034 #include "asterisk/utils.h"
00035 #include "asterisk/app.h"
00036 #include "asterisk/callerid.h"
00037 
00038 /*
00039  * Do not document the CALLERID(pres) datatype.
00040  * The name and number now have their own presentation value.  The pres
00041  * option will simply live on as a historical relic with as best
00042  * as can be managed backward compatible meaning.
00043  *
00044  * Do not document the CALLERID(ton) datatype.
00045  * It is an alias for num-plan.
00046  *
00047  * Do not document the CALLERID(ANI-subaddr-...) datatype.
00048  * This is not used.
00049  *
00050  * Do not document the CONNECTEDLINE(source) datatype.
00051  * It has turned out to not be needed.  The source value is really
00052  * only useful as a possible tracing aid.
00053  *
00054  * Do not document the CONNECTEDLINE(pres) datatype.
00055  * The name and number now have their own presentation value.  The pres
00056  * option will simply live on as a historical relic with as best
00057  * as can be managed backward compatible meaning.
00058  *
00059  * Do not document the CONNECTEDLINE(ton) datatype.
00060  * It is an alias for num-plan.
00061  *
00062  * Do not document the REDIRECTING(pres) datatype.
00063  * It has turned out that the from-pres and to-pres values must be kept
00064  * separate.  They represent two different parties and there is a case when
00065  * they are active at the same time.  The plain pres option will simply
00066  * live on as a historical relic.
00067  *
00068  * Do not document the REDIRECTING(from-pres) or REDIRECTING(to-pres) datatypes.
00069  * The name and number now have their own presentation value.  The from-pres
00070  * and to-pres options will simply live on as a historical relic with as best
00071  * as can be managed backward compatible meaning.
00072  *
00073  * Do not document the REDIRECTING(from-ton) or REDIRECTING(to-ton) datatypes.
00074  * They are aliases for from-num-plan and to-num-plan respectively.
00075  */
00076 /*** DOCUMENTATION
00077    <function name="CALLERID" language="en_US">
00078       <synopsis>
00079          Gets or sets Caller*ID data on the channel.
00080       </synopsis>
00081       <syntax>
00082          <parameter name="datatype" required="true">
00083             <para>The allowable datatypes are:</para>
00084             <enumlist>
00085                <enum name = "all" />
00086                <enum name = "name" />
00087                <enum name = "name-valid" />
00088                <enum name = "name-charset" />
00089                <enum name = "name-pres" />
00090                <enum name = "num" />
00091                <enum name = "num-valid" />
00092                <enum name = "num-plan" />
00093                <enum name = "num-pres" />
00094                <enum name = "subaddr" />
00095                <enum name = "subaddr-valid" />
00096                <enum name = "subaddr-type" />
00097                <enum name = "subaddr-odd" />
00098                <enum name = "tag" />
00099                <enum name = "ANI-all" />
00100                <enum name = "ANI-name" />
00101                <enum name = "ANI-name-valid" />
00102                <enum name = "ANI-name-charset" />
00103                <enum name = "ANI-name-pres" />
00104                <enum name = "ANI-num" />
00105                <enum name = "ANI-num-valid" />
00106                <enum name = "ANI-num-plan" />
00107                <enum name = "ANI-num-pres" />
00108                <enum name = "ANI-tag" />
00109                <enum name = "RDNIS" />
00110                <enum name = "DNID" />
00111                <enum name = "dnid-num-plan" />
00112                <enum name = "dnid-subaddr" />
00113                <enum name = "dnid-subaddr-valid" />
00114                <enum name = "dnid-subaddr-type" />
00115                <enum name = "dnid-subaddr-odd" />
00116             </enumlist>
00117          </parameter>
00118          <parameter name="CID">
00119             <para>Optional Caller*ID</para>
00120          </parameter>
00121       </syntax>
00122       <description>
00123          <para>Gets or sets Caller*ID data on the channel. Uses channel callerid by
00124          default or optional callerid, if specified.</para>
00125          <para>The allowable values for the <replaceable>name-charset</replaceable>
00126          field are the following:</para>
00127          <enumlist>
00128             <enum name = "unknown"><para>Unknown</para></enum>
00129             <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
00130             <enum name = "withdrawn"><para>Withdrawn</para></enum>
00131             <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
00132             <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
00133             <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
00134             <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
00135             <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
00136             <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
00137             <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
00138          </enumlist>
00139       </description>
00140    </function>
00141    <function name="CALLERPRES" language="en_US">
00142       <synopsis>
00143          Gets or sets Caller*ID presentation on the channel.
00144       </synopsis>
00145       <syntax />
00146       <description>
00147          <para>Gets or sets Caller*ID presentation on the channel.
00148          This function is deprecated in favor of CALLERID(num-pres)
00149          and CALLERID(name-pres).
00150          The following values are valid:</para>
00151          <enumlist>
00152             <enum name="allowed_not_screened">
00153                <para>Presentation Allowed, Not Screened.</para>
00154             </enum>
00155             <enum name="allowed_passed_screen">
00156                <para>Presentation Allowed, Passed Screen.</para>
00157             </enum>
00158             <enum name="allowed_failed_screen">
00159                <para>Presentation Allowed, Failed Screen.</para>
00160             </enum>
00161             <enum name="allowed">
00162                <para>Presentation Allowed, Network Number.</para>
00163             </enum>
00164             <enum name="prohib_not_screened">
00165                <para>Presentation Prohibited, Not Screened.</para>
00166             </enum>
00167             <enum name="prohib_passed_screen">
00168                <para>Presentation Prohibited, Passed Screen.</para>
00169             </enum>
00170             <enum name="prohib_failed_screen">
00171                <para>Presentation Prohibited, Failed Screen.</para>
00172             </enum>
00173             <enum name="prohib">
00174                <para>Presentation Prohibited, Network Number.</para>
00175             </enum>
00176             <enum name="unavailable">
00177                <para>Number Unavailable.</para>
00178             </enum>
00179          </enumlist>
00180       </description>
00181    </function>
00182    <function name="CONNECTEDLINE" language="en_US">
00183       <synopsis>
00184          Gets or sets Connected Line data on the channel.
00185       </synopsis>
00186       <syntax>
00187          <parameter name="datatype" required="true">
00188             <para>The allowable datatypes are:</para>
00189             <enumlist>
00190                <enum name = "all" />
00191                <enum name = "name" />
00192                <enum name = "name-valid" />
00193                <enum name = "name-charset" />
00194                <enum name = "name-pres" />
00195                <enum name = "num" />
00196                <enum name = "num-valid" />
00197                <enum name = "num-plan" />
00198                <enum name = "num-pres" />
00199                <enum name = "subaddr" />
00200                <enum name = "subaddr-valid" />
00201                <enum name = "subaddr-type" />
00202                <enum name = "subaddr-odd" />
00203                <enum name = "tag" />
00204             </enumlist>
00205          </parameter>
00206          <parameter name="i">
00207             <para>If set, this will prevent the channel from sending out protocol
00208             messages because of the value being set</para>
00209          </parameter>
00210       </syntax>
00211       <description>
00212          <para>Gets or sets Connected Line data on the channel.</para>
00213          <para>The allowable values for the <replaceable>name-charset</replaceable>
00214          field are the following:</para>
00215          <enumlist>
00216             <enum name = "unknown"><para>Unknown</para></enum>
00217             <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
00218             <enum name = "withdrawn"><para>Withdrawn</para></enum>
00219             <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
00220             <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
00221             <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
00222             <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
00223             <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
00224             <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
00225             <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
00226          </enumlist>
00227       </description>
00228    </function>
00229    <function name="REDIRECTING" language="en_US">
00230       <synopsis>
00231          Gets or sets Redirecting data on the channel.
00232       </synopsis>
00233       <syntax>
00234          <parameter name="datatype" required="true">
00235             <para>The allowable datatypes are:</para>
00236             <enumlist>
00237                <enum name = "from-all" />
00238                <enum name = "from-name" />
00239                <enum name = "from-name-valid" />
00240                <enum name = "from-name-charset" />
00241                <enum name = "from-name-pres" />
00242                <enum name = "from-num" />
00243                <enum name = "from-num-valid" />
00244                <enum name = "from-num-plan" />
00245                <enum name = "from-num-pres" />
00246                <enum name = "from-subaddr" />
00247                <enum name = "from-subaddr-valid" />
00248                <enum name = "from-subaddr-type" />
00249                <enum name = "from-subaddr-odd" />
00250                <enum name = "from-tag" />
00251                <enum name = "to-all" />
00252                <enum name = "to-name" />
00253                <enum name = "to-name-valid" />
00254                <enum name = "to-name-charset" />
00255                <enum name = "to-name-pres" />
00256                <enum name = "to-num" />
00257                <enum name = "to-num-valid" />
00258                <enum name = "to-num-plan" />
00259                <enum name = "to-num-pres" />
00260                <enum name = "to-subaddr" />
00261                <enum name = "to-subaddr-valid" />
00262                <enum name = "to-subaddr-type" />
00263                <enum name = "to-subaddr-odd" />
00264                <enum name = "to-tag" />
00265                <enum name = "reason" />
00266                <enum name = "count" />
00267             </enumlist>
00268          </parameter>
00269          <parameter name="i">
00270             <para>If set, this will prevent the channel from sending out protocol
00271             messages because of the value being set</para>
00272          </parameter>
00273       </syntax>
00274       <description>
00275          <para>Gets or sets Redirecting data on the channel.</para>
00276          <para>The allowable values for the <replaceable>reason</replaceable>
00277          field are the following:</para>
00278          <enumlist>
00279             <enum name = "unknown"><para>Unknown</para></enum>
00280             <enum name = "cfb"><para>Call Forwarding Busy</para></enum>
00281             <enum name = "cfnr"><para>Call Forwarding No Reply</para></enum>
00282             <enum name = "unavailable"><para>Callee is Unavailable</para></enum>
00283             <enum name = "time_of_day"><para>Time of Day</para></enum>
00284             <enum name = "dnd"><para>Do Not Disturb</para></enum>
00285             <enum name = "deflection"><para>Call Deflection</para></enum>
00286             <enum name = "follow_me"><para>Follow Me</para></enum>
00287             <enum name = "out_of_order"><para>Called DTE Out-Of-Order</para></enum>
00288             <enum name = "away"><para>Callee is Away</para></enum>
00289             <enum name = "cf_dte"><para>Call Forwarding By The Called DTE</para></enum>
00290             <enum name = "cfu"><para>Call Forwarding Unconditional</para></enum>
00291          </enumlist>
00292          <para>The allowable values for the <replaceable>xxx-name-charset</replaceable>
00293          field are the following:</para>
00294          <enumlist>
00295             <enum name = "unknown"><para>Unknown</para></enum>
00296             <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
00297             <enum name = "withdrawn"><para>Withdrawn</para></enum>
00298             <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
00299             <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
00300             <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
00301             <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
00302             <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
00303             <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
00304             <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
00305          </enumlist>
00306       </description>
00307    </function>
00308  ***/
00309 
00310 enum ID_FIELD_STATUS {
00311    ID_FIELD_VALID,
00312    ID_FIELD_INVALID,
00313    ID_FIELD_UNKNOWN
00314 };
00315 
00316 AST_DEFINE_APP_ARGS_TYPE(ast_party_func_args,
00317    AST_APP_ARG(member); /*!< Member name */
00318    AST_APP_ARG(opts);      /*!< Options token */
00319    AST_APP_ARG(other);     /*!< Any remining unused arguments */
00320    );
00321 
00322 AST_DEFINE_APP_ARGS_TYPE(ast_party_members,
00323    AST_APP_ARG(subnames[10]); /*!< Option member subnames */
00324    );
00325 
00326 enum CONNECTED_LINE_OPT_FLAGS {
00327    CONNECTED_LINE_OPT_INHIBIT = (1 << 0),
00328 };
00329 enum CONNECTED_LINE_OPT_ARGS {
00330    CONNECTED_LINE_OPT_DUMMY,  /*!< Delete this if CONNECTED_LINE ever gets an option with parameters. */
00331 
00332    /*! \note This entry _MUST_ be the last one in the enum */
00333    CONNECTED_LINE_OPT_ARG_ARRAY_SIZE
00334 };
00335 
00336 AST_APP_OPTIONS(connectedline_opts, BEGIN_OPTIONS
00337    AST_APP_OPTION('i', CONNECTED_LINE_OPT_INHIBIT),
00338 END_OPTIONS);
00339 
00340 enum REDIRECTING_OPT_FLAGS {
00341    REDIRECTING_OPT_INHIBIT = (1 << 0),
00342 };
00343 enum REDIRECTING_OPT_ARGS {
00344    REDIRECTING_OPT_DUMMY,  /*!< Delete this if REDIRECTING ever gets an option with parameters. */
00345 
00346    /*! \note This entry _MUST_ be the last one in the enum */
00347    REDIRECTING_OPT_ARG_ARRAY_SIZE
00348 };
00349 
00350 AST_APP_OPTIONS(redirecting_opts, BEGIN_OPTIONS
00351    AST_APP_OPTION('i', REDIRECTING_OPT_INHIBIT),
00352 END_OPTIONS);
00353 
00354 /*!
00355  * \internal
00356  * \brief Read values from the party name struct.
00357  * \since 1.8
00358  *
00359  * \param buf Buffer to fill with read value.
00360  * \param len Length of the buffer.
00361  * \param argc Number of party member subnames.
00362  * \param argv Party member subnames given.
00363  * \param name Party name to get values from.
00364  *
00365  * \retval ID_FIELD_VALID on success.
00366  * \retval ID_FIELD_UNKNOWN on unknown field name.
00367  */
00368 static enum ID_FIELD_STATUS party_name_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_name *name)
00369 {
00370    enum ID_FIELD_STATUS status;
00371 
00372    status = ID_FIELD_VALID;
00373 
00374    if (argc == 0) {
00375       /* We want the name string */
00376       if (name->valid && name->str) {
00377          ast_copy_string(buf, name->str, len);
00378       }
00379    } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
00380       snprintf(buf, len, "%d", name->valid);
00381    } else if (argc == 1 && !strcasecmp("charset", argv[0])) {
00382       ast_copy_string(buf, ast_party_name_charset_str(name->char_set), len);
00383    } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
00384       /* Accept pres[entation] */
00385       ast_copy_string(buf, ast_named_caller_presentation(name->presentation), len);
00386    } else {
00387       status = ID_FIELD_UNKNOWN;
00388    }
00389 
00390    return status;
00391 }
00392 
00393 /*!
00394  * \internal
00395  * \brief Read values from the party number struct.
00396  * \since 1.8
00397  *
00398  * \param buf Buffer to fill with read value.
00399  * \param len Length of the buffer.
00400  * \param argc Number of party member subnames.
00401  * \param argv Party member subnames given.
00402  * \param number Party number to get values from.
00403  *
00404  * \retval ID_FIELD_VALID on success.
00405  * \retval ID_FIELD_UNKNOWN on unknown field name.
00406  */
00407 static enum ID_FIELD_STATUS party_number_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_number *number)
00408 {
00409    enum ID_FIELD_STATUS status;
00410 
00411    status = ID_FIELD_VALID;
00412 
00413    if (argc == 0) {
00414       /* We want the number string */
00415       if (number->valid && number->str) {
00416          ast_copy_string(buf, number->str, len);
00417       }
00418    } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
00419       snprintf(buf, len, "%d", number->valid);
00420    } else if (argc == 1 && !strcasecmp("plan", argv[0])) {
00421       snprintf(buf, len, "%d", number->plan);
00422    } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
00423       /* Accept pres[entation] */
00424       ast_copy_string(buf, ast_named_caller_presentation(number->presentation), len);
00425    } else {
00426       status = ID_FIELD_UNKNOWN;
00427    }
00428 
00429    return status;
00430 }
00431 
00432 /*!
00433  * \internal
00434  * \brief Read values from the party subaddress struct.
00435  * \since 1.8
00436  *
00437  * \param buf Buffer to fill with read value.
00438  * \param len Length of the buffer.
00439  * \param argc Number of party member subnames.
00440  * \param argv Party member subnames given.
00441  * \param subaddress Party subaddress to get values from.
00442  *
00443  * \retval ID_FIELD_VALID on success.
00444  * \retval ID_FIELD_UNKNOWN on unknown field name.
00445  */
00446 static enum ID_FIELD_STATUS party_subaddress_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_subaddress *subaddress)
00447 {
00448    enum ID_FIELD_STATUS status;
00449 
00450    status = ID_FIELD_VALID;
00451 
00452    if (argc == 0) {
00453       /* We want the subaddress string */
00454       if (subaddress->str) {
00455          ast_copy_string(buf, subaddress->str, len);
00456       }
00457    } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
00458       snprintf(buf, len, "%d", subaddress->valid);
00459    } else if (argc == 1 && !strcasecmp("type", argv[0])) {
00460       snprintf(buf, len, "%d", subaddress->type);
00461    } else if (argc == 1 && !strcasecmp("odd", argv[0])) {
00462       snprintf(buf, len, "%d", subaddress->odd_even_indicator);
00463    } else {
00464       status = ID_FIELD_UNKNOWN;
00465    }
00466 
00467    return status;
00468 }
00469 
00470 /*!
00471  * \internal
00472  * \brief Read values from the party id struct.
00473  * \since 1.8
00474  *
00475  * \param buf Buffer to fill with read value.
00476  * \param len Length of the buffer.
00477  * \param argc Number of party member subnames.
00478  * \param argv Party member subnames given.
00479  * \param id Party id to get values from.
00480  *
00481  * \retval ID_FIELD_VALID on success.
00482  * \retval ID_FIELD_UNKNOWN on unknown field name.
00483  */
00484 static enum ID_FIELD_STATUS party_id_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_id *id)
00485 {
00486    enum ID_FIELD_STATUS status;
00487 
00488    if (argc == 0) {
00489       /* Must have at least one subname. */
00490       return ID_FIELD_UNKNOWN;
00491    }
00492 
00493    status = ID_FIELD_VALID;
00494 
00495    if (argc == 1 && !strcasecmp("all", argv[0])) {
00496       snprintf(buf, len, "\"%s\" <%s>",
00497           S_COR(id->name.valid, id->name.str, ""),
00498           S_COR(id->number.valid, id->number.str, ""));
00499    } else if (!strcasecmp("name", argv[0])) {
00500       status = party_name_read(buf, len, argc - 1, argv + 1, &id->name);
00501    } else if (!strncasecmp("num", argv[0], 3)) {
00502       /* Accept num[ber] */
00503       status = party_number_read(buf, len, argc - 1, argv + 1, &id->number);
00504    } else if (!strncasecmp("subaddr", argv[0], 7)) {
00505       /* Accept subaddr[ess] */
00506       status = party_subaddress_read(buf, len, argc - 1, argv + 1, &id->subaddress);
00507    } else if (argc == 1 && !strcasecmp("tag", argv[0])) {
00508       if (id->tag) {
00509          ast_copy_string(buf, id->tag, len);
00510       }
00511    } else if (argc == 1 && !strcasecmp("ton", argv[0])) {
00512       /* ton is an alias for num-plan */
00513       snprintf(buf, len, "%d", id->number.plan);
00514    } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
00515       /*
00516        * Accept pres[entation]
00517        * This is the combined name/number presentation.
00518        */
00519       ast_copy_string(buf,
00520          ast_named_caller_presentation(ast_party_id_presentation(id)), len);
00521    } else {
00522       status = ID_FIELD_UNKNOWN;
00523    }
00524 
00525    return status;
00526 }
00527 
00528 /*!
00529  * \internal
00530  * \brief Write new values to the party name struct
00531  * \since 1.8
00532  *
00533  * \param name Party name struct to write values
00534  * \param argc Number of party member subnames.
00535  * \param argv Party member subnames given.
00536  * \param value Value to assign to the party name.
00537  *
00538  * \retval ID_FIELD_VALID on success.
00539  * \retval ID_FIELD_INVALID on error with field value.
00540  * \retval ID_FIELD_UNKNOWN on unknown field name.
00541  */
00542 static enum ID_FIELD_STATUS party_name_write(struct ast_party_name *name, int argc, char *argv[], const char *value)
00543 {
00544    char *val;
00545    enum ID_FIELD_STATUS status;
00546 
00547    status = ID_FIELD_VALID;
00548 
00549    if (argc == 0) {
00550       /* We are setting the name string */
00551       name->valid = 1;
00552       name->str = ast_strdup(value);
00553       ast_trim_blanks(name->str);
00554    } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
00555       name->valid = atoi(value) ? 1 : 0;
00556    } else if (argc == 1 && !strcasecmp("charset", argv[0])) {
00557       int char_set;
00558 
00559       val = ast_strdupa(value);
00560       ast_trim_blanks(val);
00561 
00562       if (('0' <= val[0]) && (val[0] <= '9')) {
00563          char_set = atoi(val);
00564       } else {
00565          char_set = ast_party_name_charset_parse(val);
00566       }
00567 
00568       if (char_set < 0) {
00569          ast_log(LOG_ERROR,
00570             "Unknown name char-set '%s', value unchanged\n", val);
00571          status = ID_FIELD_INVALID;
00572       } else {
00573          name->char_set = char_set;
00574       }
00575    } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
00576       int pres;
00577 
00578       /* Accept pres[entation] */
00579       val = ast_strdupa(value);
00580       ast_trim_blanks(val);
00581 
00582       if (('0' <= val[0]) && (val[0] <= '9')) {
00583          pres = atoi(val);
00584       } else {
00585          pres = ast_parse_caller_presentation(val);
00586       }
00587 
00588       if (pres < 0) {
00589          ast_log(LOG_ERROR,
00590             "Unknown name presentation '%s', value unchanged\n", val);
00591          status = ID_FIELD_INVALID;
00592       } else {
00593          name->presentation = pres;
00594       }
00595    } else {
00596       status = ID_FIELD_UNKNOWN;
00597    }
00598 
00599    return status;
00600 }
00601 
00602 /*!
00603  * \internal
00604  * \brief Write new values to the party number struct
00605  * \since 1.8
00606  *
00607  * \param number Party number struct to write values
00608  * \param argc Number of party member subnames.
00609  * \param argv Party member subnames given.
00610  * \param value Value to assign to the party number.
00611  *
00612  * \retval ID_FIELD_VALID on success.
00613  * \retval ID_FIELD_INVALID on error with field value.
00614  * \retval ID_FIELD_UNKNOWN on unknown field name.
00615  */
00616 static enum ID_FIELD_STATUS party_number_write(struct ast_party_number *number, int argc, char *argv[], const char *value)
00617 {
00618    char *val;
00619    enum ID_FIELD_STATUS status;
00620 
00621    status = ID_FIELD_VALID;
00622 
00623    if (argc == 0) {
00624       /* We are setting the number string */
00625       number->valid = 1;
00626       number->str = ast_strdup(value);
00627       ast_trim_blanks(number->str);
00628    } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
00629       number->valid = atoi(value) ? 1 : 0;
00630    } else if (argc == 1 && !strcasecmp("plan", argv[0])) {
00631       val = ast_strdupa(value);
00632       ast_trim_blanks(val);
00633 
00634       if (('0' <= val[0]) && (val[0] <= '9')) {
00635          number->plan = atoi(val);
00636       } else {
00637          ast_log(LOG_ERROR,
00638             "Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
00639          status = ID_FIELD_INVALID;
00640       }
00641    } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
00642       int pres;
00643 
00644       /* Accept pres[entation] */
00645       val = ast_strdupa(value);
00646       ast_trim_blanks(val);
00647 
00648       if (('0' <= val[0]) && (val[0] <= '9')) {
00649          pres = atoi(val);
00650       } else {
00651          pres = ast_parse_caller_presentation(val);
00652       }
00653 
00654       if (pres < 0) {
00655          ast_log(LOG_ERROR,
00656             "Unknown number presentation '%s', value unchanged\n", val);
00657          status = ID_FIELD_INVALID;
00658       } else {
00659          number->presentation = pres;
00660       }
00661    } else {
00662       status = ID_FIELD_UNKNOWN;
00663    }
00664 
00665    return status;
00666 }
00667 
00668 /*!
00669  * \internal
00670  * \brief Write new values to the party subaddress struct
00671  * \since 1.8
00672  *
00673  * \param subaddress Party subaddress struct to write values
00674  * \param argc Number of party member subnames.
00675  * \param argv Party member subnames given.
00676  * \param value Value to assign to the party subaddress.
00677  *
00678  * \retval ID_FIELD_VALID on success.
00679  * \retval ID_FIELD_INVALID on error with field value.
00680  * \retval ID_FIELD_UNKNOWN on unknown field name.
00681  */
00682 static enum ID_FIELD_STATUS party_subaddress_write(struct ast_party_subaddress *subaddress, int argc, char *argv[], const char *value)
00683 {
00684    enum ID_FIELD_STATUS status;
00685 
00686    status = ID_FIELD_VALID;
00687 
00688    if (argc == 0) {
00689       /* We are setting the subaddress string */
00690       subaddress->str = ast_strdup(value);
00691       ast_trim_blanks(subaddress->str);
00692    } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
00693       subaddress->valid = atoi(value) ? 1 : 0;
00694    } else if (argc == 1 && !strcasecmp("type", argv[0])) {
00695       subaddress->type = atoi(value) ? 2 : 0;
00696    } else if (argc == 1 && !strcasecmp("odd", argv[0])) {
00697       subaddress->odd_even_indicator = atoi(value) ? 1 : 0;
00698    } else {
00699       status = ID_FIELD_UNKNOWN;
00700    }
00701 
00702    return status;
00703 }
00704 
00705 /*!
00706  * \internal
00707  * \brief Write new values to the party id struct
00708  * \since 1.8
00709  *
00710  * \param id Party ID struct to write values
00711  * \param argc Number of party member subnames.
00712  * \param argv Party member subnames given.
00713  * \param value Value to assign to the party id.
00714  *
00715  * \retval ID_FIELD_VALID on success.
00716  * \retval ID_FIELD_INVALID on error with field value.
00717  * \retval ID_FIELD_UNKNOWN on unknown field name.
00718  */
00719 static enum ID_FIELD_STATUS party_id_write(struct ast_party_id *id, int argc, char *argv[], const char *value)
00720 {
00721    char *val;
00722    enum ID_FIELD_STATUS status;
00723 
00724    if (argc == 0) {
00725       /* Must have at least one subname. */
00726       return ID_FIELD_UNKNOWN;
00727    }
00728 
00729    status = ID_FIELD_VALID;
00730 
00731    if (argc == 1 && !strcasecmp("all", argv[0])) {
00732       char name[256];
00733       char num[256];
00734 
00735       ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
00736       id->name.valid = 1;
00737       id->name.str = ast_strdup(name);
00738       if (!id->name.str) {
00739          return ID_FIELD_INVALID;
00740       }
00741       id->number.valid = 1;
00742       id->number.str = ast_strdup(num);
00743       if (!id->number.str) {
00744          return ID_FIELD_INVALID;
00745       }
00746    } else if (!strcasecmp("name", argv[0])) {
00747       status = party_name_write(&id->name, argc - 1, argv + 1, value);
00748    } else if (!strncasecmp("num", argv[0], 3)) {
00749       /* Accept num[ber] */
00750       status = party_number_write(&id->number, argc - 1, argv + 1, value);
00751    } else if (!strncasecmp("subaddr", argv[0], 7)) {
00752       /* Accept subaddr[ess] */
00753       status = party_subaddress_write(&id->subaddress, argc - 1, argv + 1, value);
00754    } else if (argc == 1 && !strcasecmp("tag", argv[0])) {
00755       id->tag = ast_strdup(value);
00756       ast_trim_blanks(id->tag);
00757    } else if (argc == 1 && !strcasecmp("ton", argv[0])) {
00758       /* ton is an alias for num-plan */
00759       argv[0] = "plan";
00760       status = party_number_write(&id->number, argc, argv, value);
00761    } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
00762       int pres;
00763 
00764       /*
00765        * Accept pres[entation]
00766        * This is the combined name/number presentation.
00767        */
00768       val = ast_strdupa(value);
00769       ast_trim_blanks(val);
00770 
00771       if (('0' <= val[0]) && (val[0] <= '9')) {
00772          pres = atoi(val);
00773       } else {
00774          pres = ast_parse_caller_presentation(val);
00775       }
00776 
00777       if (pres < 0) {
00778          ast_log(LOG_ERROR,
00779             "Unknown combined presentation '%s', value unchanged\n", val);
00780          status = ID_FIELD_INVALID;
00781       } else {
00782          id->name.presentation = pres;
00783          id->number.presentation = pres;
00784       }
00785    } else {
00786       status = ID_FIELD_UNKNOWN;
00787    }
00788 
00789    return status;
00790 }
00791 
00792 /*! TRUE if we have already notified about CALLERPRES being deprecated. */
00793 static int callerpres_deprecate_notify;
00794 
00795 /*!
00796  * \internal
00797  * \brief Read values from the caller-id presentation information struct.
00798  *
00799  * \param chan Asterisk channel to read
00800  * \param cmd Not used
00801  * \param data Caller-id presentation function datatype string
00802  * \param buf Buffer to fill with read value.
00803  * \param len Length of the buffer
00804  *
00805  * \retval 0 on success.
00806  * \retval -1 on error.
00807  */
00808 static int callerpres_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00809 {
00810    if (!callerpres_deprecate_notify) {
00811       callerpres_deprecate_notify = 1;
00812       ast_log(LOG_WARNING, "CALLERPRES is deprecated."
00813          "  Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
00814    }
00815    ast_copy_string(buf,
00816       ast_named_caller_presentation(ast_party_id_presentation(&chan->caller.id)), len);
00817    return 0;
00818 }
00819 
00820 /*!
00821  * \internal
00822  * \brief Write new values to the caller-id presentation information struct.
00823  *
00824  * \param chan Asterisk channel to update
00825  * \param cmd Not used
00826  * \param data Caller-id presentation function datatype string
00827  * \param value Value to assign to the caller-id presentation information struct.
00828  *
00829  * \retval 0 on success.
00830  * \retval -1 on error.
00831  */
00832 static int callerpres_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00833 {
00834    int pres;
00835 
00836    if (!callerpres_deprecate_notify) {
00837       callerpres_deprecate_notify = 1;
00838       ast_log(LOG_WARNING, "CALLERPRES is deprecated."
00839          "  Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
00840    }
00841 
00842    pres = ast_parse_caller_presentation(value);
00843    if (pres < 0) {
00844       ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show function CALLERPRES')\n", value);
00845    } else {
00846       chan->caller.id.name.presentation = pres;
00847       chan->caller.id.number.presentation = pres;
00848    }
00849    return 0;
00850 }
00851 
00852 /*!
00853  * \internal
00854  * \brief Read values from the caller-id information struct.
00855  *
00856  * \param chan Asterisk channel to read
00857  * \param cmd Not used
00858  * \param data Caller-id function datatype string
00859  * \param buf Buffer to fill with read value.
00860  * \param len Length of the buffer
00861  *
00862  * \retval 0 on success.
00863  * \retval -1 on error.
00864  */
00865 static int callerid_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00866 {
00867    enum ID_FIELD_STATUS status;
00868    char *parms;
00869    struct ast_party_members member;
00870    AST_DECLARE_APP_ARGS(args,
00871       AST_APP_ARG(member); /*!< Member name */
00872       AST_APP_ARG(cid);    /*!< Optional caller id to parse instead of from the channel. */
00873       );
00874 
00875    /* Ensure that the buffer is empty */
00876    *buf = 0;
00877 
00878    if (!chan) {
00879       return -1;
00880    }
00881 
00882    parms = ast_strdupa(data);
00883    AST_STANDARD_APP_ARGS(args, parms);
00884    if (args.argc == 0) {
00885       /* Must have at least one argument. */
00886       return -1;
00887    }
00888 
00889    AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
00890    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
00891       /* Too few or too many subnames */
00892       return -1;
00893    }
00894 
00895    if (args.argc == 2) {
00896       char name[80];
00897       char num[80];
00898 
00899       ast_callerid_split(args.cid, name, sizeof(name), num, sizeof(num));
00900 
00901       if (member.argc == 1 && !strcasecmp("all", member.argv[0])) {
00902          snprintf(buf, len, "\"%s\" <%s>", name, num);
00903       } else if (member.argc == 1 && !strcasecmp("name", member.argv[0])) {
00904          ast_copy_string(buf, name, len);
00905       } else if (member.argc == 1 && !strncasecmp("num", member.argv[0], 3)) {
00906          /* Accept num[ber] */
00907          ast_copy_string(buf, num, len);
00908       } else {
00909          ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
00910       }
00911    } else {
00912       ast_channel_lock(chan);
00913 
00914       if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
00915          if (chan->redirecting.from.number.valid
00916             && chan->redirecting.from.number.str) {
00917             ast_copy_string(buf, chan->redirecting.from.number.str, len);
00918          }
00919       } else if (!strcasecmp("dnid", member.argv[0])) {
00920          if (member.argc == 1) {
00921             /* Setup as if user had given dnid-num instead. */
00922             member.argc = 2;
00923             member.argv[1] = "num";
00924          }
00925          if (!strncasecmp("num", member.argv[1], 3)) {
00926             /*
00927              * Accept num[ber]
00928              * dnid-num...
00929              */
00930             if (member.argc == 2) {
00931                /* dnid-num */
00932                if (chan->dialed.number.str) {
00933                   ast_copy_string(buf, chan->dialed.number.str, len);
00934                }
00935             } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
00936                /* dnid-num-plan */
00937                snprintf(buf, len, "%d", chan->dialed.number.plan);
00938             } else {
00939                ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
00940             }
00941          } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
00942             /*
00943              * Accept subaddr[ess]
00944              * dnid-subaddr...
00945              */
00946             status = party_subaddress_read(buf, len, member.argc - 2, member.argv + 2,
00947                &chan->dialed.subaddress);
00948             switch (status) {
00949             case ID_FIELD_VALID:
00950             case ID_FIELD_INVALID:
00951                break;
00952             default:
00953                ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
00954                break;
00955             }
00956          } else {
00957             ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
00958          }
00959       } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
00960          snprintf(buf, len, "%d", chan->caller.ani2);
00961       } else if (!strcasecmp("ani", member.argv[0])) {
00962          if (member.argc == 1) {
00963             /* Setup as if user had given ani-num instead. */
00964             member.argc = 2;
00965             member.argv[1] = "num";
00966          }
00967          status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
00968             &chan->caller.ani);
00969          switch (status) {
00970          case ID_FIELD_VALID:
00971          case ID_FIELD_INVALID:
00972             break;
00973          default:
00974             ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
00975             break;
00976          }
00977       } else {
00978          status = party_id_read(buf, len, member.argc, member.argv, &chan->caller.id);
00979          switch (status) {
00980          case ID_FIELD_VALID:
00981          case ID_FIELD_INVALID:
00982             break;
00983          default:
00984             ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
00985             break;
00986          }
00987       }
00988 
00989       ast_channel_unlock(chan);
00990    }
00991 
00992    return 0;
00993 }
00994 
00995 /*!
00996  * \internal
00997  * \brief Write new values to the caller-id information struct.
00998  *
00999  * \param chan Asterisk channel to update
01000  * \param cmd Not used
01001  * \param data Caller-id function datatype string
01002  * \param value Value to assign to the caller-id information struct.
01003  *
01004  * \retval 0 on success.
01005  * \retval -1 on error.
01006  */
01007 static int callerid_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
01008 {
01009    struct ast_party_caller caller;
01010    struct ast_party_dialed dialed;
01011    enum ID_FIELD_STATUS status;
01012    char *val;
01013    char *parms;
01014    struct ast_party_func_args args;
01015    struct ast_party_members member;
01016 
01017    if (!value || !chan) {
01018       return -1;
01019    }
01020 
01021    parms = ast_strdupa(data);
01022    AST_STANDARD_APP_ARGS(args, parms);
01023    if (args.argc == 0) {
01024       /* Must have at least one argument. */
01025       return -1;
01026    }
01027 
01028    AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
01029    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
01030       /* Too few or too many subnames */
01031       return -1;
01032    }
01033 
01034    value = ast_skip_blanks(value);
01035 
01036    ast_channel_lock(chan);
01037    if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
01038       chan->redirecting.from.number.valid = 1;
01039       ast_free(chan->redirecting.from.number.str);
01040       chan->redirecting.from.number.str = ast_strdup(value);
01041       if (chan->cdr) {
01042          ast_cdr_setcid(chan->cdr, chan);
01043       }
01044    } else if (!strcasecmp("dnid", member.argv[0])) {
01045       ast_party_dialed_set_init(&dialed, &chan->dialed);
01046       if (member.argc == 1) {
01047          /* Setup as if user had given dnid-num instead. */
01048          member.argc = 2;
01049          member.argv[1] = "num";
01050       }
01051       if (!strncasecmp("num", member.argv[1], 3)) {
01052          /*
01053           * Accept num[ber]
01054           * dnid-num...
01055           */
01056          if (member.argc == 2) {
01057             /* dnid-num */
01058             dialed.number.str = ast_strdup(value);
01059             ast_trim_blanks(dialed.number.str);
01060             ast_party_dialed_set(&chan->dialed, &dialed);
01061             if (chan->cdr) {
01062                ast_cdr_setcid(chan->cdr, chan);
01063             }
01064          } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
01065             /* dnid-num-plan */
01066             val = ast_strdupa(value);
01067             ast_trim_blanks(val);
01068 
01069             if (('0' <= val[0]) && (val[0] <= '9')) {
01070                chan->dialed.number.plan = atoi(val);
01071                if (chan->cdr) {
01072                   ast_cdr_setcid(chan->cdr, chan);
01073                }
01074             } else {
01075                ast_log(LOG_ERROR,
01076                   "Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
01077             }
01078          } else {
01079             ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
01080          }
01081       } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
01082          /*
01083           * Accept subaddr[ess]
01084           * dnid-subaddr...
01085           */
01086          status = party_subaddress_write(&dialed.subaddress, member.argc - 2,
01087             member.argv + 2, value);
01088          switch (status) {
01089          case ID_FIELD_VALID:
01090             ast_party_dialed_set(&chan->dialed, &dialed);
01091             if (chan->cdr) {
01092                ast_cdr_setcid(chan->cdr, chan);
01093             }
01094             break;
01095          case ID_FIELD_INVALID:
01096             break;
01097          default:
01098             ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
01099             break;
01100          }
01101       } else {
01102          ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
01103       }
01104       ast_party_dialed_free(&dialed);
01105    } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
01106       val = ast_strdupa(value);
01107       ast_trim_blanks(val);
01108 
01109       if (('0' <= val[0]) && (val[0] <= '9')) {
01110          chan->caller.ani2 = atoi(val);
01111          if (chan->cdr) {
01112             ast_cdr_setcid(chan->cdr, chan);
01113          }
01114       } else {
01115          ast_log(LOG_ERROR, "Unknown callerid ani2 '%s', value unchanged\n", val);
01116       }
01117    } else if (!strcasecmp("ani", member.argv[0])) {
01118       ast_party_caller_set_init(&caller, &chan->caller);
01119       if (member.argc == 1) {
01120          /* Setup as if user had given ani-num instead. */
01121          member.argc = 2;
01122          member.argv[1] = "num";
01123       }
01124       status = party_id_write(&caller.ani, member.argc - 1, member.argv + 1, value);
01125       switch (status) {
01126       case ID_FIELD_VALID:
01127          ast_party_caller_set(&chan->caller, &caller, NULL);
01128          if (chan->cdr) {
01129             ast_cdr_setcid(chan->cdr, chan);
01130          }
01131          break;
01132       case ID_FIELD_INVALID:
01133          break;
01134       default:
01135          ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
01136          break;
01137       }
01138       ast_party_caller_free(&caller);
01139    } else {
01140       ast_party_caller_set_init(&caller, &chan->caller);
01141       status = party_id_write(&caller.id, member.argc, member.argv, value);
01142       switch (status) {
01143       case ID_FIELD_VALID:
01144          ast_channel_set_caller_event(chan, &caller, NULL);
01145          if (chan->cdr) {
01146             ast_cdr_setcid(chan->cdr, chan);
01147          }
01148          break;
01149       case ID_FIELD_INVALID:
01150          break;
01151       default:
01152          ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
01153          break;
01154       }
01155       ast_party_caller_free(&caller);
01156    }
01157    ast_channel_unlock(chan);
01158 
01159    return 0;
01160 }
01161 
01162 /*!
01163  * \internal
01164  * \brief Read values from the connected line information struct.
01165  *
01166  * \param chan Asterisk channel to read
01167  * \param cmd Not used
01168  * \param data Connected line function datatype string
01169  * \param buf Buffer to fill with read value.
01170  * \param len Length of the buffer
01171  *
01172  * \retval 0 on success.
01173  * \retval -1 on error.
01174  */
01175 static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
01176 {
01177    struct ast_party_members member;
01178    char *read_what;
01179    enum ID_FIELD_STATUS status;
01180 
01181    /* Ensure that the buffer is empty */
01182    *buf = 0;
01183 
01184    if (!chan) {
01185       return -1;
01186    }
01187 
01188    read_what = ast_strdupa(data);
01189    AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
01190    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
01191       /* Too few or too many subnames */
01192       return -1;
01193    }
01194 
01195    ast_channel_lock(chan);
01196 
01197    if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
01198       ast_copy_string(buf, ast_connected_line_source_name(chan->connected.source), len);
01199    } else {
01200       status = party_id_read(buf, len, member.argc, member.argv, &chan->connected.id);
01201       switch (status) {
01202       case ID_FIELD_VALID:
01203       case ID_FIELD_INVALID:
01204          break;
01205       default:
01206          ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
01207          break;
01208       }
01209    }
01210 
01211    ast_channel_unlock(chan);
01212 
01213    return 0;
01214 }
01215 
01216 /*!
01217  * \internal
01218  * \brief Write new values to the connected line information struct.
01219  *
01220  * \param chan Asterisk channel to update
01221  * \param cmd Not used
01222  * \param data Connected line function datatype string
01223  * \param value Value to assign to the connected line information struct.
01224  *
01225  * \retval 0 on success.
01226  * \retval -1 on error.
01227  */
01228 static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
01229 {
01230    struct ast_party_connected_line connected;
01231    enum ID_FIELD_STATUS status;
01232    char *val;
01233    char *parms;
01234    void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update);
01235    struct ast_party_func_args args;
01236    struct ast_party_members member;
01237    struct ast_flags opts;
01238    char *opt_args[CONNECTED_LINE_OPT_ARG_ARRAY_SIZE];
01239 
01240    if (!value || !chan) {
01241       return -1;
01242    }
01243 
01244    parms = ast_strdupa(data);
01245    AST_STANDARD_APP_ARGS(args, parms);
01246    if (args.argc == 0) {
01247       /* Must have at least one argument. */
01248       return -1;
01249    }
01250 
01251    AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
01252    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
01253       /* Too few or too many subnames */
01254       return -1;
01255    }
01256 
01257    if (ast_app_parse_options(connectedline_opts, &opts, opt_args, args.opts)) {
01258       /* General invalid option syntax. */
01259       return -1;
01260    }
01261 
01262    /* Determine if the update indication inhibit option is present */
01263    if (ast_test_flag(&opts, CONNECTED_LINE_OPT_INHIBIT)) {
01264       set_it = ast_channel_set_connected_line;
01265    } else {
01266       set_it = ast_channel_update_connected_line;
01267    }
01268 
01269    ast_channel_lock(chan);
01270    ast_party_connected_line_set_init(&connected, &chan->connected);
01271    ast_channel_unlock(chan);
01272 
01273    value = ast_skip_blanks(value);
01274 
01275    if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
01276       int source;
01277 
01278       val = ast_strdupa(value);
01279       ast_trim_blanks(val);
01280 
01281       if (('0' <= val[0]) && (val[0] <= '9')) {
01282          source = atoi(val);
01283       } else {
01284          source = ast_connected_line_source_parse(val);
01285       }
01286 
01287       if (source < 0) {
01288          ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val);
01289       } else {
01290          connected.source = source;
01291          set_it(chan, &connected, NULL);
01292       }
01293    } else {
01294       status = party_id_write(&connected.id, member.argc, member.argv, value);
01295       switch (status) {
01296       case ID_FIELD_VALID:
01297          set_it(chan, &connected, NULL);
01298          break;
01299       case ID_FIELD_INVALID:
01300          break;
01301       default:
01302          ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
01303          break;
01304       }
01305       ast_party_connected_line_free(&connected);
01306    }
01307 
01308    return 0;
01309 }
01310 
01311 /*!
01312  * \internal
01313  * \brief Read values from the redirecting information struct.
01314  *
01315  * \param chan Asterisk channel to read
01316  * \param cmd Not used
01317  * \param data Redirecting function datatype string
01318  * \param buf Buffer to fill with read value.
01319  * \param len Length of the buffer
01320  *
01321  * \retval 0 on success.
01322  * \retval -1 on error.
01323  */
01324 static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
01325 {
01326    struct ast_party_members member;
01327    char *read_what;
01328    enum ID_FIELD_STATUS status;
01329 
01330    /* Ensure that the buffer is empty */
01331    *buf = 0;
01332 
01333    if (!chan) {
01334       return -1;
01335    }
01336 
01337    read_what = ast_strdupa(data);
01338    AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
01339    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
01340       /* Too few or too many subnames */
01341       return -1;
01342    }
01343 
01344    ast_channel_lock(chan);
01345 
01346    if (!strcasecmp("from", member.argv[0])) {
01347       status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
01348          &chan->redirecting.from);
01349       switch (status) {
01350       case ID_FIELD_VALID:
01351       case ID_FIELD_INVALID:
01352          break;
01353       default:
01354          ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01355          break;
01356       }
01357    } else if (!strcasecmp("to", member.argv[0])) {
01358       status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
01359          &chan->redirecting.to);
01360       switch (status) {
01361       case ID_FIELD_VALID:
01362       case ID_FIELD_INVALID:
01363          break;
01364       default:
01365          ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01366          break;
01367       }
01368    } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
01369       /*
01370        * Accept pres[entation]
01371        * This is the combined from name/number presentation.
01372        */
01373       ast_copy_string(buf,
01374          ast_named_caller_presentation(
01375             ast_party_id_presentation(&chan->redirecting.from)), len);
01376    } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
01377       ast_copy_string(buf, ast_redirecting_reason_name(chan->redirecting.reason), len);
01378    } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
01379       snprintf(buf, len, "%d", chan->redirecting.count);
01380    } else {
01381       ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01382    }
01383 
01384    ast_channel_unlock(chan);
01385 
01386    return 0;
01387 }
01388 
01389 /*!
01390  * \internal
01391  * \brief Write new values to the redirecting information struct.
01392  *
01393  * \param chan Asterisk channel to update
01394  * \param cmd Not used
01395  * \param data Redirecting function datatype string
01396  * \param value Value to assign to the redirecting information struct.
01397  *
01398  * \retval 0 on success.
01399  * \retval -1 on error.
01400  */
01401 static int redirecting_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
01402 {
01403    struct ast_party_redirecting redirecting;
01404    enum ID_FIELD_STATUS status;
01405    char *val;
01406    char *parms;
01407    void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update);
01408    struct ast_party_func_args args;
01409    struct ast_party_members member;
01410    struct ast_flags opts;
01411    char *opt_args[REDIRECTING_OPT_ARG_ARRAY_SIZE];
01412 
01413    if (!value || !chan) {
01414       return -1;
01415    }
01416 
01417    parms = ast_strdupa(data);
01418    AST_STANDARD_APP_ARGS(args, parms);
01419    if (args.argc == 0) {
01420       /* Must have at least one argument. */
01421       return -1;
01422    }
01423 
01424    AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
01425    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
01426       /* Too few or too many subnames */
01427       return -1;
01428    }
01429 
01430    if (ast_app_parse_options(redirecting_opts, &opts, opt_args, args.opts)) {
01431       /* General invalid option syntax. */
01432       return -1;
01433    }
01434 
01435    /* Determine if the update indication inhibit option is present */
01436    if (ast_test_flag(&opts, REDIRECTING_OPT_INHIBIT)) {
01437       set_it = ast_channel_set_redirecting;
01438    } else {
01439       set_it = ast_channel_update_redirecting;
01440    }
01441 
01442    ast_channel_lock(chan);
01443    ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
01444    ast_channel_unlock(chan);
01445 
01446    value = ast_skip_blanks(value);
01447 
01448    if (!strcasecmp("from", member.argv[0])) {
01449       status = party_id_write(&redirecting.from, member.argc - 1, member.argv + 1,
01450          value);
01451       switch (status) {
01452       case ID_FIELD_VALID:
01453          set_it(chan, &redirecting, NULL);
01454          break;
01455       case ID_FIELD_INVALID:
01456          break;
01457       default:
01458          ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01459          break;
01460       }
01461       ast_party_redirecting_free(&redirecting);
01462    } else if (!strcasecmp("to", member.argv[0])) {
01463       status = party_id_write(&redirecting.to, member.argc - 1, member.argv + 1, value);
01464       switch (status) {
01465       case ID_FIELD_VALID:
01466          set_it(chan, &redirecting, NULL);
01467          break;
01468       case ID_FIELD_INVALID:
01469          break;
01470       default:
01471          ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01472          break;
01473       }
01474       ast_party_redirecting_free(&redirecting);
01475    } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
01476       int pres;
01477 
01478       val = ast_strdupa(value);
01479       ast_trim_blanks(val);
01480 
01481       if (('0' <= val[0]) && (val[0] <= '9')) {
01482          pres = atoi(val);
01483       } else {
01484          pres = ast_parse_caller_presentation(val);
01485       }
01486 
01487       if (pres < 0) {
01488          ast_log(LOG_ERROR,
01489             "Unknown redirecting combined presentation '%s', value unchanged\n", val);
01490       } else {
01491          redirecting.from.name.presentation = pres;
01492          redirecting.from.number.presentation = pres;
01493          redirecting.to.name.presentation = pres;
01494          redirecting.to.number.presentation = pres;
01495          set_it(chan, &redirecting, NULL);
01496       }
01497    } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
01498       int reason;
01499 
01500       val = ast_strdupa(value);
01501       ast_trim_blanks(val);
01502 
01503       if (('0' <= val[0]) && (val[0] <= '9')) {
01504          reason = atoi(val);
01505       } else {
01506          reason = ast_redirecting_reason_parse(val);
01507       }
01508 
01509       if (reason < 0) {
01510          ast_log(LOG_ERROR, "Unknown redirecting reason '%s', value unchanged\n", val);
01511       } else {
01512          redirecting.reason = reason;
01513          set_it(chan, &redirecting, NULL);
01514       }
01515    } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
01516       val = ast_strdupa(value);
01517       ast_trim_blanks(val);
01518 
01519       if (('0' <= val[0]) && (val[0] <= '9')) {
01520          redirecting.count = atoi(val);
01521          set_it(chan, &redirecting, NULL);
01522       } else {
01523          ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val);
01524       }
01525    } else {
01526       ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01527    }
01528 
01529    return 0;
01530 }
01531 
01532 static struct ast_custom_function callerid_function = {
01533    .name = "CALLERID",
01534    .read = callerid_read,
01535    .read_max = 256,
01536    .write = callerid_write,
01537 };
01538 
01539 static struct ast_custom_function callerpres_function = {
01540    .name = "CALLERPRES",
01541    .read = callerpres_read,
01542    .read_max = 50,
01543    .write = callerpres_write,
01544 };
01545 
01546 static struct ast_custom_function connectedline_function = {
01547    .name = "CONNECTEDLINE",
01548    .read = connectedline_read,
01549    .write = connectedline_write,
01550 };
01551 
01552 static struct ast_custom_function redirecting_function = {
01553    .name = "REDIRECTING",
01554    .read = redirecting_read,
01555    .write = redirecting_write,
01556 };
01557 
01558 /*!
01559  * \internal
01560  * \brief Unload the function module
01561  *
01562  * \retval 0 on success.
01563  * \retval -1 on error.
01564  */
01565 static int unload_module(void)
01566 {
01567    int res;
01568 
01569    res = ast_custom_function_unregister(&callerpres_function);
01570    res |= ast_custom_function_unregister(&callerid_function);
01571    res |= ast_custom_function_unregister(&connectedline_function);
01572    res |= ast_custom_function_unregister(&redirecting_function);
01573    return res;
01574 }
01575 
01576 /*!
01577  * \internal
01578  * \brief Load and initialize the function module.
01579  *
01580  * \retval AST_MODULE_LOAD_SUCCESS on success.
01581  * \retval AST_MODULE_LOAD_DECLINE on error.
01582  */
01583 static int load_module(void)
01584 {
01585    int res;
01586 
01587    res = ast_custom_function_register(&callerpres_function);
01588    res |= ast_custom_function_register(&callerid_function);
01589    res |= ast_custom_function_register(&connectedline_function);
01590    res |= ast_custom_function_register(&redirecting_function);
01591    return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
01592 }
01593 
01594 /* Do not wrap the following line. */
01595 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)");

Generated on Mon Jun 27 16:50:53 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7