Quoting Zeev Suraski <[EMAIL PROTECTED]>:

> This change was my last major TODO item for PHP 4.0.7.  At this point,
> we
> should try to get PHP 4.0.7 out the door soon.  I suggest we branch
> 4.0.7
> away next Tuesday, and start the QA process.  This should give people
> enough time to make any final changes they want to put into 4.0.7.

Would you like SOCKS support to be included in the CVS before the branch?
I enclose the diff file.

Regards,


Paolo Prandini
S.P.E.Sistemi e Progetti Elettronici s.a.s.
Via Liguria 5
I-25125 Brescia (BS)
Tel +39 0302427266
Fax +39 0302449252
Email [EMAIL PROTECTED]
World Wide Web http://www.spe.it

diff file:

diff -urN php-4.0.6.orig/ext/standard/Makefile.in
php-4.0.6/ext/standard/Makefile.in
--- php-4.0.6.orig/ext/standard/Makefile.in     Mon Nov 20 11:05:57 2000
+++ php-4.0.6/ext/standard/Makefile.in  Thu Aug  9 11:14:51 2001
@@ -7,7 +7,7 @@
        link.c mail.c math.c md5.c metaphone.c microtime.c pack.c pageinfo.c \
         parsedate.c quot_print.c rand.c reg.c soundex.c string.c scanf.c \
        syslog.c type.c uniqid.c url.c url_scanner.c var.c output.c assert.c \
-       strnatcmp.c levenshtein.c incomplete_class.c url_scanner_ex.c \
+       strnatcmp.c levenshtein.c incomplete_class.c url_scanner_ex.c socks.c \
        ftp_fopen_wrapper.c http_fopen_wrapper.c php_fopen_wrapper.c credits.c

 include $(top_srcdir)/build/dynlib.mk
diff -urN php-4.0.6.orig/ext/standard/basic_functions.c
php-4.0.6/ext/standard/basic_functions.c
--- php-4.0.6.orig/ext/standard/basic_functions.c       Sun May 20 02:31:45 2001
+++ php-4.0.6/ext/standard/basic_functions.c    Thu Aug  9 11:21:32 2001
@@ -644,6 +644,15 @@
        PHP_INI_ENTRY_EX("safe_mode_protected_env_vars",
SAFE_MODE_PROTECTED_ENV_VARS,   PHP_INI_SYSTEM,
OnUpdateSafeModeProtectedEnvVars,               NULL)
        PHP_INI_ENTRY_EX("safe_mode_allowed_env_vars",
SAFE_MODE_ALLOWED_ENV_VARS,             PHP_INI_SYSTEM,
OnUpdateSafeModeAllowedEnvVars,                 NULL)
        STD_PHP_INI_ENTRY("session.use_trans_sid",          "1",
PHP_INI_ALL,                    OnUpdateBool,                   use_trans_sid,         
         php_basic_globals,
basic_globals)
+
+        PHP_INI_ENTRY("socks.user","",PHP_INI_ALL,NULL)
+        PHP_INI_ENTRY("socks.pass","",PHP_INI_ALL,NULL)
+        PHP_INI_ENTRY("socks.default_pass","",PHP_INI_SYSTEM,NULL)
+        PHP_INI_ENTRY("socks.default_user","",PHP_INI_SYSTEM,NULL)
+        PHP_INI_ENTRY("socks.server","",PHP_INI_SYSTEM,NULL)
+        PHP_INI_ENTRY("socks.type","4",PHP_INI_SYSTEM,NULL)
+        PHP_INI_ENTRY("socks.port","",PHP_INI_SYSTEM,NULL)
+        PHP_INI_ENTRY("socks.local","",PHP_INI_SYSTEM,NULL)
 PHP_INI_END()


