summaryrefslogtreecommitdiff
path: root/fml/lib
diff options
context:
space:
mode:
authorfukachan <fukachan>2004-03-31 12:53:50 +0000
committerfukachan <fukachan>2004-03-31 12:53:50 +0000
commit5432a7011fcb4386b56fc044a54ec4c4dd2da0e5 (patch)
tree0d73b11db0e7a903d7b020323b97f6aaaa8cd10d /fml/lib
parent408f950159c3aae27154eaaceb15d6d91095d9d9 (diff)
downloadfml8-5432a7011fcb4386b56fc044a54ec4c4dd2da0e5.tar.gz
fml8-5432a7011fcb4386b56fc044a54ec4c4dd2da0e5.tar.bz2
fml8-5432a7011fcb4386b56fc044a54ec4c4dd2da0e5.zip
Mail::ThreadTrack is obsoleted. remove related codes.
Diffstat (limited to 'fml/lib')
-rw-r--r--fml/lib/FML/CGI/ThreadTrack.pm247
-rw-r--r--fml/lib/FML/Command/Admin/thread.pm116
-rw-r--r--fml/lib/FML/Process/Distribute.pm41
-rw-r--r--fml/lib/FML/Process/Switch.pm3
-rwxr-xr-xfml/lib/Mail/ThreadTrack.pm591
-rw-r--r--fml/lib/Mail/ThreadTrack/Analyze.pm663
-rw-r--r--fml/lib/Mail/ThreadTrack/DB.pm321
-rw-r--r--fml/lib/Mail/ThreadTrack/HeaderRewrite.pm133
-rw-r--r--fml/lib/Mail/ThreadTrack/Print.pm419
-rw-r--r--fml/lib/Mail/ThreadTrack/Print/HTML.pm291
-rw-r--r--fml/lib/Mail/ThreadTrack/Print/Message.pm253
-rw-r--r--fml/lib/Mail/ThreadTrack/Print/Sort.pm124
-rw-r--r--fml/lib/Mail/ThreadTrack/Print/Text.pm247
-rw-r--r--fml/lib/Mail/ThreadTrack/Print/Utils.pm115
14 files changed, 3 insertions, 3561 deletions
diff --git a/fml/lib/FML/CGI/ThreadTrack.pm b/fml/lib/FML/CGI/ThreadTrack.pm
deleted file mode 100644
index 9e729338..00000000
--- a/fml/lib/FML/CGI/ThreadTrack.pm
+++ /dev/null
@@ -1,247 +0,0 @@
-#-*- perl -*-
-#
-# Copyright (C) 2001,2002,2003,2004 Ken'ichi Fukamachi
-# All rights reserved. This program is free software; you can
-# redistribute it and/or modify it under the same terms as Perl itself.
-#
-# $FML: ThreadTrack.pm,v 1.28 2004/01/01 23:52:10 fukachan Exp $
-#
-
-package FML::CGI::ThreadTrack;
-use strict;
-use Carp;
-use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
-use CGI qw/:standard/; # load standard CGI routines
-
-use FML::Process::CGI;
-@ISA = qw(FML::Process::CGI);
-
-
-=head1 NAME
-
-FML::CGI::ThreadTrack - CGI details to control thread system
-
-=head1 SYNOPSIS
-
- $obj = new FML::CGI::ThreadTrack;
- $obj->prepare();
- $obj->verify_request();
- $obj->run();
- $obj->finish();
-
-run() executes html_start(), run_cgi() and html_end() described below.
-
-See L<FML::Process::Flow> for flow details.
-
-=head1 DESCRIPTION
-
-=head2 CLASS HIERARCHY
-
-C<FML::CGI::ThreadTrack> is a subclass of C<FML::Process::CGI>.
-
-=head1 METHODS
-
-Almost methods common for CGI or HTML are forwarded to
-C<FML::Process::CGI> base class.
-
-=cut
-
-
-# Descriptions: print out HTML header + body former part
-# Arguments: OBJ($curproc)
-# Side Effects: none
-# Return Value: none
-sub html_start
-{
- my ($curproc) = @_;
- my $config = $curproc->config();
- my $title = $config->{ thread_cgi_title } || 'thread system interface';
- my $color = $config->{ thread_cgi_bgcolor } || '#E6E6FA';
- my $myname = $curproc->myname();
- my $charset = $curproc->get_charset("cgi");
-
- # o.k start html
- print start_html(-title => $title,
- -lang => $charset,
- -BGCOLOR => $color);
- print "\n";
-}
-
-
-# Descriptions: print out body latter part
-# Arguments: OBJ($curproc)
-# Side Effects: none
-# Return Value: none
-sub html_end
-{
- my ($curproc) = @_;
-
- # o.k. end of html
- print end_html;
- print "\n";
-}
-
-
-# Descriptions: main routine for thread control.
-# run_cgi() can process request: list, show, change_status
-# Arguments: OBJ($curproc)
-# Side Effects: none
-# Return Value: none
-sub run_cgi_main
-{
- my ($curproc) = @_;
- my $config = $curproc->config();
- my $myname = $config->{ program_name }; # XXX-TODO: valid ?
- my $ttargs = $curproc->_build_threadtrack_param();
- my $action = $curproc->safe_param_action() || '';
-
- use Mail::ThreadTrack;
- my $thread = new Mail::ThreadTrack $ttargs;
-
- if (defined $thread) {
- $thread->set_mode('html');
-
- if ($action eq 'list') {
- $thread->summary();
- }
- elsif ($action eq 'show') {
- my $id = $curproc->safe_param_article_id();
- # XXX-TODO: do not call _XXX() internal method from outside.
- my $tid = $thread->_create_thread_id_strings($id);
- $thread->show($tid);
- }
- elsif ($action eq 'change_status') {
- # fmlthread.cgi is for administorator, so you can change status.
- if ($myname eq 'fmlthread.cgi') {
- my $list = $curproc->safe_paramlist2_threadcgi_change_status();
- for my $param (@$list) {
- my ($ml, $id, $value) = @$param;
- if ($value eq 'closed') {
- my $tid = $thread->_create_thread_id_strings($id);
- print "closed $tid", br, "\n";
- $thread->close($tid);
- }
- }
- }
- # XXX-TODO: ? clarify this message more.
- else {
- print "Warning: only administrator change status\n";
- }
-
- $thread->summary();
- }
- else {
- $thread->summary();
- }
- }
- else {
- croak("fail to create thread object");
- }
-}
-
-
-# Descriptions: prepare basic parameters for Mail::ThreadTrack module
-# Arguments: OBJ($curproc)
-# Side Effects: none
-# Return Value: HASH_REF
-sub _build_threadtrack_param
-{
- my ($curproc) = @_;
- my $config = $curproc->config();
- my $myname = $config->{ program_name };
- my $option = $curproc->command_line_options();
-
- # prepare arguments for thread track module
- # XXX-TODO: hmm, we should provide $curproc->util->article_max_id() ?
- my $ml_name = $curproc->safe_param_ml_name();
- my $thread_db_dir = $config->{ thread_db_dir };
- my $spool_dir = $config->{ spool_dir };
- my $max_id = $curproc->article_max_id();
- my $ttargs = {
- myname => $myname,
- logfp => \&Log,
- fd => \*STDOUT,
- db_base_dir => $thread_db_dir,
- ml_name => $ml_name,
- spool_dir => $spool_dir,
- reverse_order => 0,
- };
-
- # import some variables
- for my $varname (qw(base_url msg_base_url)) {
- if (defined $option->{ $varname }) {
- $ttargs->{ $varname } = $option->{ $varname };
- }
- elsif (defined $config->{ $varname }) {
- $ttargs->{ $varname } = $config->{ $varname };
- }
- }
-
- return $ttargs;
-}
-
-
-# Descriptions: print navigation bar
-# Arguments: OBJ($curproc)
-# Side Effects: none
-# Return Value: none
-sub run_cgi_navigator
-{
- my ($curproc) = @_;
- my $config = $curproc->config();
- my $action = $curproc->safe_cgi_action_name();
- my $target = $config->{ thread_cgi_target_window } || '_top';
- # XXX-TODO: we should provide $curproc->util->get_ml_list() method ?
- my $ml_list = $curproc->get_ml_list();
- my $ml_name = $config->{ ml_name };
-
- print start_form(-action=>$action, -target=>$target);
-
- print "ML: ";
- print popup_menu(-name => 'ml_name', -values => $ml_list);
- print "<BR>\n";
-
- print "orderd by: ";
- my $order = [ 'cost', 'date', 'reverse date' ];
- print popup_menu(-name => 'order', -values => $order );
- print "<BR>\n";
-
- print submit(-name => 'change target');
- print reset(-name => 'reset');
-
- print end_form;
- print "<HR>\n";
-}
-
-
-=head1 SEE ALSO
-
-L<CGI>,
-L<FML::Process::CGI>
-and
-L<FML::Process::Flow>
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 AUTHOR
-
-Ken'ichi Fukamachi
-
-=head1 COPYRIGHT
-
-Copyright (C) 2001,2002,2003,2004 Ken'ichi Fukamachi
-
-All rights reserved. This program is free software; you can
-redistribute it and/or modify it under the same terms as Perl itself.
-
-=head1 HISTORY
-
-FML::CGI::ThreadTrack first appeared in fml8 mailing list driver package.
-See C<http://www.fml.org/> for more details.
-
-=cut
-
-
-1;
diff --git a/fml/lib/FML/Command/Admin/thread.pm b/fml/lib/FML/Command/Admin/thread.pm
index b6038ee8..f3876af0 100644
--- a/fml/lib/FML/Command/Admin/thread.pm
+++ b/fml/lib/FML/Command/Admin/thread.pm
@@ -4,7 +4,7 @@
# All rights reserved. This program is free software; you can
# redistribute it and/or modify it under the same terms as Perl itself.
#
-# $FML: thread.pm,v 1.5 2004/03/28 13:05:55 fukachan Exp $
+# $FML: thread.pm,v 1.6 2004/03/29 14:13:20 fukachan Exp $
#
package FML::Command::Admin::thread;
@@ -126,120 +126,6 @@ sub _new_switch
}
-=head1 OLD VERSION
-
-=cut
-
-
-# Descriptions: thread manipulation interface.
-# Arguments: OBJ($self) OBJ($curproc) HASH_REF($command_args)
-# Side Effects: update $recipient_map
-# Return Value: none
-sub old_process
-{
- my ($self, $curproc, $command_args) = @_;
- my $config = $curproc->config();
- my $myname = $curproc->myname();
-
- # prepare argumente for thread track module (Mail::ThreadTrack).
- my $ml_name = $config->{ ml_name };
- my $thread_db_dir = $config->{ thread_db_dir };
- my $spool_dir = $config->{ spool_dir };
- my $max_id = $curproc->article_max_id();
- my $ttargs = {
- myname => $myname,
- logfp => \&Log,
- fd => \*STDOUT,
- db_base_dir => $thread_db_dir,
- ml_name => $ml_name,
- spool_dir => $spool_dir,
- max_id => $max_id,
- reverse_order => 1,
- };
-
- # if (defined $options->{ f }) {
- # _read_filter_list($thread, $options->{ f });
- # }
-
- $self->_old_switch($curproc, $command_args, $ttargs);
-}
-
-
-# Descriptions: switch thread library command
-# Arguments: OBJ($self) OBJ($curproc) HASH_REF($command_args)
-# HASH_REF($ttargs)
-# Side Effects: thread db may be updated
-# Return Value: none
-sub _old_switch
-{
- my ($self, $curproc, $command_args, $ttargs) = @_;
- my $options = $command_args->{ options };
- my $command = $options->[ 0 ] || 'list';
- my $max_id = $ttargs->{ max_id };
-
- # utility functions for spool in fml side.
- use FML::Article::Thread;
- my $a_thread = new FML::Article::Thread $curproc;
-
- # functions to manipulate thread db.
- use Mail::ThreadTrack;
- my $thread = new Mail::ThreadTrack $ttargs;
- $thread->set_mode('text');
-
- if ($command eq 'list' || $command eq 'summary') {
- $thread->$command();
- }
- elsif ($command eq 'review') {
- my $str = $options->[ 1 ] || 'last:100';
- $thread->review( $str , 1, $max_id );
- }
- elsif ($command eq 'db_dump') {
- my $type = $options->[ 1 ] || 'status';
- $thread->db_open();
- $thread->db_dump( $type );
- $thread->db_close();
- }
- elsif ($command eq 'db_update') {
- my $last_id = $a_thread->speculate_last_id($curproc, $thread);
- print STDERR "db_update: $last_id -> $max_id\n";
- $thread->db_mkdb($last_id, $max_id);
- }
- elsif ($command eq 'db_rebuild') {
- print STDERR "\$thread->db_mkdb(1, $max_id);\n";
- $thread->db_mkdb(1, $max_id);
- }
- elsif ($command eq 'db_clear') {
- $thread->db_open();
- $thread->db_clear();
- $thread->db_close();
- }
- elsif ($command eq 'close') {
- my $thread_id = $options->[ 1 ];
- if (defined $thread_id) {
- $a_thread->close($thread, $thread_id, 1, $max_id);
- }
- else {
- croak("specify \$thread_id");
- }
- }
- elsif ($command eq 'cui') {
- # XXX-TODO: hmm, run interactive session unless @ARGV ?
- # XXX-TODO: showing help is appropriate ?
- if ($options->[ 1 ]) {
- push(@ISA, 'FML::Article::Thread::CUI');
- # $ttargs->{ ml_name } = $argv->[ 0 ];
- $a_thread->interactive($thread, $ttargs);
- }
- else {
- help();
- }
- }
- else {
- croak("subcommand not specified");
- }
-}
-
-
=head1 CODING STYLE
See C<http://www.fml.org/software/FNF/> on fml coding style guide.
diff --git a/fml/lib/FML/Process/Distribute.pm b/fml/lib/FML/Process/Distribute.pm
index 717e45be..a756acd8 100644
--- a/fml/lib/FML/Process/Distribute.pm
+++ b/fml/lib/FML/Process/Distribute.pm
@@ -3,7 +3,7 @@
# Copyright (C) 2000,2001,2002,2003,2004 Ken'ichi Fukamachi
# All rights reserved.
#
-# $FML: Distribute.pm,v 1.140 2004/03/17 10:27:35 fukachan Exp $
+# $FML: Distribute.pm,v 1.141 2004/03/28 10:33:35 fukachan Exp $
#
package FML::Process::Distribute;
@@ -514,45 +514,6 @@ sub _deliver_article
# Arguments: OBJ($curproc)
# Side Effects: update thread information
# Return Value: none
-sub _old_thread_check
-{
- my ($curproc) = @_;
- my $config = $curproc->config();
- my $pcb = $curproc->pcb();
- my $myname = $curproc->myname();
-
- my $ml_name = $config->{ ml_name };
- my $thread_db_dir = $config->{ thread_db_dir };
- my $spool_dir = $config->{ spool_dir };
- my $article_id = $pcb->get('article', 'id');
- my $is_rewrite_hdr = $config->yes('use_thread_subject_tag') ? 1 : 0;
- my $ttargs = {
- myname => $myname,
- logfp => \&Log,
- fd => \*STDOUT,
- db_base_dir => $thread_db_dir,
- ml_name => $ml_name,
- spool_dir => $spool_dir,
- article_id => $article_id,
- rewrite_header => $is_rewrite_hdr,
- };
-
- my $msg = $curproc->article_message();
-
- # old thread engine
- eval q{
- use Mail::ThreadTrack;
- my $thread = new Mail::ThreadTrack $ttargs;
- $thread->analyze($msg);
- };
- $curproc->log($@) if $@;
-}
-
-
-# Descriptions: the top level interface to drive thread tracking system.
-# Arguments: OBJ($curproc)
-# Side Effects: update thread information
-# Return Value: none
sub _new_thread_check
{
my ($curproc) = @_;
diff --git a/fml/lib/FML/Process/Switch.pm b/fml/lib/FML/Process/Switch.pm
index bd1f6fd1..4ed2859b 100644
--- a/fml/lib/FML/Process/Switch.pm
+++ b/fml/lib/FML/Process/Switch.pm
@@ -4,7 +4,7 @@
# All rights reserved. This program is free software; you can
# redistribute it and/or modify it under the same terms as Perl itself.
#
-# $FML: Switch.pm,v 1.103 2003/12/30 03:56:00 fukachan Exp $
+# $FML: Switch.pm,v 1.104 2004/01/02 14:42:44 fukachan Exp $
#
package FML::Process::Switch;
@@ -547,7 +547,6 @@ L<FML::Process::Distribute>,
L<FML::Process::Command>,
L<FML::Process::ListServer>,
L<FML::Process::Configure>,
-L<FML::Process::ThreadTrack>,
L<FML::Process::MailErrorAnalyzer>
=head1 CODING STYLE
diff --git a/fml/lib/Mail/ThreadTrack.pm b/fml/lib/Mail/ThreadTrack.pm
deleted file mode 100755
index f57154b1..00000000
--- a/fml/lib/Mail/ThreadTrack.pm
+++ /dev/null
@@ -1,591 +0,0 @@
-#-*- perl -*-
-#
-# Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-# All rights reserved. This program is free software; you can
-# redistribute it and/or modify it under the same terms as Perl itself.
-#
-# $FML: ThreadTrack.pm,v 1.34 2003/01/11 15:16:34 fukachan Exp $
-#
-
-package Mail::ThreadTrack;
-use strict;
-use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
-use Carp;
-
-use Mail::ThreadTrack::Analyze;
-use Mail::ThreadTrack::DB;
-use Mail::ThreadTrack::Print;
-
-@ISA = qw(Mail::ThreadTrack::Analyze
- Mail::ThreadTrack::DB
- Mail::ThreadTrack::Print
- );
-
-
-=head1 NAME
-
-Mail::ThreadTrack - analyze message thread
-
-=head1 SYNOPSIS
-
- ... lock mailing list ...
-
- my $args = {
- fd => \*STDOUT,
- db_base_dir => "/var/spool/ml/\@db\@/thread",
- ml_name => 'elena',
- spool_dir => "/var/spool/ml/elena/spool",
- article_id => 100,
- };
-
- use Mail::ThreadTrack;
- my $thread = new Mail::ThreadTrack $args;
- $thread->analyze($msg);
- $thread->show_summary();
-
- ... unlock mailing list ...
-
-where C<$msg> is Mail::Message object for the article 100.
-
-=head1 DESCRIPTION
-
-=head1 METHODS
-
-=head2 new($args)
-
- $args = {
- fd => \*STDOUT,
- db_base_dir => "/var/spool/ml/\@db\@/thread",
- ml_name => 'elena',
- spool_dir => "/var/spool/ml/elena/spool",
- article_id => $id,
- };
-
-C<db_base_dir>, C<spool_dir> and C<ml_name> in C<config> are mandatory.
-C<$id> is the sequential number for input data (article).
-
-Available variables in $args follows:
-
- variables type example
- ------------------------------------------------------------
- myname STR ?
- ml_name STR elena
- spool_dir STR /var/spool/ml/elena
- article_id STR 100
- db_base_dir STR /var/spool/ml/@db@/thread
- reverse_order STR 1 or 0
- rewrite_header STR 1 or 0
- base_url STR "" or URL
- msg_base_url STR "" or URL
- dir_mode NUM 0755
- thread_id_syntax STR elena/%d
- thread_subject_tag STR [elena/%d]
- fd HANDLE \*STDOUT
- logfp CODE \&Log()
-
-=cut
-
-
-my $dir_mode = 0755;
-
-
-# Descriptions: constructor
-# Arguments: OBJ($self) HASH_REF($args)
-# Side Effects: none
-# Return Value: OBJ
-sub new
-{
- my ($self, $args) = @_;
- my ($type) = ref($self) || $self;
- my $me = {};
- my $config = $me->{ _config } = {
- db_type => 'AnyDBM_File',
- };
-
- if (defined $args->{ dir_mode }) {
- $dir_mode = $args->{ dir_mode };
- }
-
- my @keys = qw(myname ml_name spool_dir article_id db_base_dir
- reverse_order
- rewrite_header
- base_url msg_base_url
- );
-
- my %must = ('ml_name' => 1, 'spool_dir' => 1, 'db_base_dir' => 1);
-
- for my $key (@keys) {
- if (defined $args->{ $key }) {
- $config->{ $key } = $args->{ $key };
- }
- elsif (defined $must{ $key }) {
- croak("specify $key");
- }
-
- }
- my $ml_name = $config->{ ml_name };
-
- unless (defined $args->{ thread_id_syntax }) {
- $config->{ thread_id_syntax } = "$ml_name/\%d";
- }
-
- unless (defined $args->{ thread_subject_tag }) {
- my $id_syntax = $config->{ thread_id_syntax };
- $config->{ thread_subject_tag } = "[$id_syntax]";
- }
-
- # database directory used to store thread information et. al.
- use File::Spec;
- my $base_dir = $config->{ db_base_dir };
- $me->{ _db_base_dir } = $base_dir;
- $me->{ _index_db } = File::Spec->catfile($base_dir, "index");
- $me->{ _db_dir } = File::Spec->catfile($base_dir, $ml_name);
- $me->{ _fd } = $args->{ fd } || \*STDOUT;
- $me->{ _saved_args } = $args;
-
- if (defined $config->{ rewrite_header } && $config->{ rewrite_header }) {
- $me->{ _is_rewrite_header } = 1;
- eval q{ use Mail::ThreadTrack::HeaderRewrite; };
- croak($@) if $@;
- push(@ISA, 'Mail::ThreadTrack::HeaderRewrite');
- }
-
- # XXX-TODO: $article_summary_lines hard-coded.
- # ::Print parameters
- $me->{ _article_summary_lines } = 5;
-
- # log function pointer
- if (defined $args->{ logfp }) {
- $me->{ _logfp } = $args->{ logfp };
- }
-
- # initialize directory
- _init_dir($me);
-
- return bless $me, $type;
-}
-
-
-# Descriptions: dummy
-# Arguments: OBJ($self) HASH_REF($args)
-# Side Effects: none
-# Return Value: none
-sub DESTROY {}
-
-
-# Descriptions: "mkdir -p" or "mkdirhier"
-# Arguments: STR($dir) STR($mode)
-# Side Effects: set $ErrorString
-# Return Value: 1 or UNDEF
-sub _mkdirhier
-{
- my ($dir, $mode) = @_;
-
- # XXX $mode (e.g. 0755) should be a numeric not a string
- eval q{
- use File::Path;
- mkpath($dir, 0, $dir_mode);
- };
-
- return ($@ ? undef : 1);
-}
-
-
-# Descriptions: create the directory taken from $self->{ _db_dir }.
-# Arguments: OBJ($self) HASH_REF($args)
-# Side Effects: create a "_db_dir" directory if needed
-# Return Value: 1 (success) or undef (fail)
-sub _init_dir
-{
- my ($self, $args) = @_;
-
- if (defined $self->{ _db_dir }) {
- my $db_dir = $self->{ _db_dir };
- unless (-d $db_dir) {
- _mkdirhier($db_dir) || do {
- croak("cannot make \$db_dir=$db_dir\n");
- };
- }
- }
- else {
- croak("no \$db_dir\n");
- }
-
- return 1;
-}
-
-
-=head2 increment_id(file)
-
-increment thread number which is taken up from C<file>
-and save the new number to C<file>.
-
-=cut
-
-
-# Descriptions: increment thread number $id holded in DB.
-# Arguments: OBJ($self) STR($seq_file)
-# Side Effects: increment id holded in $seq_file
-# Return Value: NUM
-sub increment_id
-{
- my ($self, $seq_file) = @_;
- my $seq = 0;
-
- # XXX-TODO: $seq_file is not used. fix this method.
-
- $self->db_open();
-
- # prepare hash table tied to db_dir/*db's
- # XXX-TODO: we prepare $self->db_base(); ?
- my $rh = $self->{ _hash_table };
-
- if (defined $rh->{ _info }->{ sequence }) {
- $rh->{ _info }->{ sequence }++;
- return $rh->{ _info }->{ sequence };
- }
- else {
- $seq = $rh->{ _info }->{ sequence } = 1;
- }
-
- $self->db_close();
-
- return $seq;
-}
-
-
-=head2 list_up_thread_id()
-
-return not closed ticket id(s) as ARRRAY_REF.
-
-=cut
-
-
-# Descriptions: return not closed ticket id(s) as ARRRAY_REF.
-# Arguments: OBJ($self)
-# Side Effects: none
-# Return Value: ARRAY_HASH
-sub list_up_thread_id
-{
- my ($self) = @_;
- my ($tid, $status);
- my $rh_status = $self->{ _hash_table }->{ _status };
- my $mode = 'default';
- my $stat = {};
- my @thread_id = ();
-
- TICEKT_LIST:
- while (($tid, $status) = each %$rh_status) {
- if ($status =~ /close/o) {
- $stat->{ 'closed' }++;
- }
- else {
- $stat->{ $status }++;
- }
-
- if ($mode eq 'default') {
- next TICEKT_LIST if $status =~ /close/o;
- }
-
- push(@thread_id, $tid);
- }
-
- # save statistics
- $self->{ _ticket_id_stat } = $stat;
-
- \@thread_id;
-}
-
-
-=head2 set_mode($mode)
-
-specify output format by $mode string.
-"text" and "html" are available.
-"text" by default.
-
-=head2 get_mode()
-
-get output format.
-
-=cut
-
-
-# Descriptions: set output format
-# Arguments: OBJ($self) STR($mode)
-# Side Effects: update info in object
-# Return Value: STR
-sub set_mode
-{
- my ($self, $mode) = @_;
- $self->{ _mode } = $mode || 'text';
-}
-
-
-# Descriptions: set output format
-# Arguments: OBJ($self)
-# Side Effects: update info in object
-# Return Value: STR
-sub get_mode
-{
- my ($self) = @_;
- return(defined $self->{ _mode } ? $self->{ _mode } : undef);
-}
-
-
-=head2 set_fd( $fd )
-
-=head2 get_fd()
-
-=cut
-
-
-# Descriptions: set output channel handle.
-# Arguments: OBJ($self) HADNLE($fd)
-# Side Effects: update info in object.
-# Return Value: HANDLE
-sub set_fd
-{
- my ($self, $fd) = @_;
- $self->{ _fd } = $fd;
-}
-
-
-# Descriptions: get output channel handle.
-# Arguments: OBJ($self)
-# Side Effects: update info in object.
-# Return Value: HANDLE
-sub get_fd
-{
- my ($self) = @_;
- return $self->{ _mode };
-}
-
-
-=head2 set_order( $order )
-
-set thread listing order where $order is 'normal' or 'reverse'.
-
-=cut
-
-
-# Descriptions: set thread listing order
-# Arguments: OBJ($self) STR($order)
-# Side Effects: update info in object.
-# Return Value: none
-sub set_order
-{
- my ($self, $order) = @_;
-
- if ((defined $order) && $order eq 'normal') {
- $self->{ _config }->{ reverse_order } = 0;
- }
- elsif ((defined $order) && $order eq 'reverse') {
- $self->{ _config }->{ reverse_order } = 1;
- }
- else {
- warn("set_order: unknown order $order");
- }
-}
-
-
-=head2 exist($thread_id)
-
-$thread_id exists or not in database?
-return 1 (exist) or 0.
-
-=cut
-
-
-# Descriptions: $thread_id exists or not in database?
-# Arguments: OBJ($self) STR($id)
-# Side Effects: none
-# Return Value: 1 or 0
-sub exist
-{
- my ($self, $id) = @_;
- my $r = 0;
-
- $self->db_open();
-
- my $rh = $self->{ _hash_table };
-
- if (defined $rh->{ _articles }) {
- my $a = $rh->{ _articles };
- $r = (defined $a->{ $id } ? 1 : 0);
- }
-
- $self->db_close();
-
- return $r;
-}
-
-
-=head2 close($thread_id)
-
-close specified $thread_id.
-
-=cut
-
-
-# Descriptions: close specified $thread_id.
-# Arguments: OBJ($self) STR($thread_id)
-# Side Effects: update status
-# Return Value: none
-sub close
-{
- my ($self, $thread_id) = @_;
-
- $self->db_open();
- $self->_set_status($thread_id, "close");
- $self->db_close();
-}
-
-
-=head2 set_status($args)
-
-set $status for $thread_id. It rewrites DB (file).
-C<$args>, HASH reference, must have two keys.
-
- $args = {
- thread_id => $thread_id,
- status => $status,
- }
-
-C<set_status()> calls db_open() an db_close() automatically within it.
-
-=cut
-
-
-# Descriptions: set status.
-# Arguments: OBJ($self) HASH_REF($args)
-# Side Effects: update status in db.
-# Return Value: none
-sub set_status
-{
- my ($self, $args) = @_;
- my $thread_id = $args->{ thread_id };
- my $status = $args->{ status };
-
- # XXX-TODO: validate input.
- $self->db_open();
- $self->_set_status($thread_id, $status);
- $self->db_close();
-}
-
-
-# Descriptions: set status.
-# Arguments: OBJ($self) STR($thread_id) STR($value)
-# Side Effects: update status in db.
-# Return Value: none
-sub _set_status
-{
- my ($self, $thread_id, $value) = @_;
- $self->{ _hash_table }->{ _status }->{ $thread_id } = $value;
-}
-
-
-=head2 add_filter( { key => value } )
-
-add filter rule to ignore in thread database.
-
- my $thread = new Mail::ThreadTrack;
- $thread->set_filter( { 'subject' => 'fml cvs weekly changes' } );
-
-=cut
-
-
-# Descriptions: add filter rule(s) to ignore in thread database.
-# Arguments: OBJ($self) HASH_REF($hash)
-# Side Effects: none
-# Return Value: none
-sub add_filter
-{
- my ($self, $hash) = @_;
-
- # update filter list
- my ($k, $v);
- while (($k, $v) = each %$hash) {
- $self->{ _filterlist }->{ $k } = $v;
- }
-}
-
-
-=head2 log( $str )
-
-log $str using the specified log function or into STDERR if logfp
-unspecified.
-
-=cut
-
-
-# Descriptions: log
-# Arguments: OBJ($self) STR($str)
-# Side Effects: none
-# Return Value: none
-sub log
-{
- my ($self, $str) = @_;
-
- if (defined $self->{ _logfp }) {
- my $fp = $self->{ _logfp };
- &$fp( $str );
- }
- else {
- print STDERR "Log> $str\n";
- }
-}
-
-
-=head2 filepath($args)
-
-return the article file path.
-
- $args = {
- base_dir => DIR,
- id => NUM,
- use_subdir => 1 or 0,
- };
-
-=cut
-
-
-# Descriptions: return the article file path.
-# Arguments: OBJ($self) HASH_REF($args)
-# Side Effects: none
-# Return Value: STR(file path)
-sub filepath
-{
- my ($self, $args) = @_;
-
- use Mail::Message::Spool;
- my $spool = new Mail::Message::Spool;
- my $file = $spool->filepath($args);
-
- return $file;
-}
-
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 AUTHOR
-
-Ken'ichi Fukamachi
-
-=head1 COPYRIGHT
-
-Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-
-All rights reserved. This program is free software; you can
-redistribute it and/or modify it under the same terms as Perl itself.
-
-=head1 HISTORY
-
-Mail::ThreadTrack first appeared in fml8 mailing list driver package.
-See C<http://www.fml.org/> for more details.
-
-=cut
-
-
-1;
diff --git a/fml/lib/Mail/ThreadTrack/Analyze.pm b/fml/lib/Mail/ThreadTrack/Analyze.pm
deleted file mode 100644
index 96b01a6b..00000000
--- a/fml/lib/Mail/ThreadTrack/Analyze.pm
+++ /dev/null
@@ -1,663 +0,0 @@
-#-*- perl -*-
-#
-# Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-# All rights reserved. This program is free software; you can
-# redistribute it and/or modify it under the same terms as Perl itself.
-#
-# $FML: Analyze.pm,v 1.32 2003/07/21 11:29:15 fukachan Exp $
-#
-
-package Mail::ThreadTrack::Analyze;
-use strict;
-use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
-use Carp;
-
-# XXX-TODO: we should remove not used function ?
-
-my $debug = 0;
-
-=head1 NAME
-
-Mail::ThreadTrack::Analyze - analyze mail thread relation
-
-=head1 SYNOPSIS
-
-See C<Mail::ThreadTrack> perl module for more detail.
-
-=head1 DESCRIPTION
-
-=head1 METHODS
-
-=head2 analyze($mesg)
-
-C<$mesg> is Mail::Message object.
-
-This is top level entrance for
-
-1) assign a new thread or extract the existing thread-id from the subject.
-
-2) update thread status if needed.
-
-3) update database.
-
-=cut
-
-
-# Descriptions: top level entrance
-# Arguments: OBJ($self) OBJ($msg)
-# $msg = "Mail::Messge object"
-# Side Effects: none
-# Return Value: none
-sub analyze
-{
- my ($self, $msg) = @_;
-
- $self->assign($msg);
- $self->rewrite_header($msg) if $self->{ _is_rewrite_header };
- $self->update_thread_status($msg);
- $self->update_db($msg);
-}
-
-
-=head2 assign($msg)
-
-analyze message given by $msg and assign thread id if needed.
-
-=cut
-
-
-# Descriptions: given string looks like subject or not
-# Arguments: STR($subject)
-# Side Effects: none
-# Return Value: 1 or 0
-sub _is_reply
-{
- my ($subject) = @_;
-
- use Mail::Message::Language::Japanese::Subject;
- return Mail::Message::Language::Japanese::Subject::is_reply($subject);
-}
-
-
-# Descriptions: assign a new thread id or
-# extract the existing thread-id from the subject
-# Arguments: OBJ($self) OBJ($msg)
-# $msg = Mail::Message object
-# Side Effects: a new thread_id may be assigned
-# Return Value: none
-sub assign
-{
- my ($self, $msg) = @_;
- my $header = $msg->whole_message_header();
- my $subject = $header->get('subject');
- my $is_reply = _is_reply($subject);
-
- # XXX-TODO: who validate $thread_id regexp
- # XXX-TODO: since $thread_id is given from outside.
- # 1. try to extract $thread_id from header
- my $thread_id = $self->_extract_thread_id_in_subject($header);
- unless ($thread_id) {
- # If we fail to pick up thread id from subject,
- # we try to speculate id from other fields in header.
- $thread_id = $self->_speculate_thread_id_from_header($header);
- if ($thread_id) {
- $is_reply = 1; # message already have thread_id, so replied one?
- $self->set_thread_id($thread_id);
- $self->log("speculated id=$thread_id");
- }
- else {
- $self->log("(debug) fail to spelucate thread_id") if $debug;
- }
- }
-
- # 2. check "X-Thread-Pragma:" field,
- # we ignore this mail if the pragma is specified as "ignore".
- if (defined $header->get('x-thread-pragma')) {
- my $pragma = $header->get('x-thread-pragma') || '';
- if ($pragma =~ /ignore/io) {
- $self->{ _pragma } = 'ignore';
- $self->_append_thread_status_info("ignored");
- return undef;
- }
- }
-
- # 3. if the header has some thread_id,
- # we do not rewrite the subject but save the extracted $thread_id.
- if ($is_reply && $thread_id) {
- $self->log("reply message with thread_id=$thread_id");
- $self->set_thread_id($thread_id);
- $self->set_thread_status('analyzed');
- $self->_append_thread_status_info('analyzed');
- }
- elsif ($thread_id) {
- $self->log("message with thread_id=$thread_id but not reply");
- $self->set_thread_id($thread_id);
- $self->_append_thread_status_info("found");
- }
- else {
- $self->log("message without thread_id") if $debug;
-
- my $id = $self->_assign_new_thread_id_number();
-
- # side effect:
- # define $self->{ _thread_subject_tag } and $self->{ _thread_id }
- my $thread_id = $self->_create_thread_id_strings($id);
- $self->set_thread_id($thread_id);
- $self->_append_thread_status_info("newly assigned");
- }
-}
-
-
-# Descriptions: assign new thread_id
-# Arguments: OBJ($self)
-# Side Effects: increment id
-# Return Value: NUM
-sub _assign_new_thread_id_number
-{
- my ($self) = @_;
- my $id = 0;
-
- # assign a new thread number for a new message
- if (1) {
- # unique but non sequential number
- $id = $self->{ _config }->{ article_id };
- }
- else {
- # incremental number
- $id = $self->increment_id();
- }
-
- $self->log("assign thread_id=$id") if $debug;
- return $id;
-}
-
-
-# Descriptions: update $self->{ _status_info }
-# Arguments: OBJ($self) STR($s)
-# Side Effects: update $self->{ _status_info }
-# Return Value: STR
-sub _append_thread_status_info
-{
- my ($self, $s) = @_;
- $self->{ _status_info } .= $self->{ _status_info } ? " -> ".$s : $s;
-}
-
-
-=head2 get_thread_status()
-
-get thread status.
-
-=head2 set_thread_status($status)
-
-set thread status.
-
-=cut
-
-
-# Descriptions: get thread status
-# Arguments: OBJ($self)
-# Side Effects: none
-# Return Value: STR
-sub get_thread_status
-{
- my ($self) = @_;
- return(defined $self->{ _status } ? $self->{ _status } : undef);
-}
-
-
-# Descriptions: set thread status
-# Arguments: OBJ($self) STR($thread_status)
-# Side Effects: none
-# Return Value: STR
-sub set_thread_status
-{
- my ($self, $thread_status) = @_;
- $self->{ _status } = $thread_status;
- return $thread_status;
-}
-
-
-=head2 update_thread_status($msg)
-
-ignore this procedure if "ignore" pragma is specified.
-
-update status to "close" if "close" pragma or "close" commmand in the
-message is found.
-
-=cut
-
-
-# Descriptions: update thread status
-# Arguments: OBJ($self) OBJ($msg)
-# Side Effects: update database
-# Return Value: none
-sub update_thread_status
-{
- my ($self, $msg) = @_;
- my $content = '';
- my $subject = '';
- my $pragma = '';
-
- if (defined $self->{ _pragma }) {
- return if $self->{ _pragma } eq 'ignore';
- }
-
- unless (ref($msg) eq 'Mail::Message') {
- croak("invalid object");
- }
-
- # filter messages of some class
- if (defined $self->{ _filterlist }) {
- if ($self->_is_ignore($msg)) {
- $self->log("this thread should be ignored");
- $pragma = "close";
- }
- }
-
- my $header = $msg->whole_message_header();
- my $textmsg = $msg->find_first_plaintext_message();
- $content = $textmsg->message_text() if defined $textmsg;
- $subject = $header->get('subject') || '';
- $pragma = $header->get('x-thread-pragma') || $pragma || '';
-
- if ($pragma =~ /close/ ||
- $content =~ /^\s*close/ ||
- $subject =~ /^\s*close/) {
- $self->set_thread_status("close");
- $self->_append_thread_status_info("closed");
- $self->log("thread is closed");
- }
- else {
- $self->log("thread status not changed");
- }
-}
-
-
-# Descriptions: check filter whether this $msg should be ignored or not.
-# Arguments: OBJ($self) OBJ($msg)
-# Side Effects: none
-# Return Value: 1 or 0
-sub _is_ignore
-{
- my ($self, $msg) = @_;
- my ($header, $textmsg, $content);
- my ($field, $rule);
- my $filterlist = $self->{ _filterlist };
-
- $header = $msg->whole_message_header();
- $textmsg = $msg->find_first_plaintext_message();
- $content = $textmsg->message_text() if defined $textmsg;
-
- # check header
- while (($field, $rule) = each %$filterlist) {
- if (defined $header->get($field)) {
- my $value = $header->get($field);
- if ($debug) {
- print STDERR "ignore $field: $value\n" if $value =~ /$rule/m;
- }
- return 1 if $value =~ /$rule/;
- }
- }
-
- return 0;
-}
-
-
-=head2 get_thread_id()
-
-get thread_id in object ($self->{ _thread_id }).
-
-=head2 set_thread_id($thread_id)
-
-set thread_id in object ($self->{ _thread_id }).
-
-=cut
-
-
-# Descriptions: get thread_id in object ($self->{ _thread_id }).
-# Arguments: OBJ($self)
-# Side Effects: none.
-# Return Value: STR or UNDEF
-sub get_thread_id
-{
- my ($self) = @_;
- return(defined $self->{ _thread_id } ? $self->{ _thread_id } : undef);
-}
-
-
-# Descriptions: set thread_id
-# Arguments: OBJ($self) STR($thread_id)
-# Side Effects: update $self->{ _thread_id }.
-# Return Value: STR
-sub set_thread_id
-{
- my ($self, $thread_id) = @_;
- $self->{ _thread_id } = $thread_id;
- return $thread_id;
-}
-
-
-# Descriptions: create regexp for a subject tag, for example
-# "[%s %05d]" => "\[\S+ \d+\]"
-# Arguments: STR($s)
-# XXX non OO type function
-# Side Effects: none
-# Return Value: STR(a regexp for the given tag)
-sub _regexp_compile
-{
- my ($s) = @_;
-
- $s = quotemeta( $s );
- $s =~ s@\\\%@\%@g;
- $s =~ s@\%s@\\S+@g;
- $s =~ s@\%d@\\d+@g;
- $s =~ s@\%0\d+d@\\d+@g;
- $s =~ s@\%\d+d@\\d+@g;
- $s =~ s@\%\-\d+d@\\d+@g;
-
- # quote for regexp substitute: [ something ] -> \[ something \]
- # $s =~ s/^(.)/quotemeta($1)/e;
- # $s =~ s/(.)$/quotemeta($1)/e;
-
- return $s;
-}
-
-
-# Descriptions: extract message-id list and return it.
-# Arguments: OBJ($header)
-# function not OO
-# Side Effects: none
-# Return Value: ARRAY_HASH
-sub _extract_message_id_references
-{
- my ($header) = @_;
- my (@addrs, @r, %uniq) = ();
-
- # XXX-TODO: Mail::Message should provide this function ?
-
- use Mail::Address;
-
- if (defined $header->get('in-reply-to')) {
- my $buf = $header->get('in-reply-to');
- push(@addrs, Mail::Address->parse($buf));
- }
-
- if (defined $header->get('references')) {
- my $buf = $header->get('references');
- push(@addrs, Mail::Address->parse($buf));
- }
-
- for my $addr (@addrs) {
- my $a = $addr->address;
- unless (defined $uniq{ $a } && $uniq{ $a }) {
- # RFC822 says msg-id = "<" addr-spec ">" ; Unique message id
- push(@r, "<".$addr->address.">");
- $uniq{ $a } = 1;
- }
- }
-
- return \@r;
-}
-
-
-# Descriptions: extract thread_id in Subject:
-# Arguments: OBJ($self) OBJ($header)
-# Side Effects: none
-# Return Value: STR or 0
-sub _extract_thread_id_in_subject
-{
- my ($self, $header) = @_;
- my $config = $self->{ _config };
- my $tag = $config->{ thread_subject_tag } || '';
- my $loctype = $config->{ thread_subject_tag_location } || 'appended';
- my $subject = $header->get('subject') || '';
- my $regexp = _regexp_compile($tag);
-
- # Subject: ... [thread_id]
- if (($loctype eq 'appended') && ($subject =~ /($regexp)\s*$/)) {
- my $id = $1;
- $id =~ s/^(\[|\(|\{)//;
- $id =~ s/(\]|\)|\})$//;
- return $id;
- }
- # XXX incomplete, we check subject after cutting off "Re:" et. al.
- # Subject: [thread_id] ...
- # Subject: Re: [thread_id] ...
- elsif (($loctype eq 'prepended') && ($subject =~ /^\s*($regexp)/)) {
- my $id = $1;
- $id =~ s/^(\[|\(|\{)//;
- $id =~ s/(\]|\)|\})$//;
- return $id;
- }
- else {
- $self->log("no thread id /$regexp/ in subject") if $debug;
- return 0;
- }
-}
-
-
-# Descriptions:
-# For example, consider a posting to both elena ML and
-# rudo (DM) from kenken.
-#
-# From: kenken
-# To: elena-ml
-# Cc: rudo
-#
-# The reply to this DM (direct message) from rudo is
-#
-# From: rudo
-# To: elena-ml
-#
-# This reply message has no thread_id since the
-# message from kenken to rudo comes directly from
-# kenken not through fml driver. In this case, we
-# try to speculdate the reply relation and the
-# thread_id of this thread by using _
-# speculate_thread_id_from_header().
-#
-# Arguments: OBJ($self) OBJ($header)
-# Side Effects: none
-# Return Value: STR(message id)
-sub _speculate_thread_id_from_header
-{
- my ($self, $header) = @_;
- my $midlist = _extract_message_id_references( $header );
- my $result = '';
-
- if (defined $midlist) {
- $self->db_open();
-
- # prepare hash table tied to db_dir/*db's
- my $rh = $self->{ _hash_table };
-
- MSGID_LIST:
- for my $mid (@$midlist) {
- $result = $rh->{ _message_id }->{ $mid };
- last MSGID_LIST if $result;
- }
-
- $self->db_close();
- }
-
- if ($debug) {
- $self->log("(debug) not speculated") unless $result;
- }
- $result;
-}
-
-
-# Descriptions: create thread_id
-# Arguments: OBJ($self) STR($id)
-# Side Effects: update $self->{ _thread_subject_tag }
-# Return Value: STR(thread_id string)
-sub _create_thread_id_strings
-{
- my ($self, $id) = @_;
- my $config = $self->{ _config };
-
- # thread_id appeared in subject: field
- my $subject_tag = $config->{ thread_subject_tag };
- $self->{ _thread_subject_tag } = sprintf($subject_tag, $id);
-
- # thread_id used as primary key
- my $id_syntax = $config->{ thread_id_syntax };
- return sprintf($id_syntax, $id);
-}
-
-
-=head2 update_db($msg)
-
-update database.
-
-=cut
-
-
-# Descriptions: top level dispatcher to drive database update
-# Arguments: OBJ($self) OBJ($msg)
-# Side Effects: update databases
-# Return Value: none
-sub update_db
-{
- my ($self, $msg) = @_;
- my $config = $self->{ _config };
- my $ml_name = $config->{ ml_name };
-
- if (defined $self->{ _pragma }) {
- return if $self->{ _pragma } eq 'ignore';
- }
-
- $self->db_open();
-
- # save $ticke_id et.al. in db_dir/$ml_name
- $self->_update_db($msg);
-
- $self->prepare_history_info($msg) if $self->{ _is_rewrite_header };
-
- # save cross reference pointers among $ml_name
- $self->_update_index_db();
-
- $self->db_close();
-}
-
-
-# Descriptions: speculate unixtime from header
-# Arguments: OBJ($msg)
-# Side Effects: none
-# Return Value: NUM(unix time)
-sub _speculate_time
-{
- my ($msg) = @_;
- my $header = $msg->whole_message_header;
-
- if (defined $header->get('date')) {
- use Mail::Message::Date;
- my $obj = new Mail::Message::Date;
- return $obj->date_to_unixtime($header->get('date'));
- }
- else {
- return time;
- }
-}
-
-
-# Descriptions: update database
-# Arguments: OBJ($self) OBJ($msg)
-# Side Effects: update database
-# Return Value: STR
-sub _update_db
-{
- my ($self, $msg) = @_;
- my $config = $self->{ _config };
- my $article_id = $config->{ article_id };
- my $thread_id = $self->get_thread_id();
-
- # 0. logging
- $self->log("article_id=$article_id thread_id=$thread_id") if $debug;
-
- # prepare hash table tied to db_dir/*db's
- my $rh = $self->{ _hash_table };
-
- # check
- if (defined $rh->{ _thread_id }->{ $article_id }) {
- print STDERR "_update_db.ignore id=$article_id\n" if $debug;
- return;
- }
-
- # 1.
- $rh->{ _thread_id }->{ $article_id } = $thread_id;
- $rh->{ _date }->{ $article_id } = _speculate_time($msg);
- $rh->{ _articles }->{ $thread_id } .= $article_id . " ";
-
- # 2. record the sender information
- my $header = $msg->whole_message_header;
- $rh->{ _sender }->{ $article_id } = $header->get('from');
-
- # 3. update status information
- if (defined $self->get_thread_status()) {
- my $status = $self->get_thread_status();
- $self->_set_status($thread_id, $status);
- }
- else {
- # set the default status value for the first time.
- unless (defined $rh->{ _status }->{ $thread_id }) {
- $self->_set_status($thread_id, 'open');
- }
- }
-
- # 4. save optional/additional information
- # message_id hash is { message_id => thread_id };
- # RFC822 says msg-id = "<" addr-spec ">" ; Unique message id
- my $mid = $header->get('message-id'); $mid =~ s/[\n\s]*$//;
- if ($mid eq "") {
- print STDERR "missing message-id $thread_id\n" if $debug;
- return;
- }
- $rh->{ _message_id }->{ $mid } = $thread_id;
-}
-
-
-# Descriptions: register myself to index_db for further reference
-# among mailing lists
-# Arguments: OBJ($self)
-# Side Effects: update object
-# Return Value: STR
-sub _update_index_db
-{
- my ($self) = @_;
- my $config = $self->{ _config };
- my $thread_id = $self->get_thread_id();
- my $rh = $self->{ _hash_table };
- my $ml_name = $config->{ ml_name };
-
- my $ref = $rh->{ _index }->{ $thread_id } || '';
- if ($ref !~ /^$ml_name|\s$ml_name\s|$ml_name$/) {
- $rh->{ _index }->{ $thread_id } .= $ml_name." ";
- }
-}
-
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 AUTHOR
-
-Ken'ichi Fukamachi
-
-=head1 COPYRIGHT
-
-Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-
-All rights reserved. This program is free software; you can
-redistribute it and/or modify it under the same terms as Perl itself.
-
-=head1 HISTORY
-
-Mail::ThreadTrack::Analyze first appeared in fml8 mailing list driver package.
-See C<http://www.fml.org/> for more details.
-
-=cut
-
-
-1;
diff --git a/fml/lib/Mail/ThreadTrack/DB.pm b/fml/lib/Mail/ThreadTrack/DB.pm
deleted file mode 100644
index a7831861..00000000
--- a/fml/lib/Mail/ThreadTrack/DB.pm
+++ /dev/null
@@ -1,321 +0,0 @@
-#-*- perl -*-
-#
-# Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-# All rights reserved. This program is free software; you can
-# redistribute it and/or modify it under the same terms as Perl itself.
-#
-# $FML: DB.pm,v 1.33 2003/08/23 04:35:49 fukachan Exp $
-#
-
-package Mail::ThreadTrack::DB;
-use strict;
-use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
-use Carp;
-
-my $debug = 0;
-
-=head1 NAME
-
-Mail::ThreadTrack::DB - database access.
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-=head1 METHODS
-
-=cut
-
-=head2 db_open()
-
-open database.
-It uses tie() to bind a hash to a DB file.
-Our thread model uses several DB files such as
-C<%thread_id>,
-C<%date>,
-C<%status>,
-C<%sender>,
-C<%articles>,
-C<%message_id>
-and
-C<%index>.
-
-=head2 db_close()
-
-untie() the corresponding hashes opened by C<db_open()>.
-
-=cut
-
-my @kind_of_databases = qw(thread_id date status sender articles
- message_id);
-
-
-# Descriptions: open database by tie()
-# Arguments: OBJ($self)
-# Side Effects: $self->{ _hash_table } initialized.
-# Return Value: none
-sub db_open
-{
- my ($self) = @_;
- my $db_type = $self->{ config }->{ db_type } || 'AnyDBM_File';
- my $db_dir = $self->{ _db_dir };
- my $file_mode = $self->{ _file_mode } || 0644;
-
- use File::Spec;
- eval qq{ use $db_type; use Fcntl;};
- unless ($@) {
- for my $db (@kind_of_databases) {
- my $file = File::Spec->catfile($db_dir, $db);
- my $str = qq{
- my \%$db = ();
- tie \%$db, \$db_type, \$file, O_RDWR|O_CREAT, $file_mode;
- \$self->{ _hash_table }->{ _$db } = \\\%$db;
- };
- eval $str;
- croak($@) if $@;
- }
-
- my %index = ();
- my $index_file = $self->{ _index_db };
- eval q{
- tie %index, $db_type, $index_file, O_RDWR|O_CREAT, $file_mode;
- $self->{ _hash_table }->{ _index } = \%index;
- };
- croak($@) if $@;
- }
- else {
- croak("failed to \"use $db_type\"");
- }
-
- 1;
-}
-
-
-# Descriptions: clear database
-# Arguments: OBJ($self)
-# Side Effects: update database
-# Return Value: none
-sub db_clear
-{
- my ($self) = @_;
- my $db_dir = '';
-
- $db_dir = $self->{ _db_dir };
- _db_clear($db_dir) if -d $db_dir;
-
- $db_dir = $self->{ _db_base_dir };
- _db_clear($db_dir) if -d $db_dir;
-}
-
-
-# Descriptions: clear database
-# Arguments: STR($db_dir)
-# Side Effects: clear database, remove file if needed
-# Return Value: none
-sub _db_clear
-{
- my ($db_dir) = @_;
-
- eval q{
- use DirHandle;
- use File::Spec;
- my $dh = new DirHandle $db_dir;
-
- if (defined $dh) {
- my $f = '';
- while (defined($f = $dh->read)) {
- next if $f =~ /^\./;
- my $file = File::Spec->catfile($db_dir, $f);
- if (-f $file) {
- unlink $file;
- print STDERR "removed $file\n" unless -f $file;
- }
- }
- $dh->close;
- }
- };
- croak($@) if $@;
-}
-
-
-# Descriptions: close database by untie()
-# Arguments: OBJ($self)
-# Side Effects: none
-# Return Value: none
-sub db_close
-{
- my ($self) = @_;
-
- for my $db (@kind_of_databases) {
- my $str = qq{
- my \$${db} = \$self->{ _hash_table }->{ _$db };
- untie \%\$${db};
- };
- eval $str;
- croak($@) if $@;
- }
-
- my $index = $self->{ _hash_table }->{ _index };
- untie %$index;
-}
-
-
-=head2 db_mkdb($min, $max)
-
-remake database.
-
-=cut
-
-
-# Descriptions: remake database for messages from $min_id to $max_id
-# Arguments: OBJ($self) NUM($min_id) NUM($max_id)
-# Side Effects: remake database
-# Return Value: none
-sub db_mkdb
-{
- my ($self, $min_id, $max_id) = @_;
- my $config = $self->{ _config };
- my $spool_dir = $config->{ spool_dir };
- my $saved_args = $self->{ _saved_args }; # original $args
-
- return undef unless (defined $min_id && defined $max_id);
-
- use Mail::Message;
- use File::Spec;
-
- my $count = 0;
- my ($fh, $file, $msg);
- print STDERR "db_mkdb: $min_id -> $max_id\n" if $debug;
-
- ID:
- for my $id ( $min_id .. $max_id ) {
- print STDERR "." if $count++ % 10 == 0;
- print STDERR "process $id\n" if $debug;
-
- # XXX-TODO: this code is workaround, we should create more clever way.
- # XXX-TODO: overwrite (tricky)
- $self->{ _config }->{ article_id } = $id;
-
- # parse article and analyze it.
- $file = $self->filepath({
- base_dir => $spool_dir,
- id => $id,
- });
-
- $fh = new FileHandle $file;
- if (defined $fh) {
- my $msg = Mail::Message->parse({ fd => $fh });
- $self->analyze($msg);
-
- # XXX-TODO: workaround, we should create more clever way.
- # XXX-TODO: remove current status (tricky ;)
- delete $self->{ _status };
- }
- }
- print STDERR "\n" if $count > 0;
-}
-
-
-=head2 db_dump([$type])
-
-dump hash as text.
-dump status database if $type is not specified.
-
-=cut
-
-
-# Descriptions: dump data for database $type
-# Arguments: OBJ($self) STR($type)
-# Side Effects: none
-# Return Value: none
-sub db_dump
-{
- my ($self, $type) = @_;
- my $db_type = "_" . ( defined $type ? $type : 'status' );
- my $rh = $self->{ _hash_table }->{ $db_type };
-
- my ($k, $v);
- while (($k, $v) = each %$rh) {
- printf "%-20s %s\n", $k, $v;
- }
-}
-
-
-=head2 db_hash( $type )
-
-return HASH REFERENCE for specified database $type.
-
-=cut
-
-
-# Descriptions: get HASH REFERENCE for specified $type.
-# Arguments: OBJ($self) STR($db_type)
-# Side Effects: none
-# Return Value: HASH_REF or UNDEF
-sub db_hash
-{
- my ($self, $db_type) = @_;
- my $type = "_" . $db_type;
-
- if (defined $self->{ _hash_table }->{ $type }) {
- return $self->{ _hash_table }->{ $type };
- }
- else {
- return undef;
- }
-}
-
-
-=head2 db_last_modified()
-
-return the last modified time of our dateabase as unix time.
-This time is the latest modified time among all database files.
-
-=cut
-
-
-# Descriptions: return the last modified time (unix time) of database
-# Arguments: OBJ($self) STR($db_type)
-# Side Effects: none
-# Return Value: STR or UNDEF
-sub db_last_modified
-{
- my ($self, $db_type) = @_;
- my $db_dir = $self->{ _db_dir };
- my $last_modified = 0;
-
- # XXX-TODO: we supporse Berkeley DB. fix it.
- use File::Spec;
- my $file = File::Spec->catfile($db_dir, "date.db");
- if (-f $file) {
- $last_modified = (stat($file))[8];
- }
-
- return $last_modified;
-}
-
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 AUTHOR
-
-Ken'ichi Fukamachi
-
-=head1 COPYRIGHT
-
-Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-
-All rights reserved. This program is free software; you can
-redistribute it and/or modify it under the same terms as Perl itself.
-
-=head1 HISTORY
-
-Mail::ThreadTrack::DB first appeared in fml8 mailing list driver package.
-See C<http://www.fml.org/> for more details.
-
-=cut
-
-
-1;
diff --git a/fml/lib/Mail/ThreadTrack/HeaderRewrite.pm b/fml/lib/Mail/ThreadTrack/HeaderRewrite.pm
deleted file mode 100644
index 5b47445c..00000000
--- a/fml/lib/Mail/ThreadTrack/HeaderRewrite.pm
+++ /dev/null
@@ -1,133 +0,0 @@
-#-*- perl -*-
-#
-# Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-# All rights reserved. This program is free software; you can
-# redistribute it and/or modify it under the same terms as Perl itself.
-#
-# $FML: HeaderRewrite.pm,v 1.14 2003/08/23 04:35:49 fukachan Exp $
-#
-
-package Mail::ThreadTrack::HeaderRewrite;
-use strict;
-use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
-use Carp;
-
-=head1 NAME
-
-Mail::ThreadTrack::HeaderRewrite - header manipulation
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-=head1 METHODS
-
-=head2 rewrite_header($msg)
-
-C<$msg> is Mail::Message object.
-
-=cut
-
-
-# Descriptions: add thread track info into $msg where
-# $msg is Mail::Message object.
-# Arguments: OBJ($self) OBJ($msg)
-# Side Effects: modify $msg header
-# Return Value: none
-sub rewrite_header
-{
- my ($self, $msg) = @_;
- my $config = $self->{ _config };
- my $loctype = $config->{ thread_subject_tag_location } || 'appended';
- my $header = $msg->whole_message_header();
- my $tag = $self->{ _thread_subject_tag } || '';
-
- # append the thread tag to the subject
- if (defined $header->get('subject')) {
- my $subject = $header->get('subject');
-
- if ($loctype eq 'appended' && $tag) {
- $header->replace('subject', $subject ." ". $tag);
- }
- elsif ($loctype eq 'prepended' && $tag) {
- $header->replace('subject', $tag ." ". $subject);
- }
- else {
- $self->log("unknown thread_subject_tag_location type");
- }
-
- if (defined $self->{ _status_info }) {
- $header->add('X-Thread-Status', $self->{ _status_info });
- }
-
- if (defined $self->{ _thread_id }) {
- $header->add('X-Thread-ID', $self->{ _thread_id });
- }
-
- if (defined $self->{ _status_history }) {
- $header->add('X-Thread-History', $self->{ _status_history });
- }
- }
-}
-
-
-# Descriptions: prepare history infomation for further header rewriting.
-# Arguments: OBJ($self) OBJ($msg)
-# Side Effects: update $self->{ _status_history }
-# Return Value: none
-sub prepare_history_info
-{
- my ($self, $msg) = @_;
- my $thread_id = $self->get_thread_id();
-
- # prepare hash table tied to db_dir/*db's
- my $rh = $self->{ _hash_table };
-
- if (defined $rh->{ _articles }->{ $thread_id }) {
- my $buf = '';
- my (@aid) = split(/\s+/, $rh->{ _articles }->{ $thread_id });
- my $sender = $rh->{ _sender }->{ $aid[0] };
- my $when = $rh->{ _date }->{ $aid[0] };
-
- # clean up
- $sender =~ s/[\s\n]*$//;
- $when =~ s/[\s\n]*$//;
-
- use Mail::Message::Date;
- $when = Mail::Message::Date->new($when)->mail_header_style();
-
- # XXX-TODO: validate $aid[0], $sender, $when, @aid.
- $buf .= "\t\n";
- $buf .= "\tthis thread is opended at article $aid[0]\n";
- $buf .= "\tby $sender\n";
- $buf .= "\ton $when\n";
- $buf .= "\tarticle references: @aid\n";
- $self->{ _status_history } = $buf;
- }
-}
-
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 AUTHOR
-
-Ken'ichi Fukamachi
-
-=head1 COPYRIGHT
-
-Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-
-All rights reserved. This program is free software; you can
-redistribute it and/or modify it under the same terms as Perl itself.
-
-=head1 HISTORY
-
-Mail::ThreadTrack::HeaderRewrite first appeared in fml8 mailing list driver package.
-See C<http://www.fml.org/> for more details.
-
-=cut
-
-
-1;
diff --git a/fml/lib/Mail/ThreadTrack/Print.pm b/fml/lib/Mail/ThreadTrack/Print.pm
deleted file mode 100644
index c8b08bfc..00000000
--- a/fml/lib/Mail/ThreadTrack/Print.pm
+++ /dev/null
@@ -1,419 +0,0 @@
-#-*- perl -*-
-#
-# Copyright (C) 2001,2002,2004 Ken'ichi Fukamachi
-# All rights reserved. This program is free software; you can
-# redistribute it and/or modify it under the same terms as Perl itself.
-#
-# $FML: Print.pm,v 1.27 2002/12/22 03:21:33 fukachan Exp $
-#
-
-package Mail::ThreadTrack::Print;
-use strict;
-use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
-use Carp;
-use Mail::ThreadTrack::Print::Utils qw(decode_mime_string STR2EUC);
-
-=head1 NAME
-
-Mail::ThreadTrack::Print - dispatcher to print out thread
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-=head1 METHODS
-
-=head2 list([ @opts ])
-
-show todo list without article summary.
-
-=cut
-
-
-# Descriptions: show todo list without article summary.
-# Arguments: OBJ($self) VARARGS(@opts)
-# Side Effects: none
-# Return Value: none
-sub list
-{
- my ($self, @opts) = @_;
-
- $self->_load_library();
- $self->db_open();
- $self->_do_list(@opts);
- $self->db_close();
-}
-
-
-=head2 summary([ @opts ])
-
-show the thread summary, which is todo list C<with> article summary.
-
-Each row that C<show_summary()> returns has a set of
-C<date>, C<age>, C<status>, C<thread-id> and
-C<articles>, which is a list of articles with the thread-id.
-
-list() shows entries by the thread_id order. For example,
-
- date age status thread id articles
- ------------------------------------------------------------
- 2001/02/07 3.6 going elena_#00000450 807 808 809
- 2001/02/07 3.1 open elena_#00000451 810
- 2001/02/07 3.0 open elena_#00000452 812
- 2001/02/07 3.0 open elena_#00000453 813
- 2001/02/07 3.0 going elena_#00000454 814 815
- 2001/02/10 0.1 open elena_#00000456 821
-
-summary() shows the todo list above and article summaries.
-
-=cut
-
-
-# Descriptions: show todo list with article summary.
-# Arguments: OBJ($self) VARARGS(@opts)
-# Side Effects: none
-# Return Value: none
-sub summary
-{
- my ($self, @opts) = @_;
-
- $self->_load_library();
- $self->db_open();
- $self->_do_summary(@opts);
- $self->db_close();
-}
-
-
-=head2 review([ @opts ])
-
-show a chain of a few lines summary for articles in each thread.
-This summary is a collection of short summary of articles in one thread.
-
-=cut
-
-
-# Descriptions: show a chain of summaries for each thread.
-# Arguments: OBJ($self) VARARGS(@opts)
-# Side Effects: none
-# Return Value: none
-sub review
-{
- my ($self, @opts) = @_;
-
- $self->_load_library();
- $self->db_open();
- $self->_do_review(@opts);
- $self->db_close();
-}
-
-
-
-# Descriptions: load subclasses, change @INC.
-# Arguments: OBJ($self)
-# Side Effects: @INC modified
-# Return Value: none
-sub _load_library
-{
- my ($self) = @_;
- my $mode = $self->get_mode || 'text';
-
- require Mail::ThreadTrack::Print::Message;
- require Mail::ThreadTrack::Print::Sort;
- my @list =
- qw(Mail::ThreadTrack::Print::Message Mail::ThreadTrack::Print::Sort);
-
- if ($mode eq 'text') {
- require Mail::ThreadTrack::Print::Text;
- push(@list, 'Mail::ThreadTrack::Print::Text');
- }
- elsif ($mode eq 'html') {
- require Mail::ThreadTrack::Print::HTML;
- push(@list, 'Mail::ThreadTrack::Print::HTML');
- }
-
- unshift(@ISA, @list);
-}
-
-
-#
-# SUMMARY MODE
-#
-
-
-# Descriptions: dispatcher to show todo list with article summary.
-# Arguments: OBJ($self)
-# Side Effects: none
-# Return Value: none
-sub _do_summary
-{
- my ($self) = @_;
- $self->__do_summary( { mode => 'summary' });
-}
-
-
-# Descriptions: dispatcher to show todo list without article summary.
-# Arguments: OBJ($self)
-# Side Effects: none
-# Return Value: none
-sub _do_list
-{
- my ($self) = @_;
- $self->__do_summary( { mode => 'list' });
-}
-
-
-# Descriptions: get thread id list with status != 'close' and
-# show summary for the list if needed.
-# Arguments: OBJ($thread) HASH_REF($option)
-# Side Effects: none
-# Return Value: none
-sub __do_summary
-{
- my ($thread, $option) = @_;
- my $mode = $thread->get_mode || 'text';
- my $config = $thread->{ _config };
-
- # rh: thread id list picked from status.db
- my $thread_id_list = $thread->list_up_thread_id();
-
- # 1. sort the thread output order by cost
- # 2. print the thread brief summary in that order.
- # 3. show short summary for each message if needed (mode dependent)
- if (@$thread_id_list) {
- # XXX-TODO: $thread->sort() method should accept the order ?
- $thread->sort_thread_id($thread_id_list);
-
- # reverse order (first thread is the latest one) if reverse mode
- if ($config->{ reverse_order }) {
- @$thread_id_list = reverse @$thread_id_list;
- }
-
- # XXX thread summary == todo list
- $thread->_print_thread_summary($thread_id_list);
-
- # XXX message summary == brief summary of articles.
- if ($option->{ mode } eq 'summary') {
- $thread->_print_message_summary($thread_id_list);
- }
- }
-}
-
-
-# Descriptions: show thread summary (without article summary).
-# Arguments: OBJ($self) ARRAY_REF($thread_id_list)
-# Side Effects: none
-# Return Value: none
-sub _print_thread_summary
-{
- my ($self, $thread_id_list) = @_;
- my $mode = $self->get_mode || 'text';
- my $db = $self->{ _hash_table };
-
- # guide of presentation
- $self->__start_thread_summary(); # XXX dynamic binding
-
- # show brief summary along thread_id list
- my ($thread_id, @article_id, $article_id, $date, $age, $status) = ();
- my $date_h = new Mail::Message::Date;
- for $thread_id (@$thread_id_list) {
- next unless defined $db->{ _articles }->{ $thread_id };
-
- # get the first $article_id from the article_id list
- (@article_id) = split(/\s+/, $db->{ _articles }->{ $thread_id });
- $article_id = $article_id[0];
-
- # format $date for the $article_id
- $date = $date_h->YYYYxMMxDD( $db->{ _date }->{ $article_id } , '/');
- $age = $self->{ _age }->{ $thread_id };
- $status = $db->{ _status }->{ $thread_id };
-
- # XXX-TODO: who care for output mode ? (e.g. against CSS).
- $self->__print_thread_summary( {
- date => $date,
- age => $age,
- status => $status,
- thread_id => $thread_id,
- articles => $db->{ _articles }->{ $thread_id },
- }); # XXX dynamic binding
- }
-
- $self->__end_thread_summary(); # XXX dynamic binding
-}
-
-
-# Descriptions: show the first few lines of the first message in the thread
-# Arguments: OBJ($self) STR($thread_id)
-# Side Effects: none
-# Return Value: none
-sub _print_message_summary
-{
- my ($self, $thread_id) = @_;
- $self->__print_message_summary($thread_id);
-}
-
-
-#
-# REVIEW MODE
-#
-
-# Descriptions: show brief summary chain of messages in the thread.
-# Arguments: OBJ($self) STR($str) NUM($min) NUM($max)
-# Side Effects: none
-# Return Value: none
-sub _do_review
-{
- my ($self, $str, $min, $max) = @_;
- my $config = $self->{ _config };
- my $spool_dir = $config->{ spool_dir };
- my $fd = $self->{ _fd } || \*STDOUT;
- my $db = $self->{ _hash_table };
- my %uniq = ();
- my $is_first = 0;
-
- # translate the given parameter (MH style)
- # get ARRAY_REF of specified range
- use Mail::Message::MH;
- my $range = Mail::Message::MH->expand($str, $min, $max);
-
- # reverse order (first thread is the latest one) if reverse mode
- if ($config->{ reverse_order }) { @$range = reverse @$range;}
-
- ID_LIST:
- for my $id (@$range) {
- next ID_LIST unless defined $id;
-
- if ($id =~ /^\d+$/) {
- # create thread identifier string: e.g. 100 -> elena/100
- my $tid = $self->_create_thread_id_strings($id);
-
- # check thread id $tid exists really ?
- if (defined $db->{ _articles }->{ $tid }) {
- # XXX-TODO: validate $tid.
- printf $fd "\n>Thread-Id: %-10s %s\n", $tid;
-
- # different treatment for the fisrt article in this thread
- $is_first = 1;
-
- # show all articles in this thread
- ARTICLE:
- for my $aid (split(/\s+/, $db->{ _articles }->{ $tid })) {
- # ensure uniquness
- next ARTICLE if $uniq{ $aid };
- $uniq{ $aid } = 1;
-
- # show header only for the first message in this thread
- if ($is_first) {
- undef $self->{ _no_header_summary };
- $is_first = 0;
- }
- else {
- $self->{ _no_header_summary } = 1;
- }
-
- my $file = $self->filepath({
- base_dir => $spool_dir,
- id => $aid,
- });
- if (-f $file) {
- $self->print( $self->message_summary($file) );
- print $fd "\n";
- }
- }
- }
- }
- }
-}
-
-
-=head2 show($tid)
-
-show all articles in specified thread.
-
-=cut
-
-
-# Descriptions: show all articles in specified thread.
-# Arguments: OBJ($self) STR($tid)
-# Side Effects: none
-# Return Value: none
-sub show
-{
- my ($self, $tid) = @_;
-
- $self->_load_library();
- $self->db_open();
- $self->show_articles_in_thread($tid);
- $self->db_close();
-}
-
-
-=head2 print(str)
-
-print str with special effect e.g. quoting if needed.
-The function depends the mode, 'text' or 'html'.
-
-=cut
-
-
-# Descriptions: wrapper of print()
-# Arguments: OBJ($self) STR($str)
-# Side Effects: quote if needed
-# Return Value: none
-sub print
-{
- my ($self, $str) = @_;
- my $mode = $self->get_mode || 'text';
- my $fd = $self->{ _fd } || \*STDOUT;
-
- if ($mode eq 'text') {
- print $fd $str;
- }
- elsif ($mode eq 'html') {
- $str = &_quote($str);
- $str =~ s/\n/<BR>\n/g;
- print $fd $str;
- }
-}
-
-
-# Descriptions: quote for html metachars
-# Arguments: STR($str)
-# Side Effects: none
-# Return Value: STR
-sub _quote
-{
- my ($str) = @_;
-
- $str =~ s/&/&amp;/g;
- $str =~ s/</&lt;/g;
- $str =~ s/>/&gt;/g;
- $str =~ s/\"/&quot;/g;
-
- return $str;
-}
-
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 AUTHOR
-
-Ken'ichi Fukamachi
-
-=head1 COPYRIGHT
-
-Copyright (C) 2001,2002,2004 Ken'ichi Fukamachi
-
-All rights reserved. This program is free software; you can
-redistribute it and/or modify it under the same terms as Perl itself.
-
-=head1 HISTORY
-
-Mail::ThreadTrack::Print first appeared in fml8 mailing list driver package.
-See C<http://www.fml.org/> for more details.
-
-=cut
-
-
-1;
diff --git a/fml/lib/Mail/ThreadTrack/Print/HTML.pm b/fml/lib/Mail/ThreadTrack/Print/HTML.pm
deleted file mode 100644
index 220c6e09..00000000
--- a/fml/lib/Mail/ThreadTrack/Print/HTML.pm
+++ /dev/null
@@ -1,291 +0,0 @@
-#-*- perl -*-
-#
-# Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-# All rights reserved. This program is free software; you can
-# redistribute it and/or modify it under the same terms as Perl itself.
-#
-# $FML: HTML.pm,v 1.17 2003/02/11 11:22:56 fukachan Exp $
-#
-
-package Mail::ThreadTrack::Print::HTML;
-
-use strict;
-use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
-use Carp;
-
-
-=head1 NAME
-
-Mail::ThreadTrack::Print::HTML - print thread summary as HTML
-
-=head1 SYNOPSIS
-
-See C<Mail::ThreadTrack::Print> for usage of this subclass.
-
-=head1 DESCRIPTION
-
-See C<Mail::ThreadTrack::Print> for usage of this subclass.
-
-=head1 METHODS
-
-=head2 show_articles_in_thread(thread_id)
-
-show articles as HTML in this thread.
-
-=cut
-
-
-use CGI qw/:standard/;
-use Mail::ThreadTrack::Print::Utils qw(decode_mime_string STR2EUC);
-
-
-# Descriptions: show articles as HTML in this thread
-# Arguments: OBJ($self) STR($thread_id)
-# Side Effects: none
-# Return Value: none
-sub show_articles_in_thread
-{
- my ($self, $thread_id) = @_;
- my $mode = $self->get_mode || 'text';
- my $config = $self->{ _config };
- my $spool_dir = $config->{ spool_dir };
-
- my $articles = $self->{ _hash_table }->{ _articles }->{ $thread_id };
-
- # XXX-TODO: who validates $thread_id ?
- print "<B>";
- print "show contents related with thread_id=$thread_id\n";
- print "</B>";
- print "<HR>";
- print "<PRE>\n";
-
- if (defined($articles) && defined($spool_dir) && -d $spool_dir) {
- use FileHandle;
-
- my $s = '';
- for my $article (split(/\s+/, $articles)) {
- my $file = $self->filepath({
- base_dir => $spool_dir,
- id => $article,
- });
-
- # XXX-TODO: care for non Japanese char(s).
- # XXX-TODO: to avoid CSS bug, convert all special char(s).
- # XXX-TODO: create method safe_html_string() in Mail::Message ?
- if (-f $file) {
- my $fh = new FileHandle $file;
-
- if (defined $fh) {
- my $buf;
-
- while (defined($buf = $fh->getline())) {
- # ignore header part.
- next if 1 .. $buf =~ /^$/o;
-
- $s = STR2EUC($buf);
- $s =~ s/&/&amp;/g;
- $s =~ s/</&lt;/g;
- $s =~ s/>/&gt;/g;
- $s =~ s/\"/&quot;/g;
- print $s;
- }
- $fh->close;
- }
- }
- }
- }
-
- print "</PRE>";
-}
-
-
-# Descriptions: show guide
-# Arguments: OBJ($self) HASH_REF($args)
-# Side Effects: none
-# Return Value: none
-sub __start_thread_summary
-{
- my ($self, $args) = @_;
- my $config = $self->{ _config };
- my $ml_name = $config->{ ml_name };
- my $fd = $self->{ _fd } || \*STDOUT;
- my $action = $curproc->safe_cgi_action_name();
- my $target = '_top';
-
- # statistics
- if (defined $self->{ _ticket_id_stat }) {
- my $stat = $self->{ _ticket_id_stat };
- for my $key ('open', 'analyzed', 'closed') {
- print $fd "$key: ";
- print $fd defined $stat->{ $key } ? $stat->{ $key } : 0;
- print $fd ", ";
- }
- print $fd br, "\n";
- }
-
- # XXX-TODO: validate $action ?
- print $fd start_form(-action=>$action, -target=>$target);
- print $fd submit(-name => 'submit');
- print $fd reset(-name => 'reset');
- print $fd "\n";
-
- # XXX-TODO: validate $ml_name ?
- print $fd hidden(-name => 'ml_name',
- -default => [ $ml_name ],
- ), "\n";
-
- param('action', 'change_status'); # we need to override
- print $fd hidden(-name => 'action',
- -default => [ 'change_status ' ],
- ), "\n";
-
- print $fd "<TABLE BORDER=4>\n";
- print $fd "<TD>id\n";
- print $fd "<TD>change\n";
- print $fd "<TD>summary\n";
- print $fd "<TD>age\n";
- print $fd "<TD>status\n";
-}
-
-
-# Descriptions: finalize thread list.
-# close TABLE tag.
-# Arguments: OBJ($self) HASH_REF($args)
-# Side Effects: none
-# Return Value: none
-sub __end_thread_summary
-{
- my ($self, $args) = @_;
- my $fd = $self->{ _fd } || \*STDOUT;
-
- print $fd "</TABLE>\n";
-
- print submit(-name => 'submit');
- print reset(-name => 'reset');
- print $fd end_form;
-}
-
-
-# Descriptions: This shows summary on C<$thread_id> in HTML language.
-# It is used in C<FML::CGI::ThreadSystem>.
-# Arguments: OBJ($self) HASH_REF($optargs)
-# Side Effects: none
-# Return Value: none
-sub __print_thread_summary
-{
- my ($self, $optargs) = @_;
- my $config = $self->{ _config };
- my $ml_name = $config->{ ml_name };
- my $spool_dir = $config->{ spool_dir };
- my $action = $curproc->safe_cgi_action_name();
- my $target = $config->{ thread_cgi_target_window } || '_top';
-
- my $date = $optargs->{ date };
- my $age = $optargs->{ age };
- my $status = $optargs->{ status };
- my $tid = $optargs->{ thread_id };
- my $articles = $optargs->{ articles };
- my $aid = (split(/\s+/, $articles))[0];
-
- # do nothing if the $thread_id is unknown.
- return unless $tid;
-
- # XXX-TODO: validate $action, $ml_name, $aid ...
- # <FORM ACTION=> ..>
- my $xtid = CGI::escape($tid);
- $action = "${action}?ml_name=${ml_name}&article_id=$aid";
-
- $self->{ _table_count } = 1 unless defined $self->{ _table_count };
- if (($self->{ _table_count }++ % 5) == 0) {
- print "<TR>\n<TD>\n";
- print submit(-name => 'submit');
- print reset(-name => 'reset');
- }
-
- print "<TR>\n";
-
- # XXX-TODO: validate $msg_base_url ?
- # show articles in this thread id
- print "<TD>";
- if (defined $config->{ msg_base_url }) {
- my $msg_base_url = $config->{ msg_base_url };
- my $url = "$msg_base_url/msg$aid.html";
- print "<A HREF=\"$url\" TARGET=\"article\">\n";
- print $tid;
- print "\n</A>\n";
- }
- else {
- # XXX-TODO: validate $action ?
- print "<A HREF=\"$action&action=show\" TARGET=\"article\">\n";
- print $tid;
- print "\n</A>\n";
- }
-
- # action
- print "<TD>";
- my $name = "change_status.$tid";
- my $values = ["open", "analyzed", "closed"];
- my $default = $status;
- print radio_group(-name => $name,
- -values => $values,
- -default => $default,
- -linebreak => 'true',
- );
-
- # message (article) brief summary
- print "<TD>";
- if (defined $articles) {
- $aid = (split(/\s+/, $articles))[0];
- my $f = $self->filepath({
- base_dir => $spool_dir,
- id => $aid,
- });
- if (-f $f) {
- # XXX-TODO: care for non Japanese.
- my $buf = $self->message_summary($f);
- $self->print( STR2EUC($buf) );
- }
- }
-
- # addional information: age, status
- print "<TD>$age\n";
- print "<TD>$status\n";
-
- print "\n\n";
-}
-
-
-# Descriptions: dummy, defined for symmetry
-# Arguments: none
-# Side Effects: none
-# Return Value: none
-sub __print_message_summary
-{
- ;
-}
-
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 AUTHOR
-
-Ken'ichi Fukamachi
-
-=head1 COPYRIGHT
-
-Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-
-All rights reserved. This program is free software; you can
-redistribute it and/or modify it under the same terms as Perl itself.
-
-=head1 HISTORY
-
-Mail::ThreadTrack::Print::HTML first appeared in fml8 mailing list driver package.
-See C<http://www.fml.org/> for more details.
-
-=cut
-
-
-1;
diff --git a/fml/lib/Mail/ThreadTrack/Print/Message.pm b/fml/lib/Mail/ThreadTrack/Print/Message.pm
deleted file mode 100644
index 7c61a63a..00000000
--- a/fml/lib/Mail/ThreadTrack/Print/Message.pm
+++ /dev/null
@@ -1,253 +0,0 @@
-#-*- perl -*-
-#
-# Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-# All rights reserved. This program is free software; you can
-# redistribute it and/or modify it under the same terms as Perl itself.
-#
-# $FML: Message.pm,v 1.9 2002/12/22 03:19:15 fukachan Exp $
-#
-
-package Mail::ThreadTrack::Print::Message;
-use strict;
-use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
-use Carp;
-use Mail::ThreadTrack::Print::Utils qw(decode_mime_string STR2EUC);
-
-
-=head1 NAME
-
-Mail::ThreadTrack::Print::Message - summarize message et.al.
-
-=head1 SYNOPSIS
-
-See C<Mail::ThreadTrack::Print> for usage of this subclass.
-
-=head1 DESCRIPTION
-
-See C<Mail::ThreadTrack::Print> for usage of this subclass.
-
-=head1 METHODS
-
-=head2 message_summary($file)
-
-make message summary for specified $file (article).
-
-=cut
-
-
-# Descriptions: make summary of the specified $file (article).
-# Arguments: OBJ($self) STR($file)
-# Side Effects: none
-# Return Value: STR
-sub message_summary
-{
- my ($self, $file) = @_;
- my (@header) = ();
- my $msgbuf = '';
- my $line = $self->{ _article_summary_lines } || 3;
- my $mode = $self->get_mode || 'text';
- my $padding = $mode eq 'text' ? ' ' : '';
-
- use FileHandle;
- my $fh = new FileHandle $file;
-
- if (defined $fh) {
- my $buf;
-
- LINE:
- while ($buf = <$fh>) {
- # remove useless lines
- next LINE if $buf =~ /^\>/o;
- next LINE if $buf =~ /^\-/o;
-
- # header part
- if (1 .. $buf =~ /^$/o) {
- push(@header, $buf);
- }
- # body part
- else {
- next LINE if $buf =~ /^\s*$/o;
-
- # ignore mail header like patterns.
- next LINE if $buf =~ /^X-[-A-Za-z0-9]+:/io;
- next LINE if $buf =~ /^Return-[-A-Za-z0-9]+:/io;
- next LINE if $buf =~ /^Mime-[-A-Za-z0-9]+:/io;
- next LINE if $buf =~ /^Content-[-A-Za-z0-9]+:/io;
- next LINE if $buf =~ /^(To|From|Subject|Reply-To|Received):/io;
- next LINE if $buf =~ /^(Message-ID|Date):/io;
-
- # pick up effetive the first $line lines
- if (_is_valid_buf($buf)) {
- $line--;
- $msgbuf .= $padding . $buf;
- }
-
- last LINE if $line < 0;
- }
- }
-
- $fh->close();
-
- # XXX-TODO: WHO CARE FOR CSS ? return raw messages from here.
- # XXX-TODO: care for non Japanese.
- if (defined $self->{ _no_header_summary }) {
- return STR2EUC( $msgbuf );
- }
- else {
- use Mail::Header;
- my $header = new Mail::Header \@header;
- my $header_info = $self->header_summary({
- header => $header,
- padding => $padding,
- });
- return STR2EUC( $header_info ."\n". $msgbuf );
- }
- }
- else {
- return undef;
- }
-}
-
-
-# Descriptions: check if $str looks effective, not quotation et.al. ?
-# Arguments: STR($str)
-# Side Effects: none
-# Return Value: 1 or 0
-sub _is_valid_buf
-{
- my ($str) = @_;
- $str = STR2EUC( $str );
-
- if ($str =~ /^[\>\#\|\*\:\;\=]/o) {
- return 0;
- }
- elsif ($str =~ /^in /o) { # quotation ?
- return 0;
- }
- elsif ($str =~ /\w+\@\w+/o) { # mail address ?
- return 0;
- }
- elsif ($str =~ /^\S+\>/o) { # quotation ?
- return 0;
- }
-
- return 1;
-}
-
-
-# Descriptions: remove subject tag like string in $str e.g. [elena 100].
-# Arguments: STR($str)
-# Side Effects: none
-# Return Value: STR
-sub _delete_subject_tag_like_string
-{
- my ($str) = @_;
-
- if (defined $str) {
- # XXX-TODO: hmm, method-ify Mail::Message::Utils ?
- use Mail::Message::Utils;
- return Mail::Message::Utils::remove_subject_tag_like_string($str);
- }
- else {
- return undef;
- }
-}
-
-
-# Descriptions: make summary of header $args->{ header }.
-# Arguments: OBJ($self) HASH_REF($args)
-# Side Effects: none
-# Return Value: STR
-sub header_summary
-{
- my ($self, $args) = @_;
- my $date = $args->{ header }->get('date');
- my $from = $args->{ header }->get('from');
- my $subject = $args->{ header }->get('subject');
- my $padding = $args->{ padding } || ' ';
-
- # XXX-TODO: care for non Japanese.
- if (defined $subject) {
- $subject = decode_mime_string($subject, { charset => 'euc-japan' });
- $subject =~ s/\n/ /g;
- $subject = _delete_subject_tag_like_string($subject);
- $subject =~ s/[\s\n]*$//g;
- }
-
- if (defined $from) {
- $from = $self->_who_of_address( $from );
- $from =~ s/\n/ /g;
- $from =~ s/[\s\n]*$//g;
- }
-
- # XXX-TODO: WHO CARE FOR CSS ? return raw messages from here.
- # XXX-TODO: care for non Japanese.
- # return buffer
- my $r = $padding. $date;
- $r .= $padding. "$subject, $from\n";
- return STR2EUC( $r );
-}
-
-
-# Descriptions: get gecos field in $address.
-# return $address itself if the extraction failed.
-# Arguments: OBJ($self) STR($address)
-# Side Effects: none
-# Return Value: STR
-sub _who_of_address
-{
- my ($self, $address) = @_;
- my ($user);
-
- use Mail::Address;
- my (@addrs) = Mail::Address->parse($address);
-
- for my $addr (@addrs) {
- if (defined( $addr->phrase() )) {
- # XXX-TODO: care for non Japanese.
- my $phrase = decode_mime_string( $addr->phrase(), {
- charset => 'euc-japan',
- });
-
- if ($phrase) {
- return($phrase);
- }
- }
-
- $user = $addr->user();
- }
-
- # XXX-TODO: hmm, CROSS SITE SCRIPTING may cause ?
- if ($self->get_mode() eq 'html') {
- return( $user ? "$user\@xxx.xxx.xxx.xxx" : $address );
- }
- else {
- return $address;
- }
-}
-
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 AUTHOR
-
-Ken'ichi Fukamachi
-
-=head1 COPYRIGHT
-
-Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-
-All rights reserved. This program is free software; you can
-redistribute it and/or modify it under the same terms as Perl itself.
-
-=head1 HISTORY
-
-Mail::ThreadTrack::Print::Message first appeared in fml8 mailing list driver package.
-See C<http://www.fml.org/> for more details.
-
-=cut
-
-
-1;
diff --git a/fml/lib/Mail/ThreadTrack/Print/Sort.pm b/fml/lib/Mail/ThreadTrack/Print/Sort.pm
deleted file mode 100644
index 6b0fa5bf..00000000
--- a/fml/lib/Mail/ThreadTrack/Print/Sort.pm
+++ /dev/null
@@ -1,124 +0,0 @@
-#-*- perl -*-
-#
-# Copyright (C) 2001,2002,2004 Ken'ichi Fukamachi
-# All rights reserved. This program is free software; you can
-# redistribute it and/or modify it under the same terms as Perl itself.
-#
-# $FML: Sort.pm,v 1.9 2002/12/22 03:21:33 fukachan Exp $
-#
-
-package Mail::ThreadTrack::Print::Sort;
-use strict;
-use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
-use Carp;
-
-
-=head1 NAME
-
-Mail::ThreadTrack::Print::Sort - sort function for printing
-
-=head1 SYNOPSIS
-
-See C<Mail::ThreadTrack::Print> for usage of this subclass.
-
-=head1 DESCRIPTION
-
-See C<Mail::ThreadTrack::Print> for usage of this subclass.
-
-=head1 METHODS
-
-=head2 sort_thread_id($thread_id_list)
-
-=cut
-
-
-# Descriptions: sort ARRAY REFERENCE $thread_id_list
-# Arguments: OBJ($self) ARRAY_REF($thread_id_list)
-# Side Effects: initialize $self->{ _age } and $self->{ _cost }
-# Return Value: ARRAY_REF
-sub sort_thread_id
-{
- my ($self, $thread_id_list) = @_;
-
- # get age HASH TABLE
- my ($age, $cost) = $self->_calculate_age($thread_id_list);
- $self->{ _age } = $age;
- $self->{ _cost } = $cost;
-
- @$thread_id_list = sort {
- $cost->{$b} <=> $cost->{$a}
- } @$thread_id_list;
-
- return $thread_id_list;
-}
-
-
-my $status_cost = {
- open => ( 1 << 10 ),
- analyzed => ( 1 << 9 ),
-};
-
-
-# Descriptions: evaluate how old and status each thread is
-# Arguments: OBJ($self) ARRAY_REF($thread_id_list)
-# Side Effects: none
-# Return Value: ARRAY( HASH_REF, HASH_REF )
-sub _calculate_age
-{
- my ($self, $thread_id_list) = @_;
- my (%age, %cost) = ();
- my $now = time; # save the current UTC for convenience
- my $rh = $self->{ _hash_table } || {};
- my $day = 24*3600;
-
- # $age hash referehence = { $thread_id => $age };
- my (@aid, $last, $age, $date, $status, $tid) = ();
- for $tid (sort @$thread_id_list) {
- next unless defined $rh->{ _articles }->{ $tid };
-
- # $last: get the latest one of article_id's
- (@aid) = split(/\s+/, $rh->{ _articles }->{ $tid });
- $last = $aid[ $#aid ] || 0;
-
- # how long this thread is not concerned ?
- $age = sprintf("%2.1f%s", ($now - $rh->{ _date }->{ $last })/$day);
- $age{ $tid } = $age;
-
- # evaluate cost hash table which is { $thread_id => $cost }
- my $status = $rh->{ _status }->{ $tid };
- $cost{ $tid } = $status_cost->{ $status } + $age;
- }
-
- return (\%age, \%cost);
-}
-
-
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 AUTHOR
-
-Ken'ichi Fukamachi
-
-=head1 COPYRIGHT
-
-Copyright (C) 2001,2002,2004 Ken'ichi Fukamachi
-
-All rights reserved. This program is free software; you can
-redistribute it and/or modify it under the same terms as Perl itself.
-
-=head1 HISTORY
-
-Mail::ThreadTrack::Print::Sort first appeared in fml8 mailing list driver package.
-See C<http://www.fml.org/> for more details.
-
-=cut
-
-
-1;
diff --git a/fml/lib/Mail/ThreadTrack/Print/Text.pm b/fml/lib/Mail/ThreadTrack/Print/Text.pm
deleted file mode 100644
index c6d5a6a1..00000000
--- a/fml/lib/Mail/ThreadTrack/Print/Text.pm
+++ /dev/null
@@ -1,247 +0,0 @@
-#-*- perl -*-
-#
-# Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-# All rights reserved. This program is free software; you can
-# redistribute it and/or modify it under the same terms as Perl itself.
-#
-# $FML: Text.pm,v 1.14 2003/01/11 15:16:37 fukachan Exp $
-#
-
-package Mail::ThreadTrack::Print::Text;
-use strict;
-use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
-use Carp;
-use Mail::ThreadTrack::Print::Utils qw(decode_mime_string STR2EUC);
-
-#
-# XXX-TODO: insert more examples on format in each function.
-#
-
-=head1 NAME
-
-Mail::ThreadTrack::Print::Text - printing suitable for text
-
-=head1 SYNOPSIS
-
-See C<Mail::ThreadTrack::Print> for usage of this subclass.
-
-=head1 DESCRIPTION
-
-See C<Mail::ThreadTrack::Print> for usage of this subclass.
-
-=head1 METHODS
-
-=head2 show_articles_in_thread(thread_id)
-
-show articles as text in this thread.
-
-=cut
-
-# XXX-TODO: $is_show_cost_indicate hard-coded.
-my $is_show_cost_indicate = 0;
-
-# XXX-TODO: $format hard-coded.
-my $format = "%-20s %10s %5s %8s %s\n";
-
-
-# Descriptions: show articles as text in this thread
-# Arguments: OBJ($self) STR($thread_id)
-# Side Effects: none
-# Return Value: none
-sub show_articles_in_thread
-{
- my ($self, $thread_id) = @_;
- my $mode = $self->get_mode || 'text';
- my $config = $self->{ _config };
- my $spool_dir = $config->{ spool_dir };
- my $articles = $self->{ _hash_table }->{ _articles }->{ $thread_id };
- my $wh = $self->{ _fd } || \*STDOUT;
-
- use FileHandle;
- if (defined($articles) && defined($spool_dir) && -d $spool_dir) {
- my $s = '';
- # $articles = "1 2 3 4 5";
- for my $id (split(/\s+/, $articles)) {
- my $file = $self->filepath({
- base_dir => $spool_dir,
- id => $id,
- });
-
- my $fh = new FileHandle $file;
- if (defined $fh) {
- my $buf;
-
- LINE:
- while (defined($buf = $fh->getline())) {
- next LINE if 1 .. $buf =~ /^$/o;
-
- # XXX-TODO: we suppose Japanese only here.
- $s = STR2EUC($buf);
- print $wh $s;
- }
- $fh->close;
- }
- }
- }
-}
-
-
-# Descriptions: show guide line
-# Arguments: OBJ($self) HASH_REF($args)
-# Side Effects: none
-# Return Value: none
-sub __start_thread_summary
-{
- my ($self, $args) = @_;
- my $fd = $self->{ _fd } || \*STDOUT;
-
- # XXX-TODO: guide line is hard-coded. o.k.?
- printf($fd $format, 'id', 'date', 'age', 'status', 'articles');
- print $fd "-" x60;
- print $fd "\n";
-}
-
-
-# Descriptions: print formatted brief summary
-# Arguments: OBJ($self) HASH_REF($optargs)
-# Side Effects: none
-# Return Value: none
-sub __print_thread_summary
-{
- my ($self, $optargs) = @_;
- my $fd = $self->{ _fd } || \*STDOUT;
- my $date = $optargs->{ date };
- my $age = $optargs->{ age };
- my $status = $optargs->{ status };
- my $thread_id = $optargs->{ thread_id };
- my $articles = $optargs->{ articles };
- my $aid = (split(/\s+/, $articles))[0]; # the head of this thread
-
- printf($fd $format, $thread_id, $date, $age, $status,
- _format_list(25, $articles));
-}
-
-
-# Descriptions: print closing string, empty now (dummy).
-# Arguments: OBJ($self) HASH_REF($args)
-# Side Effects: none
-# Return Value: none
-sub __end_thread_summary
-{
- my ($self, $args) = @_;
- my $fd = $self->{ _fd } || \*STDOUT;
-}
-
-
-# Descriptions: create a string of "a b c .." style up to $num bytes
-# Arguments: NUM($max) STR($str)
-# Side Effects: none
-# Return Value: STR
-sub _format_list
-{
- my ($max, $str) = @_;
- my (@idlist) = split(/\s+/, $str);
- my $r = '';
-
- ID:
- for my $id (@idlist) {
- $r .= $id . " ";
- if (length($r) > $max) {
- $r .= "...";
- last ID;
- }
- }
-
- return $r;
-}
-
-
-# Descriptions: print message summary
-# Arguments: OBJ($self) STR($thread_id)
-# Side Effects: none
-# Return Value: none
-sub __print_message_summary
-{
- my ($self, $thread_id) = @_;
- my $config = $self->{ _config };
- my $age = $self->{ _age } || {};
- my $cost = $self->{ _cost } || {};
- my $fd = $self->{ _fd } || \*STDOUT;
- my $rh = $self->{ _hash_table };
-
- if (defined $config->{ spool_dir }) {
- my ($aid, @aid, $file);
- my $spool_dir = $config->{ spool_dir };
-
- THREAD_ID_LIST:
- for my $thread_id (@$thread_id) {
- if ($is_show_cost_indicate) {
- my $how_bad = _cost_to_indicator( $cost->{ $thread_id } );
- printf $fd "\n%6s %-10s %s\n", $how_bad, $thread_id;
- }
- else {
- printf $fd "\n>Thread-Id: %-10s %s\n", $thread_id;
- }
-
- # show only the first article of this thread $thread_id
- if (defined $rh->{ _articles }->{ $thread_id }) {
- (@aid) = split(/\s+/, $rh->{ _articles }->{ $thread_id });
- $aid = $aid[0];
- $file = $self->filepath({
- base_dir => $spool_dir,
- id => $aid,
- });
- if (-f $file) {
- $self->print( $self->message_summary($file) );
- }
- }
- }
- }
-}
-
-
-# Descriptions: for example, cost -> '!!!'
-# broken now ;-)
-# Arguments: STR($cost)
-# Side Effects: none
-# Return Value: STR
-sub _cost_to_indicator
-{
- my ($cost) = @_;
- my $how_bad = 0;
-
- # XXX-TODO: cost indicator is broken ?
- if ($cost =~ /(\w+)\-(\d+)/) {
- $how_bad += $2;
- $how_bad += 2 if $1 =~ /open/;
- $how_bad = "!" x ($how_bad > 6 ? 6 : $how_bad);
- }
-
- $how_bad;
-}
-
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 AUTHOR
-
-Ken'ichi Fukamachi
-
-=head1 COPYRIGHT
-
-Copyright (C) 2001,2002,2003 Ken'ichi Fukamachi
-
-All rights reserved. This program is free software; you can
-redistribute it and/or modify it under the same terms as Perl itself.
-
-=head1 HISTORY
-
-Mail::ThreadTrack::Print::Text first appeared in fml8 mailing list driver package.
-See C<http://www.fml.org/> for more details.
-
-=cut
-
-
-1;
diff --git a/fml/lib/Mail/ThreadTrack/Print/Utils.pm b/fml/lib/Mail/ThreadTrack/Print/Utils.pm
deleted file mode 100644
index 45bfcbcf..00000000
--- a/fml/lib/Mail/ThreadTrack/Print/Utils.pm
+++ /dev/null
@@ -1,115 +0,0 @@
-#-*- perl -*-
-#
-# Copyright (C) 2001,2002,2004 Ken'ichi Fukamachi
-# All rights reserved. This program is free software; you can
-# redistribute it and/or modify it under the same terms as Perl itself.
-#
-# $FML: Utils.pm,v 1.6 2002/12/22 03:21:33 fukachan Exp $
-#
-
-package Mail::ThreadTrack::Print::Utils;
-use strict;
-use vars qw(@ISA @EXPORT @EXPORT_OK $AUTOLOAD);
-use Carp;
-
-require Exporter;
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(decode_mime_string STR2EUC);
-
-
-=head1 NAME
-
-Mail::ThreadTrack::Print::Utils - utility functions
-
-=head1 SYNOPSIS
-
- use Mail::ThreadTrack::Print::Utils qw(decode_mime_string STR2EUC);
-
-=head1 DESCRIPTION
-
-utility functions to manipulate Japanese string.
-
-=head1 METHODS
-
-=head2 decode_mime_string(string, [$options])
-
-decode a base64/quoted-printable encoded string to a plain message.
-The encoding method is automatically detected.
-
-C<$options> is a HASH REFERENCE.
-You can specify the charset of the string to return
-by $options->{ charset }.
-
-=head2 STR2EUC(str)
-
-convert str to Japanese EUC.
-
-=cut
-
-
-# Descriptions: decode $str
-# Arguments: STR($str) HASH_REF($options)
-# Side Effects: none
-# Return Value: STR
-sub decode_mime_string
-{
- my ($str, $options) = @_;
- my $charset = $options->{ 'charset' } || 'euc-japan';
-
- # XXX-TODO: care for non Japanese.
- if ($charset eq 'euc-japan') {
- if ($str =~ /=\?ISO\-2022\-JP\?B\?(\S+\=*)\?=/i) {
- eval q{ use MIME::Base64; };
- $str =~ s/=\?ISO\-2022\-JP\?B\?(\S+\=*)\?=/decode_base64($1)/gie;
- }
-
- if ($str =~ /=\?ISO\-2022\-JP\?Q\?(\S+\=*)\?=/i) {
- eval q{ use MIME::QuotedPrint;};
- $str =~ s/=\?ISO\-2022\-JP\?Q\?(\S+\=*)\?=/decode_qp($1)/gie;
- }
- }
-
- use Jcode;
- &Jcode::convert(\$str, 'euc');
- $str;
-}
-
-
-# Descriptions: convert $str to Japanese EUC
-# Arguments: STR($str)
-# Side Effects: none
-# Return Value: STR
-sub STR2EUC
-{
- my ($str) = @_;
-
- use Jcode;
- &Jcode::convert(\$str, 'euc');
- return $str;
-}
-
-
-=head1 CODING STYLE
-
-See C<http://www.fml.org/software/FNF/> on fml coding style guide.
-
-=head1 AUTHOR
-
-Ken'ichi Fukamachi
-
-=head1 COPYRIGHT
-
-Copyright (C) 2001,2002,2004 Ken'ichi Fukamachi
-
-All rights reserved. This program is free software; you can
-redistribute it and/or modify it under the same terms as Perl itself.
-
-=head1 HISTORY
-
-Mail::ThreadTrack::Print::Utils first appeared in fml8 mailing list driver package.
-See C<http://www.fml.org/> for more details.
-
-=cut
-
-
-1;