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