• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

processone / ejabberd / 1296

19 Jan 2026 11:25AM UTC coverage: 33.562% (+0.09%) from 33.468%
1296

push

github

badlop
mod_conversejs: Cosmetic change: sort paths alphabetically

0 of 4 new or added lines in 1 file covered. (0.0%)

11245 existing lines in 174 files now uncovered.

15580 of 46421 relevant lines covered (33.56%)

1074.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.41
/src/mod_antispam_dump.erl
1
%%%----------------------------------------------------------------------
2
%%% File    : mod_antispam_dump.erl
3
%%% Author  : Holger Weiss <holger@zedat.fu-berlin.de>
4
%%% Author  : Stefan Strigler <stefan@strigler.de>
5
%%% Purpose : Manage dump file for filtered spam messages
6
%%% Created : 31 Mar 2019 by Holger Weiss <holger@zedat.fu-berlin.de>
7
%%%
8
%%%
9
%%% ejabberd, Copyright (C) 2019-2026 ProcessOne
10
%%%
11
%%% This program is free software; you can redistribute it and/or
12
%%% modify it under the terms of the GNU General Public License as
13
%%% published by the Free Software Foundation; either version 2 of the
14
%%% License, or (at your option) any later version.
15
%%%
16
%%% This program is distributed in the hope that it will be useful,
17
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
18
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19
%%% General Public License for more details.
20
%%%
21
%%% You should have received a copy of the GNU General Public License along
22
%%% with this program; if not, write to the Free Software Foundation, Inc.,
23
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
%%%
25
%%%----------------------------------------------------------------------
26

27
%%| Definitions
28
%% @format-begin
29

30
-module(mod_antispam_dump).
31

32
-author('holger@zedat.fu-berlin.de').
33
-author('stefan@strigler.de').
34

35
-export([init_dumping/1, terminate_dumping/2, reload_dumping/4, reopen_dump_file/2,
36
         write_stanza_dump/2]).
37
%% ejabberd_hooks callbacks
38
-export([dump_spam_stanza/1, reopen_log/0]).
39

40
-include("logger.hrl").
41
-include("mod_antispam.hrl").
42
-include("translate.hrl").
43

44
-include_lib("xmpp/include/xmpp.hrl").
45

46
%%--------------------------------------------------------------------
47
%%| Exported
48

49
init_dumping(Host) ->
UNCOV
50
    case get_path_option(Host) of
2✔
51
        false ->
52
            undefined;
×
53
        DumpFile when is_binary(DumpFile) ->
UNCOV
54
            case filelib:ensure_dir(DumpFile) of
2✔
55
                ok ->
UNCOV
56
                    ejabberd_hooks:add(spam_stanza_rejected, Host, ?MODULE, dump_spam_stanza, 50),
2✔
UNCOV
57
                    ejabberd_hooks:add(reopen_log_hook, ?MODULE, reopen_log, 50),
2✔
UNCOV
58
                    open_dump_file(DumpFile);
2✔
59
                {error, Reason} ->
60
                    Dirname = filename:dirname(DumpFile),
×
61
                    throw({open, Dirname, Reason})
×
62
            end
63
    end.
64

65
terminate_dumping(_Host, false) ->
66
    ok;
×
67
terminate_dumping(Host, Fd) ->
UNCOV
68
    DumpFile1 = get_path_option(Host),
2✔
UNCOV
69
    close_dump_file(Fd, DumpFile1),
2✔
UNCOV
70
    ejabberd_hooks:delete(spam_stanza_rejected, Host, ?MODULE, dump_spam_stanza, 50),
2✔
UNCOV
71
    case gen_mod:is_loaded_elsewhere(Host, ?MODULE) of
2✔
72
        false ->
UNCOV
73
            ejabberd_hooks:delete(reopen_log_hook, ?MODULE, reopen_log, 50);
2✔
74
        true ->
75
            ok
×
76
    end.
77

78
reload_dumping(Host, Fd, OldOpts, NewOpts) ->
UNCOV
79
    case {get_path_option(Host, OldOpts), get_path_option(Host, NewOpts)} of
4✔
80
        {Old, Old} ->
UNCOV
81
            Fd;
4✔
82
        {Old, New} ->
83
            reopen_dump_file(Fd, Old, New)
×
84
    end.
85

86
-spec reopen_dump_file(binary(), file:io_device()) -> file:io_device().
87
reopen_dump_file(Host, Fd) ->
88
    DumpFile1 = get_path_option(Host),
×
89
    reopen_dump_file(Fd, DumpFile1, DumpFile1).
×
90

