/[suikacvs]/messaging/bunshin/Bunshin.pm
Suika

Contents of /messaging/bunshin/Bunshin.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (show annotations) (download)
Tue Sep 10 23:37:43 2002 UTC (21 years, 7 months ago) by wakaba
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +21 -2 lines
2002-09-11  Wakaba <w@suika.fam.cx>

	* Bunshin.pm (set_element_decoders): New method.

1
2 =head1 NAME
3
4 Bunshin --- A shimbun implemrntion written in Perl
5
6 =cut
7
8 package Bunshin;
9 use strict;
10 use vars qw($DEBUG $MYNAME $VERSION);
11 $VERSION=do{my @r=(q$Revision: 1.5 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
12 $MYNAME = 'Bunshin';
13 $DEBUG = 0;
14 use FileHandle;
15 require Message::Entity;
16 require Message::Util;
17 require Message::Field::Date;
18
19 sub new ($;%) {
20 my $class = shift;
21 my $self = bless {}, $class;
22 $self->{fmt2str} = Message::Util::make_clone
23 (\%Message::Field::Date::FMT2STR);
24 $self;
25 }
26
27 =item $b->msg_regex ($regex)
28
29 Set regex used to cut a message.
30
31 =cut
32
33 sub set_regex ($$$) {
34 my $self = shift;
35 my $name = shift;
36 my $regex = shift;
37 $regex =~ s/\x20/\\x20/g;
38 $regex =~ s/\x09/\\x09/g;
39 $regex =~ s/\x0D(?!\x0A)/\x0D\x0A/g;
40 $regex =~ s/(?<!\x0D)\x0A/\x0D\x0A/g;
41 $regex =~ s/\x0D/\\x0D/g;
42 $regex =~ s/\x0A/\\x0A/g;
43 $regex =~ s/\x23/\\x23/g;
44 $self->{'regex_'.$name} = $regex;
45 }
46
47 sub set_hook_function ($$\&) {
48 my $self = shift;
49 my $name = shift;
50 my $function = shift;
51 $self->{'hook_'.$name} = $function;
52 }
53
54 sub set_element_decoders ($%) {
55 my $self = shift;
56 my %list = @_;
57 for (keys %list) {
58 if ($list{$_} eq 'enentity_html') {
59 $list{$_} = \&Message::Util::enentity_html;
60 } elsif ($list{$_} eq 'deentity_html') {
61 $list{$_} = \&Message::Util::deentity_html;
62 ## TODO: escape_uri, unescape_uri
63 }
64 }
65 $self->{element_decoder} = %list;
66 }
67
68 sub set_format ($$\&) {
69 my $self = shift;
70 my $name = shift;
71 my $function = shift;
72 $self->{fmt2str}->{$name} = $function;
73 }
74
75 sub set_elements ($$@) {
76 my $self = shift;
77 my $name = shift;
78 $self->{'elements_'.$name} = \@_;
79 }
80
81 sub set_source ($%) {
82 my $self = shift;
83 my %option = @_;
84 ($self->{source}, $self->{meta_info}) = $self->_get_resource (%option);
85 $self->default_parameter (base_uri => $option{uri}) if $option{uri};
86 ## BUG: Doesn't support redirection
87 if ($option{uri} || $option{file}) {
88 my $c = $self->{hook_code_conversion} || \&_code_conversion;
89 $self->{source} = &$c ($self, $self->{source}, \%option, $self->{meta_info});
90 }
91 $self->{source} =~ s/\x0D(?!\x0A)/\x0D\x0A/g;
92 $self->{source} =~ s/(?<!\x0D)\x0A/\x0D\x0A/g;
93 $self;
94 }
95
96 sub _get_resource ($%) {
97 my $self = shift;
98 my %option = @_;
99 my ($resource, $meta);
100 if (defined $option{value}) {
101 $resource = $option{value};
102 } elsif ($option{uri}) {
103 require Message::Field::UA;
104 require LWP::UserAgent;
105 my $ua = Message::Field::UA->new;
106 $ua->add_our_name;
107 $ua->add ('libwww-perl' => $LWP::VERSION);
108 my $lwp = LWP::UserAgent->new;
109 $lwp->agent ($ua->stringify);
110 my $req = HTTP::Request->new (GET => $option{uri});
111 my $res = $lwp->request ($req);
112 $resource = $res->content;
113 $meta = parse Message::Header $res->headers_as_string,
114 -parse_all => 0, -format => 'http-response',
115 ;
116 } elsif ($option{file}) {
117 my $f = new FileHandle $option{file} => 'r';
118 Carp::croak "set_source: $option{file}: $!" unless defined $f;
119 my $c = $self->{hook_code_conversion} || \&_code_conversion;
120 local $/ = undef;
121 $resource = $f->getline;
122 } else {
123 Carp::croak "_get_resource: $_[0]: Unsupported data source type";
124 }
125 ($resource, $meta);
126 }
127
128 ## $self->_code_conversion ($string, \%option, $meta_info)
129 sub _code_conversion ($$\%$) {
130 $_[1];
131 }
132
133 sub make_msgs ($) {
134 my $self = shift;
135 my $s = $self->{source};
136 my $f = $self->{hook_make_msg} || \&_make_a_msg;
137 my @msg;
138 my %param = %{$self->{default_parameter}};
139 if ($self->{regex_metainfo} && ref $self->{elements_metainfo}) {
140 $s =~ s{ $self->{regex_metainfo} }{
141 no strict 'refs';
142 for my $i (0..$#{$self->{elements_metainfo}}) {
143 $param{$self->{elements_metainfo}->[$i]} = ${$i+1};
144 }
145 $&;
146 }esx;
147 }
148 $s =~ s{ $self->{regex_message} }{
149 no strict 'refs';
150 my %p = %param;
151 for my $i (0..$#{$self->{elements_message}}) {
152 $p{$self->{elements_message}->[$i]} = ${$i+1};
153 }
154 for my $n (keys %{$self->{element_decoder}}) {
155 if ($p{$n} && ref $self->{element_decoder}->{$n}) {
156 $p{$n} = &{ $self->{element_decoder}->{$n} } ($p{$n});
157 }
158 }
159 my $msg = &$f ($self, %p);
160 push @msg, $msg;
161 }gesx;
162 @msg;
163 }
164
165 ## Default function for "make_msg"
166 sub _make_a_msg ($@) {
167 my $self = shift;
168 my %p = @_;
169 my $msg = new Message::Entity
170 -fill_date => 0,
171 -fill_msgid => 0,
172 -fill_ua_name => 'x-shimbun-agent',
173 -format => 'news-usefor',
174 -parse_all => 1,
175 ;
176 my $hdr = $msg->header;
177 ## Originator and date
178 my $from = $hdr->field ('from')->add ($p{from_mail} || 'foo@bar.invalid');
179 $from->display_name ($p{from_name}) if length $p{from_name};
180 my $date = $hdr->field ('date');
181 $p{date_year} ||= (gmtime)[5];
182 $date->set_datetime (@p{qw/date_year date_month
183 date_day date_hour date_minute date_second/},
184 zone => $p{date_zone});
185 $hdr->add (x_uri => $p{from_uri}) if $p{from_uri};
186 if ($p{from_face}) {
187 $msg->header->field ('x-face')->value ($p{from_face});
188 } elsif ($p{faces}->{$p{from_mail}}) {
189 $msg->header->field ('x-face')->value ($p{faces}->{$p{from_mail}});
190 } elsif ($p{list_face}) {
191 $msg->header->field ('x-face')->value ($p{list_face});
192 }
193 ## Message attribute
194 if (length $p{msg_id}) {
195 $hdr->add ('message-id' => $p{msg_id});
196 } elsif ($p{msg_id_from} || $p{msg_id_right} || $p{list_id}) {
197 my $c = $p{msg_count};
198 $c = '.d'.(0+$date) unless defined $p{msg_count};
199 my $mid;
200 if ($p{msg_id_from}) {
201 $mid = sprintf '<msg%s.BS%%%s%%%s>', $c, $p{list_id}, $p{msg_id_from};
202 } elsif ($p{msg_id_right}) {
203 $mid = sprintf '<msg%s.BS%%%s%%list@%s>', $c, $p{list_id}, $p{msg_id_right};
204 } else { #if ($p{list_id}) {
205 $mid = sprintf '<msg%s.BS%%list@%s>', $c, $p{list_id};
206 }
207 $hdr->add (($DEBUG?'x-':'').'message-id' => $mid);
208 }
209 if (length $p{subject}) {
210 $hdr->add (subject => $p{subject});
211 } elsif (length $p{DEFAULT_subject}) {
212 $hdr->add (subject => $p{DEFAULT_subject});
213 }
214 my $a;
215 for (grep {/^misc_/} keys %p) {
216 $a = $hdr->field ('content-x-properties') unless ref $a;
217 my $name = substr ($_, 5);
218 $name =~ tr/_/-/;
219 if ($p{base_uri} && /uri/ && length $p{$_}) {
220 require URI::WithBase;
221 $a->add ($name => URI::WithBase->new ($p{$_}, $p{base_uri})->abs);
222 } elsif (/color/) {
223 $p{$_} = '#'.$p{$_} if $p{$_} =~ /^[A-Za-z0-9]{6}$/;
224 $a->add ($name => $p{$_}) if length $p{$_};
225 } else {
226 $a->add ($name => $p{$_}) if length $p{$_};
227 }
228 }
229 ## Body and body information
230 my $b = $self->{hook_msg_body} || \&_make_a_msg_body;
231 &$b ($self, $msg, $p{body}, \%p);
232 ## List information
233 if (length $p{list_id}) {
234 my $lid = $hdr->field ('list-id');
235 $lid->value ($p{list_id});
236 $lid->display_name ($p{list_name}) if length $p{list_name};
237 }
238 $hdr->add (x_mail_count => $p{msg_count}) if defined $p{msg_count};
239 $hdr->add (x_ml_info => $p{list_info}) if defined $p{list_info};
240 if ($p{base_uri}) {
241 my $uri = $hdr->add (x_uri => '');
242 $uri->value ($p{base_uri});
243 $uri->display_name ($p{list_name}) if length $p{list_name};
244 }
245 if ($p{urn_template}) {
246 my $urn = $date->stringify (
247 -format_macros => $self->{fmt2str},
248 -format_template => $p{urn_template},
249 -format_parameters => \%p,
250 );
251 #my $urn = $self->Message::Field::Date::_date2str ({
252 # format_template => $p{urn_template},
253 # date_time => $date->unix_time,
254 # zone => $date->zone,
255 # fmt2str => $self->{fmt2str},
256 #}, \%p);
257 $hdr->add ('x-uri')->value ($urn);
258 }
259 ## Additional information
260 my $u = $self->{hook_msg_header_add};
261 &$u ($self, $msg, \%p) if ref $u;
262 $hdr->field ('x-shimbun-agent')->add ($MYNAME => $VERSION);
263 $msg;
264 }
265
266 sub _make_a_msg_body ($$$\%) {
267 my $self = shift;
268 my ($msg, $body, $param) = @_;
269 if (length $body) {
270 $body =~ s/(?<!\x0D\x0A)\z/\x0D\x0A/s;
271 $msg->body ($body);
272 }
273 }
274
275 sub default_parameter ($@) {
276 my $self = shift;
277 if (@_ == 1) {
278 return $self->{default_parameter}->{ $_[0] };
279 }
280 while (my ($name, $value) = splice (@_, 0, 2)) {
281 $self->{default_parameter}->{$name} = $value;
282 }
283 $self;
284 }
285
286 =head1 $meta = $b->meta_information
287
288 Gets meta information from resource requesting protocol.
289 Usually returned value is Message::Header object.
290 When resource is getten via HTTP, its content is HTTP response
291 header.
292
293 =cut
294
295 sub meta_information ($) {
296 my $self = shift;
297 $self->{meta_info};
298 }
299
300 =head1 LICENSE
301
302 Copyright 2002 wakaba E<lt>w@suika.fam.cxE<gt>.
303
304 This program is free software; you can redistribute it and/or modify
305 it under the terms of the GNU General Public License as published by
306 the Free Software Foundation; either version 2 of the License, or
307 (at your option) any later version.
308
309 This program is distributed in the hope that it will be useful,
310 but WITHOUT ANY WARRANTY; without even the implied warranty of
311 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
312 GNU General Public License for more details.
313
314 You should have received a copy of the GNU General Public License
315 along with this program; see the file COPYING. If not, write to
316 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
317 Boston, MA 02111-1307, USA.
318
319 =head1 CHANGE
320
321 See F<ChangeLog>.
322 $Date: 2002/08/29 12:10:59 $
323
324 =cut
325
326 1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24