File: pseudo_http.pm

package info (click to toggle)
libapache2-mod-perl2 2.0.9~1624218-2%2Bdeb8u2
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 11,912 kB
  • ctags: 4,588
  • sloc: perl: 95,064; ansic: 14,527; makefile: 49; sh: 18
file content (177 lines) | stat: -rw-r--r-- 4,073 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
package TestProtocol::pseudo_http;

# this is a more advanced protocol implementation. While using a
# simplistic socket communication, the protocol uses an almost
# complete HTTP AAA (access and authentication, but not authorization,
# which can be easily added) provided by mod_auth (but can be
# implemented in perl too)
#
# see the protocols.pod document for the explanations of the code

use strict;
use warnings FATAL => 'all';

use Apache2::Connection ();
use Apache2::RequestUtil ();
use Apache2::HookRun ();
use Apache2::Access ();
use APR::Socket ();

use Apache::TestTrace;

use Apache2::Const -compile => qw(OK DONE DECLINED);
use APR::Const -compile => qw(SO_NONBLOCK);

my @cmds = qw(date quit);
my %commands = map { $_, \&{$_} } @cmds;

sub handler {
    my $c = shift;
    my $socket = $c->client_socket;

    if ($socket->opt_get(APR::Const::SO_NONBLOCK)) {
        $socket->opt_set(APR::Const::SO_NONBLOCK => 0);
    }

    if ((my $rc = greet($c)) != Apache2::Const::OK) {
        $socket->send("Say HELO first\n");
        return $rc;
    }

    if ((my $rc = login($c)) != Apache2::Const::OK) {
        $socket->send("Access Denied\n");
        return $rc;
    }

    $socket->send("Welcome to " . __PACKAGE__ .
                  "\nAvailable commands: @cmds\n");

    while (1) {
        my $cmd;
        next unless $cmd = getline($socket);

        if (my $sub = $commands{$cmd}) {
            last unless $sub->($socket) == Apache2::Const::OK;
        }
        else {
            $socket->send("Commands: @cmds\n");
        }
    }

    return Apache2::Const::OK;
}

sub greet {
    my $c = shift;
    my $socket = $c->client_socket;

    $socket->send("HELO\n");
    my $reply = getline($socket) || '';

    return $reply eq 'HELO' ?  Apache2::Const::OK : Apache2::Const::DECLINED;
}

sub login {
    my $c = shift;

    my $r = Apache2::RequestRec->new($c);

    # test whether we can invoke modperl HTTP handlers on the fake $r
    $r->push_handlers(PerlAccessHandler => \&my_access);

    $r->location_merge(__PACKAGE__);

    for my $method (qw(run_access_checker run_check_user_id
                       run_auth_checker)) {

        my $rc = $r->$method();

        if ($rc != Apache2::Const::OK and $rc != Apache2::Const::DECLINED) {
            return $rc;
        }

        last unless $r->some_auth_required;

        unless ($r->user) {
            my $socket = $c->client_socket;

            my $username = prompt($socket, "Login");
            my $password = prompt($socket, "Password");

            $r->set_basic_credentials($username, $password);
        }
    }

    return Apache2::Const::OK;
}

sub my_access {
    # just test that we can invoke a mod_perl HTTP handler
    debug "running my_access";
    return Apache2::Const::OK;
}

sub getline {
    my $socket = shift;

    my $line;
    $socket->recv($line, 1024);
    return unless $line;
    $line =~ s/[\r\n]*$//;

    return $line;
}

sub prompt {
    my ($socket, $msg) = @_;

    $socket->send("$msg:\n");
    getline($socket);
}

sub date {
    my $socket = shift;

    $socket->send("The time is: " . scalar(localtime) . "\n");

    return Apache2::Const::OK;
}

sub quit {
    my $socket = shift;

    $socket->send("Goodbye\n");

    return Apache2::Const::DONE
}

1;
__END__
<NoAutoConfig>
<VirtualHost TestProtocol::pseudo_http>

  PerlProcessConnectionHandler TestProtocol::pseudo_http

  <Location TestProtocol::pseudo_http>

      <IfModule @ACCESS_MODULE@>
          Order Deny,Allow
          Allow from @servername@
      </IfModule>

      <IfModule @AUTH_MODULE@>
          # htpasswd -mbc basic-auth stas foobar
          # using md5 password so it'll work on win32 too
          AuthUserFile @ServerRoot@/htdocs/protocols/basic-auth
      </IfModule>

      AuthName TestProtocol::pseudo_http
      AuthType Basic
      Require user stas
      Satisfy any

  </Location>

</VirtualHost>
</NoAutoConfig>