From efed8b824bbddfa6a7f69c2a45bcae34db7d636b Mon Sep 17 00:00:00 2001
From: deuce <>
Date: Sat, 4 Feb 2006 21:07:20 +0000
Subject: [PATCH] GUTS support optionally can be compiled in. Add "Safe Mode"
 by specifying -S on the command line... prevents writing to any files on the
 local system as well as preventing any browsing.  File transfers are
 disabled.  Only the last connected and connection count are updated in the
 BBS list.

Features requested bu obliVi0us who has done extensive testing of the ANSI
output of ciolib.  SyncTERM can now run as a door!  :-)
---
 src/syncterm/GNUmakefile |   7 +-
 src/syncterm/bbslist.c   |  50 ++++++--
 src/syncterm/fonts.c     |   4 +-
 src/syncterm/syncterm.c  |   5 +
 src/syncterm/syncterm.h  |   1 +
 src/syncterm/term.c      | 247 ++++++++++++++++++++++++++++++++++++++-
 6 files changed, 304 insertions(+), 10 deletions(-)

diff --git a/src/syncterm/GNUmakefile b/src/syncterm/GNUmakefile
index 934f0d4153..e142d4b41e 100644
--- a/src/syncterm/GNUmakefile
+++ b/src/syncterm/GNUmakefile
@@ -10,10 +10,15 @@ ifdef CHANNEL_CLIPPY
  CFLAGS +=	-DPCM
 endif
 
+ifdef USE_GUTS
+ CFLAGS +=	-I../guts -DGUTS_BUILTIN
+ OBJS	+=	$(MTOBJODIR)$(DIRSEP)gutsz$(OFILE)
+endif
+
 CFLAGS	+=	$(UIFC-MT_CFLAGS) $(CIOLIB-MT_CFLAGS) $(XPDEV-MT_CFLAGS) -I../sbbs3 -I../smblib
 LDFLAGS	+=	$(UIFC-MT_LDFLAGS) $(CIOLIB-MT_LDFLAGS) $(XPDEV-MT_LDFLAGS)
 
-vpath %.c ../sbbs3 ../smblib ../uifc
+vpath %.c ../sbbs3 ../smblib ../uifc ../guts
 
 $(SYNCTERM): $(EXEODIR) $(OBJS) $(BUILD_DEPENDS)
 	@echo Linking $@
diff --git a/src/syncterm/bbslist.c b/src/syncterm/bbslist.c
index 4e2ec93362..261fc1f2c0 100644
--- a/src/syncterm/bbslist.c
+++ b/src/syncterm/bbslist.c
@@ -302,9 +302,11 @@ int edit_list(struct bbslist *item,char *listpath,int isdefault)
 				if(!confirm("Quit editing?", NULL))
 					continue;
 #endif
-				if((listfile=fopen(listpath,"w"))!=NULL) {
-					iniWriteFile(listfile,inifile);
-					fclose(listfile);
+				if(!safe_mode) {
+					if((listfile=fopen(listpath,"w"))!=NULL) {
+						iniWriteFile(listfile,inifile);
+						fclose(listfile);
+					}
 				}
 				strListFreeStrings(inifile);
 				return(changed);
@@ -534,6 +536,8 @@ void add_bbs(char *listpath, struct bbslist *bbs)
 	FILE *listfile;
 	str_list_t	inifile;
 
+	if(safe_mode)
+		return;
 	if((listfile=fopen(listpath,"r"))!=NULL) {
 		inifile=iniReadFile(listfile);
 		fclose(listfile);
@@ -574,6 +578,8 @@ void del_bbs(char *listpath, struct bbslist *bbs)
 	FILE *listfile;
 	str_list_t	inifile;
 
+	if(safe_mode)
+		return;
 	if((listfile=fopen(listpath,"r"))!=NULL) {
 		inifile=iniReadFile(listfile);
 		fclose(listfile);
@@ -657,9 +663,11 @@ void change_settings(void)
 		}
 	}
 write_ini:
-	if((inifile=fopen(inipath,"w"))!=NULL) {
-		iniWriteFile(inifile,inicontents);
-		fclose(inifile);
+	if(!safe_mode) {
+		if((inifile=fopen(inipath,"w"))!=NULL) {
+			iniWriteFile(inifile,inicontents);
+			fclose(inifile);
+		}
 	}
 }
 
@@ -800,6 +808,13 @@ struct bbslist *show_bbslist(int mode)
 								uifc.msg("Max List size reached!");
 								break;
 							}
