/[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.5 - (hide annotations) (download)
Sun Nov 9 14:06:23 2008 UTC (16 years ago) by wakaba
Branch: MAIN
Changes since 1.4: +8 -3 lines
++ manakai/lib/Message/CGI/ChangeLog	29 Oct 2008 05:42:58 -0000
2008-10-29  Wakaba  <wakaba@suika.fam.cx>

	* HTTP.pm (remote_user): New method.

++ manakai/lib/Message/DOM/ChangeLog	9 Nov 2008 14:06:17 -0000
2008-11-09  Wakaba  <wakaba@suika.fam.cx>

	* Element.pm (inner_html): Setter for HTML element nodes
	implemented.

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.5 our $VERSION = do{my @r=(q$Revision: 1.4 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
17 wakaba 1.4 push our @ISA, 'Message::IF::CGIRequest', 'Message::IF::HTTPCGIRequest';
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.3 This method returns a C<Message::DOM::DOMStringList>.
75 wakaba 1.2
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.3 This method returns a C<Message::DOM::DOMStringList>.
112 wakaba 1.2
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 wakaba 1.3 my $qs = $self->get_meta_variable ('QUERY_STRING');
130 wakaba 1.1 push @src, $qs if (index ($qs, '=') > -1);
131    
132     ## Entity-body
133 wakaba 1.3 if ($self->get_meta_variable ('REQUEST_METHOD') eq 'POST') {
134     my $mt = $self->get_meta_variable ('CONTENT_TYPE');
135 wakaba 1.5 ## TODO: Uppercase
136 wakaba 1.1 if ($mt =~ m<^application/(?:x-www|sgml)-form-urlencoded\b>) {
137 wakaba 1.3 push @src, $self->entity_body;
138 wakaba 1.1 }
139     ## TODO: support non-standard "charset" parameter
140     }
141    
142     my %temp_params;
143     for my $src (@src) {
144     for (split /[;&]/, $src) {
145     my ($name, $val) = split '=', $_, 2;
146     for ($name, $val) {
147     tr/+/ /;
148     s/%([0-9A-Fa-f][0-9A-Fa-f])/pack 'C', hex $1/ge;
149     }
150     $temp_params{$name} ||= [];
151     push @{$temp_params{$name}}, $val;
152     }
153     }
154     for (keys %temp_params) {
155     my $name = &{$self->{decoder}->{'#name'}
156     ||$self->{decoder}->{'#default'}} ($self, $_, \%temp_params);
157     for (@{$temp_params{$name}}) {
158     push @{$self->{param}->{$name}},
159     &{$self->{decoder}->{$name}
160     ||$self->{decoder}->{'#default'}} ($self, $_, \%temp_params);
161     }
162     }
163 wakaba 1.3 } # __get_parameter
164 wakaba 1.1
165 wakaba 1.2 =item I<$body> = I<$cgi>->entity_body;
166 wakaba 1.1
167     Returns entity-body content if any.
168    
169     =cut
170    
171 wakaba 1.2 sub entity_body ($) {
172 wakaba 1.1 my $self = shift;
173     $self->__get_entity_body unless defined $self->{body};
174    
175 wakaba 1.2 return $self->{body};
176     } # entity_body
177 wakaba 1.1
178     sub __get_entity_body ($) {
179     my $self = shift;
180     binmode $self->{-in_handle};
181     read $self->{-in_handle}, $self->{body},
182 wakaba 1.3 $self->get_meta_variable ('CONTENT_LENGTH');
183 wakaba 1.2 } # __get_entity_body
184 wakaba 1.1 ## TODO: Entity too large
185    
186 wakaba 1.2 =item I<$uri> = I<$cgi>->request_uri;
187 wakaba 1.1
188 wakaba 1.3 Returns Request-URI as a C<Message::URI::URIReference> object.
189 wakaba 1.1
190     Note that stringified value of returned value might not be same as the
191     URI specified as the Request-URI of HTTP request or (possibly pseudo-)
192     URI entered by the user, since no standarized way to get it is
193     defined by HTTP and CGI/1.1 specifications.
194    
195     =cut
196    
197     sub request_uri ($;%) {
198     my ($self, %opt) = @_;
199 wakaba 1.2 require Message::URI::URIReference;
200 wakaba 1.1 my $uri = $opt{no_path_info} ? undef
201 wakaba 1.3 : $self->get_meta_variable ('REQUEST_URI'); # non-standard
202 wakaba 1.1 if ($uri) {
203     $uri =~ s/\#[^#]*$//; ## Fragment identifier not allowed here
204     $uri =~ s/\?[^?]*$// if $opt{no_query};
205     if ($uri =~ /^[0-9A-Za-z.%+-]+:/) { ## REQUEST_URI is an absolute URI
206 wakaba 1.2 return Message::DOM::DOMImplementation->create_uri_reference ($uri);
207 wakaba 1.1 }
208     } else { ## REQUEST_URI is not provided
209     my $pi = $opt{no_path_info} ? q<>
210 wakaba 1.3 : $self->get_meta_variable ('PATH_INFO');
211     $uri = $self->__uri_encode ($self->get_meta_variable ('SCRIPT_NAME').$pi,
212 wakaba 1.1 qr([^0-9A-Za-z_.!~*'();/:\@&=\$,-]));
213 wakaba 1.3 my $qs = $self->get_meta_variable ('QUERY_STRING');
214 wakaba 1.1 $uri .= '?' . $qs if not $opt{no_query} and defined $qs;
215     }
216    
217     ## REQUEST_URI is a relative URI or
218     ## REQUEST_URI is not provided
219     my $scheme = 'http';
220 wakaba 1.3 my $port = ':' . $self->get_meta_variable ('SERVER_PORT');
221 wakaba 1.1 ## TODO: HTTPS=off
222 wakaba 1.3 if ( $self->get_meta_variable ('HTTPS')
223     || $self->get_meta_variable ('CERT_SUBJECT')
224     || $self->get_meta_variable ('SSL_VERSION')) {
225 wakaba 1.1 $scheme = 'https';
226     $port = '' if $port eq ':443';
227     } else {
228     $port = '' if $port eq ':80';
229     }
230    
231 wakaba 1.3 my $host_and_port = $self->get_meta_variable ('HTTP_HOST');
232 wakaba 1.1 if ($host_and_port) {
233     $uri = $scheme . '://'
234     . $self->__uri_encode ($host_and_port, qr/[^0-9A-Za-z.:-]/)
235     . $uri; ## ISSUE: Should we allow "[" / "]" for IPv6 here?
236     } else {
237     $uri = $scheme . '://'
238 wakaba 1.3 . $self->__uri_encode ($self->get_meta_variable ('SERVER_NAME'),
239 wakaba 1.1 qr/[^0-9A-Za-z.-]/)
240     . $port . $uri;
241     }
242 wakaba 1.2 return Message::DOM::DOMImplementation->create_uri_reference ($uri);
243     } # request_uri
244 wakaba 1.1
245     sub __uri_encode ($$;$) {
246     my ($self, $s, $char) = @_;
247     $char ||= qr([^0-9A-Za-z_.!~*'();/?:\@&=+\$,-]);
248     require Encode;
249     $s = Encode::decode ('utf8', $s);
250     $s =~ s/($char)/sprintf '%%%02X', ord $1/ge;
251 wakaba 1.2 return $s;
252     } # __uri_encode
253 wakaba 1.1
254 wakaba 1.4 =item I<$value> = I<$cgi>->path_info ([I<$new_value>]);
255    
256 wakaba 1.5 =item I<$value> = I<$cgi>->remote_user ([I<$new_value>]);
257    
258     These methods reflect meta-variables with the same name (in
259     uppercase).
260 wakaba 1.4
261     =cut
262    
263     for (
264     [path_info => 'PATH_INFO'],
265     [query_string => 'QUERY_STRING'],
266 wakaba 1.5 [remote_user => 'REMOTE_USER'],
267 wakaba 1.4 [request_method => 'REQUEST_METHOD'],
268     [script_name => 'SCRIPT_NAME'],
269     ) {
270     eval qq{
271     sub $_->[0] (\$;\$) {
272     if (\@_ > 1) {
273     if (defined \$_[1]) {
274     \$main::ENV{'$_->[1]'} = ''.\$_[1];
275     } else {
276     delete \$main::ENV{'$_->[1]'};
277     }
278     }
279     return \$main::ENV{'$_->[1]'};
280     }
281     };
282     }
283    
284 wakaba 1.2 package Message::IF::CGIRequest;
285 wakaba 1.4 package Message::IF::HTTPCGIRequest;
286 wakaba 1.1
287 wakaba 1.2 =back
288 wakaba 1.1
289 wakaba 1.2 =head1 TODO
290 wakaba 1.1
291 wakaba 1.2 =over 4
292 wakaba 1.1
293 wakaba 1.2 =item multipart/form-data support
294 wakaba 1.1
295 wakaba 1.2 =back
296 wakaba 1.1
297 wakaba 1.2 =head1 SEE ALSO
298 wakaba 1.1
299 wakaba 1.2 A draft specification for DOM CGI Module
300     <http://suika.fam.cx/gate/2005/sw/manakai/%E3%83%A1%E3%83%A2/2005-07-04>
301     (This module does not implement the interface defined in this
302     specification, however.)
303 wakaba 1.1
304 wakaba 1.2 =head1 AUTHOR
305 wakaba 1.1
306 wakaba 1.2 Wakaba <w@suika.fam.cx>
307 wakaba 1.1
308 wakaba 1.3 This module was originally developed as part of SuikaWiki.
309    
310 wakaba 1.1 =head1 LICENSE
311    
312 wakaba 1.2 Copyright 2003, 2007 Wakaba <w@suika.fam.cx>
313 wakaba 1.1
314     This program is free software; you can redistribute it and/or
315     modify it under the same terms as Perl itself.
316    
317     =cut
318    
319 wakaba 1.2 1;
320 wakaba 1.5 # $Date: 2007/08/22 10:59:43 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24