/[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.11 - (hide annotations) (download)
Sun Jun 9 11:08:28 2002 UTC (22 years, 5 months ago) by wakaba
Branch: MAIN
Changes since 1.10: +25 -13 lines
2002-06-09  wakaba <w@suika.fam.cx>

	* Addresses.pm (_delete_match): 'addr-spec': new 'by' option.
	* ContentType.pm:
	- (_save_param): Call _parse_param_value if parse_all.
	- (_parse_value): New function.  Check Message::MIME::MediaType.
	* CSV.pm (use_comment): New option.
	* Date.pm:
	- (zone): New method.
	- (set_datetime): Likewise.
	* Mailbox.pm (display_name): New method.
	* Numval.pm (use_comment): New option.
	* Param.pm (_parse_param_value): New function.
	* Structured.pm:
	- (_add_return_value, _replace_return_value): New functions.
	- (_parse_value): Sync with Message::Entity's.
	- (option): Sync with Message::Entity's.
	- (option): '-recursive': new option.
	- (_option_recursive): New function.

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

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24