⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_deflate.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * mod_deflate.c: Perform deflate content-encoding on the fly * * Written by Ian Holsman, Justin Erenkrantz, and Nick Kew *//* * Portions of this software are based upon zlib code by Jean-loup Gailly * (zlib functions gz_open and gzwrite, check_header) *//* zlib flags */#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */#define ORIG_NAME    0x08 /* bit 3 set: original file name present */#define COMMENT      0x10 /* bit 4 set: file comment present */#define RESERVED     0xE0 /* bits 5..7: reserved */#include "httpd.h"#include "http_config.h"#include "http_log.h"#include "apr_lib.h"#include "apr_strings.h"#include "apr_general.h"#include "util_filter.h"#include "apr_buckets.h"#include "http_request.h"#define APR_WANT_STRFUNC#include "apr_want.h"#include "zlib.h"static const char deflateFilterName[] = "DEFLATE";module AP_MODULE_DECLARE_DATA deflate_module;typedef struct deflate_filter_config_t{    int windowSize;    int memlevel;    int compressionlevel;    apr_size_t bufferSize;    char *note_ratio_name;    char *note_input_name;    char *note_output_name;} deflate_filter_config;/* RFC 1952 Section 2.3 defines the gzip header: * * +---+---+---+---+---+---+---+---+---+---+ * |ID1|ID2|CM |FLG|     MTIME     |XFL|OS | * +---+---+---+---+---+---+---+---+---+---+ */static const char gzip_header[10] ={ '\037', '\213', Z_DEFLATED, 0,  0, 0, 0, 0, /* mtime */  0, 0x03 /* Unix OS_CODE */};/* magic header */static const char deflate_magic[2] = { '\037', '\213' };/* windowsize is negative to suppress Zlib header */#define DEFAULT_COMPRESSION Z_DEFAULT_COMPRESSION#define DEFAULT_WINDOWSIZE -15#define DEFAULT_MEMLEVEL 9#define DEFAULT_BUFFERSIZE 8096/* Check whether a request is gzipped, so we can un-gzip it. * If a request has multiple encodings, we need the gzip * to be the outermost non-identity encoding. */static int check_gzip(request_rec *r, apr_table_t *hdrs1, apr_table_t *hdrs2){    int found = 0;    apr_table_t *hdrs = hdrs1;    const char *encoding = apr_table_get(hdrs, "Content-Encoding");    if (!encoding && (hdrs2 != NULL)) {        /* the output filter has two tables and a content_encoding to check */        encoding = apr_table_get(hdrs2, "Content-Encoding");        hdrs = hdrs2;        if (!encoding) {            encoding = r->content_encoding;            hdrs = NULL;        }    }    if (encoding && *encoding) {        /* check the usual/simple case first */        if (!strcasecmp(encoding, "gzip")            || !strcasecmp(encoding, "x-gzip")) {            found = 1;            if (hdrs) {                apr_table_unset(hdrs, "Content-Encoding");            }            else {                r->content_encoding = NULL;            }        }        else if (ap_strchr_c(encoding, ',') != NULL) {            /* If the outermost encoding isn't gzip, there's nowt             * we can do.  So only check the last non-identity token             */            char *new_encoding = apr_pstrdup(r->pool, encoding);            char *ptr;            for(;;) {                char *token = ap_strrchr(new_encoding, ',');                if (!token) {        /* gzip:identity or other:identity */                    if (!strcasecmp(new_encoding, "gzip")                        || !strcasecmp(new_encoding, "x-gzip")) {                        found = 1;                        if (hdrs) {                            apr_table_unset(hdrs, "Content-Encoding");                        }                        else {                            r->content_encoding = NULL;                        }                    }                    break; /* seen all tokens */                }                for (ptr=token+1; apr_isspace(*ptr); ++ptr);                if (!strcasecmp(ptr, "gzip")                    || !strcasecmp(ptr, "x-gzip")) {                    *token = '\0';                    if (hdrs) {                        apr_table_setn(hdrs, "Content-Encoding", new_encoding);                    }                    else {                        r->content_encoding = new_encoding;                    }                    found = 1;                }                else if (!ptr[0] || !strcasecmp(ptr, "identity")) {                    *token = '\0';                    continue; /* strip the token and find the next one */                }                break; /* found a non-identity token */            }        }    }    return found;}/* Outputs a long in LSB order to the given file * only the bottom 4 bits are required for the deflate file format. */static void putLong(unsigned char *string, unsigned long x){    string[0] = (unsigned char)(x & 0xff);    string[1] = (unsigned char)((x & 0xff00) >> 8);    string[2] = (unsigned char)((x & 0xff0000) >> 16);    string[3] = (unsigned char)((x & 0xff000000) >> 24);}/* Inputs a string and returns a long. */static unsigned long getLong(unsigned char *string){    return ((unsigned long)string[0])          | (((unsigned long)string[1]) << 8)          | (((unsigned long)string[2]) << 16)          | (((unsigned long)string[3]) << 24);}static void *create_deflate_server_config(apr_pool_t *p, server_rec *s){    deflate_filter_config *c = apr_pcalloc(p, sizeof *c);    c->memlevel   = DEFAULT_MEMLEVEL;    c->windowSize = DEFAULT_WINDOWSIZE;    c->bufferSize = DEFAULT_BUFFERSIZE;    c->compressionlevel = DEFAULT_COMPRESSION;    return c;}static const char *deflate_set_window_size(cmd_parms *cmd, void *dummy,                                           const char *arg){    deflate_filter_config *c = ap_get_module_config(cmd->server->module_config,                                                    &deflate_module);    int i;    i = atoi(arg);    if (i < 1 || i > 15)        return "DeflateWindowSize must be between 1 and 15";    c->windowSize = i * -1;    return NULL;}static const char *deflate_set_buffer_size(cmd_parms *cmd, void *dummy,                                           const char *arg){    deflate_filter_config *c = ap_get_module_config(cmd->server->module_config,                                                    &deflate_module);    int n = atoi(arg);    if (n <= 0) {        return "DeflateBufferSize should be positive";    }    c->bufferSize = (apr_size_t)n;    return NULL;}static const char *deflate_set_note(cmd_parms *cmd, void *dummy,                                    const char *arg1, const char *arg2){    deflate_filter_config *c = ap_get_module_config(cmd->server->module_config,                                                    &deflate_module);    if (arg2 == NULL) {        c->note_ratio_name = apr_pstrdup(cmd->pool, arg1);    }    else if (!strcasecmp(arg1, "ratio")) {        c->note_ratio_name = apr_pstrdup(cmd->pool, arg2);    }    else if (!strcasecmp(arg1, "input")) {        c->note_input_name = apr_pstrdup(cmd->pool, arg2);    }    else if (!strcasecmp(arg1, "output")) {        c->note_output_name = apr_pstrdup(cmd->pool, arg2);    }    else {        return apr_psprintf(cmd->pool, "Unknown note type %s", arg1);    }    return NULL;}static const char *deflate_set_memlevel(cmd_parms *cmd, void *dummy,                                        const char *arg){    deflate_filter_config *c = ap_get_module_config(cmd->server->module_config,                                                    &deflate_module);    int i;    i = atoi(arg);    if (i < 1 || i > 9)        return "DeflateMemLevel must be between 1 and 9";    c->memlevel = i;    return NULL;}static const char *deflate_set_compressionlevel(cmd_parms *cmd, void *dummy,                                        const char *arg){    deflate_filter_config *c = ap_get_module_config(cmd->server->module_config,                                                    &deflate_module);    int i;    i = atoi(arg);    if (i < 1 || i > 9)        return "Compression Level must be between 1 and 9";    c->compressionlevel = i;    return NULL;}typedef struct deflate_ctx_t{    z_stream stream;    unsigned char *buffer;    unsigned long crc;    apr_bucket_brigade *bb, *proc_bb;    int (*libz_end_func)(z_streamp);    unsigned char *validation_buffer;    apr_size_t validation_buffer_length;    int inflate_init;} deflate_ctx;/* Number of validation bytes (CRC and length) after the compressed data */#define VALIDATION_SIZE 8/* Do not update ctx->crc, see comment in flush_libz_buffer */#define NO_UPDATE_CRC 0/* Do update ctx->crc, see comment in flush_libz_buffer */#define UPDATE_CRC 1static int flush_libz_buffer(deflate_ctx *ctx, deflate_filter_config *c,                             struct apr_bucket_alloc_t *bucket_alloc,                             int (*libz_func)(z_streamp, int), int flush,                             int crc){    int zRC = Z_OK;    int done = 0;    unsigned int deflate_len;    apr_bucket *b;    for (;;) {         deflate_len = c->bufferSize - ctx->stream.avail_out;         if (deflate_len != 0) {             /*              * Do we need to update ctx->crc? Usually this is the case for              * inflate action where we need to do a crc on the output, whereas              * in the deflate case we need to do a crc on the input              */             if (crc) {                 ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer,                                  deflate_len);             }             b = apr_bucket_heap_create((char *)ctx->buffer,                                        deflate_len, NULL,                                        bucket_alloc);             APR_BRIGADE_INSERT_TAIL(ctx->bb, b);             ctx->stream.next_out = ctx->buffer;             ctx->stream.avail_out = c->bufferSize;         }         if (done)             break;         zRC = libz_func(&ctx->stream, flush);         /*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -