Index: include/curl/curl.h
===================================================================
RCS file: /cvsroot/curl/curl/include/curl/curl.h,v
retrieving revision 1.335
diff -u -r1.335 curl.h
--- include/curl/curl.h	2 Dec 2007 23:38:24 -0000	1.335
+++ include/curl/curl.h	2 Jan 2008 02:07:00 -0000
@@ -512,6 +512,7 @@
 typedef enum {
   CURLPROXY_HTTP = 0,
   CURLPROXY_SOCKS4 = 4,
+  CURLPROXY_SOCKS4A = 41,
   CURLPROXY_SOCKS5 = 5
 } curl_proxytype;
 
@@ -958,7 +959,7 @@
   CINIT(SHARE, OBJECTPOINT, 100),
 
   /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
-     CURLPROXY_SOCKS4 and CURLPROXY_SOCKS5. */
+     CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
   CINIT(PROXYTYPE, LONG, 101),
 
   /* Set the Accept-Encoding string. Use this to tell a server you would like
Index: lib/ftp.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/ftp.c,v
retrieving revision 1.457
diff -u -r1.457 ftp.c
--- lib/ftp.c	8 Dec 2007 22:50:55 -0000	1.457
+++ lib/ftp.c	2 Jan 2008 02:07:04 -0000
@@ -1727,7 +1727,8 @@
 
           if(conn->bits.tunnel_proxy ||
               data->set.proxytype == CURLPROXY_SOCKS5 ||
-              data->set.proxytype == CURLPROXY_SOCKS4)
+              data->set.proxytype == CURLPROXY_SOCKS4 ||
+              data->set.proxytype == CURLPROXY_SOCKS4A)
             /* proxy tunnel -> use other host info because ip_addr_str is the
                proxy address not the ftp host */
             snprintf(newhost, sizeof(newhost), "%s", conn->host.name);
@@ -1781,7 +1782,8 @@
             conn->ip_addr_str);
       if(conn->bits.tunnel_proxy ||
           data->set.proxytype == CURLPROXY_SOCKS5 ||
-          data->set.proxytype == CURLPROXY_SOCKS4)
+          data->set.proxytype == CURLPROXY_SOCKS4 ||
+          data->set.proxytype == CURLPROXY_SOCKS4A)
         /* proxy tunnel -> use other host info because ip_addr_str is the
            proxy address not the ftp host */
         snprintf(newhost, sizeof(newhost), "%s", conn->host.name);
@@ -1886,7 +1888,11 @@
     break;
   case CURLPROXY_SOCKS4:
     result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
-                         SECONDARYSOCKET, conn);
+                         SECONDARYSOCKET, conn, false);
+    break;
+  case CURLPROXY_SOCKS4A:
+    result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
+                         SECONDARYSOCKET, conn, true);
     break;
   default:
     failf(data, "unknown proxytype option given");
Index: lib/socks.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/socks.c,v
retrieving revision 1.16
diff -u -r1.16 socks.c
--- lib/socks.c	5 Nov 2007 09:45:09 -0000	1.16
+++ lib/socks.c	2 Jan 2008 02:07:04 -0000
@@ -118,16 +118,18 @@
 *   http://socks.permeo.com/protocol/socks4.protocol
 *
 * Note :
-*   Nonsupport "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
+*   Set protocol4a=true for  "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
 *   Nonsupport "Identification Protocol (RFC1413)"
 */
 CURLcode Curl_SOCKS4(const char *proxy_name,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn)
