CVS update: php31/main
| From: | cschneid | Date: | Sun, 08 Nov 1998 02:43:36 +0000 |
| Subject: | CVS update: php31/main | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-2280@lists.php.net to get a copy of this message | ||
Date: Saturday November 7, 1998 @ 21:43
Author: cschneid
Update of /repository/php31/main
In directory asf:/u2/tmp/cvs-serv18111/main
Modified Files:
main.c
Log Message:
Added on the fly output compression. It requires zlib support and includes
configure option --disable-output-compression and
php31.ini option compress_output=yes|no
Output is sent compressed with Content-encoding: gzip if browser sent
Accept-encoding: *gzip* before. All code related to output compression
is enclosed in #if PHP3_COMPRESS_OUTPUT set by configure.
Index: php31/main/main.c
diff -c php31/main/main.c:2.47 php31/main/main.c:2.48
*** php31/main/main.c:2.47 Thu Nov 5 16:45:10 1998
--- php31/main/main.c Sat Nov 7 21:43:35 1998
***************
*** 29,35 ****
+----------------------------------------------------------------------+
*/
! /* $Id: main.c,v 2.47 1998/11/05 21:45:10 cschneid Exp $ */
/* #define CRASH_DETECTION */
--- 29,35 ----
+----------------------------------------------------------------------+
*/
! /* $Id: main.c,v 2.48 1998/11/08 02:43:35 cschneid Exp $ */
/* #define CRASH_DETECTION */
***************
*** 137,142 ****
--- 137,334 ----
static void php3_set_timeout(long seconds INLINE_TLS);
extern void php3_treat_headers(INLINE_TLS_VOID);
+ #if PHP3_COMPRESS_OUTPUT
+ static voidpf compress_output_zalloc(voidpf opaque, uInt items, uInt size)
+ {
+ return emalloc(items * size);
+ }
+
+ static void compress_output_zfree(voidpf opaque, voidpf address)
+ {
+ efree(address);
+ }
+
+ static void compress_output_putlong (struct sapi_request_info *sapi_info, uLong x)
+ {
+ unsigned char buf[4];
+
+ buf[0] = x & 0xff;
+ buf[1] = (x >> 8) & 0xff;
+ buf[2] = (x >> 16) & 0xff;
+ buf[3] = (x >> 24) & 0xff;
+
+ sapi_info->savedwriteclient(buf, sizeof(buf) _INLINE_TLS);
+ }
+
+ static int compress_output_writeclient(SAPI_GLOBAL_INCLUDE unsigned char *buf, int size)
+ {
+ int written;
+
+ int zerr = Z_OK;
+
+ GLOBAL(sapi_rqst)->zstream.next_in = (Bytef*)buf;
+ GLOBAL(sapi_rqst)->zstream.avail_in = size;
+
+ /* Basic compression loop adapted from gzwrite in zlib gzio.c */
+ while (GLOBAL(sapi_rqst)->zstream.avail_in > 0) {
+ if (GLOBAL(sapi_rqst)->zstream.avail_out == 0) {
+ GLOBAL(sapi_rqst)->zstream.next_out = GLOBAL(sapi_rqst)->zoutbuf;
+
+ if (GLOBAL(sapi_rqst)->savedwriteclient(SAPI_GLOBAL_PASS GLOBAL(sapi_rqst)->zoutbuf,
ZOUTBUF_SIZE) != ZOUTBUF_SIZE) {
+ zerr = Z_ERRNO;
+ break;
+ }
+
+ GLOBAL(sapi_rqst)->zstream.avail_out = ZOUTBUF_SIZE;
+ }
+
+ zerr = deflate(&GLOBAL(sapi_rqst)->zstream, Z_NO_FLUSH);
+
+ if (zerr != Z_OK)
+ break;
+ }
+
+ GLOBAL(sapi_rqst)->zcrc = crc32(GLOBAL(sapi_rqst)->zcrc, (const Bytef *)buf, size);
+
+ written = (zerr == Z_OK) ? size : -1;
+
+ return written;
+ }
+
+ static int compress_output_flush(SAPI_GLOBAL_INCLUDE_V)
+ {
+ uInt len;
+ int done = 0;
+ int zerr = Z_OK;
+
+ /* Flush loop adapted from do_flush in zlib gzio.c */
+ for (;;) {
+ len = ZOUTBUF_SIZE - GLOBAL(sapi_rqst)->zstream.avail_out;
+
+ if (len != 0) {
+ if (GLOBAL(sapi_rqst)->savedwriteclient(SAPI_GLOBAL_PASS GLOBAL(sapi_rqst)->zoutbuf, len
_INLINE_TLS) != len) {
+ zerr = Z_ERRNO;
+ break;
+ }
+ GLOBAL(sapi_rqst)->zstream.next_out = GLOBAL(sapi_rqst)->zoutbuf;
+ GLOBAL(sapi_rqst)->zstream.avail_out = ZOUTBUF_SIZE;
+ }
+
+ if (done)
+ break;
+
+ zerr = deflate(&GLOBAL(sapi_rqst)->zstream, Z_SYNC_FLUSH);
+
+ /* deflate has finished flushing only when it used all input:
+ */
+ done = (GLOBAL(sapi_rqst)->zstream.avail_in == 0);
+
+ if (zerr != Z_OK)
+ break;
+ }
+
+ return GLOBAL(sapi_rqst)->savedflush(SAPI_GLOBAL_PASS_V);
+ }
+
+ static void compress_output_init(struct sapi_request_info *sapi_info)
+ {
+ /* Protect against being called twice on same sapi_info */
+ if (sapi_info && (sapi_info->writeclient != compress_output_writeclient)) {
+ long compress_output;
+
+ sapi_info->savedwriteclient = NULL;
+ sapi_info->savedflush = NULL;
+
+ if ((ini_get_long("compress_output", &compress_output) != FAILURE) &&
(compress_output)) {
+ char *s = sapi_info->getenv("HTTP_ACCEPT_ENCODING");
+
+ if (s && strstr(s, "gzip")) {
+ sapi_info->zoutbuf = emalloc(ZOUTBUF_SIZE);
+
+ if (sapi_info->zoutbuf) {
+ sapi_info->zstream.zalloc = compress_output_zalloc;
+ sapi_info->zstream.zfree = compress_output_zfree;
+ sapi_info->zstream.opaque = Z_NULL;
+
+ /* windowBits < 0 to suppress zlib header if gzip mode */
+ if (deflateInit2(&(sapi_info->zstream), Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS,
DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY) == Z_OK) {
+ /* Prefill output buffer with gzip file header */
+ static Bytef gz_header[] = { 0x1f, 0x8b, Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0
/*xflags*/, OS_CODE };
+
+ sapi_info->zstream.next_out = sapi_info->zoutbuf;
+ sapi_info->zstream.avail_out = ZOUTBUF_SIZE;
+
+ memcpy(sapi_info->zoutbuf, gz_header, sizeof(gz_header));
+ sapi_info->zstream.next_out += sizeof(gz_header);
+ sapi_info->zstream.avail_out -= sizeof(gz_header);
+ sapi_info->zcrc = 0;
+ sapi_info->insert_header("Content-encoding: gzip");
+
+ /* Wedge into output functions */
+ sapi_info->savedwriteclient = sapi_info->writeclient;
+ sapi_info->writeclient = compress_output_writeclient;
+ sapi_info->savedflush = sapi_info->flush;
+ sapi_info->flush = compress_output_flush;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static void compress_output_exit(struct sapi_request_info *sapi_info)
+ {
+ if (sapi_info && sapi_info->savedwriteclient) {
+ uInt len;
+ int done = 0;
+ int zerr = Z_OK;
+
+ /* Flush loop adapted from do_flush in zlib gzio.c */
+ for (;;) {
+ len = ZOUTBUF_SIZE - sapi_info->zstream.avail_out;
+
+ if (len != 0) {
+ if (sapi_info->savedwriteclient(SAPI_GLOBAL_PASS sapi_info->zoutbuf, len _INLINE_TLS) !=
len) {
+ zerr = Z_ERRNO;
+ break;
+ }
+ sapi_info->zstream.next_out = sapi_info->zoutbuf;
+ sapi_info->zstream.avail_out = ZOUTBUF_SIZE;
+ }
+
+ if (done)
+ break;
+
+ zerr = deflate(&sapi_info->zstream, Z_FINISH);
+
+ /* deflate has finished flushing only when it hasn't used up
+ * all the available space in the output buffer:
+ */
+ done = (sapi_info->zstream.avail_out != 0 || zerr == Z_STREAM_END);
+
+ if (zerr != Z_OK && zerr != Z_STREAM_END)
+ break;
+ }
+
+ compress_output_putlong(sapi_info, sapi_info->zcrc);
+ compress_output_putlong(sapi_info, sapi_info->zstream.total_in);
+ }
+
+ if (sapi_info->zoutbuf) {
+ efree(sapi_info->zoutbuf);
+ sapi_info->zoutbuf = NULL;
+ }
+
+ if (sapi_info->savedwriteclient) {
+ deflateEnd(&sapi_info->zstream);
+
+ /* Undo wedge into output functions */
+ sapi_info->writeclient = sapi_info->savedwriteclient;
+ sapi_info->flush = sapi_info->savedflush;
+ }
+ }
+ #endif
+
#if defined(CRASH_DETECTION)
/*
* function to log debug messages
***************
*** 247,252 ****
--- 439,445 ----
PHPAPI int php3_sapi_writeclient(void *buf, int size INLINE_TLS)
{
int ret;
+
if (GLOBAL(sapi_rqst)->buffered_output) {
string_buffer_concat(&GLOBAL(sapi_rqst)->output_buffer, buf, size);
return size;
***************
*** 1516,1521 ****
--- 1709,1718 ----
}
php3_treat_headers(_INLINE_TLS_VOID);
+ #if PHP3_COMPRESS_OUTPUT
+ compress_output_init(sapi_info);
+ #endif
+
#if defined(CRASH_DETECTION)
debug_log("%d:request startup success\n", GetCurrentThreadId());
#endif
***************
*** 1655,1660 ****
--- 1852,1860 ----
debug_log("%d:start request shutdown\n", GetCurrentThreadId());
#endif
php3_header(); /* Make sure headers have been sent */
+ #if PHP3_COMPRESS_OUTPUT
+ compress_output_exit(sapi_info);
+ #endif
php3_request_shutdown((void *) GLOBAL(sapi_rqst) _INLINE_TLS);
#if defined(CRASH_DETECTION)
debug_log("%d:request shutdown done\n", GetCurrentThreadId());
--
PHP Development Mailing List http://www.php.net/
To unsubscribe send an empty message to php-dev-unsubscribe@lists.php.net
For help: php-dev-help@lists.php.net