Sun Oct 16 2011 08:41:40

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