/[suikacvs]/messaging/manakai/lib/Message/Field/URI.pm
Suika

Contents of /messaging/manakai/lib/Message/Field/URI.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide annotations) (download)
Fri May 17 05:42:27 2002 UTC (22 years, 6 months ago) by wakaba
Branch: MAIN
Changes since 1.2: +142 -280 lines
2002-05-17  wakaba <w@suika.fam.cx>

	* Mailbox.pm: Bug fix and minor changes.
	* URI.pm: Remade.  It is now designed by M::F::Mailbox
	like interface.

1 wakaba 1.1
2     =head1 NAME
3    
4 wakaba 1.3 Message::Field::URI --- A perl module for a URI
5     which is part of Internet Messages
6 wakaba 1.1
7     =cut
8    
9     package Message::Field::URI;
10     use strict;
11     require 5.6.0;
12     use re 'eval';
13 wakaba 1.3 use vars qw(%DEFAULT @ISA %REG $VERSION);
14     $VERSION=do{my @r=(q$Revision: 1.2 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
15     require Message::Field::Structured;
16     push @ISA, qw(Message::Field::Structured);
17 wakaba 1.1
18     $REG{WSP} = qr/[\x09\x20]/;
19     $REG{FWS} = qr/[\x09\x20]*/;
20    
21 wakaba 1.3 %REG = %Message::Util::REG;
22     $REG{SCM_angle_quoted} = qr/<([^\x3E]*)>/;
23    
24 wakaba 1.1 $REG{uri_literal} = qr/\x3C[\x09\x20\x21\x23-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E]*\x3E/;
25     $REG{phrase} = qr/(?:$REG{atext}|$REG{quoted_string})(?:$REG{atext}|$REG{quoted_string}|\.|$REG{FWS})*/;
26     $REG{phrase_c} = qr/(?:$REG{atext}|$REG{quoted_string}|$REG{comment}|\.|$REG{FWS})*/;
27    
28 wakaba 1.3 ## Simple version of URI regex See RFC 2396, RFC 2732, RFC 2324.
29     $REG{escaped} = qr/%[0-9A-Fa-f][0-9A-Fa-f]/;
30     $REG{scheme} = qr/(?:[A-Za-z]|$REG{escaped})(?:[0-9A-Za-z+.-]|$REG{escaped})*/;
31     ## RFC 2324 defines escaped UTF-8 schemes:-)
32     $REG{fragment} = qr/\x23(?:[\x21\x24\x26-\x3B\x3D\x3F-\x5A\x5F\x61-\x7A\x7E]|$REG{escaped})*/;
33     $REG{S_uri_body} = qr/(?:[\x21\x24\x26-\x3B\x3D\x3F-\x5A\x5B\x5D\x5F\x61-\x7A\x7E]|$REG{escaped})+/;
34     $REG{S_absoluteURI} = qr/$REG{scheme}:$REG{S_uri_body}/;
35     $REG{S_relativeURI} = qr/$REG{S_uri_body}/;
36     $REG{S_URI_reference} = qr/(?:$REG{S_absoluteURI}|$REG{S_relativeURI})(?:$REG{fragment})?|(?:$REG{fragment})/;
37     ## RFC 2396 allows <> (empty URI), but this regex doesn't.
38 wakaba 1.1 $REG{M_uri_literal} = qr/\x3C([\x09\x20\x21\x23-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E]*)\x3E/;
39     $REG{M_S_phrase_uri} = qr/($REG{phrase_c})$REG{M_uri_literal}/;
40     $REG{uri_phrase} = qr/[\x21\x23-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E]+(?:$REG{WSP}+[\x21\x23-\x27\x29-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E][\x21\x23-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E]*)*/;
41     #$REG{M_phrase_uri} = qr/($REG{phrase_c})<$REG{FWS}($REG{S_URI_reference})$REG{FWS}>/;
42     #$REG{M_phrase_uri_a} = qr/($REG{phrase_c})<$REG{FWS}($REG{S_absoluteURI})$REG{FWS}>/;
43     #$REG{M_phrase_uri_af} = qr/($REG{phrase_c})<$REG{FWS}($REG{S_absoluteURI}(?:$REG{fragment})?)$REG{FWS}>/;
44     #$REG{M_uri_content} = qr/$REG{M_S_phrase_uri}((?:$REG{FWS}$REG{comment})*)|($REG{S_URI_reference})($REG{WSP}(?:$REG{FWS}$REG{comment})*)?/;
45     $REG{M_uri_content} = qr/$REG{M_S_phrase_uri}((?:$REG{FWS}$REG{comment})*)|($REG{uri_phrase})($REG{WSP}(?:$REG{FWS}$REG{comment})*)?/;
46    
47 wakaba 1.3 =head1 CONSTRUCTORS
48    
49     The following methods construct new objects:
50 wakaba 1.1
51 wakaba 1.3 =over 4
52    
53     =cut
54 wakaba 1.1
55     %DEFAULT = (
56 wakaba 1.3 -_MEMBERS => [qw|display_name|],
57     -_METHODS => [qw|display_name uri
58     comment_add comment_delete comment_item
59     comment_count|],
60     -allow_absolute => 1, ## TODO: not implemented
61     -allow_empty => 1,
62     -allow_fragment => 1, ## TODO: not implemented
63     -allow_relative => 1, ## TODO: not implemented
64     #encoding_after_encode
65     #encoding_before_decode
66     #field_param_name
67     #field_name
68     #hook_encode_string
69     #hook_decode_string
70     -output_angle_bracket => 1,
71     -output_comment => 1,
72     -output_display_name => 1,
73     #parse_all
74     -unsafe_rule_display_name => 'NON_http_attribute_char_wsp',
75     -use_comment => 1,
76     -use_display_name => 1,
77 wakaba 1.1 );
78    
79 wakaba 1.3 sub _init ($;%) {
80 wakaba 1.1 my $self = shift;
81 wakaba 1.3 my %options = @_;
82     my $DEFAULT = Message::Util::make_clone (\%DEFAULT);
83     $self->SUPER::_init (%$DEFAULT, %options);
84     #$self->{option}->{value_type}->{uri} = ['URI::'];
85    
86 wakaba 1.1 my $format = $self->{option}->{format};
87 wakaba 1.3 my $field = $self->{option}->{field_name};
88     $format = 'mhtml' if $format =~ /mail|news/;
89     if ($field =~ /^list-/) { ## mail
90     $self->{option}->{output_display_name} = 0;
91     $self->{option}->{allow_empty} = 0;
92     } elsif ($field eq 'content-location') { ## HTTP / MHTML
93     $self->{option}->{output_angle_bracket} = 0;
94     $self->{option}->{output_display_name} = 0;
95     $self->{option}->{output_comment} = 0;
96     $self->{option}->{use_display_name} = 0;
97     $self->{option}->{allow_fragment} = 0;
98     } elsif ($field eq 'link') { ## HTTP
99     $self->{option}->{output_display_name} = 0;
100     $self->{option}->{output_comment} = 0;
101     $self->{option}->{allow_fragment} = 0;
102     } elsif ($field eq 'location') { ## HTTP / HTTP-CGI
103     $self->{option}->{output_angle_bracket} = 0;
104     $self->{option}->{use_comment} = 0;
105     $self->{option}->{use_display_name} = 0;
106     if ($format =~ /cgi/) {
107     $self->{option}->{allow_relative} = 0;
108     $self->{option}->{allow_fragment} = 0;
109 wakaba 1.1 }
110 wakaba 1.3 } elsif ($field eq 'referer') { ## HTTP
111     $self->{option}->{output_angle_bracket} = 0;
112     $self->{option}->{use_comment} = 0;
113     $self->{option}->{use_display_name} = 0;
114     $self->{option}->{allow_fragment} = 0;
115     } elsif ($field eq 'uri') { ## HTTP
116     $self->{option}->{output_comment} = 0;
117     $self->{option}->{output_display_name} = 0;
118     } elsif ($field eq 'content-base') { ## HTTP / MHTML
119     $self->{option}->{output_angle_bracket} = 0;
120     $self->{option}->{output_comment} = 0;
121     $self->{option}->{use_display_name} = 0;
122     $self->{option}->{allow_relative} = 0;
123     $self->{option}->{allow_fragment} = 0;
124 wakaba 1.1 }
125     }
126    
127 wakaba 1.3 =item $uri = Message::Field::URI->new ([%options])
128 wakaba 1.1
129 wakaba 1.3 Constructs a new object. You might pass some options as parameters
130     to the constructor.
131 wakaba 1.1
132     =cut
133    
134 wakaba 1.3 ## Inherited
135 wakaba 1.1
136 wakaba 1.3 =item $uri = Message::Field::URI->parse ($field-body, [%options])
137 wakaba 1.1
138 wakaba 1.3 Constructs a new object with given field body. You might pass
139     some options as parameters to the constructor.
140 wakaba 1.1
141     =cut
142    
143     sub parse ($$;%) {
144     my $class = shift;
145 wakaba 1.3 my $self = bless {}, $class;
146 wakaba 1.1 my $body = shift;
147 wakaba 1.3 $self->_init (@_);
148     ($body, @{$self->{comment}})
149     = $self->Message::Util::delete_comment_to_array ($body, -use_angle_quoted)
150     if $self->{option}->{use_comment};
151     if ($body =~ /([^\x3C]*)$REG{SCM_angle_quoted}/) {
152     my ($dn, $as) = ($1, $2);
153     $dn =~ s/^$REG{WSP}+//; $dn =~ s/$REG{WSP}+$//;
154     $self->{display_name} = $self->Message::Util::decode_quoted_string ($dn);
155     #$as =~ s/^$REG{WSP}+//; $as =~ s/$REG{WSP}+$//;
156     $as =~ tr/\x09\x20//d;
157     $self->{value} = $as;
158     } else {
159     #$body =~ s/^$REG{WSP}+//; $body =~ s/$REG{WSP}+$//;
160     $body =~ tr/\x09\x20//d;
161     $self->{value} = $body;
162 wakaba 1.1 }
163 wakaba 1.3 $self->{value} = $self->_parse_value (uri => $self->{value})
164     if $self->{option}->{parse_all};
165 wakaba 1.1 $self;
166     }
167    
168    
169 wakaba 1.3 =head2 $URI = $uri->uri ([$newURI])
170 wakaba 1.2
171     Set/gets C<URI>. See also L<NOTE>.
172    
173     =cut
174    
175     sub uri ($;$%) {
176     my $self = shift;
177     my $dname = shift;
178     if (defined $dname) {
179 wakaba 1.3 $self->{value} = $dname;
180 wakaba 1.2 }
181 wakaba 1.3 $self->{value};
182 wakaba 1.2 }
183    
184 wakaba 1.1
185     sub display_name ($;$%) {
186     my $self = shift;
187     my $dname = shift;
188     if (defined $dname) {
189     $self->{display_name} = $dname;
190     }
191     $self->{display_name};
192     }
193    
194    
195     sub stringify ($;%) {
196     my $self = shift;
197 wakaba 1.3 my %o = @_; my %option = %{$self->{option}};
198     for (grep {/^-/} keys %o) {$option{substr ($_, 1)} = $o{$_}}
199     my $uri = ''.$self->{value};
200     if ((!$option{allow_relative} || !$option{allow_empty})
201     && length $uri == 0) {
202 wakaba 1.1 return '';
203     }
204 wakaba 1.3 my ($dn, $as, $cm) = ('', '', '');
205 wakaba 1.1 if (length $self->{display_name}) {
206 wakaba 1.3 if ($option{use_display_name} && $option{output_display_name}) {
207     my %s = &{$option{hook_encode_string}} ($self,
208     $self->{display_name}, type => 'phrase');
209     $dn = Message::Util::quote_unsafe_string
210     ($s{value}, unsafe => $option{unsafe_rule_display_name}) . ' ';
211     } elsif ($option{use_comment} && $option{output_comment}) {
212     $dn = ' ('. $self->Message::Util::encode_ccontent ($self->{display_name}) .')';
213 wakaba 1.1 }
214     }
215 wakaba 1.3
216     if ($option{output_angle_bracket}) {
217     $as = '<'.$uri.'>';
218 wakaba 1.1 } else {
219 wakaba 1.3 $as = $uri;
220 wakaba 1.1 }
221 wakaba 1.3
222     if ($option{use_comment} && $option{output_comment}) {
223     $cm = $self->_comment_stringify (\%option);
224     $cm = ' ' . $cm if $cm;
225     if ($dn && !($option{use_display_name} && $option{output_display_name})) {
226     $cm = $dn . $cm; $dn = '';
227 wakaba 1.1 }
228     }
229 wakaba 1.3 $dn . $as . $cm;
230 wakaba 1.1 }
231 wakaba 1.3 *as_string = \&stringify;
232 wakaba 1.1
233    
234     =head1 NOTE
235    
236     Current version of this module does not check whether
237     URI is correct or not. In particullar, implementor
238     should be careful not to output URI that is syntactically
239     valid, but do not match to context. For example,
240     C<Location:> field defined by HTTP/1.1 [RFC2616] doesn't
241     allow relative URIs. (Interestingly, with CGI/1.1,
242     we can use relative URI as value of C<Location> field.
243    
244     There is three options related with URI type.
245     C<allow_absolute>, C<allow_relative>, and C<allow_fragment>.
246     But this options don't work as you hope.
247     These options are only reserved for future implemention.
248    
249     =head1 LICENSE
250    
251     Copyright 2002 wakaba E<lt>w@suika.fam.cxE<gt>.
252    
253     This program is free software; you can redistribute it and/or modify
254     it under the terms of the GNU General Public License as published by
255     the Free Software Foundation; either version 2 of the License, or
256     (at your option) any later version.
257    
258     This program is distributed in the hope that it will be useful,
259     but WITHOUT ANY WARRANTY; without even the implied warranty of
260     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
261     GNU General Public License for more details.
262    
263     You should have received a copy of the GNU General Public License
264     along with this program; see the file COPYING. If not, write to
265     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
266     Boston, MA 02111-1307, USA.
267    
268     =head1 CHANGE
269    
270     See F<ChangeLog>.
271 wakaba 1.3 $Date: 2002/04/01 06:27:32 $
272 wakaba 1.1
273     =cut
274    
275     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24