| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  |  | 
| 2 |  |  |  |  |  |  | ############################################################################# | 
| 3 |  |  |  |  |  |  | ## $Id: HTTP.pm 13887 2010-04-06 13:36:42Z spadkins $ | 
| 4 |  |  |  |  |  |  | ############################################################################# | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | package App::Context::HTTP; | 
| 7 |  |  |  |  |  |  | $VERSION = (q$Revision: 13887 $ =~ /(\d[\d\.]*)/)[0];  # VERSION numbers generated by svn | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 1 |  |  | 1 |  | 5 | use App; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 22 |  | 
| 10 | 1 |  |  | 1 |  | 974 | use App::Context; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 58 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | @ISA = ( "App::Context" ); | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 1 |  |  | 1 |  | 662 | use App::UserAgent; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 28 |  | 
| 15 | 1 |  |  | 1 |  | 6 | use Time::HiRes qw(gettimeofday tv_interval); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 10 |  | 
| 16 | 1 |  |  | 1 |  | 184 | use Date::Format; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 51 |  | 
| 17 |  |  |  |  |  |  |  | 
| 18 | 1 |  |  | 1 |  | 4 | use strict; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 7057 |  | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | =head1 NAME | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | App::Context::HTTP - context in which we are currently running | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | # ... official way to get a Context object ... | 
| 27 |  |  |  |  |  |  | use App; | 
| 28 |  |  |  |  |  |  | $context = App->context(); | 
| 29 |  |  |  |  |  |  | $config = $context->config();   # get the configuration | 
| 30 |  |  |  |  |  |  | $config->dispatch_events();     # dispatch events | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | # ... alternative way (used internally) ... | 
| 33 |  |  |  |  |  |  | use App::Context::HTTP; | 
| 34 |  |  |  |  |  |  | $context = App::Context::HTTP->new(); | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | =cut | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | ############################################################################# | 
| 39 |  |  |  |  |  |  | # DESCRIPTION | 
| 40 |  |  |  |  |  |  | ############################################################################# | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | A Context class models the environment (aka "context) | 
| 45 |  |  |  |  |  |  | in which the current process is running. | 
| 46 |  |  |  |  |  |  | For the App::Context::HTTP class, this models any of the | 
| 47 |  |  |  |  |  |  | web application runtime environments which employ the HTTP protocol | 
| 48 |  |  |  |  |  |  | and produce HTML pages as output.  This includes CGI, mod_perl, FastCGI, | 
| 49 |  |  |  |  |  |  | etc.  The difference between these environments is not in the Context | 
| 50 |  |  |  |  |  |  | but in the implementation of the Request and Response objects. | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | =cut | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | ############################################################################# | 
| 55 |  |  |  |  |  |  | # PROTECTED METHODS | 
| 56 |  |  |  |  |  |  | ############################################################################# | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | =head1 Protected Methods: | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | The following methods are intended to be called by subclasses of the | 
| 61 |  |  |  |  |  |  | current class. | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | =cut | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | ############################################################################# | 
| 66 |  |  |  |  |  |  | # _init() | 
| 67 |  |  |  |  |  |  | ############################################################################# | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | =head2 _init() | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | The _init() method is called from within the standard Context constructor. | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | The _init() method sets debug flags. | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | * Signature: $context->_init($args) | 
| 76 |  |  |  |  |  |  | * Param:     $args            hash{string} [in] | 
| 77 |  |  |  |  |  |  | * Return:    void | 
| 78 |  |  |  |  |  |  | * Throws:    App::Exception | 
| 79 |  |  |  |  |  |  | * Since:     0.01 | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | Sample Usage: | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | $context->_init($args); | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | =cut | 
| 86 |  |  |  |  |  |  |  | 
| 87 |  |  |  |  |  |  | sub _init { | 
| 88 | 1 | 50 |  | 1 |  | 4 | &App::sub_entry if ($App::trace); | 
| 89 | 1 |  |  |  |  | 2 | my ($self, $args) = @_; | 
| 90 | 1 | 50 |  |  |  | 3 | $args = {} if (!defined $args); | 
| 91 |  |  |  |  |  |  |  | 
| 92 | 1 |  |  |  |  | 3 | eval { | 
| 93 | 1 |  |  |  |  | 12 | $self->{user_agent} = App::UserAgent->new($self); | 
| 94 |  |  |  |  |  |  | }; | 
| 95 | 1 | 50 |  |  |  | 3 | $self->add_message("Context::HTTP::_init(): $@") if ($@); | 
| 96 |  |  |  |  |  |  |  | 
| 97 | 1 | 50 |  |  |  | 5 | &App::sub_exit() if ($App::trace); | 
| 98 |  |  |  |  |  |  | } | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | sub _default_session_class { | 
| 101 | 0 | 0 |  | 0 |  | 0 | &App::sub_entry if ($App::trace); | 
| 102 | 0 |  |  |  |  | 0 | my $session_class = "App::Session::HTMLHidden"; | 
| 103 | 0 | 0 |  |  |  | 0 | &App::sub_exit($session_class) if ($App::trace); | 
| 104 | 0 |  |  |  |  | 0 | return($session_class); | 
| 105 |  |  |  |  |  |  | } | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | ############################################################################# | 
| 108 |  |  |  |  |  |  | # PROTECTED METHODS | 
| 109 |  |  |  |  |  |  | ############################################################################# | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | =head1 Protected Methods | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | These methods are considered protected because no class is ever supposed | 
| 114 |  |  |  |  |  |  | to call them.  They may however be called by the context-specific drivers. | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | =cut | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | sub dispatch_events_begin { | 
| 119 | 0 | 0 |  | 0 | 0 | 0 | &App::sub_entry if ($App::trace); | 
| 120 | 0 |  |  |  |  | 0 | my ($self) = @_; | 
| 121 | 0 |  |  |  |  | 0 | my $events = $self->{events}; | 
| 122 | 0 |  |  |  |  | 0 | my $request = $self->request(); | 
| 123 |  |  |  |  |  |  |  | 
| 124 | 0 |  |  |  |  | 0 | my $session_id = $request->get_session_id(); | 
| 125 | 0 |  |  |  |  | 0 | my $session = $self->session($session_id); | 
| 126 | 0 |  |  |  |  | 0 | $self->set_current_session($session); | 
| 127 |  |  |  |  |  |  |  | 
| 128 | 0 |  |  |  |  | 0 | my $request_events = $request->get_events(); | 
| 129 | 0 | 0 | 0 |  |  | 0 | if ($request_events && $#$request_events > -1) { | 
| 130 | 0 |  |  |  |  | 0 | push(@$events, @$request_events); | 
| 131 |  |  |  |  |  |  | } | 
| 132 | 0 |  |  |  |  | 0 | $self->init_profiler_log(); | 
| 133 |  |  |  |  |  |  |  | 
| 134 | 0 | 0 |  |  |  | 0 | &App::sub_exit() if ($App::trace); | 
| 135 |  |  |  |  |  |  | } | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | sub dispatch_events { | 
| 138 | 0 | 0 |  | 0 | 1 | 0 | &App::sub_entry if ($App::trace); | 
| 139 | 0 |  |  |  |  | 0 | my ($self) = @_; | 
| 140 |  |  |  |  |  |  |  | 
| 141 | 0 |  |  |  |  | 0 | my ($content_length); | 
| 142 | 0 |  |  |  |  | 0 | my $content_description = "Unknown"; | 
| 143 |  |  |  |  |  |  |  | 
| 144 | 0 |  |  |  |  | 0 | $self->dispatch_events_begin(); | 
| 145 | 0 |  |  |  |  | 0 | my $events = $self->{events}; | 
| 146 |  |  |  |  |  |  |  | 
| 147 | 0 |  |  |  |  | 0 | my $options  = $self->{options}; | 
| 148 | 0 |  | 0 |  |  | 0 | my $app      = $options->{app} || "app"; | 
| 149 | 0 |  |  |  |  | 0 | my $profiler = $options->{"app.Context.profiler"}; | 
| 150 | 0 |  |  |  |  | 0 | my ($app_scope, $app_scope_id_type, $app_scope_id, $content_name); | 
| 151 |  |  |  |  |  |  |  | 
| 152 | 0 |  |  |  |  | 0 | eval { | 
| 153 | 0 |  |  |  |  | 0 | my $user = $self->user(); | 
| 154 | 0 |  |  |  |  | 0 | my $authorization = $self->authorization(); | 
| 155 | 0 |  |  |  |  | 0 | my ($event, $service_type, $service_name, $method, $args, $return_results, $return_event_results, $event_results); | 
| 156 | 0 |  |  |  |  | 0 | my $results = ""; | 
| 157 |  |  |  |  |  |  | # my $display_current_widget = 1; | 
| 158 |  |  |  |  |  |  |  | 
| 159 | 0 | 0 |  |  |  | 0 | if ($#$events > -1) { | 
| 160 | 0 | 0 |  |  |  | 0 | if ($profiler) { | 
| 161 | 0 |  |  |  |  | 0 | $self->profile_start("event"); | 
| 162 |  |  |  |  |  |  | } | 
| 163 | 0 |  |  |  |  | 0 | while ($#$events > -1) { | 
| 164 | 0 |  |  |  |  | 0 | $event = shift(@$events); | 
| 165 | 0 |  |  |  |  | 0 | ($service_type, $service_name, $method, $args, $return_event_results) = @$event; | 
| 166 | 0 | 0 |  |  |  | 0 | if ($authorization->is_authorized("/App/$service_type/$service_name/$method", $user)) { | 
| 167 | 0 |  |  |  |  | 0 | $event_results = $self->call($service_type, $service_name, $method, $args); | 
| 168 | 0 | 0 |  |  |  | 0 | if ($return_event_results) { | 
| 169 | 0 |  |  |  |  | 0 | $results = $event_results; | 
| 170 | 0 |  |  |  |  | 0 | $return_results = 1; | 
| 171 |  |  |  |  |  |  | } | 
| 172 | 0 |  |  |  |  | 0 | $user = $self->user(); | 
| 173 |  |  |  |  |  |  | } | 
| 174 |  |  |  |  |  |  | } | 
| 175 | 0 | 0 |  |  |  | 0 | if ($profiler) { | 
| 176 | 0 | 0 |  |  |  | 0 | my $args_str  = (ref($args) eq "ARRAY") ? join(",", @$args) : $args; | 
| 177 | 0 |  |  |  |  | 0 | $app_scope    = "$service_type($service_name).$method($args_str)"; | 
| 178 | 0 |  |  |  |  | 0 | $self->profile_stop("event"); | 
| 179 |  |  |  |  |  |  | } | 
| 180 |  |  |  |  |  |  | } | 
| 181 | 0 |  |  |  |  | 0 | $service_type = $self->so_get("default","ctype","SessionObject"); | 
| 182 | 0 |  |  |  |  | 0 | $service_name = $self->so_get("default","cname"); | 
| 183 |  |  |  |  |  |  |  | 
| 184 | 0 | 0 |  |  |  | 0 | if ($authorization->is_authorized("/App/$service_type/$service_name", $user)) { | 
| 185 |  |  |  |  |  |  | # do nothing | 
| 186 |  |  |  |  |  |  | } | 
| 187 |  |  |  |  |  |  | else { | 
| 188 | 0 | 0 |  |  |  | 0 | if ($self->session_object_exists("login_${app}")) { | 
| 189 | 0 |  |  |  |  | 0 | $service_name = "login_${app}"; | 
| 190 |  |  |  |  |  |  | } | 
| 191 |  |  |  |  |  |  | else { | 
| 192 | 0 |  |  |  |  | 0 | $service_name = "login"; | 
| 193 |  |  |  |  |  |  | } | 
| 194 |  |  |  |  |  |  | } | 
| 195 |  |  |  |  |  |  |  | 
| 196 | 0 | 0 |  |  |  | 0 | $results = $self->service($service_type, $service_name) if (!$return_results); | 
| 197 |  |  |  |  |  |  |  | 
| 198 | 0 |  |  |  |  | 0 | my $response = $self->response(); | 
| 199 | 0 |  |  |  |  | 0 | my $ref = ref($results); | 
| 200 | 0 | 0 | 0 |  |  | 0 | if (!$ref || $ref eq "ARRAY" || $ref eq "HASH") { | 
|  |  | 0 | 0 |  |  |  |  | 
| 201 | 0 |  |  |  |  | 0 | $app_scope = "results [$ref]"; | 
| 202 | 0 | 0 |  |  |  | 0 | if ($profiler) { | 
| 203 | 0 |  |  |  |  | 0 | $self->update_profiler_log($app_scope, $service_name, $app_scope_id_type, $app_scope_id); | 
| 204 |  |  |  |  |  |  | } | 
| 205 | 0 |  |  |  |  | 0 | $response->content($results); | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  | elsif ($results->isa("App::Service")) { | 
| 208 | 0 |  |  |  |  | 0 | ($app_scope, $app_scope_id_type, $app_scope_id, $content_name) = $results->content_description(); | 
| 209 | 0 |  | 0 |  |  | 0 | $content_name ||= $service_name; | 
| 210 | 0 | 0 |  |  |  | 0 | if ($profiler) { | 
| 211 | 0 |  |  |  |  | 0 | $self->update_profiler_log($app_scope, $content_name, $app_scope_id_type, $app_scope_id); | 
| 212 |  |  |  |  |  |  | } | 
| 213 | 0 |  |  |  |  | 0 | $response->content($results->content()); | 
| 214 | 0 |  |  |  |  | 0 | $response->content_type($results->content_type()); | 
| 215 |  |  |  |  |  |  | } | 
| 216 |  |  |  |  |  |  | else { | 
| 217 | 0 |  |  |  |  | 0 | $app_scope = "$service_type($service_name).internals()"; | 
| 218 | 0 | 0 |  |  |  | 0 | if ($profiler) { | 
| 219 | 0 |  |  |  |  | 0 | $self->update_profiler_log($app_scope, $service_name, $app_scope_id_type, $app_scope_id); | 
| 220 |  |  |  |  |  |  | } | 
| 221 | 0 |  |  |  |  | 0 | $response->content($results->internals()); | 
| 222 |  |  |  |  |  |  | } | 
| 223 |  |  |  |  |  |  |  | 
| 224 | 0 | 0 |  |  |  | 0 | if ($profiler) { | 
| 225 | 0 |  |  |  |  | 0 | $self->profile_start("xfer", 1); | 
| 226 |  |  |  |  |  |  | } | 
| 227 | 0 |  |  |  |  | 0 | $content_length = $self->send_response(); | 
| 228 |  |  |  |  |  |  |  | 
| 229 | 0 | 0 |  |  |  | 0 | if ($profiler) { | 
| 230 | 0 |  |  |  |  | 0 | $self->{profile_state}{app_scope} = $app_scope; | 
| 231 | 0 |  |  |  |  | 0 | $self->{profile_state}{content_length} = $content_length; | 
| 232 |  |  |  |  |  |  | } | 
| 233 |  |  |  |  |  |  | }; | 
| 234 | 0 | 0 |  |  |  | 0 | if ($@) { | 
| 235 | 0 |  |  |  |  | 0 | $content_length = $self->send_error($@); | 
| 236 | 0 | 0 |  |  |  | 0 | if ($profiler) { | 
| 237 | 0 |  |  |  |  | 0 | $self->{profile_state}{app_scope} = "ERROR [$app_scope]: $@"; | 
| 238 | 0 |  |  |  |  | 0 | $self->{profile_state}{content_length} = $content_length; | 
| 239 |  |  |  |  |  |  | } | 
| 240 |  |  |  |  |  |  | } | 
| 241 |  |  |  |  |  |  |  | 
| 242 | 0 | 0 |  |  |  | 0 | if ($self->{options}{debug_context}) { | 
| 243 | 0 |  |  |  |  | 0 | print STDERR $self->dump(); | 
| 244 |  |  |  |  |  |  | } | 
| 245 |  |  |  |  |  |  |  | 
| 246 | 0 |  |  |  |  | 0 | $self->dispatch_events_finish(); | 
| 247 | 0 | 0 |  |  |  | 0 | &App::sub_exit() if ($App::trace); | 
| 248 |  |  |  |  |  |  | } | 
| 249 |  |  |  |  |  |  |  | 
| 250 |  |  |  |  |  |  | sub dispatch_events_finish { | 
| 251 | 0 | 0 |  | 0 | 0 | 0 | &App::sub_entry if ($App::trace); | 
| 252 | 0 |  |  |  |  | 0 | my ($self) = @_; | 
| 253 | 0 |  |  |  |  | 0 | $self->restore_default_session(); | 
| 254 | 0 |  |  |  |  | 0 | $self->shutdown();  # assume we won't be doing anything else (this can be overridden) | 
| 255 | 0 | 0 |  |  |  | 0 | &App::sub_exit() if ($App::trace); | 
| 256 |  |  |  |  |  |  | } | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  | sub send_error { | 
| 259 | 0 | 0 |  | 0 | 0 | 0 | &App::sub_entry if ($App::trace); | 
| 260 | 0 |  |  |  |  | 0 | my ($self, $errmsg) = @_; | 
| 261 | 0 |  |  |  |  | 0 | my $str = < | 
| 262 |  |  |  |  |  |  | Content-type: text/plain | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  | ----------------------------------------------------------------------------- | 
| 265 |  |  |  |  |  |  | AN ERROR OCCURRED in App::Context::HTTP->dispatch_events() | 
| 266 |  |  |  |  |  |  | ----------------------------------------------------------------------------- | 
| 267 |  |  |  |  |  |  | $errmsg | 
| 268 |  |  |  |  |  |  |  | 
| 269 |  |  |  |  |  |  | ----------------------------------------------------------------------------- | 
| 270 |  |  |  |  |  |  | Additional messages from earlier stages may be relevant if they exist below. | 
| 271 |  |  |  |  |  |  | ----------------------------------------------------------------------------- | 
| 272 |  |  |  |  |  |  | $self->{messages} | 
| 273 |  |  |  |  |  |  | EOF | 
| 274 | 0 |  |  |  |  | 0 | my $content_length = length($str); | 
| 275 | 0 |  |  |  |  | 0 | print $str; | 
| 276 | 0 | 0 |  |  |  | 0 | &App::sub_exit($content_length) if ($App::trace); | 
| 277 | 0 |  |  |  |  | 0 | return($content_length); | 
| 278 |  |  |  |  |  |  | } | 
| 279 |  |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | ############################################################################# | 
| 281 |  |  |  |  |  |  | # request() | 
| 282 |  |  |  |  |  |  | ############################################################################# | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | =head2 request() | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | * Signature: $context->request() | 
| 287 |  |  |  |  |  |  | * Param:     void | 
| 288 |  |  |  |  |  |  | * Return:    void | 
| 289 |  |  |  |  |  |  | * Throws:    App::Exception | 
| 290 |  |  |  |  |  |  | * Since:     0.01 | 
| 291 |  |  |  |  |  |  |  | 
| 292 |  |  |  |  |  |  | Sample Usage: | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | $context->request(); | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | The request() method gets the current Request being handled in the Context. | 
| 297 |  |  |  |  |  |  |  | 
| 298 |  |  |  |  |  |  | =cut | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | sub request { | 
| 301 | 1 | 50 |  | 1 | 1 | 5 | &App::sub_entry if ($App::trace); | 
| 302 | 1 |  |  |  |  | 3 | my $self = shift; | 
| 303 |  |  |  |  |  |  |  | 
| 304 | 1 | 50 |  |  |  | 5 | if (! defined $self->{request}) { | 
| 305 |  |  |  |  |  |  |  | 
| 306 |  |  |  |  |  |  | ################################################################# | 
| 307 |  |  |  |  |  |  | # REQUEST | 
| 308 |  |  |  |  |  |  | ################################################################# | 
| 309 |  |  |  |  |  |  |  | 
| 310 | 1 |  |  |  |  | 14 | my $request_class = $self->get_option("request_class"); | 
| 311 | 1 | 50 |  |  |  | 97 | if (!$request_class) { | 
| 312 | 1 |  |  |  |  | 5 | my $gateway = $ENV{GATEWAY_INTERFACE}; | 
| 313 |  |  |  |  |  |  | # TODO: need to distinguish between PerlRun, Registry, libapreq, other | 
| 314 | 1 | 50 |  |  |  | 7 | if ($ENV{MOD_PERL}) {  # mod_perl: Registry | 
|  |  | 50 |  |  |  |  |  | 
| 315 | 0 |  |  |  |  | 0 | $request_class = "App::Request::CGI"; | 
| 316 |  |  |  |  |  |  | } | 
| 317 |  |  |  |  |  |  | elsif ($ENV{HTTP_USER_AGENT}) {  # running as CGI script? | 
| 318 | 0 |  |  |  |  | 0 | $request_class = "App::Request::CGI"; | 
| 319 |  |  |  |  |  |  | } | 
| 320 |  |  |  |  |  |  | else { | 
| 321 | 1 |  |  |  |  | 4 | $request_class = "App::Request::CGI"; | 
| 322 |  |  |  |  |  |  | } | 
| 323 |  |  |  |  |  |  | } | 
| 324 |  |  |  |  |  |  |  | 
| 325 | 1 |  |  |  |  | 1 | eval { | 
| 326 | 1 |  |  |  |  | 11 | $self->{request} = App->new($request_class, "new", $self, $self->{options}); | 
| 327 |  |  |  |  |  |  | }; | 
| 328 |  |  |  |  |  |  | # ignore the failure to find a request. no request is currently available. method will return undef. | 
| 329 |  |  |  |  |  |  | } | 
| 330 |  |  |  |  |  |  |  | 
| 331 | 1 | 50 |  |  |  | 5 | &App::sub_exit($self->{request}) if ($App::trace); | 
| 332 | 1 |  |  |  |  | 6 | return $self->{request}; | 
| 333 |  |  |  |  |  |  | } | 
| 334 |  |  |  |  |  |  |  | 
| 335 |  |  |  |  |  |  | ############################################################################# | 
| 336 |  |  |  |  |  |  | # send_response() | 
| 337 |  |  |  |  |  |  | ############################################################################# | 
| 338 |  |  |  |  |  |  |  | 
| 339 |  |  |  |  |  |  | =head2 send_response() | 
| 340 |  |  |  |  |  |  |  | 
| 341 |  |  |  |  |  |  | * Signature: $context->send_response() | 
| 342 |  |  |  |  |  |  | * Param:     void | 
| 343 |  |  |  |  |  |  | * Return:    void | 
| 344 |  |  |  |  |  |  | * Throws:    App::Exception | 
| 345 |  |  |  |  |  |  | * Since:     0.01 | 
| 346 |  |  |  |  |  |  |  | 
| 347 |  |  |  |  |  |  | Sample Usage: | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | $context->send_response(); | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | =cut | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | sub send_response { | 
| 354 | 0 | 0 |  | 0 | 1 |  | &App::sub_entry if ($App::trace); | 
| 355 | 0 |  |  |  |  |  | my $self = shift; | 
| 356 |  |  |  |  |  |  |  | 
| 357 | 0 |  |  |  |  |  | my ($serializer, $response, $content, $content_type, $content_length, $headers); | 
| 358 | 0 |  |  |  |  |  | $response = $self->response(); | 
| 359 | 0 |  |  |  |  |  | $content  = $response->content(); | 
| 360 |  |  |  |  |  |  |  | 
| 361 |  |  |  |  |  |  | # NOTE: $content will be a scalar if HTML is being returned | 
| 362 | 0 | 0 |  |  |  |  | if (ref($content)) { | 
| 363 | 0 |  |  |  |  |  | my $request    = $self->request(); | 
| 364 | 0 |  |  |  |  |  | my $returntype = $request->get_returntype(); | 
| 365 | 0 |  |  |  |  |  | $serializer = $self->serializer($returntype); | 
| 366 | 0 |  |  |  |  |  | $content = $serializer->serialize($content); | 
| 367 | 0 |  |  |  |  |  | $content_type = $serializer->serialized_content_type(); | 
| 368 |  |  |  |  |  |  | } | 
| 369 |  |  |  |  |  |  |  | 
| 370 | 0 | 0 |  |  |  |  | $content_type = $response->content_type() if (!$content_type); | 
| 371 | 0 | 0 |  |  |  |  | $content_type = "text/plain" if (!$content_type); | 
| 372 | 0 |  |  |  |  |  | $headers      = "Content-type: $content_type\n"; | 
| 373 |  |  |  |  |  |  |  | 
| 374 | 0 | 0 |  |  |  |  | if (defined $self->{headers}) { | 
| 375 | 0 |  |  |  |  |  | $headers .= $self->{headers}; | 
| 376 | 0 |  |  |  |  |  | delete $self->{headers} | 
| 377 |  |  |  |  |  |  | } | 
| 378 |  |  |  |  |  |  |  | 
| 379 | 0 | 0 |  |  |  |  | if ($self->{options}{gzip}) { | 
| 380 | 0 |  |  |  |  |  | my $user_agent = $self->user_agent(); | 
| 381 | 0 |  |  |  |  |  | my $gzip_ok    = $user_agent->supports("http.header.accept-encoding.x-gzip"); | 
| 382 |  |  |  |  |  |  |  | 
| 383 | 0 | 0 |  |  |  |  | if ($gzip_ok) { | 
| 384 | 0 |  |  |  |  |  | $headers .= "Content-encoding: gzip\n"; | 
| 385 | 1 |  |  | 1 |  | 5225 | use Compress::Zlib; | 
|  | 1 |  |  |  |  | 101837 |  | 
|  | 1 |  |  |  |  | 1219 |  | 
| 386 | 0 |  |  |  |  |  | $content = Compress::Zlib::memGzip($content); | 
| 387 |  |  |  |  |  |  | } | 
| 388 |  |  |  |  |  |  | } | 
| 389 | 0 |  |  |  |  |  | $content_length = length($content); | 
| 390 |  |  |  |  |  |  |  | 
| 391 | 0 | 0 |  |  |  |  | if ($self->{messages}) { | 
| 392 | 0 |  |  |  |  |  | my $msg = $self->{messages}; | 
| 393 | 0 |  |  |  |  |  | $self->{messages} = ""; | 
| 394 | 0 |  |  |  |  |  | $msg =~ s/ /\n/g;
 | 
| 395 | 0 |  |  |  |  |  | print "Content-type: text/plain\n\n", $msg, "\n"; | 
| 396 |  |  |  |  |  |  | } | 
| 397 |  |  |  |  |  |  | else { | 
| 398 | 0 |  |  |  |  |  | print $headers, "\n", $content; | 
| 399 |  |  |  |  |  |  | } | 
| 400 | 0 | 0 |  |  |  |  | &App::sub_exit($content_length) if ($App::trace); | 
| 401 | 0 |  |  |  |  |  | return($content_length); | 
| 402 |  |  |  |  |  |  | } | 
| 403 |  |  |  |  |  |  |  | 
| 404 |  |  |  |  |  |  | ############################################################################# | 
| 405 |  |  |  |  |  |  | # set_header() | 
| 406 |  |  |  |  |  |  | ############################################################################# | 
| 407 |  |  |  |  |  |  |  | 
| 408 |  |  |  |  |  |  | =head2 set_header() | 
| 409 |  |  |  |  |  |  |  | 
| 410 |  |  |  |  |  |  | * Signature: $context->set_header() | 
| 411 |  |  |  |  |  |  | * Param:     void | 
| 412 |  |  |  |  |  |  | * Return:    void | 
| 413 |  |  |  |  |  |  | * Throws:    App::Exception | 
| 414 |  |  |  |  |  |  | * Since:     0.01 | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | Sample Usage: | 
| 417 |  |  |  |  |  |  |  | 
| 418 |  |  |  |  |  |  | $context->set_header(); | 
| 419 |  |  |  |  |  |  |  | 
| 420 |  |  |  |  |  |  | =cut | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | sub set_header { | 
| 423 | 0 | 0 |  | 0 | 1 |  | &App::sub_entry if ($App::trace); | 
| 424 | 0 |  |  |  |  |  | my ($self, $header) = @_; | 
| 425 | 0 | 0 |  |  |  |  | if ($self->{headers}) { | 
| 426 | 0 |  |  |  |  |  | $self->{headers} .= $header; | 
| 427 |  |  |  |  |  |  | } | 
| 428 |  |  |  |  |  |  | else { | 
| 429 | 0 |  |  |  |  |  | $self->{headers} = $header; | 
| 430 |  |  |  |  |  |  | } | 
| 431 | 0 | 0 |  |  |  |  | &App::sub_exit() if ($App::trace); | 
| 432 |  |  |  |  |  |  | } | 
| 433 |  |  |  |  |  |  |  | 
| 434 |  |  |  |  |  |  | ############################################################################# | 
| 435 |  |  |  |  |  |  | # user_agent() | 
| 436 |  |  |  |  |  |  | ############################################################################# | 
| 437 |  |  |  |  |  |  |  | 
| 438 |  |  |  |  |  |  | =head2 user_agent() | 
| 439 |  |  |  |  |  |  |  | 
| 440 |  |  |  |  |  |  | The user_agent() method returns a UserAgent objects which is primarily | 
| 441 |  |  |  |  |  |  | useful to see what capabilities the user agent (browser) supports. | 
| 442 |  |  |  |  |  |  |  | 
| 443 |  |  |  |  |  |  | * Signature: $user_agent = $context->user_agent(); | 
| 444 |  |  |  |  |  |  | * Param:  void | 
| 445 |  |  |  |  |  |  | * Return: $user_agent    App::UserAgent | 
| 446 |  |  |  |  |  |  | * Throws: | 
| 447 |  |  |  |  |  |  | * Since:  0.01 | 
| 448 |  |  |  |  |  |  |  | 
| 449 |  |  |  |  |  |  | Sample Usage: | 
| 450 |  |  |  |  |  |  |  | 
| 451 |  |  |  |  |  |  | $user_agent = $context->user_agent(); | 
| 452 |  |  |  |  |  |  |  | 
| 453 |  |  |  |  |  |  | =cut | 
| 454 |  |  |  |  |  |  |  | 
| 455 |  |  |  |  |  |  | sub user_agent { | 
| 456 | 0 | 0 |  | 0 | 1 |  | &App::sub_entry if ($App::trace); | 
| 457 | 0 |  |  |  |  |  | my $self = shift; | 
| 458 | 0 |  |  |  |  |  | my $user_agent = $self->{user_agent}; | 
| 459 | 0 | 0 |  |  |  |  | &App::sub_exit($user_agent) if ($App::trace); | 
| 460 | 0 |  |  |  |  |  | return($user_agent); | 
| 461 |  |  |  |  |  |  | } | 
| 462 |  |  |  |  |  |  |  | 
| 463 |  |  |  |  |  |  | ############################################################################# | 
| 464 |  |  |  |  |  |  | # PUBLIC METHODS | 
| 465 |  |  |  |  |  |  | ############################################################################# | 
| 466 |  |  |  |  |  |  |  | 
| 467 |  |  |  |  |  |  | =head1 Public Methods: | 
| 468 |  |  |  |  |  |  |  | 
| 469 |  |  |  |  |  |  | =cut | 
| 470 |  |  |  |  |  |  |  | 
| 471 |  |  |  |  |  |  | ############################################################################# | 
| 472 |  |  |  |  |  |  | # user() | 
| 473 |  |  |  |  |  |  | ############################################################################# | 
| 474 |  |  |  |  |  |  |  | 
| 475 |  |  |  |  |  |  | =head2 user() | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  | The user() method returns the username of the authenticated user. | 
| 478 |  |  |  |  |  |  | The special name, "guest", refers to the unauthenticated (anonymous) user. | 
| 479 |  |  |  |  |  |  |  | 
| 480 |  |  |  |  |  |  | * Signature: $username = $self->user(); | 
| 481 |  |  |  |  |  |  | * Param:  void | 
| 482 |  |  |  |  |  |  | * Return: string | 
| 483 |  |  |  |  |  |  | * Throws: | 
| 484 |  |  |  |  |  |  | * Since:  0.01 | 
| 485 |  |  |  |  |  |  |  | 
| 486 |  |  |  |  |  |  | Sample Usage: | 
| 487 |  |  |  |  |  |  |  | 
| 488 |  |  |  |  |  |  | $username = $context->user(); | 
| 489 |  |  |  |  |  |  |  | 
| 490 |  |  |  |  |  |  | In a request/response environment, this turns out to be a convenience | 
| 491 |  |  |  |  |  |  | method which gets the authenticated user from the current Request object. | 
| 492 |  |  |  |  |  |  |  | 
| 493 |  |  |  |  |  |  | =cut | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | sub user { | 
| 496 | 0 | 0 |  | 0 | 1 |  | &App::sub_entry if ($App::trace); | 
| 497 | 0 |  |  |  |  |  | my $self = shift; | 
| 498 | 0 |  | 0 |  |  |  | my $user = $self->{effective_user} || $self->{user}; | 
| 499 |  |  |  |  |  |  |  | 
| 500 | 0 | 0 |  |  |  |  | if (!$user) { | 
| 501 | 0 |  |  |  |  |  | my $options = $self->{options}; | 
| 502 | 0 |  |  |  |  |  | my ($effective_user); | 
| 503 | 0 |  |  |  |  |  | my $authenticated = 0; | 
| 504 | 0 | 0 |  |  |  |  | if ($options->{app_auth_required}) { | 
| 505 |  |  |  |  |  |  | # Bypass Basic Authentication, /../..?u=username&p=password | 
| 506 | 0 |  |  |  |  |  | my $password = $self->so_get("default","p"); | 
| 507 | 0 |  |  |  |  |  | $user = $self->so_get("default","u"); | 
| 508 |  |  |  |  |  |  |  | 
| 509 | 0 | 0 | 0 |  |  |  | if (defined $password && defined $user) { | 
| 510 | 0 |  |  |  |  |  | my $authentication = $self->authentication(); | 
| 511 | 0 | 0 |  |  |  |  | if ( $authentication->validate_password($user, $password) ) { | 
| 512 | 0 |  |  |  |  |  | $authenticated = 1; | 
| 513 | 0 |  |  |  |  |  | $effective_user = $self->so_get("default","eu"); | 
| 514 |  |  |  |  |  |  | } | 
| 515 |  |  |  |  |  |  | } | 
| 516 |  |  |  |  |  |  | } | 
| 517 |  |  |  |  |  |  | else { | 
| 518 | 0 |  |  |  |  |  | $user = $self->request()->user(); | 
| 519 |  |  |  |  |  |  |  | 
| 520 | 0 |  |  |  |  |  | my $p_pass = $self->so_get("default","p"); | 
| 521 | 0 |  |  |  |  |  | my $u_user = $self->so_get("default","u"); | 
| 522 | 0 | 0 | 0 |  |  |  | if (defined $p_pass && defined $u_user) { | 
| 523 | 0 |  |  |  |  |  | my $authentication = $self->authentication(); | 
| 524 | 0 | 0 |  |  |  |  | if ( $authentication->validate_password($u_user, $p_pass) ) { | 
| 525 | 0 |  |  |  |  |  | $authenticated = 1; | 
| 526 | 0 |  |  |  |  |  | $user = $self->so_get("default","u"); | 
| 527 | 0 |  |  |  |  |  | $effective_user = $self->so_get("default","u"); | 
| 528 |  |  |  |  |  |  | } | 
| 529 |  |  |  |  |  |  | else { | 
| 530 | 0 |  |  |  |  |  | $user = 'guest'; | 
| 531 | 0 |  |  |  |  |  | $effective_user = 'guest'; | 
| 532 |  |  |  |  |  |  | } | 
| 533 |  |  |  |  |  |  | } | 
| 534 |  |  |  |  |  |  |  | 
| 535 | 0 |  |  |  |  |  | $authenticated = 1; | 
| 536 | 0 |  |  |  |  |  | $effective_user = $self->so_get("default","u"); | 
| 537 |  |  |  |  |  |  | } | 
| 538 |  |  |  |  |  |  |  | 
| 539 | 0 | 0 |  |  |  |  | $user = "guest" if (!$authenticated); | 
| 540 | 0 |  |  |  |  |  | $ENV{REMOTE_USER} = $user; | 
| 541 | 0 |  |  |  |  |  | $self->{user} = $user; | 
| 542 | 0 | 0 | 0 |  |  |  | if ($user && $authenticated) { | 
| 543 | 0 |  |  |  |  |  | my $switchable_users = $self->get_option("switchable_users"); | 
| 544 | 0 | 0 | 0 |  |  |  | if ($switchable_users && $switchable_users =~ /\b$user\b/) { | 
| 545 |  |  |  |  |  |  | # check more carefully ... | 
| 546 | 0 | 0 | 0 |  |  |  | if ($switchable_users eq $user || | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 547 |  |  |  |  |  |  | $switchable_users =~ /:$user:/ || | 
| 548 |  |  |  |  |  |  | $switchable_users =~ /^$user:/ || | 
| 549 |  |  |  |  |  |  | $switchable_users =~ /:$user$/) { | 
| 550 | 0 | 0 |  |  |  |  | if ($effective_user) { | 
| 551 | 0 |  |  |  |  |  | $user = $effective_user; | 
| 552 | 0 |  |  |  |  |  | $self->{effective_user} = $effective_user; | 
| 553 |  |  |  |  |  |  | } | 
| 554 |  |  |  |  |  |  | } | 
| 555 |  |  |  |  |  |  | } | 
| 556 |  |  |  |  |  |  | } | 
| 557 | 0 |  |  |  |  |  | $self->so_set("default", "user", $user); | 
| 558 |  |  |  |  |  |  | } | 
| 559 |  |  |  |  |  |  |  | 
| 560 | 0 | 0 |  |  |  |  | &App::sub_exit($user) if ($App::trace); | 
| 561 | 0 |  |  |  |  |  | return $user; | 
| 562 |  |  |  |  |  |  | } | 
| 563 |  |  |  |  |  |  |  | 
| 564 |  |  |  |  |  |  | sub set_user { | 
| 565 | 0 | 0 |  | 0 | 0 |  | &App::sub_entry if ($App::trace); | 
| 566 | 0 |  |  |  |  |  | my ($self, $user) = @_; | 
| 567 | 0 |  |  |  |  |  | $self->{user} = $user; | 
| 568 | 0 |  |  |  |  |  | delete $self->{effective_user}; | 
| 569 | 0 | 0 |  |  |  |  | &App::sub_exit() if ($App::trace); | 
| 570 |  |  |  |  |  |  | } | 
| 571 |  |  |  |  |  |  |  | 
| 572 |  |  |  |  |  |  | 1; | 
| 573 |  |  |  |  |  |  |  |