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