+							if(safe_mode) {
+								uifc.helpbuf=	"`Cannot edit list in safe mode`\n\n"
+												"SyncTERM is currently running in safe mode.  This means you cannot add to the\n"
+												"BBS list.";
+								uifc.msg("Cannot edit list in safe mode");
+								break;
+							}
 		#ifdef PCM
 							if(!confirm("Add new Entry?",NULL))
 								continue;
@@ -851,6 +866,13 @@ struct bbslist *show_bbslist(int mode)
 								uifc.msg("It's gone, calm down man!");
 								break;
 							}
+							if(safe_mode) {
+								uifc.helpbuf=	"`Cannot edit list in safe mode`\n\n"
+												"SyncTERM is currently running in safe mode.  This means you cannot remove from the\n"
+												"BBS list.";
+								uifc.msg("Cannot edit list in safe mode");
+								break;
+							}
 							sprintf(str,"Delete %s?",list[opt]->name);
 							i=1;
 							if(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,str,YesNo)!=0)
@@ -867,6 +889,13 @@ struct bbslist *show_bbslist(int mode)
 							oldopt=-1;
 							break;
 						case MSK_EDIT:
+							if(safe_mode) {
+								uifc.helpbuf=	"`Cannot edit list in safe mode`\n\n"
+												"SyncTERM is currently running in safe mode.  This means you cannot edit the\n"
+												"BBS list.";
+								uifc.msg("Cannot edit list in safe mode");
+								break;
+							}
 		#ifdef PCM
 							if(!confirm("Edit this entry?",NULL))
 								continue;
