<commit_before>#include <stdint.h>
#include <ap_config.h>
#include <http_core.h>
#include <http_log.h>
#include <apr_version.h>
#include <apr_pools.h>
#include <apr_strings.h>
#include "unixd.h"

#if APR_HAS_SHARED_MEMORY
#include "apr_rmm.h"
#include "apr_shm.h"
#else
#error "APR_HAS_SHARED_MEMORY required for upload_progress module"
#endif

#if APR_HAVE_UNISTD_H
#include <unistd.h>
#endif

#include "ap_backports.h"

#ifndef PROGRESS_ID
#  define PROGRESS_ID "X-Progress-ID"
#endif
#ifndef JSON_CB_PARAM
#  define JSON_CB_PARAM "callback"
#endif
#ifndef CACHE_FILENAME
#  define CACHE_FILENAME "/tmp/upload_progress_cache"
#endif
#ifndef PROGRESS_EXPIRES
/* shared memory entries not updated in PROGRESS_EXPIRES seconds
   will be reused when needed */
#  define PROGRESS_EXPIRES 60
#endif
#ifndef UP_DEBUG
#  define UP_DEBUG 0
#endif

#ifndef ARG_ALLOWED_PROGRESSID
#  define ARG_ALLOWED_PROGRESSID "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_:./!{}"
#endif
#ifndef ARG_ALLOWED_JSONPCALLBACK
#  define ARG_ALLOWED_JSONPCALLBACK "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._$"
#endif
#ifndef ARG_MINLEN_PROGRESSID
#  define ARG_MINLEN_PROGRESSID 8
#endif
#ifndef ARG_MAXLEN_PROGRESSID
#  define ARG_MAXLEN_PROGRESSID 128
#endif
#ifndef ARG_MINLEN_JSONPCALLBACK
#  define ARG_MINLEN_JSONPCALLBACK 1
#endif
#ifndef ARG_MAXLEN_JSONPCALLBACK
/* This limit is set by most JS implementations on identifier length */
#  define ARG_MAXLEN_JSONPCALLBACK 64
#endif

#if UP_DEBUG > 0
#  if UP_DEBUG > 1
#    define up_log(m,s,err,srv,fmtstr,...) ap_log_error( m, s, err, srv, "pid:%" APR_PID_T_FMT " " fmtstr, getpid(), ##__VA_ARGS__ )
#  else
#    define up_log(...) ap_log_error( __VA_ARGS__ )
#  endif
#else
#  define up_log(...)
#endif

#define CACHE_LOCK() do {                                  \
    if (config->cache_lock) {                              \
        char errbuf[200];                                  \
        up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "CACHE_LOCK()"); \
        apr_status_t status = apr_global_mutex_lock(config->cache_lock);        \
        if (status != APR_SUCCESS) {                          \
            ap_log_error(APLOG_MARK, APLOG_CRIT, status, server, \
                       "%s", apr_strerror(status, errbuf, sizeof(errbuf))); \
        }                                                  \
    } \
} while (0)

#define CACHE_UNLOCK() do {                                \
    if (config->cache_lock)                               \
    {	\
        up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "CACHE_UNLOCK()"); \
        apr_global_mutex_unlock(config->cache_lock);      \
    }	\
} while (0)

typedef struct {
    int track_enabled;
    int report_enabled;
} DirConfig;

typedef struct upload_progress_node_s{
    apr_off_t length;
    apr_off_t received;
    int err_status;
    time_t started_at;
    apr_off_t speed; /* bytes per second */
    time_t updated_at;
    int done;
    char key[ARG_MAXLEN_PROGRESSID];
} upload_progress_node_t;

typedef struct {
    int count;
    int active;
} upload_progress_cache_t;

typedef struct {
    apr_global_mutex_t *cache_lock;
    char *lock_file;           /* filename for shm lock mutex */
    apr_size_t cache_bytes;
    apr_shm_t *cache_shm;
    char *cache_file;
    upload_progress_cache_t *cache;
    int *list; /* static array of node indexes, list begins with indexes of active nodes */
    upload_progress_node_t *nodes; /* all nodes allocated at once */
} ServerConfig;

static upload_progress_node_t* insert_node(request_rec *r, const char *key);
static upload_progress_node_t *store_node(ServerConfig *config, const char *key);
static upload_progress_node_t *find_node(request_rec *r, const char *key);
static void clean_old_connections(request_rec *r);
static void fill_new_upload_node_data(upload_progress_node_t *node, request_rec *r);
static apr_status_t upload_progress_cleanup(void *data);
static const char *get_progress_id(request_rec *, int *);

extern module AP_MODULE_DECLARE_DATA upload_progress_module;

static server_rec *global_server = NULL;

static inline ServerConfig *get_server_config(server_rec *s)
{
    return (ServerConfig *)ap_get_module_config(s->module_config, &upload_progress_module);
}

static inline DirConfig *get_dir_config(request_rec *r)
{
    return (DirConfig *)ap_get_module_config(r->per_dir_config, &upload_progress_module);
}

