diff --git a/src/sbbs3/bat_xfer.cpp b/src/sbbs3/bat_xfer.cpp
index a8d4674f7b7b283ec63e1f94b39f770de3b363d0..a65cef4ebb16eb39f74df632167ae663b569874f 100644
--- a/src/sbbs3/bat_xfer.cpp
+++ b/src/sbbs3/bat_xfer.cpp
@@ -193,7 +193,7 @@ void sbbs_t::batchmenu()
 bool sbbs_t::batch_upload()
 {
 	char str[129];
-	char tmp[512];
+	char keys[128];
 	char ch;
 	int i;
 
@@ -201,24 +201,16 @@ bool sbbs_t::batch_upload()
 		bputs(text[UploadQueueIsEmpty]);
 		return false;
 	}
-	xfer_prot_menu(XFER_BATCH_UPLOAD);
+	xfer_prot_menu(XFER_BATCH_UPLOAD, &useron, keys, sizeof keys);
+	SAFECAT(keys, quit_key(str));
 	if(!create_batchup_lst())
 		return false;
 	sync();
 	mnemonics(text[ProtocolOrQuit]);
-	SAFEPRINTF(str,"%c",quit_key());
-	for(i=0;i<cfg.total_prots;i++)
-		if(cfg.prot[i]->batulcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
-			sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
-			SAFECAT(str,tmp);
-		}
-	ch=(char)getkeys(str,0);
+	ch=(char)getkeys(keys,0);
 	if(ch==quit_key() || !online)
 		return false;
-	for(i=0;i<cfg.total_prots;i++)
-		if(cfg.prot[i]->batulcmd[0] && cfg.prot[i]->mnemonic==ch
-			&& chk_ar(cfg.prot[i]->ar,&useron,&client))
-			break;
+	i = protnum(ch, XFER_BATCH_UPLOAD);
 	if(i >= cfg.total_prots)
 		return false;
 	SAFEPRINTF(str,"%sBATCHUP.LST",cfg.node_dir);
@@ -342,24 +334,17 @@ bool sbbs_t::start_batch_download()
 		bputs(text[NotEnoughTimeToDl]);
 		return(false); 
 	}
-	i = protnum(useron.prot);
+	i = protnum(useron.prot, XFER_BATCH_DOWNLOAD);
 	if (i >= cfg.total_prots) {
-		xfer_prot_menu(XFER_BATCH_DOWNLOAD);
+		char keys[128];
+		xfer_prot_menu(XFER_BATCH_DOWNLOAD, &useron, keys, sizeof keys);
+		SAFECAT(keys, quit_key(str));
 		sync();
 		mnemonics(text[ProtocolOrQuit]);
-		SAFEPRINTF(str,"%c",quit_key());
-		for(i=0;i<cfg.total_prots;i++)
-			if(cfg.prot[i]->batdlcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
-				sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
-				SAFECAT(str,tmp); 
-			}
-		ch=(char)getkeys(str,0);
+		ch=(char)getkeys(keys, 0);
 		if(ch==quit_key() || sys_status&SS_ABORT)
 			return(false);
-		for(i=0;i<cfg.total_prots;i++)
-			if(cfg.prot[i]->batdlcmd[0] && cfg.prot[i]->mnemonic==ch
-				&& chk_ar(cfg.prot[i]->ar,&useron,&client))
-				break;
+		i = protnum(ch, XFER_BATCH_DOWNLOAD);
 	}
 	if(i>=cfg.total_prots || !create_batchdn_lst((cfg.prot[i]->misc&PROT_NATIVE) ? true:false)) {
 		return(false);
diff --git a/src/sbbs3/download.cpp b/src/sbbs3/download.cpp
index 9a4ac5cc0634330b981d4aef29559aacbb32fb38..f2f697380dda595a05f36c986d7cf534be753281 100644
--- a/src/sbbs3/download.cpp
+++ b/src/sbbs3/download.cpp
@@ -391,27 +391,22 @@ void sbbs_t::seqwait(uint devnum)
 bool sbbs_t::sendfile(char* fname, char prot, const char* desc, bool autohang)
 {
 	char	keys[128];
+	char	tmp[128];
 	char	ch;
 	int		i;
 	int		error;
 	bool	result;
 
-	i = protnum(prot);
+	i = protnum(prot, XFER_DOWNLOAD);
 	if (i >= cfg.total_prots) {
-		xfer_prot_menu(XFER_DOWNLOAD);
+		xfer_prot_menu(XFER_DOWNLOAD, &useron, keys, sizeof keys);
+		SAFECAT(keys, quit_key(tmp));
 		mnemonics(text[ProtocolOrQuit]);
-		sprintf(keys,"%c",quit_key());
-		for(i=0;i<cfg.total_prots;i++)
-			if(cfg.prot[i]->dlcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client))
-				sprintf(keys+strlen(keys),"%c",cfg.prot[i]->mnemonic);
-
 		ch=(char)getkeys(keys,0);
 
 		if(ch==quit_key() || sys_status&SS_ABORT)
-			return false; 
-		for(i=0;i<cfg.total_prots;i++)
-			if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron,&client))
-				break;
+			return false;
+		i = protnum(ch, XFER_DOWNLOAD);
 		if(i >= cfg.total_prots)
 			return false;
 	}
