Ejemplo n.º 1
0
/*	Determine file format from file name -- string version
**	------------------------------------------------------
*/
PUBLIC char *HTFileMimeType ARGS2 (
			WWW_CONST char *,	filename,
                        WWW_CONST char *,   default_type)
{
  HTAtom *pencoding;
  HTFormat format;
  int compressed;

  format = HTFileFormat (filename, &pencoding, HTAtom_for (default_type),
                         &compressed);

  if (HTAtom_name (format))
    return HTAtom_name (format);
  else
    return default_type;
}
Ejemplo n.º 2
0
static void SetupFilename(bstring **filename,
			  const char *sug_filename)
{
    HTFormat format;
    HTAtom *encoding;
    char *cp;

    BStrCopy0(*filename, sug_filename);		/* add suggestion info */
    BStrAlloc(*filename, LY_MAXPATH);	/* FIXME */
    change_sug_filename((*filename)->str);
    if (!(HTisDocumentSource())
	&& (cp = strrchr((*filename)->str, '.')) != NULL) {
	format = HTFileFormat((*filename)->str, &encoding, NULL);
	CTRACE((tfp, "... format %s\n", format->name));
	if (!strcasecomp(format->name, "text/html") ||
	    !IsUnityEnc(encoding)) {
	    (*filename)->len = (int) (cp - (*filename)->str);
	    BStrCat0(*filename, TEXT_SUFFIX);
	}
    }
    CTRACE((tfp, "... result %s\n", (*filename)->str));
}
Ejemplo n.º 3
0
/*	Load a document
**	---------------
**
** On entry,
**	addr		must point to the fully qualified hypertext reference.
**			This is the physsical address of the file
**
** On exit,
**	returns		<0		Error has occured.
**			HTLOADED	OK 
**
*/
PUBLIC int HTLoadFile ARGS4 (
	WWW_CONST char *,		addr,
	HTParentAnchor *,	anchor,
	HTFormat,		format_out,
	HTStream *,		sink
)
{
    char * filename;
    HTFormat format;
    int fd = -1;		/* Unix file descriptor number = INVALID */
    char * nodename = 0;
    char * newname=0;	/* Simplified name of file */
    HTAtom * encoding;	/* @@ not used yet */
    int compressed;
    extern char *HTgeticonname(HTFormat, char *);
    
/*	Reduce the filename to a basic form (hopefully unique!)
*/
    StrAllocCopy(newname, addr);
    filename=HTParse(newname, "", PARSE_PATH|PARSE_PUNCTUATION);
    nodename=HTParse(newname, "", PARSE_HOST);
    free(newname);
    
    format = HTFileFormat(filename, &encoding, WWW_PLAINTEXT, &compressed);


#ifdef vms
/* Assume that the file is in Unix-style syntax if it contains a '/'
   after the leading one @@ */
    {
	char * vmsname = strchr(filename + 1, '/') ?
	  vms_name(nodename, filename) : filename + 1;
	fd = open(vmsname, O_RDONLY, 0);
	
/*	If the file wasn't VMS syntax, then perhaps it is ultrix
*/
	if (fd<0) {
	    char ultrixname[INFINITY];
#ifndef DISABLE_TRACE
	    if (www2Trace) fprintf(stderr, "HTFile: Can't open as %s\n", vmsname);
#endif
	    sprintf(ultrixname, "%s::\"%s\"", nodename, filename);
	    fd = open(ultrixname, O_RDONLY, 0);
	    if (fd<0) {
#ifndef DISABLE_TRACE
		if (www2Trace) fprintf(stderr, 
				   "HTFile: Can't open as %s\n", ultrixname);
#endif
	    }
	}
    }
#else

    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 */
	 
    {		/* try local file system */
	char * localname = HTLocalName(addr);
	struct stat dir_info;

        if (!localname)
          goto suicide;
	
#ifdef GOT_READ_DIR

/*			  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;

	    STRUCT_DIRENT * dirbuf;
	    float best = NO_VALUE_FOUND;	/* So far best is bad */
	    HTFormat best_rep = NULL;	/* Set when rep found */
	    STRUCT_DIRENT best_dirbuf;	/* Best dir entry so far */

	    char * base = strrchr(localname, '/');
	    int baselen;

	    if (!base || base == localname) goto forget_multi;
	    *base++ = 0;		/* Just got directory name */
	    baselen = strlen(base)- strlen(MULTI_SUFFIX);
	    base[baselen] = 0;	/* Chop off suffix */

	    dp = opendir(localname);
	    if (!dp) {
forget_multi:
		free(localname);
		return HTLoadError(sink, 500,
			"Multiformat: directory scan failed.");
	    }
	    
	    while (dirbuf = readdir(dp)) {
			/* while there are directory entries to be read */
		if (dirbuf->d_ino == 0) continue;
				/* if the entry is not being used, skip it */
		
		if (!strncmp(dirbuf->d_name, base, baselen)) {	
		    HTFormat rep = HTFileFormat(dirbuf->d_name, &encoding,
                                                WWW_PLAINTEXT, &compressed);
		    float value = HTStackValue(rep, format_out,
		    				HTFileValue(dirbuf->d_name),
						0.0  /* @@@@@@ */);
		    if (value != NO_VALUE_FOUND) {
#ifndef DISABLE_TRACE
		        if (www2Trace) fprintf(stderr,
				"HTFile: value of presenting %s is %f\n",
				HTAtom_name(rep), value);
#endif
			if  (value > best) {
			    best_rep = rep;
			    best = value;
			    best_dirbuf = *dirbuf;
		       }
		    }	/* if best so far */ 		    
		 } /* if match */  
		    
	    } /* end while directory entries left to read */
	    closedir(dp);
	    
	    if (best_rep) {
		format = best_rep;
		base[-1] = '/';		/* Restore directory name */
		base[0] = 0;
		StrAllocCat(localname, best_dirbuf.d_name);
		goto open_file;
		
	    } else { 			/* If not found suitable file */
		free(localname);
		return HTLoadError(sink, 403,	/* List formats? */
		   "Could not find suitable representation for transmission.");
	    }
	    /*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 existance 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.
*/
	
	
	if (stat(localname,&dir_info) == -1) {     /* get file information */
	                               /* if can't read file information */
#ifndef DISABLE_TRACE
	    if (www2Trace) fprintf(stderr, "HTFile: can't stat %s\n", localname);
#endif
	}  else {		/* Stat was OK */
		

	    if (((dir_info.st_mode) & S_IFMT) == S_IFDIR) {
		/* if localname is a directory */	

/*
**
** Read the localdirectory and present a nicely formatted list to the user
** Re-wrote most of the read directory code here, excepting for the checking
** access.
**
** Author: Charles Henrich ([email protected])   10-09-93
**
** This is still pretty messy, need to go through and clean it up at some point
**
*/

/* Define some parameters that everyone should already have */

#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif

#ifndef BUFSIZ
#define BUFSIZ 4096
#endif

                char filepath[MAXPATHLEN];
                char buffer[4096];
     
                char *ptr;
                char *dataptr;

                HText * HT;
                HTFormat format;
                HTAtom *pencoding;

		struct stat statbuf;
		STRUCT_DIRENT * dp;
		DIR *dfp;
 
                int cmpr;
                int count;

#ifndef DISABLE_TRACE
		if (www2Trace)
		    fprintf(stderr,"%s is a directory\n",localname);
#endif			
/*	Check directory access.
**	Selective access means only those directories containing a
**	marker file can be browsed
*/
		if (HTDirAccess == HT_DIR_FORBID) {
		    free(localname);
		    return HTLoadError(sink, 403,
		    "Directory browsing is not allowed.");
		}


		if (HTDirAccess == HT_DIR_SELECTIVE) {
		    char * enable_file_name = 
			malloc(strlen(localname)+ 1 +
			 strlen(HT_DIR_ENABLE_FILE) + 1);
		    strcpy(enable_file_name, localname);
		    strcat(enable_file_name, "/");
		    strcat(enable_file_name, HT_DIR_ENABLE_FILE);
		    if (stat(enable_file_name, &statbuf) != 0) {
			free(localname);
			return HTLoadError(sink, 403,
			"Selective access is not enabled for this directory.");
		    }
		}

 
		dfp = opendir(localname);
		if (!dfp) {
		    free(localname);
		    return HTLoadError(sink, 403, "This directory is not readable.");
		}

/* Suck the directory up into a list to be sorted */

                HTSortInit();

                for(dp=readdir(dfp);dp != NULL;dp=readdir(dfp))
                    {
                    ptr = malloc(strlen(dp->d_name)+1);
                    if(ptr == NULL)
                        {
		        return HTLoadError(sink, 403, "Ran out of memory in directory read!");
                        }
                    strcpy(ptr,dp->d_name);
                     
                    HTSortAdd(ptr);
                    }

                closedir(dfp);

/* Sort the dir list */

                HTSortSort();

/* Start a new HTML page */

                HT = HText_new();
                HText_beginAppend(HT);
                HText_appendText(HT, "<H1>Local Directory ");
                HText_appendText(HT, localname);
                HText_appendText(HT, "</H1>\n");
                HText_appendText(HT,"<DL>\n"); 

/* Sort the list and then spit it out in a nice form */

/* How this for a disgusting loop :) */

                for(count=0,dataptr=HTSortFetch(count); 
                    dataptr != NULL; 
                    free(dataptr), count++, dataptr=HTSortFetch(count))
                    {

/* We dont want to see . */

                    if(strcmp(dataptr,".") == 0) continue;
 
/* If its .. *and* the current directory is / dont show anything, otherwise
/* print out a nice Parent Directory entry.
/* */

                    if(strcmp(dataptr,"..") == 0)
                        {
                        if(strcmp(localname,"/") != 0)
                            {
                            strcpy(buffer,localname);

                            ptr = strrchr(buffer, '/');

                            if(ptr != NULL) *ptr='\0'; 

                            if(buffer[0] == '\0') strcpy(buffer,"/");

                            HText_appendText(HT,"<DD><A HREF=\"");
                            HText_appendText(HT, buffer);

                            HText_appendText(HT,"\"><IMG SRC=\"");
                            HText_appendText(HT, HTgeticonname(NULL, "directory"));

                            HText_appendText(HT,"\"> Parent Directory</a>");
                            continue;
                            }
                        else
                            {
                            continue;
                            }
                        }
                      
/* Get the filesize information from a stat, if we cant stat it, we probably */
/* cant read it either, so ignore it. */

                    sprintf(filepath,"%s/%s",localname, dataptr);

                    if(stat(filepath, &statbuf) == -1) continue;
     
                    HText_appendText(HT,"<DD><A HREF=\"");
                    HText_appendText (HT, localname);

                    if(localname[strlen(localname)-1] != '/') 
                        {
                        HText_appendText (HT, "/");
                        }

                    HText_appendText (HT, dataptr);
                    HText_appendText (HT, "\">");

/* If its a directory, dump out a dir icon, dont bother with anything else */
/* if it is a file try and figure out what type of file it is, and grab    */
/* the appropriate icon.  If we cant figure it out, call it text.  If its  */
/* a compressed file, call it binary no matter what                        */

                    if(statbuf.st_mode & S_IFDIR)
                        {
                        sprintf(buffer,"%s",dataptr);
                        HText_appendText(HT, "<IMG SRC=\"");
                        HText_appendText(HT, HTgeticonname(NULL, "directory"));
                        HText_appendText(HT, "\"> ");
                        }
                    else
                        {
                        sprintf(buffer,"%s (%d bytes)", 
                            dataptr, (int)statbuf.st_size);
              
                        format = HTFileFormat(dataptr, &pencoding, 
                                     WWW_SOURCE, &cmpr);

/* If its executable then call it application, else it might as well be text */

                        if(cmpr == 0)
                            {
                            HText_appendText(HT, "<IMG SRC=\"");
                            if((statbuf.st_mode & S_IXUSR) ||
                               (statbuf.st_mode & S_IXGRP) || 
                               (statbuf.st_mode & S_IXOTH))
                                {
                                HText_appendText(HT, 
                                    HTgeticonname(format, "application"));
                                }
                            else
                                {
                                HText_appendText(HT, 
                                    HTgeticonname(format, "text"));
                                }
                            HText_appendText(HT, "\"> ");
                            }
                        else
                            {
                            HText_appendText(HT, "<IMG SRC=\"");
                            HText_appendText(HT, HTgeticonname(NULL, "application"));
                            HText_appendText(HT, "\"> ");
                            }
                        }

/* Spit out the anchor */

                    HText_appendText (HT, buffer);
                    HText_appendText (HT, "</A>\n");
		    }

/* End of list, clean up and we are done */

            HText_appendText (HT, "</DL>\n");
            HText_endAppend (HT);
            free(localname);
            return HT_LOADED;
	    } /* end if localname is directory */
	
	} /* end if file stat worked */
	
/* End of directory reading section
*/
#endif
open_file:
	{
	    FILE * fp = fopen(localname,"r");
#ifndef DISABLE_TRACE
	    if(www2Trace) fprintf (stderr, "HTFile: Opening `%s' gives %p\n",
				localname, (void*)fp);
#endif
	    if (fp) {		/* Good! */
		if (HTEditable(localname)) {
		    HTAtom * put = HTAtom_for("PUT");
		    HTList * methods = HTAnchor_methods(anchor);
		    if (HTList_indexOf(methods, put) == (-1)) {
			HTList_addObject(methods, put);
		    }
		}
		free(localname);
		HTParseFile(format, format_out, anchor, fp, sink, compressed);
/*
This is closed elsewhere...SWP
		fclose(fp);
*/
		return HT_LOADED;
	    }  /* If succesfull open */
	}    /* scope of fp */
    }  /* local unix file system */    
#endif
#endif

/*	Now, as transparently mounted access has failed, we try FTP.
*/
  suicide:
/*
    return HTFTPLoad(addr, anchor, format_out, sink);
*/
  /* Sorry Charlie...if we are given a file:// URL and it fails, then it
	fails! Do NOT FTP!! */
    return HT_NOT_LOADED;
}
Ejemplo n.º 4
0
/*							HTVMSBrowseDir()
**
**	This function generates a directory listing as an HTML-object
**	for local file URL's.  It assumes the first two elements of
**	of the path are a device followed by a directory:
**
**		file://localhost/device/directory[/[foo]]
**
**	Will not accept 000000 as a directory name.
**	Will offer links to parent through the top directory, unless
**	a terminal slash was included in the calling URL.
**
**	Returns HT_LOADED on success, HTLoadError() messages on error.
**
**	Developed for Lynx by Foteos Macrides ([email protected]).
*/
PUBLIC int HTVMSBrowseDir ARGS4(
	CONST char *,		address,
	HTParentAnchor *,	anchor,
	HTFormat,		format_out,
	HTStream *,		sink
)
{
    HTStructured* target;
    HTStructuredClass targetClass;
    char *pathname = HTParse(address, "", PARSE_PATH + PARSE_PUNCTUATION);
    char *tail = NULL;
    char *title = NULL;
    char *header = NULL;
    char *parent = NULL;
    char *relative = NULL;
    char *cp, *cp1;
    int  pathend, len;
    DIR *dp;
    struct stat file_info;
    time_t NowTime;
    static char ThisYear[8];
    VMSEntryInfo *entry_info = 0;
    char string_buffer[64];

    HTUnEscape(pathname);
    CTRACE((tfp,"HTVMSBrowseDir: Browsing `%s\'\n", pathname));

    /*
     *  Require at least two elements (presumably a device and directory)
     *  and disallow the device root (000000 directory).  Symbolic paths
     *  (e.g., sys$help) should have been translated and expanded (e.g.,
     *  to /sys$sysroot/syshlp) before calling this routine.
     */
    if (((*pathname != '/') ||
	 (cp = strchr(pathname+1, '/')) == NULL ||
	 *(cp + 1) == '\0' ||
	 0 == strncmp((cp + 1), "000000", 6)) ||
	(dp = HTVMSopendir(pathname)) == NULL) {
	FREE(pathname);
	return HTLoadError(sink, 403, COULD_NOT_ACCESS_DIR);
    }

    /*
     *  Set up the output stream.
     */
    _HTProgress (BUILDING_DIR_LIST);
    if (UCLYhndl_HTFile_for_unspec >= 0) {
	HTAnchor_setUCInfoStage(anchor,
				UCLYhndl_HTFile_for_unspec,
				UCT_STAGE_PARSER,
				UCT_SETBY_DEFAULT);
    }
    target = HTML_new(anchor, format_out, sink);
    targetClass = *(target->isa);

    /*
     *  Set up the offset string of the anchor reference,
     *  and strings for the title and header.
     */
    cp = strrchr(pathname, '/');  /* find lastslash */
    StrAllocCopy(tail, (cp+1)); /* take slash off the beginning */
    if (*tail != '\0') {
	StrAllocCopy(title, tail);
	*cp = '\0';
	if ((cp1=strrchr(pathname, '/')) != NULL &&
	    cp1 != pathname &&
	    strncmp((cp1+1), "000000", 6))
	    StrAllocCopy(parent, (cp1+1));
	*cp = '/';
    } else {
	pathname[strlen(pathname)-1] = '\0';
	cp = strrchr(pathname, '/');
	StrAllocCopy(title, (cp+1));
	pathname[strlen(pathname)] = '/';
    }
    StrAllocCopy(header, pathname);

    /*
     *  Initialize path name for HTStat().
     */
    pathend = strlen(pathname);
    if (*(pathname+pathend-1) != '/') {
	StrAllocCat(pathname, "/");
	pathend++;
    }

    /*
     *  Output the title and header.
     */
    START(HTML_HTML);
    PUTC('\n');
    START(HTML_HEAD);
    PUTC('\n');
    HTUnEscape(title);
    START(HTML_TITLE);
    PUTS(title);
    PUTS(" directory");
    END(HTML_TITLE);
    PUTC('\n');
    FREE(title);
    END(HTML_HEAD);
    PUTC('\n');
    START(HTML_BODY);
    PUTC('\n');
    HTUnEscape(header);
    START(HTML_H1);
    PUTS(header);
    END(HTML_H1);
    PUTC('\n');
    if (HTDirReadme == HT_DIR_README_TOP) {
	FILE * fp;
	if (header[strlen(header)-1] != '/')
	    StrAllocCat(header, "/");
	StrAllocCat(header, HT_DIR_README_FILE);
	if ((fp = fopen(header,	 "r")) != NULL) {
	    START(HTML_PRE);
	    for(;;) {
		char c = fgetc(fp);
		if (c == (char)EOF)
		    break;
#ifdef NOTDEFINED
		switch (c) {
		    case '&':
		    case '<':
		    case '>':
			PUTC('&');
			PUTC('#');
			PUTC((char)(c / 10));
			PUTC((char) (c % 10));
			PUTC(';');
			break;
		    default:
			PUTC(c);
		}
#else
		PUTC(c);
#endif /* NOTDEFINED */
	    }
	    END(HTML_PRE);
	    fclose(fp);
	}
    }
    FREE(header);
    if (parent) {
	HTSprintf0(&relative, "%s/..", tail);
	HTStartAnchor(target, "", relative);
	PUTS("Up to ");
	HTUnEscape(parent);
	PUTS(parent);
	END(HTML_A);
	START(HTML_P);
	PUTC('\n');
	FREE(relative);
	FREE(parent);
    }

    /*
     *  Set up the date comparison.
     */
    NowTime = time(NULL);
    strcpy(ThisYear, (char *)ctime(&NowTime)+20);
    ThisYear[4] = '\0';

    /*
     * Now, generate the Btree and put it out to the output stream.
     */
    {
	char dottest = 2;	/* To avoid two strcmp() each time */
	STRUCT_DIRENT *dirbuf;
	HTBTree *bt;

	/* Set up sort key and initialize BTree */
	bt = HTBTree_new((HTComparer) compare_VMSEntryInfo_structs);

	/* Build tree */
	while ((dirbuf = HTVMSreaddir(dp))) {
	    HTAtom *encoding = NULL;
	    HTFormat format;

	    /* Skip if not used */
	    if (!dirbuf->d_ino)	{
		continue;
	    }

	    /* Current and parent directories are never shown in list */
	    if (dottest && (!strcmp(dirbuf->d_name, ".") ||
			    !strcmp(dirbuf->d_name, ".."))) {
		dottest--;
		continue;
	    }

	    /* Don't show the selective enabling file
	     * unless version numbers are included */
	    if (!strcasecomp(dirbuf->d_name, HT_DIR_ENABLE_FILE)) {
		continue;
	    }

	    /* Skip files beginning with a dot? */
	    if ((no_dotfiles || !show_dotfiles) && *dirbuf->d_name == '.') {
		continue;
	    }

	    /* OK, make an lstat() and get a key ready. */
	    *(pathname+pathend) = '\0';
	    StrAllocCat(pathname, dirbuf->d_name);
	    if (HTStat(pathname, &file_info)) {
		/* for VMS the failure here means the file is not readable...
		   we however continue to browse through the directory... */
		continue;
	    }
	    entry_info = (VMSEntryInfo *)malloc(sizeof(VMSEntryInfo));
	    if (entry_info == NULL)
		outofmem(__FILE__, "HTVMSBrowseDir");
	    entry_info->type = 0;
	    entry_info->size = 0;
	    entry_info->date = 0;
	    entry_info->filename = 0;
	    entry_info->display = TRUE;

	    /* Get the type */
	    format = HTFileFormat(dirbuf->d_name, &encoding,
				  (CONST char **)&cp);
	    if (!cp) {
		if(!strncmp(HTAtom_name(format), "application",11))
		{
		    cp = HTAtom_name(format) + 12;
		    if(!strncmp(cp,"x-", 2))
			cp += 2;
		}
		else
		    cp = HTAtom_name(format);
	    }
	    StrAllocCopy(entry_info->type, cp);

	    StrAllocCopy(entry_info->filename, dirbuf->d_name);
	    if (S_ISDIR(file_info.st_mode)) {
		/* strip .DIR part... */
		char *dot;
		dot = strstr(entry_info->filename, ".DIR");
		if (dot)
		   *dot = '\0';
		LYLowerCase(entry_info->filename);
		StrAllocCopy(entry_info->type, "Directory");
	    } else {
		if ((cp = strstr(entry_info->filename, "READ")) == NULL) {
		    cp = entry_info->filename;
		} else {
		    cp += 4;
		    if (!strncmp(cp, "ME", 2)) {
			cp += 2;
			while (cp && *cp && *cp != '.') {
			    cp++;
			}
		    } else if (!strncmp(cp, ".ME", 3)) {
			cp = (entry_info->filename +
			      strlen(entry_info->filename));
		    } else {
			cp = entry_info->filename;
		    }
		}
		LYLowerCase(cp);
		if (((len = strlen(entry_info->filename)) > 2) &&
		    entry_info->filename[len-1] == 'z') {
		    if (entry_info->filename[len-2] == '.' ||
			entry_info->filename[len-2] == '_')
			entry_info->filename[len-1] = 'Z';
		}
	    }

	    /* Get the date */
	    {
		char *t = (char *)ctime((CONST time_t *)&file_info.st_ctime);
		*(t+24) = '\0';

		StrAllocCopy(entry_info->date, (t+4));
		*((entry_info->date)+7) = '\0';
		if ((atoi((t+19))) < atoi(ThisYear))
		    StrAllocCat(entry_info->date,  (t+19));
		else {
		    StrAllocCat(entry_info->date, (t+11));
		    *((entry_info->date)+12) = '\0';
		}
	    }

	    /* Get the size */
	    if (!S_ISDIR(file_info.st_mode))
		entry_info->size = (unsigned int)file_info.st_size;
	    else
		entry_info->size = 0;

	    /* Now, update the BTree etc. */
	    if(entry_info->display)
	      {
		 CTRACE((tfp,"Adding file to BTree: %s\n",
						      entry_info->filename));
		 HTBTree_add(bt, entry_info);
	      }

	} /* End while HTVMSreaddir() */

	FREE(pathname);
	HTVMSclosedir(dp);

	START(HTML_PRE);
	/*
	 * Run through the BTree printing out in order
	 */
	{
	    HTBTElement * ele;
	    int i;
	    for (ele = HTBTree_next(bt, NULL);
		 ele != NULL;
		 ele = HTBTree_next(bt, ele))
	    {
		entry_info = (VMSEntryInfo *)HTBTree_object(ele);

		/* Output the date */
		if(entry_info->date)
		       {
			     PUTS(entry_info->date);
			     PUTS("  ");
		       }
		else
			PUTS("     * ");

		/* Output the type */
		if(entry_info->type)
		  {
		    for(i = 0; entry_info->type[i] != '\0' && i < 15; i++)
			PUTC(entry_info->type[i]);
		    for(; i < 17; i++)
			PUTC(' ');

		  }

		/* Output the link for the name */
		HTDirEntry(target, tail, entry_info->filename);
		PUTS(entry_info->filename);
		END(HTML_A);

		/* Output the size */
		if(entry_info->size)
		  {
			  if(entry_info->size < 1024)
			      sprintf(string_buffer,"  %d bytes",
							entry_info->size);
			  else
			      sprintf(string_buffer,"  %dKb",
							entry_info->size/1024);
			  PUTS(string_buffer);
		  }

		PUTC('\n'); /* end of this entry */

		free_VMSEntryInfo_contents(entry_info);
	    }
	}

	HTBTreeAndObject_free(bt);

    } /* End of both BTree loops */

    /*
     *  Complete the output stream.
     */
    END(HTML_PRE);
    PUTC('\n');
    END(HTML_BODY);
    PUTC('\n');
    END(HTML_HTML);
    PUTC('\n');
    FREE(tail);
    FREE_TARGET;

    return HT_LOADED;

} /* End of directory reading section */
Ejemplo n.º 5
0
/*		Load Document from HTTP Server			HTLoadHTTP()
**		==============================
**
**	Given a hypertext address, this routine loads a document.
**
**
** On entry,
**	arg	is the hypertext reference of the article to be loaded.
**	gate	is nill if no gateway, else the gateway address.
**
** On exit,
**	returns	>=0	If no error, a good socket number
**		<0	Error.
**
**	The socket must be closed by the caller after the document has been
**	read.
**
*/
PUBLIC int HTLoadHTTP ARGS4 (CONST char *, arg,
	CONST char *,	gate, 
	HTAnchor *,	anAnchor,
	int,		diag)
{
    int s;				/* Socket number for returned data */
    char *command;			/* The whole command */
    int status;				/* tcp return */
    char host[256];         /* Hold on to the host */
 
    SockA soc_address;			/* Binary network address */
    SockA * sin = &soc_address;

    if (!arg) return -3;		/* Bad if no name sepcified	*/
    if (!*arg) return -2;		/* Bad if name had zero length	*/

/*  Set up defaults:
*/
#ifdef DECNET
	sin->sdn_family = AF_DECnet;	    /* Family = DECnet, host order */
	sin->sdn_objnum = DNP_OBJ;          /* Default: http object number */
#else  /* Internet */
	sin->sin_family = AF_INET;	    /* Family = internet, host order */
	sin->sin_port = htons(TCP_PORT);    /* Default: http port    */
#endif

    if (TRACE) {
        if (gate) fprintf(stderr,
		"HTTPAccess: Using gateway %s for %s\n", gate, arg);
        else fprintf(stderr, "HTTPAccess: Direct access for %s\n", arg);
    }
    
/* Get node name and optional port number:
*/
    {
	char *p1 = HTParse(gate ? gate : arg, "", PARSE_HOST);
    strcpy(host, p1);
	int status = HTParseInet(sin, p1);  /* TBL 920622 */
        free(p1);
	if (status) return status;   /* No such host for example */
    }
    
   
/*	Now, let's get a socket set up from the server for the sgml data:
*/      
#ifdef DECNET
    s = socket(AF_DECnet, SOCK_STREAM, 0);
#else
    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
#endif
    status = connect(s, (struct sockaddr*)&soc_address, sizeof(soc_address));
    if (status < 0) {
#ifndef DECNET
	/* This code is temporary backward-compatibility. It should
	   go away when no server runs on port 2784 alone */
	if (sin->sin_port == htons(TCP_PORT)) {  /* Try the old one */
	  if (TRACE) printf (
	    "HTTP: Port %d doesn't answer (errno = %d). Trying good old port %d...\n",
	    TCP_PORT, errno, OLD_TCP_PORT);
	  sin->sin_port = htons(OLD_TCP_PORT);
	  /* First close current socket and open a clean one */
	  status = NETCLOSE (s);
	  s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	  status = connect(s, (struct sockaddr*)&soc_address,
			   sizeof(soc_address));
	}
	if (status < 0)
#endif
	  {
	    if (TRACE) fprintf(stderr, 
	      "HTTP: Unable to connect to remote host for `%s' (errno = %d).\n", arg, errno);
	    /* free(command);   BUG OUT TBL 921121 */
	    return HTInetStatus("connect");
	  }
      }
    
    if (TRACE) fprintf(stderr, "HTTP connected, socket %d\n", s);

/*	Ask that node for the document,
**	omitting the host name & anchor if not gatewayed.
*/        
    if (gate) {
        command = malloc(4 + strlen(arg)+ 2 + 1);
        if (command == NULL) outofmem(__FILE__, "HTLoadHTTP");
        strcpy(command, "GET ");
	strcat(command, arg);
    } else if ( HTTP11 ) { /* not gatewayed */
        /* Switch this to HTTP 1.1 */
	char * p1 = HTParse(arg, "", PARSE_PATH|PARSE_PUNCTUATION);
        command = malloc(4 + strlen(arg) + 11 + 6 + strlen(host) + 2 + 20 + 2 + 1);
        if (command == NULL) outofmem(__FILE__, "HTLoadHTTP");
        strcpy(command, "GET ");
	    strcat(command, arg);
        strcat(command, " HTTP/1.1\r\n");
        strcat(command, "Host: ");
        strcat(command, host);
        strcat(command, "\r\n");
        strcat(command, "Connection: close\r\n");
    } else {
	char * p1 = HTParse(arg, "", PARSE_PATH|PARSE_PUNCTUATION);
        command = malloc(4 + strlen(p1)+ 2 + 1);
        if (command == NULL) outofmem(__FILE__, "HTLoadHTTP");
        strcpy(command, "GET ");
	strcat(command, p1);
	free(p1);
    }
    strcat(command, "\r\n");		/* Include CR for telnet compat. */
	    

    if (TRACE) fprintf(stderr, "HTTP writing command `%s' to socket %d\n", command, s);
    
#ifdef NOT_ASCII
    {
    	char * p;
	for(p = command; *p; p++) {
	    *p = TOASCII(*p);
	}
    }
#endif

    status = NETWRITE(s, command, (int)strlen(command));
    free(command);
    if (status<0) {
	if (TRACE) fprintf(stderr, "HTTPAccess: Unable to send command.\n");
	    return HTInetStatus("send");
    }

    /* Skip the HTTP 1.1 headers */
    if ( HTTP11 ) {
        char buffer[2];
        int endhdr = 0;
        while ( 1 ) {
            int rc = read(s, buffer, 1) ;
            if ( TRACE ) fprintf(stderr,"%c",buffer[0]);
            if ( rc < 1 ) {
	        if (TRACE) fprintf(stderr, "HTTPAccess: EOF reading headers.\n");
	        return HTInetStatus("send");
            }
            if ( buffer[0] == '\r' && endhdr == 0 ) endhdr = 1;
            else if ( buffer[0] == '\n' && endhdr == 1 ) endhdr = 2;
            else if ( buffer[0] == '\r' && endhdr == 2 ) endhdr = 3;
            else if ( buffer[0] == '\n' && endhdr == 3 ) break;
            else endhdr = 0;
        }
    }
/*	Now load the data
*/
    
    {
      char *url = HTParse(arg, "",
                          PARSE_ACCESS | PARSE_HOST | PARSE_PATH |
                          PARSE_PUNCTUATION);
      int compressed;
      int fmt = 
        diag ? WWW_PLAINTEXT : HTFileFormat (url, WWW_HTML, &compressed);

      HTParseFormat(fmt, (HTParentAnchor *) anAnchor, s, compressed);

      free (url);
    }
      
    if (TRACE) fprintf(stderr, "HTTP: close socket %d.\n", s);
    status = NETCLOSE(s);

    return HT_LOADED;			/* Good return */
}
Ejemplo n.º 6
0
PUBLIC int HTLoadHTTP ARGS4 (
	char *, 		arg,
	HTParentAnchor *,	anAnchor,
	HTFormat,		format_out,
	HTStream*,		sink)
{
  int s;				/* Socket number for returned data */
  char *command;			/* The whole command */
  char *eol;			/* End of line if found */
  char *start_of_data;		/* Start of body of reply */
  int status;				/* tcp return */
  int bytes_already_read;
  char crlf[3];			/* A CR LF equivalent string */
  HTStream *target;		/* Unconverted data */
  HTFormat format_in;			/* Format arriving in the message */

  char *line_buffer;
  char *line_kept_clean;
  BOOL extensions;		/* Assume good HTTP server */
  int compressed;
  char line[2048];	/* bumped up to cover Kerb huge headers */

  int length, doing_redirect, rv;
  int already_retrying = 0;
  int return_nothing;

  int i;
  int keepingalive = 0;
  char *p;

/*SWP*/
  int statusError=0;

  if (!arg)
    {
      status = -3;
      HTProgress ("Bad request.");
      goto done;
    }
  if (!*arg)
    {
      status = -2;
      HTProgress ("Bad request.");
      goto done;
    }

  sprintf(crlf, "%c%c", CR, LF);

  /* At this point, we're talking HTTP/1.0. */
  extensions = YES;

 try_again:
  /* All initializations are moved down here from up above,
     so we can start over here... */
  eol = 0;
  bytes_already_read = 0;
  length = 0;
  doing_redirect = 0;
  compressed = 0;
  target = NULL;
  line_buffer = NULL;
  line_kept_clean = NULL;
  return_nothing = 0;

	/* okay... addr looks like http://hagbard.ncsa.uiuc.edu/blah/etc.html
	lets crop it at the 3rd '/' */
	for(p = arg,i=0;*p && i!=3;p++)
		if(*p=='/') i++;

	if(i==3)
		i = p-arg; /* i = length not counting last '/' */
	else
		i = 0;

	if((lsocket != -1) && i && addr && !strncmp(addr,arg,i)){
		/* keepalive is active and addresses match -- try the old socket */
		s = lsocket;
		keepingalive = 1; /* flag in case of network error due to server timeout*/
		lsocket = -1; /* prevent looping on failure */
#ifndef DISABLE_TRACE
		if (www2Trace)
			fprintf (stderr,
				 "HTTP: Keep-Alive reusing '%s'\n",addr);
#endif
/*
		if (addr && *addr) {
			sprintf(tmpbuf,"Reusing socket from %s.",addr);
			HTProgress(tmpbuf);
		}
*/
	} else {
		if(addr) free(addr);
		/* save the address for next time around */
		addr = malloc(i+1);
		strncpy(addr,arg,i);
		*(addr+i)=0;

		keepingalive = 0; /* just normal opening of the socket */
		if(lsocket != -1) NETCLOSE(lsocket); /* no socket leaks here */
		lsocket = -1; /*dont assign until we know the server says okay */

#ifndef DISABLE_TRACE
		if (www2Trace)
			fprintf (stderr,
				 "HTTP: Keep-Alive saving '%s'\n",addr);
#endif
/*
		if (addr && *addr) {
			sprintf(tmpbuf,"Saving %s for possible socket reuse.",addr);
			HTProgress(tmpbuf);
		}
*/
	}

  if (!keepingalive) {
      status = HTDoConnect (arg, "HTTP", TCP_PORT, &s);
      if (status == HT_INTERRUPTED){
	  /* Interrupt cleanly. */
#ifndef DISABLE_TRACE
	  if (www2Trace)
	      fprintf (stderr,
		       "HTTP: Interrupted on connect; recovering cleanly.\n");
#endif
	  HTProgress ("Connection interrupted.");
	  /* status already == HT_INTERRUPTED */
	  goto done;
      }
      if (status < 0) {
#ifndef DISABLE_TRACE
	  if (www2Trace)
	      fprintf(stderr,
		      "HTTP: Unable to connect to remote host for `%s' (errno = %d).\n", arg, errno);
#endif
	  HTProgress ("Unable to connect to remote host.");
	  status = HT_NO_DATA;
	  goto done;
      }
  }
  /*	Ask that node for the document,
   **	omitting the host name & anchor
   */
  {
    char * p1 = HTParse(arg, "", PARSE_PATH|PARSE_PUNCTUATION);
    command = malloc(5 + strlen(p1)+ 2 + 31);

    if (do_post && !do_put)
      strcpy(command, "POST ");
    else if (do_post && do_put)
      strcpy(command, "PUT ");
    else if (do_head)
      strcpy(command, "HEAD ");
    else if (do_meta)
      strcpy(command, "META ");
    else
      strcpy(command, "GET ");

    /*
     * For a gateway, the beginning '/' on the request must
     * be stripped before appending to the gateway address.
     */
    if ((using_gateway)||(using_proxy)) {
        strcat(command, p1+1);
    }
    else
        strcat(command, p1);
    free(p1);
  }
  if (extensions)
    {
      strcat(command, " ");
      strcat(command, HTTP_VERSION);
    }

  strcat(command, crlf);	/* CR LF, as in rfc 977 */

  if (extensions)
    {
#ifdef SAM_NOT_YET
		/* SAM This produces an absolutely huge Accept: line.  While
		   there is probably a better way to turn this off, just
		   compiling it out works for now.
		*/
      int n, i;

      if (!HTPresentations) HTFormatInit();
      n = HTList_count(HTPresentations);

      begin_ptr=command+strlen(command);
      env_length=0;

      sprintf(line, "Accept:");
      env_length+=strlen(line);
      StrAllocCat(command, line);

	/* KCMS Accept Header - swp */
	if (KCMS_Return_Format==JPEG) {
		sprintf(line," image/x-pcd-jpeg,");
		StrAllocCat(command, line);
		env_length+=strlen(line);
	}
	else if (KCMS_Return_Format==JYCC) {
		sprintf(line," image/x-pcd-jycc,");
		StrAllocCat(command, line);
		env_length+=strlen(line);
	}
	else if (KCMS_Return_Format==GIF) {
		sprintf(line," image/x-pcd-gif,");
		StrAllocCat(command, line);
		env_length+=strlen(line);
	}

      for(i=0; i<n; i++)
        {
          HTPresentation * pres = HTList_objectAt(HTPresentations, i);
          if (pres->rep_out == WWW_PRESENT)
            {
		sprintf(line, " %s,",HTAtom_name(pres->rep));
		env_length+=strlen(line);
		StrAllocCat(command, line);
		if (env_length>200) {
			if ((tmp_ptr=strrchr(command,','))!=NULL) {
				*tmp_ptr='\0';
			}
			sprintf(line, "%c%c",CR,LF);
			StrAllocCat(command, line);

			begin_ptr=command+strlen(command);
			sprintf(line, "Accept:");
			env_length=strlen(line);
			StrAllocCat(command, line);
		}
            }
        }

      /* This gets rid of the last comma. */
      if ((tmp_ptr=strrchr(command,','))!=NULL) {
	*tmp_ptr='\0';
	sprintf(line, "%c%c",CR,LF);
	StrAllocCat(command, line);
      }
      else { /* No accept stuff...get rid of "Accept:" */
	begin_ptr='\0';
      }
#endif

      /* if reloading, send no-cache pragma to proxy servers. --swp */
      /* original patch from Ari L. <*****@*****.**> */
      if (reloading) {
	sprintf(line, "Pragma: no-cache%c%c", CR, LF);
	StrAllocCat(command, line);
      }

      /*This is just used for "not" sending this header on a proxy request*/
      if (useKeepAlive) {
	sprintf(line, "Connection: keep-alive%c%c", CR, LF);
	StrAllocCat(command, line);
      }

      if (sendAgent) {
	sprintf(line, "User-Agent: %s%c%c",agent[selectedAgent],CR,LF);
/*
	sprintf(line, "User-Agent:  %s/%s  libwww/%s%c%c",
		HTAppName ? HTAppName : "unknown",
		HTAppVersion ? HTAppVersion : "0.0",
		HTLibraryVersion, CR, LF);
*/
	StrAllocCat(command, line);
      }

      if (sendReferer) {
	/* HTTP Referer field, specifies back-link URL   - amb */
	if (HTReferer) {
		sprintf(line, "Referer: %s%c%c", HTReferer, CR, LF);
		StrAllocCat(command, line);
		HTReferer = NULL;
	}
      }

      {
	char *tmp,*startPtr,*endPtr;

	/* addr is always in URL form */

	if (addr && !using_proxy && !using_gateway) {
		tmp=strdup(addr);
		startPtr=strchr(tmp,'/');
		if (startPtr) {
			startPtr+=2; /*now at begining of hostname*/
			if (*startPtr) {
				endPtr=strchr(startPtr,':');
				if (!endPtr) {
					endPtr=strchr(startPtr,'/');
					if (endPtr && *endPtr) {
						*endPtr='\0';
					}
				}
				else {
					*endPtr='\0';
				}

				sprintf(line, "Host: %s%c%c", startPtr, CR, LF);
				StrAllocCat(command, line);

				free(tmp);
				tmp=startPtr=endPtr=NULL;
			}
		}
	}
	else if (using_proxy || using_gateway) {
		sprintf(line, "Host: %s%c%c", proxy_host_fix, CR, LF);
		StrAllocCat(command, line);
	}
      }

      /* SWP -- 7/10/95 */
      /* HTTP Extension headers */
      /* Domain Restriction */
      sprintf(line,"Extension: Notify-Domain-Restriction%c%c",CR,LF);
      StrAllocCat(command,line);

      /* BJS -- 12/05/95 -- allow arbitrary headers sent from browser */
      if(extra_headers){
		int h;
		for(h=0;extra_headers[h];h++){
			sprintf(line,"%s%c%c",extra_headers[h],CR,LF);
			StrAllocCat(command,line);
		}
      }

      {
        char *docname;
        char *hostname;
        char *colon;
        int portnumber;
        char *auth;

        docname = HTParse(arg, "", PARSE_PATH);
        hostname = HTParse(arg, "", PARSE_HOST);
        if (hostname &&
            NULL != (colon = strchr(hostname, ':')))
          {
            *(colon++) = '\0';	/* Chop off port number */
            portnumber = atoi(colon);
          }
        else portnumber = 80;

        if (NULL!=(auth=HTAA_composeAuth(hostname, portnumber, docname)))
          {
            sprintf(line, "%s%c%c", auth, CR, LF);
            StrAllocCat(command, line);
          }
#ifndef DISABLE_TRACE
        if (www2Trace)
          {
            if (auth)
              fprintf(stderr, "HTTP: Sending authorization: %s\n", auth);
            else
              fprintf(stderr, "HTTP: Not sending authorization (yet)\n");
          }
#endif
        FREE(hostname);
        FREE(docname);
      }
    }

  if (do_post && !do_put)
    {
#ifndef DISABLE_TRACE
      if (www2Trace)
        fprintf (stderr, "HTTP: Doing post, content-type '%s'\n",
                 post_content_type);
#endif
      sprintf (line, "Content-type: %s%c%c",
               post_content_type ? post_content_type : "lose", CR, LF);
      StrAllocCat(command, line);
      {
        int content_length;
        if (!post_data)
          content_length = 4; /* 4 == "lose" :-) */
        else
          content_length = strlen (post_data);
        sprintf (line, "Content-length: %d%c%c",
                 content_length, CR, LF);
        StrAllocCat(command, line);
      }

      StrAllocCat(command, crlf);	/* Blank line means "end" */

      if (post_data)
        StrAllocCat(command, post_data);
      else
        StrAllocCat(command, "lose");
    }
  else if (do_post && do_put)
    {
      sprintf (line, "Content-length: %d%c%c",
	       put_file_size, CR, LF);
      StrAllocCat(command, line);
      StrAllocCat(command, crlf);	/* Blank line means "end" */
    }
  else {
      StrAllocCat(command, crlf);	/* Blank line means "end" */
  }

#ifndef DISABLE_TRACE
  if (www2Trace)
    fprintf (stderr, "Writing:\n%s----------------------------------\n",
             command);
#endif

/*
  HTProgress ("Sending HTTP request.");
*/

  status = NETWRITE(s, command, (int)strlen(command));
  if (do_post && do_put) {
      char buf[BUFSIZ];
      int upcnt=0,n;

      while (status>0) {
	n=fread(buf,1,BUFSIZ-1,put_fp);

	upcnt+= status = NETWRITE(s, buf, n);
#ifndef DISABLE_TRACE
	if (www2Trace) {
		fprintf(stderr,"[%d](%d) %s",status,n,buf);
	}
#endif
	if (feof(put_fp)) {
		break;
	}
      }

      if (status<0 || !feof(put_fp) || upcnt!=put_file_size) {
	char tmpbuf[BUFSIZ];

	sprintf(tmpbuf,"Status: %d  --  EOF: %d  --  UpCnt/FileSize: %d/%d\n\nThe server you connected to either does not support\nthe PUT method, or an error occurred.\n\nYour upload was corrupted! Please try again!",status,(feof(put_fp)?1:0),upcnt,put_file_size);
	application_error(tmpbuf,"Upload Error!");
      }
  }

  /* Twirl on each request to make things look nicer -- SWP */
  HTCheckActiveIcon(1);

#ifndef DISABLE_TRACE
  if (httpTrace) {
	fprintf(stderr,"%s",command);
  }
#endif

  free (command);
  if (status <= 0)
    {
      if (status == 0)
        {
#ifndef DISABLE_TRACE
          if (www2Trace)
            fprintf (stderr, "HTTP: Got status 0 in initial write\n");
#endif
          /* Do nothing. */
        }
      else if
        ((errno == ENOTCONN || errno == ECONNRESET || errno == EPIPE) &&
         !already_retrying &&
         /* Don't retry if we're posting. */ !do_post)
          {
            /* Arrrrgh, HTTP 0/1 compability problem, maybe. */
#ifndef DISABLE_TRACE
            if (www2Trace)
              fprintf
                (stderr,
                 "HTTP: BONZO ON WRITE Trying again with HTTP0 request.\n");
#endif
/*
            HTProgress ("Retrying as HTTP0 request.");
*/
            NETCLOSE(s);
// SAM            extensions = NO;
            already_retrying = 1;
            goto try_again;
          }
      else
        {
		if(keepingalive){
#ifndef DISABLE_TRACE
			if (www2Trace)
				fprintf (stderr, "HTTP: Timeout on Keep-Alive. Retrying.\n");
#endif
			HTProgress("Server Timeout: Reconnecting");
			goto try_again;
		}
#ifndef DISABLE_TRACE
          if (www2Trace)
            fprintf (stderr, "HTTP: Hit unexpected network WRITE error; aborting connection.\n");
#endif
          NETCLOSE (s);
          status = -1;
          HTProgress ("Unexpected network write error; connection aborted.");
          goto done;
        }
    }

#ifndef DISABLE_TRACE
  if (www2Trace)
    fprintf (stderr, "HTTP: WRITE delivered OK\n");
#endif
  HTProgress ("Done sending HTTP request; waiting for response.");

  /*	Read the first line of the response
   **	-----------------------------------
   */

  {
      /* Get numeric status etc */
      BOOL end_of_file = NO;
      int buffer_length = INIT_LINE_SIZE;

      line_buffer = (char *) malloc(buffer_length * sizeof(char));

      do {
	  /* Loop to read in the first line */
	  /* Extend line buffer if necessary for those crazy WAIS URLs ;-) */
	  if (buffer_length - length < LINE_EXTEND_THRESH) {
	      buffer_length = buffer_length + buffer_length;
	      line_buffer =
		  (char *) realloc(line_buffer, buffer_length * sizeof(char));
          }
#ifndef DISABLE_TRACE
	  if (www2Trace)
	      fprintf (stderr, "HTTP: Trying to read %d\n",
		       buffer_length - length - 1);
#endif
	  status = NETREAD(s, line_buffer + length,
			   buffer_length - length - 1);
#ifndef DISABLE_TRACE
	  if (www2Trace)
	      fprintf (stderr, "HTTP: Read %d\n", status);
#endif
	  if (status <= 0) {
	      /* Retry if we get nothing back too;
		 bomb out if we get nothing twice. */
	      if (status == HT_INTERRUPTED) {
#ifndef DISABLE_TRACE
		  if (www2Trace)
		      fprintf (stderr, "HTTP: Interrupted initial read.\n");
#endif
		  HTProgress ("Connection interrupted.");
		  status = HT_INTERRUPTED;
		  NETCLOSE (s);
		  goto clean_up;
              } else
		  if
		  (status < 0 &&
		   (errno == ENOTCONN || errno == ECONNRESET || errno == EPIPE)
		   && !already_retrying && !do_post)
		      {
			  /* Arrrrgh, HTTP 0/1 compability problem, maybe. */
#ifndef DISABLE_TRACE
			  if (www2Trace)
			      fprintf (stderr, "HTTP: BONZO Trying again with HTTP0 request.\n");
#endif
			  NETCLOSE(s);
			  if (line_buffer)
			      free(line_buffer);
			  if (line_kept_clean)
			      free(line_kept_clean);

			  extensions = NO;
			  already_retrying = 1;
			  HTProgress ("Retrying as HTTP0 request.");
			  goto try_again;
		      } else {
			      if(keepingalive){
#ifndef DISABLE_TRACE
					if (www2Trace)
						fprintf (stderr, "HTTP: Timeout on Keep-Alive. Retrying.\n");
#endif
					HTProgress("Server Timeout: Reconnecting");
					goto try_again;
			      }
#ifndef DISABLE_TRACE
			  if (www2Trace)
			      fprintf (stderr, "HTTP: Hit unexpected network read error; aborting connection; status %d.\n", status);
#endif
			  HTProgress
			      ("Unexpected network read error; connection aborted.");

			  NETCLOSE (s);
			  status = -1;
			  goto clean_up;
		      }
          }

	  bytes_already_read += status;
	  {
	      char line[256];
	      sprintf (line, "Read %d bytes of data.", bytes_already_read);
	      HTProgress (line);
	  }

	  if (status == 0) {
	      end_of_file = YES;
	      break;
          }
	  line_buffer[length+status] = 0;

	  if (line_buffer) {
	      if (line_kept_clean)
		  free (line_kept_clean);
	      line_kept_clean = (char *)malloc (buffer_length * sizeof (char));
/*
	      bcopy (line_buffer, line_kept_clean, buffer_length);
*/
	      memcpy (line_kept_clean, line_buffer, buffer_length);
          }

	  eol = strchr(line_buffer + length, LF);
	  /* Do we *really* want to do this? */
	  if (eol && eol != line_buffer && *(eol-1) == CR)
	      *(eol-1) = ' ';

	  length = length + status;

	  /* Do we really want to do *this*? */
	  if (eol)
	      *eol = 0;		/* Terminate the line */
      /* All we need is the first line of the response.  If it's a HTTP/1.0
	 response, then the first line will be absurdly short and therefore
	 we can safely gate the number of bytes read through this code
	 (as opposed to below) to ~1000. */
      /* Well, let's try 100. */
      } while (!eol && !end_of_file && bytes_already_read < 100);
  } /* Scope of loop variables */


  /*	We now have a terminated unfolded line. Parse it.
   **	-------------------------------------------------
   */
#ifndef DISABLE_TRACE
  if (www2Trace)
    fprintf(stderr, "HTTP: Rx: %s\n", line_buffer);
#endif

  {
    int fields;
    char server_version[VERSION_LENGTH+1];
    int server_status;

	/*SWP*/
	statusError=0;

    server_version[0] = 0;

    fields = sscanf(line_buffer, "%20s %d",
                    server_version,
                    &server_status);

#ifndef DISABLE_TRACE
    if (www2Trace)
      fprintf (stderr, "HTTP: Scanned %d fields from line_buffer\n", fields);
#endif
#ifndef DISABLE_TRACE
    if (www2Trace)
      fprintf (stderr, "HTTP: line_buffer '%s'\n", line_buffer);
#endif

    /* Rule out HTTP/1.0 reply as best we can. */
    if (fields < 2 || !server_version[0] || server_version[0] != 'H' ||
        server_version[1] != 'T' || server_version[2] != 'T' ||
        server_version[3] != 'P' || server_version[4] != '/' ||
        server_version[6] != '.')
      {
        /* HTTP0 reply */
        HTAtom * encoding;

#ifndef DISABLE_TRACE
        if (www2Trace)
          fprintf (stderr, "--- Talking HTTP0.\n");
#endif

        format_in = HTFileFormat(arg, &encoding, WWW_HTML, &compressed);
        start_of_data = line_kept_clean;
      }
    else
      {
        /* Decode full HTTP response */
        format_in = HTAtom_for("www/mime");
        /* We set start_of_data to "" when !eol here because there
           will be a put_block done below; we do *not* use the value
           of start_of_data (as a pointer) in the computation of
           length or anything else in this situation. */
        start_of_data = eol ? eol + 1 : "";
        length = eol ? length - (start_of_data - line_buffer) : 0;

#ifndef DISABLE_TRACE
        if (www2Trace)
          fprintf (stderr, "--- Talking HTTP1.\n");
#endif

        switch (server_status / 100)
          {
          case 3:		/* Various forms of redirection */
            /* We now support this in the parser, at least. */
            doing_redirect = 1;
            break;

          case 4:		/* "I think I goofed" */
            switch (server_status)
              {
              case 403:
		statusError=1;
                /* 403 is "forbidden"; display returned text. */
                break;

              case 401:
                /* length -= start_of_data - text_buffer; */
                if (HTAA_shouldRetryWithAuth(start_of_data, length, s))
                  {
                    (void)NETCLOSE(s);
			lsocket = -1;
                    if (line_buffer)
                      free(line_buffer);
                    if (line_kept_clean)
                      free(line_kept_clean);

#ifndef DISABLE_TRACE
                    if (www2Trace)
                      fprintf(stderr, "%s %d %s\n",
                              "HTTP: close socket", s,
                              "to retry with Access Authorization");
#endif

                    HTProgress ("Retrying with access authorization information.");
                    goto try_again;
                    break;
                  }
                else
                  {
		    statusError=1;
                    /* Fall through. */
                  }

              default:
		statusError=1;
                break;
              } /* case 4 switch */
            break;

          case 5:		/* I think you goofed */
	    statusError=1;
            break;

          case 2:		/* Good: Got MIME object */
            switch (server_status)
              {
              case 204:
                return_nothing = 1;
                format_in = HTAtom_for("text/html");
                break;
	      case 200:
		if (do_head) {
			if (!start_of_data || !*start_of_data) {
				headData=NULL;
			}
			else {
				char *ptr;

				headData=strdup(start_of_data);
				ptr=strchr(headData,'\n');
				*ptr='\0';
			}
		}
		break;
              default:
                break;
              }
            break;

          default:		/* bad number */
	    statusError=1;
            HTAlert("Unknown status reply from server!");
            break;
          } /* Switch on server_status/100 */

      }	/* Full HTTP reply */
  } /* scope of fields */

  /* Set up the stream stack to handle the body of the message */
  target = HTStreamStack(format_in,
                         format_out,
                         compressed,
                         sink, anAnchor);

  if (!target)
    {
      char buffer[1024];	/* @@@@@@@@ */
      sprintf(buffer, "Sorry, no known way of converting %s to %s.",
              HTAtom_name(format_in), HTAtom_name(format_out));
      HTProgress (buffer);
      status = -1;
      NETCLOSE (s);
	lsocket = -1;
      goto clean_up;
    }

  if (!return_nothing)
    {
#ifndef DISABLE_TRACE
      if (www2Trace)
        fprintf (stderr, "HTTP: Doing put_block, '%s'\n", start_of_data);
#endif
/* BJS: parse start_of_data...*/
	for(p=start_of_data;*p;p++){
/*		if(*p=='C' && !strncmp("Content-length: ",p,16)){
		i = 0;
		p+=16;
		while(*p && isdigit(*p)){
			i = i*10 + *p-'0';
			p++;
		}
		p--;
#ifndef DISABLE_TRACE
		if(www2Trace)
			fprintf(stderr, "HTTP: Content Length is %d\n",i);
#endif
	}
*/
		if(*p=='K' && !strncmp("Keep-Alive:",p,11)){
#ifndef DISABLE_TRACE
			if (www2Trace)
				fprintf (stderr, "HTTP: Server Agrees to Keep-Alive\n");
#endif
			lsocket = s;
			p+=10;
		}
	}

#ifndef DISABLE_TRACE
        if (www2Trace && lsocket == -1)
		fprintf (stderr, "HTTP: Server does not agree to Keep-Alive\n");
#endif
      /* Recycle the first chunk of data, in all cases. */
      (*target->isa->put_block)(target, start_of_data, length);

      /* Go pull the bulk of the data down. */
	/* if we dont use length, header length is wrong due to the
	    discarded first line - bjs*/
      rv = HTCopy(s, target, length /*bytes_already_read*/);
      if (rv == -1)
        {
          (*target->isa->handle_interrupt) (target);
          status = HT_INTERRUPTED;
	  NETCLOSE (s);
		lsocket = -1;
          goto clean_up;
        }
      if (rv == -2 && !already_retrying && !do_post)
        {
          /* Aw hell. */
#ifndef DISABLE_TRACE
          if (www2Trace)
            fprintf (stderr, "HTTP: Trying again with HTTP0 request.\n");
#endif
          /* May as well consider it an interrupt -- right? */
          (*target->isa->handle_interrupt) (target);
          NETCLOSE(s);
          if (line_buffer)
            free(line_buffer);
          if (line_kept_clean)
            free(line_kept_clean);

          extensions = NO;
          already_retrying = 1;
          HTProgress ("Retrying as HTTP0 request.");
          goto try_again;
        }
    }
  else
    {
      /* return_nothing is high. */
      (*target->isa->put_string) (target, "<mosaic-access-override>\n");
      HTProgress ("And silence filled the night.");
    }

  (*target->isa->end_document)(target);

  /* Close socket before doing free. */
	if(lsocket == -1){
		NETCLOSE(s);
#ifndef DISABLE_TRACE
		if(www2Trace)
			fprintf(stderr,"HTTP: Closing connection\n");
#endif
	} else {
		HTProgress("Leaving Server Connection Open");
#ifndef DISABLE_TRACE
		if(www2Trace)
			fprintf(stderr,"HTTP: Keeping connection alive\n");
#endif
	}
/*
  else {
      NETCLOSE(s);
#ifndef DISABLE_TRACE
      if(www2Trace)
	fprintf(stderr,"HTTP: Closing connection\n");
#endif
  }
*/

  (*target->isa->free)(target);

  if (doing_redirect)
    {
      /* OK, now we've got the redirection URL temporarily stored
         in external variable redirecting_url, exported from HTMIME.c,
         since there's no straightforward way to do this in the library
         currently.  Do the right thing. */
      status = HT_REDIRECTING;
    }
  else
    {
      status = HT_LOADED;
    }

  /*	Clean up
   */

 clean_up:
  if (line_buffer)
    free(line_buffer);
  if (line_kept_clean)
    free(line_kept_clean);

 done:
  /* Clear out on exit, just in case. */
  do_post = 0;

  if (statusError) {
	securityType=HTAA_NONE;
#ifndef DISABLE_TRACE
	if (www2Trace)
		fprintf(stderr,"Resetting security type to NONE.\n");
#endif
  }

  return status;
}