Revert "Imported Upstream version 7.53.1"
[platform/upstream/curl.git] / lib / url.c
index 38b9552..f355c7a 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
 #include <limits.h>
 #endif
 
-#ifdef USE_LIBIDN2
-#include <idn2.h>
-
+#ifdef USE_LIBIDN
+#include <idna.h>
+#include <tld.h>
+#include <stringprep.h>
+#ifdef HAVE_IDN_FREE_H
+#include <idn-free.h>
+#else
+/* prototype from idn-free.h, not provided by libidn 0.4.5's make install! */
+void idn_free (void *ptr);
+#endif
+#ifndef HAVE_IDN_FREE
+/* if idn_free() was not found in this version of libidn use free() instead */
+#define idn_free(x) (free)(x)
+#endif
 #elif defined(USE_WIN32_IDN)
 /* prototype for curl_win32_idn_to_ascii() */
 bool curl_win32_idn_to_ascii(const char *in, char **out);
-#endif  /* USE_LIBIDN2 */
+#endif  /* USE_LIBIDN */
 
 #include "urldata.h"
 #include "netrc.h"
@@ -77,7 +88,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
 #include "sendf.h"
 #include "progress.h"
 #include "cookie.h"
-#include "strcase.h"
+#include "strequal.h"
 #include "strerror.h"
 #include "escape.h"
 #include "strtok.h"
@@ -89,10 +100,10 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
 #include "multiif.h"
 #include "easyif.h"
 #include "speedcheck.h"
+#include "rawstr.h"
 #include "warnless.h"
 #include "non-ascii.h"
 #include "inet_pton.h"
-#include "getinfo.h"
 
 /* And now for the protocols */
 #include "ftp.h"
@@ -452,7 +463,6 @@ CURLcode Curl_close(struct Curl_easy *data)
   }
   data->change.url = NULL;
 
-  Curl_safefree(data->state.buffer);
   Curl_safefree(data->state.headerbuff);
 
   Curl_flush_cookies(data, 1);
@@ -465,7 +475,6 @@ CURLcode Curl_close(struct Curl_easy *data)
   /* this destroys the channel and we cannot use it anymore after this */
   Curl_resolver_cleanup(data->state.resolver);
 
-  Curl_http2_cleanup_dependencies(data);
   Curl_convert_close(data);
 
   /* No longer a dirty share, if it exists */
@@ -528,9 +537,9 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
   set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
 
   /* Set the default size of the SSL session ID cache */
-  set->general_ssl.max_ssl_sessions = 5;
+  set->ssl.max_ssl_sessions = 5;
 
-  set->proxyport = 0;
+  set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
   set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
   set->httpauth = CURLAUTH_BASIC;  /* defaults to basic */
   set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
@@ -542,16 +551,14 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
    * libcurl 7.10 introduced SSL verification *by default*! This needs to be
    * switched off unless wanted.
    */
-  set->ssl.primary.verifypeer = TRUE;
-  set->ssl.primary.verifyhost = TRUE;
+  set->ssl.verifypeer = TRUE;
+  set->ssl.verifyhost = TRUE;
 #ifdef USE_TLS_SRP
   set->ssl.authtype = CURL_TLSAUTH_NONE;
 #endif
   set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
                                                       type */
-  set->general_ssl.sessionid = TRUE; /* session ID caching enabled by
-                                        default */
-  set->proxy_ssl = set->ssl;
+  set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
 
   set->new_file_perms = 0644;    /* Default permissions */
   set->new_directory_perms = 0755; /* Default permissions */
@@ -574,20 +581,12 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
 
   /* This is our preferred CA cert bundle/path since install time */
 #if defined(CURL_CA_BUNDLE)
-  result = setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
-  if(result)
-    return result;
-
-  result = setstropt(&set->str[STRING_SSL_CAFILE_PROXY], CURL_CA_BUNDLE);
+  result = setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
   if(result)
     return result;
 #endif
 #if defined(CURL_CA_PATH)
-  result = setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
-  if(result)
-    return result;
-
-  result = setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
+  result = setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
   if(result)
     return result;
 #endif
@@ -647,12 +646,6 @@ CURLcode Curl_open(struct Curl_easy **curl)
 
   /* We do some initial setup here, all those fields that can't be just 0 */
 
