Revision 3 (by ahitrov@rambler.ru, 2010/03/24 15:19:32) |
The CORE
|
package Contenido::Apache;
# ----------------------------------------------------------------------------
# ����� ����� ��������� ��� �������� Apache...
# ----------------------------------------------------------------------------
use strict;
use warnings;
use locale;
use vars qw($VERSION);
$VERSION = '7.0';
use Apache::Constants;
use Apache::Request;
use Contenido::Globals;
use Contenido::Project;
use Contenido::Request;
use Contenido::State;
use Contenido::Keeper;
use Contenido::Object;
use Contenido::User;
use Contenido::Document;
use Contenido::Section;
use Contenido::Link;
use Contenido::Init;
use Contenido::Logger;
# ----------------------------------------------------------------------------
# �������, ������� ����������� ��� ������ ������� ������ ��������� ��������
# web-�������.
# ----------------------------------------------------------------------------
sub child_init {
my $r = shift;
$log->info("������������ �������� ��������� �������� Apache") if $DEBUG;
my $project_keeper_module;
eval {
$project_keeper_module=$state->project().'::Keeper';
$keeper = $project_keeper_module->new($state);
};
if ($@) {
$log->error("�� ���� ���������������� $project_keeper_module ��-��: $@");
die;
}
for my $plugin ($state->project, split(/\s+/, $state->plugins)) {
my $class = $plugin.'::Apache';
eval { $class->child_init($r); };
if ( $@ ) {
$log->error("�� ���� ��������� ����� child_init ������� $plugin ($class) �� ������� '$@'");
}
}
return OK;
}
# ----------------------------------------------------------------------------
# �������, ������� ����������� � ����� ������ ��������� ������� ������������.
# ----------------------------------------------------------------------------
sub request_init {
my $r = shift;
$r = ref($r) eq 'Apache::Request' ? $r : Apache::Request->instance($r);
my $URI = $r->uri;
my $ARGS = $r->args;
$log->info("������ ��������� ������� ".$URI.($ARGS ? "?$ARGS":'')) if $DEBUG;
$state->_refresh_();
$request = Contenido::Request->new($state);
if ($DEBUG) {
$request->{_start} = Time::HiRes::time();
$Contenido::Globals::DB_TIME = 0;
$Contenido::Globals::CORE_TIME = 0;
$Contenido::Globals::DB_COUNT = 0;
$Contenido::Globals::RPC_TIME = 0;
}
if (ref($r)) {
my %headers = $r->headers_in();
my $ip = $headers{'X-Real-IP'} ? $headers{'X-Real-IP'} : $r->connection->remote_ip();
my @ips = split(/\s*,\s*/, $ip);
$ip = $ips[ $#ips ];
$request->set_properties (
'uri' => $URI||'',
'query' => $r->args()||'',
'ip' => $ip||'',
'user' => $r->connection->user()||'',
'http_host' => $ENV{HTTP_HOST},
'r' => $r,
)
}
$project->restore($keeper);
for my $plugin ($state->project, split(/\s+/, $state->plugins)) {
my $class = $plugin.'::Apache';
eval { $class->request_init($r); };
if ( $@ ) {
$log->error("�� ���� ��������� ����� request_init ������� $plugin ($class) �� ������� '$@'");
}
}
return OK;
}
sub is_valid_request {
my $r = shift;
if ($r->uri =~ /^(?:\/i\/|\/images\/|\/binary\/)/ or ($r->content_type && $r->content_type !~ m#(?:^text/|javascript|json|^httpd/unix-directory)#i)) {
return 0;
} else {
return 1;
}
}
#���������� ������� (������������ ����� ������ ������... ��� ��� ����� ��� ������ ��������������� ��� ����� ���������� ����������
sub cleanup {
my $r = shift;
#����� ���������� ���������� �������
$user = undef;
$session = undef;
return Apache::Constants::DECLINED unless Contenido::Apache::is_valid_request($r);
#��������� ���������� ������ � memcached
if ($state->{memcached_enable} and $request->{_to_memcache}) {
while ( my ($key, $values) = each(%{$request->{_to_memcache}}) ) {
my ($value, $expire, $mode) = @$values;
if (ref($key) or !$key) {
$log->warning("bad key value in set ($key)");
next;
}
$mode ||= 'set';
if ($mode eq 'add') {
$keeper->{MEMD}->add($key, $value, $expire);
} elsif ($mode eq 'delete') {
$keeper->{MEMD}->delete($key);
#�� ��������� set
} else {
$keeper->{MEMD}->set($key, $value, $expire);
}
}
}
for my $plugin ($state->project, split(/\s+/, $state->plugins)) {
my $class = $plugin.'::Apache';
next unless ($class->can('cleanup'));
eval { $class->cleanup($r); };
if ( $@ ) {
$log->error("�� ���� ��������� ����� request_init ������� $plugin ($class) �� ������� '$@'");
}
}
# ������������� �� ���� ������� � ��������
# (���� �� ������������ ���������� �����������)
# ����� ���������� ������������ �������� �������������� ����������
unless ($state->db_type eq 'none') {
$keeper->shutdown unless $state->db_keepalive;
$keeper->{_connect_ok} = 0;
$keeper->t_shutdown(1);
}
for (split /\s+/, $state->plugins) {
next unless $keeper->{$_};
next if $state->{$_}->db_type eq 'none';
$keeper->{$_}->shutdown unless $state->{$_}->db_keepalive;
$keeper->{$_}->{_connect_ok} = 0;
$keeper->{$_}->t_shutdown(1);
}
if ($DEBUG) {
my $finish = Time::HiRes::time();
my $time = int(10000*($finish-$request->{_start}))/10;
my $db_time = int(10000*($Contenido::Globals::DB_TIME)/10);
my $core_time = int(10000*($Contenido::Globals::CORE_TIME)/10);
my $rpc_time = int(10000*($Contenido::Globals::RPC_TIME)/10);
$log->info("DEBUG: $$ ".__PACKAGE__." ".scalar(localtime())." ".($r->uri || '').($r->args ? '?'.$r->args : '')." worked $time ms, database time $db_time ms, rpc time $rpc_time ms, core time: $core_time ms, db requests count: $Contenido::Globals::DB_COUNT");
}
$request = undef;
return OK;
}
# ----------------------------------------------------------------------------
# �������, ������� ����������� ��� ��������� ������ ��������� ��������
# web-�������...
# ----------------------------------------------------------------------------
sub child_exit {
my $r = shift;
for my $plugin ($state->project, split(/\s+/, $state->plugins)) {
my $class = $plugin.'::Apache';
eval { $class->child_exit($r); };
if ( $@ ) {
$log->error("�� ���� ��������� ����� child_exit ������� $plugin ($class) �� ������� '$@'");
}
}
unless ($state->db_type eq 'none') {
$keeper->shutdown;
}
$log->info("������������ ������ ��������� �������� Apache.") if ($DEBUG);
return OK;
}
# ----------------------------------------------------------------------------
# ������� ��� ��������������.
# - ���� ��� �������� ��� ������������� ����������, �� ������
# ������������� ������ ���� ������� 1 (���������)
# ----------------------------------------------------------------------------
sub authentication {
my $r = shift;
return Apache::Constants::DECLINED unless Contenido::Apache::is_valid_request($r);
return FORBIDDEN if $state->db_type eq 'none';
my ($res, $sent_pw) = $r->get_basic_auth_pw();
return $res if $res != OK;
my $username = $r->connection->user();
$keeper->db_connect unless $keeper->is_connected;
$user = $keeper->get_user_by_login($username);
$keeper->shutdown unless $state->db_keepalive;
if (ref($user) && ($user->login() eq $username) && ($user->passwd() eq $sent_pw) && $user->passwd() && $user->status == 1) {
return OK;
} else {
$log->warning("������� ����������� � �������� ����� �����/������ ($username, $sent_pw)");
$r->note_basic_auth_failure();
return AUTH_REQUIRED;
}
}
1;