Example #1
0
/*	Free an HTML object
**	-------------------
**
**	Note that the SGML parsing context is freed, but the created
**	object is not,
**	as it takes on an existence of its own unless explicitly freed.
*/
PRIVATE void HTFWriter_free ARGS1(HTStream *, me)
{
    if (me->cache) {
	time_t finish_time;
	time(&finish_time);
	me->cache->load_delay = finish_time - me->cache->load_time;
	/* Actually, ought to use draft ANSI-C difftime() */
	/* But that I bet is more portable in real life  (@@?) */
    }

    if (me->leave_open != YES) fclose(me->fp);

    if (me->end_command) {		/* Temp file */
	HTProgress(me->end_command);	/* Tell user what's happening */
	system(me->end_command);	/* @@ Beware of security hole */
	free (me->end_command);
	if (me->remove_on_close) {
	    unlink(me->filename);
	}
    }
    if (me->callback) {
	(*me->callback)(me->request, me->filename);
    }
    if (me->filename) free(me->filename);
    free(me);
}
Example #2
0
PUBLIC int HTSendMailTo ARGS4(
      WWW_CONST char *,     arg,
      HTParentAnchor *,	anAnchor,
      HTFormat,		format_out,
      HTStream*,	stream)
{
  char *mailtoURL;
  char *mailtoSubject;

#ifndef DISABLE_TRACE
  if (www2Trace) 
    fprintf(stderr, "HTMailto: Mailing to %s\n", arg);
#endif
  
  if (!initialized) 
    initialized = initialize();
  if (!initialized) 
    {
      HTProgress ((char *) 0);
      return HT_NOT_LOADED;
    }

  {
    WWW_CONST char * p1=arg;
    
    /*	We will ask for the document, omitting the host name & anchor.
     **
     **	Syntax of address is
     **		xxx@yyy			User xxx at site yyy (xxx is optional).
     */        
    if (!my_strncasecmp (arg, "mailto:", 7))
      p1 = arg + 7;		/* Skip "mailto:" prefix */
    
    if (!*arg) 
      {
	HTProgress ("Could not find email address");
	return HT_NOT_LOADED;	/* Ignore if no name */
      }

    GetMailtoKludgeInfo(&mailtoURL,&mailtoSubject);
    (void) mo_post_mailto_win(p1,mailtoSubject);
    return HT_LOADED;
  }
}
Example #3
0
/*	String handling
**	---------------
**
**	Strings must be smaller than this buffer size.
*/
PRIVATE void HTFWriter_put_string ARGS2(HTStream *, me, WWW_CONST char*, s)
{
  int rv;

  if (me->write_error)
    return;

  rv = fputs(s, me->fp);
  if (rv == EOF)
    {
      HTProgress ("Error writing to temporary file.");
      me->write_error = 1;
    }
}
Example #4
0
/*	Buffer write.  Buffers can (and should!) be big.
**	------------
*/
PRIVATE void HTFWriter_write ARGS3(HTStream *, me, WWW_CONST char*, s, int, l)
{
  int rv;

  if (me->write_error)
    return;

  rv = fwrite(s, 1, l, me->fp); 
  if (rv != l)
    {
      HTProgress ("Error writing to temporary file.");
      me->write_error = 1;
    }
}
Example #5
0
PRIVATE void HTFWriter_put_character ARGS2(HTStream *, me, char, c)
{
  int rv;

  if (me->write_error)
    return;

  /* Make sure argument to putc is in range 0-255, to avoid weirdness
     with rv == -1 == EOF when it's not supposed to. */
  rv = putc ((int)(unsigned char)c, me->fp);

  if (rv == EOF)
    {
      HTProgress ("Error writing to temporary file.");
      me->write_error = 1;
    }
}
Example #6
0
/*	Take action using a system command
**	----------------------------------
**
**	Creates temporary file, writes to it, executes system command
**	on end-document.  The suffix of the temp file can be given
**	in case the application is fussy, or so that a generic opener can
**	be used.
**
**      WARNING: If force_dump_to_file is high, pres may be NULL
**      (as we may get called directly from HTStreamStack).
*/
PUBLIC HTStream* HTSaveAndExecute ARGS5(
	HTPresentation *,	pres,
	HTParentAnchor *,	anchor,	/* Not used */
	HTStream *,		sink,
        HTFormat,               format_in,
        int,                    compressed)	/* Not used */
{
  char *command;
  WWW_CONST char * suffix;
  
  HTStream* me;

  me = (HTStream*)malloc(sizeof(*me));
  me->isa = &HTFWriter;  
  me->interrupted = 0;
  me->write_error = 0;
  me->fnam = NULL;
  me->end_command = NULL;
  me->compressed = compressed;
  if (!format_in || !format_in->name || !*(format_in->name)) {
	me->mime_type=NULL;
  }
  else {
	if (!strncmp(format_in->name,"image",5)) {
		me->mime_type=strdup(format_in->name);
	}
	else {
		me->mime_type=NULL;
	}
  }

#ifndef DISABLE_TRACE
  if (www2Trace)
    fprintf (stderr, "[HTSaveAndExecute] me->compressed is '%d'\n",
             me->compressed);
#endif
  
  /* Save the file under a suitably suffixed name */
  
  if (!force_dump_to_file)
    {
      extern char *mo_tmpnam (char *);

      suffix = HTFileSuffix(pres->rep);
      
      me->fnam = mo_tmpnam(anchor->address);
      if (suffix) 
        {
          char *freeme = me->fnam;
         
          me->fnam = (char *)malloc (strlen (me->fnam) + strlen (suffix) + 8);
          strcpy(me->fnam, freeme);
          strcat(me->fnam, suffix);
          free (freeme);
        }
    }
  else
    {
      me->fnam = strdup (force_dump_filename);
    }

  me->fp = fopen (me->fnam, "w");
  if (!me->fp) 
    {
      HTProgress("Can't open temporary file -- serious problem.");
      me->write_error = 1;
      return me;
    }

  /* If force_dump_to_file is high, we're done here. */
  if (!force_dump_to_file)
    {
      if (!strstr (pres->command, "mosaic-internal-reference"))
        {
          /* If there's a "%s" in the command, or if the command
             is magic... */
#ifndef DISABLE_TRACE
          if (www2Trace)
            fprintf (stderr, "HTFWriter: pres->command is '%s'\n",
                     pres->command);
#endif
          if (strstr (pres->command, "%s") ||
              strstr (pres->command, "mosaic-internal"))
            {
              /* Make command to process file */
              command = (char *)malloc 
                ((strlen (pres->command) + 10 + 3*strlen(me->fnam)) * 
                 sizeof (char));
              
              /* Cute.  pres->command will be something like "xv %s"; me->fnam
                 gets filled in as many times as appropriate.  */
              sprintf (command, pres->command, me->fnam, me->fnam, me->fnam);
              
              me->end_command = (char *)malloc 
                ((strlen (command) + 32 + strlen(me->fnam)) * sizeof (char));
              sprintf (me->end_command, "(%s ; /bin/rm -f %s) &",
                       command, me->fnam);

              free (command);
            }
          else
            {
              /* Make command to process file -- but we have to cat
                 to the viewer's stdin. */
              me->end_command = (char *)malloc 
                ((strlen (pres->command) + 64 + (2 * strlen(me->fnam))) * 
                 sizeof (char));
              sprintf (me->end_command, "((cat %s | %s); /bin/rm -f %s) &",
                       me->fnam, pres->command, me->fnam);
            }
        }
      else
        {
          /* Overload me->end_command to be what we should write out as text
             to communicate back to client code. */
          me->end_command = (char *)malloc
            (strlen ("mosaic-internal-reference") + strlen (me->fnam) + 32);
          sprintf (me->end_command, "<%s \"%s\">\n", "mosaic-internal-reference", me->fnam);
        }
    }
  
  return me;
}
Example #7
0
/*	Free an HTML object
**	-------------------
**
**	Note that the SGML parsing context is freed, but the created
**	object is not,
**	as it takes on an existence of its own unless explicitly freed.
*/
PRIVATE void HTFWriter_free ARGS1(HTStream *, me)
{
  HText *text;
  static char *envbuf1=NULL;
  static char *envbuf2=NULL;

  /* I dunno if this is necessary... */
  if (me->interrupted)
    {
      free (me->fnam);
      free (me);
      return;
    }

  if (me->write_error)
    {
/*
      char *cmd = (char *)malloc ((strlen (me->fnam) + 32));
      sprintf (cmd, "/bin/rm -f %s &", me->fnam);
      system (cmd);
      free (cmd);
*/
/*ddt*/unlink(me->fnam);
      
      HTProgress ("Insufficient temporary disk space; could not transfer data.");

      free (me->fnam);
      free (me);
      return;
    }

  fflush (me->fp);
  fclose (me->fp);

  /* We do want to be able to handle compressed inlined images,
     but we don't want transparent uncompression to take place
     in binary transfer mode. */
  if (!binary_transfer && me->compressed != COMPRESSED_NOT)
    {
#ifndef DISABLE_TRACE
      if (www2Trace)
        fprintf (stderr, "[HTFWriter] Hi there; compressed is %d, fnam is '%s'\n",
                 me->compressed, me->fnam);
#endif
      HTCompressedFileToFile (me->fnam, me->compressed);
    }

  if (force_dump_to_file)
    {
      if (!binary_transfer)
        goto done;
    }

  /* Now, me->end_command can either be something starting with
     "<mosaic-internal-reference" or it can be a real command.
     Deal with appropriately. */
  if (me->end_command)
    {
	/* Check for forced dump condition.  The left paren comes
		from the construction of me->end_command as a compound shell
		command below. */
	if (strstr (me->end_command, "mosaic-internal-dump")) {
		rename_binary_file (me->fnam);
        }
	else if (!strstr (me->end_command, "mosaic-internal-reference")) {
		if (imageViewInternal && supportedImageType(me->mime_type)) {
			char *newHTML="<html>\n<head>\n<title>Mosaic's Internal Image Display</title>\n</head>\n<body>\n<img align=center src=\"%s\">\n</body>\n</html>\n";
			char *buf;

			buf=(char *)calloc((strlen(currentURL)+strlen(newHTML)+5),sizeof(char));
			sprintf(buf,newHTML,currentURL);

			text=HText_new();
			HText_beginAppend(text);
			HText_appendText(text,buf);
			HText_endAppend(text);

			free(buf);

			buf=(char *)calloc((strlen(currentURL)+strlen(me->fnam)+5),sizeof(char));
			sprintf(buf,"%s\n%s",me->fnam,currentURL);
			ImageResolve(NULL,buf,0);

			free(buf);

			goto done;
		}

		HTProgress("Spawning external viewer.");

		/*
		 * Have to dance around putenv since it makes "envbuf*" part
		 *   of the actual environment string...*sigh* What a mess!
		 */
		if (envbuf1) {
			envbuf2=(char *)calloc((strlen(currentURL)+
						strlen("MOSAIC_CURRENT_URL=")+
						2),
					       sizeof(char));
			sprintf(envbuf2,"MOSAIC_CURRENT_URL=%s",currentURL);
			putenv(envbuf2);
			free(envbuf1);
			envbuf1=NULL;
		}
		else if (envbuf2) {
			envbuf1=(char *)calloc((strlen(currentURL)+
						strlen("MOSAIC_CURRENT_URL=")+
						2),
					       sizeof(char));
			sprintf(envbuf1,"MOSAIC_CURRENT_URL=%s",currentURL);
			putenv(envbuf1);
			free(envbuf2);
			envbuf2=NULL;
		}
		else { /* Likely it is the first time */
			envbuf1=(char *)calloc((strlen(currentURL)+
						strlen("MOSAIC_CURRENT_URL=")+
						2),
					       sizeof(char));
			sprintf(envbuf1,"MOSAIC_CURRENT_URL=%s",currentURL);
			putenv(envbuf1);
		}

		system (me->end_command);

		if (envbuf1) {
			envbuf2=(char *)calloc((strlen("MOSAIC_CURRENT_URL=")+
						2),
					       sizeof(char));
			sprintf(envbuf2,"MOSAIC_CURRENT_URL=");
			putenv(envbuf2);
			free(envbuf1);
			envbuf1=NULL;
		}
		else if (envbuf2) {
			envbuf1=(char *)calloc((strlen("MOSAIC_CURRENT_URL=")+
						2),
					       sizeof(char));
			sprintf(envbuf1,"MOSAIC_CURRENT_URL=");
			putenv(envbuf1);
			free(envbuf2);
			envbuf2=NULL;
		}
		else { /* Likely it is the first time */
			envbuf1=(char *)calloc((strlen("MOSAIC_CURRENT_URL=")+
						2),
					       sizeof(char));
			sprintf(envbuf1,"MOSAIC_CURRENT_URL=");
			putenv(envbuf1);
		}
	}
	else {
          /* Internal reference, aka HDF file.  Just close output file. */
	}
    }
  else
    {
      /* No me->end_command; just close the file. */
    }

  /* Construct dummy HText thingie so Mosaic knows
     not to try to access this "document". */
  text = HText_new ();
  HText_beginAppend (text);
  /* If it's a real internal reference, tell Mosaic. */
  if (me->end_command) {
	if (strstr (me->end_command, "mosaic-internal-reference")) {
          HText_appendText (text, me->end_command);
	}
	else {
		HText_appendText (text, "<mosaic-access-override>\n");
	}
	free (me->end_command);
  }
  else {
      /* No me->end_command; just override the access. */
      HText_appendText (text, "<mosaic-access-override>\n");
  }
  HText_endAppend (text);

 done:
  if (binary_transfer)
    rename_binary_file (me->fnam);

 really_done:
  free (me->fnam);
  if (me->mime_type) {
	free(me->mime_type);
  }
  free (me);

  return;
}
Example #8
0
PUBLIC int HTCopy ARGS3(int,			file_number,
                         HTStream*,		sink,
                         int,                   bytes_already_read)
{
  HTStreamClass targetClass;    
  char line[256];
  char *msg;
  int bytes = bytes_already_read;
  extern int twirl_increment;
  int next_twirl = twirl_increment;
  int rv = 0;

  int left = -1, total_read = bytes_already_read, hdr_len = 0;

/*  if(loading_length != -1) left = loading_length;*/

  HTClearActiveIcon();

  /*	Push the data down the stream
   **
   */
  targetClass = *(sink->isa);	/* Copy pointers to procedures */
  
  hdr_len = HTMIME_get_header_length(sink);

      /*	Push binary from socket down sink */
  for(;;) 
    {
      int status, intr;

      if (bytes > next_twirl)
        {
          intr = HTCheckActiveIcon(1);
          next_twirl += twirl_increment;
        }
      else
        {
          intr = HTCheckActiveIcon(0);
        }
      if (intr)
        {
#ifdef SWP_HACK
	  loading_length=(-1);
#endif
          HTProgress ("Data transfer interrupted.");
	  noLength=0;
	  HTMeter(100,NULL);
	  noLength=1;
          (*targetClass.handle_interrupt)(sink);
          rv = -1;
          goto ready_to_leave;
        }
      
      if(loading_length == -1) {
	  left = -1;
	  status = NETREAD(file_number, input_buffer, INPUT_BUFFER_SIZE);
      } else {
	  left = (loading_length+hdr_len)-total_read;
	  if(left>0) status = NETREAD(file_number, input_buffer, 
                                      (left>INPUT_BUFFER_SIZE?
                                       INPUT_BUFFER_SIZE:left));
          else status=0;
      }

      if (status > 0)
	  total_read += status;
      
/*      fprintf(stderr,"ll = %d status = %d left = %d hdr = %d tr = %d\n",
              loading_length,status,left,hdr_len,total_read);
              */		  

/*
      status = NETREAD(file_number, input_buffer, INPUT_BUFFER_SIZE);
*/
      if (status <= 0) 
        {
          if (status == 0) 
            break;
          if (status == HT_INTERRUPTED)
            {
#ifdef SWP_HACK
	      loading_length=(-1);
#endif
              HTProgress ("Data transfer interrupted.");
	      noLength=0;
	      HTMeter(100,NULL);
	      noLength=1;
              (*targetClass.handle_interrupt)(sink);
              rv = -1;
              goto ready_to_leave;
            }
          if (errno == ENOTCONN || errno == ECONNRESET || errno == EPIPE)
            {
              /* Arrrrgh, HTTP 0/1 compability problem, maybe. */
              rv = -2;
              goto ready_to_leave;
            }
          break;
	}

#ifndef DISABLE_TRACE
      if (www2Trace)
	  fprintf (stderr, "HTCopy: put_block on input_buffer '%s'\n", input_buffer);
#endif

      (*targetClass.put_block)(sink, input_buffer, status);

      if (ftpKludge) {
	hdr_len=0;
      }
      else {
	hdr_len = HTMIME_get_header_length(sink);
      }

/*	  left = loading_length - total_read;*/

      bytes += status;

      /* moved msg stuff here as loading_length may change midstream -bjs*/
      if (loading_length == -1){
	  msg = (loading_inlined_images ? 
		 "Read %d bytes of inlined image data." : 
		 "Read %d bytes of data.");
        sprintf (line, msg, bytes);
/*	HTMeter(0,NULL);*/
      }else{
	  msg = (loading_inlined_images ? 
		 "Read %d of %d bytes of inlined image data." : 
		 "Read %d of %d bytes of data.");
        sprintf (line, msg, bytes, loading_length+hdr_len);
	HTMeter((bytes*100)/(loading_length+hdr_len),NULL);
      }
      HTProgress (line);
      if((loading_length != -1) && (total_read>=(loading_length+hdr_len))) {
/*	  fprintf(stderr,"done\n");*/
	  break;
      }
    } /* next bufferload */
  
/*
  HTProgress (loading_inlined_images ?
              "Data transfer complete." : "Data transfer complete.");    
*/
  HTProgress("Data transfer complete.");
  noLength=0;
  HTMeter(100,NULL);
  noLength=1;

/*  fprintf(stderr,"HTFormat: KeepAlive Exit\n");*/
/*
  NETCLOSE (file_number);
*/

  /* Success. */
  rv = 0;

 ready_to_leave:
  /* Reset ourselves so we don't get confused. */
  loading_length = -1;

  return rv;
}
Example #9
0
/*		Load by name					HTLoadFinger
 *		============
 */
