source: perl/lib/BarnOwl/Message.pm

Last change on this file was 4fd3c04, checked in by Anders Kaseorg <andersk@mit.edu>, 7 years ago
Remove AIM support This code has received almost no security attention, and anyway, AIM is shutting down on December 15, 2017. https://aimemories.tumblr.com/post/166091776077/aimemories Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • Property mode set to 100644
File size: 8.8 KB
Line 
1use strict;
2use warnings;
3
4package BarnOwl::Message;
5
6use File::Spec;
7
8use BarnOwl::Message::Admin;
9use BarnOwl::Message::Generic;
10use BarnOwl::Message::Loopback;
11use BarnOwl::Message::Zephyr;
12
13sub new {
14    my $class = shift;
15    my %args = (@_);
16    if($class eq __PACKAGE__ && $args{type}) {
17        $class = "BarnOwl::Message::" . ucfirst $args{type};
18    }
19    return bless {%args}, $class;
20}
21
22sub type        { return shift->{"type"}; }
23sub direction   { return shift->{"direction"}; }
24sub time        { return shift->{"time"}; }
25sub unix_time   { return shift->{"unix_time"}; }
26sub id          { return shift->{"id"}; }
27sub body        { return shift->{"body"}; }
28sub sender      { return shift->{"sender"}; }
29sub recipient   { return shift->{"recipient"}; }
30sub login       { return shift->{"login"}; }
31sub is_private  { return shift->{"private"}; }
32
33sub is_login    { return shift->login eq "login"; }
34sub is_logout   { return shift->login eq "logout"; }
35sub is_loginout { my $m=shift; return ($m->is_login or $m->is_logout); }
36sub is_incoming { return (shift->{"direction"} eq "in"); }
37sub is_outgoing { return (shift->{"direction"} eq "out"); }
38
39sub is_deleted  { return shift->{"deleted"}; }
40
41sub is_admin    { return (shift->{"type"} eq "admin"); }
42sub is_generic  { return (shift->{"type"} eq "generic"); }
43sub is_zephyr   { return (shift->{"type"} eq "zephyr"); }
44sub is_aim      { return ''; }
45sub is_jabber   { return (shift->{"type"} eq "jabber"); }
46sub is_icq      { return (shift->{"type"} eq "icq"); }
47sub is_yahoo    { return (shift->{"type"} eq "yahoo"); }
48sub is_msn      { return (shift->{"type"} eq "msn"); }
49sub is_loopback { return (shift->{"type"} eq "loopback"); }
50
51# These are overridden by appropriate message types
52sub is_ping     { return 0; }
53sub is_mail     { return 0; }
54sub is_personal { return BarnOwl::message_matches_filter(shift, "personal"); }
55sub class       { return undef; }
56sub instance    { return undef; }
57sub realm       { return undef; }
58sub opcode      { return undef; }
59sub header      { return undef; }
60sub host        { return undef; }
61sub hostname    { return undef; }
62sub auth        { return undef; }
63sub fields      { return undef; }
64sub zsig        { return undef; }
65sub zwriteline  { return undef; }
66sub login_host  { return undef; }
67sub login_tty   { return undef; }
68
69# This is for back-compat with old messages that set these properties
70# New protocol implementations are encourages to user override these
71# methods.
72sub replycmd         { return shift->{replycmd}};
73sub replysendercmd   { return shift->{replysendercmd}};
74
75sub pretty_sender    { return shift->sender; }
76sub pretty_recipient { return shift->recipient; }
77
78# Override if you want a context (instance, network, etc.) on personals
79sub personal_context { return ""; }
80# extra short version, for use where space is especially tight
81# (eg, the oneline style)
82sub short_personal_context { return ""; }
83
84sub delete_and_expunge {
85    my ($m) = @_;
86    &BarnOwl::command("delete-and-expunge --quiet --id " . $m->id);
87}
88
89sub delete {
90    my ($m) = @_;
91    &BarnOwl::command("delete --id ".$m->id);
92}
93
94sub undelete {
95    my ($m) = @_;
96    &BarnOwl::command("undelete --id ".$m->id);
97}
98
99# Serializes the message into something similar to the zwgc->vt format
100sub serialize {
101    my ($this) = @_;
102    my $s;
103    for my $f (keys %$this) {
104        my $val = $this->{$f};
105        if (ref($val) eq "ARRAY") {
106            for my $i (0..@$val-1) {
107                my $aval;
108                $aval = $val->[$i];
109                $aval =~ s/\n/\n$f.$i: /g;
110                $s .= "$f.$i: $aval\n";
111            }
112        } else {
113            $val =~ s/\n/\n$f: /g;
114            $s .= "$f: $val\n";
115        }
116    }
117    return $s;
118}
119
120=head2 log MESSAGE
121
122Returns the text that should be written to a file to log C<MESSAGE>.
123
124=cut
125
126sub log {
127    my ($m) = @_;
128    return $m->log_header . "\n\n" . $m->log_body . "\n\n";
129}
130
131=head2 log_header MESSAGE
132
133Returns the header of the message, for logging purposes.
134If you override L<BarnOwl::Message::log>, this method is not called.
135
136=cut
137
138sub log_header {
139    my ($m) = @_;
140    my $sender = $m->sender;
141    my $recipient = $m->recipient;
142    my $timestr = $m->time;
143    return "From: <$sender> To: <$recipient>\n"
144         . "Time: $timestr";
145}
146
147=head2 log_body MESSAGE
148
149Returns the body of the message, for logging purposes.
150If you override L<BarnOwl::Message::log>, this method is not called.
151
152=cut
153
154sub log_body {
155    my ($m) = @_;
156    if ($m->is_loginout) {
157        return uc($m->login)
158            . $m->login_type
159            . ($m->login_extra ? ' at ' . $m->login_extra : '');
160    } else {
161        return $m->body;
162    }
163}
164
165=head2 log_filenames MESSAGE
166
167Returns a list of filenames to which this message should be logged.
168The filenames should be relative to the path returned by C<log_path>.
169See L<BarnOwl::Logging::get_filenames> for the specification of valid
170filenames, and for what happens if this method returns an invalid
171filename.
172
173=cut
174
175sub log_filenames {
176    my ($m) = @_;
177    my $filename;
178    if ($m->is_incoming) {
179        $filename = $m->pretty_sender;
180    } elsif ($m->is_outgoing) {
181        $filename = $m->pretty_recipient;
182    }
183    $filename = "unknown" if !defined($filename) || $filename eq '';
184    if (BarnOwl::getvar('log-to-subdirectories') eq 'on') {
185        return ($filename);
186    } else {
187        return ($m->log_subfolder . ':' . $filename);
188    }
189}
190
191=head2 log_to_all_file MESSAGE
192
193There is an C<all> file.  This method determines if C<MESSAGE>
194should get logged to it, in addition to any files returned by
195C<log_filenames>.
196
197It defaults to returning true if and only if C<MESSAGE> is outgoing.
198
199=cut
200
201sub log_to_all_file {
202    my ($m) = @_;
203    return $m->is_outgoing;
204}
205
206=head2 log_path MESSAGE
207
208Returns the folder in which all messages of this class get logged.
209
210Defaults to C<log_base_path/log_subfolder> if C<log-to-subdirectories>
211is enabled, or to the C<logpath> BarnOwl variable if it is not.
212
213Most protocols should override C<log_subfolder> rather than
214C<log_path>, in order to properly take into account the value of
215C<log-to-subdirectories>.
216
217=cut
218
219sub log_path {
220    my ($m) = @_;
221    if (BarnOwl::getvar('log-to-subdirectories') eq 'on') {
222        return File::Spec->catfile($m->log_base_path, $m->log_subfolder);
223    } else {
224        return BarnOwl::getvar('logpath');
225    }
226}
227
228=head2 log_base_path MESSAGE
229
230Returns the base path for logging.  See C<log_path> for more information.
231
232Defaults to the BarnOwl variable C<logbasepath>.
233
234=cut
235
236sub log_base_path {
237    return BarnOwl::getvar('logbasepath');
238}
239
240=head2 log_subfolder MESSAGE
241
242Returns the subfolder of C<log_base_path> to log messages in.
243
244Defaults to C<lc($m->type)>.
245
246=cut
247
248sub log_subfolder {
249    return lc(shift->type);
250}
251
252=head2 log_outgoing_error MESSAGE
253
254Returns the string that should be logged if there is an error sending
255an outgoing message.
256
257=cut
258
259sub log_outgoing_error {
260    my ($m) = @_;
261    my $recipient = $m->pretty_recipient;
262    my $body = $m->body;
263    chomp $body;
264    return "ERROR (BarnOwl): $recipient\n$body\n\n";
265}
266
267=head2 should_log MESSAGE
268
269Returns true if we should log C<MESSAGE>.  This does not override
270user settings; if the BarnOwl variable C<loggingdirection> is in,
271and C<MESSAGE> is outgoing and does not match the C<logfilter>, it
272will not get logged regardless of what this method returns.
273
274Note that this method I<does> override the BarnOwl C<logging>
275variable; if a derived class overrides this method and does not
276provide an alternative BarnOwl variable (such as C<classlogging>),
277the overriding method should check the BarnOwl C<logging> variable.
278
279Defaults to returning the value of the BarnOwl variable C<logging>.
280
281=cut
282
283sub should_log {
284    return BarnOwl::getvar('logging') eq 'on';
285}
286
287# Populate the annoying legacy global variables
288sub legacy_populate_global {
289    my ($m) = @_;
290    $BarnOwl::direction  = $m->direction ;
291    $BarnOwl::type       = $m->type      ;
292    $BarnOwl::id         = $m->id        ;
293    $BarnOwl::class      = $m->class     ;
294    $BarnOwl::instance   = $m->instance  ;
295    $BarnOwl::recipient  = $m->recipient ;
296    $BarnOwl::sender     = $m->sender    ;
297    $BarnOwl::realm      = $m->realm     ;
298    $BarnOwl::opcode     = $m->opcode    ;
299    $BarnOwl::zsig       = $m->zsig      ;
300    $BarnOwl::msg        = $m->body      ;
301    $BarnOwl::time       = $m->time      ;
302    $BarnOwl::host       = $m->host      ;
303    $BarnOwl::login      = $m->login     ;
304    $BarnOwl::auth       = $m->auth      ;
305    if ($m->fields) {
306        @BarnOwl::fields = @{$m->fields};
307        @main::fields = @{$m->fields};
308    } else {
309        @BarnOwl::fields = undef;
310        @main::fields = undef;
311    }
312}
313
314sub smartfilter {
315    die("smartfilter not supported for this message\n");
316}
317
318# Display fields -- overridden by subclasses when needed
319sub login_type {""}
320sub login_extra {""}
321sub long_sender {""}
322
323# The context in which a non-personal message was sent, e.g. a chat or
324# class
325sub context {""}
326
327# Some indicator of context *within* $self->context. e.g. the zephyr
328# instance
329sub subcontext {""}
330
331
3321;
Note: See TracBrowser for help on using the repository browser.