CTRACE(tfp, "Can't open `%s', errno=%d\n", addr, SOCKET_ERRNO);
CTRACE((tfp, "Can't open `%s', errno=%d\n", addr, SOCKET_ERRNO));
PUBLIC int HTLoadFile ARGS4(	CONST char *,		addr,	HTParentAnchor *,	anchor,	HTFormat,		format_out,	HTStream *,		sink){    char * filename = NULL;    char * acc_method = NULL;    char * ftp_newhost;    HTFormat format;    char * nodename = NULL;    char * newname = NULL;	/* Simplified name of file */    HTAtom * encoding;		/* @@ not used yet */    HTAtom * myEncoding = NULL; /* enc of this file, may be gzip etc. */    int status;#ifdef VMS    struct stat stat_info;#endif /* VMS */#ifdef USE_ZLIB    gzFile gzfp = 0;    BOOL use_gzread = NO;#endif /* USE_ZLIB */    /*    **	Reduce the filename to a basic form (hopefully unique!).    */    StrAllocCopy(newname, addr);    filename=HTParse(newname, "", PARSE_PATH|PARSE_PUNCTUATION);    nodename=HTParse(newname, "", PARSE_HOST);    /*    **	If access is ftp, or file is on another host, invoke ftp now.    */    acc_method = HTParse(newname, "", PARSE_ACCESS);    if (strcmp("ftp", acc_method) == 0 ||       (strcmp("localhost", nodename) != 0 &&#ifdef VMS	strcasecomp(nodename, HTHostName()) != 0#else	strcmp(nodename, HTHostName()) != 0#endif /* VMS */    )) {	FREE(newname);	FREE(filename);	FREE(nodename);	FREE(acc_method);#ifndef DISABLE_FTP	ftp_newhost = HTParse(addr, "", PARSE_HOST);	/* HTParse mallocs */	if (strcmp(ftp_lasthost, ftp_newhost))		ftp_local_passive = ftp_passive;	/* set to default */	status = HTFTPLoad(addr, anchor, format_out, sink);	if ( ftp_passive == ftp_local_passive ) {		if (( status <= -4 ) || ( status == -1 )) {			ftp_local_passive = !ftp_passive;			status = HTFTPLoad(addr, anchor, format_out, sink);		}	}	free(ftp_lasthost);	ftp_lasthost = ftp_newhost;	return status;#else	return -1;#endif /* DISABLE_FTP */    } else {	FREE(newname);	FREE(acc_method);    }#ifdef VMS    HTUnEscape(filename);#endif /* VMS */    /*    **	Determine the format and encoding mapped to any suffix.    */    if (anchor->content_type && anchor->content_encoding) {	/*	 *  If content_type and content_encoding are BOTH already set	 *  in the anchor object, we believe it and don't try to	 *  derive format and encoding from the filename. - kw	 */	format = HTAtom_for(anchor->content_type);	myEncoding = HTAtom_for(anchor->content_encoding);    } else {	int default_UCLYhndl = UCLYhndl_HTFile_for_unspec;	if (force_old_UCLYhndl_on_reload) {	    force_old_UCLYhndl_on_reload = FALSE;	    default_UCLYhndl = forced_UCLYhdnl;	}	format = HTFileFormat(filename, &myEncoding, NULL);    /*    **	Check the format for an extended MIME charset value, and    **	act on it if present.  Otherwise, assume what is indicated    **	by the last parameter (fallback will effectively be    **	UCLYhndl_for_unspec, by default ISO-8859-1). - kw    */	format = HTCharsetFormat(format, anchor, default_UCLYhndl );    }#ifdef VMS    /*    **	Check to see if the 'filename' is in fact a directory.	If it is    **	create a new hypertext object containing a list of files and    **	subdirectories contained in the directory.  All of these are links    **	to the directories or files listed.    */    if (HTStat(filename, &stat_info) == -1) {	CTRACE(tfp, "HTLoadFile: Can't stat %s\n", filename);    } else {	if (S_ISDIR(stat_info.st_mode)) {	    if (HTDirAccess == HT_DIR_FORBID) {		FREE(filename);		FREE(nodename);		return HTLoadError(sink, 403, DISALLOWED_DIR_SCAN);	    }	    if (HTDirAccess == HT_DIR_SELECTIVE) {		char * enable_file_name =		    malloc(strlen(filename)+ 1 +		    strlen(HT_DIR_ENABLE_FILE) + 1);		if (enable_file_name == NULL)		    outofmem(__FILE__, "HTLoadFile");		strcpy(enable_file_name, filename);		strcat(enable_file_name, "/");		strcat(enable_file_name, HT_DIR_ENABLE_FILE);		if (HTStat(enable_file_name, &stat_info) == -1) {		    FREE(filename);		    FREE(nodename);		    FREE(enable_file_name);		    return HTLoadError(sink, 403, DISALLOWED_SELECTIVE_ACCESS);		}	    }	    FREE(filename);	    FREE(nodename);	    return HTVMSBrowseDir(addr, anchor, format_out, sink);	}    }    /*    **	Assume that the file is in Unix-style syntax if it contains a '/'    **	after the leading one. @@    */    {	FILE * fp;	char * vmsname = strchr(filename + 1, '/') ?		    HTVMS_name(nodename, filename) : filename + 1;	fp = fopen(vmsname, "r", "shr=put", "shr=upd");	/*	**  If the file wasn't VMS syntax, then perhaps it is Ultrix.	*/	if (!fp) {	    char * ultrixname = 0;	    CTRACE(tfp, "HTLoadFile: Can't open as %s\n", vmsname);	    HTSprintf0(&ultrixname, "%s::\"%s\"", nodename, filename);	    fp = fopen(ultrixname, "r", "shr=put", "shr=upd");	    if (!fp) {		CTRACE(tfp, "HTLoadFile: Can't open as %s\n",			    ultrixname);	    }	    FREE(ultrixname);	}	if (fp) {	    int len;	    char *cp = NULL;	    char *semicolon = NULL;	    if (HTEditable(vmsname)) {		HTAtom * put = HTAtom_for("PUT");		HTList * methods = HTAnchor_methods(anchor);		if (HTList_indexOf(methods, put) == (-1)) {		    HTList_addObject(methods, put);		}	    }	    /*	    **	Trim vmsname at semicolon if a version number was	    **	included, so it doesn't interfere with the check	    **	for a compressed file. - FM	    */	    if ((semicolon = strchr(vmsname, ';')) != NULL)		*semicolon = '\0';	    /*	    **	Fake a Content-Encoding for compressed files. - FM	    */	    if (!IsUnityEnc(myEncoding)) {		/*		 *  We already know from the call to HTFileFormat above		 *  that this is a compressed file, no need to look at		 *  the filename again. - kw		 */#ifdef USE_ZLIB		if (strcmp(format_out->name, "www/download") != 0 &&		    (!strcmp(HTAtom_name(myEncoding), "gzip") ||		     !strcmp(HTAtom_name(myEncoding), "x-gzip"))) {		    fclose(fp);		    if (semicolon != NULL)			*semicolon = ';';		    gzfp = gzopen(vmsname, "rb");		    CTRACE(tfp, "HTLoadFile: gzopen of `%s' gives %p\n",				vmsname, (void*)gzfp);		    use_gzread = YES;		} else#endif	/* USE_ZLIB */		{		    StrAllocCopy(anchor->content_type, format->name);		    StrAllocCopy(anchor->content_encoding, HTAtom_name(myEncoding));		    format = HTAtom_for("www/compressed");		}	    } else if ((len = strlen(vmsname)) > 2) {		if ((vmsname[len - 1] == 'Z') &&		    (vmsname[len - 2] == '.' ||		     vmsname[len - 2] == '-' ||		     vmsname[len - 2] == '_') &&		    vmsname[len - 3] != ']' &&		    vmsname[len - 3] != ':') {		    StrAllocCopy(cp, vmsname);		    cp[len - 2] = '\0';		    format = HTFileFormat(cp, &encoding, NULL);		    FREE(cp);		    format = HTCharsetFormat(format, anchor,					     UCLYhndl_HTFile_for_unspec);		    StrAllocCopy(anchor->content_type, format->name);		    StrAllocCopy(anchor->content_encoding, "x-compress");		    format = HTAtom_for("www/compressed");		} else if ((len > 3) &&			   !strcasecomp((char *)&vmsname[len - 2], "gz")) {		    if (vmsname[len - 3] == '.' ||			vmsname[len - 3] == '-' ||			vmsname[len - 3] == '_') {			StrAllocCopy(cp, vmsname);			cp[len - 3] = '\0';			format = HTFileFormat(cp, &encoding, NULL);			FREE(cp);			format = HTCharsetFormat(format, anchor,						 UCLYhndl_HTFile_for_unspec);			StrAllocCopy(anchor->content_type, format->name);			StrAllocCopy(anchor->content_encoding, "x-gzip");#ifdef USE_ZLIB			if (strcmp(format_out->name, "www/download") != 0) {			    fclose(fp);			    if (semicolon != NULL)				*semicolon = ';';			    gzfp = gzopen(vmsname, "rb");			    CTRACE(tfp, "HTLoadFile: gzopen of `%s' gives %p\n",					vmsname, (void*)gzfp);			    use_gzread = YES;			}#else  /* USE_ZLIB */			format = HTAtom_for("www/compressed");#endif	/* USE_ZLIB */		    }		}	    }	    if (semicolon != NULL)		*semicolon = ';';	    FREE(filename);	    FREE(nodename);#ifdef USE_ZLIB	    if (use_gzread) {		if (gzfp) {		    char * sugfname = NULL;		    if (anchor->SugFname) {			StrAllocCopy(sugfname, anchor->SugFname);		    } else {			char * anchor_path = HTParse(anchor->address, "",						     PARSE_PATH + PARSE_PUNCTUATION);			char * lastslash;			HTUnEscape(anchor_path);			lastslash = strrchr(anchor_path, '/');			if (lastslash)			    StrAllocCopy(sugfname, lastslash + 1);			FREE(anchor_path);		    }		    FREE(anchor->content_encoding);		    if (sugfname && *sugfname)			HTCheckFnameForCompression(&sugfname, anchor,						   TRUE);		    if (sugfname && *sugfname)			StrAllocCopy(anchor->SugFname, sugfname);		    FREE(sugfname);		    status = HTParseGzFile(format, format_out,					   anchor,					   gzfp, sink);		} else {		    status = HTLoadError(NULL,					 -(HT_ERROR),					 FAILED_OPEN_COMPRESSED_FILE);		}	    } else#endif /* USE_ZLIB */	    {		status = HTParseFile(format, format_out, anchor, fp, sink);		fclose(fp);	    }	    return status;	}  /* If successful open */	FREE(filename);    }#else /* Unix: */    FREE(filename);    /*    **	For unix, we try to translate the name into the name of a    **	transparently mounted file.    **    **	Not allowed in secure (HTClienntHost) situations. TBL 921019    */#ifndef NO_UNIX_IO    /*	Need protection here for telnet server but not httpd server. */    if (!HTSecure) {		/* try local file system */	char * localname = HTLocalName(addr);	struct stat dir_info;#ifdef HAVE_READDIR	/*	**  Multiformat handling.	**	**  If needed, scan directory to find a good file.	**  Bug:  We don't stat the file to find the length.	*/	if ((strlen(localname) > strlen(MULTI_SUFFIX)) &&	    (0 == strcmp(localname + strlen(localname) - strlen(MULTI_SUFFIX),			 MULTI_SUFFIX))) {	    DIR *dp = 0;	    BOOL forget_multi = NO;	    STRUCT_DIRENT * dirbuf;	    float best = NO_VALUE_FOUND;	/* So far best is bad */	    HTFormat best_rep = NULL;	/* Set when rep found */	    HTAtom * best_enc = NULL;	    char * best_name = NULL;	/* Best dir entry so far */	    char *base = strrchr(localname, '/');	    int baselen = 0;	    if (!base || base == localname) {		forget_multi = YES;	    } else {		*base++ = '\0';		/* Just got directory name */		baselen = strlen(base)- strlen(MULTI_SUFFIX);		base[baselen] = '\0';	/* Chop off suffix */		dp = opendir(localname);	    }	    if (forget_multi || !dp) {		FREE(localname);		FREE(nodename);		return HTLoadError(sink, 500, FAILED_DIR_SCAN);	    }	    while ((dirbuf = readdir(dp)) != NULL) {		/*		**  While there are directory entries to be read...		*/#ifndef DOSPATH		if (dirbuf->d_ino == 0)		    continue;	/* if the entry is not being used, skip it */#endif		if ((int)strlen(dirbuf->d_name) > baselen &&	 /* Match? */		    !strncmp(dirbuf->d_name, base, baselen)) {		    HTAtom * enc;		    HTFormat rep = HTFileFormat(dirbuf->d_name, &enc, NULL);		    float filevalue = HTFileValue(dirbuf->d_name);		    float value = HTStackValue(rep, format_out,						filevalue,						0L  /* @@@@@@ */);		    if (value <= 0.0) {			char * cp = NULL;			int len = strlen(dirbuf->d_name);			enc = NULL;			if (len > 2 &&			    dirbuf->d_name[len - 1] == 'Z' &&			    dirbuf->d_name[len - 2] == '.') {			    StrAllocCopy(cp, dirbuf->d_name);			    cp[len - 2] = '\0';			    format = HTFileFormat(cp, NULL, NULL);			    FREE(cp);			    value = HTStackValue(format, format_out,						 filevalue, 0);			    if (value <= 0.0) {				format = HTAtom_for("application/x-compressed");				value = HTStackValue(format, format_out,						     filevalue, 0);			    }			    if (value <= 0.0) {				format = HTAtom_for("www/compressed");				value = HTStackValue(format, format_out,						     filevalue, 0);			    }			} else if ((len > 3) &&				   !strcasecomp((char *)&dirbuf->d_name[len - 2],						"gz") &&				   dirbuf->d_name[len - 3] == '.') {			    StrAllocCopy(cp, dirbuf->d_name);			    cp[len - 3] = '\0';			    format = HTFileFormat(cp, NULL, NULL);			    FREE(cp);			    value = HTStackValue(format, format_out,						 filevalue, 0);			    if (value <= 0.0) {				format = HTAtom_for("application/x-gzip");				value = HTStackValue(format, format_out,						     filevalue, 0);			    }			    if (value <= 0.0) {				format = HTAtom_for("www/compressed");				value = HTStackValue(format, format_out,						     filevalue, 0);			    }			}		    }		    if (value != NO_VALUE_FOUND) {			CTRACE(tfp, "HTLoadFile: value of presenting %s is %f\n",				    HTAtom_name(rep), value);			if  (value > best) {			    best_rep = rep;			    best_enc = enc;			    best = value;			    StrAllocCopy(best_name, dirbuf->d_name);			}		    }	/* if best so far */		 } /* if match */	    } /* end while directory entries left to read */	    closedir(dp);	    if (best_rep) {		format = best_rep;		myEncoding = best_enc;		base[-1] = '/';		/* Restore directory name */		base[0] = '\0';		StrAllocCat(localname, best_name);		FREE(best_name);	    } else {			/* If not found suitable file */		FREE(localname);		FREE(nodename);		return HTLoadError(sink, 403, FAILED_NO_REPRESENTATION);	    }	    /*NOTREACHED*/	} /* if multi suffix */	/*	**  Check to see if the 'localname' is in fact a directory.  If it	**  is create a new hypertext object containing a list of files and	**  subdirectories contained in the directory.	All of these are	**  links to the directories or files listed.	**  NB This assumes the existence of a type 'STRUCT_DIRENT', which	**  will hold the directory entry, and a type 'DIR' which is used	**  to point to the current directory being read.	*/#ifdef _WINDOWS	if (!exists(localname))#else	if (stat(localname,&dir_info) == -1)	   /* get file information */#endif	{				/* if can't read file information */	    CTRACE(tfp, "HTLoadFile: can't stat %s\n", localname);	}  else {		/* Stat was OK */#ifdef _WINDOWS	    if (stat(localname,&dir_info) == -1) dir_info.st_mode = S_IFDIR;#endif	    if (S_ISDIR(dir_info.st_mode)) {		/*		**  If localname is a directory.		*/		DIR *dp;		struct stat file_info;		CTRACE(tfp, "%s is a directory\n", localname);		/*		**  Check directory access.		**  Selective access means only those directories containing		**  a marker file can be browsed.		*/		if (HTDirAccess == HT_DIR_FORBID) {		    FREE(localname);		    FREE(nodename);		    return HTLoadError(sink, 403, DISALLOWED_DIR_SCAN);		}		if (HTDirAccess == HT_DIR_SELECTIVE) {		    char * enable_file_name =			malloc(strlen(localname)+ 1 +				      strlen(HT_DIR_ENABLE_FILE) + 1);		    if (enable_file_name == NULL)			outofmem(__FILE__, "HTLoadFile");		    strcpy(enable_file_name, localname);		    strcat(enable_file_name, "/");		    strcat(enable_file_name, HT_DIR_ENABLE_FILE);		    if (stat(enable_file_name, &file_info) != 0) {			FREE(localname);			FREE(nodename);			FREE(enable_file_name);			return HTLoadError(sink, 403, DISALLOWED_SELECTIVE_ACCESS);		    }		}		dp = opendir(localname);		if (!dp) {		    FREE(localname);		    FREE(nodename);		    return HTLoadError(sink, 403, FAILED_DIR_UNREADABLE);		}		/*		**  Directory access is allowed and possible.		*/		status = print_local_dir(dp, localname,					anchor, format_out, sink);		FREE(localname);		FREE(nodename);		return status;	/* document loaded, maybe partial */	   } /* end if localname is a directory */	} /* end if file stat worked *//* End of directory reading section*/#endif /* HAVE_READDIR */	{#  ifdef __EMX__	    int len = strlen(localname);	    int bin = ((len > 3) && !strcasecomp(localname + len - 3, ".gz"));	    FILE * fp = fopen(localname, (bin ? "rb" : "r"));#  else	/* !( defined __EMX__ ) */	    FILE * fp = fopen(localname, "r");#  endif	    CTRACE (tfp, "HTLoadFile: Opening `%s' gives %p\n",				 localname, (void*)fp);	    if (fp) {		/* Good! */		int len;		char *cp = NULL;		if (HTEditable(localname)) {		    HTAtom * put = HTAtom_for("PUT");		    HTList * methods = HTAnchor_methods(anchor);		    if (HTList_indexOf(methods, put) == (-1)) {			HTList_addObject(methods, put);		    }		}		/*		**  Fake a Content-Encoding for compressed files. - FM		*/		if (!IsUnityEnc(myEncoding)) {		    /*		     *	We already know from the call to HTFileFormat above		     *	that this is a compressed file, no need to look at		     *	the filename again. - kw		     */#ifdef USE_ZLIB		    if (strcmp(format_out->name, "www/download") != 0 &&			(!strcmp(HTAtom_name(myEncoding), "gzip") ||			 !strcmp(HTAtom_name(myEncoding), "x-gzip"))) {			fclose(fp);			gzfp = gzopen(localname, "rb");			CTRACE(tfp, "HTLoadFile: gzopen of `%s' gives %p\n",				    localname, (void*)gzfp);			use_gzread = YES;		    } else#endif	/* USE_ZLIB */		    {			StrAllocCopy(anchor->content_type, format->name);			StrAllocCopy(anchor->content_encoding, HTAtom_name(myEncoding));			format = HTAtom_for("www/compressed");		    }		} else if ((len = strlen(localname)) > 2) {		    if (localname[len - 1] == 'Z' &&			localname[len - 2] == '.') {			StrAllocCopy(cp, localname);			cp[len - 2] = '\0';			format = HTFileFormat(cp, &encoding, NULL);			FREE(cp);			format = HTCharsetFormat(format, anchor,						 UCLYhndl_HTFile_for_unspec);			StrAllocCopy(anchor->content_type, format->name);			StrAllocCopy(anchor->content_encoding, "x-compress");			format = HTAtom_for("www/compressed");		    } else if ((len > 3) &&			       !strcasecomp((char *)&localname[len - 2],					    "gz") &&			       localname[len - 3] == '.') {			StrAllocCopy(cp, localname);			cp[len - 3] = '\0';			format = HTFileFormat(cp, &encoding, NULL);			FREE(cp);			format = HTCharsetFormat(format, anchor,						 UCLYhndl_HTFile_for_unspec);			StrAllocCopy(anchor->content_type, format->name);			StrAllocCopy(anchor->content_encoding, "x-gzip");#ifdef USE_ZLIB			if (strcmp(format_out->name, "www/download") != 0) {			    fclose(fp);			    gzfp = gzopen(localname, "rb");			    CTRACE(tfp, "HTLoadFile: gzopen of `%s' gives %p\n",					localname, (void*)gzfp);			    use_gzread = YES;			}#else  /* USE_ZLIB */			format = HTAtom_for("www/compressed");#endif	/* USE_ZLIB */		    }		}		FREE(localname);		FREE(nodename);#ifdef USE_ZLIB		if (use_gzread) {		    if (gzfp) {			char * sugfname = NULL;			if (anchor->SugFname) {			    StrAllocCopy(sugfname, anchor->SugFname);			} else {			    char * anchor_path = HTParse(anchor->address, "",							 PARSE_PATH + PARSE_PUNCTUATION);			    char * lastslash;			    HTUnEscape(anchor_path);			    lastslash = strrchr(anchor_path, '/');			    if (lastslash)				StrAllocCopy(sugfname, lastslash + 1);			    FREE(anchor_path);			}			FREE(anchor->content_encoding);			if (sugfname && *sugfname)			    HTCheckFnameForCompression(&sugfname, anchor,						       TRUE);			if (sugfname && *sugfname)			    StrAllocCopy(anchor->SugFname, sugfname);			FREE(sugfname);			status = HTParseGzFile(format, format_out,					       anchor,					       gzfp, sink);		    } else {			status = HTLoadError(NULL,					     -(HT_ERROR),					     FAILED_OPEN_COMPRESSED_FILE);		    }		} else#endif /* USE_ZLIB */		{		    status = HTParseFile(format, format_out, anchor, fp, sink);		    fclose(fp);		}		return status;	    }  /* If successful open */	    FREE(localname);	}  /* scope of fp */    }  /* local unix file system */#endif /* !NO_UNIX_IO */#endif /* VMS */#ifndef DECNET    /*    **	Now, as transparently mounted access has failed, we try FTP.    */    {	/*	**  Deal with case-sensitivity differences on VMS versus Unix.	*/#ifdef VMS	if (strcasecomp(nodename, HTHostName()) != 0)#else	if (strcmp(nodename, HTHostName()) != 0)#endif /* VMS */	{	    FREE(nodename);	    if (!strncmp(addr, "file://localhost", 16)) {		return -1;  /* never go to ftp site when URL			     * is file://localhost			     */	    } else {#ifndef DISABLE_FTP		return HTFTPLoad(addr, anchor, format_out, sink);#else		return -1;#endif /* DISABLE_FTP */	    }	}	FREE(nodename);    }#endif /* !DECNET */    /*    **	All attempts have failed.    */    {	CTRACE(tfp, "Can't open `%s', errno=%d\n", addr, SOCKET_ERRNO);	return HTLoadError(sink, 403, FAILED_FILE_UNREADABLE);    }}