+                     struct connectdata *conn,
+                     bool protocol4a)
 {
-  unsigned char socksreq[262]; /* room for SOCKS4 request incl. user id */
+  #define SOCKS4REQLEN 262
+  unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user id */
   int result;
   CURLcode code;
   curl_socket_t sock = conn->sock[sockindex];
@@ -165,8 +167,8 @@
   socksreq[1] = 1; /* connect */
   *((unsigned short*)&socksreq[2]) = htons((unsigned short)remote_port);
 
-  /* DNS resolve */
-  {
+  /* DNS resolve only for SOCKS4, not SOCKS4a */
+  if (!protocol4a) {
     struct Curl_dns_entry *dns;
     Curl_addrinfo *hp=NULL;
     int rc;
@@ -225,15 +227,39 @@
   {
     ssize_t actualread;
     ssize_t written;
+    ssize_t hostnamelen = 0;
     int packetsize = 9 +
       (int)strlen((char*)socksreq + 8); /* size including NUL */
 
+    /* If SOCKS4a, set special invalid IP address 0.0.0.x */
+    if (protocol4a) {
+      socksreq[4] = 0;
+      socksreq[5] = 0;
+      socksreq[6] = 0;
+      socksreq[7] = 1;
+      /* If still enough room in buffer, also append hostname */
+      hostnamelen = strlen(hostname) + 1; /* length including NUL */
+      if (packetsize + hostnamelen <= SOCKS4REQLEN)
+        strcpy((char*)socksreq + packetsize, hostname);
+      else
+        hostnamelen = 0; /* Flag: hostname did not fit in buffer */
+    }
+
     /* Send request */
-    code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
-    if((code != CURLE_OK) || (written != packetsize)) {
+    code = Curl_write(conn, sock, (char *)socksreq, packetsize + hostnamelen, &written);
+    if((code != CURLE_OK) || (written != packetsize + hostnamelen)) {
       failf(data, "Failed to send SOCKS4 connect request.");
       return CURLE_COULDNT_CONNECT;
     }
+    if (protocol4a && hostnamelen == 0) {
+      /* SOCKS4a with very long hostname - send that name separately */
+      hostnamelen = strlen(hostname) + 1;
+      code = Curl_write(conn, sock, (char *)hostname, hostnamelen, &written);
+      if((code != CURLE_OK) || (written != hostnamelen)) {
+        failf(data, "Failed to send SOCKS4 connect request.");
+        return CURLE_COULDNT_CONNECT;
+      }
+    }
 
     packetsize = 8; /* receive data size */
 
@@ -275,7 +301,10 @@
     switch(socksreq[1])
     {
     case 90:
-      infof(data, "SOCKS4 request granted.\n");
+      if (protocol4a)
+        infof(data, "SOCKS4a request granted.\n");
+      else
+        infof(data, "SOCKS4 request granted.\n");
       break;
     case 91:
       failf(data,
Index: lib/socks.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/socks.h,v
retrieving revision 1.5
diff -u -r1.5 socks.h
--- lib/socks.h	27 Aug 2007 06:31:28 -0000	1.5
+++ lib/socks.h	2 Jan 2008 02:07:04 -0000
@@ -24,14 +24,15 @@
  ***************************************************************************/
 
 /*
- * This function logs in to a SOCKS4 proxy and sends the specifics to the
+ * This function logs in to a SOCKS4(a) proxy and sends the specifics to the
  * final destination server.
  */
 CURLcode Curl_SOCKS4(const char *proxy_name,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn);
+                     struct connectdata *conn,
+                     bool protocol4a);
 
 /*
  * This function logs in to a SOCKS5 proxy and sends the specifics to the
Index: lib/url.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/url.c,v
retrieving revision 1.684
diff -u -r1.684 url.c
--- lib/url.c	26 Dec 2007 23:29:36 -0000	1.684
+++ lib/url.c	2 Jan 2008 02:07:08 -0000
@@ -1868,7 +1868,7 @@
 
   case CURLOPT_PROXYTYPE:
     /*
-     * Set proxy type. HTTP/SOCKS4/SOCKS5
+     * Set proxy type. HTTP/SOCKS4/SOCKS4a/SOCKS5
      */
     data->set.proxytype = (curl_proxytype)va_arg(param, long);
     break;
@@ -2644,7 +2644,11 @@
         break;
       case CURLPROXY_SOCKS4:
         result = Curl_SOCKS4(conn->proxyuser, conn->host.name, conn->remote_port,
-                             FIRSTSOCKET, conn);
+                             FIRSTSOCKET, conn, false);
+        break;
+      case CURLPROXY_SOCKS4A:
+        result = Curl_SOCKS4(conn->proxyuser, conn->host.name, conn->remote_port,
+                             FIRSTSOCKET, conn, true);
         break;
       default:
         failf(data, "unknown proxytype option given");
Index: src/main.c
===================================================================
RCS file: /cvsroot/curl/curl/src/main.c,v
retrieving revision 1.439
diff -u -r1.439 main.c
--- src/main.c	1 Jan 2008 21:11:27 -0000	1.439
+++ src/main.c	2 Jan 2008 02:07:13 -0000
@@ -712,6 +712,7 @@
     " -s/--silent        Silent mode. Don't output anything",
     " -S/--show-error    Show error. With -s, make curl show errors when they occur",
     "    --socks4 <host[:port]> Use SOCKS4 proxy on given host + port",
+    "    --socks4a <host[:port]> Use SOCKS4a proxy on given host + port",
     "    --socks5 <host[:port]> Use SOCKS5 proxy on given host + port",
     "    --stderr <file> Where to redirect stderr. - means stdout",
     " -t/--telnet-option <OPT=val> Set telnet option",
@@ -1532,6 +1533,7 @@
     {"$r", "ftp-method", TRUE},
     {"$s", "local-port", TRUE},
     {"$t", "socks4",     TRUE},
+    {"$T", "socks4a",    TRUE},
     {"$u", "ftp-alternative-to-user", TRUE},
     {"$v", "ftp-ssl-reqd", FALSE},
     {"$w", "no-sessionid", FALSE},
@@ -1906,6 +1908,10 @@
         GetStr(&config->socksproxy, nextarg);
         config->socksver = CURLPROXY_SOCKS4;
         break;
+      case 'T': /* --socks4a specifies a socks4a proxy to use */
+        GetStr(&config->socksproxy, nextarg);
+        config->socksver = CURLPROXY_SOCKS4A;
+        break;
       case 'd': /* --tcp-nodelay option */
         config->tcp_nodelay ^= TRUE;
         break;

