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

Generated on Wed May 16 06:33:33 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6