about summary refs log tree commit diff stats
path: root/WWW/Library/Implementation/HTFormat.c
diff options
context:
space:
mode:
Diffstat (limited to 'WWW/Library/Implementation/HTFormat.c')
-rw-r--r--WWW/Library/Implementation/HTFormat.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/WWW/Library/Implementation/HTFormat.c b/WWW/Library/Implementation/HTFormat.c
index c8bda5de..b5f8584d 100644
--- a/WWW/Library/Implementation/HTFormat.c
+++ b/WWW/Library/Implementation/HTFormat.c
@@ -661,6 +661,99 @@ PUBLIC int HTFileCopy ARGS2(
     return rv;
 }
 
+#ifdef USE_ZLIB
+/*	Push data from a gzip file pointer down a stream
+**	-------------------------------------
+**
+**   This routine is responsible for creating and PRESENTING any
+**   graphic (or other) objects described by the file.
+**
+**
+*/
+PRIVATE int HTGzFileCopy ARGS2(
+	gzFile,			gzfp,
+	HTStream*,		sink)
+{
+    HTStreamClass targetClass;    
+    char line[256];
+    int status, bytes = 0, nreads = 0, nprogr = 0;
+    int gzerrnum;
+    int rv = HT_OK;
+    
+    /*  Push the data down the stream
+    */
+    targetClass = *(sink->isa);	/* Copy pointers to procedures */
+
+    /*	read and inflate gzipped file, and push binary down sink
+    */
+    for (;;) {
+	status = gzread(gzfp, input_buffer, INPUT_BUFFER_SIZE);
+	nreads++;
+	if (status <= 0) { /* EOF or error */
+	    if (status == 0) {
+		rv = HT_LOADED;
+	        break;
+	    }
+	    if (TRACE) {
+	        fprintf(stderr,
+			"HTGzFileCopy: Read error, gzread returns %d\n",
+			status);
+	        fprintf(stderr,
+			"gzerror   : %s\n",
+			gzerror(gzfp, &gzerrnum));
+		if (gzerrnum == Z_ERRNO)
+		    perror("gzerror   ");
+	    }
+	    if (bytes) {
+		rv = HT_PARTIAL_CONTENT;
+	    } else {
+		rv = -1;
+	    }
+	    break;
+	}
+	(*targetClass.put_block)(sink, input_buffer, status);
+
+	bytes += status;
+	if (nreads >= 100) {
+	    /*
+	    **  Show progress messages for local files, and check for
+	    **  user interruption.  Start doing so only after a certain
+	    **  number of reads have been done, and don't update it on
+	    **  every read (normally reading in a local file should be
+	    **  speedy). - KW
+	    */
+	    if (nprogr == 0) {
+		if (bytes < 1024000) {
+		    sprintf(line,
+			    "Read %d uncompressed bytes of data.", bytes);
+		} else {
+		    sprintf(line, "Read %d uncompressed KB of data. %s",
+				  bytes/1024,
+		    "(Press 'z' to abort.)");
+		}
+		HTProgress(line);
+		if (HTCheckForInterrupt()) {
+		    _HTProgress ("Data transfer interrupted.");
+		    if (bytes) {
+			rv = HT_INTERRUPTED;
+		    } else {
+			rv = -1;
+		    }
+		    break;
+		}
+		nprogr++;
+	    } else if (nprogr == 25) {
+		nprogr = 0;
+	    } else {
+		nprogr++;
+	    }
+	}
+    } /* next bufferload */
+
+    return rv;
+}
+#endif /* USE_ZLIB */
+
 /*	Push data from a socket down a stream STRIPPING CR
 **	--------------------------------------------------
 **
@@ -807,6 +900,78 @@ PUBLIC int HTParseFile ARGS5(
 	return HT_LOADED;
 }
 
+#ifdef USE_ZLIB
+PRIVATE int HTCloseGzFile ARGS1(
+	gzFile,			gzfp)
+{
+    int gzres;
+    if (gzfp == NULL)
+	return 0;
+    gzres = gzclose(gzfp);
+    if (TRACE) {
+	if (gzres == Z_ERRNO) {
+	    perror("gzclose   ");
+	} else if (gzres != Z_OK) {
+	    fprintf(stderr, "gzclose   : error number %d\n", gzres);
+	}
+    }
+    return(gzres);
+}
+    
+PUBLIC int HTParseGzFile ARGS5(
+	HTFormat,		rep_in,
+	HTFormat,		format_out,
+	HTParentAnchor *,	anchor,
+	gzFile,			gzfp,
+	HTStream*,		sink)
+{
+    HTStream * stream;
+    HTStreamClass targetClass;    
+    int rv;
+
+    stream = HTStreamStack(rep_in,
+			format_out,
+	 		sink , anchor);
+    
+    if (!stream) {
+        char buffer[1024];	/* @@@@@@@@ */
+	extern char LYCancelDownload;
+	HTCloseGzFile(gzfp);
+        if (LYCancelDownload) {
+	    LYCancelDownload = FALSE;
+	    return -1;
+	}
+	sprintf(buffer, "Sorry, can't convert from %s to %s.",
+		HTAtom_name(rep_in), HTAtom_name(format_out));
+	if (TRACE)
+	    fprintf(stderr, "HTFormat(in HTParseGzFile): %s\n", buffer);
+        return HTLoadError(sink, 501, buffer);
+    }
+    
+    /*  Push the data down the stream
+    **
+    **  @@  Bug:  This decision ought to be made based on "encoding"
+    **  rather than on content-type.  @@@  When we handle encoding.
+    **  The current method smells anyway.
+    */
+    targetClass = *(stream->isa);	/* Copy pointers to procedures */
+    rv = HTGzFileCopy(gzfp, stream);
+    if (rv == -1 || rv == HT_INTERRUPTED) {
+        (*targetClass._abort)(stream, NULL);
+    } else {
+	(*targetClass._free)(stream);
+    }
+
+    HTCloseGzFile(gzfp);
+    if (rv == -1)
+	return HT_NO_DATA;
+    else if (rv == HT_INTERRUPTED || (rv > 0 && rv != HT_LOADED))
+	return HT_PARTIAL_CONTENT;
+    else
+	return HT_LOADED;
+}
+#endif /* USE_ZLIB */
+
 /*	Converter stream: Network Telnet to internal character text
 **	-----------------------------------------------------------
 **