int HTLoadFinger(const char *arg,
		 HTParentAnchor *anAnchor,
		 HTFormat format_out,
		 HTStream *stream)
{
    static char empty[1];

    char *username, *sitename;	/* Fields extracted from URL */
    char *slash, *at_sign;	/* Fields extracted from URL */
    char *command, *str, *param;	/* Buffers */
    int port;			/* Port number from URL */
    int status;			/* tcp return */
    int result = HT_LOADED;
    BOOL IsGopherURL = FALSE;
    const char *p1 = arg;

    CTRACE((tfp, "HTFinger: Looking for %s\n", (arg ? arg : "NULL")));

    if (!(arg && *arg)) {
	HTAlert(COULD_NOT_LOAD_DATA);
	return HT_NOT_LOADED;	/* Ignore if no name */
    }

    if (!initialized)
	initialized = initialize();
    if (!initialized) {
	HTAlert(gettext("Could not set up finger connection."));
	return HT_NOT_LOADED;	/* FAIL */
    }

    /*  Set up the host and command fields.
     */
    if (!strncasecomp(arg, "finger://", 9)) {
	p1 = arg + 9;		/* Skip "finger://" prefix */
    } else if (!strncasecomp(arg, "gopher://", 9)) {
	p1 = arg + 9;		/* Skip "gopher://" prefix */
	IsGopherURL = TRUE;
    }

    param = 0;
    sitename = StrAllocCopy(param, p1);
    if (param == 0) {
	HTAlert(COULD_NOT_LOAD_DATA);
	return HT_NOT_LOADED;
    } else if ((slash = StrChr(sitename, '/')) != NULL) {
	*slash++ = '\0';
	HTUnEscape(slash);
	if (IsGopherURL) {
	    if (*slash != '0') {
		HTAlert(COULD_NOT_LOAD_DATA);
		return HT_NOT_LOADED;	/* FAIL */
	    }
	    *slash++ = '\0';
	}
    }

    if ((at_sign = StrChr(sitename, '@')) != NULL) {
	if (IsGopherURL) {
	    HTAlert(COULD_NOT_LOAD_DATA);
	    return HT_NOT_LOADED;	/* FAIL */
	} else {
	    *at_sign++ = '\0';
	    username = sitename;
	    sitename = at_sign;
	    HTUnEscape(username);
	}
    } else if (slash) {
	username = slash;
    } else {
	username = empty;
    }

    if (*sitename == '\0') {
	HTAlert(gettext("Could not load data (no sitename in finger URL)"));
	result = HT_NOT_LOADED;	/* Ignore if no name */
    } else if (HTParsePort(sitename, &port) != NULL) {
	if (port != 79) {
	    HTAlert(gettext("Invalid port number - will only use port 79!"));
	    result = HT_NOT_LOADED;	/* Ignore if wrong port */
	}
    }

    if (result == HT_LOADED) {
	/* Load the string for making a connection/
	 */
	str = 0;
	HTSprintf0(&str, "lose://%s/", sitename);

	/* Load the command for the finger server.
	 */
	command = 0;
	if (at_sign && slash) {
	    if (*slash == 'w' || *slash == 'W') {
		HTSprintf0(&command, "/w %s%c%c", username, CR, LF);
	    } else {
		HTSprintf0(&command, "%s%c%c", username, CR, LF);
	    }
	} else if (at_sign) {
	    HTSprintf0(&command, "%s%c%c", username, CR, LF);
	} else if (*username == '/') {
	    if ((slash = StrChr((username + 1), '/')) != NULL) {
		*slash = ' ';
	    }
	    HTSprintf0(&command, "%s%c%c", username, CR, LF);
	} else if ((*username == 'w' || *username == 'W') &&
		   *(username + 1) == '/') {
	    if (*username + 2 != '\0') {
		*(username + 1) = ' ';
	    } else {
		*(username + 1) = '\0';
	    }
	    HTSprintf0(&command, "/%s%c%c", username, CR, LF);
	} else if ((*username == 'w' || *username == 'W') &&
		   *(username + 1) == '\0') {
	    HTSprintf0(&command, "/%s%c%c", username, CR, LF);
	} else if ((slash = StrChr(username, '/')) != NULL) {
	    *slash++ = '\0';
	    if (*slash == 'w' || *slash == 'W') {
		HTSprintf0(&command, "/w %s%c%c", username, CR, LF);
	    } else {
		HTSprintf0(&command, "%s%c%c", username, CR, LF);
	    }
	} else {
	    HTSprintf0(&command, "%s%c%c", username, CR, LF);
	}

	/* Now, let's get a stream setup up from the FingerHost:
	 * CONNECTING to finger host
	 */
	CTRACE((tfp, "HTFinger: doing HTDoConnect on '%s'\n", str));
	status = HTDoConnect(str, "finger", FINGER_PORT, &finger_fd);
	CTRACE((tfp, "HTFinger: Done DoConnect; status %d\n", status));

	if (status == HT_INTERRUPTED) {
	    /* Interrupt cleanly */
	    CTRACE((tfp,
		    "HTFinger: Interrupted on connect; recovering cleanly.\n"));
	    HTProgress(CONNECTION_INTERRUPTED);
	    result = HT_NOT_LOADED;
	} else if (status < 0) {
	    NETCLOSE(finger_fd);
	    finger_fd = -1;
	    CTRACE((tfp, "HTFinger: Unable to connect to finger host.\n"));
	    HTAlert(gettext("Could not access finger host."));
	    result = HT_NOT_LOADED;	/* FAIL */
	} else {
	    CTRACE((tfp, "HTFinger: Connected to finger host '%s'.\n", str));

	    /* Send the command, and process response if successful.
	     */
	    if (response(command, sitename, anAnchor, format_out, stream) != 0) {
		HTAlert(gettext("No response from finger server."));
		result = HT_NOT_LOADED;
	    }
	}
	FREE(str);
	FREE(command);
    }
    FREE(param);
    return result;
}
Example #10
0
/*	Translate by rules					HTTranslate()
 *	------------------
 *
 *	The most recently defined rules are applied first.
 *
 * On entry,
 *	required	points to a string whose equivalent value is needed
 * On exit,
 *	returns		the address of the equivalent string allocated from
 *			the heap which the CALLER MUST FREE. If no translation
 *			occurred, then it is a copy of the original.
 * NEW FEATURES:
 *			When a "protect" or "defprot" rule is matched,
 *			a call to HTAA_setCurrentProtection() or
 *			HTAA_setDefaultProtection() is made to notify
 *			the Access Authorization module that the file is
 *			protected, and so it knows how to handle it.
 *								-- AL
 */
