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

📄 protocol.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed 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. *//* * http_protocol.c --- routines which directly communicate with the client. * * Code originally by Rob McCool; much redone by Robert S. Thau * and the Apache Software Foundation. */#include "apr.h"#include "apr_strings.h"#include "apr_buckets.h"#include "apr_lib.h"#include "apr_signal.h"#include "apr_strmatch.h"#define APR_WANT_STDIO          /* for sscanf */#define APR_WANT_STRFUNC#define APR_WANT_MEMFUNC#include "apr_want.h"#define CORE_PRIVATE#include "util_filter.h"#include "ap_config.h"#include "httpd.h"#include "http_config.h"#include "http_core.h"#include "http_protocol.h"#include "http_main.h"#include "http_request.h"#include "http_vhost.h"#include "http_log.h"           /* For errors detected in basic auth common                                 * support code... */#include "mod_core.h"#include "util_charset.h"#include "util_ebcdic.h"#include "scoreboard.h"#if APR_HAVE_STDARG_H#include <stdarg.h>#endif#if APR_HAVE_UNISTD_H#include <unistd.h>#endifAPR_HOOK_STRUCT(    APR_HOOK_LINK(post_read_request)    APR_HOOK_LINK(log_transaction)    APR_HOOK_LINK(http_method)    APR_HOOK_LINK(default_port))AP_DECLARE_DATA ap_filter_rec_t *ap_old_write_func = NULL;/* Patterns to match in ap_make_content_type() */static const char *needcset[] = {    "text/plain",    "text/html",    NULL};static const apr_strmatch_pattern **needcset_patterns;static const apr_strmatch_pattern *charset_pattern;AP_DECLARE(void) ap_setup_make_content_type(apr_pool_t *pool){    int i;    for (i = 0; needcset[i]; i++) {        continue;    }    needcset_patterns = (const apr_strmatch_pattern **)        apr_palloc(pool, (i + 1) * sizeof(apr_strmatch_pattern *));    for (i = 0; needcset[i]; i++) {        needcset_patterns[i] = apr_strmatch_precompile(pool, needcset[i], 0);    }    needcset_patterns[i] = NULL;    charset_pattern = apr_strmatch_precompile(pool, "charset=", 0);}/* * Builds the content-type that should be sent to the client from the * content-type specified.  The following rules are followed: *    - if type is NULL, type is set to ap_default_type(r) *    - if charset adding is disabled, stop processing and return type. *    - then, if there are no parameters on type, add the default charset *    - return type */AP_DECLARE(const char *)ap_make_content_type(request_rec *r, const char *type){    const apr_strmatch_pattern **pcset;    core_dir_config *conf =        (core_dir_config *)ap_get_module_config(r->per_dir_config,                                                &core_module);    apr_size_t type_len;    if (!type) {        type = ap_default_type(r);    }    if (conf->add_default_charset != ADD_DEFAULT_CHARSET_ON) {        return type;    }    type_len = strlen(type);    if (apr_strmatch(charset_pattern, type, type_len) != NULL) {        /* already has parameter, do nothing */        /* XXX we don't check the validity */        ;    }    else {        /* see if it makes sense to add the charset. At present,         * we only add it if the Content-type is one of needcset[]         */        for (pcset = needcset_patterns; *pcset ; pcset++) {            if (apr_strmatch(*pcset, type, type_len) != NULL) {                struct iovec concat[3];                concat[0].iov_base = (void *)type;                concat[0].iov_len = type_len;                concat[1].iov_base = (void *)"; charset=";                concat[1].iov_len = sizeof("; charset=") - 1;                concat[2].iov_base = (void *)(conf->add_default_charset_name);                concat[2].iov_len = strlen(conf->add_default_charset_name);                type = apr_pstrcatv(r->pool, concat, 3, NULL);                break;            }        }    }    return type;}AP_DECLARE(void) ap_set_content_length(request_rec *r, apr_off_t clength){    r->clength = clength;    apr_table_setn(r->headers_out, "Content-Length",                   apr_off_t_toa(r->pool, clength));}/* * Return the latest rational time from a request/mtime (modification time) * pair.  We return the mtime unless it's in the future, in which case we * return the current time.  We use the request time as a reference in order * to limit the number of calls to time().  We don't check for futurosity * unless the mtime is at least as new as the reference. */AP_DECLARE(apr_time_t) ap_rationalize_mtime(request_rec *r, apr_time_t mtime){    apr_time_t now;    /* For all static responses, it's almost certain that the file was     * last modified before the beginning of the request.  So there's     * no reason to call time(NULL) again.  But if the response has been     * created on demand, then it might be newer than the time the request     * started.  In this event we really have to call time(NULL) again     * so that we can give the clients the most accurate Last-Modified.  If we     * were given a time in the future, we return the current time - the     * Last-Modified can't be in the future.     */    now = (mtime < r->request_time) ? r->request_time : apr_time_now();    return (mtime > now) ? now : mtime;}/* Min # of bytes to allocate when reading a request line */#define MIN_LINE_ALLOC 80/* Get a line of protocol input, including any continuation lines * caused by MIME folding (or broken clients) if fold != 0, and place it * in the buffer s, of size n bytes, without the ending newline. * * If s is NULL, ap_rgetline_core will allocate necessary memory from r->pool. * * Returns APR_SUCCESS if there are no problems and sets *read to be * the full length of s. * * APR_ENOSPC is returned if there is not enough buffer space. * Other errors may be returned on other errors. * * The LF is *not* returned in the buffer.  Therefore, a *read of 0 * indicates that an empty line was read. * * Notes: Because the buffer uses 1 char for NUL, the most we can return is *        (n - 1) actual characters. * *        If no LF is detected on the last line due to a dropped connection *        or a full buffer, that's considered an error. */AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n,                                          apr_size_t *read, request_rec *r,                                          int fold, apr_bucket_brigade *bb){    apr_status_t rv;    apr_bucket *e;    apr_size_t bytes_handled = 0, current_alloc = 0;    char *pos, *last_char = *s;    int do_alloc = (*s == NULL), saw_eos = 0;    for (;;) {    apr_brigade_cleanup(bb);    rv = ap_get_brigade(r->input_filters, bb, AP_MODE_GETLINE,                        APR_BLOCK_READ, 0);    if (rv != APR_SUCCESS) {        return rv;    }    /* Something horribly wrong happened.  Someone didn't block! */    if (APR_BRIGADE_EMPTY(bb)) {        return APR_EGENERAL;    }    APR_BRIGADE_FOREACH(e, bb) {        const char *str;        apr_size_t len;        /* If we see an EOS, don't bother doing anything more. */        if (APR_BUCKET_IS_EOS(e)) {            saw_eos = 1;            break;        }        rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);        if (rv != APR_SUCCESS) {            return rv;        }        if (len == 0) {            /* no use attempting a zero-byte alloc (hurts when             * using --with-efence --enable-pool-debug) or             * doing any of the other logic either             */            continue;        }        /* Would this overrun our buffer?  If so, we'll die. */        if (n < bytes_handled + len) {            *read = bytes_handled;            if (*s) {                /* ensure this string is NUL terminated */                if (bytes_handled > 0) {                    (*s)[bytes_handled-1] = '\0';                }                else {                    (*s)[0] = '\0';                }            }            return APR_ENOSPC;        }        /* Do we have to handle the allocation ourselves? */        if (do_alloc) {            /* We'll assume the common case where one bucket is enough. */            if (!*s) {                current_alloc = len;                if (current_alloc < MIN_LINE_ALLOC) {                    current_alloc = MIN_LINE_ALLOC;                }                *s = apr_palloc(r->pool, current_alloc);            }            else if (bytes_handled + len > current_alloc) {                /* Increase the buffer size */                apr_size_t new_size = current_alloc * 2;                char *new_buffer;                if (bytes_handled + len > new_size) {                    new_size = (bytes_handled + len) * 2;                }                new_buffer = apr_palloc(r->pool, new_size);                /* Copy what we already had. */                memcpy(new_buffer, *s, bytes_handled);                current_alloc = new_size;                *s = new_buffer;            }        }        /* Just copy the rest of the data to the end of the old buffer. */        pos = *s + bytes_handled;        memcpy(pos, str, len);        last_char = pos + len - 1;        /* We've now processed that new data - update accordingly. */        bytes_handled += len;    }        /* If we got a full line of input, stop reading */        if (last_char && (*last_char == APR_ASCII_LF)) {            break;        }    }    /* Now NUL-terminate the string at the end of the line;      * if the last-but-one character is a CR, terminate there */    if (last_char > *s && last_char[-1] == APR_ASCII_CR) {        last_char--;    }    *last_char = '\0';    bytes_handled = last_char - *s;    /* If we're folding, we have more work to do.     *     * Note that if an EOS was seen, we know we can't have another line.     */    if (fold && bytes_handled && !saw_eos) {        for (;;) {        const char *str;        apr_size_t len;        char c;        /* Clear the temp brigade for this filter read. */        apr_brigade_cleanup(bb);        /* We only care about the first byte. */        rv = ap_get_brigade(r->input_filters, bb, AP_MODE_SPECULATIVE,                            APR_BLOCK_READ, 1);        if (rv != APR_SUCCESS) {            return rv;        }        if (APR_BRIGADE_EMPTY(bb)) {                break;        }        e = APR_BRIGADE_FIRST(bb);        /* If we see an EOS, don't bother doing anything more. */        if (APR_BUCKET_IS_EOS(e)) {                break;        }        rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);        if (rv != APR_SUCCESS) {                apr_brigade_cleanup(bb);            return rv;        }        /* Found one, so call ourselves again to get the next line.         *         * FIXME: If the folding line is completely blank, should we         * stop folding?  Does that require also looking at the next         * char?         */            /* When we call destroy, the buckets are deleted, so save that             * one character we need.  This simplifies our execution paths             * at the cost of one character read.             */            c = *str;        if (c == APR_ASCII_BLANK || c == APR_ASCII_TAB) {            /* Do we have enough space? We may be full now. */                if (bytes_handled >= n) {                    *read = n;                    /* ensure this string is terminated */                    (*s)[n-1] = '\0';                    return APR_ENOSPC;                }                else {                apr_size_t next_size, next_len;                char *tmp;                /* If we're doing the allocations for them, we have to                 * give ourselves a NULL and copy it on return.                 */                if (do_alloc) {                    tmp = NULL;                } else {                    /* We're null terminated. */

⌨️ 快捷键说明

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