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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (hide annotations) (download)
Wed Jul 17 00:33:29 2002 UTC (22 years, 4 months ago) by wakaba
Branch: MAIN
Changes since 1.7: +10 -3 lines
2002-07-13  Wakaba <w@suika.fam.cx>

	* Util.pm:
	- (get_host_fqdn): New function.
	- (%OPTION): New hash.
	* Entity.pm (stringify): Pass 'format' option
	to the body (when stringify'ing it) with
	-parent_format option, instead of -format option.

1 wakaba 1.1
2     =head1 NAME
3    
4 wakaba 1.5 Message::Field::Subject -- Perl module for Internet
5     message header C<Subject:> field body
6 wakaba 1.1
7     =cut
8    
9     package Message::Field::Subject;
10     use strict;
11 wakaba 1.5 use vars qw(@ISA %REG $VERSION);
12 wakaba 1.8 $VERSION=do{my @r=(q$Revision: 1.7 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
13 wakaba 1.3 require Message::Util;
14 wakaba 1.5 require Message::Field::Unstructured;
15     push @ISA, q(Message::Field::Unstructured);
16     use overload '""' => sub {shift->stringify};
17 wakaba 1.1
18 wakaba 1.5 *REG = \%Message::Util::REG;
19 wakaba 1.7 $REG{re} = qr/(?:[Rr][Ee]|[Ss][Vv])\^?\[?[0-9]*\]?[:>]/;
20 wakaba 1.1 $REG{fwd} = qr/[Ff][Ww][Dd]?:/;
21     $REG{ml} = qr/[(\[][A-Za-z0-9._-]+[\x20:-][0-9]+[)\]]/;
22     $REG{M_ml} = qr/[(\[]([A-Za-z0-9._-]+)[\x20:-]([0-9]+)[)\]]/;
23     $REG{prefix} = qr/(?:$REG{re}|$REG{fwd}|$REG{ml})(?:$REG{FWS}(?:$REG{re}|$REG{fwd}|$REG{ml}))*/;
24     $REG{M_control} = qr/^cmsg$REG{FWS}([\x00-\xFF]*)$/;
25     $REG{M_was} = qr/\([Ww][Aa][Ss]:? ([\x00-\xFF]+)\)$REG{FWS}$/;
26    
27 wakaba 1.5 =head1 CONSTRUCTORS
28 wakaba 1.1
29 wakaba 1.5 The following methods construct new C<Message::Field::Subject> objects:
30 wakaba 1.1
31 wakaba 1.5 =over 4
32 wakaba 1.1
33     =cut
34    
35 wakaba 1.5 ## Initialize of this class -- called by constructors
36     sub _init ($;%) {
37     my $self = shift;
38     my %options = @_;
39     my %DEFAULT = (
40     #encoding_after_encode ## Inherited
41     #encoding_before_decode ## Inherited
42     -format_adv => 'ADV: %s',
43     -format_fwd => 'Fwd: %s',
44     -format_re => 'Re: %s',
45     -format_was => '%s (was: %s)',
46     #hook_encode_string ## Inherited
47     #hook_decode_string ## Inherited
48     -prefix_cmsg => 'cmsg ',
49     -regex_adv => qr/(?i)ADV:/,
50     -regex_adv_check => qr/^ADV:/,
51     -remove_ml_prefix => 1,
52     );
53     $self->SUPER::_init (%DEFAULT, %options);
54    
55     unless ($self->{option}->{remove_ml_prefix}) {
56     $REG{prefix} = qr/(?:$REG{re}|$REG{fwd})(?:$REG{FWS}(?:$REG{re}|$REG{fwd}))*/;
57     }
58 wakaba 1.1 }
59    
60 wakaba 1.5 =item $subject = Message::Field::Subject->new ([%options])
61 wakaba 1.1
62 wakaba 1.5 Constructs a new C<Message::Field::Subject> object. You might pass some
63     options as parameters to the constructor.
64    
65     =cut
66    
67     ## Inherited
68    
69     =item $subject = Message::Field::Subject->parse ($field-body, [%options])
70    
71     Constructs a new C<Message::Field::Subject> object with
72     given field body. You might pass some options as parameters to the constructor.
73 wakaba 1.1
74     =cut
75    
76     sub parse ($$;%) {
77     my $class = shift;
78 wakaba 1.5 my $self = bless {}, $class;
79 wakaba 1.1 my $field_body = shift;
80 wakaba 1.5 $self->_init (@_);
81 wakaba 1.1 if ($field_body =~ /$REG{M_control}/) {
82 wakaba 1.5 $self->{is_control} = 1; ## Obsoleted control message
83     $self->{field_body} = $1; ## TODO: passes to Message::Field::Control
84 wakaba 1.1 return $self;
85     }
86 wakaba 1.3 my %s = &{$self->{option}->{hook_decode_string}} ($self, $field_body,
87 wakaba 1.6 type => 'text'); $field_body = $s{value};
88 wakaba 1.1 $field_body =~ s{^$REG{FWS}($REG{prefix})$REG{FWS}}{
89     my $prefix = $1;
90     $self->{is_reply} = 1 if $prefix =~ /$REG{re}/;
91     $self->{is_foward} = 1 if $prefix =~ /$REG{fwd}/;
92     if ($prefix =~ /$REG{M_ml}/) {
93     ($self->{ml_name}, $self->{ml_count}) = ($1, $2);
94     }
95     ''
96     }ex;
97 wakaba 1.5 $self->{is_adv} = 1 if $field_body =~ /$self->{option}->{regex_adv}/;
98 wakaba 1.1 $field_body =~ s{$REG{FWS}$REG{M_was}}{
99 wakaba 1.5 my $was = $1;
100     if ($self->{option}->{parse_was}) {
101     $self->{was} = Message::Field::Subject->parse ($was);
102     $self->{was}->{option} = {%{$self->{option}}};
103     ## WARNING: this does not support the cases that some of option
104     ## values are reference to something.
105     } else {
106     $self->{was} = $was;
107     }
108 wakaba 1.1 ''
109     }ex;
110     $self->{field_body} = $field_body;
111     $self;
112     }
113    
114 wakaba 1.5 =back
115    
116     =head1 METHODS
117    
118     =over 4
119    
120     =item $body = $subject->stringify
121    
122     Retruns subject field body as string. String is encoded
123     for message if necessary.
124    
125     =cut
126    
127 wakaba 1.1 sub stringify ($;%) {
128 wakaba 1.5 my $self = shift; my %o = @_;
129     my %option = %{$self->{option}};
130     for (grep {/^-/} keys %o) {$option{substr ($_, 1)} = $o{$_}}
131     if ($self->{is_control}) {
132     my $s = $self->{field_body};
133     $s = $option{prefix_cmsg}.$s if $s;
134     return $s;
135     }
136     my %e = (value => $self->{field_body});
137     my $was = (ref $self->{was}? $self->{was}->as_plain_string: $self->{was});
138     if ($self->{is_reply}) {
139     $e{value} = sprintf $option{format_re}, $e{value};
140     }
141     if ($self->{is_foward}) {
142     $e{value} = sprintf $option{format_fwd}, $e{value};
143     }
144     if (length $was) {
145     $e{value} = sprintf $option{format_was}, $e{value} => $was;
146     }
147     if ($self->{is_adv}
148     && $self->{field_body} !~ /$option{regex_adv_check}/) {
149     $e{value} = sprintf $option{format_adv}, $e{value};
150     }
151     %e = &{$option{hook_encode_string}} ($self, $e{value}, type => 'text');
152     $e{value};
153 wakaba 1.1 }
154 wakaba 1.5 *as_string = \&stringify;
155    
156     =item $body = $subject->as_plain_string
157    
158     Returns subject field body as string. Unlike C<stringify>,
159     retrun string of this method is not encoded (i.e. returned
160     in internal code).
161    
162     =cut
163 wakaba 1.1
164 wakaba 1.3 sub as_plain_string ($;%) {
165 wakaba 1.1 my $self = shift;
166 wakaba 1.5 $self->stringify (-hook_encode_string => sub {shift; (value => shift, @_)}, @_);
167 wakaba 1.1 }
168    
169 wakaba 1.5 =item $text = $subject->text ([$new-text])
170    
171     Returns or set subject text (without prefixes such as "Re: ").
172    
173     =item $text = $subject->value
174    
175     An alias for C<text> method.
176    
177     =cut
178    
179 wakaba 1.8 sub value ($$;$) {
180     my $self = shift;
181     my $ns = shift;
182     if (defined $ns) {
183     $self->{field_body} = $ns;
184     }
185     $self->{field_body};
186     }
187 wakaba 1.5 *text = \&value;
188    
189     =item $subject->change ($new-subject)
190    
191     Changes subject to new text. Current subject is
192     moved to I<was: >, and current I<was: > subject, if any,
193     is removed.
194    
195     =cut
196    
197     sub change ($$;%) {
198 wakaba 1.1 my $self = shift;
199 wakaba 1.5 my $new_string = shift;
200     my %option = @_; $option{-no_was} = 1 unless defined $option{-no_was};
201     $self->{was} = $self->clone (%option);
202     $self->{field_body} = $new_string;
203     $self->{is_adv} = 0;
204     $self->{is_control} = 0;
205     $self->{is_foward} = 0;
206     $self->{is_reply} = 0;
207     $self;
208 wakaba 1.1 }
209    
210 wakaba 1.5 =item $bool = $subject->is ($attribute [=> $bool])
211    
212     Set/gets attribute value.
213    
214     Example:
215    
216     $isreply = $subject->is ('re');
217     ## Strictly, this checks whether start with "Re: " or not.
218    
219     $subject->is (foward => 1, re => 0);
220    
221     =cut
222    
223     sub is ($@) {
224 wakaba 1.1 my $self = shift;
225 wakaba 1.5 if (@_ == 1) {
226     return $self->{ 'is_' . $_[0] };
227     }
228     while (my ($name, $value) = splice (@_, 0, 2)) {
229     $self->{ 'is_' . $name } = $value;
230 wakaba 1.1 }
231     }
232    
233 wakaba 1.5 =item $old_subject = $subject->was
234    
235     Returns I<was: > subject.
236    
237     =cut
238    
239 wakaba 1.1 sub was ($) {
240     my $self = shift;
241     if (ref $self->{was}) {
242     #
243     } elsif ($self->{was}) {
244     $self->{was} = Message::Field::Subject->parse ($self->{was});
245 wakaba 1.5 $self->{was}->{option} = {%{$self->{option}}};
246 wakaba 1.1 } else {
247     $self->{was} = new Message::Field::Subject;
248 wakaba 1.5 $self->{was}->{option} = {%{$self->{option}}};
249 wakaba 1.1 }
250     $self->{was};
251     }
252    
253 wakaba 1.5 =item $clone = $subject->clone ()
254    
255     Returns a copy of the object.
256    
257     =cut
258    
259     sub clone ($;%) {
260     my $self = shift; my %option = @_;
261     my $clone = $self->SUPER::clone;
262     for (grep {/^is_/} keys %{$self}) {
263     $clone->{$_} = $self->{$_};
264     }
265     if (!$option{-no_was} && $self->{was}) {
266     if (ref $self->{was}) {
267     $clone->{was} = $self->{was}->clone;
268     } else {
269     $clone->{was} = $self->{was};
270     }
271     }
272     $clone;
273 wakaba 1.1 }
274    
275 wakaba 1.5 =head1 EXAMPLE
276    
277     my $subject = parse Message::Field::Subject 'Re: cool message';
278     $subject->change (q{What's "cool"?});
279     print $subject; # What's "cool"? (was: Re: cool message)
280 wakaba 1.1
281     =head1 LICENSE
282    
283     Copyright 2002 wakaba E<lt>w@suika.fam.cxE<gt>.
284    
285     This program is free software; you can redistribute it and/or modify
286     it under the terms of the GNU General Public License as published by
287     the Free Software Foundation; either version 2 of the License, or
288     (at your option) any later version.
289    
290     This program is distributed in the hope that it will be useful,
291     but WITHOUT ANY WARRANTY; without even the implied warranty of
292     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
293     GNU General Public License for more details.
294    
295     You should have received a copy of the GNU General Public License
296     along with this program; see the file COPYING. If not, write to
297     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
298     Boston, MA 02111-1307, USA.
299    
300     =head1 CHANGE
301    
302     See F<ChangeLog>.
303 wakaba 1.8 $Date: 2002/07/06 10:30:43 $
304 wakaba 1.1
305     =cut
306    
307     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24