/*******************************************************************************
 ap_dump.c - Apache debug dump functions

 Copyright (C) 2020-2026 CodeShop B.V.
 http://www.code-shop.com

 For licensing see the LICENSE file
******************************************************************************/

#include <apr_strings.h>
#include <apr_uri.h>
#include <httpd.h>
#include <inttypes.h>

#include "ap_dump.h"

#if AP_SERVER_MAJORVERSION_NUMBER > 2 || \
   (AP_SERVER_MAJORVERSION_NUMBER == 2 && AP_SERVER_MINORVERSION_NUMBER >= 4)
#define APACHE24
#endif

char *dump_apr_uri_t(apr_pool_t* pool, apr_uri_t const* u)
{
  return u == NULL ? "NULL apr_uri_t" : apr_psprintf(pool,
    "apr_uri_t at %pp:"
    " scheme=%s"
    " hostinfo=%s"
    " user=%s"
    " password=%s"
    " hostname=%s"
    " port_str=%s"
    " path=%s"
    " query=%s"
    " fragment=%s"
    " is_initialized=%u",
    u,
    u->scheme,
    u->hostinfo,
    u->user,
    u->password,
    u->hostname,
    u->port_str,
    u->path,
    u->query,
    u->fragment,
    u->is_initialized);
}

typedef struct
{
  apr_pool_t* pool;
  char* buf;
} pb_t;

static int table_handler(void *rec, const char *key, const char *value)
{
  pb_t* pb = rec;
  if(pb->buf == NULL)
  {
    pb->buf = apr_psprintf(pb->pool, "%s=%s", key, value);
  }
  else
  {
    pb->buf = apr_psprintf(pb->pool, "%s, %s=%s", pb->buf, key, value);
  }
  return !0;
}

char* dump_apr_table_t(apr_pool_t* pool, apr_table_t const* t)
{
  if(apr_is_empty_table(t))
  {
    return apr_pstrdup(pool, "<empty>");
  }
  else
  {
    pb_t pb = { pool, NULL };
    apr_table_do(table_handler, &pb, t, NULL);
    return pb.buf;
  }
}

char* dump_request_rec(apr_pool_t* pool, request_rec const* r)
{
  return r == NULL ? "NULL request_rec" : apr_psprintf(pool,
    "request_rec at %pp:"
    " pool=%pp"
    " connection=%pp"
    " server=%pp"
    " main=%pp"
    " the_request=%s"
    " proxyreq=%d"
    " header_only=%d"
    " proto_num=%d"
    " protocol=%s"
    " hostname=%s"
    " status_line=%s"
    " status=%d"
    " method_number=%d"
    " method=%s"
    " range=%s"
#ifdef APACHE24
    " kept_body=%pp"
#endif
    " headers_in={%s}"
    " headers_out={%s}"
    " subprocess_env={%s}"
    " notes={%s}"
    " content_type=%s"
    " handler=%s"
    " unparsed_uri=%s"
    " uri=%s"
    " filename=%s"
    " canonical_filename=%s"
    " path_info=%s"
    " args=%s"
#ifdef APACHE24
    " log_id=%s"
#endif
    " parsed_uri={%s}",
    r,
    r->pool,
    r->connection,
    r->server,
    r->main,
    r->the_request,
    r->proxyreq,
    r->header_only,
    r->proto_num,
    r->protocol,
    r->hostname,
    r->status_line,
    r->status,
    r->method_number,
    r->method,
    r->range,
#ifdef APACHE24
    r->kept_body,
#endif
    dump_apr_table_t(pool, r->headers_in),
    dump_apr_table_t(pool, r->headers_out),
    dump_apr_table_t(pool, r->subprocess_env),
    dump_apr_table_t(pool, r->notes),
    r->content_type,
    r->handler,
    r->unparsed_uri,
    r->uri,
    r->filename,
    r->canonical_filename,
    r->path_info,
    r->args,
#ifdef APACHE24
    r->log_id,
#endif
    dump_apr_uri_t(pool, &r->parsed_uri));
}

char* dump_server_rec(apr_pool_t* pool, server_rec const* r)
{
  return r == NULL ? "NULL server_rec" : apr_psprintf(pool,
    "server_rec at %pp:"
    " process=%pp"
    " next=%pp"
    " error_fname=%s"
    " error_log=%pp"
#ifdef APACHE24
    " log={%pp,%d}"
#endif
    " module_config=%pp"
    " lookup_defaults=%pp"
    " defn_name=%s"
    " defn_line_number=%u"
    " is_virtual=%d"
    " port=%u"
    " server_scheme=%s"
    " server_admin=%s"
    " server_hostname=%s"
    " addrs=%pp"
    " timeout=%" APR_TIME_T_FMT
    " keep_alive_timeout=%" APR_TIME_T_FMT
    " keep_alive_max=%d"
    " keep_alive=%d"
    " names=%pp"
    " wild_names=%pp"
    " path=%s"
    " pathlen=%d"
    " limit_req_line=%d"
    " limit_req_fieldsize=%d"
    " limit_req_fields=%d"
#ifdef APACHE24
    " context=%pp"
#endif
    ,
    r,
    r->process,
    r->next,
    r->error_fname,
    r->error_log,
#ifdef APACHE24
    r->log.module_levels,
    r->log.level,
#endif
    r->module_config,
    r->lookup_defaults,
    r->defn_name,
    r->defn_line_number,
    r->is_virtual,
    r->port,
    r->server_scheme,
    r->server_admin,
    r->server_hostname,
    r->addrs,
    r->timeout,
    r->keep_alive_timeout,
    r->keep_alive_max,
    r->keep_alive,
    r->names,
    r->wild_names,
    r->path,
    r->pathlen,
    r->limit_req_line,
    r->limit_req_fieldsize,
    r->limit_req_fields
#ifdef APACHE24
    ,
    r->context
#endif
    );
}

// End Of File

