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 #include "asterisk.h"
00029
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 293158 $")
00031
00032 #include <regex.h>
00033 #include <ctype.h>
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/localtime.h"
00041
00042 AST_THREADSTORAGE(result_buf);
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 static int function_fieldqty(struct ast_channel *chan, const char *cmd,
00293 char *parse, char *buf, size_t len)
00294 {
00295 char *varsubst, varval[8192], *varval2 = varval;
00296 int fieldcount = 0;
00297 AST_DECLARE_APP_ARGS(args,
00298 AST_APP_ARG(varname);
00299 AST_APP_ARG(delim);
00300 );
00301 char delim[2] = "";
00302 size_t delim_used;
00303
00304 AST_STANDARD_APP_ARGS(args, parse);
00305 if (args.delim) {
00306 ast_get_encoded_char(args.delim, delim, &delim_used);
00307
00308 varsubst = alloca(strlen(args.varname) + 4);
00309
00310 sprintf(varsubst, "${%s}", args.varname);
00311 pbx_substitute_variables_helper(chan, varsubst, varval, sizeof(varval) - 1);
00312 if (ast_strlen_zero(varval2))
00313 fieldcount = 0;
00314 else {
00315 while (strsep(&varval2, delim))
00316 fieldcount++;
00317 }
00318 } else {
00319 fieldcount = 1;
00320 }
00321 snprintf(buf, len, "%d", fieldcount);
00322
00323 return 0;
00324 }
00325
00326 static struct ast_custom_function fieldqty_function = {
00327 .name = "FIELDQTY",
00328 .read = function_fieldqty,
00329 };
00330
00331 static int listfilter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
00332 {
00333 AST_DECLARE_APP_ARGS(args,
00334 AST_APP_ARG(listname);
00335 AST_APP_ARG(delimiter);
00336 AST_APP_ARG(fieldvalue);
00337 );
00338 const char *orig_list, *ptr;
00339 const char *begin, *cur, *next;
00340 int dlen, flen, first = 1;
00341 struct ast_str *result = ast_str_thread_get(&result_buf, 16);
00342 char *delim;
00343
00344 AST_STANDARD_APP_ARGS(args, parse);
00345
00346 if (args.argc < 3) {
00347 ast_log(LOG_ERROR, "Usage: LISTFILTER(<listname>,<delimiter>,<fieldvalue>)\n");
00348 return -1;
00349 }
00350
00351
00352 if (chan) {
00353 ast_channel_lock(chan);
00354 }
00355 if (!(orig_list = pbx_builtin_getvar_helper(chan, args.listname))) {
00356 ast_log(LOG_ERROR, "List variable '%s' not found\n", args.listname);
00357 if (chan) {
00358 ast_channel_unlock(chan);
00359 }
00360 return -1;
00361 }
00362
00363
00364 if (!(ptr = strstr(orig_list, args.fieldvalue))) {
00365 ast_copy_string(buf, orig_list, len);
00366 if (chan) {
00367 ast_channel_unlock(chan);
00368 }
00369 return 0;
00370 }
00371
00372 dlen = strlen(args.delimiter);
00373 delim = alloca(dlen + 1);
00374 ast_get_encoded_str(args.delimiter, delim, dlen + 1);
00375
00376 if ((dlen = strlen(delim)) == 0) {
00377 delim = ",";
00378 dlen = 1;
00379 }
00380
00381 flen = strlen(args.fieldvalue);
00382
00383 ast_str_reset(result);
00384
00385 ast_str_make_space(&result, strlen(orig_list) + 1);
00386
00387 begin = orig_list;
00388 next = strstr(begin, delim);
00389
00390 do {
00391
00392 if (next) {
00393 cur = next;
00394 next = strstr(cur + dlen, delim);
00395 } else {
00396 cur = strchr(begin + dlen, '\0');
00397 }
00398
00399 if (flen == cur - begin && !strncmp(begin, args.fieldvalue, flen)) {
00400
00401 begin += flen + dlen;
00402 } else {
00403
00404 if (!first) {
00405 ast_str_append(&result, 0, "%s", delim);
00406 }
00407
00408 ast_str_append_substr(&result, 0, begin, cur - begin);
00409 first = 0;
00410 begin = cur + dlen;
00411 }
00412 } while (*cur != '\0');
00413 if (chan) {
00414 ast_channel_unlock(chan);
00415 }
00416
00417 ast_copy_string(buf, ast_str_buffer(result), len);
00418
00419 return 0;
00420 }
00421
00422 static struct ast_custom_function listfilter_function = {
00423 .name = "LISTFILTER",
00424 .read = listfilter,
00425 };
00426
00427 static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf,
00428 size_t len)
00429 {
00430 AST_DECLARE_APP_ARGS(args,
00431 AST_APP_ARG(allowed);
00432 AST_APP_ARG(string);
00433 );
00434 char *outbuf = buf;
00435 unsigned char ac;
00436 char allowed[256] = "";
00437 size_t allowedlen = 0;
00438 int32_t bitfield[8] = { 0, };
00439
00440 AST_STANDARD_RAW_ARGS(args, parse);
00441
00442 if (!args.string) {
00443 ast_log(LOG_ERROR, "Usage: FILTER(<allowed-chars>,<string>)\n");
00444 return -1;
00445 }
00446
00447 if (args.allowed[0] == '"' && !ast_opt_dont_warn) {
00448 ast_log(LOG_WARNING, "FILTER allowed characters includes the quote (\") character. This may not be what you want.\n");
00449 }
00450
00451
00452 for (; *(args.allowed);) {
00453 char c1 = 0, c2 = 0;
00454 size_t consumed = 0;
00455
00456 if (ast_get_encoded_char(args.allowed, &c1, &consumed))
00457 return -1;
00458 args.allowed += consumed;
00459
00460 if (*(args.allowed) == '-') {
00461 if (ast_get_encoded_char(args.allowed + 1, &c2, &consumed))
00462 c2 = c1;
00463 args.allowed += consumed + 1;
00464
00465 if ((unsigned char) c2 < (unsigned char) c1 && !ast_opt_dont_warn) {
00466 ast_log(LOG_WARNING, "Range wrapping in FILTER(%s,%s). This may not be what you want.\n", parse, args.string);
00467 }
00468
00469
00470
00471
00472
00473 for (ac = (unsigned char) c1; ac != (unsigned char) c2; ac++) {
00474 bitfield[ac / 32] |= 1 << (ac % 32);
00475 }
00476 bitfield[ac / 32] |= 1 << (ac % 32);
00477
00478 ast_debug(4, "c1=%d, c2=%d\n", c1, c2);
00479 } else {
00480 ac = (unsigned char) c1;
00481 ast_debug(4, "c1=%d, consumed=%d, args.allowed=%s\n", c1, (int) consumed, args.allowed - consumed);
00482 bitfield[ac / 32] |= 1 << (ac % 32);
00483 }
00484 }
00485
00486 for (ac = 1; ac != 0; ac++) {
00487 if (bitfield[ac / 32] & (1 << (ac % 32))) {
00488 allowed[allowedlen++] = ac;
00489 }
00490 }
00491
00492 ast_debug(1, "Allowed: %s\n", allowed);
00493
00494 for (; *(args.string) && (buf + len - 1 > outbuf); (args.string)++) {
00495 if (strchr(allowed, *(args.string)))
00496 *outbuf++ = *(args.string);
00497 }
00498 *outbuf = '\0';
00499
00500 return 0;
00501 }
00502
00503 static struct ast_custom_function filter_function = {
00504 .name = "FILTER",
00505 .read = filter,
00506 };
00507
00508 static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf,
00509 size_t len)
00510 {
00511 AST_DECLARE_APP_ARGS(args,
00512 AST_APP_ARG(null);
00513 AST_APP_ARG(reg);
00514 AST_APP_ARG(str);
00515 );
00516 int errcode;
00517 regex_t regexbuf;
00518
00519 buf[0] = '\0';
00520
00521 AST_NONSTANDARD_APP_ARGS(args, parse, '"');
00522
00523 if (args.argc != 3) {
00524 ast_log(LOG_ERROR, "Unexpected arguments: should have been in the form '\"<regex>\" <string>'\n");
00525 return -1;
00526 }
00527 if ((*args.str == ' ') || (*args.str == '\t'))
00528 args.str++;
00529
00530 ast_debug(1, "FUNCTION REGEX (%s)(%s)\n", args.reg, args.str);
00531
00532 if ((errcode = regcomp(®exbuf, args.reg, REG_EXTENDED | REG_NOSUB))) {
00533 regerror(errcode, ®exbuf, buf, len);
00534 ast_log(LOG_WARNING, "Malformed input %s(%s): %s\n", cmd, parse, buf);
00535 return -1;
00536 }
00537
00538 strcpy(buf, regexec(®exbuf, args.str, 0, NULL, 0) ? "0" : "1");
00539
00540 regfree(®exbuf);
00541
00542 return 0;
00543 }
00544
00545 static struct ast_custom_function regex_function = {
00546 .name = "REGEX",
00547 .read = regex,
00548 };
00549
00550 #define HASH_PREFIX "~HASH~%s~"
00551 #define HASH_FORMAT HASH_PREFIX "%s~"
00552
00553 static char *app_clearhash = "ClearHash";
00554
00555
00556 static void clearvar_prefix(struct ast_channel *chan, const char *prefix)
00557 {
00558 struct ast_var_t *var;
00559 int len = strlen(prefix);
00560 AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->varshead, var, entries) {
00561 if (strncasecmp(prefix, ast_var_name(var), len) == 0) {
00562 AST_LIST_REMOVE_CURRENT(entries);
00563 ast_free(var);
00564 }
00565 }
00566 AST_LIST_TRAVERSE_SAFE_END
00567 }
00568
00569 static int exec_clearhash(struct ast_channel *chan, void *data)
00570 {
00571 char prefix[80];
00572 snprintf(prefix, sizeof(prefix), HASH_PREFIX, data ? (char *)data : "null");
00573 clearvar_prefix(chan, prefix);
00574 return 0;
00575 }
00576
00577 static int array(struct ast_channel *chan, const char *cmd, char *var,
00578 const char *value)
00579 {
00580 AST_DECLARE_APP_ARGS(arg1,
00581 AST_APP_ARG(var)[100];
00582 );
00583 AST_DECLARE_APP_ARGS(arg2,
00584 AST_APP_ARG(val)[100];
00585 );
00586 char *origvar = "", *value2, varname[256];
00587 int i, ishash = 0;
00588
00589 value2 = ast_strdupa(value);
00590 if (!var || !value2)
00591 return -1;
00592
00593 if (!strcmp(cmd, "HASH")) {
00594 const char *var2 = pbx_builtin_getvar_helper(chan, "~ODBCFIELDS~");
00595 origvar = var;
00596 if (var2)
00597 var = ast_strdupa(var2);
00598 else {
00599 if (chan)
00600 ast_autoservice_stop(chan);
00601 return -1;
00602 }
00603 ishash = 1;
00604 }
00605
00606
00607
00608
00609
00610
00611
00612 ast_debug(1, "array (%s=%s)\n", var, S_OR(value2, ""));
00613 AST_STANDARD_APP_ARGS(arg1, var);
00614
00615 AST_STANDARD_APP_ARGS(arg2, value2);
00616
00617 for (i = 0; i < arg1.argc; i++) {
00618 ast_debug(1, "array set value (%s=%s)\n", arg1.var[i],
00619 S_OR(arg2.val[i], ""));
00620 if (i < arg2.argc) {
00621 if (ishash) {
00622 snprintf(varname, sizeof(varname), HASH_FORMAT, origvar, arg1.var[i]);
00623 pbx_builtin_setvar_helper(chan, varname, arg2.val[i]);
00624 } else {
00625 pbx_builtin_setvar_helper(chan, arg1.var[i], arg2.val[i]);
00626 }
00627 } else {
00628
00629
00630 if (ishash) {
00631 snprintf(varname, sizeof(varname), HASH_FORMAT, origvar, arg1.var[i]);
00632 pbx_builtin_setvar_helper(chan, varname, "");
00633 } else {
00634 pbx_builtin_setvar_helper(chan, arg1.var[i], "");
00635 }
00636 }
00637 }
00638
00639 return 0;
00640 }
00641
00642 static int hashkeys_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00643 {
00644 struct ast_var_t *newvar;
00645 int plen;
00646 char prefix[80];
00647 snprintf(prefix, sizeof(prefix), HASH_PREFIX, data);
00648 plen = strlen(prefix);
00649
00650 memset(buf, 0, len);
00651 AST_LIST_TRAVERSE(&chan->varshead, newvar, entries) {
00652 if (strncasecmp(prefix, ast_var_name(newvar), plen) == 0) {
00653
00654 strncat(buf, ast_var_name(newvar) + plen, len - strlen(buf) - 1);
00655
00656 buf[strlen(buf) - 1] = ',';
00657 }
00658 }
00659
00660 buf[strlen(buf) - 1] = '\0';
00661 return 0;
00662 }
00663
00664 static int hash_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
00665 {
00666 char varname[256];
00667 AST_DECLARE_APP_ARGS(arg,
00668 AST_APP_ARG(hashname);
00669 AST_APP_ARG(hashkey);
00670 );
00671
00672 if (!strchr(var, ',')) {
00673
00674 return array(chan, "HASH", var, value);
00675 }
00676
00677 AST_STANDARD_APP_ARGS(arg, var);
00678 snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg.hashkey);
00679 pbx_builtin_setvar_helper(chan, varname, value);
00680
00681 return 0;
00682 }
00683
00684 static int hash_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00685 {
00686 char varname[256];
00687 const char *varvalue;
00688 AST_DECLARE_APP_ARGS(arg,
00689 AST_APP_ARG(hashname);
00690 AST_APP_ARG(hashkey);
00691 );
00692
00693 AST_STANDARD_APP_ARGS(arg, data);
00694 if (arg.argc == 2) {
00695 snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg.hashkey);
00696 varvalue = pbx_builtin_getvar_helper(chan, varname);
00697 if (varvalue)
00698 ast_copy_string(buf, varvalue, len);
00699 else
00700 *buf = '\0';
00701 } else if (arg.argc == 1) {
00702 char colnames[4096];
00703 int i;
00704 AST_DECLARE_APP_ARGS(arg2,
00705 AST_APP_ARG(col)[100];
00706 );
00707
00708
00709 hashkeys_read(chan, "HASHKEYS", arg.hashname, colnames, sizeof(colnames));
00710 pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", colnames);
00711
00712 AST_STANDARD_APP_ARGS(arg2, colnames);
00713 *buf = '\0';
00714
00715
00716 for (i = 0; i < arg2.argc; i++) {
00717 snprintf(varname, sizeof(varname), HASH_FORMAT, arg.hashname, arg2.col[i]);
00718 varvalue = pbx_builtin_getvar_helper(chan, varname);
00719 strncat(buf, varvalue, len - strlen(buf) - 1);
00720 strncat(buf, ",", len - strlen(buf) - 1);
00721 }
00722
00723
00724 buf[strlen(buf) - 1] = '\0';
00725 }
00726
00727 return 0;
00728 }
00729
00730 static struct ast_custom_function hash_function = {
00731 .name = "HASH",
00732 .write = hash_write,
00733 .read = hash_read,
00734 };
00735
00736 static struct ast_custom_function hashkeys_function = {
00737 .name = "HASHKEYS",
00738 .read = hashkeys_read,
00739 };
00740
00741 static struct ast_custom_function array_function = {
00742 .name = "ARRAY",
00743 .write = array,
00744 };
00745
00746 static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00747 {
00748 char *bufptr = buf, *dataptr = data;
00749
00750 if (len < 3){
00751 ast_log(LOG_ERROR, "Not enough buffer");
00752 return -1;
00753 }
00754
00755 if (ast_strlen_zero(data)) {
00756 ast_log(LOG_WARNING, "No argument specified!\n");
00757 ast_copy_string(buf, "\"\"", len);
00758 return 0;
00759 }
00760
00761 *bufptr++ = '"';
00762 for (; bufptr < buf + len - 3; dataptr++) {
00763 if (*dataptr == '\\') {
00764 *bufptr++ = '\\';
00765 *bufptr++ = '\\';
00766 } else if (*dataptr == '"') {
00767 *bufptr++ = '\\';
00768 *bufptr++ = '"';
00769 } else if (*dataptr == '\0') {
00770 break;
00771 } else {
00772 *bufptr++ = *dataptr;
00773 }
00774 }
00775 *bufptr++ = '"';
00776 *bufptr = '\0';
00777 return 0;
00778 }
00779
00780 static struct ast_custom_function quote_function = {
00781 .name = "QUOTE",
00782 .read = quote,
00783 };
00784
00785 static int csv_quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00786 {
00787 char *bufptr = buf, *dataptr = data;
00788
00789 if (len < 3){
00790 ast_log(LOG_ERROR, "Not enough buffer");
00791 return -1;
00792 }
00793
00794 if (ast_strlen_zero(data)) {
00795 ast_log(LOG_WARNING, "No argument specified!\n");
00796 ast_copy_string(buf,"\"\"",len);
00797 return 0;
00798 }
00799
00800 *bufptr++ = '"';
00801 for (; bufptr < buf + len - 3; dataptr++){
00802 if (*dataptr == '"') {
00803 *bufptr++ = '"';
00804 *bufptr++ = '"';
00805 } else if (*dataptr == '\0') {
00806 break;
00807 } else {
00808 *bufptr++ = *dataptr;
00809 }
00810 }
00811 *bufptr++ = '"';
00812 *bufptr='\0';
00813 return 0;
00814 }
00815
00816 static struct ast_custom_function csv_quote_function = {
00817 .name = "CSV_QUOTE",
00818 .read = csv_quote,
00819 };
00820
00821 static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
00822 {
00823 int length = 0;
00824
00825 if (data)
00826 length = strlen(data);
00827
00828 snprintf(buf, buflen, "%d", length);
00829
00830 return 0;
00831 }
00832
00833 static struct ast_custom_function len_function = {
00834 .name = "LEN",
00835 .read = len,
00836 };
00837
00838 static int acf_strftime(struct ast_channel *chan, const char *cmd, char *parse,
00839 char *buf, size_t buflen)
00840 {
00841 AST_DECLARE_APP_ARGS(args,
00842 AST_APP_ARG(epoch);
00843 AST_APP_ARG(timezone);
00844 AST_APP_ARG(format);
00845 );
00846 struct timeval when;
00847 struct ast_tm tm;
00848
00849 buf[0] = '\0';
00850
00851 AST_STANDARD_APP_ARGS(args, parse);
00852
00853 ast_get_timeval(args.epoch, &when, ast_tvnow(), NULL);
00854 ast_localtime(&when, &tm, args.timezone);
00855
00856 if (!args.format)
00857 args.format = "%c";
00858
00859 if (ast_strftime(buf, buflen, args.format, &tm) <= 0)
00860 ast_log(LOG_WARNING, "C function strftime() output nothing?!!\n");
00861
00862 buf[buflen - 1] = '\0';
00863
00864 return 0;
00865 }
00866
00867 static struct ast_custom_function strftime_function = {
00868 .name = "STRFTIME",
00869 .read = acf_strftime,
00870 };
00871
00872 static int acf_strptime(struct ast_channel *chan, const char *cmd, char *data,
00873 char *buf, size_t buflen)
00874 {
00875 AST_DECLARE_APP_ARGS(args,
00876 AST_APP_ARG(timestring);
00877 AST_APP_ARG(timezone);
00878 AST_APP_ARG(format);
00879 );
00880 struct ast_tm tm;
00881
00882 buf[0] = '\0';
00883
00884 if (!data) {
00885 ast_log(LOG_ERROR,
00886 "Asterisk function STRPTIME() requires an argument.\n");
00887 return -1;
00888 }
00889
00890 AST_STANDARD_APP_ARGS(args, data);
00891
00892 if (ast_strlen_zero(args.format)) {
00893 ast_log(LOG_ERROR,
00894 "No format supplied to STRPTIME(<timestring>,<timezone>,<format>)");
00895 return -1;
00896 }
00897
00898 if (!ast_strptime(args.timestring, args.format, &tm)) {
00899 ast_log(LOG_WARNING, "STRPTIME() found no time specified within the string\n");
00900 } else {
00901 struct timeval when;
00902 when = ast_mktime(&tm, args.timezone);
00903 snprintf(buf, buflen, "%d", (int) when.tv_sec);
00904 }
00905
00906 return 0;
00907 }
00908
00909 static struct ast_custom_function strptime_function = {
00910 .name = "STRPTIME",
00911 .read = acf_strptime,
00912 };
00913
00914 static int function_eval(struct ast_channel *chan, const char *cmd, char *data,
00915 char *buf, size_t buflen)
00916 {
00917 if (ast_strlen_zero(data)) {
00918 ast_log(LOG_WARNING, "EVAL requires an argument: EVAL(<string>)\n");
00919 return -1;
00920 }
00921
00922 pbx_substitute_variables_helper(chan, data, buf, buflen - 1);
00923
00924 return 0;
00925 }
00926
00927 static struct ast_custom_function eval_function = {
00928 .name = "EVAL",
00929 .read = function_eval,
00930 };
00931
00932 static int keypadhash(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
00933 {
00934 char *bufptr, *dataptr;
00935
00936 for (bufptr = buf, dataptr = data; bufptr < buf + buflen - 1; dataptr++) {
00937 if (*dataptr == '\0') {
00938 *bufptr++ = '\0';
00939 break;
00940 } else if (*dataptr == '1') {
00941 *bufptr++ = '1';
00942 } else if (strchr("AaBbCc2", *dataptr)) {
00943 *bufptr++ = '2';
00944 } else if (strchr("DdEeFf3", *dataptr)) {
00945 *bufptr++ = '3';
00946 } else if (strchr("GgHhIi4", *dataptr)) {
00947 *bufptr++ = '4';
00948 } else if (strchr("JjKkLl5", *dataptr)) {
00949 *bufptr++ = '5';
00950 } else if (strchr("MmNnOo6", *dataptr)) {
00951 *bufptr++ = '6';
00952 } else if (strchr("PpQqRrSs7", *dataptr)) {
00953 *bufptr++ = '7';
00954 } else if (strchr("TtUuVv8", *dataptr)) {
00955 *bufptr++ = '8';
00956 } else if (strchr("WwXxYyZz9", *dataptr)) {
00957 *bufptr++ = '9';
00958 } else if (*dataptr == '0') {
00959 *bufptr++ = '0';
00960 }
00961 }
00962 buf[buflen - 1] = '\0';
00963
00964 return 0;
00965 }
00966
00967 static struct ast_custom_function keypadhash_function = {
00968 .name = "KEYPADHASH",
00969 .read = keypadhash,
00970 };
00971
00972 static int string_toupper(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
00973 {
00974 char *bufptr = buf, *dataptr = data;
00975
00976 while ((bufptr < buf + buflen - 1) && (*bufptr++ = toupper(*dataptr++)));
00977
00978 return 0;
00979 }
00980
00981 static struct ast_custom_function toupper_function = {
00982 .name = "TOUPPER",
00983 .read = string_toupper,
00984 };
00985
00986 static int string_tolower(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
00987 {
00988 char *bufptr = buf, *dataptr = data;
00989
00990 while ((bufptr < buf + buflen - 1) && (*bufptr++ = tolower(*dataptr++)));
00991
00992 return 0;
00993 }
00994
00995 static struct ast_custom_function tolower_function = {
00996 .name = "TOLOWER",
00997 .read = string_tolower,
00998 };
00999
01000 static int unload_module(void)
01001 {
01002 int res = 0;
01003
01004 res |= ast_custom_function_unregister(&fieldqty_function);
01005 res |= ast_custom_function_unregister(&filter_function);
01006 res |= ast_custom_function_unregister(&listfilter_function);
01007 res |= ast_custom_function_unregister(®ex_function);
01008 res |= ast_custom_function_unregister(&array_function);
01009 res |= ast_custom_function_unregister("e_function);
01010 res |= ast_custom_function_unregister(&csv_quote_function);
01011 res |= ast_custom_function_unregister(&len_function);
01012 res |= ast_custom_function_unregister(&strftime_function);
01013 res |= ast_custom_function_unregister(&strptime_function);
01014 res |= ast_custom_function_unregister(&eval_function);
01015 res |= ast_custom_function_unregister(&keypadhash_function);
01016 res |= ast_custom_function_unregister(&hashkeys_function);
01017 res |= ast_custom_function_unregister(&hash_function);
01018 res |= ast_unregister_application(app_clearhash);
01019 res |= ast_custom_function_unregister(&toupper_function);
01020 res |= ast_custom_function_unregister(&tolower_function);
01021
01022 return res;
01023 }
01024
01025 static int load_module(void)
01026 {
01027 int res = 0;
01028
01029 res |= ast_custom_function_register(&fieldqty_function);
01030 res |= ast_custom_function_register(&filter_function);
01031 res |= ast_custom_function_register(&listfilter_function);
01032 res |= ast_custom_function_register(®ex_function);
01033 res |= ast_custom_function_register(&array_function);
01034 res |= ast_custom_function_register("e_function);
01035 res |= ast_custom_function_register(&csv_quote_function);
01036 res |= ast_custom_function_register(&len_function);
01037 res |= ast_custom_function_register(&strftime_function);
01038 res |= ast_custom_function_register(&strptime_function);
01039 res |= ast_custom_function_register(&eval_function);
01040 res |= ast_custom_function_register(&keypadhash_function);
01041 res |= ast_custom_function_register(&hashkeys_function);
01042 res |= ast_custom_function_register(&hash_function);
01043 res |= ast_register_application_xml(app_clearhash, exec_clearhash);
01044 res |= ast_custom_function_register(&toupper_function);
01045 res |= ast_custom_function_register(&tolower_function);
01046
01047 return res;
01048 }
01049
01050 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "String handling dialplan functions");