@@ -885,6 +914,13 @@ struct bbslist *show_bbslist(int mode)
 				}
 				else {
 					if(mode==BBSLIST_EDIT) {
+						if(safe_mode) {
+							uifc.helpbuf=	"`Cannot edit list in safe mode`\n\n"
+											"SyncTERM is currently running in safe mode.  This means you cannot edit the\n"
+											"BBS list.";
+							uifc.msg("Cannot edit list in safe mode");
+							break;
+						}
 		#ifdef PCM
 						if(!confirm("Edit this entry?",NULL))
 							continue;
@@ -996,7 +1032,7 @@ struct bbslist *show_bbslist(int mode)
 						}
 						break;
 					case 3:			/* Font management */
-						font_management();
+						if(!safe_mode) font_management();
 						break;
 					case 4:			/* Program settings */
 						change_settings();
diff --git a/src/syncterm/fonts.c b/src/syncterm/fonts.c
index 5a77941588..14acc9711a 100644
--- a/src/syncterm/fonts.c
+++ b/src/syncterm/fonts.c
@@ -40,6 +40,8 @@ void save_font_files(struct font_files *fonts)
 	str_list_t	fontnames;
 	int		i;
 
+	if(safe_mode)
+		return;
 	get_syncterm_filename(inipath, sizeof(inipath), SYNCTERM_PATH_INI, FALSE);
 	if((inifile=fopen(inipath,"r"))!=NULL) {
 		ini_file=iniReadFile(inifile);
@@ -316,7 +318,7 @@ void font_management(void)
 					show_filepick=1;
 					break;
 			}
-			if(show_filepick) {
+			if(show_filepick && !safe_mode) {
 				int result;
 				struct file_pick fpick;
 				char	*savbuf;
diff --git a/src/syncterm/syncterm.c b/src/syncterm/syncterm.c
index b0fe63f151..4b053c76e9 100644
--- a/src/syncterm/syncterm.c
+++ b/src/syncterm/syncterm.c
@@ -39,6 +39,7 @@ struct syncterm_settings settings;
 char *font_names[sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)];
 unsigned char *scrollback_buf=NULL;
 unsigned int  scrollback_lines=0;
+int	safe_mode=0;
 
 #ifdef _WINSOCKAPI_
 
@@ -355,6 +356,9 @@ int main(int argc, char **argv)
 				case 'T':
 					conn_type=CONN_TYPE_TELNET;
 					break;
+				case 'S':
+					safe_mode=1;
+					break;
                 default:
 					goto USAGE;
            }
@@ -533,6 +537,7 @@ int main(int argc, char **argv)
         "-l# =  set screen lines to # (default=auto-detect)\n"
 		"-t  =  use telnet mode if URL does not include the scheme\n"
 		"-r  =  use rlogin mode if URL does not include the scheme\n"
+		"-s  =  enable \"Safe Mode\" which prevents writing/browsing local files\n"
 		"\n"
 		"URL format is: [(rlogin|telnet)://][user[:password]@]domainname[:port]\n"
 		"examples: rlogin://deuce:password@nix.synchro.net:5885\n"
diff --git a/src/syncterm/syncterm.h b/src/syncterm/syncterm.h
index b82d002714..ecbc56c3fd 100644
--- a/src/syncterm/syncterm.h
+++ b/src/syncterm/syncterm.h
@@ -23,6 +23,7 @@ extern struct syncterm_settings settings;
 void parse_url(char *url, struct bbslist *bbs, int dflt_conn_type, int force_defaults);
 extern int default_font;
 extern char *font_names[];
+extern int safe_mode;
 char *get_syncterm_filename(char *fn, int fnlen, int type, int shared);
 void load_settings(struct syncterm_settings *set);
 
diff --git a/src/syncterm/term.c b/src/syncterm/term.c
index 2071a5bf76..0452e7ee39 100644
--- a/src/syncterm/term.c
+++ b/src/syncterm/term.c
@@ -16,7 +16,15 @@
 #include "zmodem.h"
 #include "crc32.h"
 
+#ifdef GUTS_BUILTIN
+#include "gutsz.h"
+#endif
+
+#ifdef GUTS_BUILTIN
+#define	BUFSIZE	1
+#else
 #define	BUFSIZE	2048
+#endif
 static char recvbuf[BUFSIZE];
 
 #define DUMP
@@ -119,6 +127,7 @@ void update_status(struct bbslist *bbs, int speed)
 {
 	char buf[160];
 	char nbuf[LIST_NAME_MAX+10+11+1];	/* Room for "Name (Logging) (115300)" and terminator */
+						/* SAFE and Logging should me be possible. */
 	int oldscroll;
 	int olddmc;
 	struct	text_info txtinfo;
@@ -143,6 +152,8 @@ void update_status(struct bbslist *bbs, int speed)
 	gotoxy(1,1);
 	_wscroll=0;
 	strcpy(nbuf, bbs->name);
+	if(safe_mode)
+		strcat(nbuf, " (SAFE)");
 	if(cterm.log)
 		strcat(nbuf, " (Logging)");
 	if(speed)
@@ -535,6 +546,9 @@ void begin_upload(char *uldir, BOOL autozm)
 			,""
 		};
 
+	if(safe_mode)
+		return;
+
 	init_uifc(FALSE, FALSE);
 	result=filepick(&uifc, "Upload", &fpick, uldir, NULL, UIFC_FP_ALLOWENTRY);
 	
@@ -570,6 +584,191 @@ void begin_upload(char *uldir, BOOL autozm)
 	uifcbail();
 }
 
