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