| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2003 Tilghman Lesher.  All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2004-04-12 16:08:20 +00:00
										 |  |  |  * Tilghman Lesher <app_cut__v003@the-tilghman.com> | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This code is released by the author with no restrictions on usage. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  | /*! \file
 | 
					
						
							|  |  |  |  * \brief Cut application | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-11-06 15:09:47 +00:00
										 |  |  |  * \ingroup applications | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-25 17:44:48 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2005-06-06 22:39:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-21 06:02:45 +00:00
										 |  |  | #include "asterisk/file.h"
 | 
					
						
							|  |  |  | #include "asterisk/logger.h"
 | 
					
						
							|  |  |  | #include "asterisk/options.h"
 | 
					
						
							|  |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/pbx.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							| 
									
										
										
										
											2005-11-01 21:02:07 +00:00
										 |  |  | #include "asterisk/app.h"
 | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Maximum length of any variable */ | 
					
						
							|  |  |  | #define MAXRESULT	1024
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 13:34:38 +00:00
										 |  |  | static char *tdesc = "Cut out information from a string"; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static char *app_cut = "Cut"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 13:34:38 +00:00
										 |  |  | static char *cut_synopsis = "Splits a variable's contents using the specified delimiter"; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static char *cut_descrip = | 
					
						
							| 
									
										
										
										
											2005-11-11 13:34:38 +00:00
										 |  |  | "  Cut(newvar=varname,delimiter,fieldspec): This applicaiton will split the\n" | 
					
						
							|  |  |  | "contents of a variable based on the given delimeter and store the result in\n" | 
					
						
							|  |  |  | "a new variable.\n" | 
					
						
							|  |  |  | "Parameters:\n" | 
					
						
							| 
									
										
										
										
											2003-11-04 00:44:51 +00:00
										 |  |  | "  newvar    - new variable created from result string\n" | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | "  varname   - variable you want cut\n" | 
					
						
							| 
									
										
										
										
											2003-11-04 00:44:51 +00:00
										 |  |  | "  delimiter - defaults to '-'\n" | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | "  fieldspec - number of the field you want (1-based offset)\n" | 
					
						
							| 
									
										
										
										
											2005-11-11 13:34:38 +00:00
										 |  |  | "              may also be specified as a range (with -)\n" | 
					
						
							|  |  |  | "              or group of ranges and fields (with &)\n" | 
					
						
							|  |  |  | "This application has been deprecated in favor of the CUT function.\n"; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | static char *app_sort = "Sort"; | 
					
						
							|  |  |  | static char *app_sort_synopsis = "Sorts a list of keywords and values"; | 
					
						
							|  |  |  | static char *app_sort_descrip = | 
					
						
							| 
									
										
										
										
											2005-11-11 13:34:38 +00:00
										 |  |  | "  Sort(newvar=key1:val1[,key2:val2[[...],keyN:valN]]): This application will\n" | 
					
						
							|  |  |  | "sort the list provided in ascending order. The result will be stored in the\n" | 
					
						
							|  |  |  | "specified variable name.\n" | 
					
						
							|  |  |  | "  This applicaiton has been deprecated in favor of the SORT function.\n"; | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | STANDARD_LOCAL_USER; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LOCAL_USER_DECL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | struct sortable_keys { | 
					
						
							|  |  |  | 	char *key; | 
					
						
							|  |  |  | 	float value; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int sort_subroutine(const void *arg1, const void *arg2) | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 	const struct sortable_keys *one=arg1, *two=arg2; | 
					
						
							|  |  |  | 	if (one->value < two->value) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} else if (one->value == two->value) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ERROR_NOARG	(-1)
 | 
					
						
							|  |  |  | #define ERROR_NOMEM	(-2)
 | 
					
						
							|  |  |  | #define ERROR_USAGE	(-3)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int sort_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *strings, *ptrkey, *ptrvalue; | 
					
						
							| 
									
										
										
										
											2005-10-18 16:48:19 +00:00
										 |  |  | 	int count=1, count2, element_count=0; | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 	struct sortable_keys *sortable_keys; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memset(buffer, 0, buflen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!data) { | 
					
						
							|  |  |  | 		return ERROR_NOARG; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	strings = ast_strdupa((char *)data); | 
					
						
							|  |  |  | 	if (!strings) { | 
					
						
							|  |  |  | 		return ERROR_NOMEM; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (ptrkey = strings; *ptrkey; ptrkey++) { | 
					
						
							|  |  |  | 		if (*ptrkey == '|') { | 
					
						
							|  |  |  | 			count++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sortable_keys = alloca(count * sizeof(struct sortable_keys)); | 
					
						
							|  |  |  | 	if (!sortable_keys) { | 
					
						
							|  |  |  | 		return ERROR_NOMEM; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memset(sortable_keys, 0, count * sizeof(struct sortable_keys)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Parse each into a struct */ | 
					
						
							|  |  |  | 	count2 = 0; | 
					
						
							|  |  |  | 	while ((ptrkey = strsep(&strings, "|"))) { | 
					
						
							|  |  |  | 		ptrvalue = index(ptrkey, ':'); | 
					
						
							|  |  |  | 		if (!ptrvalue) { | 
					
						
							|  |  |  | 			count--; | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		*ptrvalue = '\0'; | 
					
						
							|  |  |  | 		ptrvalue++; | 
					
						
							|  |  |  | 		sortable_keys[count2].key = ptrkey; | 
					
						
							|  |  |  | 		sscanf(ptrvalue, "%f", &sortable_keys[count2].value); | 
					
						
							|  |  |  | 		count2++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Sort the structs */ | 
					
						
							|  |  |  | 	qsort(sortable_keys, count, sizeof(struct sortable_keys), sort_subroutine); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (count2 = 0; count2 < count; count2++) { | 
					
						
							| 
									
										
										
										
											2005-10-18 16:48:19 +00:00
										 |  |  | 		int blen = strlen(buffer); | 
					
						
							|  |  |  | 		if (element_count++) { | 
					
						
							|  |  |  | 			strncat(buffer + blen, ",", buflen - blen - 1); | 
					
						
							| 
									
										
										
										
											2005-12-16 00:49:39 +00:00
										 |  |  | 			blen++; | 
					
						
							| 
									
										
										
										
											2005-10-18 16:48:19 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-12-16 00:49:39 +00:00
										 |  |  | 		strncat(buffer + blen, sortable_keys[count2].key, buflen - blen - 1); | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-01 21:02:07 +00:00
										 |  |  | 	char *s, *args[3], *varname=NULL, *delimiter=NULL, *field=NULL; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 	int args_okay = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 	memset(buffer, 0, buflen); | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Check and parse arguments */ | 
					
						
							|  |  |  | 	if (data) { | 
					
						
							| 
									
										
										
										
											2003-10-25 17:44:48 +00:00
										 |  |  | 		s = ast_strdupa((char *)data); | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 		if (s) { | 
					
						
							| 
									
										
										
										
											2005-11-03 21:19:11 +00:00
										 |  |  | 			ast_app_separate_args(s, '|', args, 3); | 
					
						
							| 
									
										
										
										
											2005-11-01 21:02:07 +00:00
										 |  |  | 			varname = args[0]; | 
					
						
							|  |  |  | 			delimiter = args[1]; | 
					
						
							|  |  |  | 			field = args[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (field) { | 
					
						
							|  |  |  | 				args_okay = 1; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 			return ERROR_NOMEM; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (args_okay) { | 
					
						
							|  |  |  | 		char d, ds[2]; | 
					
						
							|  |  |  | 		char *tmp = alloca(strlen(varname) + 4); | 
					
						
							| 
									
										
										
										
											2004-04-12 16:08:20 +00:00
										 |  |  | 		char varvalue[MAXRESULT], *tmp2=varvalue; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-04-12 16:08:20 +00:00
										 |  |  | 		if (tmp) { | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 			snprintf(tmp, strlen(varname) + 4, "${%s}", varname); | 
					
						
							| 
									
										
										
										
											2004-04-12 16:08:20 +00:00
										 |  |  | 			memset(varvalue, 0, sizeof(varvalue)); | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 			return ERROR_NOMEM; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (delimiter[0]) | 
					
						
							|  |  |  | 			d = delimiter[0]; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			d = '-'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* String form of the delimiter, for use with strsep(3) */ | 
					
						
							| 
									
										
										
										
											2004-07-14 07:22:30 +00:00
										 |  |  | 		snprintf(ds, sizeof(ds), "%c", d); | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		pbx_substitute_variables_helper(chan, tmp, tmp2, MAXRESULT - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (tmp2) { | 
					
						
							|  |  |  | 			int curfieldnum = 1; | 
					
						
							|  |  |  | 			while ((tmp2 != NULL) && (field != NULL)) { | 
					
						
							|  |  |  | 				char *nextgroup = strsep(&field, "&"); | 
					
						
							|  |  |  | 				int num1 = 0, num2 = MAXRESULT; | 
					
						
							|  |  |  | 				char trashchar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (sscanf(nextgroup, "%d-%d", &num1, &num2) == 2) { | 
					
						
							|  |  |  | 					/* range with both start and end */ | 
					
						
							|  |  |  | 				} else if (sscanf(nextgroup, "-%d", &num2) == 1) { | 
					
						
							|  |  |  | 					/* range with end */ | 
					
						
							|  |  |  | 					num1 = 0; | 
					
						
							|  |  |  | 				} else if ((sscanf(nextgroup, "%d%c", &num1, &trashchar) == 2) && (trashchar == '-')) { | 
					
						
							|  |  |  | 					/* range with start */ | 
					
						
							|  |  |  | 					num2 = MAXRESULT; | 
					
						
							|  |  |  | 				} else if (sscanf(nextgroup, "%d", &num1) == 1) { | 
					
						
							|  |  |  | 					/* single number */ | 
					
						
							|  |  |  | 					num2 = num1; | 
					
						
							|  |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 					return ERROR_USAGE; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* Get to start, if any */ | 
					
						
							|  |  |  | 				if (num1 > 0) { | 
					
						
							| 
									
										
										
										
											2003-10-25 17:44:48 +00:00
										 |  |  | 					while ((tmp2 != (char *)NULL + 1) && (curfieldnum < num1)) { | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 						tmp2 = index(tmp2, d) + 1; | 
					
						
							|  |  |  | 						curfieldnum++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* Most frequent problem is the expectation of reordering fields */ | 
					
						
							|  |  |  | 				if ((num1 > 0) && (curfieldnum > num1)) { | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 					ast_log(LOG_WARNING, "We're already past the field you wanted?\n"); | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* Re-null tmp2 if we added 1 to NULL */ | 
					
						
							| 
									
										
										
										
											2003-10-25 17:44:48 +00:00
										 |  |  | 				if (tmp2 == (char *)NULL + 1) | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 					tmp2 = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* Output fields until we either run out of fields or num2 is reached */ | 
					
						
							|  |  |  | 				while ((tmp2 != NULL) && (curfieldnum <= num2)) { | 
					
						
							|  |  |  | 					char *tmp3 = strsep(&tmp2, ds); | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 					int curlen = strlen(buffer); | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 					if (curlen) { | 
					
						
							|  |  |  | 						snprintf(buffer + curlen, buflen - curlen, "%c%s", d, tmp3); | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 					} else { | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 						snprintf(buffer, buflen, "%s", tmp3); | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					curfieldnum++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-11-29 06:12:29 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		return ERROR_NOARG; | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | static int sort_exec(struct ast_channel *chan, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res=0; | 
					
						
							|  |  |  | 	struct localuser *u; | 
					
						
							|  |  |  | 	char *varname, *strings, result[512] = ""; | 
					
						
							|  |  |  | 	static int dep_warning=0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!dep_warning) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "The application Sort is deprecated.  Please use the SORT() function instead.\n"); | 
					
						
							|  |  |  | 		dep_warning=1; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 	if (!data) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Sort() requires an argument\n"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 18:19:02 +00:00
										 |  |  | 	LOCAL_USER_ADD(u); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 	strings = ast_strdupa((char *)data); | 
					
						
							|  |  |  | 	if (!strings) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Out of memory\n"); | 
					
						
							|  |  |  | 		LOCAL_USER_REMOVE(u); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	varname = strsep(&strings, "="); | 
					
						
							|  |  |  | 	switch (sort_internal(chan, strings, result, sizeof(result))) { | 
					
						
							|  |  |  | 	case ERROR_NOARG: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Sort() requires an argument\n"); | 
					
						
							|  |  |  | 		res = 0; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case ERROR_NOMEM: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Out of memory\n"); | 
					
						
							|  |  |  | 		res = -1; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 0: | 
					
						
							|  |  |  | 		pbx_builtin_setvar_helper(chan, varname, result); | 
					
						
							|  |  |  | 		res = 0; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unknown internal error\n"); | 
					
						
							|  |  |  | 		res = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	LOCAL_USER_REMOVE(u); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int cut_exec(struct ast_channel *chan, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res=0; | 
					
						
							|  |  |  | 	struct localuser *u; | 
					
						
							|  |  |  | 	char *s, *newvar=NULL, result[512]; | 
					
						
							|  |  |  | 	static int dep_warning = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	LOCAL_USER_ADD(u); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!dep_warning) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "The application Cut is deprecated.  Please use the CUT() function instead.\n"); | 
					
						
							|  |  |  | 		dep_warning=1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Check and parse arguments */ | 
					
						
							|  |  |  | 	if (data) { | 
					
						
							|  |  |  | 		s = ast_strdupa((char *)data); | 
					
						
							|  |  |  | 		if (s) { | 
					
						
							|  |  |  | 			newvar = strsep(&s, "="); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "Out of memory\n"); | 
					
						
							|  |  |  | 			LOCAL_USER_REMOVE(u); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (cut_internal(chan, s, result, sizeof(result))) { | 
					
						
							|  |  |  | 	case ERROR_NOARG: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Cut() requires an argument\n"); | 
					
						
							|  |  |  | 		res = 0; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case ERROR_NOMEM: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Out of memory\n"); | 
					
						
							|  |  |  | 		res = -1; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case ERROR_USAGE: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Usage: %s\n", cut_synopsis); | 
					
						
							|  |  |  | 		res = 0; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 0: | 
					
						
							|  |  |  | 		pbx_builtin_setvar_helper(chan, newvar, result); | 
					
						
							|  |  |  | 		res = 0; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unknown internal error\n"); | 
					
						
							|  |  |  | 		res = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 	LOCAL_USER_REMOVE(u); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | static char *acf_sort_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct localuser *u; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	LOCAL_USER_ACF_ADD(u); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (sort_internal(chan, data, buf, len)) { | 
					
						
							|  |  |  | 	case ERROR_NOARG: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "SORT() requires an argument\n"); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case ERROR_NOMEM: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Out of memory\n"); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 0: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unknown internal error\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	LOCAL_USER_REMOVE(u); | 
					
						
							|  |  |  | 	return buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *acf_cut_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct localuser *u; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	LOCAL_USER_ACF_ADD(u); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (cut_internal(chan, data, buf, len)) { | 
					
						
							|  |  |  | 	case ERROR_NOARG: | 
					
						
							| 
									
										
										
										
											2005-11-29 06:12:29 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "CUT() requires an argument\n"); | 
					
						
							| 
									
										
										
										
											2005-08-26 20:01:22 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case ERROR_NOMEM: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Out of memory\n"); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case ERROR_USAGE: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Usage: %s\n", cut_synopsis); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 0: | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unknown internal error\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	LOCAL_USER_REMOVE(u); | 
					
						
							|  |  |  | 	return buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct ast_custom_function acf_sort = { | 
					
						
							|  |  |  | 	.name = "SORT", | 
					
						
							|  |  |  | 	.synopsis = "Sorts a list of key/vals into a list of keys, based upon the vals", | 
					
						
							|  |  |  | 	.syntax = "SORT(key1:val1[...][,keyN:valN])", | 
					
						
							|  |  |  | 	.desc = | 
					
						
							|  |  |  | "Takes a comma-separated list of keys and values, each separated by a colon, and returns a\n" | 
					
						
							|  |  |  | "comma-separated list of the keys, sorted by their values.  Values will be evaluated as\n" | 
					
						
							|  |  |  | "floating-point numbers.\n", | 
					
						
							|  |  |  | 	.read = acf_sort_exec, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct ast_custom_function acf_cut = { | 
					
						
							|  |  |  | 	.name = "CUT", | 
					
						
							|  |  |  | 	.synopsis = "Slices and dices strings, based upon a named delimiter.", | 
					
						
							|  |  |  | 	.syntax = "CUT(<varname>,<char-delim>,<range-spec>)", | 
					
						
							|  |  |  | 	.desc = | 
					
						
							|  |  |  | "  varname    - variable you want cut\n" | 
					
						
							|  |  |  | "  char-delim - defaults to '-'\n" | 
					
						
							|  |  |  | "  range-spec - number of the field you want (1-based offset)\n" | 
					
						
							|  |  |  | "             may also be specified as a range (with -)\n" | 
					
						
							|  |  |  | "             or group of ranges and fields (with &)\n", | 
					
						
							|  |  |  | 	.read = acf_cut_exec, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | int unload_module(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-18 22:52:21 +00:00
										 |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	res = ast_custom_function_unregister(&acf_cut); | 
					
						
							|  |  |  | 	res |= ast_custom_function_unregister(&acf_sort); | 
					
						
							|  |  |  | 	res |= ast_unregister_application(app_sort); | 
					
						
							|  |  |  | 	res |= ast_unregister_application(app_cut); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | 	STANDARD_HANGUP_LOCALUSERS; | 
					
						
							| 
									
										
										
										
											2005-10-18 22:52:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int load_module(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-18 22:52:21 +00:00
										 |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	res = ast_custom_function_register(&acf_cut); | 
					
						
							|  |  |  | 	res |= ast_custom_function_register(&acf_sort); | 
					
						
							|  |  |  | 	res |= ast_register_application(app_sort, sort_exec, app_sort_synopsis, app_sort_descrip); | 
					
						
							|  |  |  | 	res |= ast_register_application(app_cut, cut_exec, cut_synopsis, cut_descrip); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2003-10-22 13:34:59 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *description(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return tdesc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int usecount(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 	STANDARD_USECOUNT(res); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *key() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ASTERISK_GPL_KEY; | 
					
						
							|  |  |  | } |