⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp.c

📁 prozgui是一款Linxu下著名的下载工具
💻 C
📖 第 1 页 / 共 2 页
字号:
  while (1)  {    switch (ret_code)    {    case 220:      /* IDEA: Lets add the proxy support here. */      if (!ftp_use_proxy(connection))      {	/* No proxy just direct connection. */	err = ftp_send_msg(connection, "USER %s\r\n", username);      } else      {	switch (connection->ftp_proxy->type)	{	case USERatSITE:	  err = ftp_send_msg(connection, "USER %s@%s:%d\r\n", username,			     connection->u.host, connection->u.port);	  break;	case USERatPROXYUSERatSITE:	  err = ftp_send_msg(connection, "USER %s@%s@%s:%d\r\n", username,			     connection->ftp_proxy->username,			     connection->u.host, connection->u.port);	  break;	case USERatSITE_PROXYUSER:	  err = ftp_send_msg(connection, "USER %s:%d@%s %s\r\n", username,			     connection->u.host, connection->u.port,			     connection->ftp_proxy->username);	  break;	case PROXYUSERatSITE:	  err = ftp_send_msg(connection, "USER %s@%s:%d\r\n",			     connection->ftp_proxy->username,			     connection->u.host, connection->u.port);	  break;	default:	  /* Something else, just send PROXY USER. */	  err = ftp_send_msg(connection, "USER %s\r\n",			     connection->ftp_proxy->username);	  break;	}      }      if (err != FTPOK)	return err;      err = ftp_get_reply(connection);      if (err != FTPOK)	return err;      break;    case 230:			/* Fallthrough. */    case 231:			/* Fallthrough. */    case 202:      logged_in = TRUE;      if (!ftp_use_proxy(connection))	return FTPOK;		/* Logged in succesfully. */      switch (connection->ftp_proxy->type)      {      case LOGINthenUSERatSITE:	err = ftp_send_msg(connection, "USER %s@%s:%d\r\n", username,			   connection->u.host, connection->u.port);	break;      case OPENSITE:	err =	    ftp_send_msg(connection, "OPEN %s:%d\r\n", connection->u.host,			 connection->u.port);	break;      case SITESITE:	err =	    ftp_send_msg(connection, "SITE %s:%d\r\n", connection->u.host,			 connection->u.port);	break;      case PROXYUSERatSITE:	err = ftp_send_msg(connection, "USER %s\r\n", username);	break;      default:	/* TODO What is the default here? */	return FTPOK;	break;      }      if (err != FTPOK)	return err;      err = ftp_get_reply(connection);      if (err != FTPOK)	return err;      break;      /* Handle 421 services not available. */    case 421:      return FTPSERVCLOSEDATLOGIN;      break;      /* User name is all right, need password. */    case 331:      if (!ftp_use_proxy(connection))      {	/* No proxy just direct connection. */	err = ftp_send_msg(connection, "PASS %s\r\n", passwd);      } else      {	switch (connection->ftp_proxy->type)	{	case USERatSITE:	  err = ftp_send_msg(connection, "PASS %s\r\n", passwd);	  break;	case USERatPROXYUSERatSITE:	  err = ftp_send_msg(connection, "PASS %s@%s\r\n", passwd,			     connection->ftp_proxy->passwd);	  break;	case USERatSITE_PROXYUSER:	  err = ftp_send_msg(connection, "PASS %s\r\n", passwd);	  break;	case PROXYUSERatSITE:	  err = ftp_send_msg(connection, "PASS %s\r\n",			     connection->ftp_proxy->passwd);	  break;	default:	  /* Something else we dont know about. */	  err = ftp_send_msg(connection, "PASS %s\r\n",			     connection->ftp_proxy->passwd);	  break;	}      }      if (err != FTPOK)	return err;      err = ftp_get_reply(connection);      if (err != FTPOK)	return err;      break;      /* 5xx series of commands indicate error. */    case 530:      return FTPLOGREFUSED;      break;    case 501:			/* Fallthrough. */    case 503:			/* Fallthrough. */    case 550:      return FTPERR;      break;    default:      /* Unknown error code. */      proz_debug(_("Unknown code %d retuned during FTP login"), ret_code);      return FTPERR;      break;    }    ret_code = ftp_get_return(connection->serv_ret_lines->line);    done_with_response(connection);  }  if (err != FTPOK)    return err;  return FTPOK;}/****************************************************************************** ...******************************************************************************/boolean ftp_use_proxy(connection_t * connection){  return (connection->ftp_proxy && connection->ftp_proxy->use_proxy &&	  connection->ftp_proxy->proxy_url.url) ? TRUE : FALSE;}/****************************************************************************** Gets info about the url (connection->u) from the FTP server, and fills in info like whether the server supports resume, the file size etc.******************************************************************************/uerr_t proz_ftp_get_url_info(connection_t * connection){  uerr_t err;  char *user, *passwd, *tmp;  netrc_entry *netrc_ent;  boolean passive_mode;  longstring buffer;  int size_rt;  /* if we have to use a HTTP proxy call the routine which is defined in http.c     and just return.   */  if (ftp_use_proxy(connection)      && connection->ftp_proxy->type == HTTPPROXY)  {    err = ftp_get_url_info_from_http_proxy(connection);    return err;  }  init_response(connection);  if (ftp_use_proxy(connection))  {    connection_show_message(connection, _("Connecting to %s"),			    connection->ftp_proxy->proxy_url.host);    /* Connect to the proxy server here. */    err = ftp_connect_to_server(connection,				connection->ftp_proxy->proxy_url.host,				connection->ftp_proxy->proxy_url.port);    if (err != FTPOK)    {      connection_show_message(connection,			      _("Error while connecting to %s"),			      connection->ftp_proxy->proxy_url.host);      return err;    }    connection_show_message(connection, _("Connected to %s"),			    connection->ftp_proxy->proxy_url.host);  } else  {    connection_show_message(connection, _("Connecting to %s"),			    connection->u.host);    err = ftp_connect_to_server(connection, connection->u.host,				connection->u.port);    if (err != FTPOK)    {      connection_show_message(connection,			      _("Error while connecting to %s"),			      connection->u.host);;      return err;    }    connection_show_message(connection, _("Connected to %s"),			    connection->u.host);  }  done_with_response(connection);  user = connection->u.user;  passwd = connection->u.passwd;  /* Use .netrc if asked to do so. */  if (connection->use_netrc == TRUE)  {    netrc_ent = search_netrc(libprozrtinfo.netrc_list, connection->u.host);    if (netrc_ent != NULL)    {      user = netrc_ent->account;      passwd = netrc_ent->password;    }  }  user = user ? user : libprozrtinfo.ftp_default_user;  passwd = passwd ? passwd : libprozrtinfo.ftp_default_passwd;  if (strcmp(user, "anonymous") == 0)    connection_show_message(connection,			    _("Logging in as user %s with password %s"),			    user, passwd);  else  {    int pwd_len = strlen(passwd);    char *tmp_pwd = (char *) kmalloc(pwd_len + 1);    memset(tmp_pwd, 'x', pwd_len);    tmp_pwd[pwd_len] = 0;    connection_show_message(connection,			    _("Logging in as user %s with password %s"),			    user, tmp_pwd);    kfree(tmp_pwd);  }  init_response(connection);  err = ftp_login(connection, user, passwd);  if (err != FTPOK)  {    close_sock(&connection->ctrl_sock);    return err;  }  done_with_response(connection);  connection_show_message(connection, _("Logged in successfully"));  init_response(connection);  err = ftp_binary(connection);  if (err != FTPOK)  {    close_sock(&connection->ctrl_sock);    return err;  }  done_with_response(connection);  /* Do we need to CWD? */  if (*connection->u.dir)  {    init_response(connection);    err = ftp_cwd(connection, connection->u.dir);    if (err != FTPOK)    {      connection_show_message(connection,			      _("CWD failed to change to directory '%s'"),			      connection->u.dir);      close_sock(&connection->ctrl_sock);      return err;    } else    {      done_with_response(connection);    }  } else    connection_show_message(connection, _("CWD not needed"));  init_response(connection);  err = ftp_rest(connection, 0);  if (err != FTPOK)  {    connection->resume_support = FALSE;    connection_show_message(connection, _("REST failed"));    /* NOTE: removed   return err; */  } else  {    connection->resume_support = TRUE;    connection_show_message(connection, _("REST ok"));  }  done_with_response(connection);  /* Lets see whether the URL really is a file. */  init_response(connection);  err = ftp_cwd(connection, connection->u.file);  if (err == FTPOK)  {    /* So connection->u.file is a directory and not a file. */    connection->file_type = DIRECTORY;    return FTPOK;  } else  {    /* FIXME: The statement below is strictly not true, it could be a symlink        but for the moment lets leave this as it is, later we will perform a       LIST command and detect whether it is a symlink. */    connection->file_type = REGULAR_FILE;  }  done_with_response(connection);  init_response(connection);  err =      ftp_size(connection, connection->u.file,	       &connection->main_file_size);  if ((err == FTPOK) || (err == FTPNSFOD) || (err != FTPSIZEFAIL))  {    close_sock(&connection->ctrl_sock);    return err;  }  done_with_response(connection);  /* The server did not support the SIZE command, so lets try to get the      file size through the LIST command. */  err = ftp_setup_data_sock_1(connection, &passive_mode);  if (err != FTPOK)  {    close_sock(&connection->ctrl_sock);    return err;  }  init_response(connection);  err = ftp_ascii(connection);  if (err != FTPOK)  {    close_sock(&connection->ctrl_sock);    return err;  }  done_with_response(connection);  init_response(connection);  err = ftp_list(connection, connection->u.file);  if (err != FTPOK)  {    close_sock(&connection->ctrl_sock);    return err;  }  done_with_response(connection);  err = ftp_setup_data_sock_2(connection, &passive_mode);  if (err != FTPOK)  {    close_sock(&connection->ctrl_sock);    return err;  }  /* Now read the data to the buffer. */  /* TODO Create a buffer which dynamically resizes itself as we add data. */  if (krecv(connection->data_sock, buffer, sizeof(buffer), 0,	    &connection->xfer_timeout) == -1)  {    connection_show_message(connection,			    _("Error receiving FTP transfer data: %s"),			    strerror(errno));    return FTPERR;  }  proz_debug(_("String received after the LIST command = %s"), buffer);  while ((tmp = strrchr(buffer, '\n')) || (tmp = strrchr(buffer, '\r')))  {    *tmp = 0;  };  close_sock(&connection->data_sock);  close_sock(&connection->ctrl_sock);  size_rt = size_returner(buffer, strlen(buffer));  if (size_rt == FTPPARSENOTEXIST)  {    return FTPNSFOD;  } else if (size_rt == FTPPARSEFAIL)  {    connection_show_message(connection,			    _			    ("Unable to parse the line the FTP server returned:please report URL to kalum@delrom.ro "));  }  connection->main_file_size = size_rt;  return FTPOK;}/****************************************************************************** This will be the first step in setting up a data sock, it will try PASV or PORT.******************************************************************************/uerr_t ftp_setup_data_sock_1(connection_t * connection,			     boolean * passive_mode){  uerr_t err;  /* If enabled lets try PASV. */  if (connection->ftp_use_pasv == TRUE)  {    init_response(connection);    err = ftp_pasv(connection, connection->pasv_addr);    /* If the error is due to the server not supporting PASV then set the       flag and lets try PORT. */    if ((err == FTPNOPASV) || (err == FTPINVPASV))    {      proz_debug(_("Server doesn't seem to support PASV"));      *passive_mode = FALSE;    } else if (err == FTPOK)	/* Server supports PASV. */    {      char dhost[256];      unsigned short dport;      sprintf(dhost, "%d.%d.%d.%d", connection->pasv_addr[0],	      connection->pasv_addr[1], connection->pasv_addr[2],	      connection->pasv_addr[3]);      dport = (connection->pasv_addr[4] << 8) + connection->pasv_addr[5];      err = connect_to_server(&connection->data_sock, dhost, dport,			      &connection->xfer_timeout);      if (err != NOCONERROR)	return err;      /* Everything seems to be ok. */      *passive_mode = TRUE;    } else      return err;    done_with_response(connection);  } else    *passive_mode = FALSE;	/* Ok... Since PASV is not to be used. */  if (*passive_mode == FALSE)  {    /* Obtain a listen socket. */    err = ftp_get_listen_socket(connection, &connection->listen_sock);    if (err != FTPOK)      return err;  }  return FTPOK;}/****************************************************************************** This will be the second step in setting up a data sock, if passive mode is FALSE, it will call accept_connection().******************************************************************************/uerr_t ftp_setup_data_sock_2(connection_t * connection,			     boolean * passive_mode){  uerr_t err;  if (*passive_mode == FALSE)	/* We have to accept the connection. */  {    err =	accept_connection(connection->listen_sock, &connection->data_sock);    if (err != ACCEPTOK)      return err;  }  return FTPOK;}/*Loops for connection->attempts */uerr_t ftp_get_url_info_loop(connection_t * connection){  pthread_mutex_lock(&connection->access_mutex);  connection->running = TRUE;  pthread_mutex_unlock(&connection->access_mutex);  assert(connection->attempts >= 0);  do  {    if (connection->attempts > 0 && connection->err != NEWLOCATION)    {      connection_show_message(connection,			      _("Retrying attempt %d in %d seconds"),			      connection->attempts,			      connection->retry_delay.tv_sec);      delay_ms(connection->retry_delay.tv_sec * 1000);    }    /*Push the handler which will cleanup any sockets that are left open */    pthread_cleanup_push(cleanup_socks, (void *) connection);    connection->err = proz_ftp_get_url_info(connection);    /*pop the handler */    pthread_cleanup_pop(0);    connection->attempts++;    switch (connection->err)    {    case FTPOK:      connection_show_message(connection, _("Successfully got info"));      pthread_mutex_lock(&connection->access_mutex);      connection->running = FALSE;      pthread_mutex_unlock(&connection->access_mutex);      return connection->err;      break;    case FTPNSFOD:      connection_show_message(connection, _("File not found!"));      pthread_mutex_lock(&connection->access_mutex);      connection->running = FALSE;      pthread_mutex_unlock(&connection->access_mutex);      return connection->err;      break;    default:      connection_show_message(connection, proz_strerror(connection->err));      break;    }  }  while ((connection->attempts < connection->max_attempts)	 || connection->max_attempts == 0);  connection_show_message(connection,			  _			  ("I have tried %d attempt(s) and have failed, aborting"),			  connection->attempts);  pthread_mutex_lock(&connection->access_mutex);  connection->running = FALSE;  pthread_mutex_unlock(&connection->access_mutex);  return connection->err;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -