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: 328209 $")
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 = 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 } else if (!(var_expr = alloca(strlen(args.varname) + 4))) {
00174 return ERROR_NOMEM;
00175 }
00176
00177
00178 snprintf(var_expr, strlen(args.varname) + 4, "${%s}", args.varname);
00179 var_value = ast_str_create(16);
00180 ast_str_substitute_variables(&var_value, 0, chan, var_expr);
00181
00182
00183 if (ast_get_encoded_char(args.delimiter, ds, &delim_consumed)) {
00184 ast_copy_string(ds, "-", sizeof(ds));
00185 }
00186 ds[1] = '\0';
00187
00188 if (ast_str_strlen(var_value)) {
00189 int curfieldnum = 1;
00190 char *curfieldptr = ast_str_buffer(var_value);
00191 int out_field_count = 0;
00192
00193 while (curfieldptr != NULL && args.field != NULL) {
00194 char *next_range = strsep(&(args.field), "&");
00195 int start_field, stop_field;
00196 char trashchar;
00197
00198 if (sscanf(next_range, "%30d-%30d", &start_field, &stop_field) == 2) {
00199
00200 } else if (sscanf(next_range, "-%30d", &stop_field) == 1) {
00201
00202 start_field = 1;
00203 } else if ((sscanf(next_range, "%30d%1c", &start_field, &trashchar) == 2) && (trashchar == '-')) {
00204
00205 stop_field = INT_MAX;
00206 } else if (sscanf(next_range, "%30d", &start_field) == 1) {
00207
00208 stop_field = start_field;
00209 } else {
00210
00211 ast_free(var_value);
00212 return ERROR_USAGE;
00213 }
00214
00215
00216 while (curfieldptr != NULL && curfieldnum < start_field) {
00217 strsep(&curfieldptr, ds);
00218 curfieldnum++;
00219 }
00220
00221
00222 if (curfieldnum > start_field) {
00223 ast_log(LOG_WARNING, "We're already past the field you wanted?\n");
00224 }
00225
00226
00227 while (curfieldptr != NULL && curfieldnum <= stop_field) {
00228 char *field_value = strsep(&curfieldptr, ds);
00229 ast_str_append(buf, buflen, "%s%s", out_field_count++ ? ds : "", field_value);
00230 curfieldnum++;
00231 }
00232 }
00233 }
00234 ast_free(var_value);
00235 return 0;
00236 }
00237
00238 static int acf_sort_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00239 {
00240 int ret = -1;
00241
00242 switch (sort_internal(chan, data, buf, len)) {
00243 case ERROR_NOARG:
00244 ast_log(LOG_ERROR, "SORT() requires an argument\n");
00245 break;
00246 case ERROR_NOMEM:
00247 ast_log(LOG_ERROR, "Out of memory\n");
00248 break;
00249 case 0:
00250 ret = 0;
00251 break;
00252 default:
00253 ast_log(LOG_ERROR, "Unknown internal error\n");
00254 }
00255
00256 return ret;
00257 }
00258
00259 static int acf_cut_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00260 {
00261 int ret = -1;
00262 struct ast_str *str = ast_str_create(16);
00263
00264 switch (cut_internal(chan, data, &str, len)) {
00265 case ERROR_NOARG:
00266 ast_log(LOG_ERROR, "Syntax: CUT(<varname>,<char-delim>,<range-spec>) - missing argument!\n");
00267 break;
00268 case ERROR_NOMEM:
00269 ast_log(LOG_ERROR, "Out of memory\n");
00270 break;
00271 case ERROR_USAGE:
00272 ast_log(LOG_ERROR, "Usage: CUT(<varname>,<char-delim>,<range-spec>)\n");
00273 break;
00274 case 0:
00275 ret = 0;
00276 ast_copy_string(buf, ast_str_buffer(str), len);
00277 break;
00278 default:
00279 ast_log(LOG_ERROR, "Unknown internal error\n");
00280 }
00281 ast_free(str);
00282 return ret;
00283 }
00284
00285 static int acf_cut_exec2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
00286 {
00287 int ret = -1;
00288
00289 switch (cut_internal(chan, data, buf, len)) {
00290 case ERROR_NOARG:
00291 ast_log(LOG_ERROR, "Syntax: CUT(<varname>,<char-delim>,<range-spec>) - missing argument!\n");
00292 break;
00293 case ERROR_NOMEM:
00294 ast_log(LOG_ERROR, "Out of memory\n");
00295 break;
00296 case ERROR_USAGE:
00297 ast_log(LOG_ERROR, "Usage: CUT(<varname>,<char-delim>,<range-spec>)\n");
00298 break;
00299 case 0:
00300 ret = 0;
00301 break;
00302 default:
00303 ast_log(LOG_ERROR, "Unknown internal error\n");
00304 }
00305
00306 return ret;
00307 }
00308
00309 static struct ast_custom_function acf_sort = {
00310 .name = "SORT",
00311 .read = acf_sort_exec,
00312 };
00313
00314 static struct ast_custom_function acf_cut = {
00315 .name = "CUT",
00316 .read = acf_cut_exec,
00317 .read2 = acf_cut_exec2,
00318 };
00319
00320 static int unload_module(void)
00321 {
00322 int res = 0;
00323
00324 res |= ast_custom_function_unregister(&acf_cut);
00325 res |= ast_custom_function_unregister(&acf_sort);
00326
00327 return res;
00328 }
00329
00330 static int load_module(void)
00331 {
00332 int res = 0;
00333
00334 res |= ast_custom_function_register(&acf_cut);
00335 res |= ast_custom_function_register(&acf_sort);
00336
00337 return res;
00338 }
00339
00340 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Cut out information from a string");