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

📄 libhttpd.c.bak

📁 修改后的thttp
💻 BAK
📖 第 1 页 / 共 5 页
字号:
/* libhttpd.c - HTTP protocol library**** Copyright (C)1995,1998 by Jef Poskanzer <jef@acme.com>. All rights reserved.**** Redistribution and use in source and binary forms, with or without** modification, are permitted provided that the following conditions** are met:** 1. Redistributions of source code must retain the above copyright**    notice, this list of conditions and the following disclaimer.** 2. Redistributions in binary form must reproduce the above copyright**    notice, this list of conditions and the following disclaimer in the**    documentation and/or other materials provided with the distribution.** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF** SUCH DAMAGE.*/#include "config.h"#include "version.h"#include <sys/types.h>#include <sys/param.h>#include <sys/wait.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/resource.h>#include <ctype.h>#include <errno.h>#include <fcntl.h>#ifdef HAVE_MEMORY_H#include <memory.h>#endif#include <pwd.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <syslog.h>#include <unistd.h>#ifdef HAVE_DIRENT_H# include <dirent.h># define NAMLEN(dirent) strlen((dirent)->d_name)#else# define dirent direct# define NAMLEN(dirent) (dirent)->d_namlen# ifdef HAVE_SYS_NDIR_H#  include <sys/ndir.h># endif# ifdef HAVE_SYS_DIR_H#  include <sys/dir.h># endif# ifdef HAVE_NDIR_H#  include <ndir.h># endif#endifextern char* crypt( const char* key, const char* setting );#include "libhttpd.h"#include "mmc.h"#include "timers.h"#include "match.h"#include "tdate_parse.h"#ifndef STDIN_FILENO#define STDIN_FILENO 0#endif#ifndef STDOUT_FILENO#define STDOUT_FILENO 1#endif#ifndef STDERR_FILENO#define STDERR_FILENO 2#endif#ifndef max#define max(a,b) ((a) > (b) ? (a) : (b))#endif#ifndef min#define min(a,b) ((a) < (b) ? (a) : (b))#endifstatic const char* rfc1123fmt = "%a, %d %b %Y %H:%M:%S GMT";static const char* cernfmt = "%d/%b/%Y:%H:%M:%S %Z";/* Forwards. */static void child_reaper( ClientData client_data, struct timeval* nowP );static int do_reap( void );static void check_options( void );static void free_httpd_server( httpd_server* hs );static void add_response( httpd_conn* hc, char* str );static void send_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, int length, time_t mod );static void realloc_str( char** strP, int* maxsizeP, int size );static void send_response( httpd_conn* hc, int status, char* title, char* extrahead, char* form, char* arg );#ifdef AUTH_FILEstatic void send_authenticate( httpd_conn* hc, char* realm );static int b64_decode( const char* str, unsigned char* space, int size );static int auth_check( httpd_conn* hc, char* dirname  );#endif /* AUTH_FILE */static void send_dirredirect( httpd_conn* hc );static int is_hexit( char c );static int hexit( char c );static void strdecode( char* to, char* from );static int tilde_map( httpd_conn* hc );static char* expand_symlinks( char* path, char** restP, int chrooted );static char* bufgets( httpd_conn* hc );static void figure_mime( httpd_conn* hc );static void cgi_kill2( ClientData client_data, struct timeval* nowP );static void cgi_kill( ClientData client_data, struct timeval* nowP );#ifdef GENERATE_INDEXESstatic off_t ls( httpd_conn* hc );#endif /* GENERATE_INDEXES */static char* build_env( char* fmt, char* arg );#ifdef SERVER_NAME_LISTstatic char* hostname_map( char* hostname );#endif /* SERVER_NAME_LIST */static char** make_envp( httpd_conn* hc );static char** make_argp( httpd_conn* hc );static void cgi_interpose( httpd_conn* hc, int wfd );static void cgi_child( httpd_conn* hc );static off_t cgi( httpd_conn* hc );static int really_start_request( httpd_conn* hc );static int reap_time;static voidchild_reaper( ClientData client_data, struct timeval* nowP )    {    int child_count;    static int prev_child_count = 0;    child_count = do_reap();    /* Reschedule reaping, with adaptively changed time. */    if ( child_count > prev_child_count * 3 / 2 )	reap_time = max( reap_time / 2, MIN_REAP_TIME );    else if ( child_count < prev_child_count * 2 / 3 )	reap_time = min( reap_time * 5 / 4, MAX_REAP_TIME );    (void) tmr_create(	nowP, child_reaper, (ClientData) 0, reap_time * 1000L, 0 );    }static intdo_reap( void )    {    int child_count;    pid_t pid;    int status;    /* Reap defunct children until there aren't any more. */    for ( child_count = 0; ; ++child_count )	{#ifdef HAVE_WAITPID	pid = waitpid( (pid_t) -1, &status, WNOHANG );#else /* HAVE_WAITPID */	pid = wait3( &status, WNOHANG, (struct rusage*) 0 );#endif /* HAVE_WAITPID */	if ( (int) pid == 0 )		/* none left */	    break;	if ( (int) pid < 0 )	    {	    if ( errno == EINTR )	/* because of ptrace */		continue;	    /* ECHILD shouldn't happen with the WNOHANG option, but with	    ** some kernels it does anyway.  Ignore it.	    */	    if ( errno != ECHILD )		syslog( LOG_ERR, "waitpid - %m" );	    break;	    }	}    return child_count;    }static voidcheck_options( void )    {#if defined(TILDE_MAP_1) && defined(TILDE_MAP_2)    syslog( LOG_CRIT, "both TILDE_MAP_1 and TILDE_MAP_2 are defined" );    exit( 1 );#endif /* both */    }static voidfree_httpd_server( httpd_server* hs )    {    if ( hs->cwd != (char*) 0 )	free( (void*) hs->cwd );    if ( hs->cgi_pattern != (char*) 0 )	free( (void*) hs->cgi_pattern );    free( (void*) hs );    }httpd_server*httpd_initialize(    char* hostname, u_int addr, int port, char* cgi_pattern, char* cwd,    FILE* logfp, int chrooted )    {    httpd_server* hs;    int on;    struct sockaddr_in sa;    char* cp;    check_options();    /* Set up child-process reaper. */    reap_time = min( MIN_REAP_TIME * 4, MAX_REAP_TIME );    (void) tmr_create(	(struct timeval*) 0, child_reaper, (ClientData) 0, reap_time * 1000L,	0 );    hs = NEW( httpd_server, 1 );    if ( hs == (httpd_server*) 0 )	{	syslog( LOG_CRIT, "out of memory" );	return (httpd_server*) 0;	}    if ( hostname == (char*) 0 )	hs->hostname = (char*) 0;    else	hs->hostname = strdup( hostname );    hs->port = port;    if ( cgi_pattern == (char*) 0 )	hs->cgi_pattern = (char*) 0;    else	{	/* Nuke any leading slashes. */	if ( cgi_pattern[0] == '/' )	    ++cgi_pattern;	hs->cgi_pattern = strdup( cgi_pattern );	if ( hs->cgi_pattern == (char*) 0 )	    {	    syslog( LOG_CRIT, "out of memory" );	    return (httpd_server*) 0;	    }	/* Nuke any leading slashes in the cgi pattern. */	while ( ( cp = strstr( hs->cgi_pattern, "|/" ) ) != (char*) 0 )	    (void) strcpy( cp + 1, cp + 2 );	}    hs->cwd = strdup( cwd );    if ( hs->cwd == (char*) 0 )	{	syslog( LOG_CRIT, "out of memory" );	return (httpd_server*) 0;	}    hs->logfp = logfp;    hs->chrooted = chrooted;    /* Create socket. */    hs->listen_fd = socket( AF_INET, SOCK_STREAM, 0 );    if ( hs->listen_fd < 0 )	{	syslog( LOG_CRIT, "socket - %m" );	free_httpd_server( hs );	return (httpd_server*) 0;	}    (void) fcntl( hs->listen_fd, F_SETFD, 1 );    /* Allow reuse of local addresses. */    on = 1;    if ( setsockopt(	     hs->listen_fd, SOL_SOCKET, SO_REUSEADDR, (char*) &on,	     sizeof(on) ) < 0 )        syslog( LOG_CRIT, "setsockopt SO_REUSEADDR - %m" );    /* Bind to it. */    memset( (char*) &sa, 0, sizeof(sa) );    sa.sin_family = AF_INET;    sa.sin_addr.s_addr = addr;    sa.sin_port = htons( hs->port );    hs->host_addr = sa.sin_addr;    if ( bind( hs->listen_fd, (struct sockaddr*) &sa, sizeof(sa) ) < 0 )	{	syslog( LOG_CRIT, "bind %.80s - %m", inet_ntoa( sa.sin_addr ) );	(void) close( hs->listen_fd );	free_httpd_server( hs );	return (httpd_server*) 0;	}    /* Set the listen file descriptor to no-delay mode. */    if ( fcntl( hs->listen_fd, F_SETFL, O_NDELAY ) < 0 )	{	syslog( LOG_CRIT, "fcntl O_NDELAY - %m" );	(void) close( hs->listen_fd );	free_httpd_server( hs );	return (httpd_server*) 0;	}    /* Start a listen going. */    if ( listen( hs->listen_fd, LISTEN_BACKLOG ) < 0 )	{	syslog( LOG_CRIT, "listen - %m" );	(void) close( hs->listen_fd );	free_httpd_server( hs );	return (httpd_server*) 0;	}    /* Done initializing. */    if ( hs->hostname == (char*) 0 )	syslog( LOG_INFO, "%s starting on port %d", SERVER_SOFTWARE, hs->port );    else	syslog(	    LOG_INFO, "%s starting on %.80s, port %d", SERVER_SOFTWARE,	    inet_ntoa( hs->host_addr ), hs->port );    return hs;    }voidhttpd_terminate( httpd_server* hs )    {    (void) close( hs->listen_fd );    if ( hs->logfp != (FILE*) 0 )	(void) fclose( hs->logfp );    free_httpd_server( hs );    }static char* ok200title = "OK";static char* ok206title = "Partial Content";static char* err302title = "Found";static char* err302form = "The actual URL is '%.80s'.\n";static char* err304title = "Not Modified";char* httpd_err400title = "Bad Request";char* httpd_err400form =    "Your request has bad syntax or is inherently impossible to satisfy.\n";#ifdef AUTH_FILEstatic char* err401title = "Unauthorized";static char* err401form =    "Authorization required for the URL '%.80s'.\n";#endif /* AUTH_FILE */static char* err403title = "Forbidden";static char* err403form =    "You do not have permission to get URL '%.80s' from this server.\n";static char* err404title = "Not Found";static char* err404form =    "The requested URL '%.80s' was not found on this server.\n";char* httpd_err408title = "Request Timeout";char* httpd_err408form =    "No request appeared within a reasonable time period.\n";static char* err500title = "Internal Error";static char* err500form =    "There was an unusual problem serving the requested URL '%.80s'.\n";static char* err501title = "Not Implemented";static char* err501form =    "The requested method '%.80s' is not implemented by this server.\n";char* httpd_err503title = "Service Temporarily Overloaded";char* httpd_err503form =    "The requested URL '%.80s' is temporarily overloaded.  Please try again later.\n";/* Append a string to the buffer waiting to be sent as response. */static voidadd_response( httpd_conn* hc, char* str )    {    int len;    len = strlen( str );    realloc_str( &hc->response, &hc->maxresponse, hc->responselen + len );    (void) memcpy( &(hc->response[hc->responselen]), str, len );    hc->responselen += len;    }/* Send the buffered response. */voidhttpd_write_response( httpd_conn* hc )    {    if ( hc->responselen > 0 )	{	(void) write( hc->conn_fd, hc->response, hc->responselen );	hc->responselen = 0;	}    }static voidsend_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, int length, time_t mod )    {    time_t now;    char nowbuf[100];    char modbuf[100];    char buf[1000];    int partial_content;    hc->status = status;    hc->bytes = length;    if ( hc->mime_flag )	{	if ( status == 200 && hc->got_range &&	     ( hc->end_byte_loc >= hc->init_byte_loc ) &&	     ( ( hc->end_byte_loc != length - 1 ) ||	       ( hc->init_byte_loc != 0 ) ) &&	     ( hc->range_if == (time_t) -1 ||	       hc->range_if == hc->sb.st_mtime ) )	    {	    partial_content = 1;	    hc->status = status = 206;	    title = ok206title;	    }	else	    partial_content = 0;	now = time( (time_t*) 0 );	if ( mod == (time_t) 0 )	    mod = now;#ifdef EMBED	modbuf[0] = nowbuf[0] = 0;#else	(void) strftime( nowbuf, sizeof(nowbuf), rfc1123fmt, gmtime( &now ) );	(void) strftime( modbuf, sizeof(modbuf), rfc1123fmt, gmtime( &mod ) );#endif	(void) sprintf( buf,	    "%.20s %d %s\r\nServer: %s\r\nContent-type: %s\r\nDate: %s\r\nLast-modified: %s\r\nAccept-Ranges: bytes\r\nConnection: close\r\n",	    hc->protocol, status, title, SERVER_SOFTWARE, type, nowbuf,	    modbuf );	add_response( hc, buf );	if ( encodings[0] != '\0' )	    {	    (void) sprintf( buf, "Content-encoding: %s\r\n", encodings );	    add_response( hc, buf );	    }	if ( partial_content )	    {	    (void) sprintf(		buf, "Content-range: bytes %ld-%ld/%d\r\nContent-length: %ld\r\n",		(long) hc->init_byte_loc, (long) hc->end_byte_loc, length,		(long) ( hc->end_byte_loc - hc->init_byte_loc + 1 ) );	    add_response( hc, buf );	    }	else if ( length >= 0 )	    {	    (void) sprintf( buf, "Content-length: %d\r\n", length );	    add_response( hc, buf );	    }	if ( extraheads[0] != '\0' )	    add_response( hc, extraheads );	add_response( hc, "\r\n" );	}    }static voidrealloc_str( char** strP, int* maxsizeP, int size )    {    if ( *maxsizeP == 0 )	{	*maxsizeP = MAX( 200, size );	/* arbitrary */	*strP = NEW( char, *maxsizeP + 1 );	}    else if ( size > *maxsizeP )	{	*maxsizeP = MAX( *maxsizeP * 2, size * 5 / 4 );	*strP = RENEW( *strP, char, *maxsizeP + 1 );	}    else	return;    if ( *strP == (char*) 0 )	{	syslog( LOG_ERR, "out of memory" );	exit( 1 );	}    }static voidsend_response( httpd_conn* hc, int status, char* title, char* extrahead, char* form, char* arg )

⌨️ 快捷键说明

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