<commit_before>package WWW::Livesite::Apache2;
use strict;
our $VERSION = 0;

# mod_perl
use Apache2::Const -compile => qw(:common :http M_GET M_POST);
use Apache2::Connection ();
use Apache2::ServerRec ();
use Apache2::ServerUtil ();
use Apache2::Access ();
use Apache2::Module ();
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::RequestUtil ();
use Apache2::SubRequest ();
use Apache2::URI ();
use Apache2::Directive;
use Apache2::Response;
use ModPerl::Util;
use APR::Finfo;
use APR::Const -compile => qw(:filetype FINFO_NORM);
use APR::URI;

# libapreq2
use Apache2::Request;
use Apache2::Upload;
use Apache2::Cookie;
use Apache2::Filter;

# CGI
use CGI::Cookie;

# livesite
use Perl::Module;
use Apache2::LogUtil;
use Data::OrderedHash;
use Data::Hub::Util qw(FS path_name);
use WWW::Livesite::Args;
use WWW::Livesite::Parameters;
use WWW::Livesite::Main;
use WWW::Livesite::Session;
use WWW::Livesite::Response;

# error handling
use Error qw(:try);
use Error::Simple;
use Error::Programatic;
use Error::Logical;

# miscellaneous
use Encode;
use JSON::XS;

our %Registry = (); # One Livesite Web Server per VirtualHost per Port
our $Main = undef; # The currently running Livesite Web Server instance
our $Stopwatch = Misc::Stopwatch->new; # For performance timing
our $Log = Apache2::LogUtil->new($Stopwatch); # Formatted apache log messages

# ==============================================================================
# bootstrap - Insert hooks into the current request cycle.
#
# This is a all-in-one easy configuration handler.  To use it:
#
#   PerlTransHandler +WWW::Livesite::Apache2->bootstrap
#
# and all of the other handlers will be added for you.  This ease of
# configuration comes at a cost, that is, each request goes through our handler 
# stack. Additionally, I have seen segmentation faults when trying to add the 
# cleanup handler on older mod_perl2 installations.
# ==============================================================================

sub bootstrap {

  my $r = ref($_[0]) ? $_[0] : $_[1];
  $Stopwatch->reset->start() if $r->is_initial_req;
  _handler_args($r);

  # The request cycle encompasses child requests as well.
  if ($r->is_initial_req) {
    _new_request_cycle($r);
    $r->push_handlers(PerlHeaderParserHandler => \&_header_parser_handler);
  } else {
    $Main->subrequest;
  }

  # The response handler is not invoked until _enable_response_hook is called.
  $r->push_handlers(PerlCleanupHandler => \&_cleanup_handler);
  $r->push_handlers(PerlMapToStorageHandler => \&_map_to_storage_handler);
  $r->push_handlers(PerlFixupHandler => \&_fixup_handler);

  # Allow subsequent trans handlers to run
  return Apache2::Const::DECLINED;

}

# ==============================================================================
# _map_to_storage_handler - Associate URI's which indicate mounted resources.
#
# Mount points act much like the Alias directive.
# ==============================================================================

sub _map_to_storage_handler {

  my $r = _handler_args(@_);

  # Forbidden URIs are set in /conf/handlers/access/forbidden
  return Apache2::Const::FORBIDDEN if $Main->is_forbidden($r->uri);
  return Apache2::Const::DECLINED if $Main->is_ignored($r->uri);

  if (my $node = $Main->get_fs_node($r->uri)) {

    if (isa($node, FS('File'))) {

      # A proper node will be returned even when the uri has erroneous slashes
      # due to how directories are indicated:
      #
      #   /index.html/
      #   /index.html///
      #
      return Apache2::Const::NOT_FOUND unless $r->uri eq $node->get_addr;

      # The requested URI maps to a valid node
      $Log->debug(sprintf('TRACE: Mapped %s to %s', $r->uri, $node->get_path));
      _set_finfo($r, $node->get_path);
      return Apache2::Const::OK;

    }

  }

  return Apache2::Const::DECLINED;

}

# ==============================================================================
# _header_parser_handler - Populate the system table with request information.
# ==============================================================================

