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 ); }
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 ); }
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 ); }