1
0
mirror of https://github.com/lammertb/libhttp.git synced 2025-08-09 03:22:45 +03:00
Files
libhttp/src/httplib_process_options.c
2017-01-02 13:56:08 +01:00

340 lines
17 KiB
C

/*
* Copyright (c) 2016 Lammert Bies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "httplib_main.h"
static bool check_bool( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, bool *config );
static bool check_dbg( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, enum lh_dbg_t *config );
static bool check_dir( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config );
static bool check_file( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config );
static bool check_int( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, int *config, int minval, int maxval );
static bool check_patt( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config );
static bool check_str( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config );
/*
* bool XX_httplib_process_options( struct lh_ctx_t *ctx, const struct lh_opt_t *options );
*
* The function process_options() processes the user supplied options and adds
* them to the central option list of the context. If en error occurs, the
* function returns true, otherwise FALSE is returned. In case of an error all
* cleanup is already done before returning and an error message has been
* generated.
*/
bool XX_httplib_process_options( struct lh_ctx_t *ctx, const struct lh_opt_t *options ) {
if ( ctx == NULL ) return true;
while ( options != NULL && options->name != NULL ) {
if ( check_str( ctx, options, "access_control_allow_origin", & ctx->access_control_allow_origin ) ) return true;
if ( check_str( ctx, options, "access_control_list", & ctx->access_control_list ) ) return true;
if ( check_file( ctx, options, "access_log_file", & ctx->access_log_file ) ) return true;
if ( check_bool( ctx, options, "allow_sendfile_call", & ctx->allow_sendfile_call ) ) return true;
if ( check_str( ctx, options, "authentication_domain", & ctx->authentication_domain ) ) return true;
if ( check_str( ctx, options, "cgi_environment", & ctx->cgi_environment ) ) return true;
if ( check_file( ctx, options, "cgi_interpreter", & ctx->cgi_interpreter ) ) return true;
if ( check_patt( ctx, options, "cgi_pattern", & ctx->cgi_pattern ) ) return true;
if ( check_dbg( ctx, options, "debug_level", & ctx->debug_level ) ) return true;
if ( check_bool( ctx, options, "decode_url", & ctx->decode_url ) ) return true;
if ( check_dir( ctx, options, "document_root", & ctx->document_root ) ) return true;
if ( check_bool( ctx, options, "enable_directory_listing", & ctx->enable_directory_listing ) ) return true;
if ( check_bool( ctx, options, "enable_keep_alive", & ctx->enable_keep_alive ) ) return true;
if ( check_file( ctx, options, "error_log_file", & ctx->error_log_file ) ) return true;
if ( check_dir( ctx, options, "error_pages", & ctx->error_pages ) ) return true;
if ( check_str( ctx, options, "extra_mime_types", & ctx->extra_mime_types ) ) return true;
if ( check_file( ctx, options, "global_auth_file", & ctx->global_auth_file ) ) return true;
if ( check_patt( ctx, options, "hide_file_pattern", & ctx->hide_file_pattern ) ) return true;
if ( check_str( ctx, options, "index_files", & ctx->index_files ) ) return true;
if ( check_str( ctx, options, "listening_ports", & ctx->listening_ports ) ) return true;
if ( check_int( ctx, options, "num_threads", & ctx->num_threads, 1, INT_MAX ) ) return true;
if ( check_str( ctx, options, "protect_uri", & ctx->protect_uri ) ) return true;
if ( check_file( ctx, options, "put_delete_auth_file", & ctx->put_delete_auth_file ) ) return true;
if ( check_int( ctx, options, "request_timeout", & ctx->request_timeout, 0, INT_MAX ) ) return true;
if ( check_str( ctx, options, "run_as_user", & ctx->run_as_user ) ) return true;
if ( check_int( ctx, options, "ssi_include_depth", & ctx->ssi_include_depth, 0, 20 ) ) return true;
if ( check_patt( ctx, options, "ssi_pattern", & ctx->ssi_pattern ) ) return true;
if ( check_file( ctx, options, "ssl_ca_file", & ctx->ssl_ca_file ) ) return true;
if ( check_dir( ctx, options, "ssl_ca_path", & ctx->ssl_ca_path ) ) return true;
if ( check_file( ctx, options, "ssl_certificate", & ctx->ssl_certificate ) ) return true;
if ( check_str( ctx, options, "ssl_cipher_list", & ctx->ssl_cipher_list ) ) return true;
if ( check_int( ctx, options, "ssl_protocol_version", & ctx->ssl_protocol_version, 0, 4 ) ) return true;
if ( check_bool( ctx, options, "ssl_short_trust", & ctx->ssl_short_trust ) ) return true;
if ( check_int( ctx, options, "ssl_verify_depth", & ctx->ssl_verify_depth, 0, 9 ) ) return true;
if ( check_bool( ctx, options, "ssl_verify_paths", & ctx->ssl_verify_paths ) ) return true;
if ( check_bool( ctx, options, "ssl_verify_peer", & ctx->ssl_verify_peer ) ) return true;
if ( check_int( ctx, options, "static_file_max_age", & ctx->static_file_max_age, 0, INT_MAX ) ) return true;
if ( check_str( ctx, options, "throttle", & ctx->throttle ) ) return true;
if ( check_bool( ctx, options, "tcp_nodelay", & ctx->tcp_nodelay ) ) return true;
if ( check_str( ctx, options, "url_rewrite_patterns", & ctx->url_rewrite_patterns ) ) return true;
if ( check_dir( ctx, options, "websocket_root", & ctx->websocket_root ) ) return true;
if ( check_int( ctx, options, "websocket_timeout", & ctx->websocket_timeout, 0, INT_MAX ) ) return true;
/*
* TODO: Currently silently ignoring unrecognized options
*/
options++;
}
return false;
} /* XX_httplib_process_options */
/*
* static bool check_bool( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, bool *config );
*
* The function check_bool() checks if an option is equal to a boolean config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. If the value could be found, also
* false is returned.
*/
static bool check_bool( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, bool *config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing boolean option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
if ( ! XX_httplib_option_value_to_bool( option->value, config ) ) return false;
XX_httplib_abort_start( ctx, "Invalid boolean value \"%s\" for option \"%s\"", option->value, option->name );
return true;
} /* check_bool */
/*
* static bool check_dir( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config );
*
* The function check_dir() checks if an option is equal to a directory config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_dir( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing directory option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
XX_httplib_abort_start( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_dir */
/*
* static bool check_patt( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config );
*
* The function check_patt() checks if an option is equal to a pattern config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_patt( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing pattern option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
XX_httplib_abort_start( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_patt */
/*
* static bool check_file( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config );
*
* The function check_file() checks if an option is equal to a filename config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_file( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing file option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
XX_httplib_abort_start( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_file */
/*
* static bool check_str( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config );
*
* The function check_str() checks if an option is equal to a string config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_str( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing string option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
XX_httplib_abort_start( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_str */
/*
* static bool check_int( struct lh_ctx_t *ctx, const struct httplib_opion_t *option, const char *name, int *config, int minval, int maxval );
*
* The function check_int() checks in an option is equal to an integer config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. If the value could be found and is
* valud, also false is returned.
*/
static bool check_int( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, int *config, int minval, int maxval ) {
int val;
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing integer option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
if ( ! XX_httplib_option_value_to_int( option->value, & val ) ) {
if ( val < minval ) { XX_httplib_abort_start( ctx, "Integer \"%s\" too small for option \"%s\"", option->value, option->name ); return true; }
if ( val > maxval ) { XX_httplib_abort_start( ctx, "Integer \"%s\" too large for option \"%s\"", option->value, option->name ); return true; }
*config = val;
return false;
}
XX_httplib_abort_start( ctx, "Invalid integer value \"%s\" for option \"%s\"", option->value, option->name );
return true;
} /* check_int */
/*
* static bool check_dbg( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, enum lh_dbg_t *config );
*
* The function check_dbg() checks if an option is equal to a debug level
* config parameter and stores the value if that is the case. If the value
* cannot be recognized, true is returned and the function performs a complete
* cleanup. If the option name could not be found, the function returns false
* to indicate that the search should go on. If the value could be found and is
* valid, also false is returned.
*/
static bool check_dbg( struct lh_ctx_t *ctx, const struct lh_opt_t *option, const char *name, enum lh_dbg_t *config ) {
int val;
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing debug level option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
if ( ! XX_httplib_option_value_to_int( option->value, &val ) ) {
switch ( val ) {
case LH_DEBUG_NONE :
case LH_DEBUG_CRASH :
case LH_DEBUG_ERROR :
case LH_DEBUG_WARNING :
case LH_DEBUG_INFO :
*config = val;
return false;
}
}
XX_httplib_abort_start( ctx, "Invalid value \"%s\" for option \"%s\"", option->value, option->name );
return true;
} /* check_dbg */