Skip to content
url.c 31.9 KiB
Newer Older
Daniel Stenberg's avatar
Daniel Stenberg committed

  if(!(data->conf & CONF_PROXY)) {
    /* If not connecting via a proxy, extract the port from the URL, if it is
     * there, thus overriding any defaults that might have been set above. */
    tmp = strchr(name, ':');
    if (tmp) {
      *tmp++ = '\0';
      data->port = atoi(tmp);
    }
    
    /* Connect to target host right on */
    if(!(hp = GetHost(data, name))) {
      failf(data, "Couldn't resolv host '%s'", name);
      return URG_COULDNT_RESOLVE_HOST;
    }
  }
  else {
    char *prox_portno;
    char *endofprot;

    /* we use proxy all right, but we wanna know the remote port for SSL
       reasons */
    tmp = strchr(name, ':');
    if (tmp) {
      *tmp++ = '\0'; /* cut off the name there */
      data->remote_port = atoi(tmp);
    }

    /* Daniel Dec 10, 1998:
       We do the proxy host string parsing here. We want the host name and the
       port name. Accept a protocol:// prefix, even though it should just be
       ignored. */

    /* 1. skip the protocol part if present */
    endofprot=strstr(data->proxy, "://");
    if(endofprot) {
      data->proxy = endofprot+3;
    }

    /* allow user to specify proxy.server.com:1080 if desired */
    prox_portno = strchr (data->proxy, ':');
    if (prox_portno) {
      *prox_portno = 0x0; /* cut off number from host name */
      prox_portno ++;
      /* now set the local port number */
      data->port = atoi(prox_portno);
    }

    /* connect to proxy */
    if(!(hp = GetHost(data, data->proxy))) {
      failf(data, "Couldn't resolv proxy '%s'", data->proxy);
      return URG_COULDNT_RESOLVE_PROXY;
    }
  }
  pgrsTime(data, TIMER_NAMELOOKUP);
Daniel Stenberg's avatar
Daniel Stenberg committed

  data->firstsocket = socket(AF_INET, SOCK_STREAM, 0);

  memset((char *) &serv_addr, '\0', sizeof(serv_addr));
  memcpy((char *)&(serv_addr.sin_addr), hp->h_addr, hp->h_length);
  serv_addr.sin_family = hp->h_addrtype;

  serv_addr.sin_port = htons(data->port);

  if (connect(data->firstsocket, (struct sockaddr *) &serv_addr,
	      sizeof(serv_addr)) < 0) {
    switch(errno) {
#ifdef ECONNREFUSED
      /* this should be made nicer */
    case ECONNREFUSED:
      failf(data, "Connection refused");
      break;
#endif
#ifdef EINTR
    case EINTR:
      failf(data, "Connection timeouted");
      break;
#endif
    default:
      failf(data, "Can't connect to server: %d", errno);
      break;
    }
    return URG_COULDNT_CONNECT;
  }

  if(data->conf & CONF_PROXYUSERPWD) {
    char authorization[512];
    sprintf(data->buffer, "%s:%s", data->proxyuser, data->proxypasswd);
    base64Encode(data->buffer, authorization);

    data->ptr_proxyuserpwd = maprintf("Proxy-authorization: Basic %s\015\012",
				      authorization);
  }
  if(data->conf & (CONF_HTTPS|CONF_HTTP)) {
    if(data->useragent) {
      data->ptr_uagent = maprintf("User-Agent: %s\015\012", data->useragent);
    }
  }


  /* If we are not using a proxy and we want a secure connection,
   * perform SSL initialization & connection now.
   * If using a proxy with https, then we must tell the proxy to CONNECT
   * us to the host we want to talk to.  Only after the connect
   * has occured, can we start talking SSL
   */
   if (data->conf & CONF_HTTPS) {
     if (data->conf & CONF_PROXY) {

        /* OK, now send the connect statment */
        sendf(data->firstsocket, data,
              "CONNECT %s:%d HTTP/1.0\015\012"
              "%s"
	      "%s"
              "\r\n",
              data->hostname, data->remote_port,
              (data->conf&CONF_PROXYUSERPWD)?data->ptr_proxyuserpwd:"",
	      (data->useragent?data->ptr_uagent:"")
              );

        /* wait for the proxy to send us a HTTP/1.0 200 OK header */
	/* Daniel rewrote this part Nov 5 1998 to make it more obvious */
	{
	  int httperror=0;
	  int subversion=0;
	  while(GetLine(data->firstsocket, data->buffer, data)) {
	    if('\r' == data->buffer[0])
	      break; /* end of headers */
	    if(2 == sscanf(data->buffer, "HTTP/1.%d %d",
			   &subversion,
			   &httperror)) {
	      ;
	    }
	  }
	  if(200 != httperror) {
	    if(407 == httperror)
	      /* Added Nov 6 1998 */
	      failf(data, "Proxy requires authorization!");
	    else 
	      failf(data, "Received error code %d from proxy", httperror);
	    return URG_READ_ERROR;
	  }
	}
        infof (data, "Proxy has replied to CONNECT request\n");
     }

      /* now, perform the SSL initialization for this socket */
     if(UrgSSLConnect (data)) {
       return URG_SSL_CONNECT_ERROR;
     }
  }
  pgrsTime(data, TIMER_CONNECT);
Daniel Stenberg's avatar
Daniel Stenberg committed

  now = tvnow(); /* time this *after* the connect is done */
  bytecount = 0;
  
  /* Figure out the ip-number and the first host name it shows: */
  {
    struct in_addr in;
    (void) memcpy(&in.s_addr, *hp->h_addr_list, sizeof (in.s_addr));
    infof(data, "Connected to %s (%s)\n", hp->h_name, inet_ntoa(in));
  }

  if((data->conf&(CONF_FTP|CONF_PROXY)) == CONF_FTP) {
    result = ftp(data, &bytecount, data->user, data->passwd, ppath);
    if(result)
      return result;
  }
  else if(data->conf & CONF_TELNET) {
    result=telnet(data);
    if(result)
      return result;
  }
  else if (data->conf & CONF_LDAP) {
    result = ldap(data, path, &bytecount);
    if (result)
      return result;
  }
  else if (data->conf & CONF_DICT) {
    result = dict(data, path, &bytecount);
    if(result)
      return result;
  }
  else {
    result = http(data, ppath, name, &bytecount);
    if(result)
      return result;
  }
  if(bytecount) {
    double ittook = tvdiff (tvnow(), now);
    infof(data, "%i bytes transfered in %.3lf seconds (%.0lf bytes/sec).\n",
          bytecount, ittook, (double)bytecount/(ittook!=0.0?ittook:1));
  }
  return URG_OK;
}