ERROR_CODE _encode_type(struct type_t *type, struct string_buffer_t *string_buffer) { char *buffer; struct type_t key; struct type_t *current; struct iterator_t *iterator; struct hash_map_element_t *element; switch(type->type) { case INTEGER_TYPE: buffer = MALLOC(16); SPRINTF(buffer, 16, "%d", type->value.value_int); append_string_buffer(string_buffer, (unsigned char *) "i"); _append_string_buffer(string_buffer, (unsigned char *) buffer); append_string_buffer(string_buffer, (unsigned char *) "e"); break; case STRING_TYPE: buffer = MALLOC(16); SPRINTF(buffer, 16, "%lu", (long unsigned int) type->size); _append_string_buffer(string_buffer, (unsigned char *) buffer); append_string_buffer(string_buffer, (unsigned char *) ":"); append_string_l_buffer( string_buffer, (unsigned char *) type->value.value_string, type->size ); break; case LIST_TYPE: append_string_buffer(string_buffer, (unsigned char *) "l"); create_iterator_linked_list(type->value.value_list, &iterator); while(TRUE) { get_next_iterator(iterator, (void **) ¤t); if(current == NULL) { break; } _encode_type(current, string_buffer); } delete_iterator_linked_list(type->value.value_list, iterator); append_string_buffer(string_buffer, (unsigned char *) "e"); break; case MAP_TYPE: append_string_buffer(string_buffer, (unsigned char *) "d"); create_element_iterator_hash_map(type->value.value_map, &iterator); while(TRUE) { get_next_iterator(iterator, (void **) &element); if(element == NULL) { break; } key = string_type((char *) element->key_string); _encode_type(&key, string_buffer); _encode_type((struct type_t *) element->value, string_buffer); } delete_iterator_hash_map(type->value.value_map, iterator); append_string_buffer(string_buffer, (unsigned char *) "e"); break; case SORT_MAP_TYPE: append_string_buffer(string_buffer, (unsigned char *) "d"); create_element_iterator_sort_map(type->value.value_sort_map, &iterator); while(TRUE) { get_next_iterator(iterator, (void **) &element); if(element == NULL) { break; } key = string_type((char *) element->key_string); _encode_type(&key, string_buffer); _encode_type((struct type_t *) element->value, string_buffer); } delete_iterator_sort_map(type->value.value_sort_map, iterator); append_string_buffer(string_buffer, (unsigned char *) "e"); break; default: break; } /* raises no error */ RAISE_NO_ERROR; }
ERROR_CODE parameters_http(struct hash_map_t *hash_map, unsigned char **buffer_pointer, size_t *buffer_length_pointer) { /* allocates space for an iterator object for an hash map element and for the string buffer to be used to collect all the partial strings that compose the complete url parameters string */ struct iterator_t *iterator; struct hash_map_element_t *element; struct string_buffer_t *string_buffer; /* allocates space for the string structure to hold the value of the element for the string value reference for the joined string, for the buffer string from the element and for the corresponding string lengths for both cases */ struct string_t *string; unsigned char *string_value; unsigned char *_buffer; size_t string_length; size_t _length; /* allocates and sets the initial value on the flag that controls if the iteratio to generate key values is the first one */ char is_first = 1; /* creates a new string buffer and a new hash map iterator, these structures are going to be used to handle the string from the hash map and to iterate over the hash map elements */ create_string_buffer(&string_buffer); create_element_iterator_hash_map(hash_map, &iterator); /* iterates continuously arround the hash map element the iterator is going to stop the iteration */ while(TRUE) { /* retrieves the next element from the iterator and in case such element is invalid breaks the loop */ get_next_iterator(iterator, (void **) &element); if(element == NULL) { break; } /* checks if this is the first loop in the iteration in it's not emits the and character */ if(is_first) { is_first = 0; } else { append_string_buffer(string_buffer, (unsigned char *) "&"); } /* retrieves the current element value as a string structure then encodes that value using the url encoding (percent encoding) and resets the string reference to contain the new buffer as it' own contents (avoids extra memory usage) */ string = (struct string_t *) element->value; url_encode(string->buffer, string->length, &_buffer, &_length); string->buffer = _buffer; string->length = _length; /* adds the various elements for the value to the string buffer first the key the the attribution operator and then the value */ append_string_buffer(string_buffer, (unsigned char *) element->key_string); append_string_l_buffer(string_buffer, (unsigned char *) "=", sizeof("=") - 1); _append_string_t_buffer(string_buffer, string); } /* "joins" the string buffer values into a single value (from the internal string list) and then retrieves the length of the string buffer */ join_string_buffer(string_buffer, &string_value); string_length = string_buffer->string_length; /* deletes the hash map iterator and string buffer structures, to avoid memory leak */ delete_iterator_hash_map(hash_map, iterator); delete_string_buffer(string_buffer); /* updates the buffer pointer reference and the buffer length pointer reference with the string value and the string length values */ *buffer_pointer = string_value; *buffer_length_pointer = string_length; /* raises no error */ RAISE_NO_ERROR; }
inline std::string shell_quote(C const& data, bool quote_empty = true) { string_buffer b; // NRVO in C++11 shell_quote_chars(append_string_buffer(b), to_string(data), quote_empty); return strcopy(b); }
ERROR_CODE write_http_error_a( struct connection_t *connection, char *buffer, size_t size, enum http_version_e version, int error_code, char *error_message, char *error_description, char *realm, enum http_keep_alive_e keep_alive, connection_data_callback_hu callback, void *callback_parameters ) { /* allocates space for the result buffer related variables (for both the buffer pointer and size) */ size_t result_length; unsigned char *result_buffer; /* allocates space for the references the string buffer and template handler structures */ struct string_buffer_t *string_buffer; struct template_handler_t *template_handler; /* allocates space for the "possible" locally generated error description (format based generation) */ char _error_description[1024]; /* allocates space to the path to the template file to be used for template generation */ unsigned char template_path[VIRIATUM_MAX_PATH_SIZE]; /* retrieves the service from the connection structure and then uses it to retrieve its options */ struct service_t *service = connection->service; struct service_options_t *options = service->options; /* allocates the headers buffer (it will be releases automatically by the writter) it need to be allocated in the heap so it gets throught the request cycle */ char *headers_buffer = buffer == NULL ? MALLOC(VIRIATUM_HTTP_SIZE) : buffer; size = size == 0 ? VIRIATUM_HTTP_SIZE : size; #ifndef VIRIATUM_DEBUG /* sets the error description as null in order to avoid any display of the (internal) message, otherwise a possible security hole would be created */ error_description = NULL; #endif /* in case the use template flag is set the error should be displayed using the template */ if(options->use_template) { /* creates the complete path to the template file */ SPRINTF( (char *) template_path, sizeof(template_path), "%s%s", VIRIATUM_RESOURCES_PATH, VIRIATUM_ERROR_PATH ); /* prints a debug message */ V_DEBUG_F("Processing template file '%s'\n", template_path); /* creates the template handler that will hold the error information contents */ create_template_handler(&template_handler); /* assigns the various error related variables into the template handler to be used, they may be used to display information arround the error, note that the error description value is conditional and may not be set */ assign_integer_template_handler(template_handler, (unsigned char *) "error_code", error_code); assign_string_template_handler(template_handler, (unsigned char *) "error_message", error_message); if(error_description != NULL) { assign_string_template_handler(template_handler, (unsigned char *) "error_description", error_description); } /* processes the file as a template handler, at this point the output buffer of the template engine should be populated with the complete header information, the apropriate header writing method is chosen based on the existence or not of the realm authorization field */ process_template_handler(template_handler, template_path); realm == NULL ? write_http_headers_c( connection, headers_buffer, size, version, error_code, error_message, keep_alive, strlen((char *) template_handler->string_value), NO_CACHE, TRUE ) : write_http_headers_a( connection, headers_buffer, size, version, error_code, error_message, keep_alive, strlen((char *) template_handler->string_value), NO_CACHE, realm, TRUE ); /* creates a new string buffer to hold the complete set of contents to be sent to the client then first writes the buffer containing the headers and then the resulting contents from the template handler */ create_string_buffer(&string_buffer); append_string_buffer(string_buffer, (unsigned char *) headers_buffer); append_string_buffer(string_buffer, template_handler->string_value); join_string_buffer(string_buffer, &result_buffer); result_length = string_buffer->string_length; delete_string_buffer(string_buffer); /* deletes the template handler as all the processing on it has been done (buffer generated) */ delete_template_handler(template_handler); /* releases the contents of the headers buffer, no more need to continue using them (not requried) */ FREE(headers_buffer); /* writes the resulting buffer into the connection in order to be sent to the client (sends the template results) in one chunk */ write_connection( connection, result_buffer, (unsigned int) result_length, (connection_data_callback) callback, callback_parameters ); } else { /* "stringfies" a possible null error description into a description string in order to be correctly displayed then formats the error message using the code, message and description */ error_description = error_description == NULL ? (char *) service->description : error_description; SPRINTF( _error_description, sizeof(_error_description), "%d - %s - %s", error_code, error_message, error_description ); /* writes the http static headers to the response and then writes the error description itself */ write_http_headers_m( connection, headers_buffer, size, version, error_code, error_message, keep_alive, strlen(_error_description), NO_CACHE, _error_description ); /* writes both the headers to the connection, an then registers for the appropriate callbacks */ write_connection( connection, (unsigned char *) headers_buffer, (unsigned int) strlen(headers_buffer), (connection_data_callback) callback, callback_parameters ); } /* raises no error */ RAISE_NO_ERROR; }