/[suikacvs]/messaging/manakai/lib/Message/CGI/HTTP.pm
Suika

Contents of /messaging/manakai/lib/Message/CGI/HTTP.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations) (download)
Sat Aug 11 13:37:09 2007 UTC (17 years, 3 months ago) by wakaba
Branch: MAIN
Changes since 1.1: +86 -85 lines
++ manakai/lib/Message/ChangeLog	11 Aug 2007 13:36:49 -0000
2007-08-11  Wakaba  <wakaba@suika.fam.cx>

	* Makefile: New directory |CGI| is added.

2007-08-11  Wakaba  <wakaba@suika.fam.cx>

	* CGI/: New directory.

++ manakai/lib/Message/CGI/ChangeLog	11 Aug 2007 13:33:26 -0000
	* Makefile: New file.

	* HTTP.pm: Reformed for manakai.

2007-08-11  Wakaba  <wakaba@suika.fam.cx>

1 wakaba 1.1 =head1 NAME
2    
3 wakaba 1.2 Message::CGI::HTTP - An Object-Oriented HTTP CGI Interface
4 wakaba 1.1
5     =head1 DESCRIPTION
6    
7 wakaba 1.2 The C<Message::CGI::HTTP> module provides an object-oriented
8     interface for inputs and outputs as defined by CGI specification.
9 wakaba 1.1
10 wakaba 1.2 This module is part of manakai.
11 wakaba 1.1
12     =cut
13    
14 wakaba 1.2 package Message::CGI::HTTP;
15 wakaba 1.1 use strict;
16 wakaba 1.2 our $VERSION = do{my @r=(q$Revision: 1.1 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
17     push our @ISA, 'Message::IF::CGIRequest';
18 wakaba 1.1
19     =head1 METHODS
20    
21     =over 4
22    
23 wakaba 1.2 =item I<$cgi> = Message::CGI::HTTP->new;
24 wakaba 1.1
25 wakaba 1.2 Creates and returns a new instance of HTTP CGI interface object.
26 wakaba 1.1
27     =cut
28    
29     sub new ($;%) {
30     my $self = bless {
31     decoder => {
32     '#default' => sub {$_[1]},
33     },
34     }, shift;
35     my %opt = @_;
36 wakaba 1.2 $self->{-in_handle} = *main::STDIN;
37 wakaba 1.1 $self;
38 wakaba 1.2 } # new
39    
40     =item I<$value> = I<$cgi>->get_meta_variable (I<$name>)
41 wakaba 1.1
42 wakaba 1.2 Returns the value of the meta-variable I<$name>. The name
43     specified by the I<$name> SHOULD be a meta-variable name
44     defined by a CGI specification, e.g. C<CONTENT_TYPE> or
45     C<HTTP_USER_AGENT>. Otherwise, the result is implementation
46     dependent. In an environment where meta-variables are supplied
47     as envirnoment variables, specifying an environment variable
48     that is not a meta-variable, such as C<PATH>, results in the
49     value of that environment variable. However, CGI scripts
50     SHOULD NOT depend on such behavior.
51 wakaba 1.1
52 wakaba 1.2 This method might return C<undef> when the meta-variable
53     is not defined or is defined but its value is C<undef>.
54 wakaba 1.1
55     =cut
56    
57 wakaba 1.2 sub get_meta_variable ($$) {
58     return $main::ENV{ $_[1] };
59     } # get_meta_variable
60 wakaba 1.1
61 wakaba 1.2 =item I<$list> = I<$cgi>->meta_variable_names;
62 wakaba 1.1
63     Returns list of meta variables. Note that this list might contain
64     other environmental variables than CGI meta variables, since
65     they cannot distinglish unless we know what is CGI meta variable
66     and what is not. Unfortunately, there is no complete list of CGI
67     meta variables, whilst list of standarized meta variables is available.
68    
69     NOTE: Some application might use an environmental variable named
70     'HTTP_HOME', which might make some confusion with CGI meta variable
71     for HTTP 'Home:' header field. Fortunately, such name of HTTP
72     header field is not intoroduced as far as I know.
73    
74 wakaba 1.2 This method returns a C<L<Message::DOM::DOMStringList>>.
75    
76 wakaba 1.1 =cut
77    
78 wakaba 1.2 sub meta_variable_names ($) {
79     require Message::DOM::DOMStringList;
80     bless [keys %main::ENV], 'Message::DOM::DOMStringList::StaticList';
81     } # meta_variable_names
82 wakaba 1.1
83 wakaba 1.2 =item I<$value> = C<$cgi>->get_parameter ($name);
84 wakaba 1.1
85     Returns parameter value if any.
86     Parameter value is set by query-string of Request-URI
87     and/or entity-body value.
88    
89     When multiple values with same parameter name is specified,
90     the first one is returned in scalar context or
91     an array reference of all values is returned in array context.
92     (Note that query-string is "earlier" than entity-body.)
93    
94 wakaba 1.2 =cut
95    
96     sub get_parameter ($$) {
97     my ($self, $name) = @_;
98     $self->__get_parameter unless $self->{param};
99    
100     if (wantarray) {
101     return @{$self->{param}->{$name}||[]};
102     } else {
103     return ${$self->{param}->{$name}||[]}[0];
104     }
105     } # get_parameter
106    
107     =item I<$keys> = I<$cgi>->parameter_names;
108 wakaba 1.1
109     Returnes a list of parameter names provided.
110    
111 wakaba 1.2 This method returns a C<L<Message::DOM::DOMStringList>>.
112    
113 wakaba 1.1 =cut
114    
115     sub parameter_names ($) {
116     my $self = shift;
117     $self->__get_parameter unless $self->{param};
118 wakaba 1.2
119     require Message::DOM::DOMStringList;
120     return bless [keys %{$self->{param}}],
121     'Message::DOM::DOMStringList::StaticList';
122     } # parameter_names
123 wakaba 1.1
124     sub __get_parameter ($) {
125     my $self = shift;
126     my @src;
127    
128     ## Query-string of Request-URI
129     my $qs = $self->meta_variable ('QUERY_STRING');
130     push @src, $qs if (index ($qs, '=') > -1);
131    
132     ## Entity-body
133     if ($self->meta_variable ('REQUEST_METHOD') eq 'POST') {
134     my $mt = $self->meta_variable ('CONTENT_TYPE');
135     if ($mt =~ m<^application/(?:x-www|sgml)-form-urlencoded\b>) {
136     push @src, $self->body_text;
137     }
138     ## TODO: support non-standard "charset" parameter
139     }
140    
141     my %temp_params;
142     for my $src (@src) {
143     for (split /[;&]/, $src) {
144     my ($name, $val) = split '=', $_, 2;
145     for ($name, $val) {
146     tr/+/ /;
147     s/%([0-9A-Fa-f][0-9A-Fa-f])/pack 'C', hex $1/ge;
148     }
149     $temp_params{$name} ||= [];
150     push @{$temp_params{$name}}, $val;
151     }
152     }
153     for (keys %temp_params) {
154     my $name = &{$self->{decoder}->{'#name'}
155     ||$self->{decoder}->{'#default'}} ($self, $_, \%temp_params);
156     for (@{$temp_params{$name}}) {
157     push @{$self->{param}->{$name}},
158     &{$self->{decoder}->{$name}
159     ||$self->{decoder}->{'#default'}} ($self, $_, \%temp_params);
160     }
161     }
162 wakaba 1.2 } # _get_parameter
163 wakaba 1.1
164 wakaba 1.2 =item I<$body> = I<$cgi>->entity_body;
165 wakaba 1.1
166     Returns entity-body content if any.
167    
168     =cut
169    
170 wakaba 1.2 sub entity_body ($) {
171 wakaba 1.1 my $self = shift;
172     $self->__get_entity_body unless defined $self->{body};
173    
174 wakaba 1.2 return $self->{body};
175     } # entity_body
176 wakaba 1.1
177     sub __get_entity_body ($) {
178     my $self = shift;
179     binmode $self->{-in_handle};
180     read $self->{-in_handle}, $self->{body},
181     $self->meta_variable ('CONTENT_LENGTH');
182 wakaba 1.2 } # __get_entity_body
183 wakaba 1.1 ## TODO: Entity too large
184    
185 wakaba 1.2 =item I<$uri> = I<$cgi>->request_uri;
186 wakaba 1.1
187 wakaba 1.2 Returns Request-URI as a C<L<Message::URI::URIReference>> object.
188 wakaba 1.1
189     Note that stringified value of returned value might not be same as the
190     URI specified as the Request-URI of HTTP request or (possibly pseudo-)
191     URI entered by the user, since no standarized way to get it is
192     defined by HTTP and CGI/1.1 specifications.
193    
194     =cut
195    
196     sub request_uri ($;%) {
197     my ($self, %opt) = @_;
198 wakaba 1.2 require Message::URI::URIReference;
199 wakaba 1.1 my $uri = $opt{no_path_info} ? undef
200     : $self->meta_variable ('REQUEST_URI'); # non-standard
201     if ($uri) {
202     $uri =~ s/\#[^#]*$//; ## Fragment identifier not allowed here
203     $uri =~ s/\?[^?]*$// if $opt{no_query};
204     if ($uri =~ /^[0-9A-Za-z.%+-]+:/) { ## REQUEST_URI is an absolute URI
205 wakaba 1.2 return Message::DOM::DOMImplementation->create_uri_reference ($uri);
206 wakaba 1.1 }
207     } else { ## REQUEST_URI is not provided
208     my $pi = $opt{no_path_info} ? q<>
209     : $self->meta_variable ('PATH_INFO');
210     $uri = $self->__uri_encode ($self->meta_variable ('SCRIPT_NAME').$pi,
211     qr([^0-9A-Za-z_.!~*'();/:\@&=\$,-]));
212     my $qs = $self->meta_variable ('QUERY_STRING');
213     $uri .= '?' . $qs if not $opt{no_query} and defined $qs;
214     }
215    
216     ## REQUEST_URI is a relative URI or
217     ## REQUEST_URI is not provided
218     my $scheme = 'http';
219     my $port = ':' . $self->meta_variable ('SERVER_PORT');
220     ## TODO: HTTPS=off
221     if ( $self->meta_variable ('HTTPS')
222     || $self->meta_variable ('CERT_SUBJECT')
223     || $self->meta_variable ('SSL_VERSION')) {
224     $scheme = 'https';
225     $port = '' if $port eq ':443';
226     } else {
227     $port = '' if $port eq ':80';
228     }
229    
230     my $host_and_port = $self->meta_variable ('HTTP_HOST');
231     if ($host_and_port) {
232     $uri = $scheme . '://'
233     . $self->__uri_encode ($host_and_port, qr/[^0-9A-Za-z.:-]/)
234     . $uri; ## ISSUE: Should we allow "[" / "]" for IPv6 here?
235     } else {
236     $uri = $scheme . '://'
237     . $self->__uri_encode ($self->meta_variable ('SERVER_NAME'),
238     qr/[^0-9A-Za-z.-]/)
239     . $port . $uri;
240     }
241 wakaba 1.2 return Message::DOM::DOMImplementation->create_uri_reference ($uri);
242     } # request_uri
243 wakaba 1.1
244     sub __uri_encode ($$;$) {
245     my ($self, $s, $char) = @_;
246     $char ||= qr([^0-9A-Za-z_.!~*'();/?:\@&=+\$,-]);
247     require Encode;
248     $s = Encode::decode ('utf8', $s);
249     $s =~ s/($char)/sprintf '%%%02X', ord $1/ge;
250 wakaba 1.2 return $s;
251     } # __uri_encode
252 wakaba 1.1
253 wakaba 1.2 package Message::IF::CGIRequest;
254 wakaba 1.1
255 wakaba 1.2 =back
256 wakaba 1.1
257 wakaba 1.2 =head1 TODO
258 wakaba 1.1
259 wakaba 1.2 =over 4
260 wakaba 1.1
261 wakaba 1.2 =item multipart/form-data support
262 wakaba 1.1
263 wakaba 1.2 =back
264 wakaba 1.1
265 wakaba 1.2 =head1 SEE ALSO
266 wakaba 1.1
267 wakaba 1.2 A draft specification for DOM CGI Module
268     <http://suika.fam.cx/gate/2005/sw/manakai/%E3%83%A1%E3%83%A2/2005-07-04>
269     (This module does not implement the interface defined in this
270     specification, however.)
271 wakaba 1.1
272 wakaba 1.2 =head1 AUTHOR
273 wakaba 1.1
274 wakaba 1.2 Wakaba <w@suika.fam.cx>
275 wakaba 1.1
276     =head1 LICENSE
277    
278 wakaba 1.2 Copyright 2003, 2007 Wakaba <w@suika.fam.cx>
279 wakaba 1.1
280     This program is free software; you can redistribute it and/or
281     modify it under the same terms as Perl itself.
282    
283     =cut
284    
285 wakaba 1.2 1;
286     # $Date: 2007/08/11 13:06:39 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24