/* Copyright (c) 1998,1999 Alexander Yukhimets. All rights reserved. */
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<time.h>
#include<ctype.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include"utils.h"
#include"multi.h"
#include"ftp.h"
#include"ftp_xfer.h"
#include"axyftp.h"
#include"status.h"
#include"read_init.h"
#include"dirinfo.h"
#include"dirlist.h"
#include"dirname.h"
#include"progress_dialog.h"
#include"little_dialogs.h"
#include"viewer.h"
#include"prompt_dialogs.h"
#include"functions.h"
int show_help(int num){
#ifdef AXYFTP_HELP_DIR
static char* help_loc=AXYFTP_HELP_DIR "/axyftp.html";
#else
static char* help_loc="/usr/local/share/axyftp/help/axyftp.html";
#endif /*AXYFTP_HELP_DIR*/
char* buf;
buf=WXmalloc(strlen(help_loc)*3+80);
sprintf(buf,
"netscape -remote \'OpenURL(%s)\' || netscape %s || xterm -e lynx %s &",
help_loc,help_loc,help_loc);
system(buf);
WXfree(buf);
return 0;
}
struct _file_progress_data {
WXwidget progress;
long totalsize;
time_t lasttime;
long currentsize;
float rate;
long elapsed;
long left;
int percent;
};
static int update_file_progress(int len,void* arg){
struct _file_progress_data *data;
time_t currenttime;
long newelapsed;
long newleft;
float newrate;
long newsize;
int newpercent;
data=(struct _file_progress_data*)arg;
currenttime=time(NULL);
newsize=data->currentsize+(long)len;
if(currenttime==data->lasttime){
data->currentsize=newsize;
return check_for_small_interrupt();
}
newelapsed=(currenttime-data->lasttime);
newelapsed+=data->elapsed;
if(newelapsed)newrate=((float)newsize)/newelapsed/1024;
else newrate=data->rate;
if(newelapsed && newsize){
newleft=((long long)data->totalsize)*((long long)newelapsed)/newsize;
newleft-=newelapsed;
} else {
newleft=data->left;
}
data->lasttime=currenttime;
if(data->totalsize)newpercent=
((long long)newsize)*100/data->totalsize;
else newpercent=data->percent;
if(newsize==data->currentsize)newsize=-1;else data->currentsize=newsize;
if(newrate==data->rate)newrate=-1.;else data->rate=newrate;
if(newelapsed==data->elapsed)newelapsed=-1;else data->elapsed=newelapsed;
if(newleft==data->left)newleft=-1;else data->left=newleft;
if(newpercent==data->percent)newpercent=-1;else data->percent=newpercent;
update_progress_dialog(data->progress,newpercent,newsize,newrate,
newelapsed,newleft);
return check_for_small_interrupt();
}
int check_for_interrupt(){
process_events();
if(appdata.interrupt){
appdata.interrupt=0;
return 1;
}
return 0;
}
int rename_local_num(int num){
char* text;
char* orig;
orig=appdata.local.list->files[num+1]->name;
text=WXmalloc(strlen(orig)+35);
sprintf(text,"Enter new name for \"%s\" (local):",orig);
init_rename_dialog(appdata.rename_local,text,orig);
WXfree(text);
return 0;
}
int rename_remote_num(int num){
char* text;
char* orig;
orig=appdata.remote.list->files[num+1]->name;
text=WXmalloc(strlen(orig)+35);
sprintf(text,"Enter new name for \"%s\" (remote):",orig);
init_rename_dialog(appdata.rename_remote,text,orig);
WXfree(text);
return 0;
}
int rename_local(char* from,char* to){
return rename(from,to);
}
int rename_remote(char* from,char* to){
int ret;
ret=ftp_rename(from,to,&appdata.connect,logfile,check_for_interrupt);
if(ret==10){
append_status("CONNECTION LOST\n");
appdata.connected=0;
(void)popup_reconnect_dialog(NULL);
} else {
append_status(appdata.connect.lastline);
}
return ret;
}
int exec_local(char* name){
return system(name);
}
int mkdir_local(char* name){
return mkdir(name,0755);
}
int exec_remote(char* name){
int ret;
ret=ftp_site(name,&appdata.connect,logfile,check_for_interrupt);
if(ret==10){
append_status("CONNECTION LOST\n");
appdata.connected=0;
(void)popup_reconnect_dialog(toplevel);
} else {
append_status(appdata.connect.lastline);
}
return ret;
}
int mkdir_remote(char* name){
int ret;
ret=ftp_mkdir(name,&appdata.connect,logfile,check_for_interrupt);
if(ret==10){
append_status("CONNECTION LOST\n");
appdata.connected=0;
(void)popup_reconnect_dialog(toplevel);
} else {
append_status(appdata.connect.lastline);
}
return ret;
}
int show_log(){
int lfd;
WXwidget viewer;
fflush(logfile);
if((lfd=open(log_file,O_RDONLY))<0){
char* text=WXmalloc(strlen(log_file)+25);
sprintf(text,"Cannot open log file %s",log_file);
(void)popup_warning_dialog(toplevel,text);
WXfree(text);
return 1;
}
viewer=create_viewer(toplevel,"Log Window");
return fill_viewer(viewer,lfd);
}
int view_local_num(int num){
char* cmd;
cmd=WXmalloc(2*strlen(appdata.local.list->files[num+1]->name)+100);
sprintf(cmd,"${XEDITOR-gvim} %s || xterm -e ${EDITOR-vi} %s &",
appdata.local.list->files[num+1]->name,
appdata.local.list->files[num+1]->name);
system(cmd);
WXfree(cmd);
return 0;
/* int lfd;
GtkWidget* viewer;
char* text;
if((lfd=open(appdata.local.list->files[num+1]->name,O_RDONLY))<0){
char* text=WXmalloc(strlen(appdata.local.list->files[num+1]->name)+14);
sprintf(text,"Cannot open %s",appdata.local.list->files[num+1]->name);
(void)popup_warning_dialog(toplevel,text);
WXfree(text);
return 1;
}
text=WXmalloc(strlen(appdata.local.list->files[num+1]->name)+8);
sprintf(text,"Local: %s",appdata.local.list->files[num+1]->name);
viewer=create_viewer(toplevel,text);
WXfree(text);
return fill_viewer(viewer,lfd);
*/
}
int view_remote_num(int num){
char* text;
int ret;
FILE* tmp;
struct _file_progress_data fpd;
WXwidget viewer;
if(appdata.remote.list->files[num+1]->perms[0]!='-'){
(void)popup_warning_dialog(toplevel,
"Only \"normal\" files transfers are implemented in this version\n"
"Sorry...");
return 1;
}
tmp=tmpfile();
ret=ftp_get('A',appdata.remote.list->files[num+1]->name,&appdata.connect,
logfile,check_for_interrupt);
if(ret==10){
append_status("CONNECTION LOST\n");
appdata.connected=0;
(void)popup_reconnect_dialog(toplevel);
fclose(tmp);
return 1;
} else {
append_status(appdata.connect.lastline);
}
if(ret)return 2;
if(appdata.connect.lastline[0]!='1')return 3;
/* progress=create_progress_dialog(toplevel);*/
init_progress_dialog(appdata.progress,
appdata.remote.list->files[num+1]->name,
appdata.remote.list->files[num+1]->size);
process_events();
fpd.progress=appdata.progress;
fpd.totalsize=appdata.remote.list->files[num+1]->size;
fpd.lasttime=time(NULL);
fpd.currentsize=0;
fpd.elapsed=0;
fpd.left=-1;
fpd.rate=-1.;
fpd.percent=0;
ret=ftp_xfer_get('A',appdata.connect.data,fileno(tmp),update_file_progress,
(void*)&fpd);
hide_progress_dialog(appdata.progress);
if(appdata.odata->xferbeep)beep();
if(ret==-1){
append_status("CANCELLED\n");
if(!ftp_abort_data(&appdata.connect,logfile,check_for_interrupt)){
append_status(appdata.connect.lastline);
}
} else if(ret){
append_status("CONNECTION FAILED\n");
if(!ftp_close_data(&appdata.connect,logfile,check_for_interrupt)){
append_status(appdata.connect.lastline);
}
} else {
if(!ftp_close_data(&appdata.connect,logfile,check_for_interrupt)){
append_status(appdata.connect.lastline);
}
}
lseek(fileno(tmp),0,SEEK_SET);
text=WXmalloc(strlen(appdata.remote.list->files[num+1]->name)+10);
sprintf(text,"%s (remote)",appdata.remote.list->files[num+1]->name);
viewer=create_viewer(toplevel,text);
WXfree(text);
return fill_viewer(viewer,fileno(tmp));
}
int show_local_dirinfo(){
char* text;
WXwidget viewer;
text=WXmalloc(strlen(appdata.local.list->dir)+20);
sprintf(text,"%s/ (local DirInfo)",appdata.local.list->dir);
viewer=create_viewer(toplevel,text);
WXfree(text);
fill_dirinfo(viewer,appdata.local.list);
return 0;
}
int show_remote_dirinfo(){
char* text;
WXwidget viewer;
text=WXmalloc(strlen(appdata.remote.list->dir)+20);
sprintf(text,"%s/ (remote DirInfo)",appdata.remote.list->dir);
viewer=create_viewer(toplevel,text);
WXfree(text);
fill_dirinfo(viewer,appdata.remote.list);
return 0;
}
int delete_local_num(int num){
if(appdata.local.list->files[num+1]->perms[0]=='d'){
return rmdir_local(appdata.local.list->files[num+1]->name);
} else {
return delete_local(appdata.local.list->files[num+1]->name);
}
}
int delete_remote_num(int num){
if(appdata.remote.list->files[num+1]->perms[0]=='d'){
return rmdir_remote(appdata.remote.list->files[num+1]->name);
} else {
return delete_remote(appdata.remote.list->files[num+1]->name);
}
}
int rmdir_local(char* name){
return rmdir(name);
}
int delete_local(char* name){
return unlink(name);
}
int rmdir_remote(char* name){
int ret;
ret=ftp_rmdir(name,&appdata.connect,logfile,check_for_interrupt);
if(ret==10){
append_status("CONNECTION LOST\n");
appdata.connected=0;
(void)popup_reconnect_dialog(toplevel);
} else {
append_status(appdata.connect.lastline);
}
return ret;
}
int delete_remote(char* name){
int ret;
ret=ftp_delete(name,&appdata.connect,logfile,check_for_interrupt);
if(ret==10){
append_status("CONNECTION LOST\n");
appdata.connected=0;
(void)popup_reconnect_dialog(toplevel);
} else {
append_status(appdata.connect.lastline);
}
return ret;
}
int check_for_small_interrupt(){
process_events();
if(appdata.interrupt || appdata.small_interrupt){
appdata.small_interrupt=0;
return 1;
}
return 0;
}
int upload_file(fileinfo* fi,char type){
int ret;
int lfd;
struct _file_progress_data fpd;
struct stat statbuf;
int show_progress;
if((lfd=open(fi->name,O_RDONLY))<0){
char* b;
b=WXmalloc(strlen(fi->name)+40);
sprintf(b,"Cannot open local file %s\n",fi->name);
append_status(b);
WXfree(b);
return 2;
}
if(fstat(lfd,&statbuf)){
char* b;
b=WXmalloc(strlen(fi->name)+40);
sprintf(b,"Cannot get size info for %s\n",fi->name);
append_status(b);
WXfree(b);
return 2;
}
if(!type)type='I';
ret=ftp_put(type,fi->name,&appdata.connect,logfile,check_for_small_interrupt);
if(ret==10){
/*
append_status("CONNECTION LOST\n");
appdata.connected=0;
(void)popup_reconnect_dialog(toplevel);
*/
close(lfd);
return 1;
} else {
append_status(appdata.connect.lastline);
}
if(ret){
close(lfd);
return 3;
}
if(appdata.connect.lastline[0]!='1'){
close(lfd);
return 4;
}
show_progress=0;
if(appdata.odata->show_progress){
long tres;
tres=atoi(appdata.odata->progress_treshold);
if(tres<0)tres=0;
if(statbuf.st_size/1024>=tres){
/*progress=create_progress_dialog(toplevel);*/
if(!appdata.progress_shown){
show_progress_dialog(appdata.progress);
appdata.progress_shown=1;
}
init_progress_dialog(appdata.progress,fi->name,statbuf.st_size);
process_events();
fpd.progress=appdata.progress;
fpd.totalsize=statbuf.st_size;
fpd.lasttime=time(NULL);
fpd.currentsize=0;
fpd.elapsed=0;
fpd.left=-1;
fpd.rate=-1.;
fpd.percent=0;
show_progress=1;
ret=ftp_xfer_put(type,appdata.connect.data,lfd,update_file_progress,
(void*)&fpd);
}
}
if(!show_progress){
ret=ftp_xfer_put(type,appdata.connect.data,lfd,NULL,NULL);
}
close(lfd);
if(show_progress){
init_progress_dialog(appdata.progress,"",0);
}
if(appdata.odata->xferbeep)beep();
if(ret==-1){
append_status("CANCELLED\n");
if(!ftp_abort_data(&appdata.connect,logfile,check_for_small_interrupt)){
append_status(appdata.connect.lastline);
}
} else if(ret){
append_status("CONNECTION FAILED\n");
if(!ftp_close_data(&appdata.connect,logfile,check_for_small_interrupt)){
append_status(appdata.connect.lastline);
}
} else {
if(!ftp_close_data(&appdata.connect,logfile,check_for_small_interrupt)){
append_status(appdata.connect.lastline);
}
}
return 0;
}
int download_file(fileinfo* volatile fi,char volatile type){
volatile int ret;
volatile int lfd;
volatile struct _file_progress_data fpd;
struct stat statbuf;
long size;
int show_progress;
if(!type)type='I';
ftp_size(&size,type,fi->name,&appdata.connect,logfile,
check_for_small_interrupt);
if(size<=0){
size=fi->size;
}
ret=1;
if(!stat(fi->name,&statbuf)){
volatile long save_size=size;
if(S_ISDIR(statbuf.st_mode))return 1;
if(!(ret=sigsetjmp(jmp_down_env,1))){
(void)init_xfer_dialog(appdata.xfer_dialog,fi->name);
LOOP();
}
size=save_size;
}
if(ret==1){
if((lfd=open(fi->name,O_WRONLY|O_CREAT|O_TRUNC,0755))<0){
char* b;
b=WXmalloc(strlen(fi->name)+40);
sprintf(b,"Cannot open local file %s\n",fi->name);
append_status(b);
WXfree(b);
return 2;
}
ret=ftp_get(type,fi->name,&appdata.connect,logfile,
check_for_small_interrupt);
fpd.totalsize=size;
} else if(ret==2){
if((lfd=open(fi->name,O_WRONLY|O_APPEND,0755))<0){
char* b;
b=WXmalloc(strlen(fi->name)+40);
sprintf(b,"Cannot open local file %s\n",fi->name);
append_status(b);
WXfree(b);
return 2;
}
ret=ftp_resume(type,statbuf.st_size,fi->name,&appdata.connect,logfile,
check_for_small_interrupt);
fpd.totalsize=size-statbuf.st_size;
if(fpd.totalsize<0)fpd.totalsize=0;
} else if(ret==3){
return 0;
}
if(ret==10){
return 10;
} else {
append_status(appdata.connect.lastline);
}
if(ret)return 4;
if(appdata.connect.lastline[0]!='1')return 5;
show_progress=0;
if(appdata.odata->show_progress){
long tres;
tres=atoi(appdata.odata->progress_treshold);
if(tres<0)tres=0;
if(size/1024>=tres || (fi->perms[0] == 'l' && size==fi->size)){
/*progress=create_progress_dialog(toplevel);*/
if(!appdata.progress_shown){
show_progress_dialog(appdata.progress);
appdata.progress_shown=1;
}
init_progress_dialog(appdata.progress,fi->name,size);
process_events();
fpd.progress=appdata.progress;
fpd.currentsize=0;
fpd.lasttime=time(NULL);
fpd.elapsed=0;
fpd.left=-1;
fpd.rate=-1.;
fpd.percent=0;
show_progress=1;
ret=ftp_xfer_get(type,appdata.connect.data,lfd,update_file_progress,
(void*)&fpd);
}
}
if(!show_progress){
ret=ftp_xfer_get(type,appdata.connect.data,lfd,NULL,NULL);
}
close(lfd);
if(show_progress){
init_progress_dialog(appdata.progress,"",0);
}
if(appdata.odata->xferbeep)beep();
if(ret==-1){
append_status("CANCELLED\n");
if(!ftp_abort_data(&appdata.connect,logfile,check_for_small_interrupt)){
append_status(appdata.connect.lastline);
}
} else if(ret){
append_status("CONNECTION FAILED\n");
if(!ftp_close_data(&appdata.connect,logfile,check_for_small_interrupt)){
append_status(appdata.connect.lastline);
}
} else {
if(!ftp_close_data(&appdata.connect,logfile,check_for_small_interrupt)){
append_status(appdata.connect.lastline);
}
}
return 0;
}
int chg_remote_dir(int num){
return chg_remote_dirname(appdata.remote.list->files[num+1]->name);
}
int chg_remote_dirname(char* name){
int retval;
retval=ftp_chdir(name,&appdata.connect,logfile,check_for_interrupt);
if(retval==10){
append_status("CONNECTION LOST\n");
appdata.connected=0;
(void)popup_reconnect_dialog(toplevel);
} else {
append_status(appdata.connect.lastline);
}
if(retval){
(void)popup_error_dialog(toplevel,"Could not change to remote directory");
}
return retval;
}
int chg_local_dir(int num){
return chg_local_dirname(appdata.local.list->files[num+1]->name);
}
int chg_local_dirname(char* name){
if(chdir(name)==-1){
(void)popup_error_dialog(toplevel,"Could not change to local directory");
return 1;
}
return 0;
}
void end_session(){
if(!ftp_disconnect(&appdata.connect,logfile,check_for_interrupt)){
append_status(appdata.connect.lastline);
} else {
append_status("DISCONNECTED\n");
}
appdata.connected=0;
if(appdata.remote.list){
destroy_dirinfo(appdata.remote.list);
appdata.remote.list=NULL;
}
}
void start_session(session_data* sd,char* mask){
int good;
char* p;
char* cmd;
if(check_for_interrupt())return;
appdata.connect.passive=1;
good=ftp_connect(sd->host,atoi(sd->port),
&appdata.connect,logfile,check_for_interrupt);
if(good){
append_status("CONNECT FAILED\n");
return;
}
append_status(appdata.connect.lastline);
good=ftp_login(sd->user,sd->pass,sd->account,&appdata.connect,NULL,
check_for_interrupt);
if(good){
append_status("LOGIN FAILED\n");
return;
}
append_status(appdata.connect.lastline);
if((good=ftp_syst(&appdata.connect,logfile,check_for_interrupt))==0 || good==2){
append_status(appdata.connect.lastline);
} else {
append_status("CONNECT FAILED\n");
return;
}
appdata.connected=1;
if(*(sd->locdir)){
if(!chg_local_dirname(sd->locdir)){
update_local(sd->locmask);
}
} else if(*(sd->locmask)){
update_local(sd->locmask);
}
p=sd->initcom;
for(;;){
while(*p && isspace(*p))p++;
if(*p=='\0')break;
good=0;while(p[good]!='\0' && p[good]!=';')good++;
cmd=WXmalloc(good+3);
strncpy(cmd,p,good);
strcpy(&cmd[good],"\r\n");
if(ftp_command(cmd,&appdata.connect,logfile,check_for_interrupt)==10){
appdata.connected=0;
append_status("CONNECTION LOST\n");
return;
}
if(*(p=&p[good])=='\0')break;
p++;
}
if(*(sd->remdir)){
good=chg_remote_dirname(sd->remdir);
if(good==10){
appdata.connected=0;
append_status("CONNECTION LOST\n");
return;
}
}
update_remote(mask);
}
int update_remote(char* mask){
dirinfo *di;
di=create_remote_dirinfo(mask);
if(di==NULL)return 1;
destroy_dirinfo(appdata.remote.list);
appdata.remote.list=di;
update_dirname(appdata.remote.combo,appdata.remote.list);
update_dirlist(appdata.remote.table,appdata.remote.list);
return 0;
}
int update_local(char* mask){
destroy_dirinfo(appdata.local.list);
appdata.local.list=create_local_dirinfo(mask);
if(appdata.local.list==NULL)return 1;
update_dirname(appdata.local.combo,appdata.local.list);
update_dirlist(appdata.local.table,appdata.local.list);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1