Index: apps/app_chanspy.c
===================================================================
--- apps/app_chanspy.c	(revision 102776)
+++ apps/app_chanspy.c	(working copy)
@@ -88,6 +88,9 @@
 "                    specified by the SPY_EXIT_CONTEXT channel variable. The\n"
 "                    name of the last channel that was spied on will be stored\n"
 "                    in the SPY_CHANNEL variable.\n"
+"    e(ext)        - Enable 'enforced' mode, so the spying channel can\n"
+"                    only monitor extensions whose name is in the 'ext' : \n"
+"                    delimited list.\n"
 ;
 
 static const char *app_ext = "ExtenSpy";
@@ -137,12 +140,14 @@
 	OPTION_PRIVATE   = (1 << 6),	/* Private Whisper mode */
 	OPTION_READONLY  = (1 << 7),	/* Don't mix the two channels */
 	OPTION_EXIT      = (1 << 8),	/* Exit to a valid single digit extension */
+	OPTION_ENFORCED  = (1 << 9),    /* Enforced mode */
 } chanspy_opt_flags;
 
 enum {
 	OPT_ARG_VOLUME = 0,
 	OPT_ARG_GROUP,
 	OPT_ARG_RECORD,
+	OPT_ARG_ENFORCED,
 	OPT_ARG_ARRAY_SIZE,
 } chanspy_opt_args;
 
@@ -154,6 +159,7 @@
 	AST_APP_OPTION_ARG('v', OPTION_VOLUME, OPT_ARG_VOLUME),
 	AST_APP_OPTION_ARG('g', OPTION_GROUP, OPT_ARG_GROUP),
 	AST_APP_OPTION_ARG('r', OPTION_RECORD, OPT_ARG_RECORD),
+	AST_APP_OPTION_ARG('e', OPTION_ENFORCED, OPT_ARG_ENFORCED),
 	AST_APP_OPTION('o', OPTION_READONLY),
 	AST_APP_OPTION('X', OPTION_EXIT),
 });
@@ -397,8 +403,8 @@
 }
 
 static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
-		       int volfactor, const int fd, const char *mygroup, const char *spec,
-		       const char *exten, const char *context)
+		       int volfactor, const int fd, const char *mygroup, const char *myenforced,
+		       const char *spec, const char *exten, const char *context)
 {
 	struct ast_channel *peer, *prev, *next;
 	char nameprefix[AST_NAME_STRLEN];
@@ -478,7 +484,12 @@
 			char *dup_group;
 			int x;
 			char *s;
-				
+			char *buffer;
+			char *end;
+			char *ext;
+			char *form_enforced;
+			int ienf = !myenforced;
+	
 			if (peer == prev)
 				break;
 
@@ -509,6 +520,60 @@
 			if (!igrp)
 				continue;
 
+			if (myenforced) {
+ 
+				/* We don't need to allocate more space than just the
+				length of (peer->name) for ext as we will cut the
+				channel name's ending before copying into ext */
+
+				ext = alloca(strlen(peer->name));
+
+ 				/* This one adds 3 characters in length to the colon
+				delimited list. Two characters are for the colons themselves
+				and the other is for the \0 character. */
+
+				form_enforced = alloca(strlen(myenforced) + 3);
+				
+				/* Now we add the colons to the string, one at the
+				beginning, one at the end, to make sure we
+				have properly colon delimited interface names in the
+				form_enforced string */
+				strcpy(form_enforced, ":");
+				strcat(form_enforced, myenforced);
+				strcat(form_enforced, ":");
+				
+				/* Putting the channel name into a temporary buffer, so we 
+				can add the colon at the beginning, for proper delimitation, and
+				preventing rather serious mistakes. */
+				buffer = ast_strdupa(peer->name);
+				
+				/* We find the end of the peer->name, which includes a bunch of
+				crap as some channel id or something, so we waste that, and just
+				keep the peer name proper involved in the conversation */
+				if ((end = strchr(buffer, '-'))) {
+				    *end++ = ':';
+				    *end = '\0';
+				}
+				
+				/* Now we add a beginning colon for the proper delimitation, and
+				we add then the peer name itself. We now have a proper peer name
+				delimited on both sides by colons, and this will prevent all future
+				massive fuckups. */
+				strcpy(ext, ":");
+				strcat(ext, buffer);				
+
+				/* Is the peer name we are trying to spy on in the list of allowed
+				interfaces? If it is, then we are good to go. If not, then we are not
+				allowed to spy on that interface, and we let the sucker move on to
+				an interface he has the right to spy on, maybe some other time. */
+				if (strcasestr(form_enforced, ext))
+					ienf = 1;
+
+			}
+
+			if (!ienf)
+				continue;
+
 			strcpy(peer_name, "spy-");
 			strncat(peer_name, peer->name, AST_NAME_STRLEN);
 			ptr = strchr(peer_name, '/');
@@ -562,6 +627,7 @@
 
 static int chanspy_exec(struct ast_channel *chan, void *data)
 {
+	char *myenforced = NULL;
 	char *mygroup = NULL;
 	char *recbase = NULL;
 	int fd = 0;
@@ -601,6 +667,10 @@
 
 		if (ast_test_flag(&flags, OPTION_PRIVATE))
 			ast_set_flag(&flags, OPTION_WHISPER);
+
+		if (ast_test_flag(&flags, OPTION_ENFORCED))
+			myenforced = opts[OPT_ARG_ENFORCED];
+
 	} else
 		ast_clear_flag(&flags, AST_FLAGS_ALL);
 
@@ -620,7 +690,7 @@
 		}
 	}
 
-	res = common_exec(chan, &flags, volfactor, fd, mygroup, args.spec, NULL, NULL);
+	res = common_exec(chan, &flags, volfactor, fd, mygroup, myenforced, args.spec, NULL, NULL);
 
 	if (fd)
 		close(fd);
@@ -699,8 +769,9 @@
 		}
 	}
 
-	res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, args.context);
 
+	res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, NULL, exten, args.context);
+
 	if (fd)
 		close(fd);
 
