1 |
|
2 |
=head1 NAME |
3 |
|
4 |
Message::Field::URI --- A Perl Module for Internet Message |
5 |
Header Field Bodies filled with a URI |
6 |
|
7 |
=cut |
8 |
|
9 |
package Message::Field::URI; |
10 |
use strict; |
11 |
use vars qw(%DEFAULT @ISA %REG $VERSION); |
12 |
$VERSION=do{my @r=(q$Revision: 1.7 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r}; |
13 |
require Message::Header; |
14 |
require Message::Field::AngleQuoted; |
15 |
push @ISA, qw(Message::Field::AngleQuoted); |
16 |
|
17 |
%REG = %Message::Util::REG; |
18 |
|
19 |
=head1 CONSTRUCTORS |
20 |
|
21 |
The following methods construct new objects: |
22 |
|
23 |
=over 4 |
24 |
|
25 |
=cut |
26 |
|
27 |
%DEFAULT = ( |
28 |
-_MEMBERS => [qw|display_name|], |
29 |
-_METHODS => [qw|display_name uri |
30 |
comment_add comment_delete comment_item |
31 |
comment_count|], |
32 |
-allow_absolute => 1, ## TODO: not implemented |
33 |
-allow_empty => 1, |
34 |
-allow_fragment => 1, ## TODO: not implemented |
35 |
-allow_relative => 1, ## TODO: not implemented |
36 |
#comment_to_display_name => 0, |
37 |
#encoding_after_encode |
38 |
#encoding_before_decode |
39 |
#field_param_name |
40 |
#field_name |
41 |
#hook_encode_string |
42 |
#hook_decode_string |
43 |
#output_angle_bracket => 1, |
44 |
#output_comment => 1, |
45 |
#output_display_name => 1, |
46 |
#output_keyword => 0, |
47 |
#parse_all |
48 |
-value_pattern => '%s', |
49 |
#unsafe_rule_of_display_name => 'NON_http_attribute_char_wsp', |
50 |
#unsafe_rule_of_keyword |
51 |
#use_comment => 1, |
52 |
#use_display_name => 1, |
53 |
#use_keyword => 0, |
54 |
); |
55 |
|
56 |
sub _init ($;%) { |
57 |
my $self = shift; |
58 |
my %options = @_; |
59 |
my $DEFAULT = Message::Util::make_clone (\%DEFAULT); |
60 |
$self->SUPER::_init (%$DEFAULT, %options); |
61 |
#$self->{option}->{value_type}->{uri} = ['URI::']; |
62 |
|
63 |
my $format = $self->{option}->{format}; |
64 |
my $field = $self->{option}->{field_name}; |
65 |
my $fieldns = $self->{option}->{field_ns}; |
66 |
$format = 'mhtml' if $format =~ /mail|news/; |
67 |
if ($fieldns eq $Message::Header::NS_phname2uri{list}) { ## List-* |
68 |
$self->{option}->{output_display_name} = 0; |
69 |
$self->{option}->{allow_empty} = 0; |
70 |
} elsif ($fieldns eq $Message::Header::NS_phname2uri{content}) { |
71 |
if ($field eq 'location') { ## Content-Location |
72 |
$self->{option}->{output_angle_bracket} = 0; |
73 |
$self->{option}->{output_display_name} = 0; |
74 |
$self->{option}->{output_comment} = 0; |
75 |
$self->{option}->{use_display_name} = 0; |
76 |
$self->{option}->{allow_fragment} = 0; |
77 |
} elsif ($field eq 'base') { ## Content-Base |
78 |
$self->{option}->{output_angle_bracket} = 0; |
79 |
$self->{option}->{output_comment} = 0; |
80 |
$self->{option}->{use_display_name} = 0; |
81 |
$self->{option}->{allow_relative} = 0; |
82 |
$self->{option}->{allow_fragment} = 0; |
83 |
} |
84 |
} elsif ($field eq 'link') { ## HTTP |
85 |
$self->{option}->{output_display_name} = 0; |
86 |
$self->{option}->{output_comment} = 0; |
87 |
$self->{option}->{allow_fragment} = 0; |
88 |
} elsif ($field eq 'location') { ## HTTP / HTTP-CGI |
89 |
$self->{option}->{output_angle_bracket} = 0; |
90 |
$self->{option}->{use_comment} = 0; |
91 |
$self->{option}->{use_display_name} = 0; |
92 |
if ($format =~ /cgi/) { |
93 |
$self->{option}->{allow_relative} = 0; |
94 |
$self->{option}->{allow_fragment} = 0; |
95 |
} |
96 |
} elsif ($field eq 'uri') { ## HTTP |
97 |
$self->{option}->{output_comment} = 0; |
98 |
$self->{option}->{output_display_name} = 0; |
99 |
} |
100 |
} |
101 |
|
102 |
=item $uri = Message::Field::URI->new ([%options]) |
103 |
|
104 |
Constructs a new object. You might pass some options as parameters |
105 |
to the constructor. |
106 |
|
107 |
=cut |
108 |
|
109 |
## Inherited |
110 |
|
111 |
=item $uri = Message::Field::URI->parse ($field-body, [%options]) |
112 |
|
113 |
Constructs a new object with given field body. You might pass |
114 |
some options as parameters to the constructor. |
115 |
|
116 |
=cut |
117 |
|
118 |
## $self->_save_value ($value, $display_name, \@comment) |
119 |
sub _save_value ($$\@%) { |
120 |
my $self = shift; |
121 |
my ($v, $dn, $comment, %misc) = @_; |
122 |
$v =~ tr/\x09\x0A\x0D\x20//d; |
123 |
$v =~ s/^[Uu][Rr][LlIi]://; |
124 |
$v = $self->_parse_value (uri => $v) if $self->{option}->{parse_all}; |
125 |
$self->{value} = $v; |
126 |
$self->{display_name} = $dn; |
127 |
$self->{comment} = $comment; |
128 |
$self->{keyword} = $misc{keyword}; |
129 |
} |
130 |
|
131 |
=head2 $URI = $uri->uri ([$newURI]) |
132 |
|
133 |
Set/gets C<URI>. See also L<NOTE>. |
134 |
|
135 |
=cut |
136 |
|
137 |
sub uri ($;$%) { shift->value (@_) } |
138 |
|
139 |
## display_name: Inherited |
140 |
|
141 |
## stringify: Inherited |
142 |
|
143 |
## $self->_stringify_value (\%option) |
144 |
sub _stringify_value ($\%) { |
145 |
my $self = shift; |
146 |
my $option = shift; |
147 |
my %r; |
148 |
my $v = $self->{value}; |
149 |
unless (ref $v) { |
150 |
$v =~ s/([\x00-\x20\x22\x3C\x3E\x5C\x7F-\xFF])/sprintf('%%%02X', ord $1)/ge; |
151 |
} |
152 |
$r{value} = sprintf $option->{value_pattern}, $v; |
153 |
$r{display_name} = $self->{display_name}; |
154 |
$r{comment} = $self->{comment}; |
155 |
$r{keyword} = $self->{keyword}; |
156 |
%r; |
157 |
} |
158 |
|
159 |
=head1 NOTE |
160 |
|
161 |
Current version of this module does not check whether |
162 |
URI is correct or not. In particullar, implementor |
163 |
should be careful not to output URI that is syntactically |
164 |
valid, but do not match to context. For example, |
165 |
C<Location:> field defined by HTTP/1.1 [RFC2616] doesn't |
166 |
allow relative URIs. (Interestingly, with CGI/1.1, |
167 |
we can use relative URI as value of C<Location> field. |
168 |
|
169 |
There is three options related with URI type. |
170 |
C<allow_absolute>, C<allow_relative>, and C<allow_fragment>. |
171 |
But this options don't work as you hope. |
172 |
These options are only reserved for future implemention. |
173 |
|
174 |
=head1 LICENSE |
175 |
|
176 |
Copyright 2002 wakaba E<lt>w@suika.fam.cxE<gt>. |
177 |
|
178 |
This program is free software; you can redistribute it and/or modify |
179 |
it under the terms of the GNU General Public License as published by |
180 |
the Free Software Foundation; either version 2 of the License, or |
181 |
(at your option) any later version. |
182 |
|
183 |
This program is distributed in the hope that it will be useful, |
184 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
185 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
186 |
GNU General Public License for more details. |
187 |
|
188 |
You should have received a copy of the GNU General Public License |
189 |
along with this program; see the file COPYING. If not, write to |
190 |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
191 |
Boston, MA 02111-1307, USA. |
192 |
|
193 |
=head1 CHANGE |
194 |
|
195 |
See F<ChangeLog>. |
196 |
$Date: 2002/08/03 04:57:59 $ |
197 |
|
198 |
=cut |
199 |
|
200 |
1; |