diff -urN php-4.0.6.orig/ext/standard/socks.c php-4.0.6/ext/standard/socks.c
--- php-4.0.6.orig/ext/standard/socks.c Thu Jan  1 01:00:00 1970
+++ php-4.0.6/ext/standard/socks.c      Thu Aug  9 11:16:38 2001
@@ -0,0 +1,791 @@
+/*
+
+       phpsocks - an extension to php for use with socks proxies
+       Copyright (C) 2000 Paolo Prandini
+
+       liberally derived from:
+               TSOCKS - Wrapper library for transparent SOCKS
+               Copyright (C) 2000 Shaun Clowes
+
+
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/* PreProcessor Defines */
+#define DEBUG          1                  /* Show error messages?     */
+
+/* Header Files */
+#include "php.h"
+#include "php_ini.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <pwd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+struct socksent {
+        struct in_addr localip;
+        struct in_addr localnet;
+       struct socksent *next;
+};
+
+struct sockaddr_link {
+        struct sockaddr_in ip;
+       struct sockaddr_link *next;
+};
+
+struct sockreq {
+        int8_t version;
+        int8_t command;
+        int16_t dstport;
+        int32_t dstip;
+        /* A null terminated username goes here */
+};
+
+struct sockrep {
+        int8_t version;
+        int8_t result;
+        int16_t ignore1;
+        int32_t ignore2;
+};
+
+/* Global Declarations */
+static struct socksent *localnets = NULL;
+static int initialized = 0;
+static int servertype = 0;
+static int servervalid = 0;
+static unsigned short int sin_port;
+static struct sockaddr_link *servers = NULL;
+static struct sockaddr_link *currentserver = NULL;
+static char *default_user = NULL;
+static char *default_pass = NULL;
+
+/* Exported Function Prototypes */
+int Tconnect (int, __CONST_SOCKADDR_ARG, socklen_t);
+
+/* Private Function Prototypes */
+static int initialize();
+static int read_config();
+static int handle_server(char *);
+static int handle_type(char *);
+static int handle_port(char *);
+static int handle_local(char *);
+static int handle_defuser(char *);
+static int handle_defpass(char *);
+static int is_local(struct in_addr *);
+static int connect_socks(int, struct sockaddr_in *);
+static int connect_socksv4(int, struct sockaddr_in *, struct sockaddr_in
*);
+static int connect_socksv5(int, struct sockaddr_in *, struct sockaddr_in
*);
+static void show_error(char *, ...);
+
+static int initialize () {
+
+       /* Read in the config file */
+       read_config();
+
+       initialized = 1;
+
+       return(0);
+}
+
+static int read_config () {
+
+       int cleardefs = 0;
+       struct sockaddr_link *sal;
+
+       handle_server(INI_STR("socks.server"));
+       handle_port(INI_STR("socks.port"));
+       handle_type(INI_STR("socks.type"));
+       handle_defuser(INI_STR("socks.default_user"));
+       handle_defpass(INI_STR("socks.default_pass"));
+       handle_local(INI_STR("socks.local"));
+
+       /* Always add the 127.0.0.1/255.0.0.0 subnet to local */
+       handle_local("127.0.0.0/255.0.0.0");
+
+       for (sal=servers;sal!=NULL;sal=sal->next)
+       if (is_local(&sal->ip.sin_addr)) {
+               show_error("SOCKS server is not on a local subnet!\n");
+               sal->ip.sin_family=0;
+       } else servervalid=1;
+
+       if (servers == NULL) {
+               show_error("No valid SOCKS server specified in "
+                          "configuration file\n");
+               servervalid=0;
+       }
+
+       /* Default to the default SOCKS port */
+       if (sin_port == 0) {
+               sin_port = htons(1080);
+       }
+
+       /* Default to SOCKS V4 */
+       if (servertype == 0) {
+               servertype = 4;
+       }
+
+       if ((default_user != NULL) || (default_pass != NULL)) {
+               /* If the server type is version 4, neither */
+               /* username or password is valid */
+               if (servertype == 4) {
+                       show_error("Default username/pass "
+                                  "only valid for version 5 "
+                                  "SOCKS servers\n");
+                       cleardefs = 1;
+               } else
+               /* If default user and pass not specified */
+               /* together then show an error */
+               if (!((default_user != NULL) &&
+                     (default_pass != NULL))) {
+                       show_error("Default username and "
+                                  "pass MUST be specified "
+                                  "together\n");
+                       cleardefs = 1;
+               }
+               if (cleardefs == 1) {
+                       if (default_user != NULL) {
+                               free(default_user);
+                               default_user = NULL;
+                       }
+                       if (default_pass != NULL) {
+                               free(default_user);
+                               default_user = NULL;
+                       }
+               }
+       }
+
+       return(0);
+}
+
+static int
+handle_server(char *value)
+{
+       struct sockaddr_link *ent;
+       char *ip,*srv;
+
+       while (1) {
+
+               // Process multiple servers delimited by "," symbol
+               srv = strsep(&value, ",");
+               if (srv==NULL) srv=value;
+               if (srv==NULL) break;
+
+               ip = strsep(&srv, " ");
+               if (ip==NULL) break;
+
+               ent=(struct sockaddr_link *)malloc(sizeof(struct sockaddr_link));
+               if (ent==NULL) {
+                       /* if we couldn't malloc some storage, leave */
+                       exit(-1);
+               }
+               if (!(inet_aton(ip, &ent->ip.sin_addr))) {
+                       show_error("The SOCKS server (%s) in configuration "
+                          "file is invalid\n", ip);
+                       free(ent);
+               } else {
+                       /* Construct the addr for the socks server */
+                       ent->ip.sin_family = AF_INET; /* host byte order */
+                       ent->ip.sin_port = 0;
+                       bzero(&(ent->ip.sin_zero), 8);/* zero the rest of the struct */
+                       ent->next=servers;
+                       servers=ent;
+               }
+       }
+
+       return(0);
+}
+
+static int
+handle_port(char *value)
+{
+
+       if (sin_port != 0) {
+               show_error("Server port may only be specified once "
+                          "in configuration file\n");
+       } else {
+               errno = 0;
+               sin_port = (unsigned short int)
+                                 htons(strtol(value, (char **)NULL, 10));
+               if ((errno != 0) || (sin_port == 0)) {
+                       show_error("Invalid server port number "
+                                  "specified in configuration file "
+                                  "(%s)\n", value);
+                       sin_port = 0;
+               }
+       }
+
+       return(0);
+}
+
+static int
+handle_defuser(char *value)
+{
+
+       if (default_user != NULL) {
+               show_error("Default username may only be specified "
+                          "once in configuration file\n");
+       } else {
+               default_user = strdup(value);
+       }
+
+       return(0);
+}
+
+static int
+handle_defpass(char *value)
+{
+
+       if (default_pass != NULL) {
+               show_error("Default password may only be specified "
+                          "once in configuration file\n");
+       } else {
+               default_pass = strdup(value);
+       }
+
+       return(0);
+}
+
+static int
+handle_type(char *value)
+{
+
+       if (servertype != 0) {
+               show_error("Server type may only be specified once "
+                          "in configuration file\n");
+       } else {
+               errno = 0;
+               servertype = (int) strtol(value, (char **)NULL, 10);
+               if ((errno != 0) || (servertype == 0) ||
+                   ((servertype != 4) && (servertype != 5))) {
+                       show_error("%d %d\n", errno, servertype);
+                       show_error("Invalid server type "
+                                  "specified in configuration file "
+                                  "(%s) only 4 or 5 may be "
+                                  "specified\n", value);
+                       servertype = 0;
+               }
+       }
+
+       return(0);
+}
+
+static int
+handle_local(char *value)
+{
+       char *ip;
+       char *subnet;
+       char buf[100];
+       char *split,*net;
+       struct socksent *ent;
+
+       while (1) {
+
+               // Process multiple nets delimited by "," symbol
+               net = strsep(&value, ",");
+               if (net==NULL) net=value;
+               if (net==NULL) break;
+
+               strncpy(buf, net, sizeof(buf) - 1);
+               split = buf;
+               ip = strsep(&split, "/");
+               subnet = strsep(&split, " \n");
+
+               if ((ip == NULL) && (subnet == NULL)) break;
+
+               if ((ip == NULL) || (subnet == NULL)) {
+                       show_error("Local network pair (%s) is not validly "
+                                  "constructed\n", value);
+                       return(1);
+               } else {
+                       /* Allocate the new entry */
+                       if ((ent = (struct socksent *) malloc(sizeof(struct socksent)))
+                  == NULL) {
+                               /* If we couldn't malloc some storage, leave */
+                               exit(-1);
+                       }
+
+                       if (!(inet_aton(ip, &(ent->localip)))) {
+                               show_error("In configuration file IP for local "
+                                          "network (%s) is not valid\n", ip);
+                               free(ent);
+                               return(1);
+                       }
+                       else if ((ent->localnet.s_addr = inet_addr(subnet)) == -1) {
+                               show_error("In configuration file SUBNET for "
+                                          "local network (%s) is not valid\n", ip);
+                               free(ent);
+                               return(1);
+                       }
+                       else if ((ent->localip.s_addr &
+                                 ent->localnet.s_addr) !=
+                                ent->localip.s_addr) {
+                               show_error("In configuration file IP (%s) & "
+                                          "SUBNET (%s) != IP. Ignored.\n",
+                                       ip, subnet);
+                               free(ent);
+                               continue;
+                       } else {
+                               /* The entry is valid so add to linked list */
+                               ent -> next = localnets;
+                               localnets = ent;
+                       }
+               }
+       }
+       return(0);
+}
+
+
+static int is_local(struct in_addr *testip) {
+       struct socksent *ent;
+
+       for (ent = localnets; ent != NULL; ent = ent -> next) {
+               if ((testip->s_addr & ent->localnet.s_addr) ==
+                   (ent->localip.s_addr & ent->localnet.s_addr))  {
+                       return(0);
+               }
+       }
+
+       return(1);
+}
+
+int Tconnect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) {
+       struct sockaddr_in *connaddr;
+       void **kludge;
+       int sock_type = -1;
+       int sock_type_len = sizeof(sock_type);
+
+       /* If we haven't initialized yet, do it now */
+       if (initialized == 0) {
+               initialize();
+       }
+
+       /* Ok, so this method sucks, but it's all I can think of */
+       kludge = (void *) & __addr;
+       connaddr = (struct sockaddr_in *) *kludge;
+
+       /* Get the type of the socket */
+       getsockopt(__fd, SOL_SOCKET, SO_TYPE,
+                  (void *) &sock_type, &sock_type_len);
+
+       /* Only try and use socks if the socket is an INET socket, */
+       /* is a TCP stream, isn't on a local subnet and the        */
+       /* socks server in the config was valid                    */
+       if ((connaddr->sin_family != AF_INET) ||
+           (sock_type != SOCK_STREAM) ||
+           (servervalid == 0) ||
+           !(is_local(&(connaddr->sin_addr)))) {
+               return(connect(__fd, __addr, __len));
+       } else {
+               return(connect_socks(__fd, connaddr));
+       }
+
+}
+
+static int connect_socks(int sockid, struct sockaddr_in *connaddr) {
+       int rc = 0;
+       int sockflags;
+       struct sockaddr_link *sal;
+
+       if (currentserver==NULL) currentserver=servers;
+       sal=currentserver;
+
+       do {
+
+               /* Get the flags of the socket, (incase its non blocking */
+               if ((sockflags = fcntl(sockid, F_GETFL)) == -1) {
+                       sockflags = 0;
+               }
+
+               /* If the flags show the socket as blocking, set it to   */
+               /* blocking for our connection to the socks server       */
+               if ((sockflags & O_NONBLOCK) != 0) {
+                       fcntl(sockid, F_SETFL, sockflags & (~(O_NONBLOCK)));
+               }
+
+               if (servertype == 4)
+                       rc = connect_socksv4(sockid, connaddr, &sal->ip);
+               else
+                       rc = connect_socksv5(sockid, connaddr, &sal->ip);
+
+               /* If the socket was in non blocking mode, restore that */
+               if ((sockflags & O_NONBLOCK) != 0) {
+                       fcntl(sockid, F_SETFL, sockflags);
+               }
+
+               if (rc==0) break;
+               if (rc==ECONNREFUSED) break;
+
+               sal=sal->next;
+               if (!sal) sal=servers;
+
+       } while (sal!=currentserver);
+
+       if (rc != 0) {
+               errno = rc;
+               return(-1);
+       } else {
+               currentserver=sal;
+       }
+       return(0);
+
+}
+
+static int connect_socksv4(int sockid, struct sockaddr_in *connaddr, struct
sockaddr_in *server) {
+       int rc = 0;
+       int length = 0;
+       char *realreq;
+       struct passwd *user;
+       struct sockreq *thisreq;
+       struct sockrep thisrep;
+       int tmpsock;
+
+       if (server->sin_port==0) server->sin_port=sin_port;
+       if (server->sin_family==0) return ECONNREFUSED;
+
+       /* Determine the current username */
+       user = getpwuid(getuid());
+
+       /* Allocate enough space for the request and the null */
+       /* terminated username */
+       length = sizeof(struct sockreq) +
+                       (user == NULL ? 1 : strlen(user->pw_name) + 1);
+       if ((realreq = malloc(length)) == NULL) {
+               /* Could not malloc, bail */
+               exit(1);
+       }
+       thisreq = (struct sockreq *) realreq;
+
+       /* Create the request */
+       thisreq->version = 4;
+       thisreq->command = 1;
+       thisreq->dstport = connaddr->sin_port;
+       thisreq->dstip   = connaddr->sin_addr.s_addr;
+
+       /* Copy the username */
+       strcpy(realreq + sizeof(struct sockreq),
+              (user == NULL ? "" : user->pw_name));
+
+       /* open a test socket */
+       tmpsock=socket(AF_INET,SOCK_STREAM,0);
+       if ((rc = connect(tmpsock, (struct sockaddr *) server,
+                             sizeof(struct sockaddr_in))) != 0) {
+               show_error("Error %d attempting to test connect to SOCKS "
+                               "server %s:%d\n", errno,
+                               inet_ntoa(server->sin_addr),
+                               ntohs(server->sin_port));
+               close(tmpsock);
+               return(rc);
+       }
+       shutdown(tmpsock,2);
+       close(tmpsock);
+
+       /* Connect this socket to the socks server instead */
+       if ((rc = connect(sockid, (struct sockaddr *) server,
+                             sizeof(struct sockaddr_in))) != 0) {
+               show_error("Error %d attempting to connect to SOCKS "
+                                  "server\n", errno);
+               rc = rc;
+       } else {
+               rc = send(sockid, (void *) thisreq, length,0);
+               if (rc < 0) {
+                       show_error("Error %d attempting to send SOCKS "
+                                  "request\n", errno);
+                       rc = rc;
+               } else if ((rc = recv(sockid, (void *) &thisrep,
+                                     sizeof(struct sockrep), 0)) < 0) {
+                       show_error("Error %d attempting to receive SOCKS "
+                                  "reply\n", errno);
+                       rc = ECONNREFUSED;
+               } else if (rc < sizeof(struct sockrep)) {
+                       show_error("Short reply from SOCKS server\n");
+                       /* Let the application try and see how they */
+                       /* go                                       */
+                       rc = 0;
+               } else if (thisrep.result == 91) {
+                       show_error("SOCKS server refused connection\n");
+                       rc = ECONNREFUSED;
+               } else if (thisrep.result == 92) {
+                       show_error("SOCKS server refused connection "
+                                  "because of failed connect to identd "
+                                  "on this machine\n");
+                       rc = ECONNREFUSED;
+               } else if (thisrep.result == 93) {
+                       show_error("SOCKS server refused connection "
+                                  "because identd and this library "
+                                  "reported different user-ids\n");
+                       rc = ECONNREFUSED;
+               } else {
+                       rc = 0;
+               }
+       }
+
+       /* Free the SOCKS request storage that was malloced */
+       free(realreq);
+
+       return(rc);
+
+}
+
+static int connect_socksv5(int sockid, struct sockaddr_in *connaddr, struct
sockaddr_in *server) {
+       int rc = 0;
+       int offset = 0;
+       char *verstring = "\x05\x02\x02\x00";
+       char *uname, *upass;
+       struct passwd *nixuser;
+       char buf[200];
+       int tmpsock;
+
+       if (server->sin_port==0) server->sin_port=sin_port;
+       if (server->sin_family==0) return ECONNREFUSED;
+
+       /* open a test socket */
+       tmpsock=socket(AF_INET,SOCK_STREAM,0);
+       if ((rc = connect(tmpsock, (struct sockaddr *) server,
+                             sizeof(struct sockaddr_in))) != 0) {
+               show_error("Error %d attempting to test connect to SOCKS "
+                               "server %s:%d\n", errno,
+                               inet_ntoa(server->sin_addr),
+                               ntohs(server->sin_port));
+               close(tmpsock);
+               return(rc);
+       }
+       shutdown(tmpsock,2);
+       close(tmpsock);
+
+       /* Connect this socket to the socks server */
+       if ((rc = connect(sockid, (struct sockaddr *) server,
+                             sizeof(struct sockaddr_in))) != 0) {
+               show_error("Error %d attempting to connect to SOCKS "
+                               "server %s:%d\n", errno,
+                               inet_ntoa(server->sin_addr),
+                               ntohs(server->sin_port));
+               return(rc);
+       }
+
+        /* Now send the method negotiation */
+       if ((rc = send(sockid, (void *) verstring, 4,0)) < 0) {
+               show_error("Error %d attempting to send SOCKS "
+                          "method negotiation\n", errno);
+               return(rc);
+       }
+
+       /* Now receive the reply as to which method we're using */
+       if ((rc = recv(sockid, (void *) buf, 2, 0)) < 0) {
+               show_error("Error %d attempting to receive SOCKS "
+                          "method negotiation reply\n", errno);
+               rc = ECONNREFUSED;
+               return(rc);
+       }
+
+       if (rc < 2) {
+               show_error("Short reply from SOCKS server\n");
+               rc = ECONNREFUSED;
+               return(rc);
+       }
+
+       /* See if we offered an acceptable method */
+       if (buf[1] == '\xff') {
+               show_error("SOCKS server refused authentication methods\n");
+               rc = ECONNREFUSED;
+               return(rc);
+       }
+
+       /* If the socks server chose username/password authentication */
+       /* (method 2) then do that */
+       if ((unsigned short int) buf[1] == 2) {
+
+               /* Determine the current *nix username */
+               nixuser = getpwuid(getuid());
+
+               if (
+                   ( strlen(uname = INI_STR("socks.user")) == 0) &&
+                   ((uname = getenv("TSOCKS_USERNAME")) == NULL) &&
+                   ((uname = default_user) == NULL) &&
+                   ((uname = (nixuser == NULL ? NULL : nixuser->pw_name)) == NULL)) {
+                       show_error("Could not get SOCKS username from "
+                                  "local passwd file, php.ini "
+                                  "or $TSOCKS_USERNAME to authenticate "
+                                  "with");
+                       rc = ECONNREFUSED;
+                       return(rc);
+               }
+
+               if (
+                   ( strlen(upass = INI_STR("socks.pass")) == 0) &&
+                   ((upass = getenv("TSOCKS_PASSWORD")) == NULL) &&
+                   ((upass = default_pass) == NULL)) {
+                       show_error("Need a password in php.ini or "
+                                  "$TSOCKS_PASSWORD to authenticate with");
+                       rc = ECONNREFUSED;
+                       return(rc);
+               }
+
+               offset = 0;
+               buf[offset] = '\x01';
+               offset++;
+               buf[offset] = (int8_t) strlen(uname);
+               offset++;
+               memcpy(&buf[offset], uname, strlen(uname));
+               offset = offset + strlen(uname);
+               buf[offset] = (int8_t) strlen(upass);
+               offset++;
+               memcpy(&buf[offset], upass, strlen(upass));
+               offset = offset + strlen(upass);
+
+               /* Send out the authentication */
+               if ((rc = send(sockid, (void *) buf, offset,0)) < 0) {
+                       show_error("Error %d attempting to send SOCKS "
+                                  "authentication\n", errno);
+                       return(rc);
+               }
+
+
+               /* Receive the authentication response */
+               if ((rc = recv(sockid, (void *) buf, 2, 0)) < 0) {
+                       show_error("Error %d attempting to receive SOCKS "
+                                  "authentication reply\n", errno);
+                       rc = ECONNREFUSED;
+                       return(rc);
+               }
+
+               if (rc < 2) {
+                       show_error("Short reply from SOCKS server\n");
+                       rc = ECONNREFUSED;
+                       return(rc);
+               }
+
+               if (buf[1] != '\x00') {
+                       show_error("SOCKS authentication failed, "
+                                  "check username and password\n");
+                       rc = ECONNREFUSED;
+                       return(rc);
+               }
+
+       }
+
+       /* Now send the connect */
+       buf[0] = '\x05';                /* Version 5 SOCKS */
+       buf[1] = '\x01';                /* Connect request */
+       buf[2] = '\x00';                /* Reserved        */
+       buf[3] = '\x01';                /* IP version 4    */
+       memcpy(&buf[4], &connaddr->sin_addr.s_addr, 4);
+       memcpy(&buf[8], &connaddr->sin_port, 2);
+
+        /* Now send the connection */
+       if ((rc = send(sockid, (void *) buf, 10,0)) < 0) {
+               show_error("Error %d attempting to send SOCKS "
+                          "connect command\n", errno);
+               return(rc);
+       }
+
+       /* Now receive the reply to see if we connected */
+       if ((rc = recv(sockid, (void *) buf, 10, 0)) < 0) {
+               show_error("Error %d attempting to receive SOCKS "
+                          "connection reply\n", errno);
+               rc = ECONNREFUSED;
+               return(rc);
+       }
+
+       if (rc < 10) {
+               show_error("Short reply from SOCKS server\n");
+               rc = ECONNREFUSED;
+               return(rc);
+       }
+
+       /* See the connection succeeded */
+       if (buf[1] != '\x00') {
+               show_error("SOCKS connect failed: ");
+               switch ((int8_t) buf[1]) {
+                       case 1:
+                               show_error("General SOCKS server failure\n");
+                               return(ECONNABORTED);
+                       case 2:
+                               show_error("Connection denied by rule\n");
+                               return(ECONNABORTED);
+                       case 3:
+                               show_error("Network unreachable\n");
+                               return(ENETUNREACH);
+                       case 4:
+                               show_error("Host unreachable\n");
+                               return(EHOSTUNREACH);
+                       case 5:
+                               show_error("Connection refused\n");
+                               return(ECONNREFUSED);
+                       case 6:
+                               show_error("TTL Expired\n");
+                               return(ETIMEDOUT);
+                       case 7:
+                               show_error("Command not supported\n");
+                               return(ECONNABORTED);
+                       case 8:
+                               show_error("Address type not supported\n");
+                               return(ECONNABORTED);
+                       default:
+                               show_error("Unknown error\n");
+                               return(ECONNABORTED);
+               }
+       }
+
+       return(0);
+
+}
+
+static void show_error(char *fmt, ...) {
+#ifdef DEBUG
+       va_list ap;
+       int saveerr;
+       char *newfmt;
+       FILE *fp;
+       char MYNAME[]= "phpsocks: ";
+
+       if ((newfmt = malloc(strlen(fmt) + strlen(MYNAME) + 1)) == NULL) {
+               /* Could not malloc, bail */
+               exit(1);
+       }
+
+       strcpy(newfmt, MYNAME);
+       strcpy(newfmt + strlen(MYNAME), fmt);
+
+       va_start(ap, fmt);
+
+       /* Save errno */
+       saveerr = errno;
+
+       fp=fopen("/tmp/sock.log","a");
+       if (fp!=NULL) {
+               vfprintf(fp, newfmt, ap);
+               fclose(fp);
+       }
+
+       errno = saveerr;
+
+       va_end(ap);
+
+       free(newfmt);
+#endif
+}
+
diff -urN php-4.0.6.orig/main/network.c php-4.0.6/main/network.c
--- php-4.0.6.orig/main/network.c       Sat May  5 20:36:20 2001
+++ php-4.0.6/main/network.c    Thu Aug  9 11:24:27 2001
@@ -209,13 +209,13 @@

        if (timeout == NULL)    {
                /* blocking mode */
-               return connect(sockfd, addr, addrlen);
+               return Tconnect(sockfd, addr, addrlen);
        }

        flags = fcntl(sockfd, F_GETFL, 0);
        fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

-       if ((n = connect(sockfd, addr, addrlen)) < 0) {
+       if ((n = Tconnect(sockfd, addr, addrlen)) < 0) {
                if (errno != EINPROGRESS) {
                        return -1;
                }
@@ -257,7 +257,7 @@
        }
        return ret;
 #else /* !defined(PHP_WIN32) && ... */
-       return connect(sockfd, addr, addrlen);
+       return Tconnect(sockfd, addr, addrlen);
 #endif
 }
 /* }}} */



-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to