source: perl/lib/BarnOwl/Message/Zephyr.pm @ 8cec8f7

Last change on this file since 8cec8f7 was d2ba33c, checked in by Jason Gross <jasongross9@gmail.com>, 7 years ago
Use g_utf8_casefold and g_utf8_normalize We define a convenience function compat_casefold in util.c for reuse in filters.
  • Property mode set to 100644
File size: 7.6 KB
RevLine 
[ee183be]1use strict;
2use warnings;
3
4package BarnOwl::Message::Zephyr;
5
[1522e5d]6use constant WEBZEPHYR_PRINCIPAL => "daemon/webzephyr.mit.edu";
[ee183be]7use constant WEBZEPHYR_CLASS     => "webzephyr";
8use constant WEBZEPHYR_OPCODE    => "webzephyr";
9
10use base qw( BarnOwl::Message );
11
12sub strip_realm {
13    my $sender = shift;
14    my $realm = BarnOwl::zephyr_getrealm();
[bcde942d]15    $sender =~ s/\@\Q$realm\E$//;
[ee183be]16    return $sender;
17}
18
[8d553bf]19sub principal_realm {
20    my $principal = shift;
21    my ($user, $realm) = split(/@/,$principal);
22    return $realm;
23}
24
[d2ba33c]25sub casefold_principal {
26    my $principal = shift;
27    # split the principal right after the final @, without eating any
28    # characters; this way, we always get at least '@' in $user
29    my ($user, $realm) = split(/(?<=@)(?=[^@]+$)/, $principal);
30    return lc($user) . uc($realm);
31}
32
[ee183be]33sub login_type {
34    return (shift->zsig eq "") ? "(PSEUDO)" : "";
35}
36
37sub login_extra {
38    my $m = shift;
39    return undef if (!$m->is_loginout);
40    my $s = lc($m->host);
41    $s .= " " . $m->login_tty if defined $m->login_tty;
42    return $s;
43}
44
45sub long_sender {
46    my $m = shift;
47    return $m->zsig;
48}
49
50sub context {
51    return shift->class;
52}
53
54sub subcontext {
55    return shift->instance;
56}
57
58sub login_tty {
59    my ($m) = @_;
60    return undef if (!$m->is_loginout);
[6401db3]61    return undef if (!defined($m->fields));
[ee183be]62    return $m->fields->[2];
63}
64
65sub login_host {
66    my ($m) = @_;
67    return undef if (!$m->is_loginout);
[6401db3]68    return undef if (!defined($m->fields));
[ee183be]69    return $m->fields->[0];
70}
71
72sub zwriteline  { return shift->{"zwriteline"}; }
73
74sub is_ping     { return (lc(shift->opcode) eq "ping"); }
75
76sub is_mail {
77    my ($m) = @_;
78    return ((lc($m->class) eq "mail") && $m->is_private);
79}
80
81sub pretty_sender {
82    my ($m) = @_;
83    return strip_realm($m->sender);
84}
85
86sub pretty_recipient {
87    my ($m) = @_;
88    return strip_realm($m->recipient);
89}
90
91# Portion of the reply command that preserves the context
92sub context_reply_cmd {
[bc8275e]93    my $mclass = shift;
94    my $minstance = shift;
[3a6277a]95    my @class;
[bc8275e]96    if (lc($mclass) ne "message") {
[3a6277a]97        @class = ('-c', $mclass);
[ee183be]98    }
[3a6277a]99    my @instance;
[bc8275e]100    if (lc($minstance) ne "personal") {
[3a6277a]101        @instance = ('-i', $minstance);
[ee183be]102    }
[3a6277a]103    return (@class, @instance);
[ee183be]104}
105
106sub personal_context {
107    my ($m) = @_;
[3a6277a]108    return BarnOwl::quote(context_reply_cmd($m->class, $m->instance));
[ee183be]109}
110
111sub short_personal_context {
112    my ($m) = @_;
113    if(lc($m->class) eq 'message')
114    {
115        if(lc($m->instance) eq 'personal')
116        {
117            return '';
118        } else {
119            return $m->instance;
120        }
121    } else {
122        return $m->class;
123    }
124}
125
126# These are arguably zephyr-specific
127sub class       { return shift->{"class"}; }
128sub instance    { return shift->{"instance"}; }
129sub realm       { return shift->{"realm"}; }
130sub opcode      { return shift->{"opcode"}; }
131sub host        { return shift->{"hostname"}; }
132sub hostname    { return shift->{"hostname"}; }
133sub header      { return shift->{"header"}; }
134sub auth        { return shift->{"auth"}; }
135sub fields      { return shift->{"fields"}; }
136sub zsig        { return shift->{"zsig"}; }
137
138sub zephyr_cc {
139    my $self = shift;
140    return $1 if $self->body =~ /^\s*cc:\s+([^\n]+)/i;
141    return undef;
142}
143
[eea7bed4]144sub zephyr_cc_without_recipient {
145    my $self = shift;
146    my $recipient = lc(strip_realm($self->recipient));
147    my $cc = $self->zephyr_cc;
148    return grep { lc(strip_realm($_)) ne $recipient } split(/\s+/, $cc) if defined $cc;
149    return ();
150}
151
[ee183be]152sub replycmd {
153    my $self = shift;
154    my $sender = shift;
155    $sender = 0 unless defined $sender;
156    my ($class, $instance, $to, $cc);
157    if($self->is_outgoing) {
158        return $self->{zwriteline};
159    }
160
161    if($sender && $self->opcode eq WEBZEPHYR_OPCODE) {
162        $class = WEBZEPHYR_CLASS;
163        $instance = $self->pretty_sender;
164        $instance =~ s/-webzephyr$//;
165        $to = WEBZEPHYR_PRINCIPAL;
166    } elsif($self->class eq WEBZEPHYR_CLASS
167            && $self->is_loginout) {
168        $class = WEBZEPHYR_CLASS;
169        $instance = $self->instance;
170        $to = WEBZEPHYR_PRINCIPAL;
171    } elsif($self->is_loginout) {
172        $class = 'MESSAGE';
173        $instance = 'PERSONAL';
174        $to = $self->sender;
175    } elsif($sender && !$self->is_private) {
176        # Possible future feature: (Optionally?) include the class and/or
177        # instance of the message being replied to in the instance of the
178        # outgoing personal reply
179        $class = 'MESSAGE';
180        $instance = 'PERSONAL';
181        $to = $self->sender;
182    } else {
183        $class = $self->class;
184        $instance = $self->instance;
[bf70350]185        if ($self->recipient eq '' || $self->recipient =~ /^@/) {
[edd0be7]186            $to = $self->recipient;
187        } else {
[ee183be]188            $to = $self->sender;
[edd0be7]189            $cc = $self->zephyr_cc();
[ee183be]190        }
191    }
192
[3a6277a]193    my @cmd;
[30e7ffd]194    if(lc $self->opcode eq 'crypt' and ( not $sender or $self->is_private)) {
195        # Responses to zcrypted messages should be zcrypted, so long as we
196        # aren't switching to personals
[3a6277a]197        @cmd = ('zcrypt');
[ee183be]198    } else {
[3a6277a]199        @cmd = ('zwrite');
[ee183be]200    }
201
[3a6277a]202    push @cmd, context_reply_cmd($class, $instance);
[8d553bf]203
[ee183be]204    if ($to ne '') {
205        $to = strip_realm($to);
[892e897]206        if (defined $cc and not $sender) {
[ee183be]207            my @cc = grep /^[^-]/, ($to, split /\s+/, $cc);
208            my %cc = map {$_ => 1} @cc;
[8d553bf]209            # this isn't quite right - it doesn't strip off the
210            # user if the message was addressed to them by fully qualified
211            # name
[ee183be]212            delete $cc{strip_realm(BarnOwl::zephyr_getsender())};
213            @cc = keys %cc;
[8d553bf]214
215            my $sender_realm = principal_realm($self->sender);
216            if (BarnOwl::zephyr_getrealm() ne $sender_realm) {
217                @cc = map {
218                    if($_ !~ /@/) {
219                       "${_}\@${sender_realm}";
220                    } else {
221                        $_;
222                    }
223                } @cc;
224            }
[3a6277a]225            push @cmd, '-C', @cc;
[ee183be]226        } else {
227            if(BarnOwl::getvar('smartstrip') eq 'on') {
228                $to = BarnOwl::zephyr_smartstrip_user($to);
229            }
[3a6277a]230            push @cmd, $to;
[ee183be]231        }
232    }
[3a6277a]233    return BarnOwl::quote(@cmd);
[ee183be]234}
235
236sub replysendercmd {
237    my $self = shift;
238    return $self->replycmd(1);
239}
240
[7f463cf]241# Logging
242sub log_header {
243    my ($m) = @_;
244    my $class = $m->class;
245    my $instance = $m->instance;
246    my $opcode = $m->opcode;
247    my $timestr = $m->time;
248    my $host = $m->host;
249    my $sender = $m->pretty_sender;
250    my $zsig = $m->zsig;
251    my $rtn = "Class: $class Instance: $instance";
252    $rtn .= " Opcode: $opcode" unless !defined $opcode || $opcode eq '';
253    $rtn .= "\nTime: $timestr Host: $host"
254          . "\nFrom: $zsig <$sender>";
255    return $rtn;
256}
[ee183be]257
[eea7bed4]258sub log_filenames {
259    my ($m) = @_;
260    my @filenames = ();
261    if ($m->is_personal) {
262        @filenames = $m->zephyr_cc_without_recipient;
263    }
264    if ($m->is_incoming) {
265        if ($m->is_personal) {
266            push @filenames, $m->sender;
267        } else {
[3374de9]268            my $realm = '';
269            $realm .= '@' . $m->realm if $m->realm ne BarnOwl::zephyr_getrealm();
[d2ba33c]270            return (BarnOwl::compat_casefold($m->class) . uc($realm));
[eea7bed4]271        }
272    } else {
273        push @filenames, $m->recipient;
274    }
[d2ba33c]275    return map { casefold_principal(BarnOwl::zephyr_smartstrip_user(strip_realm($_))) } @filenames;
[eea7bed4]276}
277
278sub log_to_class_file {
279    my ($m) = @_;
280    return !$m->is_personal;
281}
282
[dce72c1]283sub log_path {
[eea7bed4]284    my ($m) = @_;
285    if ($m->log_to_class_file) {
286        return BarnOwl::getvar('classlogpath');
287    } else {
288        return BarnOwl::getvar('logpath');
289    }
290}
291
[5093c6f]292sub should_log {
293    my ($m) = @_;
294    if ($m->log_to_class_file) {
295        return BarnOwl::getvar('classlogging') eq 'on';
296    } else {
297        return BarnOwl::getvar('logging') eq 'on';
298    }
299}
300
[ee183be]3011;
Note: See TracBrowser for help on using the repository browser.