int process_RETR(struct session* ses, const char* data) { if (strlen(data) > 0) { char file[MAX_PATH]; if (relative_to_absolute_path(ses->current_dir, data, file)) { struct stat st; if (lstat(file, &st) != -1) if (open_data_connection(ses) != -1) { char buf[BUF_LEN]; snprintf (buf, BUF_LEN, "Opening BINARY mode data connection for %s.", data); respond (ses, 150, buf); if (send_file(ses, file) != -1) respond (ses, 226, "Transfer complete."); else respond (ses, 550, "Transfer failed."); close_data_connection (ses); return 0; } } } respond (ses, 550, "Failed to open file."); return 0; }
// perform FTP RETR command, sends a file to the client void command_retr(CLIENT_INFO * client_info) { char line[BUFFER_SIZE] = { 0 }; client_read_line(client_info->fd, client_info->buf, &client_info->buffer_pos); extract_line(line, client_info->buf, &client_info->buffer_pos); int len = strlen(line); if (len < 6) { send_code(client_info->fd, 500); return; } char * filename = line + 5; char filenamebuf[PATH_MAX + 1] = { 0 }; if (filename[0] == '/') { snprintf(filenamebuf, PATH_MAX, "%s%s", basedir, filename); } else { snprintf(filenamebuf, PATH_MAX, "%s%s%s", basedir, client_info->dir, filename); } int fd = open(filenamebuf, O_RDONLY); if (fd == -1) { // cannot open file send_code(client_info->fd, 550); return; } send_code(client_info->fd, 150); open_data_connection(client_info); while (1) { char buf[FILE_READ_BUFFER_SIZE]; int bytes_read = read(fd, buf, FILE_READ_BUFFER_SIZE); if (bytes_read == 0) break; if (bytes_read == -1) epicfail("read"); int res = data_connection_write_buffer(client_info, buf, bytes_read); if (res == -1) break; } close(fd); close_data_connection(client_info); send_code(client_info->fd, 226); }
/********************************************************************************************** void QueryDirContent(int server_fd,char directory[]) func:get contends in current directory ***********************************************************************************************/ void QueryDirContent(int server_fd,char directory[]) { char response_type[20]; char response_argu[20]; int server_data_channel_fd; int nbytes; int item_count = 0; struct file_list * files_head = NULL; struct file_list * pfile = NULL; memset(buffer,'\0',BUF_SIZE); //clear the buffer before use sprintf(buffer,"request;querydircontent;%s%s|",current_directory,directory); if(send(server_fd,buffer,strlen(buffer),0)==-1) { printf("send error\n"); } memset(buffer,'\0',BUF_SIZE); //clear the buffer before use recv(server_fd,buffer,BUF_SIZE,0); response_analysis(buffer,response_type,response_argu); if(strcmp(response_type,"error") == 0) { printf("%s:%s\n",response_type,response_argu); return; } server_data_channel_fd = get_data_connection(); memset(buffer,BUF_SIZE,'\0'); //clear the buffer before use printf("type\tname\t\t\t\tsize\n"); while((nbytes = recv(server_data_channel_fd,buffer,BUF_SIZE,0)) > 0) { buffer[nbytes]='\0'; files_head = get_files_information(buffer); pfile = files_head; while(pfile->next_file != NULL){ item_count++; pfile = pfile->next_file; printf("%s\t%-20s\t\t%-6d\n",pfile->file_type?"dir":"file",pfile->file_name,pfile->file_size); } memset(buffer,BUF_SIZE,'\0'); //clear the buffer before use free_file_list(files_head); } printf("total %d items\n",item_count); close_data_connection(server_data_channel_fd); printf("end of query dir \n"); }
/************************************************************************* int DownloadFile(int server_fd,char* filename) func : recieve file from server return : *************************************************************************/ int DownloadFile(int server_fd,char* filename) { int bytes_recv = 0; char response_type[20]; char response_argu[20]; FILE* file_to_recv; int server_send_fd; memset(buffer,'\0',BUF_SIZE); //clear the buffer before use sprintf(buffer,"request;downloadfile;%s;%s|",current_directory,filename); if(send(server_fd,buffer,strlen(buffer),0)==-1) printf("GetConnection send package error! \n"); memset(buffer,'\0',BUF_SIZE); //clear the buffer before use if(recv(server_fd,buffer,BUF_SIZE,0)>0){ response_analysis(buffer,response_type,response_argu); if(strncmp(response_type,"ack",3)==0){ printf("file exist now begin to download\n"); server_send_fd = get_data_connection(); //get data channel connection to server if((file_to_recv=fopen(filename,"w"))==NULL){ printf("can not open the file to recv! \n"); return -1; } if((bytes_recv = recv_file(server_send_fd,file_to_recv)) == -1){ printf("recieve package error \n"); return -1; } printf("%d bytes recieved \n",bytes_recv); close_data_connection(server_send_fd); //close data channel connection to server return 1; } else{ printf("file not exist \n"); return 0; } } else{ printf("server has been shutdown\n"); return -1; } }
int process_LIST(struct session* ses, const char* data) { if (open_data_connection(ses) != -1) { // listing directory via `ls` command piped to temporary file char cmd[2*MAX_PATH]; snprintf (cmd, 2*MAX_PATH, "ls %s \"%s\" | tail -n+2 >%s", LIST_LS_PARAMS, ses->current_dir, LIST_LS_OUTFILE); if (system(cmd) != -1) { respond (ses, 150, "Here comes the directory listing."); if (send_file(ses, LIST_LS_OUTFILE) != -1) { respond (ses, 226, "Directory send OK."); close_data_connection (ses); unlink (LIST_LS_OUTFILE); return 0; } } } respond (ses, 550, "Directory listing failed."); return 0; }
/* called to retrive a file from remote host */ void getfile( char *fname) { FILE *fp=NULL; int fd, nTotal=0, nBytesRead=0, retval, aborted=0; char *abortstr = "ABORrn", ch; if( !fname || ! (*fname)) { printf("No file specified.n"); return; } /* * open the file with current mode */ if(! (fp=fopen(fname,(bMode==ASCII) ? "wt" : "wb"))) { perror("file open"); return; } /* * obtain a listen socket */ if( get_listen_socket() < 0) { fclose(fp); return; } /* * send command to server and read response */ sprintf(tmp_buffer,"RETR %srn",fname); if(!send_ctrl_msg(tmp_buffer,strlen(tmp_buffer))) { fclose(fp); return; } int l= get_host_reply(); if(l==550)return; /* * accept server connection */ if( accept_connection() <= 0) { fclose(fp); return; } /* * now get file and store */ fd = fileno(fp); printf("Type q and hit return to abortrn"); while( (nBytesRead=data_msg(tmp_buffer,1024)) > 0) { write(fd,tmp_buffer,nBytesRead); nTotal+=nBytesRead; printf("%s : %d receivedr",fname,nTotal); if( check_input() ) { ch = getchar(); if( ch != 'n') { while( getchar() != 'n') ; /* read 'til new line */ } if( ch == 'q') aborted = 1; } /* * did we abort? */ if( aborted ) { printf("rnAbort: Waiting for server to finish."); send_ctrl_msg(abortstr,strlen(abortstr)); break; } } if( aborted ) { // ignore everything if aborted. while( (nBytesRead=data_msg(tmp_buffer,1024)) > 0); get_host_reply(); } /* (void)signal(SIGINT,OldHandler); */ printf("rn"); close(fd); close_data_connection(hDataSocket); /*/ ControlCHit = 0; */ get_host_reply(); }
/* * put_file */ void put_file( char *fname) { FILE *fp=NULL; int fd, nTotal=0, nBytesRead=0, retval, aborted=0; char *abortstr = "ABORrn", ch; /* void (*OldHandler)(int); */ if( !fname || ! (*fname)) { printf("No file specified.n"); return; } if(! (fp=fopen(fname,(bMode==ASCII) ? "rt" : "rb"))) { perror("file open"); return; } if( get_listen_socket() < 0) { fclose(fp); return; } /* * send command to server & read reply */ sprintf(tmp_buffer,"STOR %srn",fname); if(!send_ctrl_msg(tmp_buffer,strlen(tmp_buffer))) { fclose(fp); return; } int m=get_host_reply(); if(m==550) return; /* * accept server connection */ if( accept_connection() <= 0) { fclose(fp); return; } /* * now send file */ fd = fileno(fp); printf("Type q and hit return to abortrn"); while( (nBytesRead=read(fd,tmp_buffer,1024)) > 0) { send_data_msg(tmp_buffer,nBytesRead); nTotal+=nBytesRead; printf("%s : %d sentr",fname,nTotal); if( check_input() ) { ch = getchar(); if( ch != 'n') { while( getchar() != 'n') ; /* read 'til new line */ } if( ch == 'q') aborted = 1; } /* * send an abort command to server if we aborted. */ if( aborted ) { printf("rnAbort: Waiting for server to finish."); send_ctrl_msg(abortstr,strlen(abortstr)); break; } } /*(void)signal(SIGINT,OldHandler); */ printf("rn"); /* * close data connection */ close_data_connection(hDataSocket); close(fd); get_host_reply(); }
// perform FTP LIST command, sends a directory listing to the client void command_list(CLIENT_INFO * client_info) { char line[BUFFER_SIZE] = { 0 }; client_read_line(client_info->fd, client_info->buf, &client_info->buffer_pos); extract_line(line, client_info->buf, &client_info->buffer_pos); int len = strlen(line); char * path = NULL; if (len != 4) { char * p = line + 5; if (*p == '-') { while (*p && (*p != ' ')) p++; } while (*p && (*p == ' ')) p++; path = p; } char dirbuf[PATH_MAX + 1] = { 0 }; snprintf(dirbuf, PATH_MAX, "%s%s", basedir, client_info->dir); if (path) { if (path[0] == '/') { snprintf(dirbuf, PATH_MAX, "%s%s", basedir, path); } else { strcat(dirbuf, "/"); strcat(dirbuf, path); } } char realpathbuf[PATH_MAX + 1] = { 0 }; if (! realpath(dirbuf, realpathbuf)) { send_code(client_info->fd, 550); return; } strcpy(dirbuf, realpathbuf); if (dirbuf[strlen(dirbuf) - 1] != '/') strncat(dirbuf, "/", PATH_MAX); DIR * dirp = opendir(dirbuf); if (! dirp) { send_code(client_info->fd, 550); return; } send_code(client_info->fd, 150); open_data_connection(client_info); while (1) { struct dirent * entry = readdir(dirp); if (! entry) break; char filenamebuf[PATH_MAX + 1] = { 0 }; snprintf(filenamebuf, PATH_MAX, "%s%s", dirbuf, entry->d_name); struct stat s; if (stat(filenamebuf, &s) == -1) { // cannot stat continue; } char buf[PATH_MAX + 128 + 1] = { 0 }; strmode(s.st_mode, buf); unsigned int size = (unsigned int)s.st_size; char date[64]; struct tm * ts = localtime(&s.st_mtime); strftime(date, 64, "%b %e %Y", ts); sprintf(buf + 11, "%3d %-8d %-8d %8u %s %s\r\n", s.st_nlink, (int)s.st_uid, (int)s.st_gid, size, date, entry->d_name); data_connection_write_string(client_info, buf); } close_data_connection(client_info); send_code(client_info->fd, 226); }