Converted C::P::CGIBin to C::C::CGIBin, added regex env key support
[catagits/Catalyst-Controller-WrapCGI.git] / lib / Catalyst / Controller / CGIBin.pm
1 package Catalyst::Controller::CGIBin;
2
3 use strict;
4 use warnings;
5
6 use Class::C3;
7 use URI::Escape;
8 use File::Slurp 'slurp';
9 use File::Find::Rule ();
10 use Cwd;
11 use Catalyst::Exception ();
12 use File::Spec::Functions 'splitdir';
13
14 use parent 'Catalyst::Controller::WrapCGI';
15
16 =head1 NAME
17
18 Catalyst::Controller::CGIBin - Serve CGIs from root/cgi-bin
19
20 =head1 VERSION
21
22 Version 0.001
23
24 =cut
25
26 our $VERSION = '0.001';
27
28 =head1 SYNOPSIS
29
30 In your controller:
31
32     package MyApp::Controller::Foo;
33
34     use parent qw/Catalyst::Controller::CGIBin/;
35
36     # example of a forward to /cgi-bin/hlagh/mtfnpy.cgi
37     sub dongs : Local Args(0) {
38         my ($self, $c) = @_;
39         $c->forward($self->cgi_action('hlagh/mtfnpy.cgi'));
40     }
41
42 In your .conf:
43
44     <Controller::Foo>
45         <CGI>
46             username_field username # used for REMOTE_USER env var
47             pass_env PERL5LIB
48             pass_env PATH
49             pass_env /^MYAPP_/
50         </CGI>
51     </Controller::Foo>
52
53 =head1 DESCRIPTION
54
55 Dispatches to executable CGI files in root/cgi-bin for /cgi-bin/ paths.
56
57 A path such as C<root/cgi-bin/hlagh/bar.cgi> will get the private path
58 C<foo/CGI_hlagh_bar_cgi>, for controller Foo, with the C</>s converted to C<_>s
59 and prepended with C<CGI_>, as well as all non-word characters converted to
60 C<_>s. This is because L<Catalyst> action names can't have non-word characters
61 in them.
62
63 Inherits from L<Catalyst::Controller::WrapCGI>, see the documentation for that
64 module for configuration information.
65
66 =cut
67
68 sub register_actions {
69     my ($self, $c) = @_;
70
71     my $cwd = getcwd;
72
73     my $cgi_bin = $c->path_to('root', 'cgi-bin');
74
75     chdir $cgi_bin ||
76         Catalyst::Exception->throw(
77             message => 'You have no root/cgi-bin directory'
78         );
79
80     my $namespace = $self->action_namespace($c);
81
82     my $class = ref $self || $self;
83
84     for my $file (File::Find::Rule->executable->file->in(".")) {
85         my ($cgi, $type);
86         my $code = do { no warnings; eval 'sub { '.slurp($file).' }' };
87
88         if (!$@) {
89             $cgi = $code;
90             $type = 'Perl';
91         } else {
92             $cgi = sub { system "$cgi_bin/$file" };
93             $type = 'Non-Perl';
94             undef $@;
95         }
96
97         $c->log->info("Registering root/cgi_bin/$file as a $type CGI.")
98             if $c->debug;
99
100         my $action_name = $self->cgi_action($file);
101         my $path        = join '/' => splitdir($file);
102         my $reverse     = $namespace ? "$namespace/$action_name" : $action_name;
103         my $attrs       = { Path => [ "cgi-bin/$path" ], Args => [ 0 ] };
104
105         $code = sub {
106             my ($controller, $context) = @_;
107             $controller->cgi_to_response($context, $cgi)
108         };
109
110         my $action = $self->create_action(
111             name       => $action_name,
112             code       => $code,
113             reverse    => $reverse,
114             namespace  => $namespace,
115             class      => $class,
116             attributes => $attrs
117         );
118
119         $c->dispatcher->register($c, $action);
120     }
121
122     chdir $cwd;
123
124     $self->next::method($c, @_);
125 }
126
127 =head1 METHODS
128
129 =head2 $self->cgi_action($cgi_path)
130
131 Takes a path to a CGI from C<root/cgi-bin> such as C<foo/bar.cgi> and returns
132 the action name it is registered as.
133
134 =cut
135
136 sub cgi_action {
137     my ($self, $cgi) = @_;
138
139     my $action_name = 'CGI_' . join '_' => splitdir($cgi);
140     $action_name    =~ s/\W/_/g;
141
142     $action_name
143 }
144
145 =head1 AUTHOR
146
147 Rafael Kitover, C<< <rkitover at cpan.org> >>
148
149 =head1 BUGS
150
151 Please report any bugs or feature requests to C<bug-catalyst-controller-wrapcgi at
152 rt.cpan.org>, or through the web interface at
153 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-Controller-WrapCGI>.
154 I will be notified, and then you'll automatically be notified of progress on
155 your bug as I make changes.
156
157 =head1 SUPPORT
158
159 More information at:
160
161 =over 4
162
163 =item * RT: CPAN's request tracker
164
165 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Catalyst-Controller-WrapCGI>
166
167 =item * AnnoCPAN: Annotated CPAN documentation
168
169 L<http://annocpan.org/dist/Catalyst-Controller-WrapCGI>
170
171 =item * CPAN Ratings
172
173 L<http://cpanratings.perl.org/d/Catalyst-Controller-WrapCGI>
174
175 =item * Search CPAN
176
177 L<http://search.cpan.org/dist/Catalyst-Controller-WrapCGI>
178
179 =back
180
181 =head1 COPYRIGHT & LICENSE
182
183 Copyright (c) 2008 Rafael Kitover
184
185 This program is free software; you can redistribute it and/or modify it
186 under the same terms as Perl itself.
187
188 =cut
189
190 1; # End of Catalyst::Controller::CGIBin
191
192 # vim: expandtab shiftwidth=4 ts=4 tw=80: