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: 211580 $")
00030
00031 #include "asterisk/file.h"
00032 #include "asterisk/channel.h"
00033 #include "asterisk/pbx.h"
00034 #include "asterisk/module.h"
00035 #include "asterisk/app.h"
00036
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 #define MAXRESULT 1024
00082
00083 struct sortable_keys {
00084 char *key;
00085 float value;
00086 };
00087
00088 static int sort_subroutine(const void *arg1, const void *arg2)
00089 {
00090 const struct sortable_keys *one=arg1, *two=arg2;
00091 if (one->value < two->value)
00092 return -1;
00093 else if (one->value == two->value)
00094 return 0;
00095 else
00096 return 1;
00097 }
00098
00099 #define ERROR_NOARG (-1)
00100 #define ERROR_NOMEM (-2)
00101 #define ERROR_USAGE (-3)
00102
00103 static int sort_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen)
00104 {
00105 char *strings, *ptrkey, *ptrvalue;
00106 int count=1, count2, element_count=0;
00107 struct sortable_keys *sortable_keys;
00108
00109 *buffer = '\0';
00110
00111 if (!data)
00112 return ERROR_NOARG;
00113
00114 strings = ast_strdupa(data);
00115
00116 for (ptrkey = strings; *ptrkey; ptrkey++) {
00117 if (*ptrkey == ',')
00118 count++;
00119 }
00120
00121 sortable_keys = alloca(count * sizeof(struct sortable_keys));
00122
00123 memset(sortable_keys, 0, count * sizeof(struct sortable_keys));
00124
00125
00126 count2 = 0;
00127 while ((ptrkey = strsep(&strings, ","))) {
00128 ptrvalue = strchr(ptrkey, ':');
00129 if (!ptrvalue) {
00130 count--;
00131 continue;
00132 }
00133 *ptrvalue++ = '\0';
00134 sortable_keys[count2].key = ptrkey;
00135 sscanf(ptrvalue, "%30f", &sortable_keys[count2].value);
00136 count2++;
00137 }
00138
00139
00140 qsort(sortable_keys, count, sizeof(struct sortable_keys), sort_subroutine);
00141
00142 for (count2 = 0; count2 < count; count2++) {
00143 int blen = strlen(buffer);
00144 if (element_count++) {
00145 strncat(buffer + blen, ",", buflen - blen - 1);
00146 blen++;
00147 }
00148 strncat(buffer + blen, sortable_keys[count2].key, buflen - blen - 1);
00149 }
00150
00151 return 0;
00152 }
00153
00154 static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen)
00155 {
00156 char *parse;
00157 size_t delim_consumed;
00158 AST_DECLARE_APP_ARGS(args,
00159 AST_APP_ARG(varname);
00160 AST_APP_ARG(delimiter);
00161 AST_APP_ARG(field);
00162 );
00163
00164 *buffer = '\0';
00165
00166 parse = ast_strdupa(data);
00167
00168 AST_STANDARD_APP_ARGS(args, parse);
00169
00170
00171 if (args.argc < 3) {
00172 return ERROR_NOARG;
00173 } else {
00174 char d, ds[2] = "";
00175 char *tmp = alloca(strlen(args.varname) + 4);
00176 char varvalue[MAXRESULT], *tmp2=varvalue;
00177
00178 if (tmp) {
00179 snprintf(tmp, strlen(args.varname) + 4, "${%s}", args.varname);
00180 } else {
00181 return ERROR_NOMEM;
00182 }
00183
00184 if (ast_get_encoded_char(args.delimiter, ds, &delim_consumed))
00185 ast_copy_string(ds, "-", sizeof(ds));
00186
00187
00188 d = *ds;
00189
00190 pbx_substitute_variables_helper(chan, tmp, tmp2, MAXRESULT - 1);
00191
00192 if (tmp2) {
00193 int curfieldnum = 1, firstfield = 1;
00194 while (tmp2 != NULL && args.field != NULL) {
00195 char *nextgroup = strsep(&(args.field), "&");
00196 int num1 = 0, num2 = MAXRESULT;
00197 char trashchar;
00198
00199 if (sscanf(nextgroup, "%30d-%30d", &num1, &num2) == 2) {
00200
00201 } else if (sscanf(nextgroup, "-%30d", &num2) == 1) {
00202
00203 num1 = 0;
00204 } else if ((sscanf(nextgroup, "%30d%1c", &num1, &trashchar) == 2) && (trashchar == '-')) {
00205
00206 num2 = MAXRESULT;
00207 } else if (sscanf(nextgroup, "%30d", &num1) == 1) {
00208
00209 num2 = num1;
00210 } else {
00211 return ERROR_USAGE;
00212 }
00213
00214
00215 if (num1 > 0) {
00216 while (tmp2 != (char *)NULL + 1 && curfieldnum < num1) {
00217 tmp2 = strchr(tmp2, d) + 1;
00218 curfieldnum++;
00219 }
00220 }
00221
00222
00223 if ((num1 > 0) && (curfieldnum > num1))
00224 ast_log(LOG_WARNING, "We're already past the field you wanted?\n");
00225
00226
00227 if (tmp2 == (char *)NULL + 1)
00228 tmp2 = NULL;
00229
00230
00231 while (tmp2 != NULL && curfieldnum <= num2) {
00232 char *tmp3 = strsep(&tmp2, ds);
00233 int curlen = strlen(buffer);
00234
00235 if (firstfield) {
00236 snprintf(buffer, buflen, "%s", tmp3);
00237 firstfield = 0;
00238 } else {
00239 snprintf(buffer + curlen, buflen - curlen, "%c%s", d, tmp3);
00240 }
00241
00242 curfieldnum++;
00243 }
00244 }
00245 }
00246 }
00247 return 0;
00248 }
00249
00250 static int acf_sort_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00251 {
00252 int ret = -1;
00253
00254 switch (sort_internal(chan, data, buf, len)) {
00255 case ERROR_NOARG:
00256 ast_log(LOG_ERROR, "SORT() requires an argument\n");
00257 break;
00258 case ERROR_NOMEM:
00259 ast_log(LOG_ERROR, "Out of memory\n");
00260 break;
00261 case 0:
00262 ret = 0;
00263 break;
00264 default:
00265 ast_log(LOG_ERROR, "Unknown internal error\n");
00266 }
00267
00268 return ret;
00269 }
00270
00271 static int acf_cut_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00272 {
00273 int ret = -1;
00274
00275 switch (cut_internal(chan, data, buf, len)) {
00276 case ERROR_NOARG:
00277 ast_log(LOG_ERROR, "Syntax: CUT(<varname>,<char-delim>,<range-spec>) - missing argument!\n");
00278 break;
00279 case ERROR_NOMEM:
00280 ast_log(LOG_ERROR, "Out of memory\n");
00281 break;
00282 case ERROR_USAGE:
00283 ast_log(LOG_ERROR, "Usage: CUT(<varname>,<char-delim>,<range-spec>)\n");
00284 break;
00285 case 0:
00286 ret = 0;
00287 break;
00288 default:
00289 ast_log(LOG_ERROR, "Unknown internal error\n");
00290 }
00291
00292 return ret;
00293 }
00294
00295 struct ast_custom_function acf_sort = {
00296 .name = "SORT",
00297 .read = acf_sort_exec,
00298 };
00299
00300 struct ast_custom_function acf_cut = {
00301 .name = "CUT",
00302 .read = acf_cut_exec,
00303 };
00304
00305 static int unload_module(void)
00306 {
00307 int res = 0;
00308
00309 res |= ast_custom_function_unregister(&acf_cut);
00310 res |= ast_custom_function_unregister(&acf_sort);
00311
00312 return res;
00313 }
00314
00315 static int load_module(void)
00316 {
00317 int res = 0;
00318
00319 res |= ast_custom_function_register(&acf_cut);
00320 res |= ast_custom_function_register(&acf_sort);
00321
00322 return res;
00323 }
00324
00325 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Cut out information from a string");