source: perl/lib/BarnOwl/Logging.pm @ 45e137c

Last change on this file since 45e137c was 45e137c, checked in by Jason Gross <jgross@mit.edu>, 7 years ago
Replace initial . with _ This is so that, e.g., we won't write to .git, .gitconfig, etc.
  • Property mode set to 100644
File size: 9.4 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 in their default state."
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 AIM, zephyr, or other protocols.  If disabled BarnOwl will not print\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 will be logged."
95        });
96
97    BarnOwl::new_variable_string('logbasepath',
98        {
99            default       => '~/zlog',
100            validsettings => '<path>',
101            summary       => 'path for logging non-zephyr messages',
102            description   => "Specifies a directory which must exist.\n"
103                           . "Each non-zephyr protocol gets its own subdirectory in\n"
104                           . "logbasepath, and messages get logged there.  Note that\n"
105                           . "if the directory logbasepath/\$protocol does not exist,\n"
106                           . "logging will fail for \$protocol."
107        });
108
109    BarnOwl::new_variable_string('logpath',
110        {
111            default       => '~/zlog/people',
112            validsettings => '<path>',
113            summary       => 'path for logging personal messages',
114            description   => "Specifies a directory which must exist.\n"
115                            . "Files will be created in the directory for each sender."
116        });
117
118    BarnOwl::new_variable_string('classlogpath',
119        {
120            default       => '~/zlog/class',
121            validsettings => '<path>',
122            summary       => 'path for logging class zephyrs',
123            description   => "Specifies a directory which must exist.\n"
124                           . "Files will be created in the directory for each class."
125        });
126
127    BarnOwl::new_variable_bool('log-to-subdirectories',
128        {
129            default     => 0,
130            summary     => "log each protocol to its own subdirectory of logbasepath",
131            description => "When this is enabled, BarnOwl will log each protocol to its own\n"
132                         . "subdirectory of logbasepath.  When this is disabled, BarnOwl will\n"
133                         . "instead log all non-zephyr non-loopback messages to the logpath,\n"
134                         . "and prefix each filename with what would otherwise be the subdirectory\n"
135                         . "name.\n\n"
136                         . "If you enable this, be sure that the relevant directories exist;\n"
137                         . "BarnOwl will not create them for you."
138        });
139
140}
141
142=head2 sanitize_filename BASE_PATH FILENAME
143
144Sanitizes C<FILENAME> and concatenates it with C<BASE_PATH>.
145
146In any filename, C<"/">, any control characters (characters which
147match C<[:cntrl:]>), and any initial C<"."> characters get replaced by
148underscores.  If the resulting filename is empty, it is replaced with
149C<"_EMPTY_">.
150
151=cut
152
153sub sanitize_filename {
154    my $base_path = BarnOwl::Internal::makepath(shift);
155    my $filename = shift;
156    $filename =~ s/[[:cntrl:]\/]/_/g;
157    $filename =~ s/^\./_/g; # handle ., .., and hidden files
158    $filename = '_EMPTY_' if $filename eq '';
159    # The original C code also removed characters less than '!' and
160    # greater than or equal to '~', marked file names beginning with a
161    # non-alphanumeric or non-ASCII character as 'weird', and rejected
162    # filenames longer than 35 characters.
163    return File::Spec->catfile($base_path, $filename);
164}
165
166=head2 get_filenames MESSAGE
167
168Returns a list of filenames in which to log the passed message.
169
170This method calls C<log_filenames> on C<MESSAGE> to determine the list
171of filenames to which C<MESSAGE> gets logged.  All filenames are
172relative to C<MESSAGE->log_path>.  If C<MESSAGE->log_to_all_file>
173returns true, then the filename C<"all"> is appended to the list of
174filenames.
175
176Filenames are sanitized by C<sanitize_filename>.
177
178=cut
179
180sub get_filenames {
181    my ($m) = @_;
182    my @filenames = $m->log_filenames;
183    push @filenames, 'all' if $m->log_to_all_file;
184    return map { sanitize_filename($m->log_path, $_) } @filenames;
185}
186
187=head2 should_log_message MESSAGE
188
189Determines whether or not the passed message should be logged.
190
191To customize the behavior of this method, override
192L<BarnOwl::Message::should_log>.
193
194=cut
195
196sub should_log_message {
197    my ($m) = @_;
198    # If there's a logfilter and this message matches it, log.
199    # pass quiet=1, because we don't care if the filter doesn't exist
200    return 1 if BarnOwl::message_matches_filter($m, BarnOwl::getvar('logfilter'), 1);
201    # otherwise we do things based on the logging variables
202    # skip login/logout messages if appropriate
203    return 0 if $m->is_loginout && BarnOwl::getvar('loglogins') eq 'off';
204    # check direction
205    return 0 if $m->is_outgoing && BarnOwl::getvar('loggingdirection') eq 'in';
206    return 0 if $m->is_incoming && BarnOwl::getvar('loggingdirection') eq 'out';
207    return $m->should_log;
208}
209
210=head2 log MESSAGE
211
212Call this method to (potentially) log a message.
213
214To customize the behavior of this method for your messages, override
215L<BarnOwl::Message::log>, L<BarnOwl::Message::should_log>,
216L<BarnOwl::Message::log_base_path>, and/or
217L<BarnOwl::Message::log_filenames>.
218
219=cut
220
221sub log {
222    my ($m) = @_;
223    return unless defined $m;
224    return unless BarnOwl::Logging::should_log_message($m);
225    my $log_text = $m->log;
226    foreach my $filename (BarnOwl::Logging::get_filenames($m)) {
227        BarnOwl::Logging::enqueue_text($log_text, $filename);
228    }
229}
230
231=head2 log_outgoing_error MESSAGE
232
233Call this method to (potentially) log an error in sending an
234outgoing message.  Errors get logged to the same file(s) as
235successful messages.
236
237To customize the behavior of this method for your messages, override
238L<BarnOwl::Message::log_outgoing_error>,
239L<BarnOwl::Message::should_log>,
240L<BarnOwl::Message::log_base_path>, and/or
241L<BarnOwl::Message::log_filenames>.
242
243=cut
244
245sub log_outgoing_error {
246    my ($m) = @_;
247    return unless BarnOwl::Logging::should_log_message($m);
248    my $log_text = $m->log_outgoing_error;
249    foreach my $filename (BarnOwl::Logging::get_filenames($m)) {
250        BarnOwl::Logging::enqueue_text($log_text, $filename);
251    }
252}
253
2541;
Note: See TracBrowser for help on using the repository browser.