Merged revisions 336316 via svnmerge from
[asterisk/asterisk.git] / funcs / func_callerid.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999-2010, Digium, Inc.
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*! \file
18  *
19  * \brief Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)
20  *
21  * \ingroup functions
22  *
23  * See Also:
24  * \arg \ref AstCREDITS
25  */
26
27 /*** MODULEINFO
28         <support_level>core</support_level>
29  ***/
30
31 #include "asterisk.h"
32
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34
35 #include "asterisk/module.h"
36 #include "asterisk/channel.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/utils.h"
39 #include "asterisk/app.h"
40 #include "asterisk/callerid.h"
41
42 /*
43  * Do not document the CALLERID(pres) datatype.
44  * The name and number now have their own presentation value.  The pres
45  * option will simply live on as a historical relic with as best
46  * as can be managed backward compatible meaning.
47  *
48  * Do not document the CALLERID(ton) datatype.
49  * It is an alias for num-plan.
50  *
51  * Do not document the CALLERID(ANI-subaddr-...) datatype.
52  * This is not used.
53  *
54  * Do not document the CONNECTEDLINE(source) datatype.
55  * It has turned out to not be needed.  The source value is really
56  * only useful as a possible tracing aid.
57  *
58  * Do not document the CONNECTEDLINE(pres) datatype.
59  * The name and number now have their own presentation value.  The pres
60  * option will simply live on as a historical relic with as best
61  * as can be managed backward compatible meaning.
62  *
63  * Do not document the CONNECTEDLINE(ton) datatype.
64  * It is an alias for num-plan.
65  *
66  * Do not document the REDIRECTING(pres) datatype.
67  * It has turned out that the from-pres and to-pres values must be kept
68  * separate.  They represent two different parties and there is a case when
69  * they are active at the same time.  The plain pres option will simply
70  * live on as a historical relic.
71  *
72  * Do not document the REDIRECTING(from-pres) or REDIRECTING(to-pres) datatypes.
73  * The name and number now have their own presentation value.  The from-pres
74  * and to-pres options will simply live on as a historical relic with as best
75  * as can be managed backward compatible meaning.
76  *
77  * Do not document the REDIRECTING(from-ton) or REDIRECTING(to-ton) datatypes.
78  * They are aliases for from-num-plan and to-num-plan respectively.
79  */
80 /*** DOCUMENTATION
81         <function name="CALLERID" language="en_US">
82                 <synopsis>
83                         Gets or sets Caller*ID data on the channel.
84                 </synopsis>
85                 <syntax>
86                         <parameter name="datatype" required="true">
87                                 <para>The allowable datatypes are:</para>
88                                 <enumlist>
89                                         <enum name = "all" />
90                                         <enum name = "name" />
91                                         <enum name = "name-valid" />
92                                         <enum name = "name-charset" />
93                                         <enum name = "name-pres" />
94                                         <enum name = "num" />
95                                         <enum name = "num-valid" />
96                                         <enum name = "num-plan" />
97                                         <enum name = "num-pres" />
98                                         <enum name = "subaddr" />
99                                         <enum name = "subaddr-valid" />
100                                         <enum name = "subaddr-type" />
101                                         <enum name = "subaddr-odd" />
102                                         <enum name = "tag" />
103                                         <enum name = "ANI-all" />
104                                         <enum name = "ANI-name" />
105                                         <enum name = "ANI-name-valid" />
106                                         <enum name = "ANI-name-charset" />
107                                         <enum name = "ANI-name-pres" />
108                                         <enum name = "ANI-num" />
109                                         <enum name = "ANI-num-valid" />
110                                         <enum name = "ANI-num-plan" />
111                                         <enum name = "ANI-num-pres" />
112                                         <enum name = "ANI-tag" />
113                                         <enum name = "RDNIS" />
114                                         <enum name = "DNID" />
115                                         <enum name = "dnid-num-plan" />
116                                         <enum name = "dnid-subaddr" />
117                                         <enum name = "dnid-subaddr-valid" />
118                                         <enum name = "dnid-subaddr-type" />
119                                         <enum name = "dnid-subaddr-odd" />
120                                 </enumlist>
121                         </parameter>
122                         <parameter name="CID">
123                                 <para>Optional Caller*ID</para>
124                         </parameter>
125                 </syntax>
126                 <description>
127                         <para>Gets or sets Caller*ID data on the channel. Uses channel callerid by
128                         default or optional callerid, if specified.</para>
129                         <para>The allowable values for the <replaceable>name-charset</replaceable>
130                         field are the following:</para>
131                         <enumlist>
132                                 <enum name = "unknown"><para>Unknown</para></enum>
133                                 <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
134                                 <enum name = "withdrawn"><para>Withdrawn</para></enum>
135                                 <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
136                                 <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
137                                 <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
138                                 <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
139                                 <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
140                                 <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
141                                 <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
142                         </enumlist>
143                 </description>
144         </function>
145         <function name="CALLERPRES" language="en_US">
146                 <synopsis>
147                         Gets or sets Caller*ID presentation on the channel.
148                 </synopsis>
149                 <syntax />
150                 <description>
151                         <para>Gets or sets Caller*ID presentation on the channel.
152                         This function is deprecated in favor of CALLERID(num-pres)
153                         and CALLERID(name-pres).
154                         The following values are valid:</para>
155                         <enumlist>
156                                 <enum name="allowed_not_screened">
157                                         <para>Presentation Allowed, Not Screened.</para>
158                                 </enum>
159                                 <enum name="allowed_passed_screen">
160                                         <para>Presentation Allowed, Passed Screen.</para>
161                                 </enum>
162                                 <enum name="allowed_failed_screen">
163                                         <para>Presentation Allowed, Failed Screen.</para>
164                                 </enum>
165                                 <enum name="allowed">
166                                         <para>Presentation Allowed, Network Number.</para>
167                                 </enum>
168                                 <enum name="prohib_not_screened">
169                                         <para>Presentation Prohibited, Not Screened.</para>
170                                 </enum>
171                                 <enum name="prohib_passed_screen">
172                                         <para>Presentation Prohibited, Passed Screen.</para>
173                                 </enum>
174                                 <enum name="prohib_failed_screen">
175                                         <para>Presentation Prohibited, Failed Screen.</para>
176                                 </enum>
177                                 <enum name="prohib">
178                                         <para>Presentation Prohibited, Network Number.</para>
179                                 </enum>
180                                 <enum name="unavailable">
181                                         <para>Number Unavailable.</para>
182                                 </enum>
183                         </enumlist>
184                 </description>
185         </function>
186         <function name="CONNECTEDLINE" language="en_US">
187                 <synopsis>
188                         Gets or sets Connected Line data on the channel.
189                 </synopsis>
190                 <syntax>
191                         <parameter name="datatype" required="true">
192                                 <para>The allowable datatypes are:</para>
193                                 <enumlist>
194                                         <enum name = "all" />
195                                         <enum name = "name" />
196                                         <enum name = "name-valid" />
197                                         <enum name = "name-charset" />
198                                         <enum name = "name-pres" />
199                                         <enum name = "num" />
200                                         <enum name = "num-valid" />
201                                         <enum name = "num-plan" />
202                                         <enum name = "num-pres" />
203                                         <enum name = "subaddr" />
204                                         <enum name = "subaddr-valid" />
205                                         <enum name = "subaddr-type" />
206                                         <enum name = "subaddr-odd" />
207                                         <enum name = "tag" />
208                                 </enumlist>
209                         </parameter>
210                         <parameter name="i">
211                                 <para>If set, this will prevent the channel from sending out protocol
212                                 messages because of the value being set</para>
213                         </parameter>
214                 </syntax>
215                 <description>
216                         <para>Gets or sets Connected Line data on the channel.</para>
217                         <para>The allowable values for the <replaceable>name-charset</replaceable>
218                         field are the following:</para>
219                         <enumlist>
220                                 <enum name = "unknown"><para>Unknown</para></enum>
221                                 <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
222                                 <enum name = "withdrawn"><para>Withdrawn</para></enum>
223                                 <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
224                                 <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
225                                 <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
226                                 <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
227                                 <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
228                                 <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
229                                 <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
230                         </enumlist>
231                 </description>
232         </function>
233         <function name="REDIRECTING" language="en_US">
234                 <synopsis>
235                         Gets or sets Redirecting data on the channel.
236                 </synopsis>
237                 <syntax>
238                         <parameter name="datatype" required="true">
239                                 <para>The allowable datatypes are:</para>
240                                 <enumlist>
241                                         <enum name = "from-all" />
242                                         <enum name = "from-name" />
243                                         <enum name = "from-name-valid" />
244                                         <enum name = "from-name-charset" />
245                                         <enum name = "from-name-pres" />
246                                         <enum name = "from-num" />
247                                         <enum name = "from-num-valid" />
248                                         <enum name = "from-num-plan" />
249                                         <enum name = "from-num-pres" />
250                                         <enum name = "from-subaddr" />
251                                         <enum name = "from-subaddr-valid" />
252                                         <enum name = "from-subaddr-type" />
253                                         <enum name = "from-subaddr-odd" />
254                                         <enum name = "from-tag" />
255                                         <enum name = "to-all" />
256                                         <enum name = "to-name" />
257                                         <enum name = "to-name-valid" />
258                                         <enum name = "to-name-charset" />
259                                         <enum name = "to-name-pres" />
260                                         <enum name = "to-num" />
261                                         <enum name = "to-num-valid" />
262                                         <enum name = "to-num-plan" />
263                                         <enum name = "to-num-pres" />
264                                         <enum name = "to-subaddr" />
265                                         <enum name = "to-subaddr-valid" />
266                                         <enum name = "to-subaddr-type" />
267                                         <enum name = "to-subaddr-odd" />
268                                         <enum name = "to-tag" />
269                                         <enum name = "reason" />
270                                         <enum name = "count" />
271                                 </enumlist>
272                         </parameter>
273                         <parameter name="i">
274                                 <para>If set, this will prevent the channel from sending out protocol
275                                 messages because of the value being set</para>
276                         </parameter>
277                 </syntax>
278                 <description>
279                         <para>Gets or sets Redirecting data on the channel.</para>
280                         <para>The allowable values for the <replaceable>reason</replaceable>
281                         field are the following:</para>
282                         <enumlist>
283                                 <enum name = "unknown"><para>Unknown</para></enum>
284                                 <enum name = "cfb"><para>Call Forwarding Busy</para></enum>
285                                 <enum name = "cfnr"><para>Call Forwarding No Reply</para></enum>
286                                 <enum name = "unavailable"><para>Callee is Unavailable</para></enum>
287                                 <enum name = "time_of_day"><para>Time of Day</para></enum>
288                                 <enum name = "dnd"><para>Do Not Disturb</para></enum>
289                                 <enum name = "deflection"><para>Call Deflection</para></enum>
290                                 <enum name = "follow_me"><para>Follow Me</para></enum>
291                                 <enum name = "out_of_order"><para>Called DTE Out-Of-Order</para></enum>
292                                 <enum name = "away"><para>Callee is Away</para></enum>
293                                 <enum name = "cf_dte"><para>Call Forwarding By The Called DTE</para></enum>
294                                 <enum name = "cfu"><para>Call Forwarding Unconditional</para></enum>
295                         </enumlist>
296                         <para>The allowable values for the <replaceable>xxx-name-charset</replaceable>
297                         field are the following:</para>
298                         <enumlist>
299                                 <enum name = "unknown"><para>Unknown</para></enum>
300                                 <enum name = "iso8859-1"><para>ISO8859-1</para></enum>
301                                 <enum name = "withdrawn"><para>Withdrawn</para></enum>
302                                 <enum name = "iso8859-2"><para>ISO8859-2</para></enum>
303                                 <enum name = "iso8859-3"><para>ISO8859-3</para></enum>
304                                 <enum name = "iso8859-4"><para>ISO8859-4</para></enum>
305                                 <enum name = "iso8859-5"><para>ISO8859-5</para></enum>
306                                 <enum name = "iso8859-7"><para>ISO8859-7</para></enum>
307                                 <enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
308                                 <enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
309                         </enumlist>
310                 </description>
311         </function>
312  ***/
313
314 enum ID_FIELD_STATUS {
315         ID_FIELD_VALID,
316         ID_FIELD_INVALID,
317         ID_FIELD_UNKNOWN
318 };
319
320 AST_DEFINE_APP_ARGS_TYPE(ast_party_func_args,
321         AST_APP_ARG(member);    /*!< Member name */
322         AST_APP_ARG(opts);              /*!< Options token */
323         AST_APP_ARG(other);             /*!< Any remining unused arguments */
324         );
325
326 AST_DEFINE_APP_ARGS_TYPE(ast_party_members,
327         AST_APP_ARG(subnames[10]);      /*!< Option member subnames */
328         );
329
330 enum CONNECTED_LINE_OPT_FLAGS {
331         CONNECTED_LINE_OPT_INHIBIT = (1 << 0),
332 };
333 enum CONNECTED_LINE_OPT_ARGS {
334         CONNECTED_LINE_OPT_DUMMY,       /*!< Delete this if CONNECTED_LINE ever gets an option with parameters. */
335
336         /*! \note This entry _MUST_ be the last one in the enum */
337         CONNECTED_LINE_OPT_ARG_ARRAY_SIZE
338 };
339
340 AST_APP_OPTIONS(connectedline_opts, BEGIN_OPTIONS
341         AST_APP_OPTION('i', CONNECTED_LINE_OPT_INHIBIT),
342 END_OPTIONS);
343
344 enum REDIRECTING_OPT_FLAGS {
345         REDIRECTING_OPT_INHIBIT = (1 << 0),
346 };
347 enum REDIRECTING_OPT_ARGS {
348         REDIRECTING_OPT_DUMMY,  /*!< Delete this if REDIRECTING ever gets an option with parameters. */
349
350         /*! \note This entry _MUST_ be the last one in the enum */
351         REDIRECTING_OPT_ARG_ARRAY_SIZE
352 };
353
354 AST_APP_OPTIONS(redirecting_opts, BEGIN_OPTIONS
355         AST_APP_OPTION('i', REDIRECTING_OPT_INHIBIT),
356 END_OPTIONS);
357
358 /*!
359  * \internal
360  * \brief Read values from the party name struct.
361  * \since 1.8
362  *
363  * \param buf Buffer to fill with read value.
364  * \param len Length of the buffer.
365  * \param argc Number of party member subnames.
366  * \param argv Party member subnames given.
367  * \param name Party name to get values from.
368  *
369  * \retval ID_FIELD_VALID on success.
370  * \retval ID_FIELD_UNKNOWN on unknown field name.
371  */
372 static enum ID_FIELD_STATUS party_name_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_name *name)
373 {
374         enum ID_FIELD_STATUS status;
375
376         status = ID_FIELD_VALID;
377
378         if (argc == 0) {
379                 /* We want the name string */
380                 if (name->valid && name->str) {
381                         ast_copy_string(buf, name->str, len);
382                 }
383         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
384                 snprintf(buf, len, "%d", name->valid);
385         } else if (argc == 1 && !strcasecmp("charset", argv[0])) {
386                 ast_copy_string(buf, ast_party_name_charset_str(name->char_set), len);
387         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
388                 /* Accept pres[entation] */
389                 ast_copy_string(buf, ast_named_caller_presentation(name->presentation), len);
390         } else {
391                 status = ID_FIELD_UNKNOWN;
392         }
393
394         return status;
395 }
396
397 /*!
398  * \internal
399  * \brief Read values from the party number struct.
400  * \since 1.8
401  *
402  * \param buf Buffer to fill with read value.
403  * \param len Length of the buffer.
404  * \param argc Number of party member subnames.
405  * \param argv Party member subnames given.
406  * \param number Party number to get values from.
407  *
408  * \retval ID_FIELD_VALID on success.
409  * \retval ID_FIELD_UNKNOWN on unknown field name.
410  */
411 static enum ID_FIELD_STATUS party_number_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_number *number)
412 {
413         enum ID_FIELD_STATUS status;
414
415         status = ID_FIELD_VALID;
416
417         if (argc == 0) {
418                 /* We want the number string */
419                 if (number->valid && number->str) {
420                         ast_copy_string(buf, number->str, len);
421                 }
422         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
423                 snprintf(buf, len, "%d", number->valid);
424         } else if (argc == 1 && !strcasecmp("plan", argv[0])) {
425                 snprintf(buf, len, "%d", number->plan);
426         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
427                 /* Accept pres[entation] */
428                 ast_copy_string(buf, ast_named_caller_presentation(number->presentation), len);
429         } else {
430                 status = ID_FIELD_UNKNOWN;
431         }
432
433         return status;
434 }
435
436 /*!
437  * \internal
438  * \brief Read values from the party subaddress struct.
439  * \since 1.8
440  *
441  * \param buf Buffer to fill with read value.
442  * \param len Length of the buffer.
443  * \param argc Number of party member subnames.
444  * \param argv Party member subnames given.
445  * \param subaddress Party subaddress to get values from.
446  *
447  * \retval ID_FIELD_VALID on success.
448  * \retval ID_FIELD_UNKNOWN on unknown field name.
449  */
450 static enum ID_FIELD_STATUS party_subaddress_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_subaddress *subaddress)
451 {
452         enum ID_FIELD_STATUS status;
453
454         status = ID_FIELD_VALID;
455
456         if (argc == 0) {
457                 /* We want the subaddress string */
458                 if (subaddress->str) {
459                         ast_copy_string(buf, subaddress->str, len);
460                 }
461         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
462                 snprintf(buf, len, "%d", subaddress->valid);
463         } else if (argc == 1 && !strcasecmp("type", argv[0])) {
464                 snprintf(buf, len, "%d", subaddress->type);
465         } else if (argc == 1 && !strcasecmp("odd", argv[0])) {
466                 snprintf(buf, len, "%d", subaddress->odd_even_indicator);
467         } else {
468                 status = ID_FIELD_UNKNOWN;
469         }
470
471         return status;
472 }
473
474 /*!
475  * \internal
476  * \brief Read values from the party id struct.
477  * \since 1.8
478  *
479  * \param buf Buffer to fill with read value.
480  * \param len Length of the buffer.
481  * \param argc Number of party member subnames.
482  * \param argv Party member subnames given.
483  * \param id Party id to get values from.
484  *
485  * \retval ID_FIELD_VALID on success.
486  * \retval ID_FIELD_UNKNOWN on unknown field name.
487  */
488 static enum ID_FIELD_STATUS party_id_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_id *id)
489 {
490         enum ID_FIELD_STATUS status;
491
492         if (argc == 0) {
493                 /* Must have at least one subname. */
494                 return ID_FIELD_UNKNOWN;
495         }
496
497         status = ID_FIELD_VALID;
498
499         if (argc == 1 && !strcasecmp("all", argv[0])) {
500                 snprintf(buf, len, "\"%s\" <%s>",
501                          S_COR(id->name.valid, id->name.str, ""),
502                          S_COR(id->number.valid, id->number.str, ""));
503         } else if (!strcasecmp("name", argv[0])) {
504                 status = party_name_read(buf, len, argc - 1, argv + 1, &id->name);
505         } else if (!strncasecmp("num", argv[0], 3)) {
506                 /* Accept num[ber] */
507                 status = party_number_read(buf, len, argc - 1, argv + 1, &id->number);
508         } else if (!strncasecmp("subaddr", argv[0], 7)) {
509                 /* Accept subaddr[ess] */
510                 status = party_subaddress_read(buf, len, argc - 1, argv + 1, &id->subaddress);
511         } else if (argc == 1 && !strcasecmp("tag", argv[0])) {
512                 if (id->tag) {
513                         ast_copy_string(buf, id->tag, len);
514                 }
515         } else if (argc == 1 && !strcasecmp("ton", argv[0])) {
516                 /* ton is an alias for num-plan */
517                 snprintf(buf, len, "%d", id->number.plan);
518         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
519                 /*
520                  * Accept pres[entation]
521                  * This is the combined name/number presentation.
522                  */
523                 ast_copy_string(buf,
524                         ast_named_caller_presentation(ast_party_id_presentation(id)), len);
525         } else {
526                 status = ID_FIELD_UNKNOWN;
527         }
528
529         return status;
530 }
531
532 /*!
533  * \internal
534  * \brief Write new values to the party name struct
535  * \since 1.8
536  *
537  * \param name Party name struct to write values
538  * \param argc Number of party member subnames.
539  * \param argv Party member subnames given.
540  * \param value Value to assign to the party name.
541  *
542  * \retval ID_FIELD_VALID on success.
543  * \retval ID_FIELD_INVALID on error with field value.
544  * \retval ID_FIELD_UNKNOWN on unknown field name.
545  */
546 static enum ID_FIELD_STATUS party_name_write(struct ast_party_name *name, int argc, char *argv[], const char *value)
547 {
548         char *val;
549         enum ID_FIELD_STATUS status;
550
551         status = ID_FIELD_VALID;
552
553         if (argc == 0) {
554                 /* We are setting the name string */
555                 name->valid = 1;
556                 name->str = ast_strdup(value);
557                 ast_trim_blanks(name->str);
558         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
559                 name->valid = atoi(value) ? 1 : 0;
560         } else if (argc == 1 && !strcasecmp("charset", argv[0])) {
561                 int char_set;
562
563                 val = ast_strdupa(value);
564                 ast_trim_blanks(val);
565
566                 if (('0' <= val[0]) && (val[0] <= '9')) {
567                         char_set = atoi(val);
568                 } else {
569                         char_set = ast_party_name_charset_parse(val);
570                 }
571
572                 if (char_set < 0) {
573                         ast_log(LOG_ERROR,
574                                 "Unknown name char-set '%s', value unchanged\n", val);
575                         status = ID_FIELD_INVALID;
576                 } else {
577                         name->char_set = char_set;
578                 }
579         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
580                 int pres;
581
582                 /* Accept pres[entation] */
583                 val = ast_strdupa(value);
584                 ast_trim_blanks(val);
585
586                 if (('0' <= val[0]) && (val[0] <= '9')) {
587                         pres = atoi(val);
588                 } else {
589                         pres = ast_parse_caller_presentation(val);
590                 }
591
592                 if (pres < 0) {
593                         ast_log(LOG_ERROR,
594                                 "Unknown name presentation '%s', value unchanged\n", val);
595                         status = ID_FIELD_INVALID;
596                 } else {
597                         name->presentation = pres;
598                 }
599         } else {
600                 status = ID_FIELD_UNKNOWN;
601         }
602
603         return status;
604 }
605
606 /*!
607  * \internal
608  * \brief Write new values to the party number struct
609  * \since 1.8
610  *
611  * \param number Party number struct to write values
612  * \param argc Number of party member subnames.
613  * \param argv Party member subnames given.
614  * \param value Value to assign to the party number.
615  *
616  * \retval ID_FIELD_VALID on success.
617  * \retval ID_FIELD_INVALID on error with field value.
618  * \retval ID_FIELD_UNKNOWN on unknown field name.
619  */
620 static enum ID_FIELD_STATUS party_number_write(struct ast_party_number *number, int argc, char *argv[], const char *value)
621 {
622         char *val;
623         enum ID_FIELD_STATUS status;
624
625         status = ID_FIELD_VALID;
626
627         if (argc == 0) {
628                 /* We are setting the number string */
629                 number->valid = 1;
630                 number->str = ast_strdup(value);
631                 ast_trim_blanks(number->str);
632         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
633                 number->valid = atoi(value) ? 1 : 0;
634         } else if (argc == 1 && !strcasecmp("plan", argv[0])) {
635                 val = ast_strdupa(value);
636                 ast_trim_blanks(val);
637
638                 if (('0' <= val[0]) && (val[0] <= '9')) {
639                         number->plan = atoi(val);
640                 } else {
641                         ast_log(LOG_ERROR,
642                                 "Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
643                         status = ID_FIELD_INVALID;
644                 }
645         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
646                 int pres;
647
648                 /* Accept pres[entation] */
649                 val = ast_strdupa(value);
650                 ast_trim_blanks(val);
651
652                 if (('0' <= val[0]) && (val[0] <= '9')) {
653                         pres = atoi(val);
654                 } else {
655                         pres = ast_parse_caller_presentation(val);
656                 }
657
658                 if (pres < 0) {
659                         ast_log(LOG_ERROR,
660                                 "Unknown number presentation '%s', value unchanged\n", val);
661                         status = ID_FIELD_INVALID;
662                 } else {
663                         number->presentation = pres;
664                 }
665         } else {
666                 status = ID_FIELD_UNKNOWN;
667         }
668
669         return status;
670 }
671
672 /*!
673  * \internal
674  * \brief Write new values to the party subaddress struct
675  * \since 1.8
676  *
677  * \param subaddress Party subaddress struct to write values
678  * \param argc Number of party member subnames.
679  * \param argv Party member subnames given.
680  * \param value Value to assign to the party subaddress.
681  *
682  * \retval ID_FIELD_VALID on success.
683  * \retval ID_FIELD_INVALID on error with field value.
684  * \retval ID_FIELD_UNKNOWN on unknown field name.
685  */
686 static enum ID_FIELD_STATUS party_subaddress_write(struct ast_party_subaddress *subaddress, int argc, char *argv[], const char *value)
687 {
688         enum ID_FIELD_STATUS status;
689
690         status = ID_FIELD_VALID;
691
692         if (argc == 0) {
693                 /* We are setting the subaddress string */
694                 subaddress->str = ast_strdup(value);
695                 ast_trim_blanks(subaddress->str);
696         } else if (argc == 1 && !strcasecmp("valid", argv[0])) {
697                 subaddress->valid = atoi(value) ? 1 : 0;
698         } else if (argc == 1 && !strcasecmp("type", argv[0])) {
699                 subaddress->type = atoi(value) ? 2 : 0;
700         } else if (argc == 1 && !strcasecmp("odd", argv[0])) {
701                 subaddress->odd_even_indicator = atoi(value) ? 1 : 0;
702         } else {
703                 status = ID_FIELD_UNKNOWN;
704         }
705
706         return status;
707 }
708
709 /*!
710  * \internal
711  * \brief Write new values to the party id struct
712  * \since 1.8
713  *
714  * \param id Party ID struct to write values
715  * \param argc Number of party member subnames.
716  * \param argv Party member subnames given.
717  * \param value Value to assign to the party id.
718  *
719  * \retval ID_FIELD_VALID on success.
720  * \retval ID_FIELD_INVALID on error with field value.
721  * \retval ID_FIELD_UNKNOWN on unknown field name.
722  */
723 static enum ID_FIELD_STATUS party_id_write(struct ast_party_id *id, int argc, char *argv[], const char *value)
724 {
725         char *val;
726         enum ID_FIELD_STATUS status;
727
728         if (argc == 0) {
729                 /* Must have at least one subname. */
730                 return ID_FIELD_UNKNOWN;
731         }
732
733         status = ID_FIELD_VALID;
734
735         if (argc == 1 && !strcasecmp("all", argv[0])) {
736                 char name[256];
737                 char num[256];
738
739                 ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
740                 id->name.valid = 1;
741                 id->name.str = ast_strdup(name);
742                 if (!id->name.str) {
743                         return ID_FIELD_INVALID;
744                 }
745                 id->number.valid = 1;
746                 id->number.str = ast_strdup(num);
747                 if (!id->number.str) {
748                         return ID_FIELD_INVALID;
749                 }
750         } else if (!strcasecmp("name", argv[0])) {
751                 status = party_name_write(&id->name, argc - 1, argv + 1, value);
752         } else if (!strncasecmp("num", argv[0], 3)) {
753                 /* Accept num[ber] */
754                 status = party_number_write(&id->number, argc - 1, argv + 1, value);
755         } else if (!strncasecmp("subaddr", argv[0], 7)) {
756                 /* Accept subaddr[ess] */
757                 status = party_subaddress_write(&id->subaddress, argc - 1, argv + 1, value);
758         } else if (argc == 1 && !strcasecmp("tag", argv[0])) {
759                 id->tag = ast_strdup(value);
760                 ast_trim_blanks(id->tag);
761         } else if (argc == 1 && !strcasecmp("ton", argv[0])) {
762                 /* ton is an alias for num-plan */
763                 argv[0] = "plan";
764                 status = party_number_write(&id->number, argc, argv, value);
765         } else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
766                 int pres;
767
768                 /*
769                  * Accept pres[entation]
770                  * This is the combined name/number presentation.
771                  */
772                 val = ast_strdupa(value);
773                 ast_trim_blanks(val);
774
775                 if (('0' <= val[0]) && (val[0] <= '9')) {
776                         pres = atoi(val);
777                 } else {
778                         pres = ast_parse_caller_presentation(val);
779                 }
780
781                 if (pres < 0) {
782                         ast_log(LOG_ERROR,
783                                 "Unknown combined presentation '%s', value unchanged\n", val);
784                         status = ID_FIELD_INVALID;
785                 } else {
786                         id->name.presentation = pres;
787                         id->number.presentation = pres;
788                 }
789         } else {
790                 status = ID_FIELD_UNKNOWN;
791         }
792
793         return status;
794 }
795
796 /*! TRUE if we have already notified about CALLERPRES being deprecated. */
797 static int callerpres_deprecate_notify;
798
799 /*!
800  * \internal
801  * \brief Read values from the caller-id presentation information struct.
802  *
803  * \param chan Asterisk channel to read
804  * \param cmd Not used
805  * \param data Caller-id presentation function datatype string
806  * \param buf Buffer to fill with read value.
807  * \param len Length of the buffer
808  *
809  * \retval 0 on success.
810  * \retval -1 on error.
811  */
812 static int callerpres_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
813 {
814         if (!callerpres_deprecate_notify) {
815                 callerpres_deprecate_notify = 1;
816                 ast_log(LOG_WARNING, "CALLERPRES is deprecated."
817                         "  Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
818         }
819         ast_copy_string(buf,
820                 ast_named_caller_presentation(ast_party_id_presentation(&chan->caller.id)), len);
821         return 0;
822 }
823
824 /*!
825  * \internal
826  * \brief Write new values to the caller-id presentation information struct.
827  *
828  * \param chan Asterisk channel to update
829  * \param cmd Not used
830  * \param data Caller-id presentation function datatype string
831  * \param value Value to assign to the caller-id presentation information struct.
832  *
833  * \retval 0 on success.
834  * \retval -1 on error.
835  */
836 static int callerpres_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
837 {
838         int pres;
839
840         if (!callerpres_deprecate_notify) {
841                 callerpres_deprecate_notify = 1;
842                 ast_log(LOG_WARNING, "CALLERPRES is deprecated."
843                         "  Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
844         }
845
846         pres = ast_parse_caller_presentation(value);
847         if (pres < 0) {
848                 ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show function CALLERPRES')\n", value);
849         } else {
850                 chan->caller.id.name.presentation = pres;
851                 chan->caller.id.number.presentation = pres;
852         }
853         return 0;
854 }
855
856 /*!
857  * \internal
858  * \brief Read values from the caller-id information struct.
859  *
860  * \param chan Asterisk channel to read
861  * \param cmd Not used
862  * \param data Caller-id function datatype string
863  * \param buf Buffer to fill with read value.
864  * \param len Length of the buffer
865  *
866  * \retval 0 on success.
867  * \retval -1 on error.
868  */
869 static int callerid_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
870 {
871         enum ID_FIELD_STATUS status;
872         char *parms;
873         struct ast_party_members member;
874         AST_DECLARE_APP_ARGS(args,
875                 AST_APP_ARG(member);    /*!< Member name */
876                 AST_APP_ARG(cid);               /*!< Optional caller id to parse instead of from the channel. */
877                 );
878
879         /* Ensure that the buffer is empty */
880         *buf = 0;
881
882         if (!chan) {
883                 return -1;
884         }
885
886         parms = ast_strdupa(data);
887         AST_STANDARD_APP_ARGS(args, parms);
888         if (args.argc == 0) {
889                 /* Must have at least one argument. */
890                 return -1;
891         }
892
893         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
894         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
895                 /* Too few or too many subnames */
896                 return -1;
897         }
898
899         if (args.argc == 2) {
900                 char name[80];
901                 char num[80];
902
903                 ast_callerid_split(args.cid, name, sizeof(name), num, sizeof(num));
904
905                 if (member.argc == 1 && !strcasecmp("all", member.argv[0])) {
906                         snprintf(buf, len, "\"%s\" <%s>", name, num);
907                 } else if (member.argc == 1 && !strcasecmp("name", member.argv[0])) {
908                         ast_copy_string(buf, name, len);
909                 } else if (member.argc == 1 && !strncasecmp("num", member.argv[0], 3)) {
910                         /* Accept num[ber] */
911                         ast_copy_string(buf, num, len);
912                 } else {
913                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
914                 }
915         } else {
916                 ast_channel_lock(chan);
917
918                 if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
919                         if (chan->redirecting.from.number.valid
920                                 && chan->redirecting.from.number.str) {
921                                 ast_copy_string(buf, chan->redirecting.from.number.str, len);
922                         }
923                 } else if (!strcasecmp("dnid", member.argv[0])) {
924                         if (member.argc == 1) {
925                                 /* Setup as if user had given dnid-num instead. */
926                                 member.argc = 2;
927                                 member.argv[1] = "num";
928                         }
929                         if (!strncasecmp("num", member.argv[1], 3)) {
930                                 /*
931                                  * Accept num[ber]
932                                  * dnid-num...
933                                  */
934                                 if (member.argc == 2) {
935                                         /* dnid-num */
936                                         if (chan->dialed.number.str) {
937                                                 ast_copy_string(buf, chan->dialed.number.str, len);
938                                         }
939                                 } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
940                                         /* dnid-num-plan */
941                                         snprintf(buf, len, "%d", chan->dialed.number.plan);
942                                 } else {
943                                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
944                                 }
945                         } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
946                                 /*
947                                  * Accept subaddr[ess]
948                                  * dnid-subaddr...
949                                  */
950                                 status = party_subaddress_read(buf, len, member.argc - 2, member.argv + 2,
951                                         &chan->dialed.subaddress);
952                                 switch (status) {
953                                 case ID_FIELD_VALID:
954                                 case ID_FIELD_INVALID:
955                                         break;
956                                 default:
957                                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
958                                         break;
959                                 }
960                         } else {
961                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
962                         }
963                 } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
964                         snprintf(buf, len, "%d", chan->caller.ani2);
965                 } else if (!strcasecmp("ani", member.argv[0])) {
966                         if (member.argc == 1) {
967                                 /* Setup as if user had given ani-num instead. */
968                                 member.argc = 2;
969                                 member.argv[1] = "num";
970                         }
971                         status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
972                                 &chan->caller.ani);
973                         switch (status) {
974                         case ID_FIELD_VALID:
975                         case ID_FIELD_INVALID:
976                                 break;
977                         default:
978                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
979                                 break;
980                         }
981                 } else {
982                         status = party_id_read(buf, len, member.argc, member.argv, &chan->caller.id);
983                         switch (status) {
984                         case ID_FIELD_VALID:
985                         case ID_FIELD_INVALID:
986                                 break;
987                         default:
988                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
989                                 break;
990                         }
991                 }
992
993                 ast_channel_unlock(chan);
994         }
995
996         return 0;
997 }
998
999 /*!
1000  * \internal
1001  * \brief Write new values to the caller-id information struct.
1002  *
1003  * \param chan Asterisk channel to update
1004  * \param cmd Not used
1005  * \param data Caller-id function datatype string
1006  * \param value Value to assign to the caller-id information struct.
1007  *
1008  * \retval 0 on success.
1009  * \retval -1 on error.
1010  */
1011 static int callerid_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1012 {
1013         struct ast_party_caller caller;
1014         struct ast_party_dialed dialed;
1015         enum ID_FIELD_STATUS status;
1016         char *val;
1017         char *parms;
1018         struct ast_party_func_args args;
1019         struct ast_party_members member;
1020
1021         if (!value || !chan) {
1022                 return -1;
1023         }
1024
1025         parms = ast_strdupa(data);
1026         AST_STANDARD_APP_ARGS(args, parms);
1027         if (args.argc == 0) {
1028                 /* Must have at least one argument. */
1029                 return -1;
1030         }
1031
1032         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
1033         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1034                 /* Too few or too many subnames */
1035                 return -1;
1036         }
1037
1038         value = ast_skip_blanks(value);
1039
1040         ast_channel_lock(chan);
1041         if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
1042                 chan->redirecting.from.number.valid = 1;
1043                 ast_free(chan->redirecting.from.number.str);
1044                 chan->redirecting.from.number.str = ast_strdup(value);
1045                 if (chan->cdr) {
1046                         ast_cdr_setcid(chan->cdr, chan);
1047                 }
1048         } else if (!strcasecmp("dnid", member.argv[0])) {
1049                 ast_party_dialed_set_init(&dialed, &chan->dialed);
1050                 if (member.argc == 1) {
1051                         /* Setup as if user had given dnid-num instead. */
1052                         member.argc = 2;
1053                         member.argv[1] = "num";
1054                 }
1055                 if (!strncasecmp("num", member.argv[1], 3)) {
1056                         /*
1057                          * Accept num[ber]
1058                          * dnid-num...
1059                          */
1060                         if (member.argc == 2) {
1061                                 /* dnid-num */
1062                                 dialed.number.str = ast_strdup(value);
1063                                 ast_trim_blanks(dialed.number.str);
1064                                 ast_party_dialed_set(&chan->dialed, &dialed);
1065                                 if (chan->cdr) {
1066                                         ast_cdr_setcid(chan->cdr, chan);
1067                                 }
1068                         } else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
1069                                 /* dnid-num-plan */
1070                                 val = ast_strdupa(value);
1071                                 ast_trim_blanks(val);
1072
1073                                 if (('0' <= val[0]) && (val[0] <= '9')) {
1074                                         chan->dialed.number.plan = atoi(val);
1075                                         if (chan->cdr) {
1076                                                 ast_cdr_setcid(chan->cdr, chan);
1077                                         }
1078                                 } else {
1079                                         ast_log(LOG_ERROR,
1080                                                 "Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
1081                                 }
1082                         } else {
1083                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1084                         }
1085                 } else if (!strncasecmp("subaddr", member.argv[1], 7)) {
1086                         /*
1087                          * Accept subaddr[ess]
1088                          * dnid-subaddr...
1089                          */
1090                         status = party_subaddress_write(&dialed.subaddress, member.argc - 2,
1091                                 member.argv + 2, value);
1092                         switch (status) {
1093                         case ID_FIELD_VALID:
1094                                 ast_party_dialed_set(&chan->dialed, &dialed);
1095                                 if (chan->cdr) {
1096                                         ast_cdr_setcid(chan->cdr, chan);
1097                                 }
1098                                 break;
1099                         case ID_FIELD_INVALID:
1100                                 break;
1101                         default:
1102                                 ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1103                                 break;
1104                         }
1105                 } else {
1106                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1107                 }
1108                 ast_party_dialed_free(&dialed);
1109         } else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
1110                 val = ast_strdupa(value);
1111                 ast_trim_blanks(val);
1112
1113                 if (('0' <= val[0]) && (val[0] <= '9')) {
1114                         chan->caller.ani2 = atoi(val);
1115                         if (chan->cdr) {
1116                                 ast_cdr_setcid(chan->cdr, chan);
1117                         }
1118                 } else {
1119                         ast_log(LOG_ERROR, "Unknown callerid ani2 '%s', value unchanged\n", val);
1120                 }
1121         } else if (!strcasecmp("ani", member.argv[0])) {
1122                 ast_party_caller_set_init(&caller, &chan->caller);
1123                 if (member.argc == 1) {
1124                         /* Setup as if user had given ani-num instead. */
1125                         member.argc = 2;
1126                         member.argv[1] = "num";
1127                 }
1128                 status = party_id_write(&caller.ani, member.argc - 1, member.argv + 1, value);
1129                 switch (status) {
1130                 case ID_FIELD_VALID:
1131                         ast_party_caller_set(&chan->caller, &caller, NULL);
1132                         if (chan->cdr) {
1133                                 ast_cdr_setcid(chan->cdr, chan);
1134                         }
1135                         break;
1136                 case ID_FIELD_INVALID:
1137                         break;
1138                 default:
1139                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1140                         break;
1141                 }
1142                 ast_party_caller_free(&caller);
1143         } else {
1144                 ast_party_caller_set_init(&caller, &chan->caller);
1145                 status = party_id_write(&caller.id, member.argc, member.argv, value);
1146                 switch (status) {
1147                 case ID_FIELD_VALID:
1148                         ast_channel_set_caller_event(chan, &caller, NULL);
1149                         if (chan->cdr) {
1150                                 ast_cdr_setcid(chan->cdr, chan);
1151                         }
1152                         break;
1153                 case ID_FIELD_INVALID:
1154                         break;
1155                 default:
1156                         ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
1157                         break;
1158                 }
1159                 ast_party_caller_free(&caller);
1160         }
1161         ast_channel_unlock(chan);
1162
1163         return 0;
1164 }
1165
1166 /*!
1167  * \internal
1168  * \brief Read values from the connected line information struct.
1169  *
1170  * \param chan Asterisk channel to read
1171  * \param cmd Not used
1172  * \param data Connected line function datatype string
1173  * \param buf Buffer to fill with read value.
1174  * \param len Length of the buffer
1175  *
1176  * \retval 0 on success.
1177  * \retval -1 on error.
1178  */
1179 static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1180 {
1181         struct ast_party_members member;
1182         char *read_what;
1183         enum ID_FIELD_STATUS status;
1184
1185         /* Ensure that the buffer is empty */
1186         *buf = 0;
1187
1188         if (!chan) {
1189                 return -1;
1190         }
1191
1192         read_what = ast_strdupa(data);
1193         AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
1194         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1195                 /* Too few or too many subnames */
1196                 return -1;
1197         }
1198
1199         ast_channel_lock(chan);
1200
1201         if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
1202                 ast_copy_string(buf, ast_connected_line_source_name(chan->connected.source), len);
1203         } else {
1204                 status = party_id_read(buf, len, member.argc, member.argv, &chan->connected.id);
1205                 switch (status) {
1206                 case ID_FIELD_VALID:
1207                 case ID_FIELD_INVALID:
1208                         break;
1209                 default:
1210                         ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
1211                         break;
1212                 }
1213         }
1214
1215         ast_channel_unlock(chan);
1216
1217         return 0;
1218 }
1219
1220 /*!
1221  * \internal
1222  * \brief Write new values to the connected line information struct.
1223  *
1224  * \param chan Asterisk channel to update
1225  * \param cmd Not used
1226  * \param data Connected line function datatype string
1227  * \param value Value to assign to the connected line information struct.
1228  *
1229  * \retval 0 on success.
1230  * \retval -1 on error.
1231  */
1232 static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1233 {
1234         struct ast_party_connected_line connected;
1235         enum ID_FIELD_STATUS status;
1236         char *val;
1237         char *parms;
1238         void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update);
1239         struct ast_party_func_args args;
1240         struct ast_party_members member;
1241         struct ast_flags opts;
1242         char *opt_args[CONNECTED_LINE_OPT_ARG_ARRAY_SIZE];
1243
1244         if (!value || !chan) {
1245                 return -1;
1246         }
1247
1248         parms = ast_strdupa(data);
1249         AST_STANDARD_APP_ARGS(args, parms);
1250         if (args.argc == 0) {
1251                 /* Must have at least one argument. */
1252                 return -1;
1253         }
1254
1255         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
1256         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1257                 /* Too few or too many subnames */
1258                 return -1;
1259         }
1260
1261         if (ast_app_parse_options(connectedline_opts, &opts, opt_args, args.opts)) {
1262                 /* General invalid option syntax. */
1263                 return -1;
1264         }
1265
1266         /* Determine if the update indication inhibit option is present */
1267         if (ast_test_flag(&opts, CONNECTED_LINE_OPT_INHIBIT)) {
1268                 set_it = ast_channel_set_connected_line;
1269         } else {
1270                 set_it = ast_channel_update_connected_line;
1271         }
1272
1273         ast_channel_lock(chan);
1274         ast_party_connected_line_set_init(&connected, &chan->connected);
1275         ast_channel_unlock(chan);
1276
1277         value = ast_skip_blanks(value);
1278
1279         if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
1280                 int source;
1281
1282                 val = ast_strdupa(value);
1283                 ast_trim_blanks(val);
1284
1285                 if (('0' <= val[0]) && (val[0] <= '9')) {
1286                         source = atoi(val);
1287                 } else {
1288                         source = ast_connected_line_source_parse(val);
1289                 }
1290
1291                 if (source < 0) {
1292                         ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val);
1293                 } else {
1294                         connected.source = source;
1295                         set_it(chan, &connected, NULL);
1296                 }
1297         } else {
1298                 status = party_id_write(&connected.id, member.argc, member.argv, value);
1299                 switch (status) {
1300                 case ID_FIELD_VALID:
1301                         set_it(chan, &connected, NULL);
1302                         break;
1303                 case ID_FIELD_INVALID:
1304                         break;
1305                 default:
1306                         ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
1307                         break;
1308                 }
1309                 ast_party_connected_line_free(&connected);
1310         }
1311
1312         return 0;
1313 }
1314
1315 /*!
1316  * \internal
1317  * \brief Read values from the redirecting information struct.
1318  *
1319  * \param chan Asterisk channel to read
1320  * \param cmd Not used
1321  * \param data Redirecting function datatype string
1322  * \param buf Buffer to fill with read value.
1323  * \param len Length of the buffer
1324  *
1325  * \retval 0 on success.
1326  * \retval -1 on error.
1327  */
1328 static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
1329 {
1330         struct ast_party_members member;
1331         char *read_what;
1332         enum ID_FIELD_STATUS status;
1333
1334         /* Ensure that the buffer is empty */
1335         *buf = 0;
1336
1337         if (!chan) {
1338                 return -1;
1339         }
1340
1341         read_what = ast_strdupa(data);
1342         AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
1343         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1344                 /* Too few or too many subnames */
1345                 return -1;
1346         }
1347
1348         ast_channel_lock(chan);
1349
1350         if (!strcasecmp("from", member.argv[0])) {
1351                 status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1352                         &chan->redirecting.from);
1353                 switch (status) {
1354                 case ID_FIELD_VALID:
1355                 case ID_FIELD_INVALID:
1356                         break;
1357                 default:
1358                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1359                         break;
1360                 }
1361         } else if (!strcasecmp("to", member.argv[0])) {
1362                 status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
1363                         &chan->redirecting.to);
1364                 switch (status) {
1365                 case ID_FIELD_VALID:
1366                 case ID_FIELD_INVALID:
1367                         break;
1368                 default:
1369                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1370                         break;
1371                 }
1372         } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
1373                 /*
1374                  * Accept pres[entation]
1375                  * This is the combined from name/number presentation.
1376                  */
1377                 ast_copy_string(buf,
1378                         ast_named_caller_presentation(
1379                                 ast_party_id_presentation(&chan->redirecting.from)), len);
1380         } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
1381                 ast_copy_string(buf, ast_redirecting_reason_name(chan->redirecting.reason), len);
1382         } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
1383                 snprintf(buf, len, "%d", chan->redirecting.count);
1384         } else {
1385                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1386         }
1387
1388         ast_channel_unlock(chan);
1389
1390         return 0;
1391 }
1392
1393 /*!
1394  * \internal
1395  * \brief Write new values to the redirecting information struct.
1396  *
1397  * \param chan Asterisk channel to update
1398  * \param cmd Not used
1399  * \param data Redirecting function datatype string
1400  * \param value Value to assign to the redirecting information struct.
1401  *
1402  * \retval 0 on success.
1403  * \retval -1 on error.
1404  */
1405 static int redirecting_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
1406 {
1407         struct ast_party_redirecting redirecting;
1408         enum ID_FIELD_STATUS status;
1409         char *val;
1410         char *parms;
1411         void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update);
1412         struct ast_party_func_args args;
1413         struct ast_party_members member;
1414         struct ast_flags opts;
1415         char *opt_args[REDIRECTING_OPT_ARG_ARRAY_SIZE];
1416
1417         if (!value || !chan) {
1418                 return -1;
1419         }
1420
1421         parms = ast_strdupa(data);
1422         AST_STANDARD_APP_ARGS(args, parms);
1423         if (args.argc == 0) {
1424                 /* Must have at least one argument. */
1425                 return -1;
1426         }
1427
1428         AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
1429         if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
1430                 /* Too few or too many subnames */
1431                 return -1;
1432         }
1433
1434         if (ast_app_parse_options(redirecting_opts, &opts, opt_args, args.opts)) {
1435                 /* General invalid option syntax. */
1436                 return -1;
1437         }
1438
1439         /* Determine if the update indication inhibit option is present */
1440         if (ast_test_flag(&opts, REDIRECTING_OPT_INHIBIT)) {
1441                 set_it = ast_channel_set_redirecting;
1442         } else {
1443                 set_it = ast_channel_update_redirecting;
1444         }
1445
1446         ast_channel_lock(chan);
1447         ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
1448         ast_channel_unlock(chan);
1449
1450         value = ast_skip_blanks(value);
1451
1452         if (!strcasecmp("from", member.argv[0])) {
1453                 status = party_id_write(&redirecting.from, member.argc - 1, member.argv + 1,
1454                         value);
1455                 switch (status) {
1456                 case ID_FIELD_VALID:
1457                         set_it(chan, &redirecting, NULL);
1458                         break;
1459                 case ID_FIELD_INVALID:
1460                         break;
1461                 default:
1462                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1463                         break;
1464                 }
1465                 ast_party_redirecting_free(&redirecting);
1466         } else if (!strcasecmp("to", member.argv[0])) {
1467                 status = party_id_write(&redirecting.to, member.argc - 1, member.argv + 1, value);
1468                 switch (status) {
1469                 case ID_FIELD_VALID:
1470                         set_it(chan, &redirecting, NULL);
1471                         break;
1472                 case ID_FIELD_INVALID:
1473                         break;
1474                 default:
1475                         ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1476                         break;
1477                 }
1478                 ast_party_redirecting_free(&redirecting);
1479         } else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
1480                 int pres;
1481
1482                 val = ast_strdupa(value);
1483                 ast_trim_blanks(val);
1484
1485                 if (('0' <= val[0]) && (val[0] <= '9')) {
1486                         pres = atoi(val);
1487                 } else {
1488                         pres = ast_parse_caller_presentation(val);
1489                 }
1490
1491                 if (pres < 0) {
1492                         ast_log(LOG_ERROR,
1493                                 "Unknown redirecting combined presentation '%s', value unchanged\n", val);
1494                 } else {
1495                         redirecting.from.name.presentation = pres;
1496                         redirecting.from.number.presentation = pres;
1497                         redirecting.to.name.presentation = pres;
1498                         redirecting.to.number.presentation = pres;
1499                         set_it(chan, &redirecting, NULL);
1500                 }
1501         } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
1502                 int reason;
1503
1504                 val = ast_strdupa(value);
1505                 ast_trim_blanks(val);
1506
1507                 if (('0' <= val[0]) && (val[0] <= '9')) {
1508                         reason = atoi(val);
1509                 } else {
1510                         reason = ast_redirecting_reason_parse(val);
1511                 }
1512
1513                 if (reason < 0) {
1514                         ast_log(LOG_ERROR, "Unknown redirecting reason '%s', value unchanged\n", val);
1515                 } else {
1516                         redirecting.reason = reason;
1517                         set_it(chan, &redirecting, NULL);
1518                 }
1519         } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
1520                 val = ast_strdupa(value);
1521                 ast_trim_blanks(val);
1522
1523                 if (('0' <= val[0]) && (val[0] <= '9')) {
1524                         redirecting.count = atoi(val);
1525                         set_it(chan, &redirecting, NULL);
1526                 } else {
1527                         ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val);
1528                 }
1529         } else {
1530                 ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
1531         }
1532
1533         return 0;
1534 }
1535
1536 static struct ast_custom_function callerid_function = {
1537         .name = "CALLERID",
1538         .read = callerid_read,
1539         .read_max = 256,
1540         .write = callerid_write,
1541 };
1542
1543 static struct ast_custom_function callerpres_function = {
1544         .name = "CALLERPRES",
1545         .read = callerpres_read,
1546         .read_max = 50,
1547         .write = callerpres_write,
1548 };
1549
1550 static struct ast_custom_function connectedline_function = {
1551         .name = "CONNECTEDLINE",
1552         .read = connectedline_read,
1553         .write = connectedline_write,
1554 };
1555
1556 static struct ast_custom_function redirecting_function = {
1557         .name = "REDIRECTING",
1558         .read = redirecting_read,
1559         .write = redirecting_write,
1560 };
1561
1562 /*!
1563  * \internal
1564  * \brief Unload the function module
1565  *
1566  * \retval 0 on success.
1567  * \retval -1 on error.
1568  */
1569 static int unload_module(void)
1570 {
1571         int res;
1572
1573         res = ast_custom_function_unregister(&callerpres_function);
1574         res |= ast_custom_function_unregister(&callerid_function);
1575         res |= ast_custom_function_unregister(&connectedline_function);
1576         res |= ast_custom_function_unregister(&redirecting_function);
1577         return res;
1578 }
1579
1580 /*!
1581  * \internal
1582  * \brief Load and initialize the function module.
1583  *
1584  * \retval AST_MODULE_LOAD_SUCCESS on success.
1585  * \retval AST_MODULE_LOAD_DECLINE on error.
1586  */
1587 static int load_module(void)
1588 {
1589         int res;
1590
1591         res = ast_custom_function_register(&callerpres_function);
1592         res |= ast_custom_function_register(&callerid_function);
1593         res |= ast_custom_function_register(&connectedline_function);
1594         res |= ast_custom_function_register(&redirecting_function);
1595         return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
1596 }
1597
1598 /* Do not wrap the following line. */
1599 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)");