/[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.18 - (hide annotations) (download)
Sun Jul 21 03:25:00 2002 UTC (22 years, 4 months ago) by wakaba
Branch: MAIN
Changes since 1.17: +4 -4 lines
2002-07-21  Wakaba <w@suika.fam.cx>

	* Structured.pm (_parse_value): Inherit header_default_charset,
	header_default_charset_input, body_default_charset,
	body_default_charset_input.

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.14 use vars qw(%DEFAULT @ISA %REG $VERSION);
14 wakaba 1.18 $VERSION=do{my @r=(q$Revision: 1.17 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
15 wakaba 1.3 require Message::Util;
16 wakaba 1.15 require Message::MIME::Charset;
17 wakaba 1.7 require Message::Field::Structured;
18     push @ISA, qw(Message::Field::Structured);
19    
20     use overload '""' => sub { $_[0]->stringify },
21     '0+' => sub { $_[0]->count },
22     '.=' => sub { $_[0]->add ($_[1], ['', value => 1]); $_[0] },
23     fallback => 1;
24    
25 wakaba 1.14 %REG = %Message::Util::REG;
26 wakaba 1.15
27     $REG{S_parameter} = qr/(?:[^\x22\x28\x3B\x3C]|$REG{comment}|$REG{quoted_string}|$REG{angle_quoted})+/;
28     $REG{S_parameter_separator} = qr/;/;
29     $REG{S_comma_parameter} = qr/(?:[^\x22\x28\x2C\x3C]|$REG{comment}|$REG{quoted_string}|$REG{angle_quoted})+/;
30     $REG{S_comma_parameter_separator} = qr/,/;
31     $REG{MS_parameter_avpair} = qr/([^\x22\x3C\x3D]+)=([\x00-\xFF]*)/;
32 wakaba 1.17 $REG{M_parameter_avpair} = qr/([^\x22\x3C\x3D]+)=([^\x3D]*)/;
33 wakaba 1.1
34 wakaba 1.14 %DEFAULT = (
35 wakaba 1.15 -_HASH_NAME => 'params',
36     -_MEMBERS => [qw/params/],
37     -_METHODS => [qw/add replace delete item parameter scan/],
38     ## count item_exist <- not implemented yet
39     -accept_coderange => '7bit',
40     -by => 'attribute',
41     #encoding_after_encode
42     #encoding_before_decode
43     #field_param_name
44     #field_name
45     #field_ns
46     #format
47     #header_default_charset
48     #header_default_charset_input
49     #hook_encode_string
50     #hook_decode_string
51     -output_comment => 1,
52     -output_parameter_extension => 0,
53     -parameter_rule => 'S_parameter', ## regex name of parameter
54     -parameter_attribute_case_sensible => 0,
55     -parameter_attribute_unsafe_rule => 'NON_http_attribute_char',
56     -parameter_av_Mrule => 'MS_parameter_avpair',
57     -parameter_no_value_attribute_unsafe_rule => 'NON_http_attribute_char',
58     -parameter_value_max_length => 60,
59     -parameter_value_split_length => 35,
60     -parameter_value_unsafe_rule => 'NON_http_attribute_char',
61     #parse_all
62     -separator => '; ',
63     -separator_rule => 'parameter_separator',
64     -use_comment => 1,
65     -use_parameter_extension => 1,
66     #value_type
67 wakaba 1.14 );
68    
69     =head1 CONSTRUCTORS
70    
71     The following methods construct new objects:
72    
73     =over 4
74    
75     =cut
76    
77     ## Initialize of this class -- called by constructors
78     sub _init ($;%) {
79     my $self = shift;
80     my %options = @_;
81 wakaba 1.7 $self->SUPER::_init (%DEFAULT, %options);
82     $self->{param} = [];
83 wakaba 1.15 my $field = $self->{option}->{field_name};
84     if ($field eq 'p3p') {
85     $self->{option}->{parameter_rule} = 'S_comma_parameter';
86     $self->{option}->{separator_rule} = 'S_comma_parameter_separator';
87 wakaba 1.8 $self->{option}->{separator} = ', ';
88     }
89 wakaba 1.15 if ($self->{option}->{format} =~ /news-usefor/) {
90     $self->{option}->{accept_coderange} = '8bit';
91     } elsif ($self->{option}->{format} =~ /http/) {
92     $self->{option}->{accept_coderange} = 'binary';
93     }
94 wakaba 1.7 }
95    
96     =item $p = Message::Field::Params->new ([%options])
97    
98     Constructs a new object. You might pass some options as parameters
99     to the constructor.
100    
101     =cut
102    
103 wakaba 1.14 ## Inherited
104 wakaba 1.1
105 wakaba 1.7 =item $p = Message::Field::Params->parse ($field-body, [%options])
106 wakaba 1.1
107 wakaba 1.7 Constructs a new object with given field body. You might pass
108     some options as parameters to the constructor.
109 wakaba 1.1
110     =cut
111    
112     sub parse ($$;%) {
113     my $class = shift;
114 wakaba 1.7 my $self = bless {}, $class;
115 wakaba 1.1 my $body = shift;
116 wakaba 1.7 $self->_init (@_);
117 wakaba 1.15 my @param;
118     $body =~ s{
119     ($REG{ $self->{option}->{parameter_rule} })
120     (?: $REG{ $self->{option}->{separator_rule} } | $ )
121     }{
122     push @param, $self->_parse_parameter_item ($1, $self->{option});
123     '';
124     }gesx;
125     $self->_decode_parameters (\@param, $self->{option});
126     $self->_save_parameters (\@param, $self->{option});
127 wakaba 1.1 $self;
128     }
129    
130 wakaba 1.15 ## $self->_parse_parameter_item ($item, \%option)
131     ## -- parses a parameter item (into attribute/value pair or no-value-attribute)
132     sub _parse_parameter_item ($$\%) {
133     my $self = shift;
134     my ($item, $option) = @_;
135     my @comment;
136     ($item, @comment) = $self->Message::Util::delete_comment_to_array
137     ($item, -use_angle_quoted);
138     $item =~ s/^$REG{WSP}+//g;
139     $item =~ s/$REG{WSP}+$//g;
140     my %item;
141     if ($item =~ /^$REG{ $option->{parameter_av_Mrule} }$/) {
142     my $encoded = 0;
143     ($item{attribute}, $item{value}) = ($1, $2);
144     $item{attribute} =~ tr/\x09\x0A\x0D\x20//d;
145     $item{value} =~ s/^$REG{WSP}+//g;
146     if ($option->{use_parameter_extension}
147     && $item{attribute} =~ /^([^*]+)(?:\*([0-9]+)(\*)?|(\*))\z/) {
148     $item{attribute} = $1;
149     $item{section_no} = $2;
150     $encoded = $3 || $4;
151     $item{section_no} = -1 if $4;
152     if ($item{section_no} <= 0 && $encoded
153     && $item{value} =~ /^([^']*)'([^']*)'([\x00-\xFF]*)$/) {
154     $item{charset} = $1; $item{charset} =~ tr/\x09\x0A\x0D\x20//d;
155     $item{language} = $2; $item{language} =~ tr/\x09\x0A\x0D\x20//d;
156     $item{value} = $3; $item{value} =~ s/^$REG{WSP}+//g;
157     }
158     if ($encoded) {
159     $item{value} =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/chr(hex($1))/ge;
160     }
161     } else {
162     $item{section_no} = -1;
163 wakaba 1.1 }
164 wakaba 1.15 ($item{value}, $encoded) = Message::Util::unquote_if_quoted_string ($item{value}) unless $encoded;
165     ($item{value}, $encoded) = Message::Util::unquote_if_angle_quoted ($item{value}) unless $encoded;
166     $item{charset} = '*bare' if !$encoded && !$item{charset};
167     $item{attribute} = lc $item{attribute}
168     unless $option->{parameter_attribute_case_sensible};
169 wakaba 1.1 } else {
170 wakaba 1.15 my $encoded = 0;
171     ($item, $encoded) = Message::Util::unquote_if_quoted_string ($item) unless $encoded;
172     ($item, $encoded) = Message::Util::unquote_if_angle_quoted ($item) unless $encoded;
173     $item{attribute} = $item;
174     $item{charset} = '*bare' if !$encoded;
175     $item{no_value} = 1;
176     }
177     $item{comment} = \@comment;
178     \%item;
179     }
180    
181     ## $self->_decode_parameters (\@parameter, \%option)
182     ## -- join RFC 2231 splited fragments and decode each parameter
183     sub _decode_parameters ($\@\%) {
184     my $self = shift;
185     my ($param, $option) = @_;
186     my %fragment;
187     my @fparameter;
188     for my $parameter (@$param) {
189     if ($parameter->{no_value}) {
190     my %item;
191     $item{no_value} = 1;
192     $item{comment} = $parameter->{comment};
193     if ($parameter->{charset} ne '*bare') {
194     my %s = &{$self->{option}->{hook_decode_string}}
195     ($self, $parameter->{attribute},
196     charset => $option->{encoding_before_decode},
197     type => 'parameter/no-value-attribute');
198     if ($s{charset}) { ## Convertion failed
199     $item{charset} = $s{charset};
200     }
201     $item{attribute} = $s{value};
202     } else {
203     $item{attribute} = $parameter->{attribute};
204     }
205     $parameter = \%item;
206     } elsif ($parameter->{section_no} < 0) {
207     my %item;
208     $item{attribute} = $parameter->{attribute};
209     $item{language} = $parameter->{language} if $parameter->{language};
210     $item{comment} = $parameter->{comment};
211     if ($parameter->{charset} ne '*bare') {
212     my %s = &{$self->{option}->{hook_decode_string}}
213     ($self, $parameter->{value},
214     charset => $parameter->{charset} || $option->{encoding_before_decode},
215     type => 'parameter/value/quoted-string');
216     if ($s{charset}) { ## Convertion failed
217     $item{charset} = $s{charset};
218     } elsif ($parameter->{charset}) {
219     $item{output_charset} = $parameter->{charset};
220 wakaba 1.1 }
221 wakaba 1.15 $item{value} = $s{value};
222 wakaba 1.1 } else {
223 wakaba 1.15 $item{value} = $parameter->{value};
224     }
225     $parameter = \%item;
226     } else { ## fragment
227     $fragment{ $parameter->{attribute} }->[ $parameter->{section_no} ]
228     = $parameter->{value};
229     if ($parameter->{section_no} == 0) {
230     $fragment{'*property'}->{ $parameter->{attribute} }
231     ->{language} = $parameter->{language};
232     $fragment{'*property'}->{ $parameter->{attribute} }
233     ->{charset} = $parameter->{charset};
234     }
235     if (ref $parameter->{comment} && @{$parameter->{comment}} > 0) {
236     push @{ $fragment{'*property'}->{ $parameter->{attribute} }
237     ->{comment} }, @{$parameter->{comment}};
238 wakaba 1.1 }
239 wakaba 1.15 $parameter = undef;
240     }
241     }
242     for (keys %fragment) {
243     next if $_ eq '*property';
244     my %item;
245     $item{attribute} = $_;
246     $item{comment} = $fragment{'*property'}->{ $item{attribute} }->{comment};
247     $item{language} = $fragment{'*property'}->{ $item{attribute} }->{language};
248     delete $item{language} unless $item{language};
249     my $charset = $fragment{'*property'}->{ $item{attribute} }->{charset};
250     my %s = &{$self->{option}->{hook_decode_string}}
251     ($self, join ('', @{ $fragment{ $item{attribute} } }),
252     charset => $charset || $option->{encoding_before_decode},
253     type => 'parameter/extended-value/encoded');
254     if ($s{charset}) { ## Convertion failed
255     $item{charset} = $s{charset};
256     } elsif ($charset) {
257     $item{output_charset} = $charset;
258 wakaba 1.3 }
259 wakaba 1.15 $item{value} = $s{value};
260     push @fparameter, \%item;
261 wakaba 1.1 }
262 wakaba 1.15 @$param = (grep { ref $_ eq 'HASH' } @$param, @fparameter);
263 wakaba 1.11 }
264    
265 wakaba 1.15 ## $self->_parse_values_of_paramters (\@parameter, \%option)
266 wakaba 1.11 ## --- Parse each values of parameters
267 wakaba 1.15 sub _parse_values_of_parameters ($\@\%) {
268 wakaba 1.11 my $self = shift;
269 wakaba 1.15 my ($param, $option) = @_;
270     @$param = map {
271     if (!$_->{no_value}) {
272     $_->{value} = $self->_parse_value ($_->{attribute} => $_->{value});
273     } else {
274     $_->{value} = $self->_parse_value ('*no_value_attribute' => $_->{value});
275 wakaba 1.9 }
276     $_;
277 wakaba 1.15 } @$param;
278     }
279    
280     ## $self->_save_parameters (\@parameter, \%option)
281     ## -- Save parameters in $self
282     sub _save_parameters ($\@\%) {
283     my $self = shift;
284     my ($param, $option) = @_;
285     $self->_parse_values_of_parameters ($param, $option) if $option->{parse_all};
286     $self->{ $option->{_HASH_NAME} } = $param;
287 wakaba 1.1 }
288 wakaba 1.15 *__save_parameters = \&_save_parameters;
289    
290 wakaba 1.1
291 wakaba 1.7 =back
292    
293     =head1 METHODS
294    
295     =over 4
296    
297     =item $p->add ($name => [$value], [$name => $value,...])
298 wakaba 1.1
299     Adds parameter name=value pair.
300    
301     Example:
302 wakaba 1.7 $p->add (title => 'foo of bar'); ## title="foo of bar"
303     $p->add (subject => 'hogehoge, foo'); ## subject*=''hogehoge%2C%20foo
304     $p->add (foo => ['bar', language => 'en']) ## foo*='en'bar
305     $p->add ('text/plain', ['', value => 1]) ## text/plain
306 wakaba 1.1
307     This method returns array reference of (name, {value => value, attribute...}).
308    
309     Available options: charset (charset name), language (language tag),
310     value (1/0, see example above).
311    
312     =cut
313    
314 wakaba 1.14 sub _add_hash_check ($$$\%) {
315     my $self = shift;
316     my ($name, $value, $option) = @_;
317     my $value_option = {};
318     if (ref $value eq 'ARRAY') {
319     ($value, %$value_option) = @$value;
320     }
321 wakaba 1.15 ## -- attribute only (no value) parameter
322     if ($value_option->{no_value}) {
323     $name = $self->_parse_value ('*no_value_attribute' => $name) if $$option{parse};
324     return (1, $name => {
325     attribute => $name, no_value => 1,
326     language => $value_option->{language},
327     comment => $value_option->{comment},
328     });
329 wakaba 1.14 }
330 wakaba 1.15 ## -- attribute=value pair
331     if ($$option{validate} && $name =~ /^$REG{NON_http_attribute_char}$/) {
332     if ($$option{dont_croak}) {
333     return (0);
334 wakaba 1.7 } else {
335 wakaba 1.15 Carp::croak qq{add: $name: Invalid parameter name};
336 wakaba 1.7 }
337 wakaba 1.1 }
338 wakaba 1.15 $value = $self->_parse_value ($name => $value) if $$option{parse};
339     (1, $name => {
340     attribute => $name, value => $value,
341     output_charset => $value_option->{charset},
342     charset => $value_option->{current_charset},
343     language => $value_option->{language},
344     comment => $value_option->{comment},
345     });
346 wakaba 1.1 }
347 wakaba 1.7
348 wakaba 1.15 *_add_return_value = \&_replace_return_value;
349    
350     ## (1/0, $name => $value) = $self->_replace_hash_check ($name => $value, \%option)
351     ## -- Checks given value and prepares saving value (hash version)
352     *_replace_hash_check = \&_add_hash_check;
353    
354     ## $value = $self->_replace_hash_shift (\%values, $name, $option)
355     ## -- Returns a value (from %values) and deletes it from %values
356     ## (like CORE::shift for array).
357     sub _replace_hash_shift ($\%$\%) {
358     shift; my $r = shift; my $n = $_[0]->{attribute};
359     if ($$r{$n}) {
360     my $d = $$r{$n};
361     $$r{$n} = undef;
362     return $d;
363     }
364     undef;
365     }
366    
367     ## $value = $self->_replace_return_value (\$item, \%option)
368     ## -- Returns returning value of replace method
369     sub _replace_return_value ($\$\%) {
370     my $self = shift;
371     my ($item, $value) = @_;
372     if ($$item->{no_value}) {
373     $$item->{attribute};
374     } else {
375     $$item->{value};
376 wakaba 1.1 }
377     }
378    
379 wakaba 1.15 ## 1/0 = $self->_delete_match ($by, \$item, \%delete_list, \%option)
380     ## -- Checks and returns whether given item is matched with
381     ## deleting item list
382     sub _delete_match ($$\$\%\%) {
383     my $self = shift;
384     my ($by, $item, $list, $option) = @_;
385     return 0 unless ref $$item; ## Already removed
386     if ($by eq 'attribute' || $by eq 'name') {
387     return 1 if $$list{ $$item->{attribute} };
388     } elsif ($by eq 'value') {
389     return 1 if $$list{ $$item->{value} };
390     } elsif ($by eq 'charset') {
391     return 1 if $$list{ $$item->{output_charset} } || $$list{ $$item->{charset} };
392     } elsif ($by eq 'language') {
393     return 1 if $$list{ $$item->{language} };
394     } elsif ($by eq 'type') {
395     if ($$item->{no_value}) {
396     return 1 if $$list{no_value_attribute};
397     } else {
398     return 1 if $$list{attribute_value_pair};
399 wakaba 1.1 }
400     }
401 wakaba 1.15 0;
402 wakaba 1.1 }
403    
404 wakaba 1.15 ## Delete empty items
405     sub _delete_empty ($) {
406 wakaba 1.1 my $self = shift;
407 wakaba 1.15 my $array = $self->{option}->{_HASH_NAME};
408     $self->{ $array } = [grep { ref $_ } @{$self->{ $array }}] if $array;
409 wakaba 1.1 }
410    
411 wakaba 1.15 =item @param = $p->parameter ($name => ($new_value), (%option))
412 wakaba 1.1
413    
414 wakaba 1.15 =cut
415    
416     sub parameter ($;@) {
417 wakaba 1.1 my $self = shift;
418 wakaba 1.15 if (@_ == 2) { ## $p->parameter (hoge => 'foo')
419     $self->replace (@_);
420     } else { ## $p->parameter ('foo')
421     $self->item (@_);
422 wakaba 1.1 }
423     }
424    
425 wakaba 1.15 *_item_match = \&_delete_match;
426     *_item_return_value = \&_replace_return_value;
427 wakaba 1.1
428 wakaba 1.15 ## $item = $self->_item_new_value ($name, \%option)
429     ## -- Returns new item with key of $name (called when
430     ## no returned value is found and -new_value_unless_exist
431     ## option is true)
432     sub _item_new_value ($$\%) {
433 wakaba 1.1 my $self = shift;
434 wakaba 1.15 my ($key, $option) = @_;
435     if ($option->{by} eq 'attribute' || $option->{by} eq 'name') {
436     return {attribute => $key};
437     }
438     undef;
439 wakaba 1.1 }
440    
441 wakaba 1.15 ## TODO: Implement count,item_exist method
442 wakaba 1.1
443 wakaba 1.7 =item $field-body = $p->stringify ()
444 wakaba 1.1
445 wakaba 1.7 Returns C<field-body> as a string.
446 wakaba 1.1
447     =cut
448    
449     sub stringify ($;%) {
450     my $self = shift;
451 wakaba 1.15 my %o = @_; my %option = %{$self->{option}};
452 wakaba 1.7 for (grep {/^-/} keys %o) {$option{substr ($_, 1)} = $o{$_}}
453 wakaba 1.15 $option{output_parameter_extension} = 0
454     unless $option{use_parameter_extension};
455     $option{output_comment} = 0 unless $option{use_comment};
456 wakaba 1.7 $self->_delete_empty;
457 wakaba 1.15 my @param;
458     $self->scan( sub {shift;
459     my ($item, $option) = @_;
460     my $r = 1;
461     ($r, $item) = $self->_stringify_param_check ($item, $option);
462     return unless $r;
463     my $comment = '';
464     if ($option->{output_comment} && ref $item->{comment}
465     && @{$item->{comment}} > 0) {
466     my @c;
467     for (@{$item->{comment}}) {
468     push @c, '('. $self->Message::Util::encode_ccontent ($_) .')';
469     }
470     $comment = ' '. join ' ', @c;
471     }
472     if ($item->{no_value}) {
473     push @param, Message::Util::quote_unsafe_string ($item->{attribute},
474     unsafe => $option->{parameter_no_value_attribute_unsafe_rule}).$comment;
475     } else {
476     my $xparam = 0;
477     my $attribute = $item->{attribute};
478     return unless length $attribute;
479     my $value = ''.$item->{value};
480     if ($attribute =~ /$REG{ $option->{parameter_attribute_unsafe_rule} }/) {
481     #return 0;
482     $attribute =~ s/($REG{NON_http_attribute_char})/sprintf('%%%02X', ord $1)/ge;
483     }
484     my %e;
485     if ($option->{output_parameter_extension}) {
486     if ($item->{charset}) {
487     %e = %$item;
488     } else {
489     %e = &{$self->{option}->{hook_encode_string}}
490     ($self, $value,
491     charset => $item->{output_charset} || $option->{encoding_after_encode},
492     current_charset => $option->{header_default_charset},
493     language => $item->{language},
494     type => 'parameter/value');
495     }
496     $xparam = 1 if (length $e{value} > $option->{parameter_value_max_length})
497     || $e{charset}
498     || $e{language}
499     || $e{value} =~ /\x0D|\x0A/s
500 wakaba 1.16 || $e{value} =~ /$REG{WSP}$REG{WSP}+/s
501 wakaba 1.15 || ($option->{accept_coderange} eq '7bit'
502     && $e{value} =~ /[\x80-\xFF]/)
503     || ($option->{accept_coderange} ne 'binary'
504     && $e{value} =~ /\x00/)
505     ;
506     } else { ## Don't use paramext
507     if ($item->{charset}) { ## But parameter value is undecodable charset value
508     %e = %$item;
509     $xparam = 1;
510 wakaba 1.1 } else {
511 wakaba 1.15 %e = &{$self->{option}->{hook_encode_string}}
512     ($self, $value,
513     charset => $option->{encoding_after_encode},
514     current_charset => $option->{header_default_charset},
515     language => $item->{language},
516     type => 'parameter/value');
517     }
518     }
519     if ($xparam) {
520     if (length $e{value} > $option->{parameter_value_max_length}) {
521     for my $i (0..(length ($e{value})
522     /$option->{parameter_value_split_length})) {
523     my $v = substr ($e{value},
524     $i * $option->{parameter_value_split_length},
525     $option->{parameter_value_split_length});
526     if ($i == 0) {
527     $v
528     =~ s/($REG{NON_http_attribute_char})/sprintf('%%%02X', ord $1)/ge;
529     my $charset = Message::MIME::Charset::name_minimumize
530     ($e{charset} || $option->{header_default_charset}, $value);
531     push @param, sprintf q{%s*0*=%s'%s'%s%s}, $attribute,
532     $charset, $e{language}, $v, $comment;
533     } else { # $i > 0
534     if ($e{charset} || $v =~ /\x0A|\x0D/s
535     || ($option->{accept_coderange} ne 'binary' && $v =~ /\x00/)
536     || ($option->{accept_coderange} eq '7bit' && $v =~ /[\x80-\xFF]/)) {
537     $v =~ s/($REG{NON_http_attribute_char})/sprintf('%%%02X', ord $1)/ge;
538     push @param, sprintf q{%s*%d*=%s}, $attribute, $i, $v;
539     } else {
540     $v = Message::Util::quote_unsafe_string ($v,
541     unsafe => $option->{parameter_value_unsafe_rule});
542     $v = q{""} if length $v == 0;
543     push @param, sprintf q{%s*%d=%s}, $attribute, $i, $v;
544     }
545 wakaba 1.1 }
546     }
547     } else {
548 wakaba 1.15 unless ($e{charset}) {
549     $e{charset} = Message::MIME::Charset::name_minimumize
550     ($option->{header_default_charset}, $e{value});
551 wakaba 1.1 }
552 wakaba 1.18 $e{value}
553     =~ s/($REG{NON_http_attribute_char})/sprintf('%%%02X', ord $1)/ge;
554 wakaba 1.15 push @param, sprintf q{%s*=%s'%s'%s%s}, $attribute,
555     $e{charset}, $e{language}, $e{value}, $comment;
556 wakaba 1.1 }
557     } else {
558 wakaba 1.15 $e{value} = Message::Util::quote_unsafe_string ($e{value},
559     unsafe => $option->{parameter_value_unsafe_rule});
560     $e{value} = q{""} if length $e{value} == 0;
561     push @param, sprintf '%s=%s%s', $attribute, $e{value}, $comment;
562 wakaba 1.1 }
563 wakaba 1.15 }
564     }, options => \%option );
565     join $option{separator}, @param;
566 wakaba 1.1 }
567 wakaba 1.7 *as_string = \&stringify;
568 wakaba 1.1
569 wakaba 1.15 ## $self->_stringify_param_check (\%item, \%option)
570     ## -- Checks parameter (and modify if necessary).
571     ## Returns either 1 (ok) or 0 (don't output)
572     sub _stringify_param_check ($\%\%) {
573 wakaba 1.9 my $self = shift;
574 wakaba 1.15 my ($item, $option) = @_;
575     (1, $item);
576 wakaba 1.9 }
577    
578 wakaba 1.15 ## scan: Inherited
579    
580     ## TODO: ...
581     sub _scan_sort ($\@) {
582     #my $self = shift;
583     @{$_[1]};
584 wakaba 1.7 }
585    
586 wakaba 1.8 =item $option-value = $p->option ($option-name)
587 wakaba 1.1
588 wakaba 1.7 Gets option value.
589    
590 wakaba 1.8 =item $p->option ($option-name, $option-value, ...)
591 wakaba 1.7
592     Set option value(s). You can pass multiple option name-value pair
593     as parameter when setting.
594 wakaba 1.1
595     =cut
596    
597 wakaba 1.15 ## $self->_option_recursive (\%argv)
598     sub _option_recursive ($\%) {
599 wakaba 1.1 my $self = shift;
600 wakaba 1.15 my $o = shift;
601     for (@{$self->{ $self->{option}->{_HASH_NAME} }}) {
602     $_->{value}->option (%$o) if ref $_ && ref $_->{value};
603 wakaba 1.1 }
604     }
605    
606 wakaba 1.9 ## value_type: Inherited
607 wakaba 1.1
608 wakaba 1.8 =item $clone = $p->clone ()
609 wakaba 1.1
610 wakaba 1.7 Returns a copy of the object.
611 wakaba 1.1
612     =cut
613    
614 wakaba 1.15 ## Inherited
615 wakaba 1.7
616 wakaba 1.1 =head1 LICENSE
617    
618     Copyright 2002 wakaba E<lt>w@suika.fam.cxE<gt>.
619    
620     This program is free software; you can redistribute it and/or modify
621     it under the terms of the GNU General Public License as published by
622     the Free Software Foundation; either version 2 of the License, or
623     (at your option) any later version.
624    
625     This program is distributed in the hope that it will be useful,
626     but WITHOUT ANY WARRANTY; without even the implied warranty of
627     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
628     GNU General Public License for more details.
629    
630     You should have received a copy of the GNU General Public License
631     along with this program; see the file COPYING. If not, write to
632     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
633     Boston, MA 02111-1307, USA.
634    
635     =head1 CHANGE
636    
637     See F<ChangeLog>.
638 wakaba 1.18 $Date: 2002/07/07 00:46:07 $
639 wakaba 1.1
640     =cut
641    
642     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24