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

📄 libhttpd.c

📁 修改后的thttp
💻 C
📖 第 1 页 / 共 5 页
字号:
    restlen = strlen( path );    realloc_str( &rest, &maxrest, restlen );    (void) strcpy( rest, path );    if ( rest[restlen - 1] == '/' )	rest[--restlen] = '\0';		/* trim trailing slash */    /* Remove any leading slashes. */    while ( rest[0] == '/' )	{	(void) strcpy( rest, &(rest[1]) );	--restlen;	}    r = rest;    nlinks = 0;    /* While there are still components to check... */    while ( restlen > 0 )	{	/* Save current checkedlen in case we get a symlink.  Save current	** restlen in case we get a non-existant component.	*/	prevcheckedlen = checkedlen;	prevrestlen = restlen;	/* Grab one component from r and transfer it to checked. */	cp1 = strchr( r, '/' );	if ( cp1 != (char*) 0 )	    {	    i = cp1 - r;	    if ( i == 0 )		{		/* Special case for absolute paths. */		realloc_str( &checked, &maxchecked, checkedlen + 1 );		(void) strncpy( &checked[checkedlen], r, 1 );		checkedlen += 1;		}	    else if ( strncmp( r, "..", MAX( i, 2 ) ) == 0 )		{		/* Ignore ..'s that go above the start of the path. */		if ( checkedlen != 0 )		    {		    cp2 = strrchr( checked, '/' );		    if ( cp2 == (char*) 0 )			checkedlen = 0;		    else if ( cp2 == checked )			checkedlen = 1;		    else			checkedlen = cp2 - checked;		    }		}	    else		{		realloc_str( &checked, &maxchecked, checkedlen + 1 + i );		if ( checkedlen > 0 && checked[checkedlen-1] != '/' )		    checked[checkedlen++] = '/';		(void) strncpy( &checked[checkedlen], r, i );		checkedlen += i;		}	    checked[checkedlen] = '\0';	    r += i + 1;	    restlen -= i + 1;	    }	else	    {	    /* No slashes remaining, r is all one component. */	    if ( strcmp( r, ".." ) == 0 )		{		/* Ignore ..'s that go above the start of the path. */		if ( checkedlen != 0 )		    {		    cp2 = strrchr( checked, '/' );		    if ( cp2 == (char*) 0 )			checkedlen = 0;		    else if ( cp2 == checked )			checkedlen = 1;		    else			checkedlen = cp2 - checked;		    checked[checkedlen] = '\0';		    }		}	    else		{		realloc_str( &checked, &maxchecked, checkedlen + 1 + restlen );		if ( checkedlen > 0 && checked[checkedlen-1] != '/' )		    checked[checkedlen++] = '/';		(void) strcpy( &checked[checkedlen], r );		checkedlen += restlen;		}	    r += restlen;	    restlen = 0;	    }	/* Try reading the current filename as a symlink */	linklen = readlink( checked, link, sizeof(link) );	if ( linklen == -1 )	    {	    if ( errno == EINVAL )		continue;		/* not a symlink */	    if ( errno == EACCES || errno == ENOENT || errno == ENOTDIR || errno == EBADF )		{		/* That last component was bogus.  Restore and return. */		*restP = r - ( prevrestlen - restlen );		if ( prevcheckedlen == 0 )		    (void) strcpy( checked, "." );		else		    checked[prevcheckedlen] = '\0';		return checked;		}	    syslog( LOG_ERR, "readlink %s - (%d) %m", checked, errno );	    return (char*) 0;	    }	++nlinks;	if ( nlinks > MAX_LINKS )	    {	    syslog( LOG_ERR, "too many symlinks in %.80s", path );	    return (char*) 0;	    }	link[linklen] = '\0';	if ( link[linklen - 1] == '/' )	    link[--linklen] = '\0';	/* trim trailing slash */	/* Insert the link contents in front of the rest of the filename. */	if ( restlen != 0 )	    {	    (void) strcpy( rest, r );	    realloc_str( &rest, &maxrest, restlen + linklen + 1 );	    for ( i = restlen; i >= 0; --i )		rest[i + linklen + 1] = rest[i];	    (void) strcpy( rest, link );	    rest[linklen] = '/';	    restlen += linklen + 1;	    r = rest;	    }	else	    {	    /* There's nothing left in the filename, so the link contents	    ** becomes the rest.	    */	    realloc_str( &rest, &maxrest, linklen );	    (void) strcpy( rest, link );	    restlen = linklen;	    r = rest;	    }	/* Re-check this component. */	checkedlen = prevcheckedlen;	checked[checkedlen] = '\0';	}    /* Ok. */    *restP = r;    if ( checked[0] == '\0' )	(void) strcpy( checked, "." );    return checked;    }inthttpd_get_conn( httpd_server* hs, httpd_conn* hc )    {    struct sockaddr_in sin;    int sz;    if ( ! hc->initialized )	{	hc->maxdecodedurl =	    hc->maxorigfilename = hc->maxexpnfilename = hc->maxencodings =	    hc->maxpathinfo = hc->maxquery = hc->maxaltdir =	    hc->maxaccept = hc->maxaccepte = hc->maxreqhost =	    hc->maxremoteuser = hc->maxresponse = 0;	realloc_str( &hc->decodedurl, &hc->maxdecodedurl, 1 );	realloc_str( &hc->origfilename, &hc->maxorigfilename, 1 );	realloc_str( &hc->expnfilename, &hc->maxexpnfilename, 0 );	realloc_str( &hc->encodings, &hc->maxencodings, 0 );	realloc_str( &hc->pathinfo, &hc->maxpathinfo, 0 );	realloc_str( &hc->query, &hc->maxquery, 0 );	realloc_str( &hc->altdir, &hc->maxaltdir, 0 );	realloc_str( &hc->accept, &hc->maxaccept, 0 );	realloc_str( &hc->accepte, &hc->maxaccepte, 0 );	realloc_str( &hc->reqhost, &hc->maxreqhost, 0 );	realloc_str( &hc->remoteuser, &hc->maxremoteuser, 0 );	realloc_str( &hc->response, &hc->maxresponse, 0 );	hc->initialized = 1;	}    /* Accept the new connection. */    sz = sizeof(sin);    hc->conn_fd = accept( hs->listen_fd, (struct sockaddr*) &sin, &sz );    if ( hc->conn_fd < 0 )	{	if ( errno == EWOULDBLOCK )	    return GC_NO_MORE;	syslog( LOG_ERR, "accept - %m" );	return GC_FAIL;	}    (void) fcntl( hc->conn_fd, F_SETFD, 1 );    hc->hs = hs;    hc->client_addr = sin.sin_addr;    hc->read_idx = 0;    hc->checked_idx = 0;    hc->checked_state = CHST_FIRSTWORD;    hc->protocol = "HTTP/1.0";    hc->mime_flag = 1;    hc->should_linger = 0;    hc->file_address = (char*) 0;    return GC_OK;    }/* Checks hc->read_buf to see whether a complete request has been read so far;** either the first line has two words (an HTTP/0.9 request), or the first** line has three words and there's a blank line present.**** hc->read_idx is how much has been read in; hc->checked_idx is how much we** have checked so far; and hc->checked_state is the current state of the** finite state machine.*/inthttpd_got_request( httpd_conn* hc )    {    char c;    for ( ; hc->checked_idx < hc->read_idx; ++hc->checked_idx )	{	c = hc->read_buf[hc->checked_idx];	switch ( hc->checked_state )	    {	    case CHST_FIRSTWORD:	    switch ( c )		{		case ' ': case '\t':		hc->checked_state = CHST_FIRSTWS;		break;		case '\n': case '\r':		hc->checked_state = CHST_BOGUS;		return GR_BAD_REQUEST;		}	    break;	    case CHST_FIRSTWS:	    switch ( c )		{		case ' ': case '\t':		break;		case '\n': case '\r':		hc->checked_state = CHST_BOGUS;		return GR_BAD_REQUEST;		default:		hc->checked_state = CHST_SECONDWORD;		break;		}	    break;	    case CHST_SECONDWORD:	    switch ( c )		{		case ' ': case '\t':		hc->checked_state = CHST_SECONDWS;		break;		case '\n': case '\r':		/* The first line has only two words - an HTTP/0.9 request. */		return GR_GOT_REQUEST;		}	    break;	    case CHST_SECONDWS:	    switch ( c )		{		case ' ': case '\t':		break;		case '\n': case '\r':		hc->checked_state = CHST_BOGUS;		return GR_BAD_REQUEST;		default:		hc->checked_state = CHST_THIRDWORD;		break;		}	    break;	    case CHST_THIRDWORD:	    switch ( c )		{		case ' ': case '\t':		hc->checked_state = CHST_BOGUS;		return GR_BAD_REQUEST;		case '\n':		hc->checked_state = CHST_LF;		break;		case '\r':		hc->checked_state = CHST_CR;		break;		}	    break;	    case CHST_LINE:	    switch ( c )		{		case '\n':		hc->checked_state = CHST_LF;		break;		case '\r':		hc->checked_state = CHST_CR;		break;		}	    break;	    case CHST_LF:	    switch ( c )		{		case '\n':		/* Two newlines in a row - a blank line - end of request. */		return GR_GOT_REQUEST;		case '\r':		hc->checked_state = CHST_CR;		break;		default:		hc->checked_state = CHST_LINE;		break;		}	    break;	    case CHST_CR:	    switch ( c )		{		case '\n':		hc->checked_state = CHST_CRLF;		break;		case '\r':		/* Two returns in a row - end of request. */		return GR_GOT_REQUEST;		default:		hc->checked_state = CHST_LINE;		break;		}	    break;	    case CHST_CRLF:	    switch ( c )		{		case '\n':		/* Two newlines in a row - end of request. */		return GR_GOT_REQUEST;		case '\r':		hc->checked_state = CHST_CRLFCR;		break;		default:		hc->checked_state = CHST_LINE;		break;		}	    break;	    case CHST_CRLFCR:	    switch ( c )		{		case '\n': case '\r':		/* Two CRLFs or two CRs in a row - end of request. */		return GR_GOT_REQUEST;		default:		hc->checked_state = CHST_LINE;		break;		}	    break;	    case CHST_BOGUS:	    return GR_BAD_REQUEST;	    }	}    return GR_NO_REQUEST;    }inthttpd_parse_request( httpd_conn* hc )    {    char* buf;    char* method_str;    char* url;    char* protocol;    char* reqhost;    char* eol;    char* cp;    char* pi;    hc->checked_idx = 0;    hc->mime_flag = 0;    hc->one_one = 0;    method_str = bufgets( hc );    url = strpbrk( method_str, " \t\n\r" );    if ( url == (char*) 0 )	{	httpd_send_err( hc, 400, httpd_err400title, httpd_err400form, "" );	return -1;	}    *url++ = '\0';    url += strspn( url, " \t\n\r" );    protocol = strpbrk( url, " \t\n\r" );    if ( protocol == (char*) 0 )	protocol = "HTTP/0.9";    else	{	*protocol++ = '\0';	protocol += strspn( protocol, " \t\n\r" );	if ( *protocol != '\0' )	    {	    hc->mime_flag = 1;	    eol = strpbrk( protocol, " \t\n\r" );	    if ( eol != (char*) 0 )		*eol = '\0';	    if ( strcasecmp( protocol, "HTTP/1.0" ) != 0 )		hc->one_one = 1;	    }	}    /* Check for HTTP/1.1 absolute URL. */    if ( strncasecmp( url, "http://", 7 ) == 0 )	{	if ( ! hc->one_one )	    {	    httpd_send_err( hc, 400, httpd_err400title, httpd_err400form, "" );	    return -1;	    }	reqhost = url + 7;	url = strchr( reqhost, '/' );	if ( url == (char*) 0 )	    {	    httpd_send_err( hc, 400, httpd_err400title, httpd_err400form, "" );	    return -1;	    }	*url = '\0';	realloc_str( &hc->reqhost, &hc->maxreqhost, strlen( reqhost ) );	(void) strcpy( hc->reqhost, reqhost );	*url = '/';	}    else	hc->reqhost[0] = '\0';    if ( strcasecmp( method_str, httpd_method_str( METHOD_GET ) ) == 0 )	hc->method = METHOD_GET;    else if ( strcasecmp( method_str, httpd_method_str( METHOD_HEAD ) ) == 0 )	hc->method = METHOD_HEAD;    else if ( strcasecmp( method_str, httpd_method_str( METHOD_POST ) ) == 0 )	hc->method = METHOD_POST;    else	{	httpd_send_err( hc, 501, err501title, err501form, method_str );	return -1;	}    hc->encodedurl = url;    realloc_str(	&hc->decodedurl, &hc->maxdecodedurl, strlen( hc->encodedurl ) );    strdecode( hc->decodedurl, hc->encodedurl );    hc->protocol = protocol;    if ( hc->decodedurl[0] != '/' )	{	httpd_send_err( hc, 400, httpd_err400title, httpd_err400form, "" );	return -1;	}    realloc_str(	&hc->origfilename, &hc->maxorigfilename, strlen( hc->decodedurl ) );    (void) strcpy( hc->origfilename, &hc->decodedurl[1] );    /* Special case for top-level URL. */    if ( hc->origfilename[0] == '\0' )	(void) strcpy( hc->origfilename, "." );    /* Extract query string from encoded URL. */    hc->query[0] = '\0';    cp = strchr( hc->encodedurl, '?' );    if ( cp != (char*) 0 )	{	++cp;	realloc_str( &hc->query, &hc->maxquery, strlen( cp ) );	(void) strcpy( hc->query, cp );	}    /* And remove query from filename. */    cp = strchr( hc->origfilename, '?' );    if ( cp != (char*) 0 )	*cp = '\0';    /* Copy original filename to expanded filename. */    realloc_str(	&hc->expnfilename, &hc->maxexpnfilename, strlen( hc->origfilename ) );    (void) strcpy( hc->expnfilename, hc->origfilename );    /* Tilde mapping. */    hc->altdir[0] = '\0';    if ( hc->expnfilename[0] == '~' )	{	if ( ! tilde_map( hc ) )	    {	    httpd_send_err( hc, 500, err500title, err500form, hc->encodedurl );	    return -1;	    }	}    /* Expand all symbolic links in the filename.  This also gives us    ** any trailing non-existing components, for pathinfo.    */    cp = expand_symlinks( hc->expnfilename, &pi, hc->hs->chrooted );    if ( cp == (char*) 0 )	{	httpd_send_err( hc, 500, err500title, err500form, hc->encodedurl );

⌨️ 快捷键说明

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