-  data->state.buffer = malloc(BUFSIZE + 1);
-  if(!data->state.buffer) {
-    DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n"));
-    result = CURLE_OUT_OF_MEMORY;
-  }
-
   data->state.headerbuff = malloc(HEADERSIZE);
   if(!data->state.headerbuff) {
     DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
@@ -665,8 +658,6 @@ CURLcode Curl_open(struct Curl_easy **curl)
 
     Curl_convert_init(data);
 
-    Curl_initinfo(data);
-
     /* most recent connection is not yet defined */
     data->state.lastconnect = NULL;
 
@@ -683,7 +674,6 @@ CURLcode Curl_open(struct Curl_easy **curl)
 
   if(result) {
     Curl_resolver_cleanup(data->state.resolver);
-    free(data->state.buffer);
     free(data->state.headerbuff);
     Curl_freeset(data);
     free(data);
@@ -716,12 +706,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     break;
   case CURLOPT_SSL_CIPHER_LIST:
     /* set a list of cipher we want to use in the SSL connection */
-    result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_SSL_CIPHER_LIST:
-    /* set a list of cipher we want to use in the SSL connection for proxy */
-    result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
+    result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
                        va_arg(param, char *));
     break;
 
@@ -797,10 +782,6 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      */
     data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
-  case CURLOPT_KEEP_SENDING_ON_ERROR:
-    data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
-                                           TRUE : FALSE;
-    break;
   case CURLOPT_UPLOAD:
   case CURLOPT_PUT:
     /*
@@ -927,18 +908,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * implementations are lame.
      */
 #ifdef USE_SSL
-    data->set.ssl.primary.version = va_arg(param, long);
-#else
-    result = CURLE_UNKNOWN_OPTION;
-#endif
-    break;
-  case CURLOPT_PROXY_SSLVERSION:
-    /*
-     * Set explicit SSL version to try to connect with for proxy, as some SSL
-     * implementations are lame.
-     */
-#ifdef USE_SSL
-    data->set.proxy_ssl.primary.version = va_arg(param, long);
+    data->set.ssl.version = va_arg(param, long);
 #else
     result = CURLE_UNKNOWN_OPTION;
 #endif
@@ -1045,7 +1015,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
           (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
         result = CURLE_OUT_OF_MEMORY;
       else {
-        char *p;
+        char * p;
 
         (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
 
@@ -1256,23 +1226,23 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     if(argptr == NULL)
       break;
 
-    if(strcasecompare(argptr, "ALL")) {
+    if(Curl_raw_equal(argptr, "ALL")) {
       /* clear all cookies */
       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
       Curl_cookie_clearall(data->cookies);
       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
     }
-    else if(strcasecompare(argptr, "SESS")) {
+    else if(Curl_raw_equal(argptr, "SESS")) {
       /* clear session cookies */
       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
       Curl_cookie_clearsess(data->cookies);
       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
     }
-    else if(strcasecompare(argptr, "FLUSH")) {
+    else if(Curl_raw_equal(argptr, "FLUSH")) {
       /* flush cookies to file, takes care of the locking */
       Curl_flush_cookies(data, 0);
     }
-    else if(strcasecompare(argptr, "RELOAD")) {
+    else if(Curl_raw_equal(argptr, "RELOAD")) {
       /* reload cookies from file */
       Curl_cookie_loadfiles(data);
       break;
@@ -1472,30 +1442,18 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
 
   case CURLOPT_PROXY:
     /*
-     * Set proxy server:port to use as proxy.
+     * Set proxy server:port to use as HTTP proxy.
      *
-     * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
-     * we explicitly say that we don't want to use a proxy
-     * (even though there might be environment variables saying so).
+     * If the proxy is set to "" we explicitly say that we don't want to use a
+     * proxy (even though there might be environment variables saying so).
      *
      * Setting it to NULL, means no proxy but allows the environment variables
-     * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
+     * to decide for us.
      */
     result = setstropt(&data->set.str[STRING_PROXY],
                        va_arg(param, char *));
     break;
 
-  case CURLOPT_PRE_PROXY:
-    /*
-     * Set proxy server:port to use as SOCKS proxy.
-     *
-     * If the proxy is set to "" or NULL we explicitly say that we don't want
-     * to use the socks proxy.
-     */
-    result = setstropt(&data->set.str[STRING_PRE_PROXY],
-                       va_arg(param, char *));
-    break;
-
   case CURLOPT_PROXYTYPE:
     /*
      * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
@@ -1507,7 +1465,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
      */
-    switch(va_arg(param, long)) {
+    switch (va_arg(param, long)) {
     case 0:
       data->set.proxy_transfer_mode = FALSE;
       break;
@@ -1960,70 +1918,35 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * String that holds file name of the SSL certificate to use
      */
-    result = setstropt(&data->set.str[STRING_CERT_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_SSLCERT:
-    /*
-     * String that holds file name of the SSL certificate to use for proxy
-     */
-    result = setstropt(&data->set.str[STRING_CERT_PROXY],
+    result = setstropt(&data->set.str[STRING_CERT],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLCERTTYPE:
     /*
      * String that holds file type of the SSL certificate to use
      */
-    result = setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_SSLCERTTYPE:
-    /*
-     * String that holds file type of the SSL certificate to use for proxy
-     */
-    result = setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
+    result = setstropt(&data->set.str[STRING_CERT_TYPE],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLKEY:
     /*
      * String that holds file name of the SSL key to use
      */
-    result = setstropt(&data->set.str[STRING_KEY_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_SSLKEY:
-    /*
-     * String that holds file name of the SSL key to use for proxy
-     */
-    result = setstropt(&data->set.str[STRING_KEY_PROXY],
+    result = setstropt(&data->set.str[STRING_KEY],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLKEYTYPE:
     /*
      * String that holds file type of the SSL key to use
      */
-    result = setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_SSLKEYTYPE:
-    /*
-     * String that holds file type of the SSL key to use for proxy
-     */
-    result = setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
+    result = setstropt(&data->set.str[STRING_KEY_TYPE],
                        va_arg(param, char *));
     break;
   case CURLOPT_KEYPASSWD:
     /*
      * String that holds the SSL or SSH private key password.
      */
-    result = setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_KEYPASSWD:
-    /*
-     * String that holds the SSL private key password for proxy.
-     */
-    result = setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
+    result = setstropt(&data->set.str[STRING_KEY_PASSWD],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLENGINE:
@@ -2086,15 +2009,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * Enable peer SSL verifying.
      */
-    data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
-                                       TRUE : FALSE;
-    break;
-  case CURLOPT_PROXY_SSL_VERIFYPEER:
-    /*
-     * Enable peer SSL verifying for proxy.
-     */
-    data->set.proxy_ssl.primary.verifypeer =
-      (0 != va_arg(param, long))?TRUE:FALSE;
+    data->set.ssl.verifypeer = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
   case CURLOPT_SSL_VERIFYHOST:
     /*
@@ -2112,25 +2027,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
 
-    data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
-    break;
-  case CURLOPT_PROXY_SSL_VERIFYHOST:
-    /*
-     * Enable verification of the host name in the peer certificate for proxy
-     */
-    arg = va_arg(param, long);
-
-    /* Obviously people are not reading documentation and too many thought
-       this argument took a boolean when it wasn't and misused it. We thus ban
-       1 as a sensible input and we warn about its use. Then we only have the
-       2 action internally stored as TRUE. */
-
-    if(1 == arg) {
-      failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
-      return CURLE_BAD_FUNCTION_ARGUMENT;
-    }
-
-    data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
+    data->set.ssl.verifyhost = (0 != arg) ? TRUE : FALSE;
     break;
   case CURLOPT_SSL_VERIFYSTATUS:
     /*
@@ -2141,8 +2038,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
       break;
     }
 
-    data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
-                                         TRUE : FALSE;
+    data->set.ssl.verifystatus = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
   case CURLOPT_SSL_CTX_FUNCTION:
 #ifdef have_curlssl_ssl_ctx
@@ -2188,19 +2084,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * Set pinned public key for SSL connection.
      * Specify file name of the public key in DER format.
      */
-    result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
-                       va_arg(param, char *));
-#else
-    result = CURLE_NOT_BUILT_IN;
-#endif
-    break;
-  case CURLOPT_PROXY_PINNEDPUBLICKEY:
-#ifdef have_curlssl_pinnedpubkey /* only by supported backends */
-    /*
-     * Set pinned public key for SSL connection.
-     * Specify file name of the public key in DER format.
-     */
-    result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
+    result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
                        va_arg(param, char *));
 #else
     result = CURLE_NOT_BUILT_IN;
@@ -2210,15 +2094,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * Set CA info for SSL connection. Specify file name of the CA certificate
      */
-    result = setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_CAINFO:
-    /*
-     * Set CA info SSL connection for proxy. Specify file name of the
-     * CA certificate
-     */
-    result = setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
+    result = setstropt(&data->set.str[STRING_SSL_CAFILE],
                        va_arg(param, char *));
     break;
   case CURLOPT_CAPATH:
@@ -2228,20 +2104,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * certificates which have been prepared using openssl c_rehash utility.
      */
     /* This does not work on windows. */
-    result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
-                       va_arg(param, char *));
-#else
-    result = CURLE_NOT_BUILT_IN;
-#endif
-    break;
-  case CURLOPT_PROXY_CAPATH:
-#ifdef have_curlssl_ca_path /* not supported by all backends */
-    /*
-     * Set CA path info for SSL connection proxy. Specify directory name of the
-     * CA certificates which have been prepared using openssl c_rehash utility.
-     */
-    /* This does not work on windows. */
-    result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
+    result = setstropt(&data->set.str[STRING_SSL_CAPATH],
                        va_arg(param, char *));
 #else
     result = CURLE_NOT_BUILT_IN;
@@ -2252,15 +2115,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * Set CRL file info for SSL connection. Specify file name of the CRL
      * to check certificates revocation
      */
-    result = setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_PROXY_CRLFILE:
-    /*
-     * Set CRL file info for SSL connection for proxy. Specify file name of the
-     * CRL to check certificates revocation
-     */
-    result = setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
+    result = setstropt(&data->set.str[STRING_SSL_CRLFILE],
                        va_arg(param, char *));
     break;
   case CURLOPT_ISSUERCERT:
@@ -2268,7 +2123,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * Set Issuer certificate file
      * to check certificates issuer
      */
-    result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
+    result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
                        va_arg(param, char *));
     break;
   case CURLOPT_TELNETOPTIONS:
@@ -2285,20 +2140,9 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      */
     data->set.buffer_size = va_arg(param, long);
 
-    if(data->set.buffer_size > MAX_BUFSIZE)
-      data->set.buffer_size = MAX_BUFSIZE; /* huge internal default */
-    else if(data->set.buffer_size < 1)
-      data->set.buffer_size = BUFSIZE;
-
-    /* Resize only if larger than default buffer size. */
-    if(data->set.buffer_size > BUFSIZE) {
-      data->state.buffer = realloc(data->state.buffer,
-                                   data->set.buffer_size + 1);
-      if(!data->state.buffer) {
-        DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
-        result = CURLE_OUT_OF_MEMORY;
-      }
-    }
+    if((data->set.buffer_size> (BUFSIZE -1)) ||
+       (data->set.buffer_size < 1))
+      data->set.buffer_size = 0; /* huge internal default */
 
     break;
 
@@ -2360,7 +2204,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
       }
 #endif   /* CURL_DISABLE_HTTP */
       if(data->share->sslsession) {
-        data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
+        data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions;
         data->state.session = data->share->sslsession;
       }
       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
@@ -2395,14 +2239,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
 
   case CURLOPT_SSL_OPTIONS:
     arg = va_arg(param, long);
-    data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
-    data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
-    break;
-
-  case CURLOPT_PROXY_SSL_OPTIONS:
-    arg = va_arg(param, long);
-    data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
-    data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+    data->set.ssl_enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
+    data->set.ssl_no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
     break;
 
 #endif
@@ -2498,8 +2336,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     break;
 
   case CURLOPT_SSL_SESSIONID_CACHE:
-    data->set.general_ssl.sessionid = (0 != va_arg(param, long)) ?
-                                      TRUE : FALSE;
+    data->set.ssl.sessionid = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
 
 #ifdef USE_LIBSSH2
@@ -2766,43 +2603,23 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     break;
 #ifdef USE_TLS_SRP
   case CURLOPT_TLSAUTH_USERNAME:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
+    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
                        va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
+    if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
     break;
-  case CURLOPT_PROXY_TLSAUTH_USERNAME:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
-                       va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
-       !data->set.proxy_ssl.authtype)
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
-    break;
   case CURLOPT_TLSAUTH_PASSWORD:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
+    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
                        va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
+    if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
     break;
-  case CURLOPT_PROXY_TLSAUTH_PASSWORD:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
-                       va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
-       !data->set.proxy_ssl.authtype)
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
-    break;
   case CURLOPT_TLSAUTH_TYPE:
-    if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
+    if(strnequal((char *)va_arg(param, char *), "SRP", strlen("SRP")))
       data->set.ssl.authtype = CURL_TLSAUTH_SRP;
     else
       data->set.ssl.authtype = CURL_TLSAUTH_NONE;
     break;
-  case CURLOPT_PROXY_TLSAUTH_TYPE:
-    if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
-    else
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
-    break;
 #endif
   case CURLOPT_DNS_SERVERS:
     result = Curl_set_dns_servers(data, va_arg(param, char *));
@@ -2842,12 +2659,6 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
 
 #ifdef USE_UNIX_SOCKETS
   case CURLOPT_UNIX_SOCKET_PATH:
-    data->set.abstract_unix_socket = FALSE;
-    result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
-                       va_arg(param, char *));
-    break;
-  case CURLOPT_ABSTRACT_UNIX_SOCKET:
-    data->set.abstract_unix_socket = TRUE;
     result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
                        va_arg(param, char *));
     break;
@@ -2875,11 +2686,9 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     return CURLE_NOT_BUILT_IN;
 #else
     struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
-    if(!dep || GOOD_EASY_HANDLE(dep)) {
-      if(data->set.stream_depends_on) {
-        Curl_http2_remove_child(data->set.stream_depends_on, data);
-      }
-      Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
+    if(dep && GOOD_EASY_HANDLE(dep)) {
+      data->set.stream_depends_on = dep;
+      data->set.stream_depends_e = (option == CURLOPT_STREAM_DEPENDS_E);
     }
     break;
 #endif
@@ -2917,10 +2726,10 @@ static void conn_reset_postponed_data(struct connectdata *conn, int num)
 #endif /* DEBUGBUILD */
   }
   else {
-    DEBUGASSERT(psnd->allocated_size == 0);
-    DEBUGASSERT(psnd->recv_size == 0);
-    DEBUGASSERT(psnd->recv_processed == 0);
-    DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
+    DEBUGASSERT (psnd->allocated_size == 0);
+    DEBUGASSERT (psnd->recv_size == 0);
+    DEBUGASSERT (psnd->recv_processed == 0);
+    DEBUGASSERT (psnd->bindsock == CURL_SOCKET_BAD);
   }
 }
 
@@ -2967,10 +2776,8 @@ static void conn_free(struct connectdata *conn)
   Curl_safefree(conn->passwd);
   Curl_safefree(conn->oauth_bearer);
   Curl_safefree(conn->options);
-  Curl_safefree(conn->http_proxy.user);
-  Curl_safefree(conn->socks_proxy.user);
-  Curl_safefree(conn->http_proxy.passwd);
-  Curl_safefree(conn->socks_proxy.passwd);
+  Curl_safefree(conn->proxyuser);
+  Curl_safefree(conn->proxypasswd);
   Curl_safefree(conn->allocptr.proxyuserpwd);
   Curl_safefree(conn->allocptr.uagent);
   Curl_safefree(conn->allocptr.userpwd);
@@ -2984,9 +2791,7 @@ static void conn_free(struct connectdata *conn)
   Curl_safefree(conn->trailer);
   Curl_safefree(conn->host.rawalloc); /* host name buffer */
   Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
-  Curl_safefree(conn->secondaryhostname);
-  Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
-  Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
+  Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
   Curl_safefree(conn->master_buffer);
 
   conn_reset_all_postponed_data(conn);
@@ -2998,12 +2803,7 @@ static void conn_free(struct connectdata *conn)
   conn->recv_pipe = NULL;
 
   Curl_safefree(conn->localdev);
-  Curl_free_primary_ssl_config(&conn->ssl_config);
-  Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
-
-#ifdef USE_UNIX_SOCKETS
-  Curl_safefree(conn->unix_domain_socket);
-#endif
+  Curl_free_ssl_config(&conn->ssl_config);
 
   free(conn); /* free all the connection oriented data */
 }
@@ -3063,8 +2863,7 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
 
   free_fixed_hostname(&conn->host);
   free_fixed_hostname(&conn->conn_to_host);
-  free_fixed_hostname(&conn->http_proxy.host);
-  free_fixed_hostname(&conn->socks_proxy.host);
+  free_fixed_hostname(&conn->proxy);
 
   Curl_ssl_close(conn, FIRSTSOCKET);
 
@@ -3089,7 +2888,7 @@ static bool SocketIsDead(curl_socket_t sock)
   int sval;
   bool ret_val = TRUE;
 
-  sval = SOCKET_READABLE(sock, 0);
+  sval = Curl_socket_ready(sock, CURL_SOCKET_BAD, 0);
   if(sval == 0)
     /* timeout */
     ret_val = FALSE;
@@ -3105,8 +2904,7 @@ static bool IsPipeliningPossible(const struct Curl_easy *handle,
                                  const struct connectdata *conn)
 {
   /* If a HTTP protocol and pipelining is enabled */
-  if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
-     (!conn->bits.protoconnstart || !conn->bits.close)) {
+  if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
 
     if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
        (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
@@ -3223,8 +3021,8 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
   struct curl_hash_iterator iter;
   struct curl_llist_element *curr;
   struct curl_hash_element *he;
-  time_t highscore=-1;
-  time_t score;
+  long highscore=-1;
+  long score;
   struct timeval now;
   struct connectdata *conn_candidate = NULL;
   struct connectbundle *bundle;
@@ -3261,21 +3059,6 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
   return conn_candidate;
 }
 
-static bool
-proxy_info_matches(const struct proxy_info* data,
-                   const struct proxy_info* needle)
-{
-  if((data->proxytype == needle->proxytype) &&
-     (data->port == needle->port) &&
-     Curl_safe_strcasecompare(data->host.name, needle->host.name) &&
-     Curl_safe_strcasecompare(data->user, needle->user) &&
-     Curl_safe_strcasecompare(data->passwd, needle->passwd))
-    return TRUE;
-
-  return FALSE;
-}
-
-
 /*
  * This function finds the connection in the connection
  * bundle that has been unused for the longest time.
@@ -3288,8 +3071,8 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
                                       struct connectbundle *bundle)
 {
   struct curl_llist_element *curr;
-  time_t highscore=-1;
-  time_t score;
+  long highscore=-1;
+  long score;
   struct timeval now;
   struct connectdata *conn_candidate = NULL;
   struct connectdata *conn;
@@ -3371,7 +3154,7 @@ static int call_disconnect_if_dead(struct connectdata *conn,
 static void prune_dead_connections(struct Curl_easy *data)
 {
   struct timeval now = Curl_tvnow();
-  time_t elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
+  long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
 
   if(elapsed >= 1000L) {
     Curl_conncache_foreach(data->state.conn_cache, data,
@@ -3439,14 +3222,19 @@ ConnectionExists(struct Curl_easy *data,
       max_pipeline_length(data->multi):0;
     size_t best_pipe_len = max_pipe_len;
     struct curl_llist_element *curr;
+    const char *hostname;
+
+    if(needle->bits.conn_to_host)
+      hostname = needle->conn_to_host.name;
+    else
+      hostname = needle->host.name;
 
     infof(data, "Found bundle for host %s: %p [%s]\n",
-          (needle->bits.conn_to_host ? needle->conn_to_host.name :
-           needle->host.name), (void *)bundle,
-          (bundle->multiuse == BUNDLE_PIPELINING ?
-           "can pipeline" :
-           (bundle->multiuse == BUNDLE_MULTIPLEX ?
-            "can multiplex" : "serially")));
+          hostname, (void *)bundle,
+          (bundle->multiuse== BUNDLE_PIPELINING?
+           "can pipeline":
+           (bundle->multiuse== BUNDLE_MULTIPLEX?
+            "can multiplex":"serially")));
 
     /* We can't pipe if we don't know anything about the server */
     if(canPipeline) {
@@ -3491,8 +3279,6 @@ ConnectionExists(struct Curl_easy *data,
       pipeLen = check->send_pipe->size + check->recv_pipe->size;
 
       if(canPipeline) {
-        if(check->bits.protoconnstart && check->bits.close)
-          continue;
 
         if(!check->bits.multiplex) {
           /* If not multiplexing, make sure the pipe has only GET requests */
@@ -3545,19 +3331,6 @@ ConnectionExists(struct Curl_easy *data,
         }
       }
 
-#ifdef USE_UNIX_SOCKETS
-      if(needle->unix_domain_socket) {
-        if(!check->unix_domain_socket)
-          continue;
-        if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
-          continue;
-        if(needle->abstract_unix_socket != check->abstract_unix_socket)
-          continue;
-      }
-      else if(check->unix_domain_socket)
-        continue;
-#endif
-
       if((needle->handler->flags&PROTOPT_SSL) !=
          (check->handler->flags&PROTOPT_SSL))
         /* don't do mixed SSL and non-SSL connections */
@@ -3566,12 +3339,23 @@ ConnectionExists(struct Curl_easy *data,
           /* except protocols that have been upgraded via TLS */
           continue;
 
-      if(needle->bits.httpproxy != check->bits.httpproxy ||
-         needle->bits.socksproxy != check->bits.socksproxy)
+      if(needle->handler->flags&PROTOPT_SSL) {
+        if((data->set.ssl.verifypeer != check->verifypeer) ||
+           (data->set.ssl.verifyhost != check->verifyhost))
+          continue;
+      }
+
+      if(needle->bits.proxy != check->bits.proxy)
+        /* don't do mixed proxy and non-proxy connections */
         continue;
 
-      if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy,
-                                                        &check->socks_proxy))
+      if(needle->bits.proxy &&
+         (needle->proxytype != check->proxytype ||
+          needle->bits.httpproxy != check->bits.httpproxy ||
+          needle->bits.tunnel_proxy != check->bits.tunnel_proxy ||
+          !Curl_raw_equal(needle->proxy.name, check->proxy.name) ||
+          needle->port != check->port))
+        /* don't mix connections that use different proxies */
         continue;
 
       if(needle->bits.conn_to_host != check->bits.conn_to_host)
@@ -3584,33 +3368,6 @@ ConnectionExists(struct Curl_easy *data,
          * connections that don't use this feature */
         continue;
 
-      if(needle->bits.httpproxy) {
-        if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
-          continue;
-
-        if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
-          continue;
-
-        if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
-          /* use https proxy */
-          if(needle->handler->flags&PROTOPT_SSL) {
-            /* use double layer ssl */
-            if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
-                                        &check->proxy_ssl_config))
-              continue;
-            if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
-              continue;
-          }
-          else {
-            if(!Curl_ssl_config_matches(&needle->ssl_config,
-                                        &check->ssl_config))
-              continue;
-            if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
-              continue;
-          }
-        }
-      }
-
       if(!canPipeline && check->inuse)
         /* this request can't be pipelined but the checked connection is
            already in use so we skip it */
@@ -3630,35 +3387,35 @@ ConnectionExists(struct Curl_easy *data,
         */
         if((check->localport != needle->localport) ||
            (check->localportrange != needle->localportrange) ||
-           (needle->localdev &&
-            (!check->localdev || strcmp(check->localdev, needle->localdev))))
+           !check->localdev ||
+           !needle->localdev ||
+           strcmp(check->localdev, needle->localdev))
           continue;
       }
 
       if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
         /* This protocol requires credentials per connection,
            so verify that we're using the same name and password as well */
-        if(strcmp(needle->user, check->user) ||
-           strcmp(needle->passwd, check->passwd)) {
+        if(!strequal(needle->user, check->user) ||
+           !strequal(needle->passwd, check->passwd)) {
           /* one of them was different */
           continue;
         }
       }
 
       if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
-         needle->bits.tunnel_proxy) {
+         (needle->bits.httpproxy && needle->bits.tunnel_proxy)) {
         /* The requested connection does not use a HTTP proxy or it uses SSL or
-           it is a non-SSL protocol tunneled or it is a non-SSL protocol which
-           is allowed to be upgraded via TLS */
-
-        if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
+           it is a non-SSL protocol tunneled over the same HTTP proxy name and
+           port number */
+        if((Curl_raw_equal(needle->handler->scheme, check->handler->scheme) ||
             (get_protocol_family(check->handler->protocol) ==
              needle->handler->protocol && check->tls_upgraded)) &&
-           (!needle->bits.conn_to_host || strcasecompare(
+           (!needle->bits.conn_to_host || Curl_raw_equal(
             needle->conn_to_host.name, check->conn_to_host.name)) &&
            (!needle->bits.conn_to_port ||
              needle->conn_to_port == check->conn_to_port) &&
-           strcasecompare(needle->host.name, check->host.name) &&
+           Curl_raw_equal(needle->host.name, check->host.name) &&
            needle->remote_port == check->remote_port) {
           /* The schemes match or the the protocol family is the same and the
              previous connection was TLS upgraded, and the hostname and host
@@ -3700,8 +3457,8 @@ ConnectionExists(struct Curl_easy *data,
            possible. (Especially we must not reuse the same connection if
            partway through a handshake!) */
         if(wantNTLMhttp) {
-          if(strcmp(needle->user, check->user) ||
-             strcmp(needle->passwd, check->passwd))
+          if(!strequal(needle->user, check->user) ||
+             !strequal(needle->passwd, check->passwd))
             continue;
         }
         else if(check->ntlm.state != NTLMSTATE_NONE) {
@@ -3711,13 +3468,12 @@ ConnectionExists(struct Curl_easy *data,
 
         /* Same for Proxy NTLM authentication */
         if(wantProxyNTLMhttp) {
-          /* Both check->http_proxy.user and check->http_proxy.passwd can be
-           * NULL */
-          if(!check->http_proxy.user || !check->http_proxy.passwd)
+          /* Both check->proxyuser and check->proxypasswd can be NULL */
+          if(!check->proxyuser || !check->proxypasswd)
             continue;
 
-          if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
-             strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
+          if(!strequal(needle->proxyuser, check->proxyuser) ||
+             !strequal(needle->proxypasswd, check->proxypasswd))
             continue;
         }
         else if(check->proxyntlm.state != NTLMSTATE_NONE) {
@@ -3821,50 +3577,51 @@ ConnectionExists(struct Curl_easy *data,
    Note: this function's sub-functions call failf()
 
 */
-CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex)
+CURLcode Curl_connected_proxy(struct connectdata *conn,
+                              int sockindex)
 {
-  CURLcode result = CURLE_OK;
+  if(!conn->bits.proxy || sockindex)
+    /* this magic only works for the primary socket as the secondary is used
+       for FTP only and it has FTP specific magic in ftp.c */
+    return CURLE_OK;
 
-  if(conn->bits.socksproxy) {
+  switch(conn->proxytype) {
 #ifndef CURL_DISABLE_PROXY
-    /* for the secondary socket (FTP), use the "connect to host"
-     * but ignore the "connect to port" (use the secondary port)
-     */
-    const char * const host = conn->bits.httpproxy ?
-                              conn->http_proxy.host.name :
-                              conn->bits.conn_to_host ?
-                              conn->conn_to_host.name :
-                              sockindex == SECONDARYSOCKET ?
-                              conn->secondaryhostname : conn->host.name;
-    const int port = conn->bits.httpproxy ? (int)conn->http_proxy.port :
-                     sockindex == SECONDARYSOCKET ? conn->secondary_port :
-                     conn->bits.conn_to_port ? conn->conn_to_port :
-                     conn->remote_port;
-    conn->bits.socksproxy_connecting = TRUE;
-    switch(conn->socks_proxy.proxytype) {
-    case CURLPROXY_SOCKS5:
-    case CURLPROXY_SOCKS5_HOSTNAME:
-      result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
-                         host, port, sockindex, conn);
-      break;
+  case CURLPROXY_SOCKS5:
+  case CURLPROXY_SOCKS5_HOSTNAME:
+    return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd,
+                       conn->bits.conn_to_host ? conn->conn_to_host.name :
+                       conn->host.name,
+                       conn->bits.conn_to_port ? conn->conn_to_port :
+                       conn->remote_port,
+                       FIRSTSOCKET, conn);
+
+  case CURLPROXY_SOCKS4:
+    return Curl_SOCKS4(conn->proxyuser,
+                       conn->bits.conn_to_host ? conn->conn_to_host.name :
+                       conn->host.name,
+                       conn->bits.conn_to_port ? conn->conn_to_port :
+                       conn->remote_port,
+                       FIRSTSOCKET, conn, FALSE);
+
+  case CURLPROXY_SOCKS4A:
+    return Curl_SOCKS4(conn->proxyuser,
+                       conn->bits.conn_to_host ? conn->conn_to_host.name :
+                       conn->host.name,
+                       conn->bits.conn_to_port ? conn->conn_to_port :
+                       conn->remote_port,
+                       FIRSTSOCKET, conn, TRUE);
 
-    case CURLPROXY_SOCKS4:
-    case CURLPROXY_SOCKS4A:
-      result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
-                           conn);
-      break;
-
-    default:
-      failf(conn->data, "unknown proxytype option given");
-      result = CURLE_COULDNT_CONNECT;
-    } /* switch proxytype */
-    conn->bits.socksproxy_connecting = FALSE;
-#else
-  (void)sockindex;
 #endif /* CURL_DISABLE_PROXY */
-  }
+  case CURLPROXY_HTTP:
+  case CURLPROXY_HTTP_1_0:
+    /* do nothing here. handled later. */
+    break;
+  default:
+    break;
+  } /* switch proxytype */
 
-  return result;
+  return CURLE_OK;
 }
 
 /*
@@ -3875,10 +3632,7 @@ void Curl_verboseconnect(struct connectdata *conn)
 {
   if(conn->data->set.verbose)
     infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
-          conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
-          conn->bits.httpproxy ? conn->http_proxy.host.dispname :
-          conn->bits.conn_to_host ? conn->conn_to_host.dispname :
-          conn->host.dispname,
+          conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname,
           conn->ip_addr_str, conn->port, conn->connection_id);
 }
 #endif
@@ -3968,14 +3722,10 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
 
   if(!conn->bits.protoconnstart) {
 
-    result = Curl_proxy_connect(conn, FIRSTSOCKET);
+    result = Curl_proxy_connect(conn);
     if(result)
       return result;
 
-    if(CONNECT_FIRSTSOCKET_PROXY_SSL())
-      /* wait for HTTPS proxy SSL initialization to complete */
-      return CURLE_OK;
-
     if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
        (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE))
       /* when using an HTTP tunnel proxy, await complete tunnel establishment
@@ -4005,7 +3755,7 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
  */
 static bool is_ASCII_name(const char *hostname)
 {
-  const unsigned char *ch = (const unsigned char *)hostname;
+  const unsigned char *ch = (const unsigned char*)hostname;
 
   while(*ch) {
     if(*ch++ & 0x80)
@@ -4014,15 +3764,58 @@ static bool is_ASCII_name(const char *hostname)
   return TRUE;
 }
 
+#ifdef USE_LIBIDN
+/*
+ * Check if characters in hostname is allowed in Top Level Domain.
+ */
+static bool tld_check_name(struct Curl_easy *data,
+                           const char *ace_hostname)
+{
+  size_t err_pos;
+  char *uc_name = NULL;
+  int rc;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+  const char *tld_errmsg = "<no msg>";
+#else
+  (void)data;
+#endif
+
+  /* Convert (and downcase) ACE-name back into locale's character set */
+  rc = idna_to_unicode_lzlz(ace_hostname, &uc_name, 0);
+  if(rc != IDNA_SUCCESS)
+    return FALSE;
+
+  /* Warning: err_pos receives "the decoded character offset rather than the
+     byte position in the string." And as of libidn 1.32 that character offset
+     is for UTF-8, even if the passed in string is another locale. */
+  rc = tld_check_lz(uc_name, &err_pos, NULL);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+#ifdef HAVE_TLD_STRERROR
+  if(rc != TLD_SUCCESS)
+    tld_errmsg = tld_strerror((Tld_rc)rc);
+#endif
+  if(rc != TLD_SUCCESS)
+    infof(data, "WARNING: TLD check for %s failed; %s\n",
+          uc_name, tld_errmsg);
+#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+  if(uc_name)
+     idn_free(uc_name);
+  if(rc != TLD_SUCCESS)
+    return FALSE;
+
+  return TRUE;
+}
+#endif
+
 /*
  * Perform any necessary IDN conversion of hostname
  */
-static void fix_hostname(struct connectdata *conn, struct hostname *host)
+static void fix_hostname(struct Curl_easy *data,
+                         struct connectdata *conn, struct hostname *host)
 {
   size_t len;
-  struct Curl_easy *data = conn->data;
 
-#ifndef USE_LIBIDN2
+#ifndef USE_LIBIDN
   (void)data;
   (void)conn;
 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -4040,26 +3833,25 @@ static void fix_hostname(struct connectdata *conn, struct hostname *host)
 
   /* Check name for non-ASCII and convert hostname to ACE form if we can */
   if(!is_ASCII_name(host->name)) {
-#ifdef USE_LIBIDN2
-    if(idn2_check_version(IDN2_VERSION)) {
+#ifdef USE_LIBIDN
+    if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
       char *ace_hostname = NULL;
-#if IDN2_VERSION_NUMBER >= 0x00140000
-      /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
-         IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
-         processing. */
-      int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
-#else
-      int flags = IDN2_NFC_INPUT;
-#endif
-      int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags);
-      if(rc == IDN2_OK) {
-        host->encalloc = (char *)ace_hostname;
+
+      int rc = idna_to_ascii_lz(host->name, &ace_hostname, 0);
+      infof(data, "Input domain encoded as `%s'\n",
+            stringprep_locale_charset());
+      if(rc == IDNA_SUCCESS) {
+        /* tld_check_name() displays a warning if the host name contains
+           "illegal" characters for this TLD */
+        (void)tld_check_name(data, ace_hostname);
+
+        host->encalloc = ace_hostname;
         /* change the name pointer to point to the encoded hostname */
         host->name = host->encalloc;
       }
       else
         infof(data, "Failed to convert %s to ACE; %s\n", host->name,
-              idn2_strerror(rc));
+              Curl_idn_strerror(conn, rc));
     }
 #elif defined(USE_WIN32_IDN)
     char *ace_hostname = NULL;
@@ -4082,9 +3874,9 @@ static void fix_hostname(struct connectdata *conn, struct hostname *host)
  */
 static void free_fixed_hostname(struct hostname *host)
 {
-#if defined(USE_LIBIDN2)
+#if defined(USE_LIBIDN)
   if(host->encalloc) {
-    idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
+    idn_free(host->encalloc); /* must be freed with idn_free() since this was
                                  allocated by libidn */
     host->encalloc = NULL;
   }
@@ -4125,7 +3917,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
   conn->connection_id = -1;    /* no ID */
   conn->port = -1; /* unknown at this point */
-  conn->remote_port = -1; /* unknown at this point */
+  conn->remote_port = -1; /* unknown */
 #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
   conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
   conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
@@ -4142,14 +3934,12 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->data = data; /* Setup the association between this connection
                         and the Curl_easy */
 
-  conn->http_proxy.proxytype = data->set.proxytype;
-  conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
+  conn->proxytype = data->set.proxytype; /* type */
 
 #ifdef CURL_DISABLE_PROXY
 
   conn->bits.proxy = FALSE;
   conn->bits.httpproxy = FALSE;
-  conn->bits.socksproxy = FALSE;
   conn->bits.proxy_user_passwd = FALSE;
   conn->bits.tunnel_proxy = FALSE;
 
@@ -4160,20 +3950,11 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->bits.proxy = (data->set.str[STRING_PROXY] &&
                       *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
   conn->bits.httpproxy = (conn->bits.proxy &&
-                          (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
-                           conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
-                           conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
-                           TRUE : FALSE;
-  conn->bits.socksproxy = (conn->bits.proxy &&
-                           !conn->bits.httpproxy) ? TRUE : FALSE;
-
-  if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
-    conn->bits.proxy = TRUE;
-    conn->bits.socksproxy = TRUE;
-  }
-
-  conn->bits.proxy_user_passwd =
-    (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
+                          (conn->proxytype == CURLPROXY_HTTP ||
+                           conn->proxytype == CURLPROXY_HTTP_1_0)) ?
+                          TRUE : FALSE;
+  conn->bits.proxy_user_passwd = (data->set.str[STRING_PROXYUSERNAME]) ?
+                                 TRUE : FALSE;
   conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
 
 #endif /* CURL_DISABLE_PROXY */
@@ -4182,13 +3963,8 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
 
-  conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
-  conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
-  conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
-  conn->proxy_ssl_config.verifystatus =
-    data->set.proxy_ssl.primary.verifystatus;
-  conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
-  conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
+  conn->verifypeer = data->set.ssl.verifypeer;
+  conn->verifyhost = data->set.ssl.verifyhost;
 
   conn->ip_version = data->set.ipver;
 
@@ -4203,7 +3979,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
      !conn->master_buffer) {
     /* Allocate master_buffer to be used for HTTP/1 pipelining */
-    conn->master_buffer = calloc(BUFSIZE, sizeof(char));
+    conn->master_buffer = calloc(BUFSIZE, sizeof (char));
     if(!conn->master_buffer)
       goto error;
   }
@@ -4258,7 +4034,7 @@ static CURLcode findprotocol(struct Curl_easy *data,
      variables based on the URL. Now that the handler may be changed later
      when the protocol specific setup function is called. */
   for(pp = protocols; (p = *pp) != NULL; pp++) {
-    if(strcasecompare(p->scheme, protostr)) {
+    if(Curl_raw_equal(p->scheme, protostr)) {
       /* Protocol found in table. Check if allowed */
       if(!(data->set.allowed_protocols & p->protocol))
         /* nope, get out */
@@ -4302,13 +4078,11 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   char *fragment;
   char *path = data->state.path;
   char *query;
-  int i;
   int rc;
+  char protobuf[16] = "";
   const char *protop = "";
   CURLcode result;
   bool rebuild_url = FALSE;
-  bool url_has_scheme = FALSE;
-  char protobuf[16];
 
   *prot_missing = FALSE;
 
@@ -4327,47 +4101,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
    * proxy -- and we don't know if we will need to use SSL until we parse the
    * url ...
    ************************************************************/
-  if(data->change.url[0] == ':') {
-    failf(data, "Bad URL, colon is first character");
-    return CURLE_URL_MALFORMAT;
-  }
-
-  /* Make sure we don't mistake a drive letter for a scheme, for example:
-     curld --proto-default file c:/foo/bar.txt */
-  if((('a' <= data->change.url[0] && data->change.url[0] <= 'z') ||
-      ('A' <= data->change.url[0] && data->change.url[0] <= 'Z')) &&
-     data->change.url[1] == ':' && data->set.str[STRING_DEFAULT_PROTOCOL] &&
-     strcasecompare(data->set.str[STRING_DEFAULT_PROTOCOL], "file")) {
-    ; /* do nothing */
-  }
-  else { /* check for a scheme */
-    for(i = 0; i < 16 && data->change.url[i]; ++i) {
-      if(data->change.url[i] == '/')
-        break;
-      if(data->change.url[i] == ':') {
-        url_has_scheme = TRUE;
-        break;
-      }
-    }
-  }
-
-  /* handle the file: scheme */
-  if((url_has_scheme && strncasecompare(data->change.url, "file:", 5)) ||
-     (!url_has_scheme && data->set.str[STRING_DEFAULT_PROTOCOL] &&
-      strcasecompare(data->set.str[STRING_DEFAULT_PROTOCOL], "file"))) {
-    bool path_has_drive = FALSE;
-
-    if(url_has_scheme)
-      rc = sscanf(data->change.url, "%*15[^\n/:]:%[^\n]", path);
-    else
-      rc = sscanf(data->change.url, "%[^\n]", path);
-
-    if(rc != 1) {
-      failf(data, "Bad URL");
-      return CURLE_URL_MALFORMAT;
-    }
-
-    if(url_has_scheme && path[0] == '/' && path[1] == '/') {
+  if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
+                  protobuf, path)) &&
+     Curl_raw_equal(protobuf, "file")) {
+    if(path[0] == '/' && path[1] == '/') {
       /* Allow omitted hostname (e.g. file:/<path>).  This is not strictly
        * speaking a valid file: URL by RFC 1738, but treating file:/<path> as
        * file://localhost/<path> is similar to how other schemes treat missing
@@ -4377,62 +4114,40 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
          memory areas overlap! */
       memmove(path, path + 2, strlen(path + 2)+1);
     }
-
-    /* the path may start with a drive letter. for backwards compatibility
-       we skip some processing on those paths. */
-    path_has_drive = (('a' <= path[0] && path[0] <= 'z') ||
-                      ('A' <= path[0] && path[0] <= 'Z')) && path[1] == ':';
-
     /*
      * we deal with file://<host>/<path> differently since it supports no
      * hostname other than "localhost" and "127.0.0.1", which is unique among
      * the URL protocols specified in RFC 1738
      */
-    if(path[0] != '/' && !path_has_drive) {
-      /* the URL includes a host name, it must match "localhost" or
-         "127.0.0.1" to be valid */
-      char *ptr;
-      if(!checkprefix("localhost/", path) &&
-         !checkprefix("127.0.0.1/", path)) {
-        failf(data, "Invalid file://hostname/, "
-                    "expected localhost or 127.0.0.1 or none");
-        return CURLE_URL_MALFORMAT;
-      }
-      ptr = &path[9]; /* now points to the slash after the host */
+    if(path[0] != '/') {
+      /* the URL included a host name, we ignore host names in file:// URLs
+         as the standards don't define what to do with them */
+      char *ptr=strchr(path, '/');
+      if(ptr) {
+        /* there was a slash present
 
-      /* there was a host name and slash present
+           RFC1738 (section 3.1, page 5) says:
 
-         RFC1738 (section 3.1, page 5) says:
+           The rest of the locator consists of data specific to the scheme,
+           and is known as the "url-path". It supplies the details of how the
+           specified resource can be accessed. Note that the "/" between the
+           host (or port) and the url-path is NOT part of the url-path.
 
-         The rest of the locator consists of data specific to the scheme,
-         and is known as the "url-path". It supplies the details of how the
-         specified resource can be accessed. Note that the "/" between the
-         host (or port) and the url-path is NOT part of the url-path.
-
-         As most agents use file://localhost/foo to get '/foo' although the
-         slash preceding foo is a separator and not a slash for the path,
-         a URL as file://localhost//foo must be valid as well, to refer to
-         the same file with an absolute path.
-      */
-
-      if('/' == ptr[1])
-        /* if there was two slashes, we skip the first one as that is then
-           used truly as a separator */
-        ptr++;
+           As most agents use file://localhost/foo to get '/foo' although the
+           slash preceding foo is a separator and not a slash for the path,
+           a URL as file://localhost//foo must be valid as well, to refer to
+           the same file with an absolute path.
+        */
 
-      /* This cannot be made with strcpy, as the memory chunks overlap! */
-      memmove(path, ptr, strlen(ptr)+1);
+        if(ptr[1] && ('/' == ptr[1]))
+          /* if there was two slashes, we skip the first one as that is then
+             used truly as a separator */
+          ptr++;
 
-      path_has_drive = (('a' <= path[0] && path[0] <= 'z') ||
-                        ('A' <= path[0] && path[0] <= 'Z')) && path[1] == ':';
-    }
-
-#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
-    if(path_has_drive) {
-      failf(data, "File drive letters are only accepted in MSDOS/Windows.");
-      return CURLE_URL_MALFORMAT;
+        /* This cannot be made with strcpy, as the memory chunks overlap! */
+        memmove(path, ptr, strlen(ptr)+1);
+      }
     }
-#endif
 
     protop = "file"; /* protocol string */
   }
@@ -4442,7 +4157,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
     path[0]=0;
 
     rc = sscanf(data->change.url,
-                "%15[^\n/:]:%3[/]%[^\n/?#]%[^\n]",
+                "%15[^\n:]:%3[/]%[^\n/?]%[^\n]",
                 protobuf, slashbuf, conn->host.name, path);
     if(2 == rc) {
       failf(data, "Bad URL");
@@ -4454,7 +4169,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
        * The URL was badly formatted, let's try the browser-style _without_
        * protocol specified like 'http://'.
        */
-      rc = sscanf(data->change.url, "%[^\n/?#]%[^\n]", conn->host.name, path);
+      rc = sscanf(data->change.url, "%[^\n/?]%[^\n]", conn->host.name, path);
       if(1 > rc) {
         /*
          * We couldn't even get this format.
@@ -4559,10 +4274,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   }
 
   /* If the URL is malformatted (missing a '/' after hostname before path) we
-   * insert a slash here. The only letters except '/' that can start a path is
-   * '?' and '#' - as controlled by the two sscanf() patterns above.
+   * insert a slash here. The only letter except '/' we accept to start a path
+   * is '?'.
    */
-  if(path[0] != '/') {
+  if(path[0] == '?') {
     /* We need this function to deal with overlapping memory areas. We know
        that the memory area 'path' points to is 'urllen' bytes big and that
        is bigger than the path. Use +1 to move the zero byte too. */
@@ -4627,10 +4342,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
     data->change.url_alloc = TRUE; /* free this later */
   }
 
-  result = findprotocol(data, conn, protop);
-  if(result)
-    return result;
-
   /*
    * Parse the login details from the URL and strip them out of
    * the host name
@@ -4717,7 +4428,8 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
    *   conn->host.name is B
    *   data->state.path is /C
    */
-  return CURLE_OK;
+
+  return findprotocol(data, conn, protop);
 }
 
 /*
@@ -4816,7 +4528,7 @@ void Curl_free_request_state(struct Curl_easy *data)
 * Checks if the host is in the noproxy list. returns true if it matches
 * and therefore the proxy should NOT be used.
 ****************************************************************/
-static bool check_noproxy(const char *name, const char *no_proxy)
+static bool check_noproxy(const char* name, const char* no_proxy)
 {
   /* no_proxy=domain1.dom,host.domain2.dom
    *   (a comma-separated list of hosts which should
@@ -4825,13 +4537,13 @@ static bool check_noproxy(const char *name, const char *no_proxy)
    */
   size_t tok_start;
   size_t tok_end;
-  const char *separator = ", ";
+  const charseparator = ", ";
   size_t no_proxy_len;
   size_t namelen;
   char *endptr;
 
   if(no_proxy && no_proxy[0]) {
-    if(strcasecompare("*", no_proxy)) {
+    if(Curl_raw_equal("*", no_proxy)) {
       return TRUE;
     }
 
@@ -4869,7 +4581,7 @@ static bool check_noproxy(const char *name, const char *no_proxy)
       if((tok_end - tok_start) <= namelen) {
         /* Match the last part of the name to the domain we are checking. */
         const char *checkn = name + namelen - (tok_end - tok_start);
-        if(strncasecompare(no_proxy + tok_start, checkn,
+        if(Curl_raw_nequal(no_proxy + tok_start, checkn,
                            tok_end - tok_start)) {
           if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
             /* We either have an exact match, or the previous character is a .
@@ -4895,6 +4607,7 @@ static char *detect_proxy(struct connectdata *conn)
 {
   char *proxy = NULL;
 
+#ifndef CURL_DISABLE_HTTP
   /* If proxy was not specified, we check for default proxy environment
    * variables, to enable i.e Lynx compliance:
    *
@@ -4912,46 +4625,62 @@ static char *detect_proxy(struct connectdata *conn)
    * For compatibility, the all-uppercase versions of these variables are
    * checked if the lowercase versions don't exist.
    */
+  char *no_proxy=NULL;
   char proxy_env[128];
-  const char *protop = conn->handler->scheme;
-  char *envp = proxy_env;
-  char *prox;
 
-  /* Now, build <protocol>_proxy and check for such a one to use */
-  while(*protop)
-    *envp++ = (char)tolower((int)*protop++);
+  no_proxy=curl_getenv("no_proxy");
+  if(!no_proxy)
+    no_proxy=curl_getenv("NO_PROXY");
+
+  if(!check_noproxy(conn->host.name, no_proxy)) {
+    /* It was not listed as without proxy */
+    const char *protop = conn->handler->scheme;
+    char *envp = proxy_env;
+    char *prox;
 
-  /* append _proxy */
-  strcpy(envp, "_proxy");
+    /* Now, build <protocol>_proxy and check for such a one to use */
+    while(*protop)
+      *envp++ = (char)tolower((int)*protop++);
 
-  /* read the protocol proxy: */
-  prox=curl_getenv(proxy_env);
+    /* append _proxy */
+    strcpy(envp, "_proxy");
 
-  /*
-   * We don't try the uppercase version of HTTP_PROXY because of
-   * security reasons:
-   *
-   * When curl is used in a webserver application
-   * environment (cgi or php), this environment variable can
-   * be controlled by the web server user by setting the
-   * http header 'Proxy:' to some value.
-   *
-   * This can cause 'internal' http/ftp requests to be
-   * arbitrarily redirected by any external attacker.
-   */
-  if(!prox && !strcasecompare("http_proxy", proxy_env)) {
-    /* There was no lowercase variable, try the uppercase version: */
-    Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
+    /* read the protocol proxy: */
     prox=curl_getenv(proxy_env);
-  }
 
-  if(prox)
-    proxy = prox; /* use this */
-  else {
-    proxy = curl_getenv("all_proxy"); /* default proxy to use */
-    if(!proxy)
-      proxy=curl_getenv("ALL_PROXY");
-  }
+    /*
+     * We don't try the uppercase version of HTTP_PROXY because of
+     * security reasons:
+     *
+     * When curl is used in a webserver application
+     * environment (cgi or php), this environment variable can
+     * be controlled by the web server user by setting the
+     * http header 'Proxy:' to some value.
+     *
+     * This can cause 'internal' http/ftp requests to be
+     * arbitrarily redirected by any external attacker.
+     */
+    if(!prox && !Curl_raw_equal("http_proxy", proxy_env)) {
+      /* There was no lowercase variable, try the uppercase version: */
+      Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
+      prox=curl_getenv(proxy_env);
+    }
+
+    if(prox)
+      proxy = prox; /* use this */
+    else {
+      proxy = curl_getenv("all_proxy"); /* default proxy to use */
+      if(!proxy)
+        proxy=curl_getenv("ALL_PROXY");
+    }
+  } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified
+       non-proxy */
+  free(no_proxy);
+
+#else /* !CURL_DISABLE_HTTP */
+
+  (void)conn;
+#endif /* CURL_DISABLE_HTTP */
 
   return proxy;
 }
@@ -4962,8 +4691,7 @@ static char *detect_proxy(struct connectdata *conn)
  * that may exist registered to the same proxy host.
  */
 static CURLcode parse_proxy(struct Curl_easy *data,
-                            struct connectdata *conn, char *proxy,
-                            curl_proxytype proxytype)
+                            struct connectdata *conn, char *proxy)
 {
   char *prox_portno;
   char *endofprot;
@@ -4972,10 +4700,6 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   char *proxyptr;
   char *portptr;
   char *atsign;
-  long port = -1;
-  char *proxyuser = NULL;
-  char *proxypasswd = NULL;
-  bool sockstype;
 
   /* We do the proxy host string parsing here. We want the host name and the
    * port name. Accept a protocol:// prefix
@@ -4985,16 +4709,14 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   endofprot = strstr(proxy, "://");
   if(endofprot) {
     proxyptr = endofprot+3;
-    if(checkprefix("https", proxy))
-      proxytype = CURLPROXY_HTTPS;
-    else if(checkprefix("socks5h", proxy))
-      proxytype = CURLPROXY_SOCKS5_HOSTNAME;
+    if(checkprefix("socks5h", proxy))
+      conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
     else if(checkprefix("socks5", proxy))
-      proxytype = CURLPROXY_SOCKS5;
+      conn->proxytype = CURLPROXY_SOCKS5;
     else if(checkprefix("socks4a", proxy))
-      proxytype = CURLPROXY_SOCKS4A;
+      conn->proxytype = CURLPROXY_SOCKS4A;
     else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
-      proxytype = CURLPROXY_SOCKS4;
+      conn->proxytype = CURLPROXY_SOCKS4;
     else if(checkprefix("http:", proxy))
       ; /* leave it as HTTP or HTTP/1.0 */
     else {
@@ -5006,28 +4728,51 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   else
     proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
 
-#ifndef HTTPS_PROXY_SUPPORT
-  if(proxytype == CURLPROXY_HTTPS) {
-    failf(data, "Unsupported proxy \'%s\'"
-                ", libcurl is built without the HTTPS-proxy support.", proxy);
-    return CURLE_NOT_BUILT_IN;
-  }
-#endif
-
-  sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
-              proxytype == CURLPROXY_SOCKS5 ||
-              proxytype == CURLPROXY_SOCKS4A ||
-              proxytype == CURLPROXY_SOCKS4;
-
   /* Is there a username and password given in this proxy url? */
   atsign = strchr(proxyptr, '@');
   if(atsign) {
+    char *proxyuser = NULL;
+    char *proxypasswd = NULL;
     CURLcode result =
       parse_login_details(proxyptr, atsign - proxyptr,
-                              &proxyuser, &proxypasswd, NULL);
+                          &proxyuser, &proxypasswd, NULL);
+    if(!result) {
+      /* found user and password, rip them out.  note that we are
+         unescaping them, as there is otherwise no way to have a
+         username or password with reserved characters like ':' in
+         them. */
+      Curl_safefree(conn->proxyuser);
+      if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
+        conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
+      else
+        conn->proxyuser = strdup("");
+
+      if(!conn->proxyuser)
+        result = CURLE_OUT_OF_MEMORY;
+      else {
+        Curl_safefree(conn->proxypasswd);
+        if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
+          conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
+        else
+          conn->proxypasswd = strdup("");
+
+        if(!conn->proxypasswd)
+          result = CURLE_OUT_OF_MEMORY;
+      }
+
+      if(!result) {
+        conn->bits.proxy_user_passwd = TRUE; /* enable it */
+        atsign++; /* the right side of the @-letter */
+
+        proxyptr = atsign; /* now use this instead */
+      }
+    }
+
+    free(proxyuser);
+    free(proxypasswd);
+
     if(result)
       return result;
-    proxyptr = atsign + 1;
   }
 
   /* start scanning for port number at this point */
@@ -5064,7 +4809,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   prox_portno = strchr(portptr, ':');
   if(prox_portno) {
     char *endp = NULL;
-
+    long port = 0;
     *prox_portno = 0x0; /* cut off number from host name */
     prox_portno ++;
     /* now set the local port number */
@@ -5098,59 +4843,15 @@ static CURLcode parse_proxy(struct Curl_easy *data,
     if(data->set.proxyport)
       /* None given in the proxy string, then get the default one if it is
          given */
-      port = data->set.proxyport;
-    else {
-      if(proxytype == CURLPROXY_HTTPS)
-        port = CURL_DEFAULT_HTTPS_PROXY_PORT;
-      else
-        port = CURL_DEFAULT_PROXY_PORT;
-    }
+      conn->port = data->set.proxyport;
   }
 
-  if(*proxyptr) {
-    struct proxy_info *proxyinfo =
-      sockstype ? &conn->socks_proxy : &conn->http_proxy;
-    proxyinfo->proxytype = proxytype;
-
-    if(proxyuser) {
-      /* found user and password, rip them out.  note that we are unescaping
-         them, as there is otherwise no way to have a username or password
-         with reserved characters like ':' in them. */
-      Curl_safefree(proxyinfo->user);
-      proxyinfo->user = curl_easy_unescape(data, proxyuser, 0, NULL);
-
-      if(!proxyinfo->user)
-        return CURLE_OUT_OF_MEMORY;
-
-      Curl_safefree(proxyinfo->passwd);
-      if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
-        proxyinfo->passwd = curl_easy_unescape(data, proxypasswd, 0, NULL);
-      else
-        proxyinfo->passwd = strdup("");
-
-      if(!proxyinfo->passwd)
-        return CURLE_OUT_OF_MEMORY;
+  /* now, clone the cleaned proxy host name */
+  conn->proxy.rawalloc = strdup(proxyptr);
+  conn->proxy.name = conn->proxy.rawalloc;
 
-      conn->bits.proxy_user_passwd = TRUE; /* enable it */
-    }
-
-    if(port >= 0) {
-      proxyinfo->port = port;
-      if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
-        conn->port = port;
-    }
-
-    /* now, clone the cleaned proxy host name */
-    Curl_safefree(proxyinfo->host.rawalloc);
-    proxyinfo->host.rawalloc = strdup(proxyptr);
-    proxyinfo->host.name = proxyinfo->host.rawalloc;
-
-    if(!proxyinfo->host.rawalloc)
-      return CURLE_OUT_OF_MEMORY;
-  }
-
-  Curl_safefree(proxyuser);
-  Curl_safefree(proxypasswd);
+  if(!conn->proxy.rawalloc)
+    return CURLE_OUT_OF_MEMORY;
 
   return CURLE_OK;
 }
@@ -5163,7 +4864,6 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
 {
   char proxyuser[MAX_CURL_USER_LENGTH]="";
   char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
-  CURLcode result;
 
   if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
     strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
@@ -5176,12 +4876,15 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
     proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
   }
 
-  result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
-                          FALSE);
-  if(!result)
-    result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
-                            NULL, FALSE);
-  return result;
+  conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
+  if(!conn->proxyuser)
+    return CURLE_OUT_OF_MEMORY;
+
+  conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
+  if(!conn->proxypasswd)
+    return CURLE_OUT_OF_MEMORY;
+
+  return CURLE_OK;
 }
 #endif /* CURL_DISABLE_PROXY */
 
@@ -5223,7 +4926,6 @@ static CURLcode parse_url_login(struct Curl_easy *data,
   DEBUGASSERT(!**user);
   DEBUGASSERT(!**passwd);
   DEBUGASSERT(!**options);
-  DEBUGASSERT(conn->handler);
 
   if(!ptr)
     goto out;
@@ -5242,12 +4944,9 @@ static CURLcode parse_url_login(struct Curl_easy *data,
   if(data->set.use_netrc == CURL_NETRC_REQUIRED)
     goto out;
 
-  /* We could use the login information in the URL so extract it. Only parse
-     options if the handler says we should. */
+  /* We could use the login information in the URL so extract it */
   result = parse_login_details(login, ptr - login - 1,
-                               &userp, &passwdp,
-                               (conn->handler->flags & PROTOPT_URLOPTIONS)?
-                               &optionsp:NULL);
+                               &userp, &passwdp, &optionsp);
   if(result)
     goto out;
 
@@ -5259,8 +4958,9 @@ static CURLcode parse_url_login(struct Curl_easy *data,
     conn->bits.user_passwd = TRUE; /* enable user+password */
 
     /* Decode the user */
-    result = Curl_urldecode(data, userp, 0, &newname, NULL, FALSE);
-    if(result) {
+    newname = curl_easy_unescape(data, userp, 0, NULL);
+    if(!newname) {
+      result = CURLE_OUT_OF_MEMORY;
       goto out;
     }
 
@@ -5270,9 +4970,9 @@ static CURLcode parse_url_login(struct Curl_easy *data,
 
   if(passwdp) {
     /* We have a password in the URL so decode it */
-    char *newpasswd;
-    result = Curl_urldecode(data, passwdp, 0, &newpasswd, NULL, FALSE);
-    if(result) {
+    char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
+    if(!newpasswd) {
+      result = CURLE_OUT_OF_MEMORY;
       goto out;
     }
 
@@ -5282,9 +4982,9 @@ static CURLcode parse_url_login(struct Curl_easy *data,
 
   if(optionsp) {
     /* We have an options list in the URL so decode it */
-    char *newoptions;
-    result = Curl_urldecode(data, optionsp, 0, &newoptions, NULL, FALSE);
-    if(result) {
+    char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
+    if(!newoptions) {
+      result = CURLE_OUT_OF_MEMORY;
       goto out;
     }
 
@@ -5536,16 +5236,11 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
       *portptr = '\0'; /* cut off the name there */
       conn->remote_port = curlx_ultous(port);
     }
-    else {
-      if(rest[0]) {
-        failf(data, "Illegal port number");
-        return CURLE_URL_MALFORMAT;
-      }
+    else
       /* Browser behavior adaptation. If there's a colon with no digits after,
          just cut off the name there which makes us ignore the colon and just
          use the default port. Firefox and Chrome both do that. */
       *portptr = '\0';
-    }
   }
 
   /* only if remote_port was not already parsed off the URL we use the
@@ -5674,10 +5369,6 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
   char *portptr;
   int port = -1;
 
-#if defined(CURL_DISABLE_VERBOSE_STRINGS)
-  (void) data;
-#endif
-
   *hostname_result = NULL;
   *port_result = -1;
 
@@ -5769,9 +5460,6 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
   int host_match = FALSE;
   int port_match = FALSE;
 
-  *host_result = NULL;
-  *port_result = -1;
-
   if(*ptr == ':') {
     /* an empty hostname always matches */
     host_match = TRUE;
@@ -5787,8 +5475,7 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
     if(!hostname_to_match)
       return CURLE_OUT_OF_MEMORY;
     hostname_to_match_len = strlen(hostname_to_match);
-    host_match = strncasecompare(ptr, hostname_to_match,
-                                 hostname_to_match_len);
+    host_match = curl_strnequal(ptr, hostname_to_match, hostname_to_match_len);
     free(hostname_to_match);
     ptr += hostname_to_match_len;
 
@@ -5834,25 +5521,28 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
 {
   CURLcode result = CURLE_OK;
   char *host = NULL;
-  int port = -1;
+  int port = 0;
 
-  while(conn_to_host && !host && port == -1) {
+  while(conn_to_host && !host) {
     result = parse_connect_to_string(data, conn, conn_to_host->data,
                                      &host, &port);
     if(result)
       return result;
 
     if(host && *host) {
+      bool ipv6host;
       conn->conn_to_host.rawalloc = host;
       conn->conn_to_host.name = host;
       conn->bits.conn_to_host = TRUE;
 
-      infof(data, "Connecting to hostname: %s\n", host);
+      ipv6host = strchr(host, ':') != NULL;
+      infof(data, "Connecting to hostname: %s%s%s\n",
+            ipv6host ? "[" : "", host, ipv6host ? "]" : "");
     }
     else {
       /* no "connect to host" */
       conn->bits.conn_to_host = FALSE;
-      Curl_safefree(host);
+      free(host);
     }
 
     if(port >= 0) {
@@ -5863,7 +5553,6 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
     else {
       /* no "connect to port" */
       conn->bits.conn_to_port = FALSE;
-      port = -1;
     }
 
     conn_to_host = conn_to_host->next;
@@ -5880,7 +5569,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
                                bool *async)
 {
   CURLcode result=CURLE_OK;
-  time_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
+  long timeout_ms = Curl_timeleft(data, NULL, TRUE);
 
   /*************************************************************
    * Resolve the name of the server or proxy
@@ -5897,37 +5586,32 @@ static CURLcode resolve_server(struct Curl_easy *data,
     struct Curl_dns_entry *hostaddr;
 
 #ifdef USE_UNIX_SOCKETS
-    if(conn->unix_domain_socket) {
+    if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
       /* Unix domain sockets are local. The host gets ignored, just use the
        * specified domain socket address. Do not cache "DNS entries". There is
        * no DNS involved and we already have the filesystem path available */
-      const char *path = conn->unix_domain_socket;
+      const char *path = data->set.str[STRING_UNIX_SOCKET_PATH];
 
       hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
       if(!hostaddr)
         result = CURLE_OUT_OF_MEMORY;
+      else if((hostaddr->addr = Curl_unix2addr(path)) != NULL)
+        hostaddr->inuse++;
       else {
-        bool longpath = FALSE;
-        hostaddr->addr = Curl_unix2addr(path, &longpath,
-                                        conn->abstract_unix_socket);
-        if(hostaddr->addr)
-          hostaddr->inuse++;
-        else {
-          /* Long paths are not supported for now */
-          if(longpath) {
-            failf(data, "Unix socket path too long: '%s'", path);
-            result = CURLE_COULDNT_RESOLVE_HOST;
-          }
-          else
-            result = CURLE_OUT_OF_MEMORY;
-          free(hostaddr);
-          hostaddr = NULL;
+        /* Long paths are not supported for now */
+        if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
+          failf(data, "Unix socket path too long: '%s'", path);
+          result = CURLE_COULDNT_RESOLVE_HOST;
         }
+        else
+          result = CURLE_OUT_OF_MEMORY;
+        free(hostaddr);
+        hostaddr = NULL;
       }
     }
     else
 #endif
-    if(!conn->bits.proxy) {
+    if(!conn->proxy.name || !*conn->proxy.name) {
       struct hostname *connhost;
       if(conn->bits.conn_to_host)
         connhost = &conn->conn_to_host;
@@ -5939,7 +5623,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
       if(conn->bits.conn_to_port)
         conn->port = conn->conn_to_port;
       else
-        conn->port = conn->remote_port;
+        conn->port = conn->remote_port; /* it is the same port */
 
       /* Resolve target host right on */
       rc = Curl_resolv_timeout(conn, connhost->name, (int)conn->port,
@@ -5959,11 +5643,8 @@ static CURLcode resolve_server(struct Curl_easy *data,
     else {
       /* This is a proxy that hasn't been resolved yet. */
 
-      struct hostname * const host = conn->bits.socksproxy ?
-        &conn->socks_proxy.host : &conn->http_proxy.host;
-
       /* resolve proxy */
-      rc = Curl_resolv_timeout(conn, host->name, (int)conn->port,
+      rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port,
                                &hostaddr, timeout_ms);
 
       if(rc == CURLRESOLV_PENDING)
@@ -5973,7 +5654,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
         result = CURLE_OPERATION_TIMEDOUT;
 
       else if(!hostaddr) {
-        failf(data, "Couldn't resolve proxy '%s'", host->dispname);
+        failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname);
         result = CURLE_COULDNT_RESOLVE_PROXY;
         /* don't return yet, we need to clean up the timeout first */
       }
@@ -5993,16 +5674,12 @@ static CURLcode resolve_server(struct Curl_easy *data,
 static void reuse_conn(struct connectdata *old_conn,
                        struct connectdata *conn)
 {
-  free_fixed_hostname(&old_conn->http_proxy.host);
-  free_fixed_hostname(&old_conn->socks_proxy.host);
-
-  free(old_conn->http_proxy.host.rawalloc);
-  free(old_conn->socks_proxy.host.rawalloc);
+  free_fixed_hostname(&old_conn->proxy);
+  free(old_conn->proxy.rawalloc);
 
   /* free the SSL config struct from this connection struct as this was
      allocated in vain and is targeted for destruction */
-  Curl_free_primary_ssl_config(&old_conn->ssl_config);
-  Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
+  Curl_free_ssl_config(&old_conn->ssl_config);
 
   conn->data = old_conn->data;
 
@@ -6022,18 +5699,12 @@ static void reuse_conn(struct connectdata *old_conn,
   conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
   if(conn->bits.proxy_user_passwd) {
     /* use the new proxy user name and proxy password though */
-    Curl_safefree(conn->http_proxy.user);
-    Curl_safefree(conn->socks_proxy.user);
-    Curl_safefree(conn->http_proxy.passwd);
-    Curl_safefree(conn->socks_proxy.passwd);
-    conn->http_proxy.user = old_conn->http_proxy.user;
-    conn->socks_proxy.user = old_conn->socks_proxy.user;
-    conn->http_proxy.passwd = old_conn->http_proxy.passwd;
-    conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
-    old_conn->http_proxy.user = NULL;
-    old_conn->socks_proxy.user = NULL;
-    old_conn->http_proxy.passwd = NULL;
-    old_conn->socks_proxy.passwd = NULL;
+    Curl_safefree(conn->proxyuser);
+    Curl_safefree(conn->proxypasswd);
+    conn->proxyuser = old_conn->proxyuser;
+    conn->proxypasswd = old_conn->proxypasswd;
+    old_conn->proxyuser = NULL;
+    old_conn->proxypasswd = NULL;
   }
 
   /* host can change, when doing keepalive with a proxy or if the case is
@@ -6059,10 +5730,8 @@ static void reuse_conn(struct connectdata *old_conn,
 
   Curl_safefree(old_conn->user);
   Curl_safefree(old_conn->passwd);
-  Curl_safefree(old_conn->http_proxy.user);
-  Curl_safefree(old_conn->socks_proxy.user);
-  Curl_safefree(old_conn->http_proxy.passwd);
-  Curl_safefree(old_conn->socks_proxy.passwd);
+  Curl_safefree(old_conn->proxyuser);
+  Curl_safefree(old_conn->proxypasswd);
   Curl_safefree(old_conn->localdev);
 
   Curl_llist_destroy(old_conn->send_pipe, NULL);
@@ -6072,10 +5741,6 @@ static void reuse_conn(struct connectdata *old_conn,
   old_conn->recv_pipe = NULL;
 
   Curl_safefree(old_conn->master_buffer);
-
-#ifdef USE_UNIX_SOCKETS
-  Curl_safefree(old_conn->unix_domain_socket);
-#endif
 }
 
 /**
@@ -6107,8 +5772,6 @@ static CURLcode create_conn(struct Curl_easy *data,
   char *options = NULL;
   bool reuse;
   char *proxy = NULL;
-  char *socksproxy = NULL;
-  char *no_proxy = NULL;
   bool prot_missing = FALSE;
   bool connections_available = TRUE;
   bool force_reuse = FALSE;
@@ -6275,48 +5938,18 @@ static CURLcode create_conn(struct Curl_easy *data,
     }
   }
 
-  if(data->set.str[STRING_PRE_PROXY]) {
-    socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
-    /* if global socks proxy is set, this is it */
-    if(NULL == socksproxy) {
-      failf(data, "memory shortage");
-      result = CURLE_OUT_OF_MEMORY;
-      goto out;
-    }
-  }
-
-  no_proxy = curl_getenv("no_proxy");
-  if(!no_proxy)
-    no_proxy = curl_getenv("NO_PROXY");
-
-  if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY]) ||
-     (!data->set.str[STRING_NOPROXY] &&
-      check_noproxy(conn->host.name, no_proxy))) {
-    Curl_safefree(proxy);
-    Curl_safefree(socksproxy);
+  if(data->set.str[STRING_NOPROXY] &&
+     check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
+    free(proxy);  /* proxy is in exception list */
+    proxy = NULL;
   }
-  else if(!proxy && !socksproxy)
-#ifndef CURL_DISABLE_HTTP
-    /* if the host is not in the noproxy list, detect proxy. */
+  else if(!proxy)
     proxy = detect_proxy(conn);
-#else  /* !CURL_DISABLE_HTTP */
-    proxy = NULL;
-#endif /* CURL_DISABLE_HTTP */
-
-  Curl_safefree(no_proxy);
 
 #ifdef USE_UNIX_SOCKETS
-  if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
-    if(proxy) {
-      free(proxy); /* Unix domain sockets cannot be proxied, so disable it */
-      proxy = NULL;
-    }
-    conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
-    if(conn->unix_domain_socket == NULL) {
-      result = CURLE_OUT_OF_MEMORY;
-      goto out;
-    }
-    conn->abstract_unix_socket = data->set.abstract_unix_socket;
+  if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) {
+    free(proxy);  /* Unix domain sockets cannot be proxied, so disable it */
+    proxy = NULL;
   }
 #endif
 
@@ -6325,36 +5958,23 @@ static CURLcode create_conn(struct Curl_easy *data,
                      protocol doesn't work with network */
     proxy = NULL;
   }
-  if(socksproxy && (!*socksproxy ||
-                    (conn->handler->flags & PROTOPT_NONETWORK))) {
-    free(socksproxy);  /* Don't bother with an empty socks proxy string or if
-                          the protocol doesn't work with network */
-    socksproxy = NULL;
-  }
 
   /***********************************************************************
    * If this is supposed to use a proxy, we need to figure out the proxy host
    * name, proxy type and port number, so that we can re-use an existing
    * connection that may exist registered to the same proxy host.
    ***********************************************************************/
-  if(proxy || socksproxy) {
-    if(proxy) {
-      result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
-      Curl_safefree(proxy); /* parse_proxy copies the proxy string */
-      if(result)
-        goto out;
-    }
+  if(proxy) {
+    result = parse_proxy(data, conn, proxy);
 
-    if(socksproxy) {
-      result = parse_proxy(data, conn, socksproxy,
-                           conn->socks_proxy.proxytype);
-      /* parse_proxy copies the socks proxy string */
-      Curl_safefree(socksproxy);
-      if(result)
-        goto out;
-    }
+    free(proxy); /* parse_proxy copies the proxy string */
+    proxy = NULL;
 
-    if(conn->http_proxy.host.rawalloc) {
+    if(result)
+      goto out;
+
+    if((conn->proxytype == CURLPROXY_HTTP) ||
+       (conn->proxytype == CURLPROXY_HTTP_1_0)) {
 #ifdef CURL_DISABLE_HTTP
       /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
       result = CURLE_UNSUPPORTED_PROTOCOL;
@@ -6373,34 +5993,12 @@ static CURLcode create_conn(struct Curl_easy *data,
       conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
       conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
     }
-
-    if(conn->socks_proxy.host.rawalloc) {
-      if(!conn->http_proxy.host.rawalloc) {
-        /* once a socks proxy */
-        if(!conn->socks_proxy.user) {
-          conn->socks_proxy.user = conn->http_proxy.user;
-          conn->http_proxy.user = NULL;
-          Curl_safefree(conn->socks_proxy.passwd);
-          conn->socks_proxy.passwd = conn->http_proxy.passwd;
-          conn->http_proxy.passwd = NULL;
-        }
-      }
-      conn->bits.socksproxy = TRUE;
-    }
-    else
-      conn->bits.socksproxy = FALSE; /* not a socks proxy */
+    conn->bits.proxy = TRUE;
   }
   else {
-    conn->bits.socksproxy = FALSE;
-    conn->bits.httpproxy = FALSE;
-  }
-  conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
-
-  if(!conn->bits.proxy) {
     /* we aren't using the proxy after all... */
     conn->bits.proxy = FALSE;
     conn->bits.httpproxy = FALSE;
-    conn->bits.socksproxy = FALSE;
     conn->bits.proxy_user_passwd = FALSE;
     conn->bits.tunnel_proxy = FALSE;
   }
@@ -6441,20 +6039,18 @@ static CURLcode create_conn(struct Curl_easy *data,
   /*************************************************************
    * IDN-fix the hostnames
    *************************************************************/
-  fix_hostname(conn, &conn->host);
+  fix_hostname(data, conn, &conn->host);
   if(conn->bits.conn_to_host)
-    fix_hostname(conn, &conn->conn_to_host);
-  if(conn->bits.httpproxy)
-    fix_hostname(conn, &conn->http_proxy.host);
-  if(conn->bits.socksproxy)
-    fix_hostname(conn, &conn->socks_proxy.host);
+    fix_hostname(data, conn, &conn->conn_to_host);
+  if(conn->proxy.name && *conn->proxy.name)
+    fix_hostname(data, conn, &conn->proxy);
 
   /*************************************************************
    * Check whether the host and the "connect to host" are equal.
-   * Do this after the hostnames have been IDN-fixed.
+   * Do this after the hostnames have been IDN-fixed .
    *************************************************************/
   if(conn->bits.conn_to_host &&
-     strcasecompare(conn->conn_to_host.name, conn->host.name)) {
+      Curl_raw_equal(conn->conn_to_host.name, conn->host.name)) {
     conn->bits.conn_to_host = FALSE;
   }
 
@@ -6538,51 +6134,20 @@ static CURLcode create_conn(struct Curl_easy *data,
      that will be freed as part of the Curl_easy struct, but all cloned
      copies will be separately allocated.
   */
-  data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
-  data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
-  data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
-  data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
-  data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
-  data->set.proxy_ssl.primary.random_file =
-    data->set.str[STRING_SSL_RANDOM_FILE];
-  data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
-  data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
-  data->set.ssl.primary.cipher_list =
-    data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
-  data->set.proxy_ssl.primary.cipher_list =
-    data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
-
-  data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
-  data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
-  data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
-  data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
-  data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
-  data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
-  data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
-  data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
-  data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
-  data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
-  data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
-  data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
-  data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
-  data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
-  data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
-  data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
+  data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH];
+  data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE];
+  data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
+  data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+  data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
+  data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+  data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
+  data->set.ssl.clientcert = data->set.str[STRING_CERT];
 #ifdef USE_TLS_SRP
-  data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
-  data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
-  data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
-  data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
+  data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
+  data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
 #endif
 
-  if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
-     &conn->ssl_config)) {
-    result = CURLE_OUT_OF_MEMORY;
-    goto out;
-  }
-
-  if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
-                                    &conn->proxy_ssl_config)) {
+  if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
   }
@@ -6639,9 +6204,7 @@ static CURLcode create_conn(struct Curl_easy *data,
     infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
           conn->connection_id,
           conn->bits.proxy?"proxy":"host",
-          conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
-          conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
-                                       conn->host.dispname);
+          conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
   }
   else {
     /* We have decided that we want a new connection. However, we may not
@@ -6772,7 +6335,6 @@ static CURLcode create_conn(struct Curl_easy *data,
   free(options);
   free(passwd);
   free(user);
-  free(socksproxy);
   free(proxy);
   return result;
 }