static int upload_progress_handle_request(request_rec *r)
{
    server_rec *server = r->server;
/**/up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "upload_progress_handle_request()");

    DirConfig *dir = get_dir_config(r);
    ServerConfig *config = get_server_config(server); /* for CACHE_LOCK */

    if (!dir || (dir->track_enabled <= 0)) {
        return DECLINED;
    }
    if (r->method_number != M_POST) {
        return DECLINED;
    }

    int param_error;
    const char *id = get_progress_id(r, &param_error);

    if (id) {<commit_msg>Report non-POST requests when extensive debugging is enabled.<commit_after>#include <stdint.h>
#include <ap_config.h>
#include <http_core.h>
#include <http_log.h>
#include <apr_version.h>
#include <apr_pools.h>
#include <apr_strings.h>
#include "unixd.h"

#if APR_HAS_SHARED_MEMORY
#include "apr_rmm.h"
#include "apr_shm.h"
#else
#error "APR_HAS_SHARED_MEMORY required for upload_progress module"
#endif

#if APR_HAVE_UNISTD_H
#include <unistd.h>
#endif

#include "ap_backports.h"

#ifndef PROGRESS_ID
#  define PROGRESS_ID "X-Progress-ID"
#endif
#ifndef JSON_CB_PARAM
#  define JSON_CB_PARAM "callback"
#endif
#ifndef CACHE_FILENAME
#  define CACHE_FILENAME "/tmp/upload_progress_cache"
#endif
#ifndef PROGRESS_EXPIRES
/* shared memory entries not updated in PROGRESS_EXPIRES seconds
   will be reused when needed */
#  define PROGRESS_EXPIRES 60
#endif
#ifndef UP_DEBUG
#  define UP_DEBUG 0
#endif

#ifndef ARG_ALLOWED_PROGRESSID
#  define ARG_ALLOWED_PROGRESSID "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_:./!{}"
#endif
#ifndef ARG_ALLOWED_JSONPCALLBACK
#  define ARG_ALLOWED_JSONPCALLBACK "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._$"
#endif
#ifndef ARG_MINLEN_PROGRESSID
#  define ARG_MINLEN_PROGRESSID 8
#endif
#ifndef ARG_MAXLEN_PROGRESSID
#  define ARG_MAXLEN_PROGRESSID 128
#endif
#ifndef ARG_MINLEN_JSONPCALLBACK
#  define ARG_MINLEN_JSONPCALLBACK 1
#endif
#ifndef ARG_MAXLEN_JSONPCALLBACK
/* This limit is set by most JS implementations on identifier length */
#  define ARG_MAXLEN_JSONPCALLBACK 64
#endif

#if UP_DEBUG > 0
#  if UP_DEBUG > 1
#    define up_log(m,s,err,srv,fmtstr,...) ap_log_error( m, s, err, srv, "pid:%" APR_PID_T_FMT " " fmtstr, getpid(), ##__VA_ARGS__ )
#  else
#    define up_log(...) ap_log_error( __VA_ARGS__ )
#  endif
#else
#  define up_log(...)
#endif

#define CACHE_LOCK() do {                                  \
    if (config->cache_lock) {                              \
        char errbuf[200];                                  \
        up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "CACHE_LOCK()"); \
        apr_status_t status = apr_global_mutex_lock(config->cache_lock);        \
        if (status != APR_SUCCESS) {                          \
            ap_log_error(APLOG_MARK, APLOG_CRIT, status, server, \
                       "%s", apr_strerror(status, errbuf, sizeof(errbuf))); \
        }                                                  \
    } \
} while (0)

#define CACHE_UNLOCK() do {                                \
    if (config->cache_lock)                               \
    {	\
        up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "CACHE_UNLOCK()"); \
        apr_global_mutex_unlock(config->cache_lock);      \
    }	\
} while (0)

typedef struct {
    int track_enabled;
    int report_enabled;
} DirConfig;

typedef struct upload_progress_node_s{
    apr_off_t length;
    apr_off_t received;
    int err_status;
    time_t started_at;
    apr_off_t speed; /* bytes per second */
    time_t updated_at;
    int done;
    char key[ARG_MAXLEN_PROGRESSID];
} upload_progress_node_t;

typedef struct {
    int count;
    int active;
} upload_progress_cache_t;

typedef struct {
    apr_global_mutex_t *cache_lock;
    char *lock_file;           /* filename for shm lock mutex */
    apr_size_t cache_bytes;
    apr_shm_t *cache_shm;
    char *cache_file;
    upload_progress_cache_t *cache;
    int *list; /* static array of node indexes, list begins with indexes of active nodes */
    upload_progress_node_t *nodes; /* all nodes allocated at once */
} ServerConfig;

static upload_progress_node_t* insert_node(request_rec *r, const char *key);
static upload_progress_node_t *store_node(ServerConfig *config, const char *key);
static upload_progress_node_t *find_node(request_rec *r, const char *key);
static void clean_old_connections(request_rec *r);
static void fill_new_upload_node_data(upload_progress_node_t *node, request_rec *r);
static apr_status_t upload_progress_cleanup(void *data);
static const char *get_progress_id(request_rec *, int *);

extern module AP_MODULE_DECLARE_DATA upload_progress_module;

static server_rec *global_server = NULL;

static inline ServerConfig *get_server_config(server_rec *s)
{
    return (ServerConfig *)ap_get_module_config(s->module_config, &upload_progress_module);
}

static inline DirConfig *get_dir_config(request_rec *r)
{
    return (DirConfig *)ap_get_module_config(r->per_dir_config, &upload_progress_module);
}

static int upload_progress_handle_request(request_rec *r)
{
    server_rec *server = r->server;
/**/up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "upload_progress_handle_request()");

    DirConfig *dir = get_dir_config(r);
    ServerConfig *config = get_server_config(server); /* for CACHE_LOCK */

    if (!dir || (dir->track_enabled <= 0)) {
        return DECLINED;
    }
    if (r->method_number != M_POST) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server,
                     "Upload Progress: Non-POST request in trackable location: %s.", r->uri);
        return DECLINED;
    }

    int param_error;
    const char *id = get_progress_id(r, &param_error);

    if (id) {
{'fraction_non_alphanumeric': 0.09728395061728395, 'fraction_numerical': 0.008197530864197531, 'mean_word_length': 3.514489522960321, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '620765', 'n_tokens_mistral': 3679, 'n_tokens_neox': 3568, 'n_words': 780}