Mon Oct 8 12:39:02 2012

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: 341704 $")
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 (!callerpres_deprecate_notify) {
00816       callerpres_deprecate_notify = 1;
00817       ast_log(LOG_WARNING, "CALLERPRES is deprecated."
00818          "  Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
00819    }
00820    ast_copy_string(buf,
00821       ast_named_caller_presentation(ast_party_id_presentation(&chan->caller.id)), len);
00822    return 0;
00823 }
00824 
00825 /*!
00826  * \internal
00827  * \brief Write new values to the caller-id presentation information struct.
00828  *
00829  * \param chan Asterisk channel to update
00830  * \param cmd Not used
00831  * \param data Caller-id presentation function datatype string
00832  * \param value Value to assign to the caller-id presentation information struct.
00833  *
00834  * \retval 0 on success.
00835  * \retval -1 on error.
00836  */
00837 static int callerpres_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00838 {
00839    int pres;
00840 
00841    if (!callerpres_deprecate_notify) {
00842       callerpres_deprecate_notify = 1;
00843       ast_log(LOG_WARNING, "CALLERPRES is deprecated."
00844          "  Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
00845    }
00846 
00847    pres = ast_parse_caller_presentation(value);
00848    if (pres < 0) {
00849       ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show function CALLERPRES')\n", value);
00850    } else {
00851       chan->caller.id.name.presentation = pres;
00852       chan->caller.id.number.presentation = pres;
00853    }
00854    return 0;
00855 }
00856 
00857 /*!
00858  * \internal
00859  * \brief Read values from the caller-id information struct.
00860  *
00861  * \param chan Asterisk channel to read
00862  * \param cmd Not used
00863  * \param data Caller-id function datatype string
00864  * \param buf Buffer to fill with read value.
00865  * \param len Length of the buffer
00866  *
00867  * \retval 0 on success.
00868  * \retval -1 on error.
00869  */
00870 static int callerid_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00871 {
00872    enum ID_FIELD_STATUS status;
00873    char *parms;
00874    struct ast_party_members member;
00875    AST_DECLARE_APP_ARGS(args,
00876       AST_APP_ARG(member); /*!< Member name */
00877       AST_APP_ARG(cid);    /*!< Optional caller id to parse instead of from the channel. */
00878       );
00879 
00880    /* Ensure that the buffer is empty */
00881    *buf = 0;
00882 
00883    if (!chan) {
00884       return -1;
00885    }
00886 
00887    parms = ast_strdupa(data);
00888    AST_STANDARD_APP_ARGS(args, parms);
00889    if (args.argc == 0) {
00890       /* Must have at least one argument. */
00891       return -1;
00892    }
00893 
00894    AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
00895    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
00896       /* Too few or too many subnames */
00897       return -1;
00898    }
00899 
00900    if (args.argc == 2) {
00901       char name[80];
00902       char num[80];
00903 
00904       ast_callerid_split(args.cid, name, sizeof(name), num, sizeof(num));
00905 
00906       if (member.argc == 1 && !strcasecmp("all", member.argv[0])) {
00907          snprintf(buf, len, "\"%s\" <%s>", name, num);
00908       } else if (member.argc == 1 && !strcasecmp("name", member.argv[0])) {
00909          ast_copy_string(buf, name, len);
00910       } else if (member.argc == 1 && !strncasecmp("num", member.argv[0], 3)) {
00911          /* Accept num[ber] */
00912          ast_copy_string(buf, num, len);
00913       } else {
00914          ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
00915       }
00916    } else {
00917       ast_channel_lock(chan);
00918 
00919       if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
00920          if (chan->redirecting.from.number.valid
00921             && chan->redirecting.from.number.str) {
00922             ast_copy_string(buf, chan->redirecting.from.number.str, len);
00923          }
00924       } else if (!strcasecmp("dnid", member.argv[0])) {
00925          if (member.argc == 1) {
00926             /* Setup as if user had given dnid-num instead. */
00927             member.argc = 2;
00928             member.argv[1] = "num";
00929          }
00930          if (!strncasecmp("num", member.argv[1], 3)) {
00931             /*
00932              * Accept num[ber]
00933              * dnid-num...
00934              */
00935             if (member.argc == 2) {
00936                /* dnid-num */
00937                if (chan->dialed.number.str) {
00938                   ast_copy_string(buf, chan->dialed.number.str, len);
00939                }
00940             } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
00941                /* dnid-num-plan */
00942                snprintf(buf, len, "%d", chan->dialed.number.plan);
00943             } else {
00944                ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
00945             }
00946          } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
00947             /*
00948              * Accept subaddr[ess]
00949              * dnid-subaddr...
00950              */
00951             status = party_subaddress_read(buf, len, member.argc - 2, member.argv + 2,
00952                &chan->dialed.subaddress);
00953             switch (status) {
00954             case ID_FIELD_VALID:
00955             case ID_FIELD_INVALID:
00956                break;
00957             default:
00958                ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
00959                break;
00960             }
00961          } else {
00962             ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
00963          }
00964       } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
00965          snprintf(buf, len, "%d", chan->caller.ani2);
00966       } else if (!strcasecmp("ani", member.argv[0])) {
00967          if (member.argc == 1) {
00968             /* Setup as if user had given ani-num instead. */
00969             member.argc = 2;
00970             member.argv[1] = "num";
00971          }
00972          status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
00973             &chan->caller.ani);
00974          switch (status) {
00975          case ID_FIELD_VALID:
00976          case ID_FIELD_INVALID:
00977             break;
00978          default:
00979             ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
00980             break;
00981          }
00982       } else {
00983          status = party_id_read(buf, len, member.argc, member.argv, &chan->caller.id);
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       }
00993 
00994       ast_channel_unlock(chan);
00995    }
00996 
00997    return 0;
00998 }
00999 
01000 /*!
01001  * \internal
01002  * \brief Write new values to the caller-id information struct.
01003  *
01004  * \param chan Asterisk channel to update
01005  * \param cmd Not used
01006  * \param data Caller-id function datatype string
01007  * \param value Value to assign to the caller-id information struct.
01008  *
01009  * \retval 0 on success.
01010  * \retval -1 on error.
01011  */
01012 static int callerid_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
01013 {
01014    struct ast_party_caller caller;
01015    struct ast_party_dialed dialed;
01016    enum ID_FIELD_STATUS status;
01017    char *val;
01018    char *parms;
01019    struct ast_party_func_args args;
01020    struct ast_party_members member;
01021 
01022    if (!value || !chan) {
01023       return -1;
01024    }
01025 
01026    parms = ast_strdupa(data);
01027    AST_STANDARD_APP_ARGS(args, parms);
01028    if (args.argc == 0) {
01029       /* Must have at least one argument. */
01030       return -1;
01031    }
01032 
01033    AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
01034    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
01035       /* Too few or too many subnames */
01036       return -1;
01037    }
01038 
01039    value = ast_skip_blanks(value);
01040 
01041    ast_channel_lock(chan);
01042    if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
01043       chan->redirecting.from.number.valid = 1;
01044       ast_free(chan->redirecting.from.number.str);
01045       chan->redirecting.from.number.str = ast_strdup(value);
01046       if (chan->cdr) {
01047          ast_cdr_setcid(chan->cdr, chan);
01048       }
01049    } else if (!strcasecmp("dnid", member.argv[0])) {
01050       ast_party_dialed_set_init(&dialed, &chan->dialed);
01051       if (member.argc == 1) {
01052          /* Setup as if user had given dnid-num instead. */
01053          member.argc = 2;
01054          member.argv[1] = "num";
01055       }
01056       if (!strncasecmp("num", member.argv[1], 3)) {
01057          /*
01058           * Accept num[ber]
01059           * dnid-num...
01060           */
01061          if (member.argc == 2) {
01062             /* dnid-num */
01063             dialed.number.str = ast_strdup(value);
01064             ast_trim_blanks(dialed.number.str);
01065             ast_party_dialed_set(&chan->dialed, &dialed);
01066             if (chan->cdr) {
01067                ast_cdr_setcid(chan->cdr, chan);
01068             }
01069          } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
01070             /* dnid-num-plan */
01071             val = ast_strdupa(value);
01072             ast_trim_blanks(val);
01073 
01074             if (('0' <= val[0]) && (val[0] <= '9')) {
01075                chan->dialed.number.plan = atoi(val);
01076                if (chan->cdr) {
01077                   ast_cdr_setcid(chan->cdr, chan);
01078                }
01079             } else {
01080                ast_log(LOG_ERROR,
01081                   "Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
01082             }
01083          } else {
01084             ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
01085          }
01086       } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
01087          /*
01088           * Accept subaddr[ess]
01089           * dnid-subaddr...
01090           */
01091          status = party_subaddress_write(&dialed.subaddress, member.argc - 2,
01092             member.argv + 2, value);
01093          switch (status) {
01094          case ID_FIELD_VALID:
01095             ast_party_dialed_set(&chan->dialed, &dialed);
01096             if (chan->cdr) {
01097                ast_cdr_setcid(chan->cdr, chan);
01098             }
01099             break;
01100          case ID_FIELD_INVALID:
01101             break;
01102          default:
01103             ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
01104             break;
01105          }
01106       } else {
01107          ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
01108       }
01109       ast_party_dialed_free(&dialed);
01110    } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
01111       val = ast_strdupa(value);
01112       ast_trim_blanks(val);
01113 
01114       if (('0' <= val[0]) && (val[0] <= '9')) {
01115          chan->caller.ani2 = atoi(val);
01116          if (chan->cdr) {
01117             ast_cdr_setcid(chan->cdr, chan);
01118          }
01119       } else {
01120          ast_log(LOG_ERROR, "Unknown callerid ani2 '%s', value unchanged\n", val);
01121       }
01122    } else if (!strcasecmp("ani", member.argv[0])) {
01123       ast_party_caller_set_init(&caller, &chan->caller);
01124       if (member.argc == 1) {
01125          /* Setup as if user had given ani-num instead. */
01126          member.argc = 2;
01127          member.argv[1] = "num";
01128       }
01129       status = party_id_write(&caller.ani, member.argc - 1, member.argv + 1, value);
01130       switch (status) {
01131       case ID_FIELD_VALID:
01132          ast_party_caller_set(&chan->caller, &caller, NULL);
01133          if (chan->cdr) {
01134             ast_cdr_setcid(chan->cdr, chan);
01135          }
01136          break;
01137       case ID_FIELD_INVALID:
01138          break;
01139       default:
01140          ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
01141          break;
01142       }
01143       ast_party_caller_free(&caller);
01144    } else {
01145       ast_party_caller_set_init(&caller, &chan->caller);
01146       status = party_id_write(&caller.id, member.argc, member.argv, value);
01147       switch (status) {
01148       case ID_FIELD_VALID:
01149          ast_channel_set_caller_event(chan, &caller, NULL);
01150          if (chan->cdr) {
01151             ast_cdr_setcid(chan->cdr, chan);
01152          }
01153          break;
01154       case ID_FIELD_INVALID:
01155          break;
01156       default:
01157          ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
01158          break;
01159       }
01160       ast_party_caller_free(&caller);
01161    }
01162    ast_channel_unlock(chan);
01163 
01164    return 0;
01165 }
01166 
01167 /*!
01168  * \internal
01169  * \brief Read values from the connected line information struct.
01170  *
01171  * \param chan Asterisk channel to read
01172  * \param cmd Not used
01173  * \param data Connected line function datatype string
01174  * \param buf Buffer to fill with read value.
01175  * \param len Length of the buffer
01176  *
01177  * \retval 0 on success.
01178  * \retval -1 on error.
01179  */
01180 static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
01181 {
01182    struct ast_party_members member;
01183    char *read_what;
01184    enum ID_FIELD_STATUS status;
01185 
01186    /* Ensure that the buffer is empty */
01187    *buf = 0;
01188 
01189    if (!chan) {
01190       return -1;
01191    }
01192 
01193    read_what = ast_strdupa(data);
01194    AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
01195    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
01196       /* Too few or too many subnames */
01197       return -1;
01198    }
01199 
01200    ast_channel_lock(chan);
01201 
01202    if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
01203       ast_copy_string(buf, ast_connected_line_source_name(chan->connected.source), len);
01204    } else {
01205       status = party_id_read(buf, len, member.argc, member.argv, &chan->connected.id);
01206       switch (status) {
01207       case ID_FIELD_VALID:
01208       case ID_FIELD_INVALID:
01209          break;
01210       default:
01211          ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
01212          break;
01213       }
01214    }
01215 
01216    ast_channel_unlock(chan);
01217 
01218    return 0;
01219 }
01220 
01221 /*!
01222  * \internal
01223  * \brief Write new values to the connected line information struct.
01224  *
01225  * \param chan Asterisk channel to update
01226  * \param cmd Not used
01227  * \param data Connected line function datatype string
01228  * \param value Value to assign to the connected line information struct.
01229  *
01230  * \retval 0 on success.
01231  * \retval -1 on error.
01232  */
01233 static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
01234 {
01235    struct ast_party_connected_line connected;
01236    enum ID_FIELD_STATUS status;
01237    char *val;
01238    char *parms;
01239    void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update);
01240    struct ast_party_func_args args;
01241    struct ast_party_members member;
01242    struct ast_flags opts;
01243    char *opt_args[CONNECTED_LINE_OPT_ARG_ARRAY_SIZE];
01244 
01245    if (!value || !chan) {
01246       return -1;
01247    }
01248 
01249    parms = ast_strdupa(data);
01250    AST_STANDARD_APP_ARGS(args, parms);
01251    if (args.argc == 0) {
01252       /* Must have at least one argument. */
01253       return -1;
01254    }
01255 
01256    AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
01257    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
01258       /* Too few or too many subnames */
01259       return -1;
01260    }
01261 
01262    if (ast_app_parse_options(connectedline_opts, &opts, opt_args, args.opts)) {
01263       /* General invalid option syntax. */
01264       return -1;
01265    }
01266 
01267    /* Determine if the update indication inhibit option is present */
01268    if (ast_test_flag(&opts, CONNECTED_LINE_OPT_INHIBIT)) {
01269       set_it = ast_channel_set_connected_line;
01270    } else {
01271       set_it = ast_channel_update_connected_line;
01272    }
01273 
01274    ast_channel_lock(chan);
01275    ast_party_connected_line_set_init(&connected, &chan->connected);
01276    ast_channel_unlock(chan);
01277 
01278    value = ast_skip_blanks(value);
01279 
01280    if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
01281       int source;
01282 
01283       val = ast_strdupa(value);
01284       ast_trim_blanks(val);
01285 
01286       if (('0' <= val[0]) && (val[0] <= '9')) {
01287          source = atoi(val);
01288       } else {
01289          source = ast_connected_line_source_parse(val);
01290       }
01291 
01292       if (source < 0) {
01293          ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val);
01294       } else {
01295          connected.source = source;
01296          set_it(chan, &connected, NULL);
01297       }
01298    } else {
01299       status = party_id_write(&connected.id, member.argc, member.argv, value);
01300       switch (status) {
01301       case ID_FIELD_VALID:
01302          set_it(chan, &connected, NULL);
01303          break;
01304       case ID_FIELD_INVALID:
01305          break;
01306       default:
01307          ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
01308          break;
01309       }
01310       ast_party_connected_line_free(&connected);
01311    }
01312 
01313    return 0;
01314 }
01315 
01316 /*!
01317  * \internal
01318  * \brief Read values from the redirecting information struct.
01319  *
01320  * \param chan Asterisk channel to read
01321  * \param cmd Not used
01322  * \param data Redirecting function datatype string
01323  * \param buf Buffer to fill with read value.
01324  * \param len Length of the buffer
01325  *
01326  * \retval 0 on success.
01327  * \retval -1 on error.
01328  */
01329 static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
01330 {
01331    struct ast_party_members member;
01332    char *read_what;
01333    enum ID_FIELD_STATUS status;
01334 
01335    /* Ensure that the buffer is empty */
01336    *buf = 0;
01337 
01338    if (!chan) {
01339       return -1;
01340    }
01341 
01342    read_what = ast_strdupa(data);
01343    AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
01344    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
01345       /* Too few or too many subnames */
01346       return -1;
01347    }
01348 
01349    ast_channel_lock(chan);
01350 
01351    if (!strcasecmp("from", member.argv[0])) {
01352       status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
01353          &chan->redirecting.from);
01354       switch (status) {
01355       case ID_FIELD_VALID:
01356       case ID_FIELD_INVALID:
01357          break;
01358       default:
01359          ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01360          break;
01361       }
01362    } else if (!strcasecmp("to", member.argv[0])) {
01363       status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
01364          &chan->redirecting.to);
01365       switch (status) {
01366       case ID_FIELD_VALID:
01367       case ID_FIELD_INVALID:
01368          break;
01369       default:
01370          ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01371          break;
01372       }
01373    } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
01374       /*
01375        * Accept pres[entation]
01376        * This is the combined from name/number presentation.
01377        */
01378       ast_copy_string(buf,
01379          ast_named_caller_presentation(
01380             ast_party_id_presentation(&chan->redirecting.from)), len);
01381    } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
01382       ast_copy_string(buf, ast_redirecting_reason_name(chan->redirecting.reason), len);
01383    } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
01384       snprintf(buf, len, "%d", chan->redirecting.count);
01385    } else {
01386       ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01387    }
01388 
01389    ast_channel_unlock(chan);
01390 
01391    return 0;
01392 }
01393 
01394 /*!
01395  * \internal
01396  * \brief Write new values to the redirecting information struct.
01397  *
01398  * \param chan Asterisk channel to update
01399  * \param cmd Not used
01400  * \param data Redirecting function datatype string
01401  * \param value Value to assign to the redirecting information struct.
01402  *
01403  * \retval 0 on success.
01404  * \retval -1 on error.
01405  */
01406 static int redirecting_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
01407 {
01408    struct ast_party_redirecting redirecting;
01409    enum ID_FIELD_STATUS status;
01410    char *val;
01411    char *parms;
01412    void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update);
01413    struct ast_party_func_args args;
01414    struct ast_party_members member;
01415    struct ast_flags opts;
01416    char *opt_args[REDIRECTING_OPT_ARG_ARRAY_SIZE];
01417 
01418    if (!value || !chan) {
01419       return -1;
01420    }
01421 
01422    parms = ast_strdupa(data);
01423    AST_STANDARD_APP_ARGS(args, parms);
01424    if (args.argc == 0) {
01425       /* Must have at least one argument. */
01426       return -1;
01427    }
01428 
01429    AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
01430    if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
01431       /* Too few or too many subnames */
01432       return -1;
01433    }
01434 
01435    if (ast_app_parse_options(redirecting_opts, &opts, opt_args, args.opts)) {
01436       /* General invalid option syntax. */
01437       return -1;
01438    }
01439 
01440    /* Determine if the update indication inhibit option is present */
01441    if (ast_test_flag(&opts, REDIRECTING_OPT_INHIBIT)) {
01442       set_it = ast_channel_set_redirecting;
01443    } else {
01444       set_it = ast_channel_update_redirecting;
01445    }
01446 
01447    ast_channel_lock(chan);
01448    ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
01449    ast_channel_unlock(chan);
01450 
01451    value = ast_skip_blanks(value);
01452 
01453    if (!strcasecmp("from", member.argv[0])) {
01454       status = party_id_write(&redirecting.from, member.argc - 1, member.argv + 1,
01455          value);
01456       switch (status) {
01457       case ID_FIELD_VALID:
01458          set_it(chan, &redirecting, NULL);
01459          break;
01460       case ID_FIELD_INVALID:
01461          break;
01462       default:
01463          ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01464          break;
01465       }
01466       ast_party_redirecting_free(&redirecting);
01467    } else if (!strcasecmp("to", member.argv[0])) {
01468       status = party_id_write(&redirecting.to, member.argc - 1, member.argv + 1, value);
01469       switch (status) {
01470       case ID_FIELD_VALID:
01471          set_it(chan, &redirecting, NULL);
01472          break;
01473       case ID_FIELD_INVALID:
01474          break;
01475       default:
01476          ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01477          break;
01478       }
01479       ast_party_redirecting_free(&redirecting);
01480    } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
01481       int pres;
01482 
01483       val = ast_strdupa(value);
01484       ast_trim_blanks(val);
01485 
01486       if (('0' <= val[0]) && (val[0] <= '9')) {
01487          pres = atoi(val);
01488       } else {
01489          pres = ast_parse_caller_presentation(val);
01490       }
01491 
01492       if (pres < 0) {
01493          ast_log(LOG_ERROR,
01494             "Unknown redirecting combined presentation '%s', value unchanged\n", val);
01495       } else {
01496          redirecting.from.name.presentation = pres;
01497          redirecting.from.number.presentation = pres;
01498          redirecting.to.name.presentation = pres;
01499          redirecting.to.number.presentation = pres;
01500          set_it(chan, &redirecting, NULL);
01501       }
01502    } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
01503       int reason;
01504 
01505       val = ast_strdupa(value);
01506       ast_trim_blanks(val);
01507 
01508       if (('0' <= val[0]) && (val[0] <= '9')) {
01509          reason = atoi(val);
01510       } else {
01511          reason = ast_redirecting_reason_parse(val);
01512       }
01513 
01514       if (reason < 0) {
01515          ast_log(LOG_ERROR, "Unknown redirecting reason '%s', value unchanged\n", val);
01516       } else {
01517          redirecting.reason = reason;
01518          set_it(chan, &redirecting, NULL);
01519       }
01520    } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
01521       val = ast_strdupa(value);
01522       ast_trim_blanks(val);
01523 
01524       if (('0' <= val[0]) && (val[0] <= '9')) {
01525          redirecting.count = atoi(val);
01526          set_it(chan, &redirecting, NULL);
01527       } else {
01528          ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val);
01529       }
01530    } else {
01531       ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
01532    }
01533 
01534    return 0;
01535 }
01536 
01537 static struct ast_custom_function callerid_function = {
01538    .name = "CALLERID",
01539    .read = callerid_read,
01540    .read_max = 256,
01541    .write = callerid_write,
01542 };
01543 
01544 static struct ast_custom_function callerpres_function = {
01545    .name = "CALLERPRES",
01546    .read = callerpres_read,
01547    .read_max = 50,
01548    .write = callerpres_write,
01549 };
01550 
01551 static struct ast_custom_function connectedline_function = {
01552    .name = "CONNECTEDLINE",
01553    .read = connectedline_read,
01554    .write = connectedline_write,
01555 };
01556 
01557 static struct ast_custom_function redirecting_function = {
01558    .name = "REDIRECTING",
01559    .read = redirecting_read,
01560    .write = redirecting_write,
01561 };
01562 
01563 /*!
01564  * \internal
01565  * \brief Unload the function module
01566  *
01567  * \retval 0 on success.
01568  * \retval -1 on error.
01569  */
01570 static int unload_module(void)
01571 {
01572    int res;
01573 
01574    res = ast_custom_function_unregister(&callerpres_function);
01575    res |= ast_custom_function_unregister(&callerid_function);
01576    res |= ast_custom_function_unregister(&connectedline_function);
01577    res |= ast_custom_function_unregister(&redirecting_function);
01578    return res;
01579 }
01580 
01581 /*!
01582  * \internal
01583  * \brief Load and initialize the function module.
01584  *
01585  * \retval AST_MODULE_LOAD_SUCCESS on success.
01586  * \retval AST_MODULE_LOAD_DECLINE on error.
01587  */
01588 static int load_module(void)
01589 {
01590    int res;
01591 
01592    res = ast_custom_function_register(&callerpres_function);
01593    res |= ast_custom_function_register(&callerid_function);
01594    res |= ast_custom_function_register(&connectedline_function);
01595    res |= ast_custom_function_register(&redirecting_function);
01596    return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
01597 }
01598 
01599 /* Do not wrap the following line. */
01600 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)");

Generated on Mon Oct 8 12:39:02 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7