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

📄 buffer.c

📁 boa:Linux系统中的轻量级Web服务
💻 C
字号:
/* *  Boa, an http server *  Copyright (C) 1995 Paul Phillips <paulp@go2net.com> *  Some changes Copyright (C) 1999 Jon Nelson <jnelson@boa.org> *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 1, or (at your option) *  any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *//* $Id: buffer.c,v 1.10.2.2 2002/07/26 03:03:44 jnelson Exp $ */#include "boa.h"#include "escape.h"#define INT_TO_HEX(x) \    ((((x)-10)>=0)?('A'+((x)-10)):('0'+(x)))/* * Name: req_write * * Description: Buffers data before sending to client. * Returns: -1 for error, otherwise how much is stored */int req_write(request * req, char *msg){    int msg_len;    msg_len = strlen(msg);    if (!msg_len || req->status == DEAD)        return req->buffer_end;    if (req->buffer_end + msg_len > BUFFER_SIZE) {        log_error_time();        fprintf(stderr, "Ran out of Buffer space!\n");        req->status = DEAD;        return -1;    }    memcpy(req->buffer + req->buffer_end, msg, msg_len);    req->buffer_end += msg_len;    return req->buffer_end;}void reset_output_buffer(request *req){    req->buffer_end = 0;}/* * Name: req_write_escape_http * Description: Buffers and "escapes" data before sending to client. *  as above, but translates as it copies, into a form suitably *  encoded for URLs in HTTP headers. * Returns: -1 for error, otherwise how much is stored */int req_write_escape_http(request * req, char *msg){    char c, *inp, *dest;    int left;    inp = msg;    dest = req->buffer + req->buffer_end;    /* 3 is a guard band, since we don't check the destination pointer     * in the middle of a transfer of up to 3 bytes */    left = BUFFER_SIZE - req->buffer_end - 3;    while ((c = *inp++) && left > 0) {        if (needs_escape((unsigned int) c)) {            *dest++ = '%';            *dest++ = INT_TO_HEX(c >> 4);            *dest++ = INT_TO_HEX(c & 15);            left -= 3;        } else {            *dest++ = c;            left--;        }    }    req->buffer_end = dest - req->buffer;    if (left == 0) {        log_error_time();        fprintf(stderr, "Ran out of Buffer space!\n");        req->status = DEAD;        return -1;    }    return req->buffer_end;}/* * Name: req_write_escape_html * Description: Buffers and "escapes" data before sending to client. *  as above, but translates as it copies, into a form suitably *  encoded for HTML bodies. * Returns: -1 for error, otherwise how much is stored */int req_write_escape_html(request * req, char *msg){    char c, *inp, *dest;    int left;    inp = msg;    dest = req->buffer + req->buffer_end;    /* 5 is a guard band, since we don't check the destination pointer     * in the middle of a transfer of up to 5 bytes */    left = BUFFER_SIZE - req->buffer_end - 5;    while ((c = *inp++) && left > 0) {        switch (c) {        case '>':            *dest++ = '&';            *dest++ = 'g';            *dest++ = 't';            *dest++ = ';';            left -= 4;            break;        case '<':            *dest++ = '&';            *dest++ = 'l';            *dest++ = 't';            *dest++ = ';';            left -= 4;            break;        case '&':            *dest++ = '&';            *dest++ = 'a';            *dest++ = 'm';            *dest++ = 'p';            *dest++ = ';';            left -= 5;            break;        case '\"':            *dest++ = '&';            *dest++ = 'q';            *dest++ = 'u';            *dest++ = 'o';            *dest++ = 't';            *dest++ = ';';            left -= 6;            break;        default:            *dest++ = c;            left--;        }    }    req->buffer_end = dest - req->buffer;    if (left == 0) {        log_error_time();        fprintf(stderr, "Ran out of Buffer space!\n");        req->status = DEAD;        return -1;    }    return req->buffer_end;}/* * Name: flush_req * * Description: Sends any backlogged buffer to client. * * Returns: -2 for error, -1 for blocked, otherwise how much is stored */int req_flush(request * req){    int bytes_to_write;    bytes_to_write = req->buffer_end - req->buffer_start;    if (req->status == DEAD)        return -2;    if (bytes_to_write) {        int bytes_written;        bytes_written = write(req->fd, req->buffer + req->buffer_start,                              bytes_to_write);        if (bytes_written < 0) {            if (errno == EWOULDBLOCK || errno == EAGAIN)                return -1;      /* request blocked at the pipe level, but keep going */            else {                req->buffer_start = req->buffer_end = 0;                if (errno != EPIPE)                    perror("buffer flush"); /* OK to disable if your logs get too big */                req->status = DEAD;                req->buffer_end = 0;                return -2;            }        }#ifdef FASCIST_LOGGING        log_error_time();        fprintf(stderr, "%s:%d - Wrote \"", __FILE__, __LINE__);        fwrite(req->buffer + req->buffer_start, sizeof (char),               bytes_written, stderr);        fprintf(stderr, "\" (%d bytes)\n", bytes_written);#endif        req->buffer_start += bytes_written;    }    if (req->buffer_start == req->buffer_end)        req->buffer_start = req->buffer_end = 0;    return req->buffer_end;     /* successful */}/* * Name: escape_string * * Description: escapes the string inp.  Uses variable buf.  If buf is *  NULL when the program starts, it will attempt to dynamically allocate *  the space that it needs, otherwise it will assume that the user *  has already allocated enough space for the variable buf, which *  could be up to 3 times the size of inp.  If the routine dynamically *  allocates the space, the user is responsible for freeing it afterwords * Returns: NULL on error, pointer to string otherwise. * Note: this function doesn't really belong here, I plopped it here to *  work around a "bug" in escape.h (it defines a global, so can't be *  used in multiple source files).  Actually, this routine shouldn't  *  exist anywhere, it's only usage is in get.c's handling of on-the-fly *  directory generation, which would be better configured to use a combination *  of req_write_escape_http and req_write_escape_html.  That would involve *  more work than I'm willing to put in right now, though, so here we are. */char *escape_string(char *inp, char *buf){    int max;    char *index;    unsigned char c;    max = strlen(inp) * 3;    if (buf == NULL && max)        buf = malloc(sizeof (char) * max + 1);    if (buf == NULL) {        log_error_time();        perror("malloc");        return NULL;    }    index = buf;    while ((c = *inp++) && max > 0) {        if (needs_escape((unsigned int) c)) {            *index++ = '%';            *index++ = INT_TO_HEX(c >> 4);            *index++ = INT_TO_HEX(c & 15);        } else            *index++ = c;    }    *index = '\0';    return buf;}

⌨️ 快捷键说明

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