summaryrefslogtreecommitdiffstats
path: root/htp/htp_transaction.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:40:56 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:40:56 +0000
commitc248d29056abbc1fc4c5dc178bab48fb8d2c1fcb (patch)
tree4a13fc30604509224504e1911bc976e5df7bdf05 /htp/htp_transaction.h
parentInitial commit. (diff)
downloadlibhtp-c248d29056abbc1fc4c5dc178bab48fb8d2c1fcb.tar.xz
libhtp-c248d29056abbc1fc4c5dc178bab48fb8d2c1fcb.zip
Adding upstream version 1:0.5.47.upstream/1%0.5.47
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'htp/htp_transaction.h')
-rw-r--r--htp/htp_transaction.h529
1 files changed, 529 insertions, 0 deletions
diff --git a/htp/htp_transaction.h b/htp/htp_transaction.h
new file mode 100644
index 0000000..32d6773
--- /dev/null
+++ b/htp/htp_transaction.h
@@ -0,0 +1,529 @@
+/***************************************************************************
+ * Copyright (c) 2009-2010 Open Information Security Foundation
+ * Copyright (c) 2010-2013 Qualys, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+
+ * - 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.
+
+ * - Neither the name of the Qualys, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * HOLDER 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.
+ ***************************************************************************/
+
+/*
+ * @file
+ * @author Ivan Ristic <ivanr@webkreator.com>
+ */
+
+#ifndef HTP_TRANSACTION_H
+#define HTP_TRANSACTION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "htp.h"
+
+/**
+ * Enumerate possible data handling strategies in hybrid parsing
+ * mode. The two possibilities are to make copies of all data and
+ * use bstr instances to wrap already available data.
+ */
+enum htp_alloc_strategy_t {
+ /**
+ * Make copies of all data. This strategy should be used when
+ * the supplied buffers are transient and will go away after
+ * the invoked function returns.
+ */
+ HTP_ALLOC_COPY = 1,
+
+ /**
+ * Reuse buffers, without a change of ownership. We assume the
+ * buffers will continue to be available until the transaction
+ * is deleted by the container.
+ */
+ HTP_ALLOC_REUSE = 2
+};
+
+/**
+ * Possible states of a progressing transaction. Internally, progress will change
+ * to the next state when the processing activities associated with that state
+ * begin. For example, when we start to process request line bytes, the request
+ * state will change from HTP_REQUEST_NOT_STARTED to HTP_REQUEST_LINE.*
+ */
+enum htp_tx_req_progress_t {
+ HTP_REQUEST_NOT_STARTED = 0,
+ HTP_REQUEST_LINE = 1,
+ HTP_REQUEST_HEADERS = 2,
+ HTP_REQUEST_BODY = 3,
+ HTP_REQUEST_TRAILER = 4,
+ HTP_REQUEST_COMPLETE = 5
+};
+
+enum htp_tx_res_progress_t {
+ HTP_RESPONSE_NOT_STARTED = 0,
+ HTP_RESPONSE_LINE = 1,
+ HTP_RESPONSE_HEADERS = 2,
+ HTP_RESPONSE_BODY = 3,
+ HTP_RESPONSE_TRAILER = 4,
+ HTP_RESPONSE_COMPLETE = 5
+};
+
+#define HTP_CONFIG_PRIVATE 0
+#define HTP_CONFIG_SHARED 1
+
+/**
+ * Creates a new transaction structure.
+ *
+ * @param[in] connp Connection parser pointer. Must not be NULL.
+ * @return The newly created transaction, or NULL on memory allocation failure.
+ */
+htp_tx_t *htp_tx_create(htp_connp_t *connp);
+
+/**
+ * Destroys the supplied transaction.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ */
+htp_status_t htp_tx_destroy(htp_tx_t *tx);
+
+/**
+ * Determines if the transaction used a shared configuration structure. See the
+ * documentation for htp_tx_set_config() for more information why you might want
+ * to know that.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return HTP_CFG_SHARED or HTP_CFG_PRIVATE.
+ */
+int htp_tx_get_is_config_shared(const htp_tx_t *tx);
+
+/**
+ * Returns the user data associated with this transaction.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return A pointer to user data or NULL.
+ */
+void *htp_tx_get_user_data(const htp_tx_t *tx);
+
+/**
+ * Registers a callback that will be invoked to process the transaction's request body data.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] callback_fn Callback function pointer. Must not be NULL.
+ */
+void htp_tx_register_request_body_data(htp_tx_t *tx, int (*callback_fn)(htp_tx_data_t *));
+
+/**
+ * Registers a callback that will be invoked to process the transaction's response body data.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] callback_fn Callback function pointer. Must not be NULL.
+ */
+void htp_tx_register_response_body_data(htp_tx_t *tx, int (*callback_fn)(htp_tx_data_t *));
+
+/**
+ * Adds one parameter to the request. THis function will take over the
+ * responsibility for the provided htp_param_t structure.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] param Parameter pointer. Must not be NULL.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_req_add_param(htp_tx_t *tx, htp_param_t *param);
+
+/**
+ * Returns the first request parameter that matches the given name, using case-insensitive matching.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] name Name data pointer. Must not be NULL.
+ * @param[in] name_len Name data length.
+ * @return htp_param_t instance, or NULL if parameter not found.
+ */
+htp_param_t *htp_tx_req_get_param(htp_tx_t *tx, const char *name, size_t name_len);
+
+/**
+ * Returns the first request parameter from the given source that matches the given name,
+ * using case-insensitive matching.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] source Parameter source (where in request the parameter was located).
+ * @param[in] name Name data pointer. Must not be NULL.
+ * @param[in] name_len Name data length.
+ * @return htp_param_t instance, or NULL if parameter not found.
+ */
+htp_param_t *htp_tx_req_get_param_ex(htp_tx_t *tx, enum htp_data_source_t source, const char *name, size_t name_len);
+
+/**
+ * Determine if the request has a body.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return 1 if there is a body, 0 otherwise.
+ */
+int htp_tx_req_has_body(const htp_tx_t *tx);
+
+/**
+ * Process a chunk of request body data. This function assumes that
+ * handling of chunked encoding is implemented by the container. When
+ * you're done submitting body data, invoke a state change (to REQUEST)
+ * to finalize any processing that might be pending. The supplied data is
+ * fully consumed and there is no expectation that it will be available
+ * afterwards. The protocol parsing code makes no copies of the data,
+ * but some parsers might.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] data Data pointer. Must not be NULL.
+ * @param[in] len Data length.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_req_process_body_data(htp_tx_t *tx, const void *data, size_t len);
+
+/**
+ * Set one request header. This function should be invoked once for
+ * each available header, and in the order in which headers were
+ * seen in the request.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] name Name data pointer. Must not be NULL.
+ * @param[in] name_len Name data length.
+ * @param[in] value Value data pointer. Must not be NULL.
+ * @param[in] value_len Value data length.
+ * @param[in] alloc Desired allocation strategy.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_req_set_header(htp_tx_t *tx, const char *name, size_t name_len,
+ const char *value, size_t value_len, enum htp_alloc_strategy_t alloc);
+
+/**
+ * Removes all request headers associated with this transaction. This
+ * function is needed because in some cases the container does not
+ * differentiate between standard and trailing headers. In that case,
+ * you set request headers once at the beginning of the transaction,
+ * read the body (at this point the request headers should contain the
+ * mix of regular and trailing headers), clear all headers, and then set
+ * them all again.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_req_set_headers_clear(htp_tx_t *tx);
+
+/**
+ * Set request line. When used, this function should always be called first,
+ * with more specific functions following. Must not contain line terminators.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] line Line data pointer. Must not be NULL.
+ * @param[in] line_len Line data length.
+ * @param[in] alloc Desired allocation strategy.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_req_set_line(htp_tx_t *tx, const char *line, size_t line_len, enum htp_alloc_strategy_t alloc);
+
+/**
+ * Set transaction request method. This function will enable you to keep
+ * track of the text representation of the method.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] method Method data pointer. Must not be NULL.
+ * @param[in] method_len Method data length.
+ * @param[in] alloc Desired allocation strategy.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_req_set_method(htp_tx_t *tx, const char *method, size_t method_len, enum htp_alloc_strategy_t alloc);
+
+/**
+ * Set transaction request method number. This function enables you to
+ * keep track how a particular method string is interpreted. This function
+ * is useful with web servers that ignore invalid methods; for example, some
+ * web servers will treat them as a GET.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] method_number Method number.
+ */
+void htp_tx_req_set_method_number(htp_tx_t *tx, enum htp_method_t method_number);
+
+/**
+ * Set parsed request URI. You don't need to use this function if you are already providing
+ * the request line or request URI. But if your container already has this data available,
+ * feeding it to LibHTP will minimize any potential data differences. This function assumes
+ * management of the data provided in parsed_uri. This function will not change htp_tx_t::parsed_uri_raw
+ * (which may have data in it from the parsing of the request URI).
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] parsed_uri URI pointer. Must not be NULL.
+ */
+void htp_tx_req_set_parsed_uri(htp_tx_t *tx, htp_uri_t *parsed_uri);
+
+/**
+ * Forces HTTP/0.9 as the transaction protocol. This method exists to ensure
+ * that both LibHTP and the container treat the transaction as HTTP/0.9, despite
+ * potential differences in how the protocol version is determined.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] is_protocol_0_9 Zero if protocol is not HTTP/0.9, or 1 if it is.
+ */
+void htp_tx_req_set_protocol_0_9(htp_tx_t *tx, int is_protocol_0_9);
+
+/**
+ * Sets the request protocol string (e.g., "HTTP/1.0"). The information provided
+ * is only stored, not parsed. Use htp_tx_req_set_protocol_number() to set the
+ * actual protocol number, as interpreted by the container.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] protocol Protocol data pointer. Must not be NULL.
+ * @param[in] protocol_len Protocol data length.
+ * @param[in] alloc Desired allocation strategy.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_req_set_protocol(htp_tx_t *tx, const char *protocol, size_t protocol_len, enum htp_alloc_strategy_t alloc);
+
+/**
+ * Set request protocol version number. Must be invoked after
+ * htp_txh_set_req_protocol(), because it will overwrite the previously
+ * extracted version number. Convert the protocol version number to an integer
+ * by multiplying it with 100. For example, 1.1 becomes 110. Alternatively,
+ * use the HTP_PROTOCOL_0_9, HTP_PROTOCOL_1_0, and HTP_PROTOCOL_1_1 constants.
+ * Note: setting protocol to HTP_PROTOCOL_0_9 alone will _not_ get the library to
+ * treat the transaction as HTTP/0.9. You need to also invoke htp_tx_req_set_protocol_0_9().
+ * This is because HTTP 0.9 is used only when protocol information is absent from the
+ * request line, and not when it is explicitly stated (as "HTTP/0.9"). This behavior is
+ * consistent with that of Apache httpd.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] protocol_number Protocol number.
+ */
+void htp_tx_req_set_protocol_number(htp_tx_t *tx, int protocol_number);
+
+/**
+ * Set transaction request URI. The value provided here will be stored in htp_tx_t::request_uri
+ * and subsequently parsed. If htp_tx_req_set_line() was previously used, the uri provided
+ * when calling this function will overwrite any previously parsed value.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] uri URI data pointer. Must not be NULL.
+ * @param[in] uri_len URI data length.
+ * @param[in] alloc Desired allocation strategy.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_req_set_uri(htp_tx_t *tx, const char *uri, size_t uri_len, enum htp_alloc_strategy_t alloc);
+
+/**
+ * Process a chunk of response body data. This function assumes that
+ * handling of chunked encoding is implemented by the container. When
+ * you're done submitting body data, invoking a state change (to RESPONSE)
+ * will finalize any processing that might be pending.
+ *
+ * The response body data will be decompressed if two conditions are met: one,
+ * decompression is enabled in configuration and two, if the response headers
+ * indicate compression. Alternatively, you can control decompression from
+ * a RESPONSE_HEADERS callback, by setting tx->response_content_encoding either
+ * to COMPRESSION_NONE (to disable compression), or to one of the supported
+ * decompression algorithms.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] data Data pointer. Must not be NULL.
+ * @param[in] len Data length.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_res_process_body_data(htp_tx_t *tx, const void *data, size_t len);
+
+/**
+ * Set one response header. This function should be invoked once for
+ * each available header, and in the order in which headers were
+ * seen in the response.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] name Name data pointer. Must not be NULL.
+ * @param[in] name_len Name data length.
+ * @param[in] value Value data pointer. Must not be NULL.
+ * @param[in] value_len Value length.
+ * @param[in] alloc Desired allocation strategy.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_res_set_header(htp_tx_t *tx, const char *name, size_t name_len,
+ const char *value, size_t value_len, enum htp_alloc_strategy_t alloc);
+
+/**
+ * Removes all response headers associated with this transaction. This
+ * function is needed because in some cases the container does not
+ * differentiate between standard and trailing headers. In that case,
+ * you set response headers once at the beginning of the transaction,
+ * read the body, clear all headers, and then set them all again. After
+ * the headers are set for the second time, they will potentially contain
+ * a mixture of standard and trailing headers.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_res_set_headers_clear(htp_tx_t *tx);
+
+/**
+ * Set response protocol number. See htp_tx_res_set_protocol_number() for more information
+ * about the correct format of the protocol_parameter parameter.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] protocol_number Protocol number.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+void htp_tx_res_set_protocol_number(htp_tx_t *tx, int protocol_number);
+
+/**
+ * Set response line. Use this function is you have a single buffer containing
+ * the entire line. If you have individual request line pieces, use the other
+ * available functions.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] line Line data pointer. Must not be NULL.
+ * @param[in] line_len Line data length.
+ * @param[in] alloc Desired allocation strategy.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_res_set_status_line(htp_tx_t *tx, const char *line, size_t line_len, enum htp_alloc_strategy_t alloc);
+
+/**
+ * Set response status code.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] status_code Response status code.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+void htp_tx_res_set_status_code(htp_tx_t *tx, int status_code);
+
+/**
+ * Set response status message, which is the part of the response
+ * line that comes after the status code.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] msg Message data pointer. Must not be NULL.
+ * @param[in] msg_len Message data length.
+ * @param[in] alloc Desired allocation strategy.
+ * @return HTP_OK on success, HTP_ERROR on failure.
+ */
+htp_status_t htp_tx_res_set_status_message(htp_tx_t *tx, const char *msg, size_t msg_len, enum htp_alloc_strategy_t alloc);
+
+/**
+ * Sets the configuration that is to be used for this transaction. If the
+ * second parameter is set to HTP_CFG_PRIVATE, the transaction will adopt
+ * the configuration structure and destroy it when appropriate. This function is
+ * useful if you need to make changes to configuration on per-transaction basis.
+ * Initially, all transactions will share the configuration with that of the
+ * connection; if you were to make changes on it, they would affect all
+ * current and future connections. To work around that, you make a copy of the
+ * configuration object, call this function with the second parameter set to
+ * HTP_CFG_PRIVATE, and modify configuration at will.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] cfg Configuration pointer. Must not be NULL.
+ * @param[in] is_cfg_shared HTP_CFG_SHARED or HTP_CFG_PRIVATE
+ */
+void htp_tx_set_config(htp_tx_t *tx, htp_cfg_t *cfg, int is_cfg_shared);
+
+/**
+ * Associates user data with this transaction.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @param[in] user_data Opaque user data pointer.
+ */
+void htp_tx_set_user_data(htp_tx_t *tx, void *user_data);
+
+/**
+ * Change transaction state to REQUEST and invoke registered callbacks.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return HTP_OK on success; HTP_ERROR on error, HTP_STOP if one of the
+ * callbacks does not want to follow the transaction any more.
+ */
+htp_status_t htp_tx_state_request_complete(htp_tx_t *tx);
+
+/**
+ * Change transaction state to REQUEST_HEADERS and invoke all
+ * registered callbacks.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return HTP_OK on success; HTP_ERROR on error, HTP_STOP if one of the
+ * callbacks does not want to follow the transaction any more.
+ */
+htp_status_t htp_tx_state_request_headers(htp_tx_t *tx);
+
+/**
+ * Change transaction state to REQUEST_LINE and invoke all
+ * registered callbacks.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return HTP_OK on success; HTP_ERROR on error, HTP_STOP if one of the
+ * callbacks does not want to follow the transaction any more.
+ */
+htp_status_t htp_tx_state_request_line(htp_tx_t *tx);
+
+/**
+ * Initialize hybrid parsing mode, change state to TRANSACTION_START,
+ * and invoke all registered callbacks.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return HTP_OK on success; HTP_ERROR on error, HTP_STOP if one of the
+ * callbacks does not want to follow the transaction any more.
+ */
+htp_status_t htp_tx_state_request_start(htp_tx_t *tx);
+
+/**
+ * Change transaction state to RESPONSE and invoke registered callbacks.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return HTP_OK on success; HTP_ERROR on error, HTP_STOP if one of the
+ * callbacks does not want to follow the transaction any more.
+ */
+htp_status_t htp_tx_state_response_complete(htp_tx_t *tx);
+
+/**
+ * Change transaction state to RESPONSE_HEADERS and invoke registered callbacks.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return HTP_OK on success; HTP_ERROR on error, HTP_STOP if one of the
+ * callbacks does not want to follow the transaction any more.
+ */
+htp_status_t htp_tx_state_response_headers(htp_tx_t *tx);
+
+/**
+ * Change transaction state to HTP_RESPONSE_LINE and invoke registered callbacks.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return HTP_OK on success; HTP_ERROR on error, HTP_STOP if one of the
+ * callbacks does not want to follow the transaction any more.
+ */
+htp_status_t htp_tx_state_response_line(htp_tx_t *tx);
+
+/**
+ * Change transaction state to RESPONSE_START and invoke registered callbacks.
+ *
+ * @param[in] tx Transaction pointer. Must not be NULL.
+ * @return HTP_OK on success; HTP_ERROR on error, HTP_STOP if one of the
+ * callbacks does not want to follow the transaction any more.
+ */
+htp_status_t htp_tx_state_response_start(htp_tx_t *tx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HTP_HYBRID_H */