mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 18:55:19 +00:00 
			
		
		
		
	add privacy/screening functionality to app_dial (bug #752)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6102 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							| @@ -462,6 +462,7 @@ clean: | ||||
| datafiles: all | ||||
| 	sh mkpkgconfig $(DESTDIR)/usr/lib/pkgconfig | ||||
| 	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits | ||||
| 	mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/priv-callerintros | ||||
| 	for x in sounds/digits/*.gsm; do \ | ||||
| 		if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \ | ||||
| 			install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits ; \ | ||||
|   | ||||
							
								
								
									
										314
									
								
								apps/app_dial.c
									
									
									
									
									
								
							
							
						
						
									
										314
									
								
								apps/app_dial.c
									
									
									
									
									
								
							| @@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| #include "asterisk/app.h" | ||||
| #include "asterisk/causes.h" | ||||
| #include "asterisk/manager.h" | ||||
| #include "asterisk/privacy.h" | ||||
|  | ||||
| static char *tdesc = "Dialing Application"; | ||||
|  | ||||
| @@ -63,6 +64,10 @@ static char *descrip = | ||||
| "n is the priority of the dialer instance), then it will be the next\n" | ||||
| "executed extension (this allows you to setup different behavior on busy from\n" | ||||
| "no-answer).\n" | ||||
| "  For the Privacy and Screening Modes, the DIALSTATUS variable will be set to DONTCALL, \n" | ||||
| "if the called party chooses to send the calling party to the 'Go Away' script, and \n" | ||||
| "the DIALSTATUS variable will be set to TORTURE, if the called party wants to send the caller to \n" | ||||
| "the TORTURE scripts\n" | ||||
| "  This application returns -1 if the originating channel hangs up, or if the\n" | ||||
| "call is bridged and either of the parties in the bridge terminate the call.\n" | ||||
| "The option string may contain zero or more of the following characters:\n" | ||||
| @@ -92,7 +97,10 @@ static char *descrip = | ||||
| "      'h' -- allow callee to hang up by hitting *.\n" | ||||
| "      'H' -- allow caller to hang up by hitting *.\n" | ||||
| "      'C' -- reset call detail record for this call.\n" | ||||
| "      'P[(x)]' -- privacy mode, using 'x' as database if provided.\n" | ||||
| "      'P[(x)]' -- privacy mode, using 'x' as database if provided, or the extension is used if not provided.\n" | ||||
| "      'p' -- screening mode.  Basically Privacy mode without memory.\n" | ||||
| "       'n' -- modifier for screen/privacy mode. No intros are to be saved in the priv-callerintros dir.\n" | ||||
| "       'N' -- modifier for screen/privacy mode. if callerID is present, do not screen the call.\n" | ||||
| "      'g' -- goes on in context if the destination channel hangs up\n" | ||||
| "      'G(context^exten^pri)' -- If the call is answered transfer both parties to the specified exten.\n" | ||||
| "      'A(x)' -- play an announcement to the called party, using x as file\n" | ||||
| @@ -112,7 +120,7 @@ static char *descrip = | ||||
| "             * LIMIT_WARNING_FILE        File to play as warning if 'y' is defined.\n" | ||||
| "                        'timeleft' is a special sound macro to auto-say the time \n" | ||||
| "                        left and is the default.\n" | ||||
| "       'n' -- Do not jump to n+101 if all of the channels were busy.\n\n" | ||||
| "       'j' -- Do not jump to n+101 if all of the channels were busy.\n\n" | ||||
| "  In addition to transferring the call, a call may be parked and then picked\n" | ||||
| "up by another user.\n" | ||||
| "  The optional URL will be sent to the called party if the channel supports it.\n" | ||||
| @@ -122,7 +130,7 @@ static char *descrip = | ||||
| "      DIALEDTIME    Time from dial to answer\n"  | ||||
| "      ANSWEREDTIME  Time for actual call\n" | ||||
| "      DIALSTATUS    The status of the call as a text string, one of\n" | ||||
| "             CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n" | ||||
| "             CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL | DONTCALL | TORTURE\n" | ||||
| ""; | ||||
|  | ||||
| /* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */ | ||||
| @@ -610,12 +618,17 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags | ||||
| 	struct localuser *u; | ||||
| 	char *info, *peers, *timeout, *tech, *number, *rest, *cur; | ||||
| 	char  privdb[256] = "", *s; | ||||
| 	char  privcid[256] = ""; | ||||
| 	char privintro[1024]; | ||||
| 	char  announcemsg[256] = "", *ann; | ||||
| 	struct localuser *outgoing=NULL, *tmp; | ||||
| 	struct ast_channel *peer; | ||||
| 	int to; | ||||
| 	int hasmacro = 0; | ||||
| 	int privacy=0; | ||||
| 	int screen=0; | ||||
| 	int no_save_intros = 0; | ||||
| 	int no_screen_callerid = 0; | ||||
| 	int announce=0; | ||||
| 	int resetcdr=0; | ||||
| 	int numbusy = 0; | ||||
| @@ -629,6 +642,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags | ||||
| 	char *newnum; | ||||
| 	char *l; | ||||
| 	char *url=NULL; /* JDG */ | ||||
| 	int privdb_val=0; | ||||
| 	unsigned int calldurationlimit=0; | ||||
| 	char *cdl; | ||||
| 	time_t now; | ||||
| @@ -814,7 +828,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags | ||||
| 				*(ann++) = 'X'; | ||||
| 			if (*ann) | ||||
| 				*ann = 'X'; | ||||
| 			/* Now find the end of the privdb */ | ||||
| 			/* Now find the end of the announce */ | ||||
| 			ann = strchr(announcemsg, ')'); | ||||
| 			if (ann) | ||||
| 				*ann = '\0'; | ||||
| @@ -906,11 +920,19 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags | ||||
| 		} else if (strchr(transfer, 'P')) { | ||||
| 			/* No specified privdb */ | ||||
| 			privacy = 1; | ||||
| 		} else if (strchr(transfer, 'p')) { | ||||
| 			screen = 1; | ||||
| 		} else if (strchr(transfer, 'C')) { | ||||
| 			resetcdr = 1; | ||||
| 		} else if (strchr(transfer, 'n')) { | ||||
| 		} else if (strchr(transfer, 'j')) { | ||||
| 			nojump = 1; | ||||
| 		} | ||||
| 		if (strchr(transfer, 'n')) { | ||||
| 			no_save_intros = 1; | ||||
| 		}  | ||||
| 		if (strchr(transfer, 'N')) { | ||||
| 			no_screen_callerid = 1; | ||||
| 		} | ||||
| 	} | ||||
| 	if (resetcdr && chan->cdr) | ||||
| 		ast_cdr_reset(chan->cdr, 0); | ||||
| @@ -918,11 +940,97 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags | ||||
| 		/* If privdb is not specified and we are using privacy, copy from extension */ | ||||
| 		ast_copy_string(privdb, chan->exten, sizeof(privdb)); | ||||
| 	} | ||||
| 	if (privacy) { | ||||
| 	if (privacy || screen) { | ||||
| 		char callerid[60]; | ||||
|  | ||||
| 		l = chan->cid.cid_num; | ||||
| 		if (!l) | ||||
| 			l = ""; | ||||
| 		ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l); | ||||
| 		if (l && !ast_strlen_zero(l)) { | ||||
| 			ast_shrink_phone_number(l); | ||||
| 			if( privacy ) { | ||||
| 				if (option_verbose > 2) | ||||
| 					ast_verbose( VERBOSE_PREFIX_3  "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l); | ||||
| 				privdb_val = ast_privacy_check(privdb, l); | ||||
| 			} | ||||
| 			else { | ||||
| 				if (option_verbose > 2) | ||||
| 					ast_verbose( VERBOSE_PREFIX_3  "Privacy Screening, clid is '%s'\n", l); | ||||
| 				privdb_val = AST_PRIVACY_UNKNOWN; | ||||
| 			} | ||||
| 		} else { | ||||
| 			char *tnam, *tn2; | ||||
|  | ||||
| 			tnam = ast_strdupa(chan->name); | ||||
| 			/* clean the channel name so slashes don't try to end up in disk file name */ | ||||
| 			for(tn2 = tnam; *tn2; tn2++) { | ||||
| 				if( *tn2=='/') | ||||
| 					*tn2 = '=';  /* any other chars to be afraid of? */ | ||||
| 			} | ||||
| 			if (option_verbose > 2) | ||||
| 				ast_verbose( VERBOSE_PREFIX_3  "Privacy-- callerid is empty\n"); | ||||
|  | ||||
| 			snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam); | ||||
| 			l = callerid; | ||||
| 			privdb_val = AST_PRIVACY_UNKNOWN; | ||||
| 		} | ||||
| 		 | ||||
| 		ast_copy_string(privcid,l,sizeof(privcid)); | ||||
|  | ||||
| 		if( strncmp(privcid,"NOCALLERID",10) != 0 && no_screen_callerid ) { /* if callerid is set, and no_screen_callerid is set also */   | ||||
| 			if (option_verbose > 2) | ||||
| 				ast_verbose( VERBOSE_PREFIX_3  "CallerID set (%s); N option set; Screening should be off\n", privcid); | ||||
| 			privdb_val = AST_PRIVACY_ALLOW; | ||||
| 		} | ||||
| 		else if( no_screen_callerid && strncmp(privcid,"NOCALLERID",10) == 0 ) { | ||||
| 			if (option_verbose > 2) | ||||
| 				ast_verbose( VERBOSE_PREFIX_3  "CallerID blank; N option set; Screening should happen; dbval is %d\n", privdb_val); | ||||
| 		} | ||||
| 		 | ||||
| 		if( privdb_val == AST_PRIVACY_DENY ) { | ||||
| 			ast_verbose( VERBOSE_PREFIX_3  "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n"); | ||||
| 			res=0; | ||||
| 			goto out; | ||||
| 		} | ||||
| 		else if( privdb_val == AST_PRIVACY_KILL ) { | ||||
| 			if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 201, chan->cid.cid_num))  | ||||
| 				chan->priority+=200; | ||||
|  | ||||
| 			res = 0; | ||||
| 			goto out; /* Is this right? */ | ||||
| 		} | ||||
| 		else if( privdb_val == AST_PRIVACY_TORTURE ) { | ||||
| 			if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 301, chan->cid.cid_num))  | ||||
| 				chan->priority+=300; | ||||
| 			res = 0; | ||||
| 			goto out; /* is this right??? */ | ||||
|  | ||||
| 		} | ||||
| 		else if( privdb_val == AST_PRIVACY_UNKNOWN ) { | ||||
| 			/* Get the user's intro, store it in priv-callerintros/$CID,  | ||||
| 			   unless it is already there-- this should be done before the  | ||||
| 			   call is actually dialed  */ | ||||
|  | ||||
| 			/* make sure the priv-callerintros dir exists? */ | ||||
|  | ||||
| 			snprintf(privintro,sizeof(privintro),"priv-callerintros/%s", privcid); | ||||
| 			if( ast_fileexists(privintro,NULL,NULL ) > 0 && strncmp(privcid,"NOCALLERID",10) != 0) { | ||||
| 				/* the DELUX version of this code would allow this caller the | ||||
| 				   option to hear and retape their previously recorded intro. | ||||
| 				*/ | ||||
| 			} | ||||
| 			else { | ||||
| 				int duration; /* for feedback from play_and_wait */ | ||||
| 				/* the file doesn't exist yet. Let the caller submit his | ||||
| 				   vocal intro for posterity */ | ||||
| 				/* priv-recordintro script: | ||||
|  | ||||
| 				   "At the tone, please say your name:" | ||||
|  | ||||
| 				*/ | ||||
| 				ast_play_and_record(chan, "priv-recordintro", privintro, 4, "gsm", &duration, 128, 2000, 0);  /* NOTE: I've reduced the total time to 4 sec */ | ||||
| 															/* don't think we'll need a lock removed, we took care of | ||||
| 															   conflicts by naming the privintro file */ | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* If a channel group has been specified, get it for use when we create peer channels */ | ||||
| @@ -1172,6 +1280,194 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags | ||||
|  			ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url); | ||||
|  			ast_channel_sendurl( peer, url ); | ||||
|  		} /* /JDG */ | ||||
| 		if( privacy || screen ) { | ||||
| 			int res2; | ||||
| 			int loopcount = 0; | ||||
| 			if( privdb_val == AST_PRIVACY_UNKNOWN ) { | ||||
|  | ||||
| 				/* Get the user's intro, store it in priv-callerintros/$CID,  | ||||
| 				   unless it is already there-- this should be done before the  | ||||
| 				   call is actually dialed  */ | ||||
|  | ||||
| 				/* all ring indications and moh for the caller has been halted as soon as the  | ||||
| 				   target extension was picked up. We are going to have to kill some | ||||
| 				   time and make the caller believe the peer hasn't picked up yet */ | ||||
|  | ||||
| 				if ( strchr(transfer, 'm') ) { | ||||
| 					ast_indicate(chan, -1); | ||||
| 					ast_moh_start(chan, mohclass); | ||||
| 				} else if ( strchr(transfer, 'r') ) { | ||||
| 					ast_indicate(chan, AST_CONTROL_RINGING); | ||||
| 					sentringing++; | ||||
| 				} | ||||
|  | ||||
| 				/* Start autoservice on the other chan ?? */ | ||||
| 				res2 = ast_autoservice_start(chan); | ||||
| 				/* Now Stream the File */ | ||||
| 				if (!res2) { | ||||
| 					do { | ||||
| 						if (!res2) | ||||
| 							res2 = ast_play_and_wait(peer,"priv-callpending"); | ||||
| 						if( res2 < '1' || (privacy && res2>'5') || (screen && res2 > '4') ) /* uh, interrupting with a bad answer is ... ignorable! */ | ||||
| 							res2 = 0; | ||||
| 						 | ||||
| 						/* priv-callpending script:  | ||||
| 						   "I have a caller waiting, who introduces themselves as:" | ||||
| 						*/ | ||||
| 						if (!res2) | ||||
| 							res2 = ast_play_and_wait(peer,privintro); | ||||
| 						if( res2 < '1' || (privacy && res2>'5') || (screen && res2 > '4') ) /* uh, interrupting with a bad answer is ... ignorable! */ | ||||
| 							res2 = 0; | ||||
| 						/* now get input from the called party, as to their choice */ | ||||
| 						if( !res2 ) { | ||||
| 							if( privacy ) | ||||
| 								res2 = ast_play_and_wait(peer,"priv-callee-options"); | ||||
| 							if( screen ) | ||||
| 								res2 = ast_play_and_wait(peer,"screen-callee-options"); | ||||
| 						} | ||||
| 						/* priv-callee-options script: | ||||
| 							"Dial 1 if you wish this caller to reach you directly in the future, | ||||
| 								and immediately connect to their incoming call | ||||
| 							 Dial 2 if you wish to send this caller to voicemail now and  | ||||
| 								forevermore. | ||||
| 							 Dial 3 to send this callerr to the torture menus, now and forevermore. | ||||
| 							 Dial 4 to send this caller to a simple "go away" menu, now and forevermore. | ||||
| 							 Dial 5 to allow this caller to come straight thru to you in the future, | ||||
| 						but right now, just this once, send them to voicemail." | ||||
| 						*/ | ||||
| 				 | ||||
| 						/* screen-callee-options script: | ||||
| 							"Dial 1 if you wish to immediately connect to the incoming call | ||||
| 							 Dial 2 if you wish to send this caller to voicemail. | ||||
| 							 Dial 3 to send this callerr to the torture menus. | ||||
| 							 Dial 4 to send this caller to a simple "go away" menu. | ||||
| 						*/ | ||||
| 						if( !res2 || res2 < '1' || (privacy && res2 > '5') || (screen && res2 > '4') ) { | ||||
| 							/* invalid option */ | ||||
| 							res2 = ast_play_and_wait(peer,"vm-sorry"); | ||||
| 						} | ||||
| 						loopcount++; /* give the callee a couple chances to make a choice */ | ||||
| 					} while( (!res2 || res2 < '1' || (privacy && res2 > '5') || (screen && res2 > '4')) && loopcount < 2 ); | ||||
| 				} | ||||
|  | ||||
| 				switch(res2) { | ||||
| 				case '1': | ||||
| 					if( privacy ) { | ||||
| 						if (option_verbose > 2) | ||||
| 							ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n", privdb, privcid); | ||||
| 						ast_privacy_set(privdb,privcid,AST_PRIVACY_ALLOW); | ||||
| 					} | ||||
| 					break; | ||||
| 				case '2': | ||||
| 					if( privacy ) { | ||||
| 						if (option_verbose > 2) | ||||
| 							ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to DENY\n", privdb, privcid); | ||||
| 						ast_privacy_set(privdb,privcid,AST_PRIVACY_DENY); | ||||
| 					} | ||||
| 					if ( strchr(transfer, 'm') ) { | ||||
| 						ast_moh_stop(chan); | ||||
| 					} else if ( strchr(transfer, 'r') ) { | ||||
| 						ast_indicate(chan, -1); | ||||
| 						sentringing=0; | ||||
| 					} | ||||
| 					res2 = ast_autoservice_stop(chan); | ||||
| 					ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */ | ||||
| 					res=0; | ||||
| 					goto out; | ||||
| 					break; | ||||
| 				case '3': | ||||
| 					if( privacy ) { | ||||
| 						ast_privacy_set(privdb,privcid,AST_PRIVACY_TORTURE); | ||||
| 						if (option_verbose > 2) | ||||
| 							ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to TORTURE\n", privdb, privcid); | ||||
| 					} | ||||
| 					ast_copy_string(status, "TORTURE", sizeof(status)); | ||||
| 					 | ||||
| 					res = 0; | ||||
| 					if ( strchr(transfer, 'm') ) { | ||||
| 						ast_moh_stop(chan); | ||||
| 					} else if ( strchr(transfer, 'r') ) { | ||||
| 						ast_indicate(chan, -1); | ||||
| 						sentringing=0; | ||||
| 					} | ||||
| 					res2 = ast_autoservice_stop(chan); | ||||
| 					ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */ | ||||
| 					goto out; /* Is this right? */ | ||||
| 					break; | ||||
| 				case '4': | ||||
| 					if( privacy ) { | ||||
| 						if (option_verbose > 2) | ||||
| 							ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to KILL\n", privdb, privcid); | ||||
| 						ast_privacy_set(privdb,privcid,AST_PRIVACY_KILL); | ||||
| 					} | ||||
|  | ||||
| 					ast_copy_string(status, "DONTCALL", sizeof(status)); | ||||
| 					res = 0; | ||||
| 					if ( strchr(transfer, 'm') ) { | ||||
| 						ast_moh_stop(chan); | ||||
| 					} else if ( strchr(transfer, 'r') ) { | ||||
| 						ast_indicate(chan, -1); | ||||
| 						sentringing=0; | ||||
| 					} | ||||
| 					res2 = ast_autoservice_stop(chan); | ||||
| 					ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */ | ||||
| 					goto out; /* Is this right? */ | ||||
| 					break; | ||||
| 				case '5': | ||||
| 					if( privacy ) { | ||||
| 						if (option_verbose > 2) | ||||
| 							ast_verbose( VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to ALLOW\n", privdb, privcid); | ||||
| 						ast_privacy_set(privdb,privcid,AST_PRIVACY_ALLOW); | ||||
| 					 | ||||
| 						if ( strchr(transfer, 'm') ) { | ||||
| 							ast_moh_stop(chan); | ||||
| 						} else if ( strchr(transfer, 'r') ) { | ||||
| 							ast_indicate(chan, -1); | ||||
| 							sentringing=0; | ||||
| 						} | ||||
| 						res2 = ast_autoservice_stop(chan); | ||||
| 						ast_hangup(peer); /* hang up on the caller -- he didn't want to talk anyway! */ | ||||
| 						res=0; | ||||
| 						goto out; | ||||
| 						break; | ||||
| 					} /* if not privacy, then 5 is the same as "default" case */ | ||||
| 				default: | ||||
| 					/* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do?  */ | ||||
| 					/* well, there seems basically two choices. Just patch the caller thru immediately, | ||||
| 				                  or,... put 'em thru to voicemail. */ | ||||
| 					/* since the callee may have hung up, let's do the voicemail thing, no database decision */ | ||||
| 					if (option_verbose > 2) | ||||
| 						ast_log(LOG_NOTICE,"privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n"); | ||||
| 					if ( strchr(transfer, 'm') ) { | ||||
| 						ast_moh_stop(chan); | ||||
| 					} else if ( strchr(transfer, 'r') ) { | ||||
| 						ast_indicate(chan, -1); | ||||
| 						sentringing=0; | ||||
| 					} | ||||
| 					res2 = ast_autoservice_stop(chan); | ||||
| 					ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */ | ||||
| 					res=0; | ||||
| 					goto out; | ||||
| 					break; | ||||
| 				} | ||||
| 				if ( strchr(transfer, 'm') ) { | ||||
| 					ast_moh_stop(chan); | ||||
| 				} else if ( strchr(transfer, 'r') ) { | ||||
| 					ast_indicate(chan, -1); | ||||
| 					sentringing=0; | ||||
| 				} | ||||
| 				res2 = ast_autoservice_stop(chan); | ||||
| 				/* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll  | ||||
| 				   just clog things up, and it's not useful information, not being tied to a CID */ | ||||
| 				if( strncmp(privcid,"NOCALLERID",10) == 0 || no_save_intros ) { | ||||
| 					ast_filedelete(privintro, NULL); | ||||
| 					if( ast_fileexists(privintro,NULL,NULL ) > 0 ) | ||||
| 						ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", privintro); | ||||
| 					else if (option_verbose > 2) | ||||
| 						ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", privintro); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if (announce && announcemsg) { | ||||
| 			/* Start autoservice on the other chan */ | ||||
| 			res = ast_autoservice_start(chan); | ||||
|   | ||||
| @@ -304,6 +304,31 @@ exten => _s-.,1,Goto(s-NOANSWER,1)				; Treat anything else as no answer | ||||
|  | ||||
| exten => a,1,VoicemailMain(${ARG1})				; If they press *, send the user into VoicemailMain | ||||
|  | ||||
| [macro-stdPrivacyexten]; | ||||
| ; | ||||
| ; Standard extension macro: | ||||
| ;   ${ARG1} - Extension  (we could have used ${MACRO_EXTEN} here as well | ||||
| ;   ${ARG2} - Device(s) to ring | ||||
| ;   ${ARG3} - Optional DONTCALL context name to jump to (assumes the s,1 extension-priority) | ||||
| ;   ${ARG4} - Optional TORTURE context name to jump to (assumes the s,1 extension-priority)` | ||||
| ; | ||||
| exten => s,1,Dial(${ARG2},20|p)					; Ring the interface, 20 seconds maximum, call screening option (or use P for databased call screening) | ||||
| exten => s,2,Goto(s-${DIALSTATUS},1)				; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER) | ||||
|  | ||||
| exten => s-NOANSWER,1,Voicemail(u${ARG1})		; If unavailable, send to voicemail w/ unavail announce | ||||
| exten => s-NOANSWER,2,Goto(default,s,1)			; If they press #, return to start | ||||
|  | ||||
| exten => s-BUSY,1,Voicemail(b${ARG1})			; If busy, send to voicemail w/ busy announce | ||||
| exten => s-BUSY,2,Goto(default,s,1)				; If they press #, return to start | ||||
|  | ||||
| exten => s-DONTCALL,1,Goto(${ARG3},s,1)               ; Callee chose to send this call to a polite "Don't call again" script. | ||||
|  | ||||
| exten => s-TORTURE,1,Goto(${ARG4},s,1)                ; Callee chose to send this call to a telemarketer torture script. | ||||
|  | ||||
| exten => _s-.,1,Goto(s-NOANSWER,1)				; Treat anything else as no answer | ||||
|  | ||||
| exten => a,1,VoicemailMain(${ARG1})				; If they press *, send the user into VoicemailMain | ||||
|  | ||||
| [demo] | ||||
| ; | ||||
| ; We start with what to do when a call first comes in. | ||||
|   | ||||
							
								
								
									
										361
									
								
								doc/README.privacy
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										361
									
								
								doc/README.privacy
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,361 @@ | ||||
| Title: Everything About The Privacy Options In The Dial Command That | ||||
| You Never Wanted To Know, And Even A Little More On Zapateller and | ||||
| PrivacyManager: | ||||
|  | ||||
| by Steve Murphy | ||||
|  | ||||
|  | ||||
| So, you want to avoid talking to pesky telemarketers/charity | ||||
| seekers/poll takers/magazine renewers/etc? | ||||
|  | ||||
| ============= | ||||
| First of all: | ||||
| ============= | ||||
|  | ||||
| Try the FTC "Don't call" database, this alone will reduce your | ||||
| telemarketing call volume considerably.  (see: | ||||
| https://www.donotcall.gov/default.aspx ) But, this list won't protect | ||||
| from the Charities, previous business relationships, etc. | ||||
|  | ||||
|  | ||||
| ================================= | ||||
| Next, Fight against autodialers!! | ||||
| ================================= | ||||
|  | ||||
| Zapateller detects if callerid is present, and if not, plays the | ||||
| da-da-da tones that immediately precede messages like, "I'm sorry, | ||||
| the number you have called is no longer in service." | ||||
|  | ||||
| Most humans, even those with unlisted/callerid-blocked numbers, will | ||||
| not immediately slam the handset down on the hook the moment they hear | ||||
| the three tones. But autodialers seem pretty quick to do this. | ||||
|  | ||||
| I just counted 40 hangups in Zapateller over the last year in my | ||||
| CDR's.  So, that is possibly 40 different telemarketers/charities that have | ||||
| hopefully slashed my back-waters, out-of-the-way, humble home phone | ||||
| number from their lists. | ||||
|  | ||||
| I highly advise Zapateller for those seeking the nirvana of "privacy". | ||||
|  | ||||
|  | ||||
| ======================================= | ||||
| Next, Fight against the empty CALLERID! | ||||
| ======================================= | ||||
|  | ||||
| A considerable percentage of the calls you don't want, come from | ||||
| sites that do not provide CallerID.  | ||||
|  | ||||
| Null callerid's are a fact of life, and could be a friend with an | ||||
| unlisted number, or some charity looking for a handout. The | ||||
| PrivacyManager application can help here. It will ask the caller to | ||||
| enter a 10-digit phone number. They get 3 tries(configurable), and this is | ||||
| configurable, with control being passed to priority+101 if they won't | ||||
| supply one. | ||||
|  | ||||
| PrivacyManager can't guarantee that the number they supply is any | ||||
| good, tho, as there is no way to find out, short of hanging up and | ||||
| calling them back. But some answers are obviously wrong. For instance, | ||||
| it seems a common practice for telemarketers to use your own number | ||||
| instead of giving you theirs. A simple test can detect this. More | ||||
| advanced tests would be to look for -555- numbers, numbers that count | ||||
| up or down, numbers of all the same digit, etc. | ||||
|  | ||||
| My logs show that 39 have hung up in the PrivacyManager script over | ||||
| the last year. | ||||
|  | ||||
| (Note: Demanding all unlisted incoming callers to enter their CID may | ||||
| not always be appropriate for all users. Another option might be to | ||||
| use call screening. See below.) | ||||
|  | ||||
| ========================== | ||||
| Next, use a WELCOME MENU ! | ||||
| ========================== | ||||
|  | ||||
| Experience has shown that simply presenting incoming callers with | ||||
| a set of options, no matter how simple, will deter them from calling | ||||
| you. In the vast majority of situations, a telemarketer will simply | ||||
| hang up rather than make a choice and press a key. | ||||
|  | ||||
| This will also immediately foil all autodialers that simply belch a | ||||
| message in your ear and hang up. | ||||
|  | ||||
|  | ||||
| ---------------------------------------------- | ||||
| Example usage of Zapateller and PrivacyManager: | ||||
| ---------------------------------------------- | ||||
|  | ||||
| [homeline] | ||||
| exten => s,1,Answer | ||||
| exten => s,2,SetVar,repeatcount=0 | ||||
| exten => s,3,Zapateller,nocallerid | ||||
| exten => s,4,PrivacyManager | ||||
| exten => s,105,Background(tt-allbusy)       ;; do this if they don't enter a number to Privacy Manager | ||||
| exten => s,106,Background(tt-somethingwrong) | ||||
| exten => s,107,Background(tt-monkeysintro) | ||||
| exten => s,108,Background(tt-monkeys) | ||||
| exten => s,109,Background(tt-weasels) | ||||
| exten => s,110,Hangup | ||||
| exten => s,5,GotoIf($[ "${CALLERIDNUM}"  = "7773334444" &  "${CALLERIDNAME}" : "Privacy Manager" ]?callerid-liar|s|1:s|7) | ||||
|  | ||||
| I suggest using Zapateller at the beginning of the context, before | ||||
| anything else, on incoming calls.This can be followed by the | ||||
| PrivacyManager App. | ||||
|  | ||||
| Make sure, if you do the PrivacyManager app, that you take care of the | ||||
| error condition! or their non-compliance will be rewarded with access | ||||
| to the system. In the above, if they can't enter a 10-digit number in | ||||
| 3 tries, they get the humorous "I'm sorry, but all household members | ||||
| are currently helping other telemarketers...", "something is terribly | ||||
| wrong", "monkeys have carried them away...", various loud monkey | ||||
| screechings, "weasels have...", and a hangup. There are plenty of | ||||
| other paths to my torture scripts, I wanted to have some fun. | ||||
|  | ||||
| In nearly all cases now, the telemarketers/charity-seekers that | ||||
| usually get thru to my main intro, hang up. I guess they can see it's | ||||
| pointless, or the average telemarketer/charity-seeker is instructed | ||||
| not to enter options when encountering such systems. Don't know.  | ||||
|  | ||||
| =================== | ||||
| Next: Torture Them! | ||||
| =================== | ||||
|  | ||||
| I have developed an elaborate script to torture Telemarketers, and | ||||
| entertain friends. (See | ||||
| http://www.voip-info.org/wiki-Asterisk+Telemarketer+Torture ) | ||||
|  | ||||
| While mostly those that call in and traverse my teletorture scripts | ||||
| are those we know, and are doing so out of curiosity, there have been | ||||
| these others from Jan 1st,2004 thru June 1st, 2004: | ||||
| (the numbers may or may not be correct.) | ||||
|  | ||||
| 603890zzzz     hung up telemarket options. | ||||
| "Integrated Sale"  called a couple times. hung up in telemarket options | ||||
| "UNITED STATES GOV"  (-- maybe a military recruiter, trying to lure one of my sons). | ||||
| 800349zzzz -- hung up in charity intro | ||||
| 800349zzzz -- hung up in charity choices, intro, about the only one who actually travelled to the bitter bottom of the scripts! | ||||
| 216377zzzz -- hung up the magazine section | ||||
| 626757zzzz = "LIR    " (pronounced "Liar"?) hung up in telemarket intro, then choices | ||||
| 757821zzzz -- hung up in new magazine subscription options. | ||||
|  | ||||
| That averages out to maybe 1 a month. That puts into question whether | ||||
| the ratio of the amount of labor it took to make the scripts versus | ||||
| the benefits of lower call volumes was worth it, but, well, I had fun, | ||||
| so what the heck. | ||||
|  | ||||
| but, that's about it. Not a whole lot. But I haven't had to say "NO" | ||||
| or "GO AWAY" to any of these folks for about a year now ...! | ||||
|  | ||||
| ======================================== | ||||
|       Using Call Screening | ||||
| ======================================= | ||||
|  | ||||
| Another option is to use call screening in the Dial command. It has | ||||
| two main privacy modes, one that remembers the CID of the caller, and | ||||
| how the callee wants the call handled, and the other, which does not | ||||
| have a "memory". | ||||
|  | ||||
| Turning on these modes in the dial command results in this sequence of | ||||
| events, when someone calls you at an extension: | ||||
|  | ||||
| 1. The caller calls the Asterisk system, and at some point, selects an | ||||
| option or enters an extension number that would dial your extension. | ||||
|  | ||||
| 2. Before ringing your extension, the caller is asked to supply an | ||||
| introduction. The application asks them: "After the tone, say your | ||||
| name". They are allowed 4 seconds of introduction. | ||||
|  | ||||
| 3. After that, they are told "Hang on, we will attempt to connect you | ||||
| to your party. Depending on your dial options, they will hear ringing | ||||
| indications, or get music on hold. I suggest music on hold. | ||||
|  | ||||
| 4. Your extension is then dialed. When (and if) you pick up, you are | ||||
| told that a caller presenting themselves as <their recorded intro is | ||||
| played> is calling, and you have options, like being connected, | ||||
| sending them to voicemail, torture, etc. | ||||
|  | ||||
| 5. You make your selection, and the call is handled as you chose. | ||||
|  | ||||
|  | ||||
| There are some variations, and these will be explained in due course. | ||||
|  | ||||
|  | ||||
| To use these options, set your Dial to something like: | ||||
|  | ||||
| exten => 3,3,Dial(Zap/5r3&Zap/6r3|35|tmPA(beep)) | ||||
|  | ||||
| or  | ||||
|  | ||||
| exten => 3,3,Dial(Zap/5r3&Zap/6r3|35|tmP(something)A(beep)) | ||||
|  | ||||
| or  | ||||
|  | ||||
| exten => 3,3,Dial(Zap/5r3&Zap/6r3|35|tmpA(beep)) | ||||
|  | ||||
|  | ||||
| The 't' allows the dialed party to transfer the call using '#'. It's | ||||
| optional. | ||||
|  | ||||
| The 'm' is for music on hold. I suggest it. Otherwise, the calling | ||||
| party gets to hear all the ringing, and lack thereof. It is generally | ||||
| better to use Music On Hold. Lots of folks hang up after the 3rd or | ||||
| 4th ring, and you might lose the call before you can enter an option! | ||||
|  | ||||
| The 'P' option alone will database everything using the extension as a | ||||
| default 'tree'. To get multiple extensions sharing the same database, use | ||||
| P(some-shared-key). Also, if the same person has multiple extensions, | ||||
| use P(unique-id) on all their dial commands. | ||||
|  | ||||
| Use little 'p' for screening. Every incoming call will include a | ||||
| prompt for the callee's choice.  | ||||
|  | ||||
| the A(beep), will generate a 'beep' that the callee will hear if they | ||||
| choose to talk to the caller. It's kind of a prompt to let the callee | ||||
| know that he has to say 'hi'. It's not required, but I find it | ||||
| helpful. | ||||
|  | ||||
| When there is no CallerID, P and p options will always record an intro | ||||
| for the incoming caller. This intro will be stored temporarily in the | ||||
| /var/lib/asterisk/sounds/priv-callerintros dir, under the name | ||||
| NOCALLERID_<extension><channelname> and will be erased after the | ||||
| callee decides what to do with the call. | ||||
|  | ||||
| Of course, NOCALLERID is not stored in the database. All those with no | ||||
| CALLERID will be considered "Unknown". | ||||
|  | ||||
| ======================== | ||||
|  The 'N' and 'n' options | ||||
| ======================== | ||||
|  | ||||
| Two other options exist, that act as modifiers to the privacy options | ||||
| 'P' and 'p'. They are 'N' and 'n'. You can enter them as dialing | ||||
| options, but they only affect things if P or p are also in the | ||||
| options. | ||||
|  | ||||
| 'N' says, "Only screen the call if no CallerID is present". So, if a | ||||
| callerID were supplied, it will come straight thru to your extension. | ||||
|  | ||||
| 'n' says, "Don't save any introductions". Folks will be asked to | ||||
| supply an introduction ("At the tone, say your name") every time they | ||||
| call. Their introductions will be removed after the callee makes a | ||||
| choice on how to handle the call. Whether the P option or the p option | ||||
| is used, the incoming caller will have to supply their intro every | ||||
| time they call. | ||||
|  | ||||
| ======================= | ||||
| Recorded Introductions | ||||
| ======================= | ||||
|  | ||||
| [Philosophical Side Note: | ||||
| The 'P' option stores the CALLERID in the database, along with the | ||||
| callee's choice of actions, as a convenience to the CALLEE, whereas | ||||
| introductions are stored and re-used for the convenience of the CALLER.] | ||||
|  | ||||
| Unless instructed to not save introductions (see the 'n' option above), | ||||
| the screening modes will save the recordings of the caller's names in | ||||
| the directory /var/lib/asterisk/sounds/priv-callerintros, if they have | ||||
| a CallerID.  Just the 10-digit callerid numbers are used as filenames, | ||||
| with a ".gsm" at the end. | ||||
|  | ||||
| Having these recordings around can be very useful, however... | ||||
|  | ||||
| First of all, if a callerid is supplied, and a recorded intro for that | ||||
| number is already present, the caller is spared the inconvenience of | ||||
| having to supply their name, which shortens their call a bit. | ||||
|  | ||||
| Next of all, these intros can be used in voicemail, played over | ||||
| loudspeakers, and perhaps other nifty things. For instance: | ||||
|  | ||||
| exten => s,7,System(/usr/bin/play /var/lib/asterisk/sounds/priv-callerintros/${CALLERIDNUM}.gsm&|0)  | ||||
|  | ||||
| When a call comes in at the house, the above priority gets executed, | ||||
| and the callers intro is played over the phone systems speakers. This | ||||
| gives us a hint who is calling. | ||||
|  | ||||
| (Note: the |0 option at the end of the System command above, is a | ||||
| local mod I made to the System command. It forces a 0 result code to | ||||
| be returned, whether the play command successfully completed or | ||||
| not. Therefore, I don't have to ensure that the file exists or | ||||
| not. While I've turned this mod into the developers, it hasn't been | ||||
| incorporated yet. You might want to write an AGI or shell script to | ||||
| handle it a little more intelligently) | ||||
|  | ||||
| And one other thing. You can easily supply your callers with an option | ||||
| to listen to, and re-record their introductions. Here's what I did in | ||||
| the home system's extensions.conf. (assume that a | ||||
| Goto(home-introduction|s|1) exists somewhere in your main menu as an | ||||
| option): | ||||
|  | ||||
| [home-introduction] | ||||
| exten => s,1,Background,intro-options   ;; Script: To hear your Introduction, dial 1. | ||||
|                                         ;;         to record a new introduction, dial 2. | ||||
|                                         ;;         to return to the main menu, dial 3. | ||||
|                                         ;;         to hear what this is all about, dial 4. | ||||
| exten => 1,1,Playback,priv-callerintros/${CALLERIDNUM} | ||||
| exten => 1,2,Goto(s,1) | ||||
| exten => 2,1,Goto(home-introduction-record,s,1) | ||||
| exten => 3,1,Goto(homeline,s,7) | ||||
| exten => 4,1,Playback,intro-intro     ;; Script: | ||||
|                                 ;; This may seem a little strange, but it really is a neat | ||||
|                                 ;; thing, both for you and for us. I've taped a short introduction | ||||
|                                 ;; for many of the folks who normally call us. Using the Caller ID | ||||
|                                 ;; from each incoming call, the system plays the introduction | ||||
|                                 ;; for that phone number over a speaker, just as the call comes in. | ||||
|                                 ;; This helps the folks | ||||
|                                 ;; here in the house more quickly determine who is calling. | ||||
|                                 ;; and gets the right ones to gravitate to the phone. | ||||
|                                 ;; You can listen to, and record a new intro for your phone number | ||||
|                                 ;; using this menu. | ||||
| exten => 4,2,Goto(s,1) | ||||
| exten => t,1,Goto(s,1) | ||||
| exten => i,1,Background,invalid | ||||
| exten => i,2,Goto(s,1) | ||||
| exten => o,1,Goto(s,1) | ||||
|  | ||||
| [home-introduction-record] | ||||
| exten => s,1,Background,intro-record-choices    ;; Script: | ||||
|                                 ;;      If you want some advice about recording your | ||||
|                                 ;;      introduction, dial 1.  | ||||
|                                 ;;      otherwise, dial 2, and introduce yourself after | ||||
|                                 ;;      the beep. | ||||
| exten => 1,1,Playback,intro-record | ||||
|                                 ;;      Your introduction should be short and sweet and crisp. | ||||
|                                 ;;      Your introduction will be limited to 4 seconds. | ||||
|                                 ;;      This is NOT meant to be a voice mail message, so | ||||
|                                 ;;      please, don't say anything about why you are calling. | ||||
|                                 ;;      After we are done making the recording, your introduction | ||||
|                                 ;;      will be saved for playback.  | ||||
|                                 ;;      If you are the only person that would call from this number,  | ||||
|                                 ;;      please state your name.  Otherwise, state your business | ||||
|                                 ;;      or residence name instead. For instance, if you are  | ||||
|                                 ;;      friend of the family, say, Olie McPherson, and both | ||||
|                                 ;;      you and your kids might call here a lot, you might | ||||
|                                 ;;      say: "This is the distinguished Olie McPherson Residence!" | ||||
|                                 ;;      If you are the only person calling, you might say this: | ||||
|                                 ;;      "This is the illustrious Kermit McFrog! Pick up the Phone, someone!!" | ||||
|                                 ;;      If you are calling from a business, you might pronounce a more sedate introduction,like, | ||||
|                                 ;;      "Fritz from McDonalds calling.", or perhaps the more original introduction: | ||||
|                                 ;;      "John, from the Park County Morgue. You stab 'em, we slab 'em!". | ||||
|                                 ;;      Just one caution: the kids will hear what you record every time | ||||
|                                 ;;      you call. So watch your language! | ||||
|                                 ;;      I will begin recording after the tone.  | ||||
|                                 ;;      When you are done, hit the # key. Gather your thoughts and get  | ||||
|                                 ;;      ready. Remember, the # key will end the recording, and play back | ||||
|                                 ;;      your intro. Good Luck, and Thank you!" | ||||
| exten => 1,2,Goto(2,1) | ||||
| exten => 2,1,Background,intro-start | ||||
|                                 ;;  OK, here we go! After the beep, please give your introduction. | ||||
| exten => 2,2,Background,beep | ||||
| exten => 2,3,Record,priv-callerintros/${CALLERIDNUM}:gsm|4 | ||||
| exten => 2,4,Background,priv-callerintros/${CALLERIDNUM} | ||||
| exten => 2,5,Goto(home-introduction,s,1) | ||||
| exten => t,1,Goto(s,1) | ||||
| exten => i,1,Background,invalid | ||||
| exten => i,2,Goto(s,1) | ||||
| exten => o,1,Goto(s,1) | ||||
|  | ||||
|  | ||||
| In the above, you'd most likely reword the messages to your liking, | ||||
| and maybe do more advanced things with the 'error' conditions (i,o,t priorities), | ||||
| but I hope it conveys the idea... | ||||
|  | ||||
|  | ||||
							
								
								
									
										10
									
								
								sounds.txt
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								sounds.txt
									
									
									
									
									
								
							| @@ -250,6 +250,16 @@ | ||||
|  | ||||
| %priv-instruct.gsm%Press 1 to accept this call.  Press 2 to not accept this call.  Press 3 to always accept calls from this number.  Press 4 to never accept calls from this number.  Press 5 to reject calls from this number and request that they add you to their do not call list. | ||||
|  | ||||
| %priv-callee-options.gsm%Dial 1 if you wish this caller to reach you directly now, and in the future.  Dial 2 if you wish to send this caller to voicemail now and forevermore.  Dial 3 to send this caller to the torture menus, now and forevermore.  Dial 4 to send this caller to a polite "don't call" menu, now and forevermore.  Dial 5 to allow this caller to come straight thru to you in the future, but just this once, send them to voicemail. | ||||
|  | ||||
| %screen-callee-options.gsm%You have these options: Dial 1 if you wish to immediately connect to the incoming call.  Dial 2 if you wish to send this caller to voicemail.  Dial 3 to send this callerr to the torture menus.  Dial 4 to send this caller to a polite "don't call" menu. | ||||
|  | ||||
| %priv-introsaved.gsm%Thank you. Please hold, while I attempt to connect you with your party! | ||||
|  | ||||
| %priv-recordintro.gsm%At the tone, please say your name. | ||||
|  | ||||
| %priv-callpending.gsm%I have a caller waiting, who introduces themselves as: | ||||
|  | ||||
| %privacy-unident.gsm%The party you are trying to reach does not accept unidentified calls. | ||||
|  | ||||
| %privacy-prompt.gsm%Please enter your phone number, starting with the area code. | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								sounds/priv-callee-options.gsm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/priv-callee-options.gsm
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/priv-callpending.gsm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/priv-callpending.gsm
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/priv-introsaved.gsm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/priv-introsaved.gsm
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/priv-recordintro.gsm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/priv-recordintro.gsm
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								sounds/screen-callee-options.gsm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sounds/screen-callee-options.gsm
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user