91
%%--------------------------------------------------------------------
92
%%| Hook callbacks
93

94
-spec dump_spam_stanza(message()) -> ok.
95
dump_spam_stanza(#message{to = #jid{lserver = LServer}} = Msg) ->
UNCOV
96
    By = jid:make(<<>>, LServer),
16✔
UNCOV
97
    Proc = get_proc_name(LServer),
16✔
UNCOV
98
    Time = erlang:timestamp(),
16✔
UNCOV
99
    Msg1 = misc:add_delay_info(Msg, By, Time),
16✔
UNCOV
100
    XML = fxml:element_to_binary(
16✔
101
              xmpp:encode(Msg1)),
UNCOV
102
    gen_server:cast(Proc, {dump_stanza, XML}).
16✔
103

104
-spec reopen_log() -> ok.
105
reopen_log() ->
106
    lists:foreach(fun(Host) ->
×
107
                     Proc = get_proc_name(Host),
×
108
                     gen_server:cast(Proc, reopen_log)
×
109
                  end,
110
                  get_spam_filter_hosts()).
111

112
%%--------------------------------------------------------------------
113
%%| File management
114

115
-spec open_dump_file(filename()) -> undefined | file:io_device().
116
open_dump_file(false) ->
117
    undefined;
×
118
open_dump_file(Name) ->
UNCOV
119
    Modes = [append, raw, binary, delayed_write],
2✔
UNCOV
120
    case file:open(Name, Modes) of
2✔
121
        {ok, Fd} ->
UNCOV
122
            ?DEBUG("Opened ~s", [Name]),
2✔
UNCOV
123
            Fd;
2✔
124
        {error, Reason} ->
125
            ?ERROR_MSG("Cannot open dump file ~s: ~s", [Name, file:format_error(Reason)]),
×
126
            undefined
×
127
    end.
128

129
-spec close_dump_file(undefined | file:io_device(), filename()) -> ok.
130
close_dump_file(undefined, false) ->
131
    ok;
×
132
close_dump_file(Fd, Name) ->
UNCOV
133
    case file:close(Fd) of
2✔
134
        ok ->
UNCOV
135
            ?DEBUG("Closed ~s", [Name]);
2✔
136
        {error, Reason} ->
137
            ?ERROR_MSG("Cannot close ~s: ~s", [Name, file:format_error(Reason)])
×
138
    end.
139

140
-spec reopen_dump_file(file:io_device(), binary(), binary()) -> file:io_device().
141
reopen_dump_file(Fd, OldDumpFile, NewDumpFile) ->
142
    close_dump_file(Fd, OldDumpFile),
×
143
    open_dump_file(NewDumpFile).
×
144

145
write_stanza_dump(Fd, XML) ->
UNCOV
146
    case file:write(Fd, [XML, <<$\n>>]) of
16✔
147
        ok ->
UNCOV
148
            ok;
16✔
149
        {error, Reason} ->
150
            ?ERROR_MSG("Cannot write spam to dump file: ~s", [file:format_error(Reason)])
×
151
    end.
152

153
%%--------------------------------------------------------------------
154
%%| Auxiliary
155

156
get_path_option(Host) ->
UNCOV
157
    Opts = gen_mod:get_module_opts(Host, ?MODULE_ANTISPAM),
4✔
UNCOV
158
    get_path_option(Host, Opts).
4✔
159

160
get_path_option(Host, Opts) ->
UNCOV
161
    case gen_mod:get_opt(spam_dump_file, Opts) of
12✔
162
        false ->
163
            false;
×
164
        true ->
165
            LogDirPath =
×
166
                iolist_to_binary(filename:dirname(
167
                                     ejabberd_logger:get_log_path())),
168
            filename:join([LogDirPath, <<"spam_dump_", Host/binary, ".log">>]);
×
169
        B when is_binary(B) ->
UNCOV
170
            B
12✔
171
    end.
172

173
%%--------------------------------------------------------------------
174
%%| Copied from mod_antispam.erl
175

176
-spec get_proc_name(binary()) -> atom().
177
get_proc_name(Host) ->
UNCOV
178
    gen_mod:get_module_proc(Host, ?MODULE_ANTISPAM).
16✔
179

180
-spec get_spam_filter_hosts() -> [binary()].
181
get_spam_filter_hosts() ->
182
    [H || H <- ejabberd_option:hosts(), gen_mod:is_loaded(H, ?MODULE_ANTISPAM)].
×
183

184
%%--------------------------------------------------------------------
185

186
%%| vim: set foldmethod=marker foldmarker=%%|,%%-:
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc