/[mws]/trunk/MWS.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/MWS.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 16 by dpavlin, Thu May 6 23:06:08 2004 UTC revision 42 by dpavlin, Mon May 10 22:04:01 2004 UTC
# Line 4  package MWS; Line 4  package MWS;
4    
5  use strict;  use strict;
6  use warnings;  use warnings;
 use Carp;  
7    
8    use lib '.';
9    
10    use Carp;
11  use Mail::Box::Manager;  use Mail::Box::Manager;
12  use Config::IniFiles;  use Config::IniFiles;
13  use POSIX qw(strftime);  use POSIX qw(strftime);
14  use Text::Autoformat;  use Text::Autoformat;
15  use Text::Iconv;  use Text::Iconv;
16    use Text::Unaccent;
17  #use MWS_plucene;  use Date::Parse;
18  use MWS_swish;  use POSIX qw(strftime);
19    use MIME::Base64;
 require Exporter;  
   
 our @ISA = qw(Exporter);  
   
 our %EXPORT_TAGS = ();  
 our @EXPORT_OK;  
 our @EXPORT;  
20    
21  our $VERSION = '1.00';  our $VERSION = '1.00';
22    
23  my $folder;     # placeholder for folders  my $debug = 1;
24    
25  my $debug = 2;  my @counters = qw(from to cc bcc folder);
26    
27  sub new {  sub new {
28          my $class = shift;          my $class = shift;
29          my $self = {};          my $self = {@_};
30          bless($self, $class);          bless($self, $class);
31    
         my $config_file = shift || die "need index file";  
32    
33          $self->{config} = new Config::IniFiles( -file => $config_file );          my $config_name = $self->{config_file} || croak "need config_file";
34            $config_name =~ s/\.conf.*$//;
35            $self->{config_name} = $config_name;
36    
37          my $index_file = $self->{config}->val('global', 'index') || croak "can't find [index] section in config file with path of index";          $self->{config} = new Config::IniFiles( -file => $self->{config_file} );
38    
39            my $index_dir = $self->{config}->val('global', 'index') || croak "can't find [index] section in config file with path of index";
40    
41          $self->{mgr} = Mail::Box::Manager->new(access => 'r');          $self->{mgr} = Mail::Box::Manager->new(access => 'r');
42          $self->{index_file} = $index_file;          $self->{index_dir} = $index_dir;
43    
44          # placeholder for opened folders          # placeholder for opened folders
45          $self->{folder} = {};          $self->{folder} = {};
46    
47          $self->{wrap_margin} = $self->{config}->val('global', 'wrap_margin');          $self->{wrap_margin} = $self->{config}->val('global', 'wrap_margin');
48            $self->{max_results} = $self->{config}->val('global', 'max_results') || 100;
49            $self->reset_counters;
50    
51          return $self;          return $self;
52  }  }
53    
54    sub normalize_string {
55            my $self = shift;
56    
57            my $v = shift || return;
58    
59            $v = unac_string('ISO-8859-2', $v);
60            $v = join('',sort split(/\s+/,$v));
61            $v =~ s/\W+//g;
62    
63            return lc($v);
64    }
65    
66    # reset tables for search results
67    sub reset_counters {
68            my $self = shift;
69    
70            $self->{counter} = {};
71    
72    #       foreach my $c (qw(thread from to cc bcc lists links att)) {
73    #               $self->{counter}->{$c} = {};
74    #       }
75    
76    }
77    
78    sub add_counter($$) {
79            my $self = shift;
80    
81            my ($c,$v) = @_;
82            my $k = $self->normalize_string($v);
83    
84            $self->{counter}->{$c}->{$k}->{name} = $v || return;
85            return $self->{counter}->{$c}->{$k}->{usage}++;
86    }
87    
88    sub yyyymmdd {
89            my $self = shift;
90    
91            my $t = shift || time;
92    
93            my (undef,undef,undef,$dd,$mm,$yyyy) = localtime($t);
94            $mm++;
95            $yyyy+=1900;
96            return ($yyyy,$mm,$dd);
97    }
98    
99    sub fmtdate {
100            my $self = shift;
101    
102            my @out;
103            my @formats = qw(%04d %02d %02d);
104            while (my $v = shift) {
105                    my $f = shift @formats;
106                    push @out, sprintf($f, $v);
107            }
108    
109            print STDERR "fmtdate: ",join('|',@out),"\n" if ($debug == 2);
110    
111            return (wantarray ? @out : join("-",@out));
112    }
113    
114    sub add_counter_calendar($) {
115            my $self = shift;
116    
117            my $t = shift || croak "add_counter_calendar without argument!";
118            
119            my ($yyyy,$mm,$dd) = $self->fmtdate($self->yyyymmdd($t));
120    
121            return $self->{counter}->{calendar}->{"$yyyy-$mm"}->{$dd}++;
122    }
123    
124    
125    sub counter {
126            my $self = shift;
127    
128            my $c = shift || return;
129    
130            return if (! $self->{counter}->{$c});
131    
132            return $self->{counter}->{$c};
133    }
134    
135  sub mbox_name2path {  sub mbox_name2path {
136          my $self = shift;          my $self = shift;
137    
# Line 106  sub fetch_message { Line 187  sub fetch_message {
187                  print STDERR "close_folder($mbox) forced on ",$self->{fetch_count},"iteration\n";                  print STDERR "close_folder($mbox) forced on ",$self->{fetch_count},"iteration\n";
188          }          }
189                    
190          return $self->open_folder($mbox)->find($id) ||          my $msg = $self->open_folder($mbox)->find($id);
191            if ($msg) {
192                    return $msg;
193            } else {
194                  print STDERR "can't find message $id in $mbox. Time to re-index?\n";                  print STDERR "can't find message $id in $mbox. Time to re-index?\n";
195                    return;
196            }
197  }  }
198    
199    
200  sub search {  sub search {
201          my $self = shift;          my $self = shift;
202    
203          my $s = shift || carp "search called without argument!";          carp "search called without argument!" if (! @_);
204    
205          print STDERR "search_index($s)\n" if ($debug == 2);          $self->reset_counters;
206          my @index_ids = $self->search_index($s);  
207            print STDERR "search(",join(" ",@_),")\n" if ($debug == 2);
208            my @index_ids = $self->search_index(@_);
209    
210          $self->{'index_ids'} = \@index_ids;          $self->{'index_ids'} = \@index_ids;
211    
212          my $results = $#index_ids + 1;          #my $results = $#index_ids + 1;
213          $self->{'results'} = $results;          #$self->{'results'} = $results;
214            
215            my $results = $self->{'total_hits'} || ($#index_ids + 1);
216    
217          $self->{'curr_result'} = 0;          $self->{'curr_result'} = 0;
218    
219            $self->reset_counters;
220    
221          print STDERR "$results results\n" if ($debug == 2);          print STDERR "$results results\n" if ($debug == 2);
222    
223          return $results || 'error';          return $results || 'error';
# Line 136  sub decode_qp($) { Line 228  sub decode_qp($) {
228    
229          my $tmp = shift || return;          my $tmp = shift || return;
230    
231          sub decode($$) {          sub decode($$$) {
232                  my ($cp,$qp) = @_;                  my ($cp,$enc,$qp) = @_;
233    
234                    print STDERR "decode($cp,$qp) -> " if ($debug == 2);
235    
236                    if (uc($enc) eq "Q") {
237                            $qp =~ s/=([a-f0-9][a-f0-9])/chr(hex($1))/ieg;
238                            $qp =~ s/_/ /g;
239                    } elsif (uc($enc) eq "B") {
240                            $qp = decode_base64($qp);
241                    } else {
242                            croak "unsupported encoding '$enc' in decode_qp\n";
243                            return $qp;
244                    }
245    
246                    print STDERR "$qp\n" if ($debug == 2);
247    
248                  my $iconv = Text::Iconv->new($cp,'ISO-8859-2');                  my $iconv = Text::Iconv->new($cp,'ISO-8859-2');
249          print STDERR "decode($cp,$qp) -> " if ($debug == 2);                  return $iconv->convert($qp) || '';
                 $qp =~ s/=([a-f0-9][a-f0-9])/chr(hex($1))/ieg;  
                 $qp =~ s/_/ /g;  
         print STDERR "$qp\n" if ($debug == 2);  
                 return $iconv->convert($qp);  
250          }          }
251    
252          $tmp =~ s/=\?([^\?]+)\?Q\?(.+)\?=/decode($1,$2)/ex;          $tmp =~ s/=\?([^\?]+)\?([QB])\?(.+?)\?=/decode($1,$2,$3)/ige;
253            $tmp =~ s/^\s*["']+(.*?)["']+\s*$/$1/g;
254            #print STDERR "$tmp\n" if ($debug == 2);
255          return $tmp;          return $tmp;
256  }  }
257    
# Line 157  sub unroll($$$) { Line 262  sub unroll($$$) {
262    
263          my @arr;          my @arr;
264    
265            return if (! $message->$part);
266    
267          foreach my $from ($message->$part) {          foreach my $from ($message->$part) {
268                  my $tmp = $from->$sub || next;                  my $tmp = $from->$sub || next;
269    
270                  $tmp = $self->decode_qp($tmp);                  $tmp = $self->decode_qp($tmp);
                 $tmp =~ s/^\s*["'](.*)["']\s*$/$1/;  
271                  push @arr, $tmp;                  push @arr, $tmp;
272          }          }
273    
# Line 181  sub fetch_all_results { Line 287  sub fetch_all_results {
287                  push @arr, $self->fetch_result_by_id($id);                  push @arr, $self->fetch_result_by_id($id);
288          }          }
289    
290    
291          return @arr;          return @arr;
292  }  }
293    
# Line 217  sub plain_text_body { Line 324  sub plain_text_body {
324                  }                  }
325          }          }
326    
327            if (! $body) {
328                    $body = "[plain/text body not found]" if ($debug == 2);
329                    print STDERR "plain/text body not found\n" if ($debug);
330                    return;
331            }
332    
333          # reformat with Text::Autoformat          # reformat with Text::Autoformat
334          my $wrap = $self->{wrap_margin};          my $wrap = $self->{wrap_margin};
335          if ($wrap && $body && $body =~ m/^.{$wrap}..*$/m) {          if ($wrap && $body && $body =~ m/^.{$wrap}..*$/m) {
336                  $body =~ s/[\r\n]/\n/gs;                  $body = autoformat($body, {right=>$wrap, all=>1});
                 $body = autoformat($body, {right=>$wrap});  
337                  $body .="\n[reformated using autoformat, margin at $wrap]" if ($debug == 2);                  $body .="\n[reformated using autoformat, margin at $wrap]" if ($debug == 2);
338          }          }
339    
# Line 240  sub fetch_result_by_id { Line 352  sub fetch_result_by_id {
352    
353                  print STDERR "fetch_result_by_id($id) not in cache, hitting disk\n" if ($debug == 2);                  print STDERR "fetch_result_by_id($id) not in cache, hitting disk\n" if ($debug == 2);
354    
355                  my $message = $self->fetch_message($id) || print STDERR "can't fetch message '$id'";                  my $message = $self->fetch_message($id) || return;
356    
357                  $row->{'id'} = $id;                  $row->{'id'} = $id;
358                  @{$row->{'from'}} = $self->unroll($message,'from','phrase');  
359                  @{$row->{'to'}} = $self->unroll($message,'to','phrase');                  foreach my $p (@counters) {
360                  @{$row->{'cc'}} = $self->unroll($message,'cc','phrase');                          foreach my $v ($self->unroll($message,$p,'phrase')) {
361                                    push @{$row->{$p}},$v;
362                                    $self->add_counter($p,$v);
363                            }
364                    }
365    
366                    $self->add_counter('folder', $1) if ($id =~ m/^(\S+)\s/);
367    
368                  $row->{'subject'} = $self->decode_qp($message->subject);                  $row->{'subject'} = $self->decode_qp($message->subject);
369                  $row->{'body'} = $self->plain_text_body($message);                  $row->{'body'} = $self->plain_text_body($message);
370                  $row->{'date'} = $message->date;                  my $utime = str2time($message->date);
371    
372                    $row->{'date_utime'} = $utime;
373    
374                    $row->{'date'} = strftime("%Y-%m-%d %H:%M:%S", localtime($utime));
375                    $self->add_counter_calendar($utime);
376    
377                  # XXX store in cache?                  # XXX store in cache?
378                  $self->{cache}->{$id} = $row;                  $self->{cache}->{$id} = $row;
379                  print STDERR "$id stored in cache\n" if ($debug == 2);                  print STDERR "$id stored in cache\n" if ($debug == 2);
380          } else {          } else {
381                  print STDERR "fetch_result_by_id($id) in cache\n" if ($debug == 2);                  print STDERR "fetch_result_by_id($id) in cache\n" if ($debug == 2);
382                    foreach my $p (@counters) {
383                            foreach my $v (@{$row->{$p}}) {
384                                    $self->add_counter($p,$v);
385                            }
386                    }
387    
388                    $self->add_counter('folder', $1) if ($id =~ m/^(\S+)\s/);
389    
390                    $self->add_counter_calendar($row->{date_utime});
391          }          }
392    
393          return $row;          return $row;

Legend:
Removed from v.16  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26