about summary refs log tree commit diff stats
path: root/WWW/Library
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>2006-05-29 23:09:26 -0400
committerThomas E. Dickey <dickey@invisible-island.net>2006-05-29 23:09:26 -0400
commit38fbf2f2474aa1e66883014080fc504475297c4f (patch)
tree20f45b048fecb8271e5c386fd2a746488c59356b /WWW/Library
parent04a316621e7163aa1d3a747c47844da55c6aa4d6 (diff)
downloadlynx-snapshots-38fbf2f2474aa1e66883014080fc504475297c4f.tar.gz
snapshot of project "lynx", label v2-8-6dev_18
Diffstat (limited to 'WWW/Library')
-rw-r--r--WWW/Library/Implementation/HTFile.c4
-rw-r--r--WWW/Library/Implementation/HTRules.h2
-rw-r--r--WWW/Library/Implementation/HTString.c119
-rw-r--r--WWW/Library/Implementation/HTString.h2
-rw-r--r--WWW/Library/Implementation/HTTCP.c98
-rw-r--r--WWW/Library/Implementation/HTTP.c98
-rw-r--r--WWW/Library/Implementation/HTTelnet.c2
-rw-r--r--WWW/Library/Implementation/HTUtils.h2
-rw-r--r--WWW/Library/Implementation/www_tcp.h5
9 files changed, 187 insertions, 145 deletions
diff --git a/WWW/Library/Implementation/HTFile.c b/WWW/Library/Implementation/HTFile.c
index 1909492f..b15c0448 100644
--- a/WWW/Library/Implementation/HTFile.c
+++ b/WWW/Library/Implementation/HTFile.c
@@ -1840,7 +1840,7 @@ static int print_local_dir(DIR *dp, char *localname,
 	 */
 	DIRED *data = NULL;
 
-#if !(defined(DOSPATH) || defined(__EMX__))
+#ifdef STRUCT_DIRENT__D_INO
 	if (dirbuf->d_ino == 0)
 	    /*
 	     * If the entry is not being used, skip it.
@@ -2645,7 +2645,7 @@ int HTLoadFile(const char *addr,
 		/*
 		 * While there are directory entries to be read...
 		 */
-#if !(defined(DOSPATH) || defined(__EMX__))
+#ifdef STRUCT_DIRENT__D_INO
 		if (dirbuf->d_ino == 0)
 		    continue;	/* if the entry is not being used, skip it */
 #endif
diff --git a/WWW/Library/Implementation/HTRules.h b/WWW/Library/Implementation/HTRules.h
index ccf838c0..fa5130e5 100644
--- a/WWW/Library/Implementation/HTRules.h
+++ b/WWW/Library/Implementation/HTRules.h
@@ -119,7 +119,7 @@ HTTranslate: Translate by rules
   ON EXIT,
 
   returns                 the address of the equivalent string allocated from the heap
-                         which the CALLER MUST FREE. If no translation occured, then it is
+                         which the CALLER MUST FREE. If no translation occurred, then it is
                          a copy of the original.
 
  */
diff --git a/WWW/Library/Implementation/HTString.c b/WWW/Library/Implementation/HTString.c
index 59dea861..e212c6f1 100644
--- a/WWW/Library/Implementation/HTString.c
+++ b/WWW/Library/Implementation/HTString.c
@@ -84,79 +84,6 @@ int strncasecomp8(const char *a,
 }
 
 #ifndef VM			/* VM has these already it seems */
-
-#ifdef SH_EX			/* 1997/12/23 (Tue) 16:40:31 */
-
-/*
- * This array is designed for mapping upper and lower case letter
- * together for a case independent comparison.  The mappings are
- * based upon ascii character sequences.
- */
-static unsigned char charmap[] =
-{
-    '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
-    '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
-    '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
-    '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
-    '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
-    '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
-    '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
-    '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
-    '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
-    '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
-    '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
-    '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
-    '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
-    '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
-    '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
-    '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
-    '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
-    '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
-    '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
-    '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
-    '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
-    '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
-    '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
-    '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
-    '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
-    '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
-    '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327',
-    '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337',
-    '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
-    '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
-    '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
-    '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
-};
-
-int strcasecomp(const char *s1,
-		const char *s2)
-{
-    register unsigned char *cm = charmap;
-    register unsigned char *us1 = (unsigned char *) s1;
-    register unsigned char *us2 = (unsigned char *) s2;
-
-    while (cm[*us1] == cm[*us2++])
-	if (*us1++ == '\0')
-	    return (0);
-    return (cm[*us1] - cm[*--us2]);
-}
-
-int strncasecomp(const char *a,
-		 const char *b,
-		 int n)
-{
-    register unsigned char *cm = charmap;
-    register unsigned char *us1 = (unsigned char *) a;
-    register unsigned char *us2 = (unsigned char *) b;
-
-    while ((long) (--n) >= 0 && cm[*us1] == cm[*us2++])
-	if (*us1++ == '\0')
-	    return (0);
-    return ((long) n < 0 ? 0 : cm[*us1] - cm[*--us2]);
-}
-
-#else /* SH_EX */
-
 /*	Strings of any length
  *	---------------------
  */
@@ -203,7 +130,51 @@ int strncasecomp(const char *a,
     /*NOTREACHED */
 }
 
-#endif /* SH_EX */
+/*
+ * Compare strings, ignoring case.  If either begins with an asterisk, treat
+ * that as a wildcard to match zero-or-more characters.  This does not test
+ * for embedded wildcards.
+ */
+int strcasecomp_asterisk(const char *a, const char *b)
+{
+    unsigned const char *us1 = (unsigned const char *) a;
+    unsigned const char *us2 = (unsigned const char *) b;
+    int result = 0;
+
+    if ((*a != '*') && (*b != '*')) {
+	result = strcasecomp(a, b);
+    } else {
+	int dir = 1;
+
+	if (*b == '*') {
+	    us1 = us2;
+	    us2 = (unsigned const char *) a;
+	    dir = -1;
+	}
+
+	if (strlen((const char *) us2) < (strlen((const char *) us1) - 1)) {
+	    result = 1;
+	} else {
+	    while (*++us1 != '\0') ;
+	    while (*++us2 != '\0') ;
+
+	    while (1) {
+		unsigned char a1 = TOLOWER(*us1);
+		unsigned char b1 = TOLOWER(*us2);
+
+		if (a1 != b1) {
+		    result = (a1 > b1) ? dir : -dir;
+		    break;
+		} else if ((*--us1) == '*') {
+		    result = 0;
+		    break;
+		}
+		--us2;
+	    }
+	}
+    }
+    return result;
+}
 #endif /* VM */
 
 #ifdef NOT_ASCII
diff --git a/WWW/Library/Implementation/HTString.h b/WWW/Library/Implementation/HTString.h
index e9d0a4df..dc3e08f8 100644
--- a/WWW/Library/Implementation/HTString.h
+++ b/WWW/Library/Implementation/HTString.h
@@ -45,6 +45,8 @@ Case-insensitive string comparison
     extern int strcasecomp8(const char *a, const char *b);
     extern int strncasecomp8(const char *a, const char *b, int n);
 
+    extern int strcasecomp_asterisk(const char *a, const char *b);
+
     /*
      * strcasecomp8 and strncasecomp8 are variants of strcasecomp and
      * strncasecomp, but use 8bit upper/lower case information from the
diff --git a/WWW/Library/Implementation/HTTCP.c b/WWW/Library/Implementation/HTTCP.c
index 91669582..2860e555 100644
--- a/WWW/Library/Implementation/HTTCP.c
+++ b/WWW/Library/Implementation/HTTCP.c
@@ -100,33 +100,6 @@ static int ResolveYield(void)
 }
 #endif
 
-/*
- * This chunk of code is used in both win32 and cygwin.
- */
-#if defined(_WINDOWS_NSL)
-static LYNX_HOSTENT *phost;	/* Pointer to host - See netdb.h */
-static int donelookup;
-
-static unsigned long __stdcall _fork_func(void *arg)
-{
-    const char *host = (const char *) arg;
-
-#ifdef SH_EX
-    unsigned long addr;
-
-    addr = (unsigned long) inet_addr(host);
-    if (addr != INADDR_NONE)
-	phost = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
-    else
-	phost = gethostbyname(host);
-#else
-    phost = gethostbyname(host);
-#endif
-    donelookup = TRUE;
-    return (unsigned long) (phost);
-}
-#endif /* _WINDOWS_NSL */
-
 #if defined(VMS) && defined(UCX)
 /*
  *  A routine to mimic the ioctl function for UCX.
@@ -462,7 +435,7 @@ static void dump_hostent(const char *msgprefix,
  *  cast to a LYNX_HOSTENT. - kw
  *  See also description of LYGetHostByName.
  */
-#ifdef NSL_FORK
+#if defined(NSL_FORK) || defined(_WINDOWS_NSL)
 
 #define REHOSTENT_SIZE 128	/* not bigger than pipe buffer! */
 
@@ -595,6 +568,49 @@ static size_t fill_rehostent(char *rehostent,
     curlen = p_next_char - (char *) rehostent;
     return curlen;
 }
+
+/*
+ * This chunk of code is used in both win32 and cygwin.
+ */
+#if defined(_WINDOWS_NSL)
+static LYNX_HOSTENT *gbl_phost;	/* Pointer to host - See netdb.h */
+
+#ifndef __CYGWIN__
+static int donelookup;
+
+static unsigned long __stdcall _fork_func(void *arg)
+{
+    const char *host = (const char *) arg;
+    static AlignedHOSTENT aligned_full_rehostent;
+    char *rehostent = (char *) &aligned_full_rehostent;
+    size_t rehostentlen = 0;
+
+#ifdef SH_EX
+    unsigned long addr;
+
+    addr = (unsigned long) inet_addr(host);
+    if (addr != INADDR_NONE)
+	gbl_phost = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
+    else
+	gbl_phost = gethostbyname(host);
+#else
+    gbl_phost = gethostbyname(host);
+#endif
+
+    if (gbl_phost) {
+	rehostentlen = fill_rehostent(rehostent, REHOSTENT_SIZE, gbl_phost);
+	if (rehostentlen == 0) {
+	    gbl_phost = (LYNX_HOSTENT *) NULL;
+	} else {
+	    gbl_phost = (LYNX_HOSTENT *) rehostent;
+	}
+    }
+
+    donelookup = TRUE;
+    return (unsigned long) (gbl_phost);
+}
+#endif /* __CYGWIN__ */
+#endif /* _WINDOWS_NSL */
 #endif /* NSL_FORK */
 
 #ifndef HAVE_H_ERRNO
@@ -742,7 +758,7 @@ LYNX_HOSTENT *LYGetHostByName(char *str)
 #ifdef NSL_FORK
     statuses.h_errno_valid = NO;
     /*
-     * Start block for fork-based gethostbyname() with checks for interrupts. 
+     * Start block for fork-based gethostbyname() with checks for interrupts.
      * - Tom Zerucha (tz@execpc.com) & FM
      */
     {
@@ -772,7 +788,7 @@ LYNX_HOSTENT *LYGetHostByName(char *str)
 	int child_exited = 0;
 
 	/*
-	 * Reap any children that have terminated since last time through. 
+	 * Reap any children that have terminated since last time through.
 	 * This might include children that we killed, then waited with WNOHANG
 	 * before they were actually ready to be reaped.  (Should be max of 1
 	 * in this state, but the loop is safe if waitpid() is implemented
@@ -945,7 +961,7 @@ LYNX_HOSTENT *LYGetHostByName(char *str)
 	     * least I don't know how), so SLANG users must live with up-to-1s
 	     * timeout.  -BL
 	     *
-	     * Whoops -- we need to make sure stdin is actually selectable! 
+	     * Whoops -- we need to make sure stdin is actually selectable!
 	     * /dev/null isn't, on some systems, which makes some useful Lynx
 	     * invocations fail.  -BL
 	     */
@@ -1124,12 +1140,12 @@ LYNX_HOSTENT *LYGetHostByName(char *str)
 
 	    t = (unsigned long) inet_addr(host);
 	    if (t != INADDR_NONE)
-		phost = gethostbyaddr((char *) &t, sizeof(t), AF_INET);
+		gbl_phost = gethostbyaddr((char *) &t, sizeof(t), AF_INET);
 	    else
-		phost = gethostbyname(host);
+		gbl_phost = gethostbyname(host);
 	} else {		/* for Windows NT */
 #endif /* !__CYGWIN__ */
-	    phost = (LYNX_HOSTENT *) NULL;
+	    gbl_phost = (LYNX_HOSTENT *) NULL;
 	    donelookup = FALSE;
 	    WSASetLastError(WSAHOST_NOT_FOUND);
 
@@ -1154,9 +1170,9 @@ LYNX_HOSTENT *LYGetHostByName(char *str)
 #ifndef __CYGWIN__
 	}
 #endif /* !__CYGWIN__ */
-	if (phost) {
+	if (gbl_phost) {
 	    lynx_nsl_status = HT_OK;
-	    result_phost = phost;
+	    result_phost = gbl_phost;
 	} else {
 	    lynx_nsl_status = HT_ERROR;
 	    goto failed;
@@ -1315,10 +1331,10 @@ static int HTParseInet(SockA * soc_in, const char *str)
 #endif /* MVS */
 
 #ifdef _WINDOWS_NSL
-	phost = LYGetHostByName(host);	/* See above */
-	if (!phost)
+	gbl_phost = LYGetHostByName(host);	/* See above */
+	if (!gbl_phost)
 	    goto failed;
-	memcpy((void *) &soc_in->sin_addr, phost->h_addr_list[0], phost->h_length);
+	memcpy((void *) &soc_in->sin_addr, gbl_phost->h_addr_list[0], gbl_phost->h_length);
 #else /* !_WINDOWS_NSL */
 	{
 	    LYNX_HOSTENT *phost;
@@ -1759,7 +1775,7 @@ int HTDoConnect(const char *url,
 		 *              ous  connection attempt has not yet been
 		 *              completed.
 		 * Thus if the SOCKET_ERRNO is NOT EALREADY we have a real
-		 * error, and should break out here and return that error. 
+		 * error, and should break out here and return that error.
 		 * Otherwise if it is EALREADY keep on trying to complete the
 		 * connection.
 		 */
@@ -1992,7 +2008,7 @@ int HTDoRead(int fildes,
 #endif
 
 	/*
-	 * If we suspend, then it is possible that select will be interrupted. 
+	 * If we suspend, then it is possible that select will be interrupted.
 	 * Allow for this possibility.  - JED
 	 */
 	do {
diff --git a/WWW/Library/Implementation/HTTP.c b/WWW/Library/Implementation/HTTP.c
index 7ced53bf..687bab83 100644
--- a/WWW/Library/Implementation/HTTP.c
+++ b/WWW/Library/Implementation/HTTP.c
@@ -451,11 +451,14 @@ static int HTLoadHTTP(const char *arg,
     const char *connect_url = NULL;	/* The URL being proxied */
     char *connect_host = NULL;	/* The host being proxied */
     SSL *handle = NULL;		/* The SSL handle */
-    char ssl_dn[256];
+    char ssl_dn[1024];
     char *cert_host;
     char *ssl_host;
     char *p;
     char *msg = NULL;
+    int status_sslcertcheck;
+    char *ssl_dn_start;
+    char *ssl_all_cns;
 
 #if SSLEAY_VERSION_NUMBER >= 0x0900
     BOOL try_tls = TRUE;
@@ -621,34 +624,79 @@ static int HTLoadHTTP(const char *arg,
 
 	X509_NAME_oneline(X509_get_subject_name(SSL_get_peer_certificate(handle)),
 			  ssl_dn, sizeof(ssl_dn));
-	if ((cert_host = strstr(ssl_dn, "/CN=")) == NULL) {
+
+	/*
+	 * X.509 DN validation taking ALL CN fields into account
+	 * (c) 2006 Thorsten Glaser <tg@mirbsd.de>
+	 */
+
+	/* initialise status information */
+	status_sslcertcheck = 0;	/* 0 = no CN found in DN */
+	ssl_dn_start = ssl_dn;
+	ssl_all_cns = NULL;
+	/* get host we're connecting to */
+	ssl_host = HTParse(url, "", PARSE_HOST);
+	/* strip port number */
+	if ((p = strchr(ssl_host, ':')) != NULL)
+	    *p = '\0';
+	/* validate all CNs found in DN */
+	while ((cert_host = strstr(ssl_dn_start, "/CN=")) != NULL) {
+	    status_sslcertcheck = 1;	/* 1 = could not verify CN */
+	    /* start of CommonName */
+	    cert_host += 4;
+	    /* find next part of DistinguishedName */
+	    if ((p = strchr(cert_host, '/')) != NULL) {
+		*p = '\0';
+		ssl_dn_start = p;	/* yes this points to the NUL byte */
+	    } else
+		ssl_dn_start = NULL;
+	    /* strip port number */
+	    if ((p = strchr(cert_host, ':')) != NULL)
+		*p = '\0';
+	    /* verify this CN */
+	    if (!strcasecomp_asterisk(ssl_host, cert_host)) {
+		status_sslcertcheck = 2;	/* 2 = verified peer */
+		/* I think this is cool to have in the logs --mirabilos */
+		HTSprintf0(&msg,
+			   gettext("Verified connection to %s (cert=%s)"),
+			   ssl_host, cert_host);
+		_HTProgress(msg);
+		FREE(msg);
+		/* no need to continue the verification loop */
+		break;
+	    }
+	    /* add this CN to list of failed CNs */
+	    if (ssl_all_cns == NULL) {
+		StrAllocCopy(ssl_all_cns, cert_host);
+	    } else {
+		StrAllocCat(ssl_all_cns, ":");
+		StrAllocCat(ssl_all_cns, cert_host);
+	    }
+	    /* if we cannot retry, don't try it */
+	    if (ssl_dn_start == NULL)
+		break;
+	    /* now retry next CN found in DN */
+	    *ssl_dn_start = '/';	/* formerly NUL byte */
+	}
+
+	/* if an error occurred, format the appropriate message */
+	if (status_sslcertcheck == 0) {
 	    HTSprintf0(&msg,
 		       gettext("SSL error:Can't find common name in certificate-Continue?"));
+	} else if (status_sslcertcheck == 1) {
+	    HTSprintf0(&msg,
+		       gettext("SSL error:host(%s)!=cert(%s)-Continue?"),
+		       ssl_host, ssl_all_cns);
+	}
+
+	/* if an error occurred, let the user decide how much he trusts */
+	if (status_sslcertcheck < 2) {
 	    if (!HTForcedPrompt(ssl_noprompt, msg, YES)) {
 		status = HT_NOT_LOADED;
 		FREE(msg);
+		FREE(ssl_all_cns);
 		goto done;
 	    }
-	} else {
-	    cert_host += 4;
-	    if ((p = strchr(cert_host, '/')) != NULL)
-		*p = '\0';
-	    if ((p = strchr(cert_host, ':')) != NULL)
-		*p = '\0';
-	    ssl_host = HTParse(url, "", PARSE_HOST);
-	    if ((p = strchr(ssl_host, ':')) != NULL)
-		*p = '\0';
-	    if (strcasecomp(ssl_host, cert_host)) {
-		HTSprintf0(&msg,
-			   gettext("SSL error:host(%s)!=cert(%s)-Continue?"),
-			   ssl_host,
-			   cert_host);
-		if (!HTForcedPrompt(ssl_noprompt, msg, YES)) {
-		    status = HT_NOT_LOADED;
-		    FREE(msg);
-		    goto done;
-		}
-	    }
 	}
 
 	HTSprintf0(&msg,
@@ -834,7 +882,7 @@ static int HTLoadHTTP(const char *arg,
 	 *
 	 * If there ever is a need to send "Negotiate:  trans" and really mean
 	 * it, we should send "Negotiate:  trans,trans" or similar, since that
-	 * is semantically equivalent and some servers may ignore "Negotiate: 
+	 * is semantically equivalent and some servers may ignore "Negotiate:
 	 * trans" as a special case when it comes from Lynx (to work around the
 	 * old faulty behavior).  - kw
 	 *
@@ -957,7 +1005,7 @@ static int HTLoadHTTP(const char *arg,
 		} else if (auth && *auth == '\0') {
 		    /*
 		     * If auth is a zero-length string, the user either
-		     * cancelled or goofed at the username and password prompt. 
+		     * cancelled or goofed at the username and password prompt.
 		     * - FM
 		     */
 		    if (!(traversal || dump_output_immediately) &&
@@ -1624,7 +1672,7 @@ static int HTLoadHTTP(const char *arg,
 		 * would include POST content, we seek confirmation from an
 		 * interactive user, with option to use 303 for 301 (but not
 		 * for 307), and otherwise refuse the redirection.  We also
-		 * don't allow permanent redirection if we keep POST content. 
+		 * don't allow permanent redirection if we keep POST content.
 		 * If we don't find the Location header or it's value is
 		 * zero-length, we display whatever the server returned, and
 		 * the user should RELOAD that to try again, or make a
diff --git a/WWW/Library/Implementation/HTTelnet.c b/WWW/Library/Implementation/HTTelnet.c
index 9474998a..2260f6c0 100644
--- a/WWW/Library/Implementation/HTTelnet.c
+++ b/WWW/Library/Implementation/HTTelnet.c
@@ -493,7 +493,7 @@ static int remote_session(char *acc_method, char *host)
  *	addr		must point to the fully qualified hypertext reference.
  *
  * On exit,
- *	returns		<0	Error has occured.
+ *	returns		<0	Error has occurred.
  *			>=0	Value of file descriptor or socket to be used
  *				 to read data.
  *	*pFormat	Set to the format of the file, if known.
diff --git a/WWW/Library/Implementation/HTUtils.h b/WWW/Library/Implementation/HTUtils.h
index 0939c4ef..a9ca41c6 100644
--- a/WWW/Library/Implementation/HTUtils.h
+++ b/WWW/Library/Implementation/HTUtils.h
@@ -176,7 +176,7 @@ char *alloca();
  */
 #if defined(_WINDOWS) && !defined(__CYGWIN__)
 
-#if defined(USE_WINSOCK2_H)
+#if defined(USE_WINSOCK2_H) && (_MSC_VER >= 1300) && (_MSC_VER < 1400)
 #include <winsock2.h>		/* includes windows.h, in turn windef.h */
 #else
 #include <windows.h>		/* #include "windef.h" */
diff --git a/WWW/Library/Implementation/www_tcp.h b/WWW/Library/Implementation/www_tcp.h
index a8179aff..7883ae03 100644
--- a/WWW/Library/Implementation/www_tcp.h
+++ b/WWW/Library/Implementation/www_tcp.h
@@ -93,6 +93,11 @@ Default values
 #  include <ndir.h>
 # endif
 #endif /* HAVE_DIRENT_H */
+
+#if !(defined(DOSPATH) || defined(__EMX__) || defined(__CYGWIN__))
+#define STRUCT_DIRENT__D_INO 1
+#endif
+
 #endif /* !VMS */
 
 #ifdef TIME_WITH_SYS_TIME