Fixed MP2, removed dependency of libapreq in MP engines, fixed C::E::C::APR
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine / CGI.pm
index 1588717..1a8f37c 100644 (file)
@@ -1,14 +1,9 @@
 package Catalyst::Engine::CGI;
 
 use strict;
-use base 'Catalyst::Engine';
-use URI;
+use base 'Catalyst::Engine::CGI::Base';
 
-require CGI::Simple;
-require CGI::Cookie;
-
-$CGI::Simple::POST_MAX        = 1048576;
-$CGI::Simple::DISABLE_UPLOADS = 0;
+use CGI;
 
 __PACKAGE__->mk_accessors('cgi');
 
@@ -34,18 +29,13 @@ appropriate engine module.
 =head1 DESCRIPTION
 
 This is the Catalyst engine specialized for the CGI environment (using the
-C<CGI::Simple> and C<CGI::Cookie> modules).  Normally Catalyst will select the
+C<CGI> and C<CGI::Cookie> modules).  Normally Catalyst will select the
 appropriate engine according to the environment that it detects, however you
 can force Catalyst to use the CGI engine by specifying the following in your
 application module:
 
     use Catalyst qw(-Engine=CGI);
 
-Catalyst::Engine::CGI generates a full set of HTTP headers, which means that
-applications using the engine must be be configured as "Non-parsed Headers"
-scripts (at least when running under Apache).  To configure this under Apache
-name the starting with C<nph->.
-
 The performance of this way of using Catalyst is not expected to be
 useful in production applications, but it may be helpful for development.
 
@@ -53,160 +43,143 @@ useful in production applications, but it may be helpful for development.
 
 =over 4
 
-=item $c->run
-
-To be called from a CGI script to start the Catalyst application.
-
 =item $c->cgi
 
-This config parameter contains the C<CGI::Simple> object.
+Contains the C<CGI> object.
 
 =back
 
 =head1 OVERLOADED METHODS
 
-This class overloads some methods from C<Catalyst>.
+This class overloads some methods from C<Catalyst::Engine::CGI::Base>.
 
 =over 4
 
-=item $c->finalize_headers
+=item $c->prepare_body
 
 =cut
 
-sub finalize_headers {
+sub prepare_body {
     my $c = shift;
-    my %headers = ( -nph => 1 );
-    $headers{-status} = $c->response->status if $c->response->status;
-    for my $name ( $c->response->headers->header_field_names ) {
-        $headers{"-$name"} = $c->response->headers->header($name);
-    }
-    my @cookies;
-    while ( my ( $name, $cookie ) = each %{ $c->response->cookies } ) {
-        push @cookies, $c->cgi->cookie(
-            -name    => $name,
-            -value   => $cookie->{value},
-            -expires => $cookie->{expires},
-            -domain  => $cookie->{domain},
-            -path    => $cookie->{path},
-            -secure  => $cookie->{secure} || 0
-        );
-    }
-    $headers{-cookie} = \@cookies if @cookies;
-    print $c->cgi->header(%headers);
-}
 
-=item $c->finalize_output
+    # XXX this is undocumented in CGI.pm. If Content-Type is not
+    # application/x-www-form-urlencoded or multipart/form-data
+    # CGI.pm will read STDIN into a param, POSTDATA.
 
-Prints the response output to STDOUT.
+    $c->request->body( $c->cgi->param('POSTDATA') );
+}
+
+=item $c->prepare_parameters
 
 =cut
 
-sub finalize_output {
+sub prepare_parameters {
     my $c = shift;
-    print $c->response->output;
-}
 
-=item $c->prepare_connection
+    my ( @params );
 
-=cut
+    if ( $c->request->method eq 'POST' ) {
+        for my $param ( $c->cgi->url_param ) {
+            for my $value (  $c->cgi->url_param($param) ) {
+                push ( @params, $param, $value );
+            }
+        }
+    }
 
-sub prepare_connection {
-    my $c = shift;
-    $c->req->hostname( $c->cgi->remote_host );
-    $c->req->address( $c->cgi->remote_addr );
-}
+    for my $param ( $c->cgi->param ) {
+        for my $value (  $c->cgi->param($param) ) {
+            push ( @params, $param, $value );
+        }
+    }
 
-=item $c->prepare_cookies
+    $c->request->param(@params);
+}
 
-Sets up cookies.
+=item $c->prepare_request
 
 =cut
 