diff --git a/src/sbbs3/email.cpp b/src/sbbs3/email.cpp
index 7b77e7be0874710b3070b1b87c910bb3c0834703..7280472fc0d8eeb9f15d0098d3199c6699ba8ba2 100644
--- a/src/sbbs3/email.cpp
+++ b/src/sbbs3/email.cpp
@@ -32,6 +32,7 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, int mode,
 {
 	char		str[256],str2[256],msgpath[256],ch
 				,buf[SDT_BLOCK_LEN];
+	char		keys[128];
 	char 		tmp[512];
 	char		title[LEN_TITLE+1] = "";
 	const char*	editor=NULL;
@@ -136,24 +137,16 @@ bool sbbs_t::email(int usernumber, const char *top, const char *subj, int mode,
 			(void)remove(msgpath);
 			return(false); 
 		}
-		xfer_prot_menu(XFER_UPLOAD);
+		xfer_prot_menu(XFER_UPLOAD, &useron, keys, sizeof keys);
+		SAFECAT(keys, quit_key(str));
 		mnemonics(text[ProtocolOrQuit]);
-		sprintf(str,"%c",quit_key());
-		for(x=0;x<cfg.total_prots;x++)
-			if(cfg.prot[x]->ulcmd[0] && chk_ar(cfg.prot[x]->ar,&useron,&client)) {
-				sprintf(tmp,"%c",cfg.prot[x]->mnemonic);
-				SAFECAT(str,tmp); 
-			}
-		ch=(char)getkeys(str,0);
+		ch=(char)getkeys(keys,0);
 		if(ch==quit_key() || sys_status&SS_ABORT) {
 			bputs(text[Aborted]);
 			(void)remove(msgpath);
 			return(false); 
 		}
-		for(x=0;x<cfg.total_prots;x++)
-			if(cfg.prot[x]->ulcmd[0] && cfg.prot[x]->mnemonic==ch
-				&& chk_ar(cfg.prot[x]->ar,&useron,&client))
-				break;
+		x = protnum(ch, XFER_UPLOAD);
 		if(x<cfg.total_prots)	/* This should be always */
 			protocol(cfg.prot[x],XFER_UPLOAD,str2,nulstr,true); 
 		safe_snprintf(tmp,sizeof(tmp),"%s%s",cfg.temp_dir,title);
diff --git a/src/sbbs3/execmisc.cpp b/src/sbbs3/execmisc.cpp
index 61131f49cbcddba9d87b3882546e9fac6aa68251..f7310cca1921fb51535ad1f192730a9b4833d4af 100644
--- a/src/sbbs3/execmisc.cpp
+++ b/src/sbbs3/execmisc.cpp
@@ -1006,9 +1006,7 @@ int sbbs_t::exec_misc(csi_t* csi, const char *path)
 					ch=*(csi->ip++);	/* Protocol */
 					cmdstr((char *)csi->ip,csi->str,csi->str,str);
 					while(*(csi->ip++));	/* Find NULL */
-					for(i=0;i<cfg.total_prots;i++)
-						if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron,&client))
-							break;
+					i = protnum(ch, j==SEND_FILE_VIA ? XFER_DOWNLOAD : XFER_UPLOAD);
 					csi->logic=LOGIC_FALSE;
 					if(i<cfg.total_prots)
 						if(protocol(cfg.prot[i],j==SEND_FILE_VIA ? XFER_DOWNLOAD : XFER_UPLOAD
@@ -1021,9 +1019,7 @@ int sbbs_t::exec_misc(csi_t* csi, const char *path)
 					ch=*(csi->ip++);	/* Protocol */
 					pp=getstrvar(csi,*(int32_t *)csi->ip);
 					csi->ip+=4;
-					for(i=0;i<cfg.total_prots;i++)
-						if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron,&client))
-							break;
+					i = protnum(ch, j==SEND_FILE_VIA_VAR ? XFER_DOWNLOAD : XFER_UPLOAD);
 					csi->logic=LOGIC_FALSE;
 					if(!pp || !(*pp))
 						return(0);
