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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (hide annotations) (download)
Mon Apr 22 08:28:20 2002 UTC (22 years, 7 months ago) by wakaba
Branch: MAIN
Changes since 1.7: +33 -14 lines
2002-04-22  wakaba <w@suika.fam.cx>

	* Makefile: New file.
	
	* Received.pm: Reformed.

1 wakaba 1.1
2     =head1 NAME
3    
4 wakaba 1.7 Message::Field::Params --- Perl module for Internet message
5     field body consist of parameters, such as C<Content-Type:> field
6 wakaba 1.1
7     =cut
8    
9     package Message::Field::Params;
10     use strict;
11     require 5.6.0;
12     use re 'eval';
13 wakaba 1.7 use vars qw(@ISA %REG $VERSION);
14 wakaba 1.8 $VERSION=do{my @r=(q$Revision: 1.7 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
15 wakaba 1.3 require Message::Util;
16 wakaba 1.7 require Message::Field::Structured;
17     push @ISA, qw(Message::Field::Structured);
18    
19     use overload '""' => sub { $_[0]->stringify },
20     '0+' => sub { $_[0]->count },
21     '.=' => sub { $_[0]->add ($_[1], ['', value => 1]); $_[0] },
22     fallback => 1;
23    
24     *REG = \%Message::Util::REG;
25     ## Inherited: comment, quoted_string, domain_literal, angle_quoted
26     ## WSP, FWS, atext, atext_dot, token, attribute_char
27     ## S_encoded_word
28     ## M_quoted_string
29 wakaba 1.1
30 wakaba 1.7 $REG{param} = qr/(?:$REG{atext_dot}|$REG{quoted_string}|$REG{angle_quoted})(?:$REG{atext_dot}|$REG{quoted_string}|$REG{WSP}|,)*/;
31 wakaba 1.8 $REG{param_nocomma} = qr/(?:$REG{atext_dot}|$REG{quoted_string}|$REG{angle_quoted})(?:$REG{atext_dot}|$REG{quoted_string}|$REG{WSP})*/;
32 wakaba 1.1 ## more naive C<parameter>. (Comma is allowed for RFC 1049)
33     $REG{parameter} = qr/$REG{token}=(?:$REG{token}|$REG{quoted_string})?/;
34     ## as defined by RFC 2045, not RFC 2231.
35    
36     $REG{M_parameter} = qr/($REG{token})=($REG{token}|$REG{quoted_string})?/;
37     ## as defined by RFC 2045, not RFC 2231.
38     $REG{M_parameter_name} = qr/($REG{attribute_char}+)(?:\*([0-9]+)(\*)?|(\*))/;
39     ## as defined by RFC 2231.
40     $REG{M_parameter_extended_value} = qr/([^']*)'([^']*)'($REG{token}*)/;
41     ## as defined by RFC 2231, but more naive.
42    
43    
44 wakaba 1.7 =head1 CONSTRUCTORS
45 wakaba 1.5
46 wakaba 1.7 The following methods construct new objects:
47 wakaba 1.1
48 wakaba 1.7 =over 4
49 wakaba 1.1
50     =cut
51    
52 wakaba 1.7 ## Initialize of this class -- called by constructors
53     sub _init ($;%) {
54     my $self = shift;
55     my %options = @_;
56     my %DEFAULT = (
57     -delete_fws => 1,
58     #encoding_after_encode ## Inherited
59     #encoding_before_decode ## Inherited
60     #format ## Inherited
61     #hook_encode_string ## Inherited
62     #hook_decode_string ## Inherited
63 wakaba 1.8 -parameter_rule => 'param',
64 wakaba 1.7 -parameter_name_case_sensible => 0,
65     -parameter_value_max_length => 78,
66     -parameter_value_unsafe_rule => {'*default' => 'NON_http_attribute_char'},
67     -parse_all => 0,
68 wakaba 1.8 -separator => '; ',
69     -separator_regex => qr/$REG{FWS};$REG{FWS}/,
70 wakaba 1.7 -use_parameter_extension => 0,
71     -value_type => {'*default' => [':none:']},
72     );
73     $self->SUPER::_init (%DEFAULT, %options);
74     $self->{param} = [];
75 wakaba 1.8 my $fname = $self->_n11n_field_name ($self->{option}->{field_name});
76     if ($fname eq 'p3p') {
77     $self->{option}->{parameter_rule} = 'param_nocomma';
78     $self->{option}->{separator} = ', ';
79     $self->{option}->{separator_regex} = qr/$REG{FWS},$REG{FWS}/;
80     }
81 wakaba 1.7 if ($self->{option}->{format} =~ /^http-sip/) {
82     $self->{option}->{encoding_before_decode} = 'utf-8';
83     $self->{option}->{encoding_after_decode} = 'utf-8';
84     } elsif ($self->{option}->{format} =~ /^http/) {
85     $self->{option}->{encoding_before_decode} = 'iso-8859-1';
86     $self->{option}->{encoding_after_decode} = 'iso-8859-1';
87     }
88 wakaba 1.1 }
89    
90     ## Initialization for new () method.
91     sub _initialize_new ($;%) {
92 wakaba 1.7 ## Nothing to do
93     }
94    
95     ## Initialization for parse () method.
96     sub _initialize_parse ($;%) {
97     ## Nothing to do
98     }
99    
100     =item $p = Message::Field::Params->new ([%options])
101    
102     Constructs a new object. You might pass some options as parameters
103     to the constructor.
104    
105     =cut
106    
107     sub new ($;%) {
108     my $self = shift->SUPER::new (@_);
109     $self->_initialize_new (@_);
110     $self;
111 wakaba 1.1 }
112    
113 wakaba 1.7 =item $p = Message::Field::Params->parse ($field-body, [%options])
114 wakaba 1.1
115 wakaba 1.7 Constructs a new object with given field body. You might pass
116     some options as parameters to the constructor.
117 wakaba 1.1
118     =cut
119    
120     sub parse ($$;%) {
121     my $class = shift;
122 wakaba 1.7 my $self = bless {}, $class;
123 wakaba 1.1 my $body = shift;
124 wakaba 1.7 $self->_init (@_);
125     $self->_initialize_parse (@_);
126     $body = Message::Util::delete_comment ($body);
127     $body = $self->_delete_fws ($body) if $self->{option}->{delete_fws};
128 wakaba 1.1 my @b = ();
129 wakaba 1.8 $body =~ s{$REG{FWS}($REG{$self->{option}->{parameter_rule}})
130     (?:$self->{option}->{separator_regex}|$)}{
131 wakaba 1.1 my $param = $1;
132     push @b, $self->_parse_param ($param);
133     }goex;
134     @b = $self->_restore_param (@b);
135     $self->_save_param (@b);
136     $self;
137     }
138    
139     sub _parse_param ($$) {
140     my $self = shift;
141     my $param = shift;
142     if ($param =~ /^$REG{M_parameter}$/) {
143 wakaba 1.7 my ($name, $value) = ($self->_n11n_param_name ($1), $2);
144 wakaba 1.1 my ($seq, $isencoded, $charset, $lang) = (-1, 0, '', '');
145     if ($name =~ /^$REG{M_parameter_name}$/) {
146     ($name, $seq, $isencoded) = ($1, $4?-1:$2, ($3||$4)?1:0);
147     }
148     if ($isencoded && $value =~ /^$REG{M_parameter_extended_value}$/) {
149     ($charset, $lang, $value) = ($1, $2, $3);
150     }
151     return [$name, {value => $value, seq => $seq, is_encoded => $isencoded,
152     charset => $charset, language => $lang, is_parameter => 1}];
153     } else {
154     return [$param, {is_parameter => 0}];
155     }
156     }
157    
158     sub _restore_param ($@) {
159     my $self = shift;
160     my @p = @_;
161     my @ret;
162     my %part;
163     for my $i (@p) {
164     if ($i->[1]->{is_parameter}) {
165     my $p = $i->[1];
166     if ($p->{seq}<0) {
167     my $s = $p->{value};
168     if ($p->{is_encoded}) {
169     $s =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/chr(hex($1))/eg;
170 wakaba 1.3 my %s = &{$self->{option}->{hook_decode_string}} ($self, $s,
171     language => $p->{language}, charset => $p->{charset},
172     type => 'parameter/encoded');
173     ($s, $p->{charset}, $p->{language}) = (@s{qw(value charset language)});
174 wakaba 1.1 } else {
175 wakaba 1.3 my $q = 0;
176 wakaba 1.7 ($s,$q) = Message::Util::unquote_if_quoted_string ($p->{value});
177 wakaba 1.3 my %s = &{$self->{option}->{hook_decode_string}} ($self, $s,
178     type => ($q?'parameter/quoted':'parameter'));
179     ($s, $p->{charset}, $p->{language}) = (@s{qw(value charset language)});
180 wakaba 1.1 }
181     push @ret, [$i->[0], {value => $s, language => $p->{language},
182     charset => $p->{charset}, is_parameter => 1}];
183     } else {
184     $part{$i->[0]}->[$p->{seq}] = {
185 wakaba 1.7 value => scalar Message::Util::unquote_if_quoted_string ($p->{value}),
186 wakaba 1.1 language => $p->{language}, charset => $p->{charset},
187     is_encoded => $p->{is_encoded}};
188     }
189 wakaba 1.3 } else {
190     my $q = 0;
191 wakaba 1.7 ($i->[0], $q) = Message::Util::unquote_if_quoted_string ($i->[0]);
192 wakaba 1.3 my %s = &{$self->{option}->{hook_decode_string}} ($self, $i->[0],
193     type => ($q?'phrase/quoted':'phrase'));
194 wakaba 1.6 push @ret, [$s{value}, {is_parameter => 0}];
195 wakaba 1.3 }
196 wakaba 1.1 }
197     for my $name (keys %part) {
198     my $t = join '', map {
199     my $v = $_;
200     my $s = $v->{value};
201     $s =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/chr(hex($1))/eg if $v->{is_encoded};
202     $s;
203     } @{$part{$name}};
204 wakaba 1.3 my %s = &{$self->{option}->{hook_decode_string}} ($self, $t,
205     type => 'parameter/encoded');
206     ($t,@part{$name}->[0]->{qw(charset language)})=(@s{qw(value charset language)});
207 wakaba 1.1 push @ret, [$name, {value => $t, charset => $part{$name}->[0]->{charset},
208     language => $part{$name}->[0]->{language},
209     is_parameter => 1}];
210     }
211     @ret;
212     }
213    
214     sub _save_param ($@) {
215     my $self = shift;
216     my @p = @_;
217     $self->{param} = \@p;
218     $self;
219     }
220    
221 wakaba 1.7 =back
222    
223     =head1 METHODS
224    
225     =over 4
226    
227     =item $p->add ($name => [$value], [$name => $value,...])
228 wakaba 1.1
229     Adds parameter name=value pair.
230    
231     Example:
232 wakaba 1.7 $p->add (title => 'foo of bar'); ## title="foo of bar"
233     $p->add (subject => 'hogehoge, foo'); ## subject*=''hogehoge%2C%20foo
234     $p->add (foo => ['bar', language => 'en']) ## foo*='en'bar
235     $p->add ('text/plain', ['', value => 1]) ## text/plain
236 wakaba 1.1
237     This method returns array reference of (name, {value => value, attribute...}).
238    
239     Available options: charset (charset name), language (language tag),
240     value (1/0, see example above).
241    
242     =cut
243    
244     sub add ($$;$%) {
245     my $self = shift;
246 wakaba 1.7 my %gp = @_;
247     my %option = %{$self->{option}};
248     for (grep {/^-/} keys %gp) {$option{substr ($_, 1)} = $gp{$_}}
249     $option{parse} = 1 if defined wantarray;
250     my $p;
251     for (grep {/^[^-]/} keys %gp) {
252     my ($name, $value, %po) = ($self->_n11n_param_name ($_));
253     if (ref $gp{$_}) {($value, %po) = @{$gp{$_}}} else {$value = $gp{$_}}
254     $p = [$name, {value => $value, charset => $po{charset},
255     is_parameter => 1, language => $po{language}}];
256     $p->[1]->{is_parameter} = 0 if !$value && $po{value};
257     Carp::croak "add: \$name contains of non-attribute-char: $name"
258     if $p->[1]->{is_parameter} && $name =~ /$REG{NON_http_attribute_char}/;
259     $p->[1]->{value} = $self->_param_value ($name => $p->[1]->{value})
260     if $option{parse};
261     if ($option{prepend}) {
262     unshift @{$self->{param}}, $p;
263     } else {
264     push @{$self->{param}}, $p;
265     }
266 wakaba 1.1 }
267 wakaba 1.7 $p->[1]->{is_parameter}? $p->[1]->{value}: $p->[0];
268 wakaba 1.1 }
269 wakaba 1.7
270     sub replace ($%) {
271 wakaba 1.1 my $self = shift;
272 wakaba 1.7 my %gp = @_;
273     my %option = %{$self->{option}};
274     for (grep {/^-/} keys %gp) {$option{substr ($_, 1)} = $gp{$_}}
275     $option{parse} = 1 if defined wantarray;
276     my $p;
277     for (grep {/^[^-]/} keys %gp) {
278     my ($name, $value, %po) = ($self->_n11n_param_name ($_));
279     if (ref $gp{$_}) {($value, %po) = @{$gp{$_}}} else {$value = $gp{$_}}
280     $p = [$name, {value => $value, charset => $po{charset},
281     is_parameter => 1, language => $po{language}}];
282 wakaba 1.8 $p->[1]->{is_parameter} = 0 if !defined ($value) && $po{value};
283 wakaba 1.7 Carp::croak "replace: \$name contains of non-attribute-char: $name"
284     if $p->[1]->{is_parameter} && $name =~ /$REG{NON_http_attribute_char}/;
285     $p->[1]->{value} = $self->_param_value ($name => $p->[1]->{value})
286     if $option{parse};
287     my $f = 0;
288     for my $param (@{$self->{param}}) {
289     if ($param->[0] eq $name) {$param = $p; $f = 1}
290 wakaba 1.1 }
291 wakaba 1.7 push @{$self->{param}}, $p unless $f == 1;
292 wakaba 1.1 }
293 wakaba 1.7 $p->[1]->{is_parameter}? $p->[1]->{value}: $p->[0];
294 wakaba 1.1 }
295    
296 wakaba 1.8 ## TODO: multiple parameters support
297 wakaba 1.1 sub delete ($$;%) {
298     my $self = shift;
299 wakaba 1.7 my ($name, $index) = ($self->_n11n_param_name (shift), shift);
300 wakaba 1.1 my $i = 0;
301     for my $param (@{$self->{param}}) {
302     if ($param->[0] eq $name) {
303     $i++;
304     if ($index == 0 || $i == $index) {
305     undef $param;
306     return $self if $i == $index;
307     }
308     }
309     }
310     $self;
311     }
312    
313     sub count ($;$%) {
314     my $self = shift;
315 wakaba 1.7 my $name = $self->_n11n_param_name (shift);
316 wakaba 1.1 unless ($name) {
317     $self->_delete_empty ();
318     return $#{$self->{param}}+1;
319     }
320     my $count = 0;
321     for my $param (@{$self->{param}}) {
322     if ($param->[0] eq $name) {
323     $count++;
324     }
325     }
326     $count;
327     }
328    
329    
330 wakaba 1.7 sub parameter ($$;$%) {
331 wakaba 1.1 my $self = shift;
332 wakaba 1.7 my $name = $self->_n11n_param_name (shift);
333 wakaba 1.1 my $newvalue = shift;
334 wakaba 1.7 return $self->replace ($name => $newvalue,@_) if defined $newvalue;
335 wakaba 1.1 my @ret;
336     for my $param (@{$self->{param}}) {
337     if ($param->[0] eq $name) {
338     unless (wantarray) {
339 wakaba 1.3 $param->[1]->{value}
340     = $self->_param_value ($name => $param->[1]->{value});
341 wakaba 1.1 return $param->[1]->{value};
342     } else {
343 wakaba 1.3 $param->[1]->{value}
344     = $self->_param_value ($name => $param->[1]->{value});
345 wakaba 1.1 push @ret, $param->[1]->{value};
346     }
347     }
348     }
349     @ret;
350     }
351    
352     sub parameter_name ($$;$) {
353     my $self = shift;
354     my $i = shift;
355     my $newname = shift;
356     if ($newname) {
357 wakaba 1.4 return 0 if $newname =~ /$REG{NON_http_attribute_char}/;
358 wakaba 1.1 $self->{param}->[$i]->[0] = $newname;
359     }
360     $self->{param}->[$i]->[0];
361     }
362     sub parameter_value ($$;$) {
363     my $self = shift;
364     my $i = shift;
365     my $newvalue = shift;
366     if ($newvalue) {
367     $newvalue = $self->_param_value ($self->{param}->[$i]->[0] => $newvalue);
368     $self->{param}->[$i]->[1]->{value} = $newvalue;
369     }
370     $self->{param}->[$i]->[1]->{value}
371     = $self->_param_value
372     ($self->{param}->[$i]->[0] => $self->{param}->[$i]->[1]->{value});
373     $self->{param}->[$i]->[1]->{value};
374     }
375    
376     ## Hook called before returning C<value>.
377     ## $self->_param_value ($name, $value);
378 wakaba 1.5 sub _param_value ($$$) {
379     my $self = shift;
380 wakaba 1.7 my $name = shift || '*default';
381 wakaba 1.5 my $value = shift;
382 wakaba 1.8 return $value if ref $value;
383 wakaba 1.6 my $vtype = $self->{option}->{value_type}->{$name}->[0]
384 wakaba 1.7 || $self->{option}->{value_type}->{'*default'}->[0];
385 wakaba 1.5 my %vopt; %vopt = %{$self->{option}->{value_type}->{$name}->[1]}
386     if ref $self->{option}->{value_type}->{$name}->[1];
387 wakaba 1.8 if ($vtype eq ':none:') {
388 wakaba 1.5 return $value;
389 wakaba 1.8 } elsif (defined $value) {
390 wakaba 1.5 eval "require $vtype";
391 wakaba 1.7 return $vtype->parse ($value, -format => $self->{option}->{format},
392 wakaba 1.8 -field_name => $self->{option}->{field_name},
393     -field_param_name => $name,
394 wakaba 1.7 -field_body => $self->{option}->{field_body}, %vopt);
395 wakaba 1.5 } else {
396     eval "require $vtype";
397 wakaba 1.7 return $vtype->new (-format => $self->{option}->{format},
398 wakaba 1.8 -field_name => $self->{option}->{field_name},
399     -field_param_name => $name,
400 wakaba 1.7 -field_body => $self->{option}->{field_body}, %vopt);
401 wakaba 1.5 }
402     }
403 wakaba 1.1
404     sub _delete_empty ($) {
405     my $self = shift;
406 wakaba 1.7 $self->{param} = [grep {length $_} @{$self->{param}}];
407 wakaba 1.1 }
408    
409    
410 wakaba 1.7 =item $field-body = $p->stringify ()
411 wakaba 1.1
412 wakaba 1.7 Returns C<field-body> as a string.
413 wakaba 1.1
414     =cut
415    
416     sub stringify ($;%) {
417     my $self = shift;
418 wakaba 1.7 my %o = @_;
419     my %option = %{$self->{option}};
420     for (grep {/^-/} keys %o) {$option{substr ($_, 1)} = $o{$_}}
421     $self->_delete_empty;
422 wakaba 1.8 join $self->{option}->{separator},
423 wakaba 1.1 map {
424     my $v = $_->[1];
425     my $new = '';
426     if ($v->{is_parameter}) {
427     my ($encoded, @value) = (0, '');
428 wakaba 1.3 my (%e) = &{$self->{option}->{hook_encode_string}} ($self,
429     $v->{value}, current_charset => $v->{charset}, language => $v->{language},
430     type => 'parameter');
431 wakaba 1.8 if ($e{value} eq undef) {
432     $value[0] = undef;
433     } elsif ($option{use_parameter_extension} && ($e{charset} || $e{language}
434 wakaba 1.3 || $e{value} =~ /[\x00\x0D\x0A\x80-\xFF]/)) {
435 wakaba 1.1 my ($charset, $lang);
436     $encoded = 1;
437 wakaba 1.3 ($charset, $lang) = ($e{charset}, $e{language});
438 wakaba 1.1 ## Note: %-quoting for charset and for language is not allowed.
439     ## But charset name can be included non-sttribute-char such as "'".
440     ## How can we treat this?
441 wakaba 1.4 $charset =~ s/($REG{NON_http_attribute_char})/sprintf('%%%02X', ord $1)/ge;
442     $lang =~ s/($REG{NON_http_attribute_char})/sprintf('%%%02X', ord $1)/ge;
443 wakaba 1.7 if (length $e{value} > $option{parameter_value_max_length}) {
444     for my $i (0..length ($e{value})/$option{parameter_value_max_length}) {
445     $value[$i] = substr ($e{value}, $i*$option{parameter_value_max_length},
446     $option{parameter_value_max_length});
447 wakaba 1.1 }
448 wakaba 1.3 } else {$value[0] = $e{value}}
449 wakaba 1.1 for my $i (0..$#value) {
450 wakaba 1.4 $value[$i] =~
451     s/($REG{NON_http_attribute_char})/sprintf('%%%02X', ord $1)/ge;
452 wakaba 1.1 }
453     $value[0] = "${charset}'${lang}'".$value[0];
454 wakaba 1.3 } elsif (length $e{value} == 0) {
455 wakaba 1.1 $value[0] = '""';
456     } else {
457 wakaba 1.7 if ($option{use_parameter_extension}
458     && length $e{value} > $option{parameter_value_max_length}) {
459     for my $i (0..length ($e{value})/$option{parameter_value_max_length}) {
460     $value[$i] = Message::Util::quote_unsafe_string
461     (substr ($e{value}, $i*$option{parameter_value_max_length},
462     $option{parameter_value_max_length}),
463 wakaba 1.4 unsafe => 'NON_http_attribute_char');
464 wakaba 1.1 }
465     } else {
466 wakaba 1.7 my $unsafe = $self->{option}->{parameter_value_unsafe_rule}->{$_->[0]}
467     || $self->{option}->{parameter_value_unsafe_rule}->{'*default'};
468     $value[0] = Message::Util::quote_unsafe_string
469     ($e{value}, unsafe => $unsafe);
470 wakaba 1.1 }
471     }
472     ## Note: quoted-string for parameter name is not allowed.
473     ## But it is better than output bare non-atext.
474     if ($#value == 0) {
475     $new =
476 wakaba 1.7 Message::Util::quote_unsafe_string ($_->[0],
477     unsafe => 'NON_attribute_char')
478 wakaba 1.8 .($encoded?'*':'').'='.$value[0]
479     if defined $value[0];
480 wakaba 1.1 } else {
481     my @new;
482 wakaba 1.7 my $name = Message::Util::quote_unsafe_string
483 wakaba 1.4 ($_->[0], unsafe => 'NON_http_attribute_char');
484 wakaba 1.1 for my $i (0..$#value) {
485     push @new, $name.'*'.$i.($encoded?'*':'').'='.$value[$i];
486     }
487     $new = join '; ', @new;
488     }
489     } else {
490 wakaba 1.3 my %e = &{$self->{option}->{hook_encode_string}} ($self,
491     $_->[0], type => 'phrase');
492 wakaba 1.7 $new = Message::Util::quote_unsafe_string ($e{value},
493 wakaba 1.4 unsafe => 'NON_http_token_wsp');
494 wakaba 1.1 }
495     $new;
496     } @{$self->{param}}
497     ;
498     }
499 wakaba 1.7 *as_string = \&stringify;
500 wakaba 1.1
501 wakaba 1.7 sub scan ($&) {
502     my ($self, $sub) = @_;
503     #my $sort;
504     #$sort = \&_header_cmp if $self->{option}->{sort} eq 'good-practice';
505     #$sort = {$a cmp $b} if $self->{option}->{sort} eq 'alphabetic';
506     my @param = @{$self->{param}};
507     #if (ref $sort) {
508     # @field = sort $sort @{$self->{param}};
509     #}
510     for my $param (@param) {
511     &$sub($param->[0] => $param->[1]->{value}, $param->[1]);
512     }
513     }
514    
515 wakaba 1.8 =item $option-value = $p->option ($option-name)
516 wakaba 1.1
517 wakaba 1.7 Gets option value.
518    
519 wakaba 1.8 =item $p->option ($option-name, $option-value, ...)
520 wakaba 1.7
521     Set option value(s). You can pass multiple option name-value pair
522     as parameter when setting.
523 wakaba 1.1
524     =cut
525    
526 wakaba 1.7 sub option ($;$%) {
527 wakaba 1.1 my $self = shift;
528 wakaba 1.7 my $format = $self->{option}->{format};
529     $self->SUPER::option (@_);
530     if ($format ne $self->{option}->{format}) {
531     $self->scan (sub {
532     if (ref $_[1]) {
533     $_[1]->option (-format => $self->{option}->{format});
534     }
535     });
536 wakaba 1.1 }
537     }
538    
539 wakaba 1.8 ## TODO: multiple value-type support
540 wakaba 1.7 sub value_type ($;$$%) {
541 wakaba 1.1 my $self = shift;
542 wakaba 1.7 my $name = shift || '*default';
543     my $new_value_type = shift;
544     if ($new_value_type) {
545     $self->{option}->{value_type}->{$name} = []
546     unless ref $self->{option}->{value_type}->{$name};
547     $self->{option}->{value_type}->{$name}->[0] = $new_value_type;
548     }
549     if (ref $self->{option}->{value_type}->{$name}) {
550     $self->{option}->{value_type}->{$name}->[0]
551     || $self->{option}->{value_type}->{'*default'}->[0];
552     } else {
553     $self->{option}->{value_type}->{'*default'}->[0];
554 wakaba 1.1 }
555     }
556    
557 wakaba 1.7 sub value_unsafe_rule ($$;$%) {
558 wakaba 1.1 my $self = shift;
559 wakaba 1.7 if (@_ == 1) {
560     return $self->{option}->{parameter_value_unsafe_rule}->{ $_[0] };
561     }
562     while (my ($name, $value) = splice (@_, 0, 2)) {
563     $name = $self->_n11n_param_name ($name);
564     $self->{option}->{parameter_value_unsafe_rule}->{$name} = $value;
565     }
566 wakaba 1.1 }
567    
568 wakaba 1.8 =item $clone = $p->clone ()
569 wakaba 1.1
570 wakaba 1.7 Returns a copy of the object.
571 wakaba 1.1
572     =cut
573    
574 wakaba 1.7 sub clone ($) {
575 wakaba 1.1 my $self = shift;
576 wakaba 1.7 $self->_delete_empty;
577     my $clone = $self->SUPER::clone;
578     $clone->{param} = Message::Util::make_clone ($self->{param});
579     $clone->{value_type} = Message::Util::make_clone ($self->{value_type});
580     $clone;
581 wakaba 1.1 }
582    
583     sub _delete_fws ($$) {
584     my $self = shift;
585     my $body = shift;
586 wakaba 1.3 $body =~ s{($REG{quoted_string}|$REG{domain_literal})|((?:$REG{token}|$REG{S_encoded_word})(?:$REG{WSP}+(?:$REG{token}|$REG{S_encoded_word}))+)|$REG{WSP}+}{
587     my ($o,$p) = ($1,$2);
588     if ($o) {$o}
589     elsif ($p) {$p=~s/$REG{WSP}+/\x20/g;$p}
590     else {''}
591 wakaba 1.1 }gex;
592     $body;
593     }
594    
595 wakaba 1.7 sub _n11n_param_name ($$) {
596     my $self = shift;
597     my $s = shift;
598     $s = lc $s unless $self->{option}->{parameter_name_case_sensible};
599     $s;
600     }
601    
602 wakaba 1.1 =head1 LICENSE
603    
604     Copyright 2002 wakaba E<lt>w@suika.fam.cxE<gt>.
605    
606     This program is free software; you can redistribute it and/or modify
607     it under the terms of the GNU General Public License as published by
608     the Free Software Foundation; either version 2 of the License, or
609     (at your option) any later version.
610    
611     This program is distributed in the hope that it will be useful,
612     but WITHOUT ANY WARRANTY; without even the implied warranty of
613     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
614     GNU General Public License for more details.
615    
616     You should have received a copy of the GNU General Public License
617     along with this program; see the file COPYING. If not, write to
618     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
619     Boston, MA 02111-1307, USA.
620    
621     =head1 CHANGE
622    
623     See F<ChangeLog>.
624 wakaba 1.8 $Date: 2002/04/21 04:27:42 $
625 wakaba 1.1
626     =cut
627    
628     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24