static size_t string_table_read(apt_str_table_item_t table[], apr_size_t max_count, FILE *file, apr_pool_t *pool) { apt_str_table_item_t *item; size_t count = 0; apt_str_t line; apt_text_stream_t text_stream; text_stream.text.length = fread(parse_buffer, 1, sizeof(parse_buffer)-1, file); parse_buffer[text_stream.text.length] = '\0'; text_stream.text.buf = parse_buffer; text_stream.pos = parse_buffer; do { if(apt_text_line_read(&text_stream,&line) == FALSE || !line.length) { break; } item = &table[count]; apt_string_copy(&item->value,&line,pool); item->key = 0; count++; } while(count < max_count); return count; }
/** Create message and read start line */ static apt_bool_t rtsp_parser_on_start(apt_message_parser_t *parser, apt_message_context_t *context, apt_text_stream_t *stream, apr_pool_t *pool) { rtsp_message_t *message; apt_str_t start_line; /* read start line */ if(apt_text_line_read(stream,&start_line) == FALSE) { return FALSE; } message = rtsp_message_create(RTSP_MESSAGE_TYPE_UNKNOWN,pool); if(rtsp_start_line_parse(&message->start_line,&start_line,message->pool) == FALSE) { return FALSE; } context->message = message; context->header = &message->header.header_section; context->body = &message->body; return TRUE; }
/** Parse MRCP start-line */ MRCP_DECLARE(apt_bool_t) mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream, apr_pool_t *pool) { apt_text_stream_t line; apt_str_t field; apt_bool_t status = TRUE; start_line->message_type = MRCP_MESSAGE_TYPE_UNKNOWN; if(apt_text_line_read(text_stream,&line.text) == FALSE) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot parse MRCP start-line"); return FALSE; } apt_text_stream_reset(&line); if(apt_text_field_read(&line,APT_TOKEN_SP,TRUE,&field) == FALSE) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot read the first field in start-line"); return FALSE; } if(field.buf == strstr(field.buf,MRCP_NAME)) { start_line->version = mrcp_version_parse(&field); if(start_line->version == MRCP_VERSION_1) { /* parsing MRCP v1 response */ start_line->message_type = MRCP_MESSAGE_TYPE_RESPONSE; status = mrcp_response_line_parse(start_line,&line); } else if(start_line->version == MRCP_VERSION_2) { /* parsing MRCP v2 start-line (request/response/event) */ status = mrcp_v2_start_line_parse(start_line,&line,pool); } else { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown MRCP version"); return FALSE; } } else { /* parsing MRCP v1 request or event */ apt_string_copy(&start_line->method_name,&field,pool); status = mrcp_request_line_parse(start_line,&line); } return status; }
static apt_bool_t resource_name_read(apr_file_t *file, mrcp_parser_t *parser) { char buffer[100]; apt_text_stream_t stream; apt_bool_t status = FALSE; apt_text_stream_init(&stream,buffer,sizeof(buffer)-1); if(apr_file_read(file,stream.pos,&stream.text.length) != APR_SUCCESS) { return FALSE; } /* skip the first line in a test file, which indicates resource name */ if(*stream.pos =='/' && *(stream.pos+1)=='/') { apt_str_t line; stream.pos += 2; if(apt_text_line_read(&stream,&line) == TRUE) { apr_off_t offset = stream.pos - stream.text.buf; apr_file_seek(file,APR_SET,&offset); mrcp_parser_resource_name_set(parser,&line); status = TRUE; } } return status; }
/** Create message and read start line */ static apt_bool_t mrcp_parser_on_start(apt_message_parser_t *parser, apt_message_context_t *context, apt_text_stream_t *stream, apr_pool_t *pool) { mrcp_message_t *mrcp_message; apt_str_t start_line; /* read start line */ if(apt_text_line_read(stream,&start_line) == FALSE) { return FALSE; } /* create new MRCP message */ mrcp_message = mrcp_message_create(pool); /* parse start-line */ if(mrcp_start_line_parse(&mrcp_message->start_line,&start_line,mrcp_message->pool) == FALSE) { return FALSE; } if(mrcp_message->start_line.version == MRCP_VERSION_1) { mrcp_parser_t *mrcp_parser = apt_message_parser_object_get(parser); if(!mrcp_parser->resource) { return FALSE; } apt_string_copy( &mrcp_message->channel_id.resource_name, &mrcp_parser->resource->name, pool); if(mrcp_message_resource_set(mrcp_message,mrcp_parser->resource) == FALSE) { return FALSE; } } context->message = mrcp_message; context->header = &mrcp_message->header.header_section; context->body = &mrcp_message->body; return TRUE; }
/** Parse individual header field (name-value pair) */ APT_DECLARE(apt_header_field_t*) apt_header_field_parse(apt_text_stream_t *stream, apr_pool_t *pool) { apr_size_t folding_length = 0; apr_array_header_t *folded_lines = NULL; apt_header_field_t *header_field; apt_str_t temp_line; apt_str_t *line; apt_pair_t pair; /* read name-value pair */ if(apt_text_header_read(stream,&pair) == FALSE) { return NULL; } /* check folding lines (value spanning multiple lines) */ while(stream->pos < stream->end) { if(apt_text_is_wsp(*stream->pos) == FALSE) { break; } stream->pos++; /* skip further white spaces (if any) */ apt_text_white_spaces_skip(stream); if(!folded_lines) { folded_lines = apr_array_make(pool,1,sizeof(apt_str_t)); } if(apt_text_line_read(stream,&temp_line) == TRUE) { line = apr_array_push(folded_lines); *line = temp_line; folding_length += line->length; } }; header_field = apt_header_field_alloc(pool); /* copy parsed name of the header field */ header_field->name.length = pair.name.length; header_field->name.buf = apr_palloc(pool, pair.name.length + 1); if(pair.name.length) { memcpy(header_field->name.buf, pair.name.buf, pair.name.length); } header_field->name.buf[header_field->name.length] = '\0'; /* copy parsed value of the header field */ header_field->value.length = pair.value.length + folding_length; header_field->value.buf = apr_palloc(pool, header_field->value.length + 1); if(pair.value.length) { memcpy(header_field->value.buf, pair.value.buf, pair.value.length); } if(folding_length) { int i; char *pos = header_field->value.buf + pair.value.length; /* copy parsed folding lines */ for(i=0; i<folded_lines->nelts; i++) { line = &APR_ARRAY_IDX(folded_lines,i,apt_str_t); memcpy(pos,line->buf,line->length); pos += line->length; } } header_field->value.buf[header_field->value.length] = '\0'; return header_field; }
/** Get the next content part */ APT_DECLARE(apt_bool_t) apt_multipart_content_get(apt_multipart_content_t *multipart_content, apt_content_part_t *content_part, apt_bool_t *is_final) { apt_str_t boundary; apt_header_field_t *header_field; apt_text_stream_t *stream = &multipart_content->stream; if(!content_part || !is_final) { return FALSE; } *is_final = FALSE; apt_content_part_reset(content_part); /* skip preamble */ apt_text_skip_to_char(stream,'-'); if(apt_text_is_eos(stream) == TRUE) { return FALSE; } /* skip initial hyphens */ apt_text_chars_skip(stream,'-'); if(apt_text_is_eos(stream) == TRUE) { return FALSE; } /* read line and the boundary */ if(apt_text_line_read(stream,&boundary) == FALSE) { return FALSE; } /* remove optional trailing spaces */ while(boundary.length && boundary.buf[boundary.length-1] == APT_TOKEN_SP) boundary.length--; /* check whether this is the final boundary */ if(boundary.length >= 2) { if(boundary.buf[boundary.length-1] == '-' && boundary.buf[boundary.length-2] == '-') { /* final boundary */ boundary.length -= 2; *is_final = TRUE; } } /* compare boundaries */ if(apt_string_is_empty(&multipart_content->boundary) == TRUE) { /* no boundary was specified from user space, learn boundary from the content */ multipart_content->boundary = boundary; } else { if(apt_string_compare(&multipart_content->boundary,&boundary) == FALSE) { /* invalid boundary */ return FALSE; } } if(*is_final == TRUE) { /* final boundary => return TRUE, content remains empty */ return TRUE; } /* read header fields */ if(apt_header_section_parse(&content_part->header,stream,multipart_content->pool) == FALSE) { return FALSE; } for(header_field = APR_RING_FIRST(&content_part->header.ring); header_field != APR_RING_SENTINEL(&content_part->header.ring, apt_header_field_t, link); header_field = APR_RING_NEXT(header_field, link)) { if(strncmp(header_field->name.buf,CONTENT_LENGTH_HEADER,header_field->name.length) == 0) { content_part->length = &header_field->value; } else if(strncmp(header_field->name.buf,CONTENT_TYPE_HEADER,header_field->name.length) == 0) { content_part->type = &header_field->value; } else if(strncmp(header_field->name.buf,CONTENT_ID_HEADER,header_field->name.length) == 0) { content_part->id = &header_field->value; } } if(content_part->length && apt_string_is_empty(content_part->length) == FALSE) { apr_size_t length = atoi(content_part->length->buf); if(length + stream->pos > stream->end) { return FALSE; } /* read content */ apt_string_assign_n(&content_part->body,stream->pos,length,multipart_content->pool); stream->pos += length; } return TRUE; }
/** Get the next content part */ APT_DECLARE(apt_bool_t) apt_multipart_content_get(apt_multipart_content_t *multipart_content, apt_str_t *content_type, apt_str_t *content) { apt_str_t boundary; apt_pair_t header; apt_bool_t is_final = FALSE; apt_text_stream_t *stream = &multipart_content->stream; if(!content || !content_type) { return FALSE; } apt_string_reset(content); /* skip preamble */ apt_text_skip_to_char(stream,'-'); if(apt_text_is_eos(stream) == TRUE) { return FALSE; } /* skip initial hyphens */ apt_text_chars_skip(stream,'-'); if(apt_text_is_eos(stream) == TRUE) { return FALSE; } /* read line and the boundary */ if(apt_text_line_read(stream,&boundary) == FALSE) { return FALSE; } /* remove optional trailing spaces */ while(boundary.length && boundary.buf[boundary.length-1] == APT_TOKEN_SP) boundary.length--; /* check whether this is the final boundary */ if(boundary.length >= 2) { if(boundary.buf[boundary.length-1] == '-' && boundary.buf[boundary.length-2] == '-') { /* final boundary */ boundary.length -= 2; is_final = TRUE; } } /* compare boundaries */ if(apt_string_is_empty(&multipart_content->boundary) == TRUE) { /* no boundary was specified from user space, learn boundary from the content */ multipart_content->boundary = boundary; } else { if(apt_string_compare(&multipart_content->boundary,&boundary) == FALSE) { /* invalid boundary */ return FALSE; } } if(is_final == TRUE) { /* final boundary => return TRUE, content remains empty */ return TRUE; } /* read header fields */ do { if(apt_text_header_read(stream,&header) == TRUE) { if(header.name.length) { if(apt_string_compare(&multipart_content->content_type_header,&header.name) == TRUE) { apt_string_copy(content_type,&header.value,multipart_content->pool); } else if(apt_string_compare(&multipart_content->content_length_header,&header.name) == TRUE) { if(header.value.buf) { content->length = atol(header.value.buf); if(content->length) { content->buf = apr_palloc(multipart_content->pool,content->length+1); content->buf[content->length] = '\0'; } } } } else { /* empty header => exit */ break; } } } while(apt_text_is_eos(stream) == FALSE); if(!content->length || content->length + stream->pos > stream->end) { return FALSE; } /* read content */ memcpy(content->buf,stream->pos,content->length); stream->pos += content->length; return TRUE; }