diff --git a/src/sbbs3/getmsg.cpp b/src/sbbs3/getmsg.cpp
index 61c488124ebd536e18eb22cc8087a52240679049..73d732cf1f63ed607b77085fed3b2ee406c9d044 100644
--- a/src/sbbs3/getmsg.cpp
+++ b/src/sbbs3/getmsg.cpp
@@ -360,6 +360,7 @@ bool sbbs_t::show_msg(smb_t* smb, smbmsg_t* msg, int p_mode, post_t* post)
 void sbbs_t::download_msg_attachments(smb_t* smb, smbmsg_t* msg, bool del, bool use_default_prot)
 {
 	char str[256];
+	char keys[128];
 	char fpath[MAX_PATH+1];
 	char* txt;
 	int attachment_index = 0;
@@ -424,20 +425,11 @@ void sbbs_t::download_msg_attachments(smb_t* smb, smbmsg_t* msg, bool del, bool
 						,getfname(fpath),u64toac(length,tmp));
 					if(length>0L && text[DownloadAttachedFileQ][0] && yesno(str)) {
 						{	/* Remote User */
-							xfer_prot_menu(XFER_DOWNLOAD);
+							xfer_prot_menu(XFER_DOWNLOAD, &useron, keys, sizeof keys);
+							SAFECAT(keys, quit_key(str));
 							mnemonics(text[ProtocolOrQuit]);
-							strcpy(str,"Q");
-							for(i=0;i<cfg.total_prots;i++)
-								if(cfg.prot[i]->dlcmd[0]
-									&& chk_ar(cfg.prot[i]->ar,&useron,&client)) {
-									sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
-									SAFECAT(str,tmp);
-								}
-							ch=(char)getkeys(str,0);
-							for(i=0;i<cfg.total_prots;i++)
-								if(cfg.prot[i]->dlcmd[0] && ch==cfg.prot[i]->mnemonic
-									&& chk_ar(cfg.prot[i]->ar,&useron,&client))
-									break;
+							ch=(char)getkeys(keys,0);
+							i = protnum(ch, XFER_DOWNLOAD);
 							if(i<cfg.total_prots) {
 								time_t elapsed = 0;
 								int error = protocol(cfg.prot[i], XFER_DOWNLOAD, fpath, nulstr, /* cid: */false, /* autohang: */true, &elapsed);
diff --git a/src/sbbs3/listfile.cpp b/src/sbbs3/listfile.cpp
index 0b26603f65ec4acec0927c5ce53933c6c3f9ad05..c37f7856c916a712bfc02cb15a8ea2c9510bd665 100644
--- a/src/sbbs3/listfile.cpp
+++ b/src/sbbs3/listfile.cpp
@@ -1016,19 +1016,14 @@ int sbbs_t::listfileinfo(const int dirnum, const char *filespec, const int mode)
 				}
 				continue;
 			}
-			xfer_prot_menu(XFER_DOWNLOAD);
+			xfer_prot_menu(XFER_DOWNLOAD, &useron, keys, sizeof keys);
 			sync();
 			mnemonics(text[ProtocolBatchQuitOrNext]);
-			SAFEPRINTF(str,"B%cN\r",quit_key());
+			SAFECAT(keys, "BN\r");
+			SAFECAT(keys, quit_key(str));
 			if(m > 1)
-				SAFECAT(str, "\b-");
-			for(i=0;i<cfg.total_prots;i++)
-				if(cfg.prot[i]->dlcmd[0]
-					&& chk_ar(cfg.prot[i]->ar,&useron,&client)) {
-					sprintf(str + strlen(str), "%c", cfg.prot[i]->mnemonic);
-				}
-	//		  ungetkey(useron.prot);
-			ch=(char)getkeys(str,0);
+				SAFECAT(keys, "\b-");
+			ch=(char)getkeys(keys, 0);
 			if(ch==quit_key()) {
 				found=-1;
 				done=1;
@@ -1045,10 +1040,7 @@ int sbbs_t::listfileinfo(const int dirnum, const char *filespec, const int mode)
 				continue;
 			}
 			else if(ch!=CR && ch!='N') {
-				for(i=0;i<cfg.total_prots;i++)
-					if(cfg.prot[i]->dlcmd[0] && cfg.prot[i]->mnemonic==ch
-						&& chk_ar(cfg.prot[i]->ar,&useron,&client))
-						break;
+				i = protnum(ch, XFER_DOWNLOAD);
 				if(i<cfg.total_prots) {
 					delfiles(cfg.temp_dir,ALLFILES);
 					if(cfg.dir[f->dir]->seqdev) {
diff --git a/src/sbbs3/netmail.cpp b/src/sbbs3/netmail.cpp
index 9c996c0d72006578e17c98186f1745a1648fd907..224e53c18d1768b43995da540082a88e532d4c06 100644
--- a/src/sbbs3/netmail.cpp
+++ b/src/sbbs3/netmail.cpp
@@ -216,23 +216,16 @@ bool sbbs_t::netmail(const char *into, const char *title, int mode, smb_t* resmb
 			return(false); 
 		}
 		{ /* Remote */
-			xfer_prot_menu(XFER_UPLOAD);
+			char keys[128];
+			xfer_prot_menu(XFER_UPLOAD, &useron, keys, sizeof keys);
+			SAFECAT(keys, quit_key(str));
 			mnemonics(text[ProtocolOrQuit]);
-			sprintf(str,"%c",quit_key());
-			for(x=0;x<cfg.total_prots;x++)
-				if(cfg.prot[x]->ulcmd[0] && chk_ar(cfg.prot[x]->ar,&useron,&client)) {
-					sprintf(tmp,"%c",cfg.prot[x]->mnemonic);
-					strcat(str,tmp); 
-				}
-			ch=(char)getkeys(str,0);
+			ch=(char)getkeys(keys, 0);
 			if(ch==quit_key() || sys_status&SS_ABORT) {
 				bputs(text[Aborted]);
 				return(false); 
 			}
-			for(x=0;x<cfg.total_prots;x++)
-				if(cfg.prot[x]->ulcmd[0] && cfg.prot[x]->mnemonic==ch
-					&& chk_ar(cfg.prot[x]->ar,&useron,&client))
-					break;
+			x = protnum(ch, XFER_UPLOAD);
 			if(x<cfg.total_prots)	/* This should be always */
 				protocol(cfg.prot[x],XFER_UPLOAD,subj,nulstr,true); 
 		}
@@ -1053,25 +1046,18 @@ bool sbbs_t::inetmail(const char *into, const char *subj, int mode, smb_t* resmb
 			return(false); 
 		}
 		{ /* Remote */
-			xfer_prot_menu(XFER_UPLOAD);
+			char keys[128];
+			xfer_prot_menu(XFER_UPLOAD, &useron, keys, sizeof keys);
+			SAFECAT(keys, quit_key(str));
 			mnemonics(text[ProtocolOrQuit]);
-			SAFEPRINTF(str,"%c",quit_key());
-			for(x=0;x<cfg.total_prots;x++)
-				if(cfg.prot[x]->ulcmd[0] && chk_ar(cfg.prot[x]->ar,&useron,&client)) {
-					SAFEPRINTF(tmp,"%c",cfg.prot[x]->mnemonic);
-					SAFECAT(str,tmp); 
-				}
-			ch=(char)getkeys(str,0);
+			ch=(char)getkeys(keys, 0);
 			if(ch==quit_key() || sys_status&SS_ABORT) {
 				bputs(text[Aborted]);
 				strListFree(&rcpt_list);
 				(void)remove(msgpath);
 				return(false); 
 			}
-			for(x=0;x<cfg.total_prots;x++)
-				if(cfg.prot[x]->ulcmd[0] && cfg.prot[x]->mnemonic==ch
-					&& chk_ar(cfg.prot[x]->ar,&useron,&client))
-					break;
+			x = protnum(ch, XFER_UPLOAD);
 			if(x<cfg.total_prots)	/* This should be always */
 				protocol(cfg.prot[x],XFER_UPLOAD,str2,nulstr,true); 
 		}
diff --git a/src/sbbs3/qwk.cpp b/src/sbbs3/qwk.cpp
index 626bf4057e67dc6461e635b6d8a800fced9d008f..7185d304f2c7e23425388a14ddaad9a4ba207e1b 100644
--- a/src/sbbs3/qwk.cpp
+++ b/src/sbbs3/qwk.cpp
@@ -603,27 +603,20 @@ void sbbs_t::qwk_sec()
 			/***************/
 			/* Send Packet */
 			/***************/
-			i = protnum(useron.prot);
+			i = protnum(useron.prot, XFER_DOWNLOAD);
 			if (i >= cfg.total_prots) {
-				xfer_prot_menu(XFER_DOWNLOAD);
+				char keys[128];
+				xfer_prot_menu(XFER_DOWNLOAD, &useron, keys, sizeof keys);
+				SAFECAT(keys, quit_key(str));
 				mnemonics(text[ProtocolOrQuit]);
-				snprintf(tmp2, sizeof tmp2, "%c",quit_key());
-				for(i=0;i<cfg.total_prots;i++)
-					if(cfg.prot[i]->dlcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
-						snprintf(tmp, sizeof tmp, "%c",cfg.prot[i]->mnemonic);
-						strcat(tmp2,tmp);
-					}
-				ch=(char)getkeys(tmp2,0);
+				ch=(char)getkeys(keys, 0);
 				if(ch==quit_key() || sys_status&SS_ABORT || !online) {
 					for(i=0;i<cfg.total_subs;i++)
 						subscan[i].ptr=sav_ptr[i];   /* re-load saved pointers */
 					last_ns_time=ns_time;
 					continue;
 				}
-				for(i=0;i<cfg.total_prots;i++)
-					if(cfg.prot[i]->dlcmd[0] && cfg.prot[i]->mnemonic==ch
-						&& chk_ar(cfg.prot[i]->ar,&useron,&client))
-						break;
+				i = protnum(ch, XFER_DOWNLOAD);
 			}
 			if(i<cfg.total_prots) {
 				snprintf(str, sizeof str, "%s%s.qwk",cfg.temp_dir,cfg.sys_id);
@@ -654,21 +647,14 @@ void sbbs_t::qwk_sec()
 			/******************/
 			/* Receive Packet */
 			/******************/
-			xfer_prot_menu(XFER_UPLOAD);
+			char keys[128];
+			xfer_prot_menu(XFER_UPLOAD, &useron, keys, sizeof keys);
+			SAFECAT(keys, quit_key(str));
 			mnemonics(text[ProtocolOrQuit]);
-			snprintf(tmp2, sizeof tmp2, "%c",quit_key());
-			for(i=0;i<cfg.total_prots;i++)
-				if(cfg.prot[i]->ulcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
-					snprintf(tmp, sizeof tmp, "%c",cfg.prot[i]->mnemonic);
-					strcat(tmp2,tmp);
-				}
-			ch=(char)getkeys(tmp2,0);
+			ch=(char)getkeys(keys, 0);
 			if(ch==quit_key() || sys_status&SS_ABORT || !online)
 				continue;
-			for(i=0;i<cfg.total_prots;i++)
-				if(cfg.prot[i]->ulcmd[0] && cfg.prot[i]->mnemonic==ch
-					&& chk_ar(cfg.prot[i]->ar,&useron,&client))
-					break;
+			i = protnum(ch, XFER_UPLOAD);
 			if(i>=cfg.total_prots)	/* This shouldn't happen */
 				continue;
 			snprintf(str, sizeof str, "%s%s.rep",cfg.temp_dir,cfg.sys_id);
diff --git a/src/sbbs3/upload.cpp b/src/sbbs3/upload.cpp
index 0e5cc5683ccd76234e0b562e9aa97dd379e70321..00034462de64d4633b79d5b7c700049ad7c7f81c 100644
--- a/src/sbbs3/upload.cpp
+++ b/src/sbbs3/upload.cpp
@@ -450,20 +450,15 @@ bool sbbs_t::upload(int dirnum, const char* fname)
 	if(fexistcase(path)) {   /* File is on disk */
 		result = uploadfile(&f);
 	} else {
-		xfer_prot_menu(XFER_UPLOAD);
+		xfer_prot_menu(XFER_UPLOAD, &useron, keys, sizeof keys);
+		SAFECAT(keys, quit_key(str));
 		sync();
-		SAFEPRINTF(keys,"%c",quit_key());
 		if(dirnum==cfg.user_dir || !cfg.max_batup)  /* no batch user to user xfers */
 			mnemonics(text[ProtocolOrQuit]);
 		else {
 			mnemonics(text[ProtocolBatchOrQuit]);
-			strcat(keys,"B"); 
+			SAFECAT(keys,"B");
 		}
-		for(i=0;i<cfg.total_prots;i++)
-			if(cfg.prot[i]->ulcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
-				SAFEPRINTF(tmp,"%c",cfg.prot[i]->mnemonic);
-				strcat(keys,tmp); 
-			}
 		ch=(char)getkeys(keys,0);
 		if(ch==quit_key() || (sys_status&SS_ABORT))
 			result = false;
@@ -478,10 +473,7 @@ bool sbbs_t::upload(int dirnum, const char* fname)
 				result = true;
 			}
 		} else {
-			for(i=0;i<cfg.total_prots;i++)
-				if(cfg.prot[i]->ulcmd[0] && cfg.prot[i]->mnemonic==ch
-					&& chk_ar(cfg.prot[i]->ar,&useron,&client))
-					break;
+			i = protnum(ch, XFER_UPLOAD);
 			if(i<cfg.total_prots) {
 				time_t elapsed = 0;
 				protocol(cfg.prot[i],XFER_UPLOAD,path,nulstr,/* cd: */true, /* autohang: */true, &elapsed);
@@ -567,7 +559,8 @@ bool sbbs_t::bulkupload(int dirnum)
 
 bool sbbs_t::recvfile(char *fname, char prot, bool autohang)
 {
-	char	keys[32];
+	char	keys[128];
+	char	str[128];
 	char	ch;
 	int		i;
 	bool	result=false;
@@ -575,21 +568,15 @@ bool sbbs_t::recvfile(char *fname, char prot, bool autohang)
 	if(prot)
 		ch=toupper(prot);
 	else {
-		xfer_prot_menu(XFER_UPLOAD);
+		xfer_prot_menu(XFER_UPLOAD, &useron, keys, sizeof keys);
+		SAFECAT(keys, quit_key(str));
 		mnemonics(text[ProtocolOrQuit]);
-		SAFEPRINTF(keys,"%c",quit_key());
-		for(i=0;i<cfg.total_prots;i++)
-			if(cfg.prot[i]->ulcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client))
-				sprintf(keys+strlen(keys),"%c",cfg.prot[i]->mnemonic);
-
 		ch=(char)getkeys(keys,0);
 
 		if(ch==quit_key() || sys_status&SS_ABORT)
 			return(false); 
 	}
-	for(i=0;i<cfg.total_prots;i++)
-		if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron,&client))
-			break;
+	i = protnum(ch, XFER_UPLOAD);
 	if(i<cfg.total_prots) {
 		if(protocol(cfg.prot[i], XFER_UPLOAD, fname, fname, true, autohang)==0)
 			result=true;
diff --git a/src/sbbs3/useredit.cpp b/src/sbbs3/useredit.cpp
index 439e6042eaf59ee056c0dee02eb690b0c76534de..4f1db5534d5f4aced583217407bb775cdc31c44a 100644
--- a/src/sbbs3/useredit.cpp
+++ b/src/sbbs3/useredit.cpp
@@ -851,7 +851,7 @@ void sbbs_t::maindflts(user_t* user)
 		if(*text[UserDefaultsProtocol]) {
 			add_hotspot('Z');
 			SAFECAT(keys, "Z");
-			bprintf(text[UserDefaultsProtocol], protname(user->prot)
+			bprintf(text[UserDefaultsProtocol], protname(user->prot, XFER_DOWNLOAD)
 				, user->misc & AUTOHANG ? "(Auto-Hangup)" : nulstr);
 		}
 		if(*text[UserDefaultsPassword] && (cfg.sys_misc & SM_PWEDIT) && !(user->rest & FLAG('G'))) {
@@ -1131,16 +1131,11 @@ void sbbs_t::maindflts(user_t* user)
 					remove(str);
 				break;
 			case 'Z':
-				xfer_prot_menu(XFER_DOWNLOAD);
+				xfer_prot_menu(XFER_DOWNLOAD, user, keys, sizeof keys);
+				SAFECAT(keys, quit_key(str));
 				sync();
 				mnemonics(text[ProtocolOrQuit]);
-				sprintf(str,"%c",quit_key());
-				for(i=0;i<cfg.total_prots;i++)
-					if(cfg.prot[i]->dlcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
-						SAFEPRINTF(tmp,"%c",cfg.prot[i]->mnemonic);
-						strcat(str,tmp); 
-					}
-				ch=(char)getkeys(str,0);
+				ch=(char)getkeys(keys,0);
 				if(ch < 0)
 					break;
 				if(sys_status & SS_ABORT)