From 6ea4278a512bc9f1f816844222e65a4ea670db8e Mon Sep 17 00:00:00 2001 From: jvoisin Date: Fri, 24 Oct 2025 23:50:18 +0200 Subject: feat(log): add the possibility to log to a file --- src/php_snuffleupagus.h | 2 +- src/snuffleupagus.c | 2 +- src/sp_config.h | 7 ++++++- src/sp_config_keywords.c | 20 ++++++++++++++------ src/sp_utils.c | 16 +++++++++++++++- .../broken_conf_invalid_log_media.phpt | 2 +- src/tests/syslog_simulation.phpt | 1 + 7 files changed, 39 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h index be37cfa..adaa6c0 100644 --- a/src/php_snuffleupagus.h +++ b/src/php_snuffleupagus.h @@ -141,7 +141,7 @@ sp_config_eval config_eval; sp_config_wrapper config_wrapper; sp_config_session config_session; sp_config_ini config_ini; -char config_log_media; +sp_config_log config_log_media; int config_log_max_len; u_long config_max_execution_depth; bool config_server_encode; diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index 6264d22..8b7f11d 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c @@ -356,7 +356,7 @@ static void dump_config(void) { // global add_assoc_bool(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_ENCRYPTION_KEY, SPCFG(encryption_key) && ZSTR_LEN(SPCFG(encryption_key))); ADD_ASSOC_ZSTR(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_ENV_VAR, SPCFG(cookies_env_var)); - add_assoc_long(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_LOG_MEDIA, SPCFG(log_media)); + //add_assoc_long(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_LOG_MEDIA, SPCFG(log_media)); add_assoc_long(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_LOG_MAX_LEN, SPCFG(log_max_len)); add_assoc_long(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_MAX_EXECUTION_DEPTH, SPCFG(max_execution_depth)); add_assoc_bool(&arr, SP_TOKEN_GLOBAL "." SP_TOKEN_SERVER_ENCODE, SPCFG(server_encode)); diff --git a/src/sp_config.h b/src/sp_config.h index 6bfb009..8886bc6 100644 --- a/src/sp_config.h +++ b/src/sp_config.h @@ -19,10 +19,15 @@ typedef enum { SP_PHP_TYPE_REFERENCE = IS_REFERENCE } sp_php_type; -typedef enum { SP_LOG_ZEND = 0, SP_LOG_SYSLOG = 1 } sp_log_media; typedef enum { SP_INI_UNSET = 0, SP_INI_READONLY = 1, SP_INI_READWRITE = -1 } sp_ini_permission; +typedef enum { SP_LOG_ZEND = 0, SP_LOG_SYSLOG = 1, SP_LOG_FILE = 2 } sp_log_media_type; +typedef struct { + sp_log_media_type type; + char* path; +} sp_config_log; + typedef struct { int ip_version; union { diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index a5b4c5d..7f41e38 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c @@ -57,19 +57,27 @@ SP_PARSE_FN(parse_session) { } SP_PARSEKW_FN(parse_log_media) { + sp_config_log *cfg = (sp_config_log*)retval; + cfg->path = NULL; + SP_PARSE_ARG(value); - + if (!strcmp(ZSTR_VAL(value), "php")) { - *(char*)retval = SP_LOG_ZEND; + cfg->type = SP_LOG_ZEND; zend_string_release_ex(value, 1); - return SP_PARSER_SUCCESS; + return SP_PARSER_STOP; } else if (!strcmp(ZSTR_VAL(value), "syslog")) { - *(char*)retval = SP_LOG_SYSLOG; + cfg->type = SP_LOG_SYSLOG; + zend_string_release_ex(value, 1); + return SP_PARSER_STOP; + } else if (!strncmp(ZSTR_VAL(value), "file:", strlen("file:"))) { + cfg->type = SP_LOG_FILE; + cfg->path = strdup(ZSTR_VAL(value)+strlen("file:")); zend_string_release_ex(value, 1); - return SP_PARSER_SUCCESS; + return SP_PARSER_STOP; } - sp_log_err("config", "." SP_TOKEN_LOG_MEDIA "() only supports 'syslog' or 'php' on line %zu", kw->lineno); + sp_log_err("config", "." SP_TOKEN_LOG_MEDIA "() only supports 'syslog', 'file:' or 'php' on line %zu, got '%s' instead", kw->lineno, ZSTR_VAL(value)); return SP_PARSER_ERROR; } diff --git a/src/sp_utils.c b/src/sp_utils.c index 775ff95..41eb638 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c @@ -43,7 +43,7 @@ void sp_log_msgf(char const* const restrict feature, int level, int type, break; } - switch (SPCFG(log_media)) { + switch (SPCFG(log_media).type) { case SP_LOG_SYSLOG: { const char* error_filename = zend_get_executed_filename(); int syslog_level = (level == E_ERROR) ? LOG_ERR : LOG_INFO; @@ -54,6 +54,20 @@ void sp_log_msgf(char const* const restrict feature, int level, int type, closelog(); break; } + case SP_LOG_FILE: { + FILE* logf = fopen(SPCFG(log_media).path, "a"); + if (!logf) { + zend_error(level, "[snuffleupagus][%s][logging][log] unable to open %s to log", client_ip, + SPCFG(log_media).path); + } else { + int error_lineno = zend_get_executed_lineno(TSRMLS_C); + const char* error_filename = zend_get_executed_filename(); + fprintf(logf, "[snuffleupagus][%s][%s][%s] %s in %s on line %d\n", + client_ip, feature, logtype, msg, error_filename, error_lineno); + fclose(logf); + } + break; + } case SP_LOG_ZEND: default: zend_error(level, "[snuffleupagus][%s][%s][%s] %s", client_ip, feature, diff --git a/src/tests/broken_configuration/broken_conf_invalid_log_media.phpt b/src/tests/broken_configuration/broken_conf_invalid_log_media.phpt index af0d61f..fef055c 100644 --- a/src/tests/broken_configuration/broken_conf_invalid_log_media.phpt +++ b/src/tests/broken_configuration/broken_conf_invalid_log_media.phpt @@ -7,7 +7,7 @@ sp.configuration_file={PWD}/config/broken_conf_invalid_log_media.ini error_log=/dev/null --FILE-- --EXPECTF-- -Fatal error: [snuffleupagus][0.0.0.0][config][log] .log_media() only supports 'syslog' or 'php' on line 1 in Unknown on line 0 +Fatal error: [snuffleupagus][0.0.0.0][config][log] .log_media() only supports 'syslog', 'file:' or 'php' on line 1, got 'pouet' instead in Unknown on line 0 Fatal error: [snuffleupagus][0.0.0.0][config][log] Invalid configuration file in Unknown on line 0 Could not startup. diff --git a/src/tests/syslog_simulation.phpt b/src/tests/syslog_simulation.phpt index 4b12f58..ff78928 100644 --- a/src/tests/syslog_simulation.phpt +++ b/src/tests/syslog_simulation.phpt @@ -9,3 +9,4 @@ sp.configuration_file={PWD}/config/syslog_simulation.ini var_dump(unserialize('s:1:"a";')); ?> --EXPECTF-- +string(1) "a" -- cgit v1.3