Wed Jan 27 20:02:11 2016

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

Generated on 27 Jan 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1