char *HTTranslate(const char *required)
{
    rule *r;
    char *current = NULL;
    char *msgtmp = NULL;
    const char *pMsg;
    int proxy_none_flag = 0;
    int permitredir_flag = 0;

    StrAllocCopy(current, required);

    HTAA_clearProtections();	/* Reset from previous call -- AL */

    for (r = rules; r; r = r->next) {
	char *p = r->pattern;
	int m = 0;		/* Number of characters matched against wildcard */
	const char *q = current;

	for (; *p && *q; p++, q++) {	/* Find first mismatch */
	    if (*p != *q)
		break;
	}

	if (*p == '*') {	/* Match up to wildcard */
	    m = strlen(q) - strlen(p + 1);	/* Amount to match to wildcard */
	    if (m < 0)
		continue;	/* tail is too short to match */
	    if (0 != strcmp(q + m, p + 1))
		continue;	/* Tail mismatch */
	} else
	    /* Not wildcard */ if (*p != *q)
	    continue;		/* plain mismatch: go to next rule */

	if (!rule_cond_ok(r))	/* check condition, next rule if false - kw */
	    continue;

	switch (r->op) {	/* Perform operation */

#ifdef ACCESS_AUTH
	case HT_DefProt:
	case HT_Protect:
	    {
		char *local_copy = NULL;
		char *p2;
		char *eff_ids = NULL;
		char *prot_file = NULL;

		CTRACE((tfp, "HTRule: `%s' matched %s %s: `%s'\n",
			current,
			(r->op == HT_Protect ? "Protect" : "DefProt"),
			"rule, setup",
			(r->equiv ? r->equiv :
			 (r->op == HT_Protect ? "DEFAULT" : "NULL!!"))));

		if (r->equiv) {
		    StrAllocCopy(local_copy, r->equiv);
		    p2 = local_copy;
		    prot_file = HTNextField(&p2);
		    eff_ids = HTNextField(&p2);
		}

		if (r->op == HT_Protect)
		    HTAA_setCurrentProtection(current, prot_file, eff_ids);
		else
		    HTAA_setDefaultProtection(current, prot_file, eff_ids);

		FREE(local_copy);

		/* continue translating rules */
	    }
	    break;
#endif /* ACCESS_AUTH */

	case HT_UserMsg:	/* Produce message immediately */
	    LYFixCursesOn("show rule message:");
	    HTUserMsg2((r->equiv ? r->equiv : "Rule: %s"), current);
	    break;
	case HT_InfoMsg:	/* Produce messages immediately */
	case HT_Progress:
	case HT_Alert:
	    LYFixCursesOn("show rule message:");	/* and fall through */
	case HT_AlwaysAlert:
	    pMsg = r->equiv ? r->equiv :
		(r->op == HT_AlwaysAlert) ? "%s" : "Rule: %s";
	    if (strchr(pMsg, '%')) {
		HTSprintf0(&msgtmp, pMsg, current);
		pMsg = msgtmp;
	    }
	    switch (r->op) {	/* Actually produce message */
	    case HT_InfoMsg:
		HTInfoMsg(pMsg);
		break;
	    case HT_Progress:
		HTProgress(pMsg);
		break;
	    case HT_Alert:
		HTAlert(pMsg);
		break;
	    case HT_AlwaysAlert:
		HTAlwaysAlert("Rule alert:", pMsg);
		break;
	    default:
		break;
	    }
	    FREE(msgtmp);
	    break;

	case HT_PermitRedir:	/* Set special flag */
	    permitredir_flag = 1;
	    CTRACE((tfp, "HTRule: Mark for redirection permitted\n"));
	    break;

	case HT_Pass:		/* Authorised */
	    if (!r->equiv) {
		if (proxy_none_flag) {
		    char *temp = NULL;

		    StrAllocCopy(temp, "NoProxy=");
		    StrAllocCat(temp, current);
		    FREE(current);
		    current = temp;
		}
		CTRACE((tfp, "HTRule: Pass `%s'\n", current));
		return current;
	    }
	    /* Else fall through ...to map and pass */

	case HT_Map:
	case HT_Redirect:
	case HT_RedirectPerm:
	    if (*p == *q) {	/* End of both strings, no wildcard */
		CTRACE((tfp, "For `%s' using `%s'\n", current, r->equiv));
		StrAllocCopy(current, r->equiv);	/* use entire translation */
	    } else {
		char *ins = strchr(r->equiv, '*');	/* Insertion point */

		if (ins) {	/* Consistent rule!!! */
		    char *temp = NULL;

		    HTSprintf0(&temp, "%.*s%.*s%s",
			       (int) (ins - r->equiv),
			       r->equiv,
			       m,
			       q,
			       ins + 1);
		    CTRACE((tfp, "For `%s' using `%s'\n",
			    current, temp));
		    FREE(current);
		    current = temp;	/* Use this */

		} else {	/* No insertion point */
		    char *temp = NULL;

		    StrAllocCopy(temp, r->equiv);
		    CTRACE((tfp, "For `%s' using `%s'\n",
			    current, temp));
		    FREE(current);
		    current = temp;	/* Use this */
		}		/* If no insertion point exists */
	    }
	    if (r->op == HT_Pass) {
		if (proxy_none_flag) {
		    char *temp = NULL;

		    StrAllocCopy(temp, "NoProxy=");
		    StrAllocCat(temp, current);
		    FREE(current);
		    current = temp;
		}
		CTRACE((tfp, "HTRule: ...and pass `%s'\n",
			current));
		return current;
	    } else if (r->op == HT_Redirect) {
		CTRACE((tfp, "HTRule: ...and redirect to `%s'\n",
			current));
		redirecting_url = current;
		HTPermitRedir = (BOOL) (permitredir_flag == 1);
		return (char *) 0;
	    } else if (r->op == HT_RedirectPerm) {
		CTRACE((tfp, "HTRule: ...and redirect like 301 to `%s'\n",
			current));
		redirecting_url = current;
		permanent_redirection = TRUE;
		HTPermitRedir = (BOOL) (permitredir_flag == 1);
		return (char *) 0;
	    }
	    break;

	case HT_UseProxy:
	    if (r->equiv && 0 == strcasecomp(r->equiv, "none")) {
		CTRACE((tfp, "For `%s' will not use proxy\n", current));
		proxy_none_flag = 1;
	    } else if (proxy_none_flag) {
		CTRACE((tfp, "For `%s' proxy server ignored: %s\n",
			current,
			NONNULL(r->equiv)));
	    } else {
		char *temp = NULL;

		StrAllocCopy(temp, "Proxied=");
		StrAllocCat(temp, r->equiv);
		StrAllocCat(temp, current);
		CTRACE((tfp, "HTRule: proxy server found: %s\n",
			NONNULL(r->equiv)));
		FREE(current);
		return temp;
	    }
	    break;

	case HT_Invalid:
	case HT_Fail:		/* Unauthorised */
	    CTRACE((tfp, "HTRule: *** FAIL `%s'\n", current));
	    FREE(current);
	    return (char *) 0;
	}			/* if tail matches ... switch operation */

    }				/* loop over rules */

    if (proxy_none_flag) {
	char *temp = NULL;

	StrAllocCopy(temp, "NoProxy=");
	StrAllocCat(temp, current);
	FREE(current);
	return temp;
    }

    return current;
}
Example #11
0
void HTFWriter_free( HTStream *me )
{
  int len;
  char *path = 0;
  char *addr = 0;
  int status;
  BOOLEAN use_zread = 0;
  BOOLEAN found = 0;
  if ( me->fp )
    fflush( &me->fp );
  if ( me->end_command )
  {
    LYCloseTempFP( &me->fp );
    if ( me->input_format == HTAtom_for( "www/compressed" ) )
    {
      if ( me->anchor->FileCache )
      {
        BOOLEAN skip_loadfile = me->viewer_command != 0;
        HTSACopy( &path, &me->anchor->FileCache );
        len = strlen( path );
        if ( len > 3 && ( strcasecomp( &path[ len + -2 ], "gz" ) == 0 || strcasecomp( &path[ len + -2 ], "zz" ) == 0 ) )
        {
          if ( skip_loadfile == 0 )
            use_zread = 1;
          else
          {
            path[ len + -3 ] = 0;
            remove( path );
          }
        }
        else
        if ( len > 4 && strcasecomp( &path[ len + -3 ], "bz2" ) == 0 )
        {
          path[ len + -4 ] = 0;
          remove( path );
        }
        else
        if ( len > 2 && strcasecomp( &path[ len + -1 ], "Z" ) == 0 )
        {
          path[ len + -2 ] = 0;
          remove( path );
        }
        if ( use_zread == 0 )
        {
          if ( dump_output_immediately == 0 )
          {
            mustshow = 1;
            HTProgress( &me->end_command );
          }
          if ( me->end_command && me->end_command[0] )
            LYSystem( &me->end_command );
          found = LYCanReadFile( &me->anchor->FileCache );
        }
        if ( found )
        {
          if ( dump_output_immediately == 0 )
          {
            lynx_force_repaint( );
            LYrefresh( );
          }
          HTAlert( gettext( "Error uncompressing temporary file!" ) );
          LYRemoveTemp( &me->anchor->FileCache );
          if ( me->anchor->FileCache )
          {
            free( &me->anchor->FileCache );
            me->anchor->FileCache = 0;
          }
        }
        else
        {
          LYLocalFileToURL( &addr, path );
          if ( use_zread == 0 )
          {
            LYRenamedTemp( &me->anchor->FileCache, path );
            HTSACopy( &me->anchor->FileCache, path );
            HTSACopy( &me->anchor->content_encoding, "binary" );
          }
          if ( path )
          {
            free( path );
            path = 0;
          }
          if ( skip_loadfile == 0 )
          {
            if ( HTAnchor_getUCLYhndl( &me->anchor, 1 ) < 0 )
              HTAnchor_copyUCInfoStage( &me->anchor, 1, 0, 2 );
            HTAnchor_copyUCInfoStage( &me->anchor, 1, 0, -1 );
          }
          if ( dump_output_immediately == 0 )
          {
            LYstore_message2( gettext( "Using %s" ), addr );
          }
          if ( skip_loadfile )
          {
            if ( me->end_command )
            {
              free( &me->end_command );
              *(int*)&me->end_command = 0;
            }
            HTAddParam( &me->end_command, &me->viewer_command, 1, &me->anchor->FileCache );
            HTEndParam( &me->end_command, &me->viewer_command, 1 );
            if ( dump_output_immediately == 0 )
            {
              HTProgress( &me->end_command );
              stop_curses( );
            }
            LYSystem( &me->end_command );
            if ( me->remove_command && me->remove_command )
            {
              free( &me->remove_command );
              *(int*)&me->remove_command = 0;
            }
            if ( dump_output_immediately == 0 )
              start_curses( );
          }
          else
          {
            status = HTLoadFile( addr, &me->anchor, &me->output_format, &me->sink );
          }
          if ( dump_output_immediately && me->output_format == HTAtom_for( "www/present" ) )
          {
            if ( addr )
            {
              free( addr );
              addr = 0;
            }
            remove( &me->anchor->FileCache );
            if ( me->anchor->FileCache )
            {
              free( &me->anchor->FileCache );
              me->anchor->FileCache = 0;
            }
            if ( me->remove_command )
            {
              free( &me->remove_command );
              *(int*)&me->remove_command = 0;
            }
            if ( me->end_command )
            {
              free( &me->end_command );
              *(int*)&me->end_command = 0;
            }
            if ( me->viewer_command )
            {
              free( &me->viewer_command );
              *(int*)&me->viewer_command = 0;
            }
            if ( me == 0 )
            {
              return;
            }
            free( me );
            me = 0;
            return;
          }
        }
        if ( addr )
        {
          free( addr );
          addr = 0;
        }
      }
      if ( me->remove_command && me->remove_command )
      {
        free( &me->remove_command );
        *(int*)&me->remove_command = 0;
      }
    }
    else
    {
      if ( strcmp( &me->end_command, "SaveToFile" ) )
      {
        if ( dump_output_immediately == 0 )
        {
          mustshow = 1;
          HTProgress( &me->end_command );
          stop_curses( );
        }
        LYSystem( &me->end_command );
        if ( me->remove_command && me->remove_command )
        {
          free( &me->remove_command );
          *(int*)&me->remove_command = 0;
        }
        if ( dump_output_immediately == 0 )
          start_curses( );
      }
      else
      {
        if ( me->remove_command && me->remove_command )
        {
          free( &me->remove_command );
          *(int*)&me->remove_command = 0;
        }
        if ( dump_output_immediately == 0 )
          start_curses( );
      }
    }
    if ( me->end_command )
    {
      free( &me->end_command );
      *(int*)&me->end_command = 0;
    }
  }
  if ( me->viewer_command )
  {
    free( &me->viewer_command );
    *(int*)&me->viewer_command = 0;
  }
  if ( dump_output_immediately )
  {
    if ( me->anchor->FileCache )
      remove( &me->anchor->FileCache );
    if ( me )
    {
      free( me );
      me = 0;
    }
    if ( persistent_cookies )
      LYStoreCookies( LYCookieSaveFile );
    exit_immediately( 0 );
  }
  if ( me == 0 )
  {
    return;
  }
  free( me );
  me = 0;
  return;
}
Example #12
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;
}