/* ftp32.c by Yoshioka Tsuneo(QWF00133@nifty.ne.jp/tsuneo-y@is.aist-nara.ac.jp) Copy,Edit,Re-distribute FREE! */ #include "ftp32.h" #include "sock.h" #include #include #include #ifdef WIN32 #include #endif #include #include #include #include "common.h" char *ftpctrlgets(ftpconn *ftp,char *buf,int len) { char *retptr; retptr = sockgets(buf,len,ftp->ftpctrl); return retptr; } int ftpctrlgetslast(ftpconn *ftp,char *buf,int len) { char *retptr; do{ retptr = ftpctrlgets(ftp,buf,len); }while(retptr!=NULL && buf[3]=='-'); return atoi(buf); } int ftpgetretcode(ftpconn *ftp) { char line[1001]; char *retptr; /* 220-Jgaa's Fan Club FTP service WarFTPd 1.70.b01.04 (Aug 18 1998) Ready (C)opyright 1996 - 1998 by Jarle (jgaa) Aase - all rights reserved. 220 Please enter your user name. User (133.203.169.133:(none)): tomita 331 User name okay, Need password. Password: 230 User logged in. */ do{ retptr = ftpctrlgets(ftp,line,1000); }while(retptr!=NULL && (line[3]=='-' || line[0] == ' ')); return atoi(line); } int ftpconnect(ftpconn *ftp) { int ret; char line[1001]; ftp->ftpctrl = sockaopen(&ftp->ctrlremoteaddr,0,ftp->ctrlremoteport,"w"); if(! ftp->ftpctrl) goto errorlabel; socksetnonblocking(ftp->ftpctrl); ftp->ctrllocaladdr = getsocklocaladdr(ftp->ftpctrl); ftp->ctrllocalport = getsocklocalport(ftp->ftpctrl); ftp->ctrlremoteaddr = getsockremoteaddr(ftp->ftpctrl); ftp->ctrlremoteport = getsockremoteport(ftp->ftpctrl); /* "220 sgi052.aist-nara.ac.jp FTP server ready." */ if(ftpgetretcode(ftp) != 220) goto errorlabel; if(ftp->proxytype==1){ ret = sockprintf(ftp->ftpctrl,"USER %s@%s\r\n",ftp->user,ftp->remotehost); }else{ ret = sockprintf(ftp->ftpctrl,"USER %s\r\n",ftp->user); } /* "331 Password required for tsuneo-y." */ if(ftpgetretcode(ftp) != 331) goto errorlabel; ret = sockprintf(ftp->ftpctrl,"PASS %s\r\n",ftp->pass); /* "230 User tsuneo-y logged in." */ if(ftpgetretcode(ftp) != 230) goto errorlabel; if(ftp->proxytype==2){ ret = sockprintf(ftp->ftpctrl,"OPEN %s\r\n",ftp->remotehost); if(ftpgetretcode(ftp) != 220) goto errorlabel; } if(ftp->proxytype==3){ ret = sockprintf(ftp->ftpctrl,"open %s\r\n",ftp->remotehost); if(ftpgetretcode(ftp) != 220) goto errorlabel; } ret = sockprintf(ftp->ftpctrl,"SYST\r\n",ftp->pass); /* "215 UNIX Type: L8 Version: SVR4" */ ret = ftpctrlgetslast(ftp,line,1000); if(ret == 215){ char *ptr1,*ptr2=ftp->osname; if(ptr1=strchr(line,' ')){ ptr1++; while(*ptr1 && !isspace((unsigned char)*ptr1)){ *ptr2++ = *ptr1++; } *ptr2 = '\0'; } } ftpsettype(ftp,ftp->type); ftpchdir(ftp,ftp->cd); return 0; errorlabel: if(ftp->ftpctrl){ sockclose(ftp->ftpctrl); ftp->ftpctrl=0; } return -1; } ftpconn *ftpopen1(void) { ftpconn *ftp = NULL; /*printf("ftpopen(%s,%d,%s,%s)\n",host,port,user,pass);*/ ftp = malloc(sizeof(ftpconn)); if(ftp==NULL) goto errorlabel; memset(ftp,0,sizeof(ftpconn)); ftp->checkindex = 1; ftp->passive = 2; strcpy(ftp->cd,""); strcpy(ftp->type,"I"); return ftp; errorlabel: if(ftp){free(ftp);} return NULL; } int ftpopen2(ftpconn *ftp,const char *host,int port,const char *user,const char *pass) { if(ftp->proxytype){ if(hostname2addr(ftp->proxyhost,&ftp->ctrlremoteaddr) == -1) goto errorlabel; ftp->ctrlremoteport = ftp->proxyport; }else{ if(hostname2addr(host,&ftp->ctrlremoteaddr) == -1) goto errorlabel; ftp->ctrlremoteport = port; } strcpy(ftp->remotehost,host); strcpy(ftp->user,user ? user : "anonymous"); strcpy(ftp->pass,pass ? pass : "ftp32"); if(ftpconnect(ftp) == -1) goto errorlabel; return 0; errorlabel: return -1; } ftpconn *ftpopen(const char *host,int port,const char *user,const char *pass) { ftpconn *ftp = NULL; int ret; ftp = ftpopen1(); if(ftp==NULL){goto errorlabel;} ret = ftpopen2(ftp,host,port,user,pass); if(ret==-1)goto errorlabel; return ftp; errorlabel: if(ftp){ ftpclose(ftp); } return NULL; } int ftpsetproxy(ftpconn *ftp,int proxytype,const char *proxyhost,int proxyport) { ftp->proxytype = proxytype; strcpy(ftp->proxyhost,proxyhost); ftp->proxyport = proxyport; return 0; } int ftpopendata1(ftpconn *ftp) { char line[1001]; int ret; int a1,a2,a3,a4,p1,p2; char ftpdataserverhost[1000]; start: if(ftp->passive){ char *ptr; ret = sockputs("PASV\r\n",ftp->ftpctrl); /* "227 Entering Passive Mode (163,221,130,22,6,196)" */ ret = ftpctrlgetslast(ftp,line,1000); if(ret!=227){ /* If server don't support passivemode, enter non passive mode */ if((atoi(line)%100 == 5) && ftp->passive==2){ftp->passive=0;goto start;} goto errorlabel; } if(ptr = strchr(line,'(')){ ret = sscanf(ptr,"(%d,%d,%d,%d,%d,%d)",&a1,&a2,&a3,&a4,&p1,&p2); }else{ goto errorlabel; } /* sprintf(ftpdataserverhost,"%d.%d.%d.%d",a1,a2,a3,a4);*/ ((char *)&ftp->dataremoteaddr)[0] = a1; ((char *)&ftp->dataremoteaddr)[1] = a2; ((char *)&ftp->dataremoteaddr)[2] = a3; ((char *)&ftp->dataremoteaddr)[3] = a4; /* ftp->dataremoteaddr.S_un.S_un_b.s_b1 = a1; ftp->dataremoteaddr.S_un.S_un_b.s_b2 = a2; ftp->dataremoteaddr.S_un.S_un_b.s_b3 = a3; ftp->dataremoteaddr.S_un.S_un_b.s_b4 = a4; */ inet_ntoa2(ftp->dataremoteaddr,ftpdataserverhost); ftp->dataremoteport = (p1 << 8) + p2; ftp->ftpdata = sockopen(ftpdataserverhost,0,ftp->dataremoteport,"w"); if(ftp->ftpdata==NULL){goto errorlabel;} socksetnonblocking(ftp->ftpdata); }else{ /* normal ftp */ ftp->datalocalport = 12321; ftp->datalocaladdr = ftp->ctrllocaladdr; a1 = ((char *)&ftp->datalocaladdr)[0]; a2 = ((char *)&ftp->datalocaladdr)[1]; a3 = ((char *)&ftp->datalocaladdr)[2]; a4 = ((char *)&ftp->datalocaladdr)[3]; /* a1 = ftp->datalocaladdr.S_un.S_un_b.s_b1; a2 = ftp->datalocaladdr.S_un.S_un_b.s_b2; a3 = ftp->datalocaladdr.S_un.S_un_b.s_b3; a4 = ftp->datalocaladdr.S_un.S_un_b.s_b4; */ p1 = (ftp->datalocalport>>8) & 0x00ff; p2 = ftp->datalocalport & 0x00ff; inet_ntoa2(ftp->ctrlremoteaddr,ftpdataserverhost); ftp->ftpdata = sockopen(ftpdataserverhost,ftp->datalocalport,22,"r"); if(ftp->ftpdata==NULL){goto errorlabel;} socksetnonblocking(ftp->ftpdata); sprintf(line,"PORT %d,%d,%d,%d,%d,%d\r\n",a1,a2,a3,a4,p1,p2); ret = sockputs(line,ftp->ftpctrl); if(ftpgetretcode(ftp) != 200){goto errorlabel;} /* retptr = sockgets(line,1000,ftp->ftpctrl);*/ } return 0; errorlabel: if(ftp->ftpdata){ sockclose(ftp->ftpdata); } return -1; } int ftpopendata2(ftpconn *ftp) { int ret; if(ftp->passive){ /* passive */ ; }else{ /* normal(active) ftp */ ret = sockaccept(ftp->ftpdata); if(ret<0){return -1;} } return 0; } int ftpclosedata(ftpconn *ftp) { if(ftp->ftpdata){sockclose(ftp->ftpdata);ftp->ftpdata=0;} return 0; } int ftpclose(ftpconn *ftp) { if(ftp==NULL){return -1;} if(ftp->statlist){ftpclosedir(ftp);} if(ftp->ftpdata){ftpclosedata(ftp);} if(ftp->ftpctrl){sockclose(ftp->ftpctrl);ftp->ftpctrl=0;} free(ftp); return 0; } int ftpsetmode(ftpconn *ftp,int mode) { if(ftp==NULL){return -1;} if(!(mode==0 || mode==1 || mode==2)){return -1;} ftp->passive = mode; return 0; } int ftpchdir(ftpconn *ftp,const char *path) { int ret; char line[1001]; char *ptr1,*ptr2; if(! ftp->ftpctrl){return -1;} if(*path!='\0'){ ret = sockprintf(ftp->ftpctrl,"CWD %s\r\n",path); /* "250 CWD command successful." */ ret = ftpgetretcode(ftp); if(ret!=250){return -1;} } ret = sockprintf(ftp->ftpctrl,"PWD\r\n",path); ret = ftpctrlgetslast(ftp,line,1000); /* "257 "/auto/home/is/tsuneo-y" is current directory." */ if(ret != 257){return -1;} if(ptr1=strchr(line,'"')){ if(ptr2=strrchr(ptr1+1,'"')){ strncpy(ftp->cd,ptr1+1,ptr2-ptr1-1); ftp->cd[ptr2-ptr1-1] = '\0'; }else{ return -1; } }else{ return -1; } return 0; } int ftpmkdir(ftpconn *ftp,const char *path) { int ret; if(! ftp->ftpctrl){return -1;} ret = sockprintf(ftp->ftpctrl,"MKD %s\r\n",path); ret = ftpgetretcode(ftp); if(ret!=257){return -1;} return 0; } int ftprmdir(ftpconn *ftp,const char *path) { int ret; if(! ftp->ftpctrl){return -1;} ret = sockprintf(ftp->ftpctrl,"RMD %s\r\n",path); ret = ftpgetretcode(ftp); if(ret!=250){return -1;} return 0; } int ftprename(ftpconn *ftp,const char *from,const char *to) { int ret; if(! ftp->ftpctrl){return -1;} ret = sockprintf(ftp->ftpctrl,"RNFR %s\r\n",from); ret = ftpgetretcode(ftp); if(ret!=350){return -1;} ret = sockprintf(ftp->ftpctrl,"RNTO %s\r\n",to); ret = ftpgetretcode(ftp); if(ret!=250){return -1;} return 0; } int ftpdelete(ftpconn *ftp,const char *path) { int ret; if(! ftp->ftpctrl){return -1;} ret = sockprintf(ftp->ftpctrl,"DELE %s\r\n",path); ret = ftpgetretcode(ftp); if(ret!=250){return -1;} return 0; } int ftpsettype(ftpconn *ftp,const char *type) { int ret; if(! ftp->ftpctrl){return -1;} ret = sockprintf(ftp->ftpctrl,"TYPE %s\r\n",type); /* "200 Type set to I." */ ret = ftpgetretcode(ftp); if(ret!=200){return -1;} strcpy(ftp->type,type); return 0; } /* resume from [pos] byte */ int ftprestart(ftpconn *ftp,int pos) { ftp->restartoffset = pos; return 0; } int ftpsetresumegetmode(ftpconn *ftp,int onoff) { ftp->resumegetmode = onoff; ftp->restartoffset = 0; return 0; } int ftpcancel(ftpconn *ftp) { if(ftp->ftpdata){sockcancel(ftp->ftpdata);} if(ftp->ftpctrl){sockcancel(ftp->ftpctrl);} return 0; } int ftpsetcallbackmsgfunc(ftpconn *ftp,int (WINAPI *callbackmsgfunc)(char *msg,void *callbackmsgfuncparam),void *callbackmsgfuncparam) { ftp->callbackmsgfunc = callbackmsgfunc; ftp->callbackmsgfuncparam = callbackmsgfuncparam; return 0; } int ftpcallbackmsg(ftpconn *ftp,char *msg) { if(ftp->callbackmsgfunc==NULL){return 0;} ftp->callbackmsgfunc(msg,ftp->callbackmsgfuncparam); } int ftpopenfile(ftpconn *ftp,const char *file,const char *mode) { int ret; int writing = 0; int binary = 0; char line[1000]; char *p; if(! ftp->ftpctrl){goto errorlabel;} while(*mode){ if(*mode == 'b'){binary = 1;} if(*mode == 'w'){writing = 1;} mode++; } ftp->writing = writing; if(binary){ftpsettype(ftp,"I");}else{ftpsettype(ftp,"A");} ret = ftpopendata1(ftp); if(ret==-1) goto errorlabel; if(ftp->restartoffset){ ret = sockprintf(ftp->ftpctrl,"REST %d\r\n",ftp->restartoffset); ret = ftpgetretcode(ftp); if(ret==350){ ftp->donesize = ftp->restartoffset; } } if(ftp->writing){ ret = sockprintf(ftp->ftpctrl,"STOR %s\r\n",file); }else{ ret = sockprintf(ftp->ftpctrl,"RETR %s\r\n",file); } ret = ftpopendata2(ftp); if(ret==-1) goto errorlabel; /* "150 Opening BINARY mode data connection for 'a'." */ /* (IIS3) "125 Data connection already open; Transfer starting." */ ret = ftpctrlgetslast(ftp,line,sizeof(line)); if((ret != 150) && (ret != 125)){goto errorlabel;} if(ftp->writing == 0){ p = strchr(line,'('); if(p != NULL){ ftp->readfilesize = atoi(p+1); } } /* ret = ftpgetretcode(ftp); if(ret!=150) goto errorlabel; */ return 0; errorlabel: ftpclosedata(ftp); return -1; } int ftpread(ftpconn *ftp,char *buf,int len) { int n; n = sockread(ftp->ftpdata,buf,len); if(n<0){ return n; } ftp->donesize += n; if(ftp->callbackmsgfunc){ int ti = time(NULL); /* send message each second */ if(ti > ftp->msgtime){ char str[1000]; sprintf(str,"READ: %d/%d\n",ftp->donesize,ftp->readfilesize); ftpcallbackmsg(ftp,str); ftp->msgtime = ti; } } return n; } int ftpwrite(ftpconn *ftp,const char *buf,int len) { int n; n = sockwrite(ftp->ftpdata,buf,len); if(n<=0){return n;} ftp->donesize += n; if(ftp->callbackmsgfunc){ int ti = time(NULL); /* send message each second */ if(ti > ftp->msgtime){ char str[1000]; sprintf(str,"WRITE: %d/%d\n",ftp->donesize,ftp->writefilestat.st_size); ftpcallbackmsg(ftp,str); ftp->msgtime = ti; } } return n; } int ftpclosefile(ftpconn *ftp) { int ret; if(ftp)ftp->readfilesize = 0; if(ftp)ftp->restartoffset = 0; if(ftp->ftpdata){ ftpclosedata(ftp); /* "226 Transfer complete." */ ret = ftpgetretcode(ftp); if(ret!=226){return -1;} } return 0; } int ftpget(ftpconn *ftp,const char *remotefn,const char *localfn,const char *mode) { FILE *fp_w = NULL; char buf[4096]; int n; int binary=0; struct stat st; char localfn2[1000]; const char *remotefn2; int func_ret = -1; int c; if(localfn!=NULL && *localfn=='\0'){localfn=NULL;} if(localfn==NULL){localfn = remotefn;} strcpy(localfn2,localfn); c = getlastchar(localfn2); if(c == '\\' || c=='/' || (stat(localfn2,&st)==0 && (st.st_mode & S_IFMT) == S_IFDIR)){ remotefn2 = strrchr(remotefn,'/'); if(remotefn2)remotefn2++; else remotefn2 = remotefn; fnamecat(localfn2,remotefn2); } if(stat(localfn2,&st)==0){ if((st.st_mode & S_IFMT)==S_IFDIR){goto endlabel;} if(ftp->resumegetmode){ ftprestart(ftp,st.st_size); } } if(strchr(mode,'b')){binary=1;} if(ftpopenfile(ftp,remotefn,binary ? "rb" : "r")==-1) goto endlabel; if(ftp->restartoffset!=0){ if((fp_w=fopen(localfn2,binary ? "ab" : "a"))==NULL) goto endlabel; }else{ if((fp_w=fopen(localfn2,binary ? "wb" : "w"))==NULL) goto endlabel; } while((n = ftpread(ftp,buf,4096))>0){ fwrite(buf,1,n,fp_w); } func_ret = 0; endlabel: if(fp_w)fclose(fp_w); ftpclosefile(ftp); return func_ret; } int ftpput(ftpconn *ftp,const char *remotefn,const char *localfn,const char *mode) { FILE *fp_r = NULL; char buf[4096]; int n; int binary=0; int ret; int func_ret = -1; if(localfn!=NULL && *localfn=='\0'){localfn=NULL;} if(remotefn!=NULL && *remotefn=='\0'){remotefn=NULL;} if(localfn==NULL && remotefn==NULL){return -1;} if(localfn==NULL){localfn = remotefn;} if(remotefn==NULL){ char *ptr; if((ptr = strrpbrk(localfn,"/\\"))!=NULL){ remotefn = ptr + 1; }else{ remotefn = localfn; } } if(strchr(mode,'b')){binary=1;} if(stat(localfn,&ftp->writefilestat)!=0){goto endlabel;} if(ftpopenfile(ftp,remotefn,binary ? "wb" : "w")==-1) goto endlabel; if((fp_r=fopen(localfn,binary ? "rb" : "r"))==NULL) goto endlabel; while((n = fread(buf,1,4096,fp_r))>0){ ret = ftpwrite(ftp,buf,n); if(ret<0){goto endlabel;} } func_ret = 0; endlabel: if(fp_r)fclose(fp_r); ftpclosefile(ftp); memset(&ftp->writefilestat,0,sizeof(ftp->writefilestat)); return func_ret; } /* 08-17-98 05:25PM 98shimane 09-08-98 02:41PM 1104 01.gif */ int ftplist2stat_windows_nt(char *list,struct ftpstat *ftpstat) { struct tm tm; int d1,d2,d3; int t1,t2; char m1; int n; int size=0; char sizedir[1000]; int ret; /* struct tm tmp_tm1,tmp_tm2,tmp_tm3; struct tm *tmp_tmptr1,*tmp_tmptr2,*tmp_tmptr3; int tmp_ti1,tmp_ti2,tmp_ti3; */ memset(&tm,0,sizeof(tm)); chopreturn(list); memset(ftpstat,0,sizeof(struct ftpstat)); /* MM-DD-YY hh:mm(AM/PM) (|size) filename */ ret = sscanf(list,"%d-%d-%d %d:%d%cM %s %n" ,&d1,&d2,&d3 ,&t1,&t2 ,&m1 ,sizedir ,&n); if(ret != 7){return -1;} if(*(list+n) == '\0'){return -1;} if(strcmp(sizedir,"")==0){ ftpstat->st_mode = S_IFDIR; }else if(isdigit((unsigned char)(sizedir[0]))){ ftpstat->st_mode = S_IFREG; ftpstat->st_size = atoi(sizedir); }else{ return -1; } /* if(ret != 6){ ret = sscanf(list,"%d-%d-%d %d:%d%cM %d %n" ,&d1,&d2,&d3 ,&t1,&t2 ,&size ,&m1 ,&n); ; if(ret != 7){return -1;} } */ ftpstat->st_mode |= S_IREAD; tm.tm_mday = d2; tm.tm_mon = d1 - 1; if(d3>=1900){ d3 -= 1900; }else if(d3<50){ d3 += 100; } tm.tm_year = d3; if(m1 == 'P'){ t1 += 12; }else if(m1 == 'A'){ ; }else{ return -1; } tm.tm_hour = t1; tm.tm_min = t2; ftpstat->st_mtime = timelocal(&tm); /*tm = (* localtime(&ftpstat->st_mtime));*/ ftpstat->st_size = size; strcpy(ftpstat->filename,list+n); /* tmp_ti1 = ftpstat->st_mtime; tmp_tmptr1 = localtime(&ftpstat->st_mtime); tmp_tmptr2 = localtime(&tmp_ti1); tmp_tm1 = (* localtime(&ftpstat->st_mtime)); tmp_ti2 = timelocal(&tmp_tm1); tmp_tm2 = (* localtime(&tmp_ti2)); tmp_ti3 = timelocal(&tmp_tm2); tmp_tm3 = (* localtime(&tmp_ti3)); */ return 0; } int ftplist2stat_unix(char *list,struct ftpstat *ftpstat) { int ret; char modestr[100]; int mode=0; struct tm tm; int n; char monstr[100]; int mday; char c1,c2,c3,c4; int year; char *ptr; int nlink; chopreturn(list); memset(ftpstat,0,sizeof(struct ftpstat)); /* printf("ftplist2stat1:list=[%s]\n",list); */ ret = sscanf(list,"%s %d %s %s %d %n" ,modestr,&nlink,ftpstat->username,ftpstat->groupname,&ftpstat->st_size,&n); if(ret!=5){return 0;} ftpstat->st_nlink = nlink; /* ftpstat->nlink maybe short... */ switch(modestr[0]){ case 'd': mode |= S_IFDIR; break; case 'c': mode |= S_IFCHR; break; case 'l': mode |= S_IFLNK; break; case '-': mode |= S_IFREG; break; default: mode |= S_IFREG; } if(modestr[1]=='r'){mode |= 0400;} if(modestr[2]=='w'){mode |= 0200;} if(modestr[3]=='x'){mode |= 0100;} if(modestr[4]=='r'){mode |= 0040;} if(modestr[5]=='w'){mode |= 0020;} if(modestr[6]=='x'){mode |= 0010;} if(modestr[7]=='r'){mode |= 0004;} if(modestr[8]=='w'){mode |= 0002;} if(modestr[9]=='x'){mode |= 0001;} ftpstat->st_mode = mode; list+=n; { time_t ti; ti = time(NULL); tm = * (localtime(&ti)); } ret = sscanf(list,"%s %d %c%c:%c%c %n",monstr,&mday,&c1,&c2,&c3,&c4,&n); if(ret==6 && isdigit(c1) && isdigit(c2) && isdigit(c3) &&isdigit(c4)){ tm.tm_sec = 0; tm.tm_min = (c3-'0')*10+(c4-'0'); tm.tm_hour = (c1-'0')*10+(c2-'0'); tm.tm_mday = mday; tm.tm_mon = monstr2mon(monstr); list+=n; }else{ ret = sscanf(list,"%s %d %d %n",monstr,&mday,&year,&n); if(ret==3){ tm.tm_sec = 0; tm.tm_min = 0; tm.tm_hour = 0; tm.tm_mday = mday; tm.tm_mon = monstr2mon(monstr); tm.tm_year = year - 1900; } list+=n; } ftpstat->st_mtime = timelocal(&tm); if(! *list){return -1;} strcpy(ftpstat->filename,list); /*i=strlen(ftpstat->filename); if(i==0){return -1;} i--; while(isspace(ftpstat->filename[i]) && i>=0){ ftpstat->filename[i] = '\0'; i--; } if(i<0){return -1;}*/ if(ptr=strstr(ftpstat->filename," -> ")){ *ptr = '\0'; strcpy(ftpstat->linkname,ptr+4); } /* if symbolic link then if filename contain "." then file is regular file else file is directory endif endif */ if((ftpstat->st_mode & S_IFMT)==S_IFLNK){ ftpstat->st_mode &= ~S_IFMT; if(strchr(ftpstat->filename,'.')!=0){ ftpstat->st_mode |= S_IFREG; }else{ ftpstat->st_mode |= S_IFDIR; } } return 0; } int ftplist2stat(char *list,struct ftpstat *ftpstat,char *osname) { int func_ret=-1; /* SYST = Windows_NT version 4.0 (IIS4.0) */ if(ftplist2stat_windows_nt(list,ftpstat)!=-1){func_ret=0;goto endlabel;} /* osname = UNIX */ if(ftplist2stat_unix(list,ftpstat)!=-1){func_ret=0;goto endlabel;} endlabel: if(func_ret==0){ char *p = ftpstat->filename; /* c:\ => c */ if(*p && *(p+1)==':' && *(p+2)=='\\' && *(p+3)=='\0'){*(p+1) = '\0';} } return func_ret; } static int ftpcheckindex(ftpconn *ftp,const char *path) { #ifndef MAX_PATH #define MAX_PATH 1000 #endif char indexfile[MAX_PATH]; int ret; char fname[1000]; FILE *fp; char line[1001]; strcpy(fname,path); if(*fname && fname[strlen(fname)-1] != '/'){strcat(fname,"/");} strcat(fname,"Index"); #ifdef WIN32 ret = GetWindowsDirectory(indexfile,MAX_PATH); if(ret<=0){return -1;} strcat(indexfile,"/Temp/Index"); #else strcpy(indexfile,"/tmp/Index"); #endif ret = ftpget(ftp,fname,indexfile,"b"); if(ret==-1){goto errorlabel;} if((fp=fopen(indexfile,"r"))==NULL){ return -1; } while(fgets(line,1000,fp)!=NULL){ char tstr[1000]; char tstr2[1000]; char fname[1001]; int type; int n; int i; chopreturn(line); ret = sscanf(line,"%s %s %s %s %n",tstr,tstr,tstr,tstr2,&n); if(ret!=4){continue;} strcpy(fname,line+n); if(atoi(tstr2)>0 || strcmp(tstr,"0")==0){ type = 0; /* file */ }else if(strcmp(tstr2,"dir")==0){ type = 1; /* dir */ }else{ continue; } for(i=0;istatlistsize;i++){ if(strcmp(ftp->statlist[i].filename,fname)==0){ ftp->statlist[i].st_mode &= ~S_IFMT; if(type == 0){ ftp->statlist[i].st_mode |= S_IFREG; }else if(type==1){ ftp->statlist[i].st_mode |= S_IFDIR; } break; } } } fclose(fp); unlink(indexfile); return 0; errorlabel: unlink(indexfile); return -1; } int ftpopendir(ftpconn *ftp,const char *path) { int ret; char *retptr; char line[1001]; struct ftpstat ftpstat; ftp->statlistsize = 0; ret = ftpopendata1(ftp); if(ret!=0) goto errorlabel; if(*path){ ret = sockprintf(ftp->ftpctrl,"LIST %s\r\n",path); }else{ ret = sockprintf(ftp->ftpctrl,"LIST\r\n"); } ret = ftpgetretcode(ftp); if(ret!=150 && ret!=125) goto errorlabel; ret = ftpopendata2(ftp); if(ret!=0) goto errorlabel; while((retptr = sockgets(line,1000,ftp->ftpdata))!=NULL){ if(strncmp(line,"total",5)==0){continue;} if(ftplist2stat(line,&ftpstat,ftp->osname) !=-1){ if(ftp->statlist = realloc(ftp->statlist,sizeof(struct ftpstat) * (ftp->statlistsize + 1))){ ftp->statlist[ftp->statlistsize] = ftpstat; ftp->statlistsize++; } } } ftpclosedata(ftp); ret = ftpgetretcode(ftp); if(ret!=226) goto errorlabel; ftp->statlist_current = -1; if(ftp->checkindex){ ftpcheckindex(ftp,path); } return 0; errorlabel: ftpclosedata(ftp); return -1; } struct ftpstat * ftpreaddir(ftpconn *ftp) { ftp->statlist_current++; if(ftp->statlist_current >= ftp->statlistsize){ return NULL; } return &ftp->statlist[ftp->statlist_current]; } int ftpclosedir(ftpconn *ftp) { if(ftp->statlist){ free(ftp->statlist); ftp->statlist=NULL; ftp->statlistsize=0; ftp->statlist_current=-1; } return 0; } #ifdef FTP32_MAIN int ftplist(char *host,char *path) { ftpconn *ftp; int ret; char localhost[1001]; char mailaddr[1000]; char username[1001]; int len; struct ftpstat *ftpstatptr; if(! (len = 1000,GetUserName(username,&len))){ strcpy(username,"ftp32"); } /* getinethostname(localhost,1000); sprintf(mailaddr,"%s@%s",username,localhost); */ strcpy(username,"username"); ftp = ftpopen(host,21,"anonymous",mailaddr); ret = ftpopendir(ftp,path); while(ftpstatptr = ftpreaddir(ftp)){ printf("%u,%d,%d,%s,%s,%s,%s,%s\n", ftpstatptr->st_mode ,ftpstatptr->st_nlink ,ftpstatptr->st_mtime ,ctime(&ftpstatptr->st_mtime) ,ftpstatptr->username ,ftpstatptr->groupname ,ftpstatptr->filename ,ftpstatptr->linkname ); } ret = ftpclosedir(ftp); /*ret = ftpopendata1(ftp); ret = sockputs("LIST\r\n",ftp->ftpctrl); ret = ftpopendata2(ftp); while((retptr = sockgets(line,1000,ftp->ftpdata))!=NULL){ printf("line=[%s]\n",line); } ftpclosedata(ftp);*/ ftpclose(ftp); return 0; #if 0 SOCK *ftpctrl; SOCK *ftpdata; char line[1000]; int ftpdataport; struct in_addr ftpdataaddr; int ret; int a1,a2,a3,a4,p1,p2; char ftpdataserverhost[1000]; int ftpdataserverport; struct in_addr ftpdataclientaddr; char ftpdataclienthostname[1000]; int ftpdataclientport; char *retptr; char *ptr; ftpctrl = sockopen(host,0,21,"w"); ftpdataclientaddr = getsocklocaladdr(ftpctrl); strcpy(ftpdataclienthostname,inet_ntoa(ftpdataclientaddr)); do{ retptr = sockgets(line,1000,ftpctrl); }while(retptr!=NULL && line[3]=='-'); ret = sockputs("USER anonymous\r\n",ftpctrl); do{ retptr = sockgets(line,1000,ftpctrl); }while(retptr!=NULL && line[3]=='-'); ret = sockputs("PASS ftp32\r\n",ftpctrl); do{ retptr = sockgets(line,1000,ftpctrl); }while(retptr!=NULL && line[3]=='-'); if(0 /* pasv */){ ret = sockputs("PASV\r\n",ftpctrl); do{ retptr = sockgets(line,1000,ftpctrl); }while(retptr!=NULL && line[3]=='-'); if(ptr = strchr(line,'(')){ ret = sscanf(ptr,"(%d,%d,%d,%d,%d,%d)",&a1,&a2,&a3,&a4,&p1,&p2); } s sprintf(ftpdataserverhost,"%d.%d.%d.%d",a1,a2,a3,a4); ftpdataserverport = (p1 << 8) + p2; ftpdata = sockopen(ftpdataserverhost,22,ftpdataserverport,"w"); ret = sockputs("LIST\r\n",ftpctrl); retptr = sockgets(line,1000,ftpctrl); /* retptr = sockgets(line,1000,ftpctrl); retptr = sockgets(line,1000,ftpctrl); sockaccept(ftpdata); */ while((retptr = sockgets(line,1000,ftpdata))!=NULL){ ; } }else{ /* normal ftp */ ftpdataclientport = 12321; a1 = ftpdataclientaddr.S_un.S_un_b.s_b1; a2 = ftpdataclientaddr.S_un.S_un_b.s_b2; a3 = ftpdataclientaddr.S_un.S_un_b.s_b3; a4 = ftpdataclientaddr.S_un.S_un_b.s_b4; p1 = (ftpdataclientport>>8) & 0x00ff; p2 = ftpdataclientport & 0x00ff; strcpy(ftpdataserverhost,inet_ntoa(getsockremoteaddr(ftpctrl))); ftpdata = sockopen(ftpdataserverhost,ftpdataclientport,22,"r"); sprintf(line,"PORT %d,%d,%d,%d,%d,%d\r\n",a1,a2,a3,a4,p1,p2); ret = sockputs(line,ftpctrl); retptr = sockgets(line,1000,ftpctrl); ret = sockputs("LIST\r\n",ftpctrl); retptr = sockgets(line,1000,ftpctrl); /*retptr = sockgets(line,1000,ftpctrl);*/ sockaccept(ftpdata); while((retptr = sockgets(line,1000,ftpdata))!=NULL){ ; } } /*ftpdataport = getsocklocalport(ftpdata); ftpdataaddr = getsocklocaladdr(ftpdata); */ return 0; #endif } int main(int argc,char *argv[]) { char ftphost[1000]; char ftppath[1000]; --argc,++argv; while(argc){ if(**argv=='-'){ char *argp=*argv+1; switch(*argp){ case 'l': break; default: break; } }else{ break; } argc--; argv++; } if(argc>0){ strcpy(ftphost,*argv); argv++; argc--; }else{ strcpy(ftphost,"localhost"); } if(argc>0){ strcpy(ftppath ,*argv); argv++; argc--; }else{ strcpy(ftppath , "/"); } ftplist(ftphost,ftppath); return 0; } #endif /* FTP32_MAIN */