source: perl/lib/BarnOwl/Logging.pm @ 5dee79a

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