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