/* ftpdata.c */
#include "scon.h"
#include <time.h>

#define SYNCH 242	// 0362
#define IP 244		// 0364
						extern int txmax;
static void databort(SOCKET sdata){
	char ctmp[MAX_PATH];
	if(aborted){
		SendMsg(socCtrl, "ABOR\r\n",-1);
		GetReply(ctmp, MAX_PATH, verbose? stdout:0);
		while(recv(sdata, ctmp, sizeof(ctmp), 0) >0 );
	}
	SocClose(&sdata);
	GetReply(ctmp, MAX_PATH, verbose? stdout:0);
	if(aborted)
		printf("...aborted\n");
}
int getfile(char *filename, char *destname, int nrestore){
	SOCKET sdata= INVALID_SOCKET;
	char ctmp[4000];
	char *fname;
	FILE *fp= 0;
	int n= 599;
	int nbytes= 0;
	double t= GetTickCount();	

	if(!destname || !destname[0])
		destname= filename;
	if(fname= strrchr(filename, '/'))++fname;
	else fname= filename;
	resumecmd[0]= 0;
	if(nrestore){
		sprintf(ctmp, "REST %d\r\n", nrestore);
		if((n= send_command(ctmp, 0)) >= 400)
			return n;
	}
	if(INVALID_SOCKET==(sdata= DataConnect()))
		return 599;
	aborted= 0;
	if((n= send_command("RETR %s\r\n", fname))<400){
		sdata= AcceptConnection(sdata);
		fp= fopen(destname, nrestore? "ab" : "wb");
		if(0==fp)
			perror(destname);
		if(nrestore)
			fseek(fp, nrestore, SEEK_SET);
		while((n= recv(sdata, ctmp, sizeof(ctmp), 0)) > 0){
			if(fp)
				fwrite(ctmp, 1, n, fp);
			nbytes += n;
			if(verbose)
				printf("%d bytes\r", nbytes);
if(txmax && nbytes>=txmax)aborted= 1;
			if(aborted)
				break;
		}
txmax= 0;
		if(fp)
			fclose(fp);
		if(!ascii && (aborted || n<0))
			sprintf(resumecmd, "get %d %s/%s %s/%s", nbytes, locdir,destname,curdir,fname);
		else
			if(0< (t= ((GetTickCount() - t)/1000.)) && verbose)
				printf("\r%d bytes received in %0.2f seconds (%0.1f kB/s)", nbytes, t, nbytes*0.001/t);
		n= 100;
		databort(sdata);
	}else
		SocClose(&sdata);
	if(!aborted && n<400)
		if(send_command_fp("MDTM %s\r\n", fname, 0) < 400)
			setlocalfiledate(destname, reply);
	return n;
}
void mget(char *pathnames, int bdelete){
	SOCKET sdata= INVALID_SOCKET;
	int n;
	int nf= 0, zf= 2*MAX_PATH;
	char *flist= malloc(zf);
	char path[MAX_PATH];
	//char fname[MAX_PATH];
	char *fname, *fnamend;

	flist[0]= 0;
	if(!*pathnames)
		strcpy(pathnames, ".");
	while(chomp(path, sizeof(path), pathnames) && !aborted){
		char *np;
		int nfiles= 0;

		if(np= strrchr(path, '/')){
			*np= 0;
			n= send_command_fp("CWD %s\r\n", path, 0);
			*np++= '/';
			if(n>=400){	// problem with the path?
				printf("Cannot find %s!\n", path);
				continue;
			}
		}else{
			np= path;
		}

		if(INVALID_SOCKET==(sdata= DataConnect()))
			return;
		if(400>send_command_fp("NLST %s\r\n", np, 0)){
			char keep[1024];
			int kn= 0;
			sdata= AcceptConnection(sdata);
			while((n= GetLine(sdata, flist+nf, zf-nf, keep, &kn)) >0){
				++nfiles;
				nf+= n;
				if(nf+MAX_PATH+2>=zf){
					char *fnew= realloc(flist, zf += MAX_PATH+2);
					if(fnew==0){
						aborted= 1;
						break;
					}
					flist= fnew;
				}
			}
			databort(sdata);
			if(aborted)
				break;
			if(nfiles==0)
				continue;

			/* fetch the files */
			if(bprompt && np>path && !aborted)
				printf("For %s:\n", path);
			for(fname= flist; fname && *fname; fname= fnamend){
				if(fnamend= strchr(fname, '\n'))
					*fnamend++= 0;
			//while(chompline(fname, sizeof(fname), flist)){
				if(bdelete){
					if(query("Delete %s? ", fname))
						n= send_command("DELE %s\r\n", fname);
				}else{
					if(query("Download %s? ", fname))
						n= getfile(fname,0,0);
				}
				if(n>=500)
					break;
			}
		}
		if(np>path)
			send_command_fp("CWD %s\r\n", curdir, 0);
	}
	send_command_fp("CWD %s\r\n", curdir, 0);
	free(flist);
	resignal();
}
int putfile(char *cmd, char *filename, char *destname, int nrestore){
	SOCKET sdata= INVALID_SOCKET;
	FILE *fp;
	int n;
	int nbytes= 0;
	int ans= 0;
	char *name;
	char ctmp[4000];
	double t= GetTickCount();	

	fp= fopen(filename, "rb");
	if(0==fp){
		perror(filename);
		return 0;
	}
	if(0==destname || 0==*destname)
		destname= filename;
	if(name= strrchr(destname, '/'))
		++name;
	else
		name= destname;
	resumecmd[0]= 0;
	if(nrestore){
		fseek(fp, nrestore, SEEK_SET);
		sprintf(ctmp, "REST %d\r\n", nrestore);
		if(400<=send_command(ctmp, 0))
			goto xit;
	}
	if(INVALID_SOCKET==(sdata= DataConnect()))
		goto xit;
	sprintf(ctmp, "%s %s\r\n", cmd, name);
	if(400<=send_command(ctmp, 0))
		goto xit;
	aborted= 0;
	ans= 1;
	sdata= AcceptConnection(sdata);
	while((n= fread(ctmp, 1, sizeof(ctmp), fp)) >0){
		SendMsg(sdata, ctmp, n);
		nbytes += n;
		if(verbose)
			printf("%d bytes\r", nbytes);
if(txmax && nbytes>=txmax)aborted= 1;
		if(aborted)
			break;
	}
txmax= 0;
	if(!ascii && (aborted || n<0))
		sprintf(resumecmd, "put %d %s/%s %s/%s", nbytes, locdir,filename,curdir,name);
	else if(0< (t= ((GetTickCount() - t)/1000.)) && verbose)
		printf("\r%d bytes sent in %0.2f seconds (%0.1f kB/s)", nbytes, t, nbytes*0.001/t);
	if(verbose)
		printf("\n");
	if(aborted){
		printf("\r...aborted              \n");
	}else{
		ans= 2;
	}
	xit:
	SocClose(&sdata);
	fclose(fp);
	if(ans)
		GetReply(ctmp, sizeof(ctmp), verbose? stdout:0);
	if(ans==2)
		setremotefiledate(filename, name);
	return ans==2;
}
void mput(char *paths){
	char apath[MAX_PATH];

	if(0==*paths)
		strcpy(paths, "*");
	while(chomp(apath, sizeof(apath), paths) && !aborted){
		char *flist= localfilelist(apath);
		char *filp;
		for(filp= flist; *filp; filp+= strlen(filp)+1){
			if(bprompt)
				printf("Upload %s? ", filp);
			if(query("? ", 0))
				putfile("STOR", filp, 0, 0);
		}
		free(flist);
		chdir(locdir);
	}
	resignal();
}
void lister(char *command, char *arg, int moring){
	SOCKET sdata= INVALID_SOCKET;
	int n;
	char *cp;
	FILE *fpout= 0;
	char chlast= '\n';
	char fname[MAX_PATH];
	char ctmp[1001];

	if(cp= strchr(arg, '>')){
		// save listing to a local file
		*cp++= ' ';
		for(n= 0; *cp>' '; n++){
			ctmp[n]= *cp;
			*cp++= ' ';
		}
		ctmp[n]= 0;
		fpout= fopen(ctmp, "wb");
		if(fpout==0)
			perror(ctmp);
		trim(arg);
	}
	if(!*arg)
		strcpy(arg, ".");
	if(!ascii)
		send_command_fp("TYPE A\r\n", 0, 0);
	while(chomp(fname, sizeof(fname), arg) && !aborted){
		int nl= 0;
		char keep[1024];
		int kn= 0;

		if(INVALID_SOCKET==(sdata= DataConnect()))
			break;
		n=send_command(command, fname);
		if(400<=n){
			SocClose(&sdata);
			if(500<=n)
				break;	// important error
			continue;	// just a gripe
		}
		sdata= AcceptConnection(sdata);
		while((n= GetLine(sdata, ctmp, sizeof(ctmp)-1, keep, &kn)) >0){
			++nl;
			ctmp[n]= 0;
			chlast= ctmp[n-1];
			fputs(ctmp, stdout);
			if(fpout){
				fputs(ctmp, fpout);
			}else if(moring && 0==(nl%25)){
				char ans;
				printf("--More-- ");
				fflush(stdout);
				getraw(&ans, 1);
				printf("\r        \r");
				fflush(stdout);
				if(ans=='\033')
					aborted= 1;
			}
		}
		if(chlast!='\n')
			printf("\n");
		databort(sdata);
		ctmp[0]= 0;
	}
	if(fpout)
		fclose(fpout);
	if(aborted)
		resignal();
	if(!ascii)
		send_command_fp("TYPE I\r\n", 0, 0);
}


