source: perl/lib/BarnOwl/Logging.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: 9.5 KB
Line 
1use strict;
2use warnings;
3
4package BarnOwl::Logging;
5
6=head1 BarnOwl::Logging
7
8=head1 DESCRIPTION
9
10C<BarnOwl::Logging> implements the internals of logging.  All customizations
11to logging should be done in the appropriate subclass of L<BarnOwl::Message>.
12
13=head2 USAGE
14
15Modules wishing to customize how messages are logged should override the
16relevant subroutines in the appropriate subclass of L<BarnOwl::Message>.
17
18Modules wishing to log errors sending outgoing messages should call
19L<BarnOwl::Logging::log_outgoing_error> with the message that failed
20to be sent.
21
22=head2 EXPORTS
23
24None by default.
25
26=cut
27
28use Exporter;
29
30our @EXPORT_OK = qw();
31
32our %EXPORT_TAGS = (all => [@EXPORT_OK]);
33
34use File::Spec;
35
36$BarnOwl::Hooks::newMessage->add("BarnOwl::Logging::log");
37$BarnOwl::Hooks::startup->add("BarnOwl::Logging::_register_variables");
38
39sub _register_variables {
40    BarnOwl::new_variable_bool('logging',
41        {
42            default     => 0,
43            summary     => 'turn personal logging on or off',
44            description => "If this is set to on, personal messages are\n"
45                         . "logged in the directory specified\n"
46                         . "by the 'logpath' variable.  The filename in that\n"
47                         . "directory is derived from the sender of the message."
48        });
49
50    BarnOwl::new_variable_bool('classlogging',
51        {
52            default     => 0,
53            summary     => 'turn class logging on or off',
54            description => "If this is set to on, class messages are\n"
55                         . "logged in the directory specified by the\n"
56                         . "'classpath' variable.  The filename in that\n"
57                         . "directory is derived from the class to which\n"
58                         . "the message was sent."
59        });
60
61    BarnOwl::new_variable_string('logfilter',
62        {
63            default     => '',
64            summary     => 'name of a filter controlling which messages to log',
65            description => "If non empty, any messages matching the given filter will be logged.\n"
66                         . "This is a completely separate mechanism from the other logging\n"
67                         . "variables like logging, classlogging, loglogins, loggingdirection,\n"
68                         . "etc.  If you want this variable to control all logging, make sure\n"
69                         . "all other logging variables are left off (the default)."
70        });
71
72    BarnOwl::new_variable_bool('loglogins',
73        {
74            default     => 0,
75            summary     => 'enable logging of login notifications',
76            description => "When this is enabled, BarnOwl will log login and logout notifications\n"
77                         . "for zephyr or other protocols.  If disabled BarnOwl will not log\n"
78                         . "login or logout notifications."
79        });
80
81    BarnOwl::new_variable_enum('loggingdirection',
82        {
83            default       => 'both',
84            validsettings => [qw(in out both)],
85            summary       => "specifies which kind of messages should be logged",
86            description   => "Can be one of 'both', 'in', or 'out'.  If 'in' is\n"
87                           . "selected, only incoming messages are logged, if 'out'\n"
88                           . "is selected only outgoing messages are logged.  If 'both'\n"
89                           . "is selected both incoming and outgoing messages are\n"
90                           . "logged.\n\n"
91                           . "Note that this variable applies to all messages. In\n"
92                           . "particular, if this variable is set to 'out', the\n"
93                           . "classlogging variable will have no effect, and no\n"
94                           . "class messages (which are always incoming) will be\n"
95                           . "logged."
96        });
97
98    BarnOwl::new_variable_string('logbasepath',
99        {
100            default       => '~/zlog',
101            validsettings => '<path>',
102            summary       => 'path for logging non-zephyr messages',
103            description   => "Specifies a directory which must exist.\n"
104                           . "Each non-zephyr protocol gets its own subdirectory in\n"
105                           . "logbasepath, and messages get logged there.  Note that\n"
106                           . "if the directory logbasepath/\$protocol does not exist,\n"
107                           . "logging will fail for \$protocol."
108        });
109
110    BarnOwl::new_variable_string('logpath',
111        {
112            default       => '~/zlog/people',
113            validsettings => '<path>',
114            summary       => 'path for logging personal messages',
115            description   => "Specifies a directory which must exist.\n"
116                            . "Files will be created in the directory for each sender."
117        });
118
119    BarnOwl::new_variable_string('classlogpath',
120        {
121            default       => '~/zlog/class',
122            validsettings => '<path>',
123            summary       => 'path for logging class zephyrs',
124            description   => "Specifies a directory which must exist.\n"
125                           . "Files will be created in the directory for each class."
126        });
127
128    BarnOwl::new_variable_bool('log-to-subdirectories',
129        {
130            default     => 0,
131            summary     => "log each protocol to its own subdirectory of logbasepath",
132            description => "When this is enabled, BarnOwl will log each protocol to its own\n"
133                         . "subdirectory of logbasepath.  When this is disabled, BarnOwl will\n"
134                         . "instead log all non-zephyr non-loopback messages to the logpath,\n"
135                         . "and prefix each filename with what would otherwise be the subdirectory\n"
136                         . "name.\n\n"
137                         . "If you enable this, be sure that the relevant directories exist;\n"
138                         . "BarnOwl will not create them for you."
139        });
140
141}
142
143=head2 sanitize_filename BASE_PATH FILENAME
144
145Sanitizes C<FILENAME> and concatenates it with C<BASE_PATH>.
146
147In any filename, C<"/">, any control characters (characters which
148match C<[:cntrl:]>), and any initial C<"."> characters get replaced by
149underscores.  If the resulting filename is empty, it is replaced with
150C<"_EMPTY_">.
151
152=cut
153
154sub sanitize_filename {
155    my $base_path = BarnOwl::Internal::makepath(shift);
156    my $filename = shift;
157    $filename =~ s/[[:cntrl:]\/]/_/g;
158    $filename =~ s/^\./_/g; # handle ., .., and hidden files
159    $filename = '_EMPTY_' if $filename eq '';
160    # The original C code also removed characters less than '!' and
161    # greater than or equal to '~', marked file names beginning with a
162    # non-alphanumeric or non-ASCII character as 'weird', and rejected
163    # filenames longer than 35 characters.
164    return File::Spec->catfile($base_path, $filename);
165}
166
167=head2 get_filenames MESSAGE
168
169Returns a list of filenames in which to log the passed message.
170
171This method calls C<log_filenames> on C<MESSAGE> to determine the list
172of filenames to which C<MESSAGE> gets logged.  All filenames are
173relative to C<MESSAGE->log_path>.  If C<MESSAGE->log_to_all_file>
174returns true, then the filename C<"all"> is appended to the list of
175filenames.
176
177Filenames are sanitized by C<sanitize_filename>.
178
179=cut
180
181sub get_filenames {
182    my ($m) = @_;
183    my @filenames = $m->log_filenames;
184    push @filenames, 'all' if $m->log_to_all_file;
185    return map { sanitize_filename($m->log_path, $_) } @filenames;
186}
187
188=head2 should_log_message MESSAGE
189
190Determines whether or not the passed message should be logged.
191
192To customize the behavior of this method, override
193L<BarnOwl::Message::should_log>.
194
195=cut
196
197sub should_log_message {
198    my ($m) = @_;
199    # If there's a logfilter and this message matches it, log.
200    # pass quiet=1, because we don't care if the filter doesn't exist
201    return 1 if BarnOwl::message_matches_filter($m, BarnOwl::getvar('logfilter'), 1);
202    # otherwise we do things based on the logging variables
203    # skip login/logout messages if appropriate
204    return 0 if $m->is_loginout && BarnOwl::getvar('loglogins') eq 'off';
205    # check direction
206    return 0 if $m->is_outgoing && BarnOwl::getvar('loggingdirection') eq 'in';
207    return 0 if $m->is_incoming && BarnOwl::getvar('loggingdirection') eq 'out';
208    return $m->should_log;
209}
210
211=head2 log MESSAGE
212
213Call this method to (potentially) log a message.
214
215To customize the behavior of this method for your messages, override
216L<BarnOwl::Message::log>, L<BarnOwl::Message::should_log>,
217L<BarnOwl::Message::log_base_path>, and/or
218L<BarnOwl::Message::log_filenames>.
219
220=cut
221
222sub log {
223    my ($m) = @_;
224    return unless defined $m;
225    return unless BarnOwl::Logging::should_log_message($m);
226    my $log_text = $m->log;
227    foreach my $filename (BarnOwl::Logging::get_filenames($m)) {
228        BarnOwl::Logging::enqueue_text($log_text, $filename);
229    }
230}
231
232=head2 log_outgoing_error MESSAGE
233
234Call this method to (potentially) log an error in sending an
235outgoing message.  Errors get logged to the same file(s) as
236successful messages.
237
238To customize the behavior of this method for your messages, override
239L<BarnOwl::Message::log_outgoing_error>,
240L<BarnOwl::Message::should_log>,
241L<BarnOwl::Message::log_base_path>, and/or
242L<BarnOwl::Message::log_filenames>.
243
244=cut
245
246sub log_outgoing_error {
247    my ($m) = @_;
248    return unless BarnOwl::Logging::should_log_message($m);
249    my $log_text = $m->log_outgoing_error;
250    foreach my $filename (BarnOwl::Logging::get_filenames($m)) {
251        BarnOwl::Logging::enqueue_text($log_text, $filename);
252    }
253}
254
2551;
Note: See TracBrowser for help on using the repository browser.