httpRead2(http_t *http,			/* I - HTTP connection */
          char   *buffer,		/* I - Buffer for data */
	  size_t length)		/* I - Maximum number of bytes */
{
  ssize_t	bytes;			/* Bytes read */


#ifdef HAVE_LIBZ
  DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ") coding=%d data_encoding=%d data_remaining=" CUPS_LLFMT, (void *)http, (void *)buffer, CUPS_LLCAST length, http->coding, http->data_encoding, CUPS_LLCAST http->data_remaining));
#else
  DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ") data_encoding=%d data_remaining=" CUPS_LLFMT, (void *)http, (void *)buffer, CUPS_LLCAST length, http->data_encoding, CUPS_LLCAST http->data_remaining));
#endif /* HAVE_LIBZ */

  if (http == NULL || buffer == NULL)
    return (-1);

  http->activity = time(NULL);
  http->error    = 0;

  if (length <= 0)
    return (0);

#ifdef HAVE_LIBZ
  if (http->coding >= _HTTP_CODING_GUNZIP)
  {
    do
    {
      if (((z_stream *)http->stream)->avail_in > 0)
      {
	int	zerr;			/* Decompressor error */

	DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d",
	              (int)((z_stream *)http->stream)->avail_in, (int)length));

	((z_stream *)http->stream)->next_out  = (Bytef *)buffer;
	((z_stream *)http->stream)->avail_out = (uInt)length;

	if ((zerr = inflate((z_stream *)http->stream, Z_SYNC_FLUSH)) < Z_OK)
	{
	  DEBUG_printf(("2httpRead2: zerr=%d", zerr));
#ifdef DEBUG
          http_debug_hex("2httpRead2", (char *)http->sbuffer, (int)((z_stream *)http->stream)->avail_in);
#endif /* DEBUG */

	  http->error = EIO;
	  return (-1);
	}

	bytes = (ssize_t)(length - ((z_stream *)http->stream)->avail_out);

	DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d, bytes=%d",
		      ((z_stream *)http->stream)->avail_in, ((z_stream *)http->stream)->avail_out,
		      (int)bytes));
      }
      else
        bytes = 0;

      if (bytes == 0)
      {
        ssize_t buflen = HTTP_MAX_BUFFER - (ssize_t)((z_stream *)http->stream)->avail_in;
					/* Additional bytes for buffer */

        if (buflen > 0)
        {
          if (((z_stream *)http->stream)->avail_in > 0 &&
              ((z_stream *)http->stream)->next_in > http->sbuffer)
            memmove(http->sbuffer, ((z_stream *)http->stream)->next_in, ((z_stream *)http->stream)->avail_in);

	  ((z_stream *)http->stream)->next_in = http->sbuffer;

          DEBUG_printf(("1httpRead2: Reading up to %d more bytes of data into "
                        "decompression buffer.", (int)buflen));

          if (http->data_remaining > 0)
          {
	    if (buflen > http->data_remaining)
	      buflen = (ssize_t)http->data_remaining;

	    bytes = http_read_buffered(http, (char *)http->sbuffer + ((z_stream *)http->stream)->avail_in, (size_t)buflen);
          }
          else if (http->data_encoding == HTTP_ENCODING_CHUNKED)
            bytes = http_read_chunk(http, (char *)http->sbuffer + ((z_stream *)http->stream)->avail_in, (size_t)buflen);
          else
            bytes = 0;

          if (bytes < 0)
            return (bytes);
          else if (bytes == 0)
            break;

          DEBUG_printf(("1httpRead2: Adding " CUPS_LLFMT " bytes to "
                        "decompression buffer.", CUPS_LLCAST bytes));

          http->data_remaining  -= bytes;
          ((z_stream *)http->stream)->avail_in += (uInt)bytes;

	  if (http->data_remaining <= 0 &&
	      http->data_encoding == HTTP_ENCODING_CHUNKED)
	  {
	   /*
	    * Read the trailing blank line now...
	    */

	    char	len[32];		/* Length string */

	    httpGets(len, sizeof(len), http);
	  }

          bytes = 0;
        }
        else
          return (0);
      }
    }
    while (bytes == 0);
  }
  else
#endif /* HAVE_LIBZ */
  if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODING_CHUNKED)
  {
    if ((bytes = http_read_chunk(http, buffer, length)) > 0)
    {
      http->data_remaining -= bytes;

      if (http->data_remaining <= 0)
      {
       /*
        * Read the trailing blank line now...
        */

        char	len[32];		/* Length string */

        httpGets(len, sizeof(len), http);
      }
    }
  }
  else if (http->data_remaining <= 0)
  {
   /*
    * No more data to read...
    */

    return (0);
  }
  else
  {
    DEBUG_printf(("1httpRead2: Reading up to %d bytes into buffer.",
                  (int)length));

    if (length > (size_t)http->data_remaining)
      length = (size_t)http->data_remaining;

    if ((bytes = http_read_buffered(http, buffer, length)) > 0)
    {
      http->data_remaining -= bytes;

      if (http->data_remaining <= 0 &&
          http->data_encoding == HTTP_ENCODING_CHUNKED)
      {
       /*
        * Read the trailing blank line now...
        */

        char	len[32];		/* Length string */

        httpGets(len, sizeof(len), http);
      }
    }
  }

  if (
#ifdef HAVE_LIBZ
      (http->coding == _HTTP_CODING_IDENTITY ||
       (http->coding >= _HTTP_CODING_GUNZIP && ((z_stream *)http->stream)->avail_in == 0)) &&
#endif /* HAVE_LIBZ */
      ((http->data_remaining <= 0 &&
        http->data_encoding == HTTP_ENCODING_LENGTH) ||
       (http->data_encoding == HTTP_ENCODING_CHUNKED && bytes == 0)))
  {
#ifdef HAVE_LIBZ
    if (http->coding >= _HTTP_CODING_GUNZIP)
      http_content_coding_finish(http);
#endif /* HAVE_LIBZ */

    if (http->state == HTTP_STATE_POST_RECV)
      http->state ++;
    else if (http->state == HTTP_STATE_GET_SEND ||
             http->state == HTTP_STATE_POST_SEND)
      http->state = HTTP_STATE_WAITING;
    else
      http->state = HTTP_STATE_STATUS;

    DEBUG_printf(("1httpRead2: End of content, set state to %s.",
		  httpStateString(http->state)));
  }

  return (bytes);
}