📄 ftpheader.c
字号:
/* Get and Resume Elite EDition source codeGet and Resume Elite EDition (GREED)Copyright (C) 1999 Anoakie TurnerThis program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.For more information on the GPL, please go to:http://www.gnu.org/copyleft/gpl.html Contact: Anoakie Turner Anoakie.Turner@asu.edu 13240 N. 94th Pl. Scottsdale, AZ 85260*/#include "main.h"void RecurseFTP(char*, char*, int);int ReadSock (int sockfd, char* buffer, char* stopstr)/*************************************** ReadSock(int, char*, char*)**** PRE: Assigned(sockfd, buffer, stopstr)** POST: reads data from socket(sockfd) until either the** stopstr is hit or sockfd reaches the EOF*************************************/{ int len = 1; int result = 0; struct timeval timeout; /* = { TIMEOUT_SEC, 0 }; .8+S patch */ timeout.tv_sec = TIMEOUT_SEC; timeout.tv_usec = 0; do { switch(select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, &timeout)) { case 0: if (OUTPUT_LEVEL > 1) printf("\ntimeout!\n"); return (0); break; case -1: printf("Big socket error or something!\n"); return (0); break; default: result = read(sockfd, buffer + len - 1, sizeof(buffer) + len - 1); len += result; buffer[len] = '\0'; break; } timeout.tv_sec = TIMEOUT_SEC; } while (result > 0 && strstr(buffer, stopstr) == NULL); if (OUTPUT_LEVEL > 8) printf("%s\n\n", buffer); return(1);}int ReadPASVPort(char* buffer)/*************************************** ReadPASVPort(char*)**** PRE: Assigned(buffer)** POST: Returns the first specified valid passive port in (buffer)*************************************/{ char *rbuffer = strstr(buffer, "Passive Mode ("); char lhost[6][4]; int i = 0, j = 0, k = 0; /* If Passive Mode was not found in the buffer, we have to assume the ftp server doesn't use PASV mode, therefore it fails NOTE: Server could aso be busy! */ if (rbuffer == NULL) { if (OUTPUT_LEVEL > 0) printf("PASV mode failed"); return(0); } else { for (i = 14; (unsigned)i < strlen(rbuffer) && rbuffer[i] != ')'; i++) if (rbuffer[i] == ',') { lhost[j][k] = '\0'; j++; k = 0; } else lhost[j][k++] = rbuffer[i]; return (atoi(lhost[4])*256 + atoi(lhost[5])); }}void GetFileListing (URLp URL){}bool ReadFTPListing (URLp URL)/*************************************** bool ReadFTPListing**** PRE: URL has been Parse()'d and Connect()'ed** POST: Sets URL->sockfd up for reading and determines the files size.*************************************/{ int i = 0, j = 0, k = 0, listfd = 0, datafd = 0, noretry = 0; unsigned int tempport = 0; int whitespace = 0; char *buffer; struct sockaddr_in datastream, liststream; URL->size = malloc(15); NOSIZE = 0; buffer = malloc(64000); /* Reads from the FTP socket until 200 (ok) is reached */ i = ReadSock(URL->sockfd, buffer, "\n200"); /* If a 501 is found, then the FTP site DOESN'T support resuming */ if (strstr(buffer, "\n501")) noretry = 1; listfd = socket(AF_INET, SOCK_STREAM, 0); tempport = ReadPASVPort(buffer); /* If we can't find a valid port to connect to, or can't open a socket to read the file listing, then an error occurs */ if (tempport == 0 || listfd == -1 || !i) { URL->retry = 1; /* Server returns 530 if busy */ if (strstr(buffer, "\n530") != NULL || strstr(buffer, "\n421") != NULL) if (OUTPUT_LEVEL > 0) printf(" because server is busy"); else URL->retry = 0; write(URL->sockfd, "\r\nQUIT\r\n", 8); close(URL->sockfd); close(listfd); if (OUTPUT_LEVEL > 0) printf("!\n"); if (OUTPUT_LEVEL > 0 && listfd == -1) printf("Error opening socket to FTP server for LIST!\n\n"); return(0); } liststream.sin_family = AF_INET; liststream.sin_port = htons(tempport); memcpy(&liststream.sin_addr, URL->host->h_addr, URL->host->h_length); if (OUTPUT_LEVEL > 0) printf ("[ CONNECTING TO PORT %d FOR FILE LISTING ]\n\n", tempport); /* Attempts to connect to socket for list of files */ if (connect(listfd, (struct sockaddr *)&liststream, sizeof(liststream)) == -1) { if (OUTPUT_LEVEL > 0) printf("Error connecting to FTP socket for LIST!\n"); write(URL->sockfd, "\r\nQUIT\r\n", 8); close(listfd); return(0); } /* Reads the socket for the file listing */ if(!ReadSock(listfd, buffer, "\r\n\r\n")) { URL->retry = 1; write(URL->sockfd, "\r\nQUIT\r\n", 8); close(listfd); return(0); } close(listfd); if (strlen(buffer) < 7 || strstr(buffer, "No such file or directory") != NULL) /* file not found */ { if (OUTPUT_LEVEL > 0) printf("Error: No file or files found!\n"); write(URL->sockfd, "\r\nQUIT\r\n", 8); close(listfd); URL->retry = 0; return(0); } if (buffer[0] != '-' && buffer[0] != 'd' && buffer[0] != 'l') buffer = strchr(buffer, '\n') + 1; if (((URL->filename == NULL || strstr(buffer, "\nd") || buffer[0] == 'd') && URL->recurse >= 0) || buffer[0] == 'l') { RecurseFTP (URL->name, buffer, URL->recurse); URL->done = 1; URL->retry = 0; sleep(3); return (0); } else if ((strstr(buffer, "\nd") != NULL || buffer[0] == 'd') && URL->recurse < 0) { if (OUTPUT_LEVEL > 0) printf("Directory hit... Ignoring!\n"); write(URL->sockfd, "\r\nQUIT\r\n", 8); close(listfd); URL->retry = 0; return(0); } /* queues the variable 'j' to the start of the filesize */ /* Sample: "-rwx-wx--x 1 root wheel 1024 /etc/passwd" */ while ((unsigned)j < strlen(buffer) && whitespace < 4) { if (buffer[j] == ' ' && buffer[j + 1] != ' ') whitespace ++; j++; } k = j; /* Calculates the size of the string being read in */ for (i = 0; (unsigned)j < strlen(buffer); j++) if (buffer[j] == ' ' || (buffer[j] > ('0' - 1) && buffer[j] < ('9' + 1))) i++; else j = strlen(buffer); /* Allocates space for the string */ URL->total = malloc(i + 1); j = k; k = 0; /* reads the first set of numbers it finds into the string URL->total */ for (i = 0; (unsigned)j < strlen(buffer); j++) if (buffer[j] == ' ' || (buffer[j] > ('0' - 1) && buffer[j] < ('9' + 1))) { URL->total[i++] = buffer[j]; if (buffer[j] != ' ') k = 1; } else j = strlen(buffer); URL->total[j - 4] = '\0'; URL->ltotal = atol(URL->total); if (OUTPUT_LEVEL > 1) { printf("# File: %s\n",URL->filename); if (!isdigit(URL->total[0])) printf("# File size is unknown!\n"); else printf("# File size: %ld kbytes (%ld bytes)\n", (long int)((URL->ltotal)/1024+.5), URL->ltotal); } usleep(FTP_WAIT_TIME); if (!noretry) write(URL->sockfd, "REST 0\r\n", 8); usleep(FTP_WAIT_TIME); write(URL->sockfd, "PASV\r\n", 6); usleep(FTP_WAIT_TIME); write(URL->sockfd, "NOOP\r\n", 6); /* Note, it looks for a 200, which NOOP returns */ if(!ReadSock(URL->sockfd, buffer, "\n200")) { URL->retry = 1; write(URL->sockfd, "\r\nQUIT\r\n", 8); close(listfd); return(0); } /* If a 350 is returned, then you cannot resume the file! */ if (strstr(buffer, "\n350") == NULL) URL->retry = 0; tempport = ReadPASVPort(buffer); if (!tempport) { URL->retry = 1; printf(" for file retrieval!\n"); write(URL->sockfd, "\r\nQUIT\r\n", 8); close(URL->sockfd); return (0); } /* Opens up the file for appending, seeks to the end of the file and determines teh files size from its current location */ if (strchr(URL->filename, ' ') != NULL) for (i = 0; i < strlen(URL->filename); i++) if (URL->filename[i] == ' ') URL->filename[i] = '_'; URL->fp = fopen (URL->filename, "a+b"); if (URL->fp == NULL) { printf("Error opening file!\n"); exit(69); } fseek (URL->fp,0,SEEK_END); URL->lsize = ftell(URL->fp); /* If the size is of the file (according to the FTP server) is 0 bytes, or it doesn't return the file size, the file is set to 2 gigs (doesn't effect transfer) and the NOSIZE flag is set */ if (k == 0) { URL->ltotal = 2000000000; NOSIZE = 1; } /* If the size of the file is greater than or equal to the size the ftp server reports, then the file is already finished! If URL->fp is NULL, then an error has occured when opening the file */ if ((URL->lsize >= URL->ltotal && URL->ltotal != 0) || URL->fp == NULL) { if (OUTPUT_LEVEL > 0) printf("Error... It seems this file has already been downloaded OR it's " "currently in use!\n"); write(URL->sockfd, "\r\nQUIT\r\n", 8); close(datafd); URL->retry = 0; return(0); } /* If the size of the file is smaller then the set ROLLBACK size, then the file size is reset to 0, otherwise it rolls the file size back ROLLBACK bytes */ if (URL->lsize < ROLLBACK || !URL->retry) URL->lsize = 0; else URL->lsize -= ROLLBACK; sprintf(URL->size, "%ld", URL->lsize); if (OUTPUT_LEVEL > 1) printf("# Found %ld kbytes : resuming from byte %ld.\n\n", URL->lsize/1024, URL->lsize); if (OUTPUT_LEVEL > 0) printf ("[ REQUESTING FILE TRANSFER ]\n"); /* Tells the FTP server that you want to resume a file at URL->size bytes */ usleep(FTP_WAIT_TIME); write(URL->sockfd, "TYPE I\r\n", 8); usleep(FTP_WAIT_TIME); if (!noretry) { write(URL->sockfd, "REST ", 5); write(URL->sockfd, URL->size, strlen(URL->size)); write(URL->sockfd, "\r\n", 2); } usleep(FTP_WAIT_TIME); write(URL->sockfd, "RETR ", 5); usleep(FTP_WAIT_TIME); write(URL->sockfd, URL->file, strlen(URL->file)); usleep(FTP_WAIT_TIME); write(URL->sockfd, "\r\n", 2); usleep(FTP_WAIT_TIME); /* Sets the dldots equal to the amount that is already downloaded */ dldots = URL->lsize / ROLLBACK; datafd = socket(AF_INET, SOCK_STREAM, 0); if (datafd == -1) { if (OUTPUT_LEVEL > 0) printf("Error opening socket to FTP server for RETR!\n"); write(URL->sockfd, "\r\nABOR\r\nQUIT\r\n", 14); close(datafd); close(URL->sockfd); URL->retry = 1; return(0); } datastream.sin_family = AF_INET; datastream.sin_port = htons(tempport); memcpy(&datastream.sin_addr, URL->host->h_addr, URL->host->h_length); if (connect(datafd, (struct sockaddr *)&datastream, sizeof(datastream)) == -1) { if (OUTPUT_LEVEL > 1) printf("Error connecting to FTP socket for RETR!\n"); write(URL->sockfd, "\r\nABOR\r\nQUIT\r\n", 14); close(datafd); URL->retry = 1; return(0); } if(!ReadSock(URL->sockfd, buffer, "\n150")) { URL->retry = 1; write(URL->sockfd, "\r\nQUIT\r\n", 8); close(listfd); return(0); } write(URL->sockfd, "\r\nQUIT\r\n", 8); listfd = URL->sockfd; URL->sockfd = datafd; close (listfd); URL->lleft = URL->ltotal - URL->lsize; if (OUTPUT_LEVEL > 0) { printf ("[ REQUEST FOR FILE %s SUCCESSFUL! ]\n", URL->filename); printf ("[ CONNECTION ESTABLISHED, TRANSFERRING FILE ]\n\n\n"); } if (OUTPUT_LEVEL > 1 && STDOUT == 0) printf("[."); /* Shrinks the file size for the rollback */ ftruncate(fileno(URL->fp), URL->lsize); usleep(FTP_WAIT_TIME); return (1);}void RecurseFTP (char* URLname, char *buff, int rec){ char *tname; char *tfilename; char *buffer; char tempch; int i, j, ahead; char type; buffer = buff; if (strchr (buffer, '\r') == NULL) tempch = '\n'; else tempch = '\r'; while (buffer != NULL && buffer[0] != '\n' && strlen (buffer) > 7) { tname = malloc (4096); tfilename = malloc (1024); tname = strcpy(tname, URLname); type = buffer[0]; i = 1; j = 0; while ((unsigned)i < strlen(buffer) && j < 8) { if (buffer[i] == ' ' && buffer[i + 1] != ' ') j ++; i++; }/* for (i = 1; i < strlen(buffer) && buffer[i] != tempch; i++); for (; i > 0 && buffer[i - 1] != ' '; i--);*/ j = 0; while (buffer != NULL && buffer[i] != tempch) { tfilename[j] = buffer[i]; j++; i++; } tfilename[j] = '\0'; ahead = 0; if (type == 'l') { if (strstr(tfilename, " -> ") != NULL) ahead = strlen(tfilename) - strlen(strstr(tfilename, " -> ")) + 4; *strrchr(tname, '/') = '\0'; } tfilename += ahead; if (tname[strlen(tname) - 1] != '/') strcat(tname, "/"); strcat(tname, tfilename); if (buffer != NULL) { if (tfilename[strlen(tfilename) - 1] != '.' && (strstr(tfilename, "/.") == NULL || strlen(strstr(tfilename, "/.")) > 3)) switch (type) { case '-': if (OUTPUT_LEVEL > 0) printf("+Added file: %s\n", tname); InsertURL(tname, 0); break; case 'l': if (rec >= 0) { if (OUTPUT_LEVEL > 0) printf("+Added"); InsertURL(tname, rec - 1); } else if (OUTPUT_LEVEL > 0) printf("-IGNORED"); if (OUTPUT_LEVEL > 0) printf(" link: %s\n", tname); break; case 'd': if (rec > 0) { if (OUTPUT_LEVEL > 0) printf("+Added"); InsertURL(strcat(tname, "/"), rec - 1); } else if (OUTPUT_LEVEL > 0) printf("-IGNORED"); if (OUTPUT_LEVEL > 0) printf(" directory: %s\n", tname); break; default: if (OUTPUT_LEVEL > 0) printf("Unrecognized file type for: %s\n", tname); break; } buffer = strchr(buffer, '\n'); if (buffer != NULL) buffer++; } tfilename -= ahead; free (tfilename); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -