📄 request.c
字号:
/*! \file request.c Based on webfs Copyright (C) 1999-2001 Gerd Knorr 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 2 of the License, 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 with the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Description: http request handling $Id: request.c,v 1.1.1.1 2004/12/23 05:52:34 s_zander Exp $*/#include "config.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <syslog.h>#include <time.h>#include <ctype.h>#include <pwd.h>#include <sys/time.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include "httpd.h"/* ---------------------------------------------------------------------- */int read_header(struct REQUEST *req, int pipelined){ int rc; char *h; restart: #ifdef USE_SSL if (with_ssl) { rc = ssl_read(req, req->hreq + req->hdata, MAX_HEADER - req->hdata); } else #endif { rc = read(req->fd, req->hreq + req->hdata, MAX_HEADER - req->hdata); } switch (rc) { case -1: if (errno == EAGAIN) { if (pipelined) { break; /* check if there is already a full request */ } else { return rc; } } if (errno == EINTR) { goto restart; } log_error_func(1,LOG_INFO,"read",req->peerhost); /* fall through */ case 0: req->state = STATE_CLOSE; return rc; default: req->hdata += rc; req->hreq[req->hdata] = 0; } /* check if this looks like a http request after the first few bytes... */ if (strncmp(req->hreq,"GET ",4) != 0 && strncmp(req->hreq,"PUT ",4) != 0 && strncmp(req->hreq,"HEAD ",5) != 0 && strncmp(req->hreq,"POST ",5) != 0) { mkerror(req,400,0); return -1; } /* header complete ?? */ if (NULL != (h = strstr(req->hreq,"\r\n\r\n")) || NULL != (h = strstr(req->hreq,"\n\n"))) { if (*h == '\r') { h += 4; *(h-2) = 0; } else { h += 2; *(h-1) = 0; } /* header length */ req->lreq = h - req->hreq; req->state = STATE_PARSE_HEADER; /* pointer to body */ req->breq = h; /* first part of body */ req->lbreq = req->hdata - req->lreq; return 0; } if (req->hdata == MAX_REQ) { /* oops: buffer full, but found no complete request ... */ mkerror(req,400,0); return -1; } return rc;}int read_body(struct REQUEST *req, int pipelined){ int rc; restart:#ifdef USE_SSL if (with_ssl) { rc = ssl_read(req, req->hreq + req->hdata, MAX_REQ - req->hdata); } else #endif { rc = read(req->fd, req->hreq + req->hdata, MAX_REQ - req->hdata); } switch (rc) { case -1: if (errno == EAGAIN) { if (pipelined) { break; /* check if there is already a full request */ } else { return rc; } } if (errno == EINTR) { goto restart; } log_error_func(1,LOG_INFO,"read",req->peerhost); /* fall through */ case 0: req->state = STATE_CLOSE; return rc; default: req->hdata += rc; req->hreq[req->hdata] = 0; } /* body complete */ if ((req->hdata - req->lreq) == req->clen) { req->state = STATE_PARSE_BODY; req->breq[req->clen] = 0; req->lbreq = req->clen; return 0; } if (req->hdata == MAX_REQ) { /* oops: buffer full, but found no complete request ... */ mkerror(req,400,0); return -1; } return rc;}/* ---------------------------------------------------------------------- */static time_t parse_date(char *line){ static char *m[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; char month[3]; struct tm tm; int i; memset(&tm, 0, sizeof(tm)); line = strchr(line,' '); /* skip weekday */ if (NULL == line) { return -1; } line++; /* first: RFC 1123 date ... */ if (6 != sscanf(line,"%2d %3s %4d %2d:%2d:%2d GMT", &tm.tm_mday,month,&tm.tm_year, &tm.tm_hour,&tm.tm_min,&tm.tm_sec)) { /* second: RFC 1036 date ... */ if (6 != sscanf(line,"%2d-%3s-%2d %2d:%2d:%2d GMT", &tm.tm_mday,month,&tm.tm_year, &tm.tm_hour,&tm.tm_min,&tm.tm_sec)) { /* third: asctime() format */ if (6 != sscanf(line,"%3s %2d %2d:%2d:%2d %4d", month,&tm.tm_mday, &tm.tm_hour,&tm.tm_min,&tm.tm_sec, &tm.tm_year)) { /* none worked :-( */ return -1; } } } for (i = 0; i <= 11; i++) { if (0 == strcmp(month,m[i])) { break; } } tm.tm_mon = i; if (tm.tm_year > 1900) { tm.tm_year -= 1900; } return mktime(&tm);}static off_t parse_off_t(char *str, int *pos){ off_t value = 0; while (isdigit((int)str[*pos])) { value *= 10; value += str[*pos] - '0'; (*pos)++; } return value;}static int parse_ranges(struct REQUEST *req){ char *h,*line = req->range_hdr; int i,off; if (req->if_range > 0 && req->if_range != req->bst.st_mtime) { return 0; } for (h = line, req->ranges=1; *h != '\n' && *h != '\0'; h++) { if (*h == ',') { req->ranges++; } }#ifdef DEBUG fprintf(stderr,"%03d/%d: %d ranges:",req->fd,req->state,req->ranges);#endif req->r_start = malloc(req->ranges*sizeof(off_t)); req->r_end = malloc(req->ranges*sizeof(off_t)); req->r_head = malloc((req->ranges+1)*BR_HEADER); req->r_hlen = malloc((req->ranges+1)*sizeof(int)); if (NULL == req->r_start || NULL == req->r_end || NULL == req->r_head || NULL == req->r_hlen) { if (req->r_start) free(req->r_start); if (req->r_end) free(req->r_end); if (req->r_head) free(req->r_head); if (req->r_hlen) free(req->r_hlen);#ifdef DEBUG fprintf(stderr,"oom\n");#endif return 500; } for (i = 0, off=0; i < req->ranges; i++) { if (line[off] == '-') { off++; if (!isdigit((int)line[off])) { goto parse_error; } req->r_start[i] = req->bst.st_size - parse_off_t(line,&off); req->r_end[i] = req->bst.st_size; } else { if (!isdigit((int)line[off])) { goto parse_error; } req->r_start[i] = parse_off_t(line,&off); if (line[off] != '-') { goto parse_error; } off++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -