App-Info

 view release on metacpan or  search on metacpan

lib/App/Info/HTTPD/Apache.pm  view on Meta::CPAN

=item search_ab_names

=item search_apachectl_names

=item search_apxs_names

=item search_htdigest_names

=item search_htpasswd_names

=item search_logresolve_names

=item search_rotatelogs_names

=back

B<Events:>

=over 4

=item info

Looking for Apache executable

=item confirm

Path to your httpd executable?

=item unknown

Path to your httpd executable?

=back

=cut

sub new {
    # Construct the object.
    my $self = shift->SUPER::new(@_);

    for my $exe (qw(search_conf_dirs search_conf_names),
                 map { "search_$_\_names" } @EXES
    ) {
        if (exists $self->{$exe}) {
            $self->{$exe} = [$self->{$exe}] unless ref $self->{$exe} eq 'ARRAY';
        } else {
            $self->{$exe} = [];
        }
    }

    # Find Apache executable.
    $self->info("Looking for Apache executable");

    my @paths = $self->search_bin_dirs;
    my @exes  = $self->search_exe_names;

    if (my $exe = $u->first_cat_exe(\@exes, @paths)) {
        # We found httpd. Confirm.
        $self->{executable} = $self->confirm(
            key      => 'path to httpd',
            prompt   => 'Path to your httpd executable?',
            value    => $exe,
            callback => sub { -x },
            error    => 'Not an executable',
        );
    } else {
        # Handle an unknown value.
        $self->{executable} = $self->unknown(
            key      => 'path to httpd',
            prompt   => 'Path to your httpd executable?',
            callback => sub { -x },
            error    => 'Not an executable',
        );
    }
    return $self;
};

##############################################################################

=head2 Class Method

=head3 key_name

  my $key_name = App::Info::HTTPD::Apache->key_name;

Returns the unique key name that describes this class. The value returned is
the string "Apache".

=cut

sub key_name { 'Apache' }

##############################################################################

=head2 Object Methods

=head3 installed

  print "apache is ", ($apache->installed ? '' : 'not '),
    "installed.\n";

Returns true if Apache is installed, and false if it is not.
App::Info::HTTPD::Apache determines whether Apache is installed based on the
presence or absence of the F<httpd> application on the file system, as found
when C<new()> constructed the object. If Apache does not appear to be
installed, then all of the other object methods will return empty values.

=cut

sub installed { return $_[0]->{executable} ? 1 : undef }

##############################################################################

=head3 name

  my $name = $apache->name;

Returns the name of the application. App::Info::HTTPD::Apache parses the name
from the system call C<`httpd -v`>.

B<Events:>

=over 4

=item info

Executing `httpd -v`

=item error

lib/App/Info/HTTPD/Apache.pm  view on Meta::CPAN

}

##############################################################################

=head3 conf_file

Returns the full path to the Apache configuration file. C<conf_file()> looks
for the configuration file in a number of locations and under a number of
names. First it tries to use the file specified by the C<SERVER_CONFIG_FILE>
compile option (as returned by a call to C<compile_option()>) -- and if it's a
relative file name, it gets appended to the directory returned by
C<httpd_root()>. If that file isn't found, C<conf_file()> then looks for a
file with one of the names returned by C<search_conf_names()> in the F<conf>
subdirectory of the HTTPD root directory. Failing that, it searches for them
in each of the directories returned by C<search_conf_dirs()> until it finds a
match.

B<Events:>

=over 4

=item info

Searching for Apache configuration file

=item error

No Apache config file found

=item unknown

Location of httpd.conf file?

=back

=cut

sub conf_file {
    my $self = shift;
    return unless $self->{executable};
    unless (exists $self->{conf_file}) {
        $self->info("Searching for Apache configuration file");
        my $root = $self->httpd_root;
        my $conf = $self->compile_option('SERVER_CONFIG_FILE');
        $conf = $u->file_name_is_absolute($conf) ?
          $conf : $u->catfile($root, $conf) if $conf;
        if ($conf && -f $conf) {
            $self->{conf_file} = $conf;
        } else {
            # Paths to search.
            my @confs = $self->search_conf_names;

            $self->{conf_file} = $u->first_cat_path(\@confs, $self->search_conf_dirs)
              or $self->error("No Apache config file found");
        }
    }

    # Handle an unknown value.
    $self->{conf_file} =
      $self->unknown( key      => 'apache conf file',
                      prompt   => "Location of httpd.conf file?",
                      callback => sub { -f },
                      error    => "Not a file")
      unless defined $self->{conf_file};
    return $self->{conf_file};
}

##############################################################################

=head3 user

  my $user = $apache->user;

Returns the name of the Apache user. This value is collected from the Apache
configuration file as returned by C<conf_file()>.

B<Events:>

=over 4

=item info

Searching for Apache configuration file

Executing `httpd -V`

Parsing Apache configuration file

=item error

No Apache config file found

Cannot parse user from file

Cannot parse group from file

Cannot parse port from file

Cannot parse DocumentRoot from file

=item unknown

Location of httpd.conf file?

Enter Apache user name

=back

=cut

# This code reference parses the Apache configuration file. It is called by
# user(), group(), or port(), whichever gets called first.
my $parse_conf_file = sub {
    my $self = shift;
    return if exists $self->{user};
    $self->{user} = undef;
    # Find the configuration file.
    my $conf = $self->conf_file or return;

    $self->info("Parsing Apache configuration file");

    # This is the place to add more regexes to collect stuff from the
    # config file in the future.
    my @regexen = (
        qr/^\s*User\s+(.*)$/,
        qr/^\s*Group\s+(.*)$/,
        qr/^\s*Port\s+(.*)$/,
        qr/^\s*DocumentRoot\s+"?([^"]+)"?\s*$/,
        qr/^\s*ScriptAlias\s+(  \S+?)\s"?(?:[^"\r\n]+)"?\s*$/x,
        qr/^\s*ScriptAlias\s+(?:\S+?)\s"?(  [^"\r\n]+)"?\s*$/x,
    );
    my ($usr, $grp, $prt, $droot, $cgibinv, $cgibinp) = $u->multi_search_file($conf, @regexen);
    # Issue a warning if we couldn't find the user and group.
    $self->error("Cannot parse user from file '$conf'") unless $usr;
    $self->error("Cannot parse group from file '$conf'") unless $grp;
    $self->error("Cannot parse port from file '$conf'") unless $prt;
    $self->error("Cannot parse DocumentRoot from file '$conf'") unless $droot;
    $self->error("Cannot parse ScriptAlias from file '$conf'") if (! ($cgibinv && $cgibinp));
    # Assign them anyway.
    @{$self}{qw(user group port doc_root cgibinv cgibinp)} = ($usr, $grp, $prt, $droot, $cgibinv, $cgibinp);
};

sub user {
    my $self = shift;
    return unless $self->{executable};
    $parse_conf_file->($self) unless exists $self->{user};
    # Handle an unknown value.
    $self->{user} = $self->unknown( key      => 'apache user',
                                    prompt   => 'Enter Apache user name',
                                    callback => sub { getpwnam $_ },
                                    error    => "Not a user")
      unless $self->{user};
    return $self->{user};
}

##############################################################################

=head3 group

Returns the name of the Apache user group. This value is collected from the
Apache configuration file as returned by C<conf_file()>.

B<Events:>

=over 4

=item info

Searching for Apache configuration file

Executing `httpd -V`

Parsing Apache configuration file

=item error

No Apache config file found

Cannot parse user from file

Cannot parse group from file

Cannot parse port from file

Cannot parse DocumentRoot from file

=item unknown

Location of httpd.conf file?

Enter Apache user group name

=back

=cut

sub group {
    my $self = shift;
    return unless $self->{executable};
    $parse_conf_file->($self) unless exists $self->{group};
    # Handle an unknown value.
    $self->{group} =
      $self->unknown( key       => 'apache group',
                      prompt    => 'Enter Apache user group name',
                      callback  => sub { getgrnam $_ },
                      error     => "Not a user group")
      unless $self->{group};
    return $self->{group};
}

##############################################################################

=head3 port

Returns the port number on which Apache listens. This value is collected from
Apache configuration file as returned by C<conf_file()>.

B<Events:>

=over 4

=item info

Searching for Apache configuration file

Executing `httpd -V`

Parsing Apache configuration file

=item error

No Apache config file found

Cannot parse user from file

Cannot parse group from file

Cannot parse port from file

Cannot parse DocumentRoot from file

=item unknown

Location of httpd.conf file?

Enter Apache TCP/IP port number

=back

=cut

sub port {
    my $self = shift;
    return unless $self->{executable};
    $parse_conf_file->($self) unless exists $self->{port};
    # Handle an unknown value.
    $self->{port} =
      $self->unknown( key      => 'apache port',
                      prompt   => 'Enter Apache TCP/IP port number',
                      callback => $is_int,
                      error    => "Not a valid port number")
      unless $self->{port};
    return $self->{port};
}

##############################################################################

=head3 doc_root

Returns the local physical path where web pages are stored. This value is
collected from Apache configuration file as returned by C<conf_file()>.

B<Events:>

=over 4

=item info

Searching for Apache configuration file

Executing `httpd -V`

Parsing Apache configuration file

=item error

No Apache config file found

Cannot parse user from file

Cannot parse group from file

Cannot parse port from file

Cannot parse DocumentRoot from file

=item unknown

Location of httpd.conf file?

Enter DocumentRoot actual directory

=back

=cut

sub doc_root {
    my $self = shift;
    return unless $self->{executable};
    $parse_conf_file->($self) unless exists $self->{doc_root};
    # Handle an unknown value.
    $self->{doc_root} = $self->unknown(
        key      => 'doc root',
        prompt   => 'Enter DocumentRoot directory',
        callback => $is_dir,
        error    => "Not a directory"
    ) unless $self->{doc_root};
    return $self->{doc_root};
} # doc_root

##############################################################################

=head3 cgibin_virtual

Returns the virtual path where cgi-bin programs are stored. This value is
collected from Apache configuration file as returned by C<conf_file()>.

B<Events:>

=over 4

=item info

Searching for Apache configuration file

Executing `httpd -V`

Parsing Apache configuration file

=item error

No Apache config file found

Cannot parse user from file

Cannot parse group from file

Cannot parse port from file

Cannot parse ScriptAlias from file

=item unknown

Location of httpd.conf file?

Enter ScriptAlias virtual directory

=back

=cut

sub cgibin_virtual {
    my $self = shift;
    return unless $self->{executable};
    $parse_conf_file->($self) unless exists $self->{cgibinv};
    # Handle an unknown value.
    $self->{cgibinv} = $self->unknown(
        key      => 'virtual cgi-bin',
        prompt   => 'Enter ScriptAlias (cgi-bin) virtual directory',
        callback => $is_dir,
        error    => "Not a directory"
    ) unless $self->{cgibinv};
    return $self->{cgibinv};
}

##############################################################################

=head3 cgibin_physical

Returns the physical path where cgi-bin programs are stored. This value is
collected from Apache configuration file as returned by C<conf_file()>.

B<Events:>

=over 4

=item info

Searching for Apache configuration file

Executing `httpd -V`

Parsing Apache configuration file

=item error

No Apache config file found

Cannot parse user from file

Cannot parse group from file

Cannot parse port from file

Cannot parse ScriptAlias from file

=item unknown

Location of httpd.conf file?

Enter ScriptAlias physical directory

=back

=cut

sub cgibin_physical {
    my $self = shift;
    return unless $self->{executable};
    $parse_conf_file->($self) unless exists $self->{cgibinp};
    # Handle an unknown value.
    $self->{cgibinp} = $self->unknown(
        key      => 'physical cgi-bin',
        prompt   => 'Enter ScriptAlias (cgi-bin) physical directory',
        callback => $is_dir,
        error    => "Not a directory"
    ) unless $self->{cgibinp};
    return $self->{cgibinp};
}

##############################################################################

=head3 executable

  my $executable = $apache->executable;

Returns the path to the Apache executable, which will be defined by one of the
names returned by C<search_exe_names()>. The executable is searched for in
C<new()>, so there are no events for this method.

=head3 httpd

  my $httpd = $apache->httpd;

An alias for C<executable()>.

=cut

sub executable { shift->{executable} }

##############################################################################

=head3 bin_dir

  my $bin_dir = $apache->bin_dir;

Returns the SQLite binary directory path. App::Info::HTTPD::Apache simply
retrieves it as the directory part of the path to the HTTPD executable.

=cut

sub bin_dir {
    my $self = shift;
    return unless $self->{executable};
    unless (exists $self->{bin_dir} ) {
        my @parts = $u->splitpath($self->{executable});
        $self->{bin_dir} = $u->catdir(
            ($parts[0] eq '' ? () : $parts[0]),
            $u->splitdir($parts[1])
        );
    }
    return $self->{bin_dir};
}

##############################################################################

=head3 inc_dir

  my $inc_dir = $apache->inc_dir;

Returns the Apache include directory path. App::Info::HTTPD::Apache simply
looks for the F<include> or F<inc> directory under the F<httpd_root>
directory, as returned by C<httpd_root()>.

lib/App/Info/HTTPD/Apache.pm  view on Meta::CPAN

=item logresolve

=item rotatelogs

=back

And the corresponding search names methods are:

=over

=item search_ab_names

=item search_apachectl_names

=item search_apxs_names

=item search_htdigest_names

=item search_htpasswd_names

=item search_logresolve_names

=item search_rotatelogs_names

=back

B<Events:>

=over 4

=item info

Looking for executable

=item confirm

Path to executable?

=item unknown

Path to executable?

=back

=cut

my $find_exe = sub  {
    my ($self, $key) = @_;
    my $exe = $key . (WIN32 ? '.exe' : '');
    my $meth = "search_$key\_names";

    # Find executable.
    $self->info("Looking for $key");

    unless ($self->{$key}) {
        my $bin = $self->bin_dir or return;
        if (my $exe = $u->first_cat_exe([$self->$meth(), $exe], $bin)) {
            # We found it. Confirm.
            $self->{$key} = $self->confirm(
                key      => "path to $key",
                prompt   => "Path to $key executable?",
                value    => $exe,
                callback => sub { -x },
                error    => 'Not an executable'
            );
        } else {
            # Handle an unknown value.
            $self->{$key} = $self->unknown(
                key      => "path to $key",
                prompt   => "Path to $key executable?",
                callback => sub { -x },
                error    => 'Not an executable'
            );
        }
    }

    return $self->{$key};
};

for my $exe (@EXES) {
    no strict 'refs';
    *{$exe} = sub { shift->$find_exe($exe) };
    *{"search_$exe\_names"} = sub { @{ shift->{"search_$exe\_names"} } }
}

*httpd = \&executable;

1;
__END__

=head1 KNOWN ISSUES

It's likely that a lot more can be done to collect data about Apache. The
methodology for determining the lib, inc, bin, and so_lib directories in
particular may be considered rather weak. And the Port number can be specified
multiple ways (and times!) in an Apache configuration file. Patches from those
who know a great deal more about interrogating Apache will be most welcome.

=head1 TO DO

Add method to return the names of available DSOs. These should either be
parsed from the F<httpd.conf> file or C<glob>bed from the file system.

=head1 SUPPORT

This module is stored in an open L<GitHub
repository|http://github.com/theory/app-info/>. Feel free to fork and
contribute!

Please file bug reports via L<GitHub
Issues|http://github.com/theory/app-info/issues/> or by sending mail to
L<bug-App-Info@rt.cpan.org|mailto:bug-App-Info@rt.cpan.org>.

=head1 AUTHOR

David E. Wheeler <david@justatheory.com> based on code by Sam Tregar
<sam@tregar.com>.

=head1 SEE ALSO

L<App::Info|App::Info> documents the event handling interface.

L<App::Info::HTTPD|App::Info::HTTPD> is the App::Info::HTTP::Apache parent
class.

L<Apache|Apache> and L<mod_perl_mod_perl> document mod_perl.

L<http://httpd.apache.org/> is the Apache web server home page.

L<http://perl.apache.org/> is the mod_perl home page.



( run in 1.439 second using v1.01-cache-2.11-cpan-6aa56a78535 )