int ftp_retr(int fd, off_t offset) { char buf[MAX_LINE]; off_t file_sz; int data_sock, ret; if (ftp_size(ctrl_sock, file, &file_sz) != P_OK) { warnx("failed to get size of file %s", file); return -1; } if ((data_sock = ftp_pasv(ctrl_sock)) == -1) return -1; if (ftp_command(ctrl_sock, "RETR %s\r\n", file) != P_PRE) return -1; ret = retr_file(data_sock, fd, file_sz, offset); if (ftp_readline(ctrl_sock, buf, sizeof buf) != P_OK) { warnx("error retrieving file %s", file); return -1; } ftp_command(ctrl_sock, "QUIT\r\n"); return ret; }
int ftp_get(off_t offset, struct url *url) { char *dir; int ret; log_info("Using binary mode to transfer files.\n"); if (ftp_command(ctrl_sock, "TYPE I\r\n") != P_OK) { fprintf(stderr, "Failed to set mode to binary\n"); return -1; } if (url->path) file = strrchr(url->path, '/'); if (file == NULL || file == url->path) dir = NULL; else { dir = url->path; *file++ = '\0'; } if (dir && ftp_command(ctrl_sock, "CWD %s\r\n", dir) != P_OK) return -1; ret = 200; if (offset && ftp_command(ctrl_sock, "REST %lld\r\n", offset) == P_OK) ret = 206; return ret; }
int ftp_move(FTP_CON * con, const char *oldname, const char *newname) /* move/rename file */ { int status; status = ftp_command(con, "RNFR %s", oldname, 200, 350, EOF); if (status < 0) return ftp_command(con, "RNTO %s", newname, 200, 250, EOF); else return status; }
static time_t ftp_modtime(FTP ftp, char *path) { int status; Str tmp; char *p; struct tm tm; time_t t, lt, gt; tmp = ftp_command(ftp, "MDTM", path, &status); if (status != 213) return -1; for (p = tmp->ptr + 4; *p && *p == ' '; p++) ; memset(&tm, 0, sizeof(struct tm)); if (sscanf(p, "%04d%02d%02d%02d%02d%02d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) < 6) return -1; tm.tm_year -= 1900; tm.tm_mon--; t = mktime(&tm); lt = mktime(localtime(&t)); gt = mktime(gmtime(&t)); return t + (lt - gt); }
int ftp_connect(struct url *url) { char buf[MAX_LINE]; int r = -1; if (url->port[0] == '\0') (void)strlcpy(url->port, "21", sizeof url->port); if ((ctrl_sock = tcp_connect(url->host, url->port)) == -1) return -1; if (proxy && proxy_connect(ctrl_sock, url) == -1) goto error; /* greeting */ if ((r = ftp_readline(ctrl_sock, buf, sizeof buf)) != P_OK) goto error; log_info("Connected to %s\n", url->host); if ((r = ftp_auth(NULL, NULL)) != P_OK) goto error; return ctrl_sock; error: if (r == -1 && errno != EINTR) warnx("Can't connect or login to host `%s'", url->host); ftp_command(ctrl_sock, "QUIT\r\n"); if (close(ctrl_sock) == -1 && errno != EINTR) err(1, "ftp_connect: close"); return -1; }
int conn_setup( conn_t *conn ) { if( conn->ftp->fd <= 0 && conn->http->fd <= 0 ) if( !conn_init( conn ) ) return( 0 ); if( conn->proto == PROTO_FTP && !conn->proxy ) { if( !ftp_data( conn->ftp ) ) /* Set up data connnection */ return( 0 ); conn->fd = conn->ftp->data_fd; if( conn->currentbyte ) { ftp_command( conn->ftp, "REST %lld", conn->currentbyte ); if( ftp_wait( conn->ftp ) / 100 != 3 && conn->ftp->status / 100 != 2 ) return( 0 ); } } else { char s[MAX_STRING]; int i; snprintf( s, MAX_STRING, "%s%s", conn->dir, conn->file ); conn->http->firstbyte = conn->currentbyte; conn->http->lastbyte = conn->lastbyte; http_get( conn->http, s ); http_addheader( conn->http, "User-Agent: %s", conn->conf->user_agent ); for( i = 0; i < conn->conf->add_header_count; i++) http_addheader( conn->http, "%s", conn->conf->add_header[i] ); } return( 1 ); }
int conn_setup( conn_t *conn ) { if( conn->ftp->fd <= 0 && conn->http->fd <= 0 ) if( !conn_init( conn ) ) return( 0 ); if( conn->proto == PROTO_FTP && !conn->proxy ) { if( !ftp_data( conn->ftp ) ) /* Set up data connnection */ return( 0 ); conn->fd = conn->ftp->data_fd; if( conn->currentbyte ) { ftp_command( conn->ftp, "REST %i", conn->currentbyte ); if( ftp_wait( conn->ftp ) / 100 != 3 && conn->ftp->status / 100 != 2 ) return( 0 ); } } else { char s[MAX_STRING]; snprintf( s, MAX_STRING, "%s%s", conn->dir, conn->file ); conn->http->firstbyte = conn->currentbyte; conn->http->lastbyte = conn->lastbyte; http_get( conn->http, s ); } return( 1 ); }
static void closeFTPdata(FILE * f) { int status; if (f) { fclose(f); if (f == current_ftp.data) current_ftp.data = NULL; } ftp_command(¤t_ftp, NULL, NULL, &status); /* status == 226 */ }
int ftp_connect( ftp_t *conn, char *host, int port, char *user, char *pass ) { #if WIN32 conn->data_fd = INVALID_SOCKET; #else conn->data_fd = -1; #endif conn->message = malloc( MAX_STRING ); if( ( conn->fd = tcp_connect( host, port, conn->local_if ) ) == -1 ) { sprintf( conn->message, _("Unable to connect to server %s:%i\n"), host, port ); return( 0 ); } if( ftp_wait( conn ) / 100 != 2 ) return( 0 ); ftp_command( conn, "USER %s", user ); if( ftp_wait( conn ) / 100 != 2 ) { if( conn->status / 100 == 3 ) { ftp_command( conn, "PASS %s", pass ); if( ftp_wait( conn ) / 100 != 2 ) return( 0 ); } else { return( 0 ); } } /* ASCII mode sucks. Just use Binary.. */ ftp_command( conn, "TYPE I" ); if( ftp_wait( conn ) / 100 != 2 ) return( 0 ); return( 1 ); }
/* Change current working directory */ int ftp_cwd( ftp_t *conn, char *cwd ) { /* Necessary at all? */ if( strncmp( conn->cwd, cwd, MAX_STRING ) == 0 ) return( 1 ); ftp_command( conn, "CWD %s", cwd ); if( ftp_wait( conn ) / 100 != 2 ) return( 0 ); strncpy( conn->cwd, cwd, MAX_STRING ); return( 1 ); }
static int ftp_auth(const char *user, const char *pass) { int code, ret; char hn[HOST_NAME_MAX+1]; char addr[LOGIN_NAME_MAX+HOST_NAME_MAX+3]; code = ftp_command(ctrl_sock, "USER %s\r\n", user ? user : "******"); if (code != P_OK && code != P_INTER) return code; if (pass == NULL) { if (gethostname(hn, sizeof hn) == -1) err(1, "ftp_auth: gethostname"); ret = snprintf(addr, sizeof addr, "%s@%s",getlogin(), hn); if (ret == -1 || ret > sizeof addr) errx(1, "addr too long"); } code = ftp_command(ctrl_sock, "PASS %s\r\n", pass ? pass : addr); return code; }
static int ftp_quit(FTP ftp) { /* * int status; * ftp_command(ftp, "QUIT", NULL, &status); * ftp_close(ftp); * if (status != 221) * return -1; */ ftp_command(ftp, "QUIT", NULL, NULL); ftp_close(ftp); return 0; }
int conn_setup(conn_t *conn) { #if WIN32 if (INVALID_SOCKET == conn->ftp->fd && INVALID_SOCKET == conn->http->fd) #else if (conn->ftp->fd <= 0 && conn->http->fd <= 0) #endif { if (!conn_init(conn)) { return 0; } } if (conn->proto == PROTO_FTP && !conn->proxy) { /* Set up data connnection */ if(!ftp_data(conn->ftp)) { return 0; } conn->fd = conn->ftp->data_fd; if (conn->currentbyte) { ftp_command(conn->ftp, "REST %lld", conn->currentbyte); if (ftp_wait(conn->ftp) / 100 != 3 && conn->ftp->status / 100 != 2) { return 0; } } } else { char s[MAX_STRING]; int i; snprintf(s, MAX_STRING, "%s%s", conn->dir, conn->file); conn->http->firstbyte = conn->currentbyte; conn->http->lastbyte = conn->lastbyte; http_get(conn->http, s); http_addheader(conn->http, "User-Agent: %s", conn->conf->user_agent); for (i = 0; i < conn->conf->add_header_count; i++) { http_addheader(conn->http, "%s", conn->conf->add_header[i]); } } return 1; }
int conn_exec( conn_t *conn ) { if( conn->proto == PROTO_FTP && !conn->proxy ) { if( !ftp_command( conn->ftp, "RETR %s", conn->file ) ) return( 0 ); return( ftp_wait( conn->ftp ) / 100 == 1 ); } else { if( !http_exec( conn->http ) ) return( 0 ); return( conn->http->status / 100 == 2 ); } }
/* Change current working directory */ int ftp_cwd( ftp_t *conn, char *cwd ) { /* Necessary at all? */ if( strncmp( conn->cwd, cwd, MAX_STRING ) == 0 ) return( 1 ); ftp_command( conn, "CWD %s", cwd ); if( ftp_wait( conn ) / 100 != 2 ) { fprintf( stderr, _("Can't change directory to %s\n"), cwd ); return( 0 ); } strncpy( conn->cwd, cwd, MAX_STRING ); return( 1 ); }
/* Open a data connection. Only Passive mode supported yet, easier.. */ int ftp_data( ftp_t *conn ) { int i, info[6]; char host[MAX_STRING]; /* Already done? */ if( conn->data_fd > 0 ) return( 0 ); /* if( conn->ftp_mode == FTP_PASSIVE ) { */ ftp_command( conn, "PASV" ); if( ftp_wait( conn ) / 100 != 2 ) return( 0 ); *host = 0; for( i = 0; conn->message[i]; i ++ ) { if( sscanf( &conn->message[i], "%i,%i,%i,%i,%i,%i", &info[0], &info[1], &info[2], &info[3], &info[4], &info[5] ) == 6 ) { sprintf( host, "%i.%i.%i.%i", info[0], info[1], info[2], info[3] ); break; } } if( !*host ) { sprintf( conn->message, _("Error opening passive data connection.\n") ); return( 0 ); } if( ( conn->data_fd = tcp_connect( host, info[4] * 256 + info[5], conn->local_if ) ) == -1 ) { sprintf( conn->message, _("Error opening passive data connection.\n") ); return( 0 ); } return( 1 ); /* } else { sprintf( conn->message, _("Active FTP not implemented yet.\n" ) ); return( 0 ); } */ }
/* Get file size. Should work with all reasonable servers now */ long long int ftp_size( ftp_t *conn, char *file, int maxredir ) { long long int i, j, size = MAX_STRING; char *reply, *s, fn[MAX_STRING]; /* Try the SIZE command first, if possible */ if( !strchr( file, '*' ) && !strchr( file, '?' ) ) { ftp_command( conn, "SIZE %s", file ); if( ftp_wait( conn ) / 100 == 2 ) { sscanf( conn->message, "%*i %lld", &i ); return( i ); } else if( conn->status / 10 != 50 ) { sprintf( conn->message, _("File not found.\n") ); return( -1 ); } } if( maxredir == 0 ) { sprintf( conn->message, _("Too many redirects.\n") ); return( -1 ); } if( !ftp_data( conn ) ) return( -1 ); ftp_command( conn, "LIST %s", file ); if( ftp_wait( conn ) / 100 != 1 ) return( -1 ); /* Read reply from the server. */ reply = malloc( size ); memset( reply, 0, size ); *reply = '\n'; i = 1; while( ( j = read( conn->data_fd, reply + i, size - i - 3 ) ) > 0 ) { i += j; reply[i] = 0; if( size - i <= 10 ) { size *= 2; reply = realloc( reply, size ); memset( reply + size / 2, 0, size / 2 ); } } close( conn->data_fd ); conn->data_fd = -1; if( ftp_wait( conn ) / 100 != 2 ) { free( reply ); return( -1 ); } #ifdef DEBUG fprintf(stderr, "%s", reply); #endif /* Count the number of probably legal matches: Files&Links only */ j = 0; for( i = 1; reply[i] && reply[i+1]; i ++ ) if( reply[i] == '-' || reply[i] == 'l' ) j ++; else while( reply[i] != '\n' && reply[i] ) i ++; /* No match or more than one match */ if( j != 1 ) { if( j == 0 ) sprintf( conn->message, _("File not found.\n") ); else sprintf( conn->message, _("Multiple matches for this URL.\n") ); free( reply ); return( -1 ); } /* Symlink handling */ if( ( s = strstr( reply, "\nl" ) ) != NULL ) { /* Get the real filename */ sscanf( s, "%*s %*i %*s %*s %*i %*s %*i %*s %100s", fn ); strcpy( file, fn ); /* Get size of the file linked to */ strncpy( fn, strstr( s, "->" ) + 3, MAX_STRING ); free( reply ); if( ( reply = strchr( fn, '\r' ) ) != NULL ) *reply = 0; if( ( reply = strchr( fn, '\n' ) ) != NULL ) *reply = 0; return( ftp_size( conn, fn, maxredir - 1 ) ); } /* Normal file, so read the size! And read filename because of possible wildcards. */ else { s = strstr( reply, "\n-" ); i = sscanf( s, "%*s %*i %*s %*s %lld %*s %*i %*s %100s", &size, fn ); if( i < 2 ) { i = sscanf( s, "%*s %*i %lld %*i %*s %*i %*i %100s", &size, fn ); if( i < 2 ) { return( -2 ); } } strcpy( file, fn ); free( reply ); return( size ); } }
/* Get file size and other information */ int conn_info( conn_t *conn ) { /* It's all a bit messed up.. But it works. */ if( conn->proto == PROTO_FTP && !conn->proxy ) { ftp_command( conn->ftp, "REST %lld", 1 ); if( ftp_wait( conn->ftp ) / 100 == 3 || conn->ftp->status / 100 == 2 ) { conn->supported = 1; ftp_command( conn->ftp, "REST %lld", 0 ); ftp_wait( conn->ftp ); } else { conn->supported = 0; } if( !ftp_cwd( conn->ftp, conn->dir ) ) return( 0 ); conn->size = ftp_size( conn->ftp, conn->file, MAX_REDIR ); if( conn->size < 0 ) conn->supported = 0; if( conn->size == -1 ) return( 0 ); else if( conn->size == -2 ) conn->size = INT_MAX; } else { char s[MAX_STRING], *t; long long int i = 0; do { conn->currentbyte = 1; if( !conn_setup( conn ) ) return( 0 ); conn_exec( conn ); conn_disconnect( conn ); /* Code 3xx == redirect */ if( conn->http->status / 100 != 3 ) break; if( ( t = http_header( conn->http, "location:" ) ) == NULL ) return( 0 ); sscanf( t, "%1023s", s ); // Warning: truncating to MAX_STRING if( strstr( s, "://" ) == NULL) { sprintf( conn->http->headers, "%s%s", conn_url( conn ), s ); strncpy( s, conn->http->headers, MAX_STRING ); } else if( s[0] == '/' ) { sprintf( conn->http->headers, "http://%s:%i%s", conn->host, conn->port, s ); strncpy( s, conn->http->headers, MAX_STRING ); } conn_set( conn, s ); i ++; } while( conn->http->status / 100 == 3 && i < MAX_REDIR ); if( i == MAX_REDIR ) { sprintf( conn->message, _("Too many redirects.\n") ); return( 0 ); } conn->size = http_size( conn->http ); if( conn->http->status == 206 && conn->size >= 0 ) { conn->supported = 1; conn->size ++; } else if( conn->http->status == 200 || conn->http->status == 206 ) { conn->supported = 0; conn->size = INT_MAX; } else { t = strchr( conn->message, '\n' ); if( t == NULL ) sprintf( conn->message, _("Unknown HTTP error.\n") ); else *t = 0; return( 0 ); } } return( 1 ); }
int ftp_open_connection(const char * host, const char * name, const char * password, const char * proxy) { int sock; struct in_addr serverAddress; union { struct sockaddr_in in; struct sockaddr sa; } destPort; int rc; int port = 21; std::string proxyname; if (!strcmp(name, "")) { name = "anonymous"; password = "******"; } if (strcmp(proxy, "")) { proxyname.append(name).append("@").append(host); name = proxyname.c_str(); host = proxy; } if ((rc = get_host_address(host, &serverAddress))) return rc; sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (sock < 0) { return FTPERR_FAILED_CONNECT; } destPort.in.sin_family = AF_INET; destPort.in.sin_port = htons(port); destPort.in.sin_addr = serverAddress; if (connect(sock, &destPort.sa, sizeof(destPort.in))) { close(sock); return FTPERR_FAILED_CONNECT; } /* ftpCheckResponse() assumes the socket is nonblocking */ if (fcntl(sock, F_SETFL, O_NONBLOCK)) { close(sock); return FTPERR_FAILED_CONNECT; } if ((rc = ftp_check_response(sock, NULL))) { return rc; } if ((rc = ftp_command(sock, "USER", name))) { close(sock); return rc; } if ((rc = ftp_command(sock, "PASS", password))) { close(sock); return rc; } if ((rc = ftp_command(sock, "TYPE", "I"))) { close(sock); return rc; } return sock; }
InputStream openFTPStream(ParsedURL *pu, URLFile *uf) { Str tmp; int status; char *user = NULL; char *pass = NULL; Str uname = NULL; Str pwd = NULL; int add_auth_cookie_flag = FALSE; char *realpathname = NULL; if (!pu->host) return NULL; if (pu->user == NULL && pu->pass == NULL) { if (find_auth_user_passwd(pu, NULL, &uname, &pwd, 0)) { if (uname) user = uname->ptr; if (pwd) pass = pwd->ptr; } } if (user) /* do nothing */ ; else if (pu->user) user = pu->user; else user = "******"; if (current_ftp.host) { if (!strcmp(current_ftp.host, pu->host) && current_ftp.port == pu->port && !strcmp(current_ftp.user, user)) { ftp_command(¤t_ftp, "NOOP", NULL, &status); if (status != 200) ftp_close(¤t_ftp); else goto ftp_read; } else ftp_quit(¤t_ftp); } if (pass) /* do nothing */ ; else if (pu->pass) pass = pu->pass; else if (pu->user) { pwd = NULL; find_auth_user_passwd(pu, NULL, &uname, &pwd, 0); if (pwd == NULL) { if (fmInitialized) { term_raw(); pwd = Strnew_charp(inputLine("Password: "******"Password: "******"Password: "******"anonymous"); #else tmp = Strnew_charp("anonymous"); #endif /* __MINGW32_VERSION */ Strcat_char(tmp, '@'); pass = tmp->ptr; } if (!current_ftp.host) { current_ftp.host = allocStr(pu->host, -1); current_ftp.port = pu->port; current_ftp.user = allocStr(user, -1); current_ftp.pass = allocStr(pass, -1); if (!ftp_login(¤t_ftp)) return NULL; } if (add_auth_cookie_flag) add_auth_user_passwd(pu, NULL, uname, pwd, 0); ftp_read: ftp_command(¤t_ftp, "TYPE", "I", &status); if (ftp_pasv(¤t_ftp) < 0) { ftp_quit(¤t_ftp); return NULL; } if (pu->file == NULL || *pu->file == '\0' || pu->file[strlen(pu->file) - 1] == '/') goto ftp_dir; realpathname = file_unquote(pu->file); if (*realpathname == '/' && *(realpathname + 1) == '~') realpathname++; /* Get file */ uf->modtime = ftp_modtime(¤t_ftp, realpathname); ftp_command(¤t_ftp, "RETR", realpathname, &status); if (status == 125 || status == 150) return newFileStream(current_ftp.data, (void (*)())closeFTPdata); ftp_dir: pu->scheme = SCM_FTPDIR; return NULL; }
static int ftp_pasv(FTP ftp) { int status; int n1, n2, n3, n4, p1, p2; int data; char *p; Str tmp; int family; #ifdef INET6 struct sockaddr_storage sockaddr; int port; socklen_t sockaddrlen; unsigned char d1, d2, d3, d4; char abuf[INET6_ADDRSTRLEN]; #endif #ifdef INET6 sockaddrlen = sizeof(sockaddr); if (getpeername(fileno(ftp->wf), (struct sockaddr *)&sockaddr, &sockaddrlen) < 0) return -1; #ifdef HAVE_OLD_SS_FAMILY family = sockaddr.__ss_family; #else family = sockaddr.ss_family; #endif #else family = AF_INET; #endif switch (family) { #ifdef INET6 case AF_INET6: tmp = ftp_command(ftp, "EPSV", NULL, &status); if (status != 229) return -1; for (p = tmp->ptr + 4; *p && *p != '('; p++) ; if (*p == '\0') return -1; if (sscanf(++p, "%c%c%c%d%c", &d1, &d2, &d3, &port, &d4) != 5 || d1 != d2 || d1 != d3 || d1 != d4) return -1; if (getnameinfo((struct sockaddr *)&sockaddr, sockaddrlen, abuf, sizeof(abuf), NULL, 0, NI_NUMERICHOST) != 0) return -1; data = openSocket(abuf, "", port); break; #endif case AF_INET: tmp = ftp_command(ftp, "PASV", NULL, &status); if (status != 227) return -1; for (p = tmp->ptr + 4; *p && !IS_DIGIT(*p); p++) ; if (*p == '\0') return -1; sscanf(p, "%d,%d,%d,%d,%d,%d", &n1, &n2, &n3, &n4, &p1, &p2); tmp = Sprintf("%d.%d.%d.%d", n1, n2, n3, n4); data = openSocket(tmp->ptr, "", p1 * 256 + p2); break; default: return -1; } if (data < 0) return -1; ftp->data = fdopen(data, "rb"); return 0; }
static int ftp_login(FTP ftp) { int sock, status; sock = openSocket(ftp->host, "ftp", 21); if (sock < 0) goto open_err; if (ftppass_hostnamegen && !strcmp(ftp->user, "anonymous")) { size_t n = strlen(ftp->pass); if (n > 0 && ftp->pass[n - 1] == '@') { #ifdef INET6 struct sockaddr_storage sockname; #else struct sockaddr_in sockname; #endif socklen_t socknamelen = sizeof(sockname); if (!getsockname(sock, (struct sockaddr *)&sockname, &socknamelen)) { struct hostent *sockent; Str tmp = Strnew_charp(ftp->pass); #ifdef INET6 char hostbuf[NI_MAXHOST]; if (getnameinfo((struct sockaddr *)&sockname, socknamelen, hostbuf, sizeof hostbuf, NULL, 0, NI_NAMEREQD) == 0) Strcat_charp(tmp, hostbuf); else if (getnameinfo((struct sockaddr *)&sockname, socknamelen, hostbuf, sizeof hostbuf, NULL, 0, NI_NUMERICHOST) == 0) Strcat_m_charp(tmp, "[", hostbuf, "]", NULL); else Strcat_charp(tmp, "unknown"); #else if ((sockent = gethostbyaddr((char *)&sockname.sin_addr, sizeof(sockname.sin_addr), sockname.sin_family))) Strcat_charp(tmp, sockent->h_name); else Strcat_m_charp(tmp, "[", inet_ntoa(sockname.sin_addr), "]", NULL); #endif ftp->pass = tmp->ptr; } } } ftp->rf = newInputStream(sock); ftp->wf = fdopen(dup(sock), "wb"); if (!ftp->rf || !ftp->wf) goto open_err; IStype(ftp->rf) |= IST_UNCLOSE; ftp_command(ftp, NULL, NULL, &status); if (status != 220) goto open_err; if (fmInitialized) { message(Sprintf("Sending FTP username (%s) to remote server.", ftp->user)->ptr, 0, 0); refresh(); } ftp_command(ftp, "USER", ftp->user, &status); /* * Some ftp daemons(e.g. publicfile) return code 230 for user command. */ if (status == 230) goto succeed; if (status != 331) goto open_err; if (fmInitialized) { message("Sending FTP password to remote server.", 0, 0); refresh(); } ftp_command(ftp, "PASS", ftp->pass, &status); if (status != 230) goto open_err; succeed: return TRUE; open_err: ftp_close(ftp); return FALSE; }
int ftp_get_filesize(int sock, const char * remotename) { int size = 0; char buf[2000]; char file[500]; char * ptr; int fd, rc, tot; int i; strcpy(buf, remotename); ptr = strrchr(buf, '/'); if (!*ptr) return -1; *ptr = '\0'; strcpy(file, ptr+1); if ((rc = ftp_command(sock, "CWD", buf))) { return -1; } fd = ftp_data_command(sock, "LIST", file); if (fd <= 0) { close(sock); return -1; } ptr = buf; while ((tot = read(fd, ptr, sizeof(buf) - (ptr - buf) - 1)) != 0) ptr += tot; *ptr = '\0'; close(fd); if (!(ptr = strstr(buf, file))) { log_message("FTP/get_filesize: Bad mood, directory does not contain searched file (%s)", file); if (ftp_end_data_command(sock)) close(sock); return -1; } for (i=0; i<4; i++) { while (*ptr && *ptr != ' ') ptr--; while (*ptr && *ptr == ' ') ptr--; } while (*ptr && *ptr != ' ') ptr--; if (ptr) size = charstar_to_int(ptr+1); else size = 0; if (ftp_end_data_command(sock)) { close(sock); return -1; } return size; }
int ftp_data(FTP_CON * con, const char *command, const char *file) /* open data socket */ { struct sockaddr_in data, from; struct hostent *host; char host_name[256]; int listen_socket, data_socket; unsigned int len = sizeof(data), fromlen = sizeof(from); int one = 1, status; char *a, *b; memset(&data, 0, sizeof(data)); memset(&from, 0, sizeof(from)); if (gethostname(host_name, sizeof(host_name)) == -1) return FTP_NET_ERROR; if ((host = (struct hostent *) gethostbyname(host_name)) == 0) return FTP_NET_ERROR; if ((listen_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) return FTP_NET_ERROR; if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) < 0) { closesocket(listen_socket); return FTP_NET_ERROR; } data.sin_family = AF_INET; data.sin_port = htons(0); data.sin_addr.s_addr = *(unsigned long *) *(host->h_addr_list); if (bind(listen_socket, (struct sockaddr *) &data, sizeof(data)) == -1) { closesocket(listen_socket); return FTP_NET_ERROR; } #ifdef OS_WINNT if (getsockname(listen_socket, (struct sockaddr *) &data, (int *)&len) < 0) { #else if (getsockname(listen_socket, (struct sockaddr *) &data, &len) < 0) { #endif closesocket(listen_socket); return FTP_NET_ERROR; } if (listen(listen_socket, 1) != 0) { closesocket(listen_socket); return FTP_NET_ERROR; } a = (char *) &data.sin_addr; b = (char *) &data.sin_port; status = ftp_port(con, FTP_CUT(a[0]), FTP_CUT(a[1]), FTP_CUT(a[2]), FTP_CUT(a[3]), FTP_CUT(b[0]), FTP_CUT(b[1])); if (status != FTP_SUCCESS) return FTP_NET_ERROR; status = ftp_command(con, command, file, 200, 120, 150, 125, 250, EOF); if (status >= 0) return status; #ifdef OS_WINNT data_socket = accept(listen_socket, (struct sockaddr *) &from, (int *)&fromlen); #else data_socket = accept(listen_socket, (struct sockaddr *) &from, &fromlen); #endif if (data_socket == -1) { closesocket(listen_socket); return FTP_NET_ERROR; } closesocket(listen_socket); con->data = data_socket; return status; } /*------------------------------------------------------------------*/ int ftp_close(FTP_CON * con) /* close data connection */ { char str[256]; closesocket(con->data); return ftp_get_message(con, str); }
Str loadFTPDir0(ParsedURL *pu) #endif { Str FTPDIRtmp; Str tmp; int status; volatile int sv_type; char *realpathname, *fn, *q; char **flist; int i, nfile, nfile_max; MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL; #ifdef USE_M17N wc_ces doc_charset = DocumentCharset; *charset = WC_CES_US_ASCII; #endif if (current_ftp.data == NULL) return NULL; tmp = ftp_command(¤t_ftp, "SYST", NULL, &status); if (strstr(tmp->ptr, "UNIX") != NULL || !strncmp(tmp->ptr + 4, "Windows_NT", 10)) /* :-) */ sv_type = UNIXLIKE_SERVER; else sv_type = SERVER_NONE; if (pu->file == NULL || *pu->file == '\0') { if (sv_type == UNIXLIKE_SERVER) ftp_command(¤t_ftp, "LIST", NULL, &status); else ftp_command(¤t_ftp, "NLST", NULL, &status); pu->file = "/"; } else { realpathname = file_unquote(pu->file); if (*realpathname == '/' && *(realpathname + 1) == '~') realpathname++; if (sv_type == UNIXLIKE_SERVER) { ftp_command(¤t_ftp, "CWD", realpathname, &status); if (status == 250) ftp_command(¤t_ftp, "LIST", NULL, &status); } else ftp_command(¤t_ftp, "NLST", realpathname, &status); } if (status != 125 && status != 150) { fclose(current_ftp.data); current_ftp.data = NULL; return NULL; } tmp = parsedURL2Str(pu); if (Strlastchar(tmp) != '/') Strcat_char(tmp, '/'); fn = html_quote(tmp->ptr); tmp = convertLine(NULL, Strnew_charp(file_unquote(tmp->ptr)), RAW_MODE, charset, doc_charset); q = html_quote(tmp->ptr); FTPDIRtmp = Strnew_m_charp("<html>\n<head>\n<base href=\"", fn, "\">\n<title>", q, "</title>\n</head>\n<body>\n<h1>Index of ", q, "</h1>\n", NULL); if (SETJMP(AbortLoading) != 0) { if (sv_type == UNIXLIKE_SERVER) Strcat_charp(FTPDIRtmp, "</a></pre>\n"); else Strcat_charp(FTPDIRtmp, "</a></ul>\n"); Strcat_charp(FTPDIRtmp, "<p>Transfer Interrupted!\n"); goto ftp_end; } TRAP_ON; if (sv_type == UNIXLIKE_SERVER) Strcat_charp(FTPDIRtmp, "<pre>\n"); else Strcat_charp(FTPDIRtmp, "<ul>\n<li>"); Strcat_charp(FTPDIRtmp, "<a href=\"..\">[Upper Directory]</a>\n"); nfile_max = 100; flist = New_N(char *, nfile_max); nfile = 0; if (sv_type == UNIXLIKE_SERVER) { char *name, *link, *date, *size, *type_str; int ftype, max_len, len, j; max_len = 20; while (tmp = Strfgets(current_ftp.data), tmp->length > 0) { Strchop(tmp); if ((ftype = ex_ftpdir_name_size_date(tmp->ptr, &name, &link, &date, &size)) == FTPDIR_NONE) continue; if (!strcmp(".", name) || !strcmp("..", name)) continue; len = strlen(name); if (!len) continue; if (ftype == FTPDIR_DIR) { len++; type_str = "/"; } else if (ftype == FTPDIR_LINK) { len++; type_str = "@"; } else { type_str = " "; } if (max_len < len) max_len = len; flist[nfile++] = Sprintf("%s%s\n%s %5s%s", name, type_str, date, size, link)->ptr; if (nfile == nfile_max) { nfile_max *= 2; flist = New_Reuse(char *, flist, nfile_max); } }
/*------------------------------------------------------------------*/ INT mftp_open(char *destination, FTP_CON ** con) { INT status; short port = 0; char *token, host_name[HOST_NAME_LENGTH], user[256], pass[256], directory[256], file_name[256], file_mode[256]; /* destination should have the form: host, port, user, password, directory, run%05d.mid, file_mode, command, ... */ /* break destination in components */ token = strtok(destination, ","); if (token) strcpy(host_name, token); token = strtok(NULL, ","); if (token) port = atoi(token); token = strtok(NULL, ","); if (token) strcpy(user, token); token = strtok(NULL, ","); if (token) strcpy(pass, token); token = strtok(NULL, ","); if (token) strcpy(directory, token); token = strtok(NULL, ","); if (token) strcpy(file_name, token); token = strtok(NULL, ","); file_mode[0] = 0; if (token) strcpy(file_mode, token); status = ftp_login(con, host_name, port, user, pass, ""); if (status >= 0) return status; status = ftp_chdir(*con, directory); if (status >= 0) { /* directory does not exist -> create it */ ftp_mkdir(*con, directory); status = ftp_chdir(*con, directory); } if (status >= 0) return status; status = ftp_binary(*con); if (status >= 0) return status; if (file_mode[0]) { status = ftp_command(*con, "umask %s", file_mode, 200, 250, EOF); if (status >= 0) return status; } while (token) { token = strtok(NULL, ","); if (token) { status = ftp_command(*con, token, NULL, 200, 250, EOF); if (status >= 0) return status; } } if (ftp_open_write(*con, file_name) >= 0) return (*con)->err_no; return SS_SUCCESS; }