+#ifdef GUTS_BUILTIN
+static int guts_lputs(void* cbdata, int level, const char* str)
+{
+	struct GUTS_info *gi=cbdata;
+	/* ToDo: Do something usefull here. */
+	/* fprintf(stderr,"%s\n",str); */
+	return(0);
+}
+
+void guts_zmodem_progress(void* cbdata, ulong current_pos)
+{
+	struct GUTS_info *gi=cbdata;
+	/* ToDo: Do something usefull here. */
+	return;
+}
+
+static int guts_send_byte(void* cbdata, uchar ch, unsigned timeout)
+{
+	int	i;
+	struct GUTS_info *gi=cbdata;
+
+	if(!socket_check(gi->oob_socket, NULL, &i, timeout*1000))
+		return(-1);
+
+	if(!i)
+		return(-1);
+
+	if(send(gi->oob_socket,&ch,1,0)==-1)
+		return(-1);
+
+	return(0);
+}
+
+static int guts_recv_byte(void* cbdata, unsigned timeout)
+{
+	BOOL	data_waiting;
+	BYTE	ch;
+	struct GUTS_info *gi=cbdata;
+
+	if(!socket_check(gi->oob_socket, &data_waiting, NULL, timeout*1000))
+		return(-1);
+
+	if(!data_waiting)
+		return(-1);
+
+	if(recv(gi->oob_socket,&ch,1,0)!=1)
+		return(-1);
+
+	return(ch);
+}
+
+static BOOL guts_is_connected(void* cbdata)
+{
+	struct GUTS_info *gi=cbdata;
+	return socket_check(gi->oob_socket,NULL,NULL,0);
+}
+
+BOOL guts_data_waiting(void* cbdata, unsigned timeout)
+{
+	BOOL rd;
+	struct GUTS_info *gi=cbdata;
+
+	if(!socket_check(gi->oob_socket,&rd,NULL,timeout*1000))
+		return(FALSE);
+	return(rd);
+}
+
+void zmodem_download(char *download_dir);
+
+void guts_background_download(void *cbdata)
+{
+	struct GUTS_info gi=*(struct GUTS_info *)cbdata;
+
+	zmodem_t	zm;
+	ulong		bytes_received;
+
+	zmodem_init(&zm
+		,&gi
+		,guts_lputs, guts_zmodem_progress
+		,guts_send_byte,guts_recv_byte,guts_is_connected
+		,guts_data_waiting);
+
+	/* ToDo: This would be a good time to detach or something. */
+	zmodem_recv_files(&zm,gi.files[0],&bytes_received);
+
+	oob_close(&gi);
+}
+
+void guts_background_upload(void *cbdata)
+{
+	struct GUTS_info gi=*(struct GUTS_info *)cbdata;
+
+	zmodem_t	zm;
+	ulong	fsize;
+	FILE*	fp;
+
+	if((fp=fopen(gi.files[0],"rb"))==NULL) {
+		fprintf(stderr,"Error %d opening %s for read",errno,gi.files[0]);
+		return;
+	}
+
+	setvbuf(fp,NULL,_IOFBF,0x10000);
+
+	zmodem_init(&zm
+		,&gi
+		,guts_lputs, guts_zmodem_progress
+		,guts_send_byte,guts_recv_byte,guts_is_connected
+		,guts_data_waiting);
+
+	zm.current_file_num = zm.total_files = 1;	/* ToDo: support multi-file/batch uploads */
+
+	fsize=filelength(fileno(fp));
+
+	if(zmodem_send_file(&zm, gi.files[0], fp
+		,/* ZRQINIT? */TRUE, /* start_time */NULL, /* sent_bytes */ NULL))
+		zmodem_get_zfin(&zm);
+
+	fclose(fp);
+
+	oob_close(&gi);
+}
+
+void guts_transfer(struct bbslist *bbs)
+{
+	struct GUTS_info gi;
+
+	if(safe_mode)
+		return;
+	setup_defaults(&gi);
+	gi.socket=conn_socket;
+	gi.telnet=bbs->conn_type==CONN_TYPE_TELNET;
+	gi.server=FALSE;
+	gi.use_daemon=FALSE;
+	gi.orig=FALSE;
+
+	if(negotiation(&gi)) {
+		oob_close(&gi);
+		return;
+	}
+
+	/* Authentication Phase */
+	if(!gi.inband) {
+		if(authenticate(&gi)) {
+			oob_close(&gi);
+			return;
+		}
+	}
+
+	if(gi.inband) {
+		if(gi.direction==UPLOAD)
+			begin_upload(bbs->uldir, TRUE);
+		else
+			zmodem_download(bbs->dldir);
+		oob_close(&gi);
+	}
+	else {
+		if(gi.direction==UPLOAD) {
+			int		result;
+			struct file_pick fpick;
+
+			init_uifc(FALSE, FALSE);
+			result=filepick(&uifc, "Upload", &fpick, bbs->uldir, NULL, UIFC_FP_ALLOWENTRY);
+
+			if(result==-1 || fpick.files<1) {
+				filepick_free(&fpick);
+				uifcbail();
+				return;
+			}
+			strListPush(&gi.files, fpick.selected[0]);
+			filepick_free(&fpick);
+
+			uifcbail();
+
+			_beginthread(guts_background_upload, 0, &gi);
+		}
+		else {
+			strListPush(&gi.files, bbs->dldir);
+			_beginthread(guts_background_download, 0, &gi);
+		}
+	}
+
+	return;
+}
+#endif
+
 void ascii_upload(FILE *fp, char *path)
 {
 	char linebuf[1024+2];	/* One extra for terminator, one extra for added CR */
@@ -645,6 +844,8 @@ void zmodem_download(char *download_dir)
 	int			files_received;
 	ulong		bytes_received;
 
+	if(safe_mode)
+		return;
 #if 0
 	bufbot=buftop=0;	/* purge our receive buffer */
 #endif
@@ -720,6 +921,8 @@ void font_control(struct bbslist *bbs)
 	struct	text_info txtinfo;
 	int i,j,k;
 
+	if(safe_mode)
+		return;
    	gettextinfo(&txtinfo);
 	buf=(char *)malloc(txtinfo.screenheight*txtinfo.screenwidth*2);
 	gettext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
@@ -755,6 +958,8 @@ void capture_control(struct bbslist *bbs)
 	struct	text_info txtinfo;
 	int i,j;
 
+	if(safe_mode)
+		return;
    	gettextinfo(&txtinfo);
 	buf=(char *)malloc(txtinfo.screenheight*txtinfo.screenwidth*2);
 	gettext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
@@ -835,13 +1040,21 @@ void capture_control(struct bbslist *bbs)
 BOOL doterm(struct bbslist *bbs)
 {
 	unsigned char ch[2];
+#ifdef GUTS_BUILTIN
+	unsigned char prn[1024];
+#else
 	unsigned char prn[BUFSIZE];
+#endif
 	int	key;
 	int i,j,k;
 	unsigned char *p;
 	BYTE zrqinit[] = { ZDLE, ZHEX, '0', '0', 0 };	/* for Zmodem auto-downloads */
 	BYTE zrinit[] = { ZDLE, ZHEX, '0', '1', 0 };	/* for Zmodem auto-uploads */
 	BYTE zrqbuf[5];
+#ifdef GUTS_BUILTIN
+	BYTE gutsinit[] = { ESC, '[', '{' };	/* For GUTS auto-transfers */
+	BYTE gutsbuf[3];
+#endif
 	int	inch;
 	long double nextchar=0;
 	long double lastchar=0;
@@ -865,6 +1078,9 @@ BOOL doterm(struct bbslist *bbs)
 	cterm.music_enable=bbs->music;
 	ch[1]=0;
 	zrqbuf[0]=0;
+#ifdef GUTS_BUILTIN
+	gutsbuf[0]=0;
+#endif
 
 	/* Main input loop */
 	oldmc=hold_update;
@@ -899,6 +1115,35 @@ BOOL doterm(struct bbslist *bbs)
 						lastchar = xp_timer();
 						nextchar = lastchar + 1/(long double)(speed/10);
 					}
+
+#ifdef GUTS_BUILTIN
+					if(!gutsbuf[0]) {
+						if(inch == gutsinit[0]) {
+							gutsbuf[0]=inch;
+							gutsbuf[1]=0;
+							continue;
+						}
+					}
+					else {		/* Already have the start of the sequence */
+						j=strlen(gutsbuf);
+						if(inch == gutsinit[j]) {
+							gutsbuf[j]=inch;
+							gutsbuf[++j]=0;
+							if(j==sizeof(gutsinit)) /* Have full sequence */
+								guts_transfer(bbs);
+						}
+						else {
+							gutsbuf[j++]=inch;
+							cterm_write(gutsbuf, j, prn, sizeof(prn), &speed);
+							if(prn[0])
+								conn_send(prn,strlen(prn),0);
+							updated=TRUE;
+							gutsbuf[0]=0;
+						}
+						continue;
+					}
+#endif
+
 					if(!zrqbuf[0]) {
 						if(inch == zrqinit[0] || inch == zrinit[0]) {
 							zrqbuf[0]=inch;
@@ -911,7 +1156,7 @@ BOOL doterm(struct bbslist *bbs)
 						if(inch == zrqinit[j] || inch == zrinit[j]) {
 							zrqbuf[j]=inch;
 							zrqbuf[++j]=0;
-							if(j==sizeof(zrqinit)-1) {	/* Have full sequence (Assumes zrinit and zrqinit are same length */
+							if(j==sizeof(zrqinit)) {	/* Have full sequence (Assumes zrinit and zrqinit are same length */
 								if(!strcmp(zrqbuf, zrqinit))
 									zmodem_download(bbs->dldir);
 								else
-- 
GitLab