-sub prepare_cookies { shift->req->cookies( { CGI::Cookie->fetch } ) }
+sub prepare_request {
+    my ( $c, $object ) = @_;
 
-=item $c->prepare_headers
+    my $cgi;
 
-=cut
+    if ( defined($object) && ref($object) ) {
 
-sub prepare_headers {
-    my $c = shift;
-    $c->req->method( $c->cgi->request_method );
-    for my $header ( $c->cgi->http ) {
-        ( my $field = $header ) =~ s/^HTTPS?_//;
-        $c->req->headers->header( $field => $c->cgi->http($header) );
-    }
-    $c->req->headers->header( 'Content-Type'   => $c->cgi->content_type );
-    $c->req->headers->header( 'Content-Length' => $c->cgi->content_length );
-}
+        if ( $object->isa('Apache') ) {                   # MP 1.3
+            $cgi = CGI->new($object);
+        }
 
-=item $c->prepare_parameters
+        elsif ( $object->isa('Apache::RequestRec') ) {    # MP 1.99
+            $cgi = CGI->new($object);
+        }
 
-=cut
+        elsif ( $object->isa('Apache2::RequestRec') ) {   # MP 2.00
+            $cgi = CGI->new($object);
+        }
 
-sub prepare_parameters {
-    my $c    = shift;
-    my %vars = $c->cgi->Vars;
-    while ( my ( $key, $value ) = each %vars ) {
-        my @values = split "\0", $value;
-        $vars{$key} = @values <= 1 ? $values[0] : \@values;
+        elsif ( $object->isa('CGI') ) {
+            $cgi = $object;
+        }
+
+        else {
+            my $class = ref($object);
+            die( qq/Invalid argument $object/ );
+        }
     }
-    $c->req->parameters( {%vars} );
+
+    $c->cgi( $cgi || CGI->new );
 }
 
-=item $c->prepare_path
+=item $c->prepare_uploads
 
 =cut
 
-sub prepare_path {
+sub prepare_uploads {
     my $c = shift;
-    $c->req->path( $c->cgi->url( -absolute => 1, -path_info => 1 ) );
-    my $loc = $c->cgi->url( -absolute => 1 );
-    no warnings 'uninitialized';
-    $c->req->{path} =~ s/^($loc)?\///;
-    $c->req->{path} .= '/' if $c->req->path eq $loc;
-    my $base = $c->cgi->url;
-    if ( $ENV{CATALYST_TEST} ) {
-        my $script = $c->cgi->script_name;
-        $base =~ s/$script$//i;
-    }
-    $base = URI->new($base);
-    $base->path('/') if ( $ENV{CATALYST_TEST} || !$base->path );
-    $c->req->base( $base->as_string );
-}
 
-=item $c->prepare_request
+    my @uploads;
 
-=cut
+    for my $param ( $c->cgi->param ) {
 
-sub prepare_request { shift->cgi( CGI::Simple->new ) }
+        my @values = $c->cgi->param($param);
 
-=item $c->prepare_uploads
+        next unless ref( $values[0] );
 
-=cut
+        for my $fh (@values) {
 
-sub prepare_uploads {
-    my $c = shift;
-    for my $name ( $c->cgi->upload ) {
-        next unless defined $name;
-        $c->req->uploads->{$name} = {
-            fh   => $c->cgi->upload($name),
-            size => $c->cgi->upload_info( $name, 'size' ),
-            type => $c->cgi->upload_info( $name, 'mime' )
-        };
+            next unless my $size = ( stat $fh )[7];
+
+            my $info        = $c->cgi->uploadInfo($fh);
+            my $tempname    = $c->cgi->tmpFileName($fh);
+            my $type        = $info->{'Content-Type'};
+            my $disposition = $info->{'Content-Disposition'};
+            my $filename    = ( $disposition =~ / filename="([^;]*)"/ )[0];
+
+            my $upload = Catalyst::Request::Upload->new(
+                filename => $filename,
+                size     => $size,
+                tempname => $tempname,
+                type     => $type
+            );
+
+            push( @uploads, $param, $upload );
+        }
     }
-}
 
-sub run { shift->handler }
+    $c->request->upload(@uploads);
+}
 
 =back
 
 =head1 SEE ALSO
 
-L<Catalyst>.
+L<Catalyst> L<Catalyst::Engine> L<Catalyst::Engine::CGI::Base>.
 
 =head1 AUTHOR
 
 Sebastian Riedel, C<sri@cpan.org>
+Christian Hansen, C<ch@ngmedia.com>
 
 =head1 COPYRIGHT