Esempio n. 1
0
static int ht_headers(struct channel *ch, struct buffer *bu, struct env *env)
{
	struct headers_state hs;
	char name_str[80];
	char value_str[2048];
	struct buffer name = buffer_wrap(name_str);
	struct buffer value = buffer_wrap(value_str);

	buffer_reset(&name);
	buffer_reset(&value);
	env_init(env);
	hs_init(&hs);
	while (!ch_fill(ch)) {
		if (headers_parse(bu, &hs, &name, &value, env)) {
			ch_close(ch);
			return -1;
		}
		if (hs.done)
			break;
	}
	return 0;
}
Esempio n. 2
0
File: file.c Progetto: jtsymon/cws
void run (int worker_id, int sock_fd, struct sockaddr addr, socklen_t addr_len) {
    
    headers_parse (sock_fd);
    if (headers_is_error (headers_get_state ()) || !headers_has_request()) {
        goto hangup;
    }
    
    char *name = get_request (1);
    char *strip = name;
    char response_buffer[255];
    while (*strip == '.' || *strip == '/') strip++;
    if (!*strip) {
        fprintf (stderr, "%s: No such file or directory\n", name);
        goto _404;
    }
    int len = strlen (strip);
    int file_fd;
    char *file = malloc (2 + len + 1);
    file[0] = '.';
    file[1] = '/';
    memcpy (file + 2, strip, len);
    file[len + 2] = 0;
    file_fd = open (file, O_RDONLY);
    free (file);

    struct stat info;
    if (file_fd == -1 || fstat (file_fd, &info)) {
        if (file_fd > 0) {
            close (file_fd);
        }
        file_fd = 0;
        perror (name);
        goto _404;
    }

    response_init (200);
    char content_length[25];
    sprintf (content_length, "%d", info.st_size);
    response_add ("Content-Length", content_length);
    if (write_headers (sock_fd)) {
        close (file_fd);
        goto _404;
    }
    len = read (file_fd, response_buffer, 255);
    while (len > 0) {
        if (write (sock_fd, response_buffer, len) < 0) {
            perror ("write");
            break;
        }
        len = read (file_fd, response_buffer, 255);
    }

    if (file_fd > 0) {
        close (file_fd);
    }
    goto hangup;

_404:
    response_init (404);
    write_headers (sock_fd);
    snprintf (response_buffer, 255, "File not found: '%s'\n", name);
    if (write (sock_fd, response_buffer, strlen (response_buffer)) < 0) {
        goto hangup;
    }
    goto hangup;

hangup:
    headers_cleanup ();
    hangup (sock_fd);
}
Esempio n. 3
0
connection_t* connection_create( website_t* website, int sockfd, char* raw, size_t size ) {
    connection_t* connection = connection_init();
    connection->website = website;
    connection->sockfd  = sockfd;

    char* ptr,* tmp,* start = raw, urlbuf[ sizeof( connection->request.full_url ) ];

    memcpy( &connection->ip, raw, sizeof( connection->ip ) );
    raw += sizeof( connection->ip );
    strncpy( connection->hostname, raw, sizeof( connection->hostname ) );
    raw += strlen( raw ) + 1;

    // type /////////////////////////////////
    if ( startswith( raw, HTTP_GET ) ) {
        connection->request.type = HTTP_GET_TYPE;
        raw += strlen( HTTP_GET );
    } else if ( startswith( raw, HTTP_POST ) ) {
        connection->request.type = HTTP_POST_TYPE;
        raw += strlen( HTTP_POST );
    } else goto fail;
    raw++; // skip over space
    ////////////////////////////////////////

    // url /////////////////////////////////
    if ( !( tmp = strstr( raw, HTTP_HDR_ENDL ) ) )
        goto fail;

    if ( !( ptr = strnstr( raw, "?", ( tmp - raw ) ) )
            && !( ptr = strnstr( raw, " ", ( tmp - raw ) ) ) )
        goto fail;

    url_decode( urlbuf, raw, ptr - raw );
    normalize_path( connection->request.full_url, urlbuf );

    while ( startswith( connection->request.full_url, "../" ) ) {
        strcpy( urlbuf, connection->request.full_url + 3 );
        strcpy( connection->request.full_url, urlbuf );
    }

    // Skip over websites leading url.
    // if website is "example.com/test/" and url is "/test/hi" "/test" gets removed
    connection->request.url = strchr( connection->website->url, '/' );
    if ( connection->request.url )
        connection->request.url = &connection->request.full_url[
                                      ( connection->website->url + strlen( connection->website->url ) ) - connection->request.url ];
    else
        connection->request.url = connection->request.full_url;

    if ( *connection->request.url == '/' )
        connection->request.url++;
    ////////////////////////////////////////

    // parse qstring params ////////////////
    tmp = strstr( raw, HTTP_HDR_ENDL );
    if ( ptr[ 0 ] == '?' ) {
        raw = ptr + 1;
        if ( !( ptr = strnstr( raw, " ", tmp - raw ) ) )
            goto fail;
        params_parse_qs( &connection->request.params, raw, ptr - raw, PARAM_TYPE_GET );
    }

    raw = ptr + 1;
    ////////////////////////////////////////

    // version /////////////////////////////
    if ( !startswith( raw, "HTTP/" ) )
        goto fail;
    raw += 5; // skips "HTTP/"
    if ( !( ptr = strstr( raw, HTTP_HDR_ENDL ) ) )
        goto fail;
    strncpy( connection->http_version, raw, SMALLEST( ptr - raw, sizeof( connection->http_version ) - 1 ) );
    connection->http_version[ SMALLEST( ptr - raw, sizeof( connection->http_version ) - 1 ) ] = '\0';
    raw = ptr + strlen( HTTP_HDR_ENDL );
    ////////////////////////////////////////

    // headers /////////////////////////////
    connection->request.headers = headers_parse( raw );
    ////////////////////////////////////////

    // cookies /////////////////////////////
    header_t* header = headers_get_header( &connection->request.headers, "Cookie" );
    if ( header )
        connection->cookies = cookies_parse( header->value );
    else
        connection->cookies = cookies_parse( "" );
    ////////////////////////////////////////


    // body ////////////////////////////////
    if ( ( connection->request.type == HTTP_POST_TYPE )
            && ( ptr = strstr( raw, HTTP_HDR_ENDL HTTP_HDR_ENDL ) ) != NULL ) {
        ptr += strlen( HTTP_HDR_ENDL HTTP_HDR_ENDL );
        header_t* header = headers_get_header( &connection->request.headers, "Content-Type" );

        char boundary[HEADER_VALUE_MAX_LEN] = "",* boundary_ptr = NULL;

        if ( website_options_get( website, WS_OPTION_PARSE_MULTIPARTS )
                && header && startswith( headers_get_header_attr( header, NULL ), "multipart" )
                && ( boundary_ptr = headers_get_header_attr( header, "boundary" ) ) ) {
            printf("parsing multiparts: %d\n", website->options );
            strcat( boundary, "--" );
            strcat( boundary, boundary_ptr );
            int i = -1;

            if ( startswith( ptr, boundary ) ) {

                ptr += strlen( boundary ) + strlen( HTTP_HDR_ENDL );

                while ( ( boundary_ptr = strstr( ptr, boundary ) ) ) {

                    connection->request.parts[++i] = (request_t*) malloc( sizeof( request_t ) );
                    memset( connection->request.parts[i], 0, sizeof( request_t ) );
                    connection->request.parts[i]->headers = headers_parse( ptr );
                    connection->request.parts[i]->post_body = NULL;

                    if ( !( ptr = strstr( ptr, HTTP_HDR_ENDL HTTP_HDR_ENDL ) ) ) break;
                    ptr += sizeof( HTTP_HDR_ENDL HTTP_HDR_ENDL ) - 1;

                    connection->request.parts[i]->post_body_len = ( boundary_ptr - ptr ) - strlen( HTTP_HDR_ENDL );
                    connection->request.parts[i]->post_body = (char*) malloc( connection->request.parts[i]->post_body_len + 1 );
                    memset( connection->request.parts[i]->post_body, 0, connection->request.parts[i]->post_body_len + 1 );
                    strncpy(connection->request.parts[i]->post_body, ptr, connection->request.parts[i]->post_body_len );

                    char* charset;
                    header = headers_get_header( &connection->request.parts[i]->headers, "Content-Type" );
                    if ( header && ( charset = headers_get_header_attr( header, "charset" ) ) )
                        strcpy( connection->request.parts[i]->charset, charset );
                    else
                        // ISO-8859-1 is the default charset for http defined by RFC
                        strcpy( connection->request.parts[i]->charset, "ISO-8859-1" );

                    ptr = boundary_ptr + strlen( boundary );
                    if ( startswith( ptr, "--" HTTP_HDR_ENDL ) || i >= CONN_MAX_HTTP_MULTIPART ) break;
                    ptr += strlen( HTTP_HDR_ENDL );


                }

                if ( header && strcmp( headers_get_header_attr( header, NULL ), "multipart/form-data" ) == 0 )
                    params_parse_multiparts( &connection->request.params, connection->request.parts, PARAM_TYPE_POST );
            }
        } else {

            connection->request.post_body_len = size - (long) ( ptr - start );
            connection->request.post_body = (char*) malloc( connection->request.post_body_len + 1 );
            memset( connection->request.post_body, 0, connection->request.post_body_len + 1 );
            strncpy( connection->request.post_body, ptr, connection->request.post_body_len );

            if ( header && strcmp( headers_get_header_attr( header, NULL ), "application/x-www-form-urlencoded" ) == 0 )
                params_parse_qs( &connection->request.params, connection->request.post_body, connection->request.post_body_len, PARAM_TYPE_POST );

        }

        char* charset;
        header = headers_get_header( &connection->request.headers, "Content-Type" );
        if ( header && ( charset = headers_get_header_attr( header, "charset" ) ) )
            strcpy( connection->request.charset, charset );
        else
            // ISO-8859-1 is the default charset for http defined by RFC
            strcpy( connection->request.charset, "ISO-8859-1" );

    }
    ////////////////////////////////////////

    return connection;

fail:
    connection_free( connection );
    return NULL;
}