sub _header_parser_handler {

  my $r = _handler_args(@_);

  # Parse query-string args into a case-insensitive multiset
  my $args = WWW::Livesite::Args->new($r->args);

  # Scheme and Hostname information of the request URI
  my $req_uri = APR::URI->parse($r->pool, $r->construct_url);

  # Standard request variables
  my $sys_req = $Main->{'sys'}{'request'};
  $sys_req->{'headers'} = $r->headers_in;
  $sys_req->{'qs'} = $args;
  $sys_req->{'hostname'} = $req_uri->hostname;  # example.com
  $sys_req->{'method'} = $r->method;            # GET|POST|...

  # URI Scheme (http|https)
  my $ssl_config = $Main->{'sys'}->get('conf/modules/ssl') || {};
  if ($$ssl_config{'trust_uri_scheme_header'}) {
    my $k = $$ssl_config{'uri_scheme_header_name'} || 'X-URI-Scheme';<commit_msg>Stash client ip/addr in request object<commit_after>package WWW::Livesite::Apache2;
use strict;
our $VERSION = 0;

# mod_perl
use Apache2::Const -compile => qw(:common :http M_GET M_POST);
use Apache2::Connection ();
use Apache2::ServerRec ();
use Apache2::ServerUtil ();
use Apache2::Access ();
use Apache2::Module ();
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::RequestUtil ();
use Apache2::SubRequest ();
use Apache2::URI ();
use Apache2::Directive;
use Apache2::Response;
use ModPerl::Util;
use APR::Finfo;
use APR::Const -compile => qw(:filetype FINFO_NORM);
use APR::URI;

# libapreq2
use Apache2::Request;
use Apache2::Upload;
use Apache2::Cookie;
use Apache2::Filter;

# CGI
use CGI::Cookie;

# livesite
use Perl::Module;
use Apache2::LogUtil;
use Data::OrderedHash;
use Data::Hub::Util qw(FS path_name);
use WWW::Livesite::Args;
use WWW::Livesite::Parameters;
use WWW::Livesite::Main;
use WWW::Livesite::Session;
use WWW::Livesite::Response;

# error handling
use Error qw(:try);
use Error::Simple;
use Error::Programatic;
use Error::Logical;

# miscellaneous
use Encode;
use JSON::XS;

our %Registry = (); # One Livesite Web Server per VirtualHost per Port
our $Main = undef; # The currently running Livesite Web Server instance
our $Stopwatch = Misc::Stopwatch->new; # For performance timing
our $Log = Apache2::LogUtil->new($Stopwatch); # Formatted apache log messages

# ==============================================================================
# bootstrap - Insert hooks into the current request cycle.
#
# This is a all-in-one easy configuration handler.  To use it:
#
#   PerlTransHandler +WWW::Livesite::Apache2->bootstrap
#
# and all of the other handlers will be added for you.  This ease of
# configuration comes at a cost, that is, each request goes through our handler 
# stack. Additionally, I have seen segmentation faults when trying to add the 
# cleanup handler on older mod_perl2 installations.
# ==============================================================================

sub bootstrap {

  my $r = ref($_[0]) ? $_[0] : $_[1];
  $Stopwatch->reset->start() if $r->is_initial_req;
  _handler_args($r);

  # The request cycle encompasses child requests as well.
  if ($r->is_initial_req) {
    _new_request_cycle($r);
    $r->push_handlers(PerlHeaderParserHandler => \&_header_parser_handler);
  } else {
    $Main->subrequest;
  }

  # The response handler is not invoked until _enable_response_hook is called.
  $r->push_handlers(PerlCleanupHandler => \&_cleanup_handler);
  $r->push_handlers(PerlMapToStorageHandler => \&_map_to_storage_handler);
  $r->push_handlers(PerlFixupHandler => \&_fixup_handler);

  # Allow subsequent trans handlers to run
  return Apache2::Const::DECLINED;

}

# ==============================================================================
# _map_to_storage_handler - Associate URI's which indicate mounted resources.
#
# Mount points act much like the Alias directive.
# ==============================================================================

sub _map_to_storage_handler {

  my $r = _handler_args(@_);

  # Forbidden URIs are set in /conf/handlers/access/forbidden
  return Apache2::Const::FORBIDDEN if $Main->is_forbidden($r->uri);
  return Apache2::Const::DECLINED if $Main->is_ignored($r->uri);

  if (my $node = $Main->get_fs_node($r->uri)) {

    if (isa($node, FS('File'))) {

      # A proper node will be returned even when the uri has erroneous slashes
      # due to how directories are indicated:
      #
      #   /index.html/
      #   /index.html///
      #
      return Apache2::Const::NOT_FOUND unless $r->uri eq $node->get_addr;

      # The requested URI maps to a valid node
      $Log->debug(sprintf('TRACE: Mapped %s to %s', $r->uri, $node->get_path));
      _set_finfo($r, $node->get_path);
      return Apache2::Const::OK;

    }

  }

  return Apache2::Const::DECLINED;

}

# ==============================================================================
# _header_parser_handler - Populate the system table with request information.
# ==============================================================================

sub _header_parser_handler {

  my $r = _handler_args(@_);

  # Parse query-string args into a case-insensitive multiset
  my $args = WWW::Livesite::Args->new($r->args);

  # Scheme and Hostname information of the request URI
  my $req_uri = APR::URI->parse($r->pool, $r->construct_url);

  # Standard request variables
  my $sys_req = $Main->{'sys'}{'request'};
  $sys_req->{'headers'} = $r->headers_in;
  $sys_req->{'qs'} = $args;
  $sys_req->{'hostname'} = $req_uri->hostname;  # example.com
  $sys_req->{'method'} = $r->method;            # GET|POST|...
  $sys_req->{'client'} = {
    'ip' => $r->connection->client_ip,
    'addr' => $r->connection->client_addr
  };

  # URI Scheme (http|https)
  my $ssl_config = $Main->{'sys'}->get('conf/modules/ssl') || {};
  if ($$ssl_config{'trust_uri_scheme_header'}) {
    my $k = $$ssl_config{'uri_scheme_header_name'} || 'X-URI-Scheme';
{'fraction_non_alphanumeric': 0.22664918297357273, 'fraction_numerical': 0.006657252370385313, 'mean_word_length': 5.045731707317073, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 100, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4800532', 'n_tokens_mistral': 3185, 'n_tokens_neox': 3026, 'n_words': 807}