/[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.20 - (hide annotations) (download)
Thu Aug 1 06:42:38 2002 UTC (22 years, 3 months ago) by wakaba
Branch: MAIN
CVS Tags: before-dis2-200411, manakai-release-0-3-2, manakai-release-0-3-1, manakai-release-0-4-0, manakai-200612, msg-0-1, HEAD
Branch point for: branch-suikawiki-1, experimental-xml-parser-200401, stable
Changes since 1.19: +3 -3 lines
2002-08-01  Wakaba <w@suika.fam.cx>

	* Unstructured.pm: Rewritten.
	* Subject.pm: Likewise.  Support Japanese government's
	spam mail prefix if Perl has defined $^V (=~ has UTF-8 support).

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.20 $VERSION=do{my @r=(q$Revision: 1.19 $=~/\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 wakaba 1.19 if ($parameter->{charset} ne '*bare') { ## non quoted-string
194 wakaba 1.15 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 wakaba 1.19 } elsif (!$s{success}) {
201     $item{charset} = $option->{header_default_charset_input};
202 wakaba 1.15 }
203     $item{attribute} = $s{value};
204     } else {
205     $item{attribute} = $parameter->{attribute};
206     }
207     $parameter = \%item;
208     } elsif ($parameter->{section_no} < 0) {
209     my %item;
210     $item{attribute} = $parameter->{attribute};
211     $item{language} = $parameter->{language} if $parameter->{language};
212     $item{comment} = $parameter->{comment};
213 wakaba 1.19 if ($parameter->{charset} ne '*bare') { ## non 2231 encoded
214 wakaba 1.15 my %s = &{$self->{option}->{hook_decode_string}}
215     ($self, $parameter->{value},
216     charset => $parameter->{charset} || $option->{encoding_before_decode},
217     type => 'parameter/value/quoted-string');
218     if ($s{charset}) { ## Convertion failed
219     $item{charset} = $s{charset};
220 wakaba 1.19 } elsif (!$s{success}) {
221     $item{charset} = $option->{header_default_charset_input};
222 wakaba 1.15 } elsif ($parameter->{charset}) {
223     $item{output_charset} = $parameter->{charset};
224 wakaba 1.1 }
225 wakaba 1.15 $item{value} = $s{value};
226 wakaba 1.1 } else {
227 wakaba 1.15 $item{value} = $parameter->{value};
228     }
229     $parameter = \%item;
230     } else { ## fragment
231     $fragment{ $parameter->{attribute} }->[ $parameter->{section_no} ]
232     = $parameter->{value};
233     if ($parameter->{section_no} == 0) {
234     $fragment{'*property'}->{ $parameter->{attribute} }
235     ->{language} = $parameter->{language};
236     $fragment{'*property'}->{ $parameter->{attribute} }
237     ->{charset} = $parameter->{charset};
238     }
239     if (ref $parameter->{comment} && @{$parameter->{comment}} > 0) {
240     push @{ $fragment{'*property'}->{ $parameter->{attribute} }
241     ->{comment} }, @{$parameter->{comment}};
242 wakaba 1.1 }
243 wakaba 1.15 $parameter = undef;
244     }
245     }
246     for (keys %fragment) {
247     next if $_ eq '*property';
248     my %item;
249     $item{attribute} = $_;
250     $item{comment} = $fragment{'*property'}->{ $item{attribute} }->{comment};
251     $item{language} = $fragment{'*property'}->{ $item{attribute} }->{language};
252     delete $item{language} unless $item{language};
253     my $charset = $fragment{'*property'}->{ $item{attribute} }->{charset};
254     my %s = &{$self->{option}->{hook_decode_string}}
255     ($self, join ('', @{ $fragment{ $item{attribute} } }),
256     charset => $charset || $option->{encoding_before_decode},
257     type => 'parameter/extended-value/encoded');
258     if ($s{charset}) { ## Convertion failed
259     $item{charset} = $s{charset};
260     } elsif ($charset) {
261     $item{output_charset} = $charset;
262 wakaba 1.3 }
263 wakaba 1.15 $item{value} = $s{value};
264     push @fparameter, \%item;
265 wakaba 1.1 }
266 wakaba 1.15 @$param = (grep { ref $_ eq 'HASH' } @$param, @fparameter);
267 wakaba 1.11 }
268    
269 wakaba 1.15 ## $self->_parse_values_of_paramters (\@parameter, \%option)
270 wakaba 1.11 ## --- Parse each values of parameters
271 wakaba 1.15 sub _parse_values_of_parameters ($\@\%) {
272 wakaba 1.11 my $self = shift;
273 wakaba 1.15 my ($param, $option) = @_;
274     @$param = map {
275     if (!$_->{no_value}) {
276     $_->{value} = $self->_parse_value ($_->{attribute} => $_->{value});
277     } else {
278     $_->{value} = $self->_parse_value ('*no_value_attribute' => $_->{value});
279 wakaba 1.9 }
280     $_;
281 wakaba 1.15 } @$param;
282     }
283    
284     ## $self->_save_parameters (\@parameter, \%option)
285     ## -- Save parameters in $self
286     sub _save_parameters ($\@\%) {
287     my $self = shift;
288     my ($param, $option) = @_;
289     $self->_parse_values_of_parameters ($param, $option) if $option->{parse_all};
290     $self->{ $option->{_HASH_NAME} } = $param;
291 wakaba 1.1 }
292 wakaba 1.15 *__save_parameters = \&_save_parameters;
293    
294 wakaba 1.1
295 wakaba 1.7 =back
296    
297     =head1 METHODS
298    
299     =over 4
300    
301     =item $p->add ($name => [$value], [$name => $value,...])
302 wakaba 1.1
303     Adds parameter name=value pair.
304    
305     Example:
306 wakaba 1.7 $p->add (title => 'foo of bar'); ## title="foo of bar"
307     $p->add (subject => 'hogehoge, foo'); ## subject*=''hogehoge%2C%20foo
308     $p->add (foo => ['bar', language => 'en']) ## foo*='en'bar
309     $p->add ('text/plain', ['', value => 1]) ## text/plain
310 wakaba 1.1
311     This method returns array reference of (name, {value => value, attribute...}).
312    
313     Available options: charset (charset name), language (language tag),
314     value (1/0, see example above).
315    
316     =cut
317    
318 wakaba 1.14 sub _add_hash_check ($$$\%) {
319     my $self = shift;
320     my ($name, $value, $option) = @_;
321     my $value_option = {};
322     if (ref $value eq 'ARRAY') {
323     ($value, %$value_option) = @$value;
324     }
325 wakaba 1.15 ## -- attribute only (no value) parameter
326     if ($value_option->{no_value}) {
327     $name = $self->_parse_value ('*no_value_attribute' => $name) if $$option{parse};
328     return (1, $name => {
329     attribute => $name, no_value => 1,
330     language => $value_option->{language},
331     comment => $value_option->{comment},
332     });
333 wakaba 1.14 }
334 wakaba 1.15 ## -- attribute=value pair
335     if ($$option{validate} && $name =~ /^$REG{NON_http_attribute_char}$/) {
336     if ($$option{dont_croak}) {
337     return (0);
338 wakaba 1.7 } else {
339 wakaba 1.15 Carp::croak qq{add: $name: Invalid parameter name};
340 wakaba 1.7 }
341 wakaba 1.1 }
342 wakaba 1.15 $value = $self->_parse_value ($name => $value) if $$option{parse};
343     (1, $name => {
344     attribute => $name, value => $value,
345     output_charset => $value_option->{charset},
346     charset => $value_option->{current_charset},
347     language => $value_option->{language},
348     comment => $value_option->{comment},
349     });
350 wakaba 1.1 }
351 wakaba 1.7
352 wakaba 1.15 *_add_return_value = \&_replace_return_value;
353    
354     ## (1/0, $name => $value) = $self->_replace_hash_check ($name => $value, \%option)
355     ## -- Checks given value and prepares saving value (hash version)
356     *_replace_hash_check = \&_add_hash_check;
357    
358     ## $value = $self->_replace_hash_shift (\%values, $name, $option)
359     ## -- Returns a value (from %values) and deletes it from %values
360     ## (like CORE::shift for array).
361     sub _replace_hash_shift ($\%$\%) {
362     shift; my $r = shift; my $n = $_[0]->{attribute};
363     if ($$r{$n}) {
364     my $d = $$r{$n};
365     $$r{$n} = undef;
366     return $d;
367     }
368     undef;
369     }
370    
371     ## $value = $self->_replace_return_value (\$item, \%option)
372     ## -- Returns returning value of replace method
373     sub _replace_return_value ($\$\%) {
374     my $self = shift;
375     my ($item, $value) = @_;
376     if ($$item->{no_value}) {
377     $$item->{attribute};
378     } else {
379     $$item->{value};
380 wakaba 1.1 }
381     }
382    
383 wakaba 1.15 ## 1/0 = $self->_delete_match ($by, \$item, \%delete_list, \%option)
384     ## -- Checks and returns whether given item is matched with
385     ## deleting item list
386     sub _delete_match ($$\$\%\%) {
387     my $self = shift;
388     my ($by, $item, $list, $option) = @_;
389     return 0 unless ref $$item; ## Already removed
390     if ($by eq 'attribute' || $by eq 'name') {
391     return 1 if $$list{ $$item->{attribute} };
392     } elsif ($by eq 'value') {
393     return 1 if $$list{ $$item->{value} };
394     } elsif ($by eq 'charset') {
395     return 1 if $$list{ $$item->{output_charset} } || $$list{ $$item->{charset} };
396     } elsif ($by eq 'language') {
397     return 1 if $$list{ $$item->{language} };
398     } elsif ($by eq 'type') {
399     if ($$item->{no_value}) {
400     return 1 if $$list{no_value_attribute};
401     } else {
402     return 1 if $$list{attribute_value_pair};
403 wakaba 1.1 }
404     }
405 wakaba 1.15 0;
406 wakaba 1.1 }
407    
408 wakaba 1.15 ## Delete empty items
409     sub _delete_empty ($) {
410 wakaba 1.1 my $self = shift;
411 wakaba 1.15 my $array = $self->{option}->{_HASH_NAME};
412     $self->{ $array } = [grep { ref $_ } @{$self->{ $array }}] if $array;
413 wakaba 1.1 }
414    
415 wakaba 1.15 =item @param = $p->parameter ($name => ($new_value), (%option))
416 wakaba 1.1
417    
418 wakaba 1.15 =cut
419    
420     sub parameter ($;@) {
421 wakaba 1.1 my $self = shift;
422 wakaba 1.15 if (@_ == 2) { ## $p->parameter (hoge => 'foo')
423     $self->replace (@_);
424     } else { ## $p->parameter ('foo')
425     $self->item (@_);
426 wakaba 1.1 }
427     }
428    
429 wakaba 1.15 *_item_match = \&_delete_match;
430     *_item_return_value = \&_replace_return_value;
431 wakaba 1.1
432 wakaba 1.15 ## $item = $self->_item_new_value ($name, \%option)
433     ## -- Returns new item with key of $name (called when
434     ## no returned value is found and -new_value_unless_exist
435     ## option is true)
436     sub _item_new_value ($$\%) {
437 wakaba 1.1 my $self = shift;
438 wakaba 1.15 my ($key, $option) = @_;
439     if ($option->{by} eq 'attribute' || $option->{by} eq 'name') {
440     return {attribute => $key};
441     }
442     undef;
443 wakaba 1.1 }
444    
445 wakaba 1.15 ## TODO: Implement count,item_exist method
446 wakaba 1.1
447 wakaba 1.7 =item $field-body = $p->stringify ()
448 wakaba 1.1
449 wakaba 1.7 Returns C<field-body> as a string.
450 wakaba 1.1
451     =cut
452    
453     sub stringify ($;%) {
454     my $self = shift;
455 wakaba 1.15 my %o = @_; my %option = %{$self->{option}};
456 wakaba 1.7 for (grep {/^-/} keys %o) {$option{substr ($_, 1)} = $o{$_}}
457 wakaba 1.15 $option{output_parameter_extension} = 0
458     unless $option{use_parameter_extension};
459     $option{output_comment} = 0 unless $option{use_comment};
460 wakaba 1.7 $self->_delete_empty;
461 wakaba 1.15 my @param;
462     $self->scan( sub {shift;
463     my ($item, $option) = @_;
464     my $r = 1;
465     ($r, $item) = $self->_stringify_param_check ($item, $option);
466     return unless $r;
467     my $comment = '';
468     if ($option->{output_comment} && ref $item->{comment}
469     && @{$item->{comment}} > 0) {
470     my @c;
471     for (@{$item->{comment}}) {
472     push @c, '('. $self->Message::Util::encode_ccontent ($_) .')';
473     }
474     $comment = ' '. join ' ', @c;
475     }
476     if ($item->{no_value}) {
477     push @param, Message::Util::quote_unsafe_string ($item->{attribute},
478     unsafe => $option->{parameter_no_value_attribute_unsafe_rule}).$comment;
479     } else {
480     my $xparam = 0;
481     my $attribute = $item->{attribute};
482     return unless length $attribute;
483     my $value = ''.$item->{value};
484     if ($attribute =~ /$REG{ $option->{parameter_attribute_unsafe_rule} }/) {
485     #return 0;
486     $attribute =~ s/($REG{NON_http_attribute_char})/sprintf('%%%02X', ord $1)/ge;
487     }
488     my %e;
489     if ($option->{output_parameter_extension}) {
490     if ($item->{charset}) {
491     %e = %$item;
492     } else {
493     %e = &{$self->{option}->{hook_encode_string}}
494     ($self, $value,
495     charset => $item->{output_charset} || $option->{encoding_after_encode},
496 wakaba 1.20 current_charset => $option->{internal_charset},
497 wakaba 1.15 language => $item->{language},
498     type => 'parameter/value');
499     }
500     $xparam = 1 if (length $e{value} > $option->{parameter_value_max_length})
501     || $e{charset}
502     || $e{language}
503     || $e{value} =~ /\x0D|\x0A/s
504 wakaba 1.16 || $e{value} =~ /$REG{WSP}$REG{WSP}+/s
505 wakaba 1.15 || ($option->{accept_coderange} eq '7bit'
506     && $e{value} =~ /[\x80-\xFF]/)
507     || ($option->{accept_coderange} ne 'binary'
508     && $e{value} =~ /\x00/)
509     ;
510     } else { ## Don't use paramext
511     if ($item->{charset}) { ## But parameter value is undecodable charset value
512     %e = %$item;
513     $xparam = 1;
514 wakaba 1.1 } else {
515 wakaba 1.15 %e = &{$self->{option}->{hook_encode_string}}
516     ($self, $value,
517     charset => $option->{encoding_after_encode},
518     current_charset => $option->{header_default_charset},
519     language => $item->{language},
520     type => 'parameter/value');
521     }
522     }
523     if ($xparam) {
524     if (length $e{value} > $option->{parameter_value_max_length}) {
525     for my $i (0..(length ($e{value})
526     /$option->{parameter_value_split_length})) {
527     my $v = substr ($e{value},
528     $i * $option->{parameter_value_split_length},
529     $option->{parameter_value_split_length});
530     if ($i == 0) {
531     $v
532     =~ s/($REG{NON_http_attribute_char})/sprintf('%%%02X', ord $1)/ge;
533     my $charset = Message::MIME::Charset::name_minimumize
534     ($e{charset} || $option->{header_default_charset}, $value);
535     push @param, sprintf q{%s*0*=%s'%s'%s%s}, $attribute,
536     $charset, $e{language}, $v, $comment;
537     } else { # $i > 0
538     if ($e{charset} || $v =~ /\x0A|\x0D/s
539     || ($option->{accept_coderange} ne 'binary' && $v =~ /\x00/)
540     || ($option->{accept_coderange} eq '7bit' && $v =~ /[\x80-\xFF]/)) {
541     $v =~ s/($REG{NON_http_attribute_char})/sprintf('%%%02X', ord $1)/ge;
542     push @param, sprintf q{%s*%d*=%s}, $attribute, $i, $v;
543     } else {
544     $v = Message::Util::quote_unsafe_string ($v,
545     unsafe => $option->{parameter_value_unsafe_rule});
546     $v = q{""} if length $v == 0;
547     push @param, sprintf q{%s*%d=%s}, $attribute, $i, $v;
548     }
549 wakaba 1.1 }
550     }
551     } else {
552 wakaba 1.15 unless ($e{charset}) {
553     $e{charset} = Message::MIME::Charset::name_minimumize
554     ($option->{header_default_charset}, $e{value});
555 wakaba 1.1 }
556 wakaba 1.18 $e{value}
557     =~ s/($REG{NON_http_attribute_char})/sprintf('%%%02X', ord $1)/ge;
558 wakaba 1.15 push @param, sprintf q{%s*=%s'%s'%s%s}, $attribute,
559     $e{charset}, $e{language}, $e{value}, $comment;
560 wakaba 1.1 }
561     } else {
562 wakaba 1.15 $e{value} = Message::Util::quote_unsafe_string ($e{value},
563     unsafe => $option->{parameter_value_unsafe_rule});
564     $e{value} = q{""} if length $e{value} == 0;
565     push @param, sprintf '%s=%s%s', $attribute, $e{value}, $comment;
566 wakaba 1.1 }
567 wakaba 1.15 }
568     }, options => \%option );
569     join $option{separator}, @param;
570 wakaba 1.1 }
571 wakaba 1.7 *as_string = \&stringify;
572 wakaba 1.1
573 wakaba 1.15 ## $self->_stringify_param_check (\%item, \%option)
574     ## -- Checks parameter (and modify if necessary).
575     ## Returns either 1 (ok) or 0 (don't output)
576     sub _stringify_param_check ($\%\%) {
577 wakaba 1.9 my $self = shift;
578 wakaba 1.15 my ($item, $option) = @_;
579     (1, $item);
580 wakaba 1.9 }
581    
582 wakaba 1.15 ## scan: Inherited
583    
584     ## TODO: ...
585     sub _scan_sort ($\@) {
586     #my $self = shift;
587     @{$_[1]};
588 wakaba 1.7 }
589    
590 wakaba 1.8 =item $option-value = $p->option ($option-name)
591 wakaba 1.1
592 wakaba 1.7 Gets option value.
593    
594 wakaba 1.8 =item $p->option ($option-name, $option-value, ...)
595 wakaba 1.7
596     Set option value(s). You can pass multiple option name-value pair
597     as parameter when setting.
598 wakaba 1.1
599     =cut
600    
601 wakaba 1.15 ## $self->_option_recursive (\%argv)
602     sub _option_recursive ($\%) {
603 wakaba 1.1 my $self = shift;
604 wakaba 1.15 my $o = shift;
605     for (@{$self->{ $self->{option}->{_HASH_NAME} }}) {
606     $_->{value}->option (%$o) if ref $_ && ref $_->{value};
607 wakaba 1.1 }
608     }
609    
610 wakaba 1.9 ## value_type: Inherited
611 wakaba 1.1
612 wakaba 1.8 =item $clone = $p->clone ()
613 wakaba 1.1
614 wakaba 1.7 Returns a copy of the object.
615 wakaba 1.1
616     =cut
617    
618 wakaba 1.15 ## Inherited
619 wakaba 1.7
620 wakaba 1.1 =head1 LICENSE
621    
622     Copyright 2002 wakaba E<lt>w@suika.fam.cxE<gt>.
623    
624     This program is free software; you can redistribute it and/or modify
625     it under the terms of the GNU General Public License as published by
626     the Free Software Foundation; either version 2 of the License, or
627     (at your option) any later version.
628    
629     This program is distributed in the hope that it will be useful,
630     but WITHOUT ANY WARRANTY; without even the implied warranty of
631     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
632     GNU General Public License for more details.
633    
634     You should have received a copy of the GNU General Public License
635     along with this program; see the file COPYING. If not, write to
636     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
637     Boston, MA 02111-1307, USA.
638    
639     =head1 CHANGE
640    
641     See F<ChangeLog>.
642 wakaba 1.20 $Date: 2002/07/22 02:42:17 $
643 wakaba 1.1
644     =cut
645    
646     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24