From 046546efc084fcf551dfc1260e464761437b78cc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Arkadiusz=20Mi=C5=9Bkiewicz?= Date: Tue, 6 May 2014 11:49:25 +0200 Subject: [PATCH] - rel 2; enable mod_logdb again --- ejabberd-mod_logdb.patch | 1776 ++++++++++++++++++++------------------ ejabberd.spec | 10 +- 2 files changed, 950 insertions(+), 836 deletions(-) diff --git a/ejabberd-mod_logdb.patch b/ejabberd-mod_logdb.patch index db65297..b8b0c65 100644 --- a/ejabberd-mod_logdb.patch +++ b/ejabberd-mod_logdb.patch @@ -1,8 +1,156 @@ -diff --git src/gen_logdb.erl src/gen_logdb.erl +diff --git a/priv/msgs/nl.msg b/priv/msgs/nl.msg +index 70e739f..76df8cf 100644 +--- a/priv/msgs/nl.msg ++++ b/priv/msgs/nl.msg +@@ -419,3 +419,17 @@ + {"Your Jabber account was successfully created.","Uw Jabber-account is succesvol gecreeerd."}. + {"Your Jabber account was successfully deleted.","Uw Jabber-account is succesvol verwijderd."}. + {"Your messages to ~s are being blocked. To unblock them, visit ~s","Uw berichten aan ~s worden geblokkeerd. Om ze te deblokkeren, ga naar ~s"}. ++% mod_logdb ++{"Users Messages", "Gebruikersberichten"}. ++{"Date", "Datum"}. ++{"Count", "Aantal"}. ++{"Logged messages for ~s", "Gelogde berichten van ~s"}. ++{"Logged messages for ~s at ~s", "Gelogde berichten van ~s op ~s"}. ++{" at ", " op "}. ++{"No logged messages for ~s", "Geen gelogde berichten van ~s"}. ++{"No logged messages for ~s at ~s", "Geen gelogde berichten van ~s op ~s"}. ++{"Date, Time", "Datum en tijd"}. ++{"Direction: Jid", "Richting: Jabber ID"}. ++{"Subject", "Onderwerp"}. ++{"Body", "Berichtveld"}. ++{"Messages", "Berichten"}. +diff --git a/priv/msgs/pl.msg b/priv/msgs/pl.msg +index 4bc2063..7540386 100644 +--- a/priv/msgs/pl.msg ++++ b/priv/msgs/pl.msg +@@ -419,3 +419,29 @@ + {"Your Jabber account was successfully created.","Twoje konto zostało stworzone."}. + {"Your Jabber account was successfully deleted.","Twoje konto zostało usunięte."}. + {"Your messages to ~s are being blocked. To unblock them, visit ~s","Twoje wiadomości do ~s są blokowane. Aby je odblokować, odwiedź ~s"}. ++% mod_logdb ++{"Users Messages", "Wiadomości użytkownika"}. ++{"Date", "Data"}. ++{"Count", "Liczba"}. ++{"Logged messages for ~s", "Zapisane wiadomości dla ~s"}. ++{"Logged messages for ~s at", "Zapisane wiadomości dla ~s o ~s"}. ++{" at ", " o "}. ++{"No logged messages for ~s", "Brak zapisanych wiadomości dla ~s"}. ++{"No logged messages for ~s at ~s", "Brak zapisanych wiadomości dla ~s o ~s"}. ++{"Date, Time", "Data, Godzina"}. ++{"Direction: Jid", "Kierunek: Jid"}. ++{"Subject", "Temat"}. ++{"Body", "Treść"}. ++{"Messages","Wiadomości"}. ++{"Filter Selected", "Odfiltruj zaznaczone"}. ++{"Do Not Log Messages", "Nie zapisuj wiadomości"}. ++{"Log Messages", "Zapisuj wiadomości"}. ++{"Messages logging engine", "System zapisywania historii rozmów"}. ++{"Default", "Domyślne"}. ++{"Set logging preferences", "Ustaw preferencje zapisywania"}. ++{"Messages logging engine settings", "Ustawienia systemu logowania"}. ++{"Set run-time settings", "Zapisz ustawienia systemu logowania"}. ++{"Groupchat messages logging", "Zapisywanie rozmów z konferencji"}. ++{"Jids/Domains to ignore", "JID/Domena która ma być ignorowana"}. ++{"Purge messages older than (days)", "Usuń wiadomości starsze niż (w dniach)"}. ++{"Poll users settings (seconds)", "Czas aktualizacji preferencji użytkowników (sekundy)"}. +diff --git a/priv/msgs/ru.msg b/priv/msgs/ru.msg +index ece7348..b159f98 100644 +--- a/priv/msgs/ru.msg ++++ b/priv/msgs/ru.msg +@@ -419,3 +419,33 @@ + {"Your Jabber account was successfully created.","Ваш Jabber-аккаунт был успешно создан."}. + {"Your Jabber account was successfully deleted.","Ваш Jabber-аккаунт был успешно удален."}. + {"Your messages to ~s are being blocked. To unblock them, visit ~s","Ваши сообщения к ~s блокируются. Для снятия блокировки перейдите по ссылке ~s"}. ++% mod_logdb.erl ++{"Users Messages", "Сообщения пользователей"}. ++{"Date", "Дата"}. ++{"Count", "Количество"}. ++{"Logged messages for ~s", "Сохранённые cообщения для ~s"}. ++{"Logged messages for ~s at ~s", "Сохранённые cообщения для ~s за ~s"}. ++{" at ", " за "}. ++{"No logged messages for ~s", "Отсутствуют сообщения для ~s"}. ++{"No logged messages for ~s at ~s", "Отсутствуют сообщения для ~s за ~s"}. ++{"Date, Time", "Дата, Время"}. ++{"Direction: Jid", "Направление: Jid"}. ++{"Subject", "Тема"}. ++{"Body", "Текст"}. ++{"Messages", "Сообщения"}. ++{"Filter Selected", "Отфильтровать выделенные"}. ++{"Do Not Log Messages", "Не сохранять сообщения"}. ++{"Log Messages", "Сохранять сообщения"}. ++{"Messages logging engine", "Система логирования сообщений"}. ++{"Default", "По умолчанию"}. ++{"Set logging preferences", "Задайте настройки логирования"}. ++{"Messages logging engine users", "Пользователи системы логирования сообщений"}. ++{"Messages logging engine settings", "Настройки системы логирования сообщений"}. ++{"Set run-time settings", "Задайте текущие настройки"}. ++{"Groupchat messages logging", "Логирование сообщений типа groupchat"}. ++{"Jids/Domains to ignore", "Игнорировать следующие jids/домены"}. ++{"Purge messages older than (days)", "Удалять сообщения старее чем (дни)"}. ++{"Poll users settings (seconds)", "Обновлять настройки пользователей через (секунд)"}. ++{"Drop", "Удалять"}. ++{"Do not drop", "Не удалять"}. ++{"Drop messages on user removal", "Удалять сообщения при удалении пользователя"}. +diff --git a/priv/msgs/uk.msg b/priv/msgs/uk.msg +index 6e21c90..9838624 100644 +--- a/priv/msgs/uk.msg ++++ b/priv/msgs/uk.msg +@@ -407,3 +407,33 @@ + {"Your Jabber account was successfully created.","Ваш Jabber-акаунт було успішно створено."}. + {"Your Jabber account was successfully deleted.","Ваш Jabber-акаунт було успішно видалено."}. + {"Your messages to ~s are being blocked. To unblock them, visit ~s","Ваші повідомлення до ~s блокуються. Для розблокування відвідайте ~s"}. ++% mod_logdb ++{"Users Messages", "Повідомлення користувачів"}. ++{"Date", "Дата"}. ++{"Count", "Кількість"}. ++{"Logged messages for ~s", "Збережені повідомлення для ~s"}. ++{"Logged messages for ~s at ~s", "Збережені повідомлення для ~s за ~s"}. ++{" at ", " за "}. ++{"No logged messages for ~s", "Відсутні повідомлення для ~s"}. ++{"No logged messages for ~s at ~s", "Відсутні повідомлення для ~s за ~s"}. ++{"Date, Time", "Дата, Час"}. ++{"Direction: Jid", "Напрямок: Jid"}. ++{"Subject", "Тема"}. ++{"Body", "Текст"}. ++{"Messages", "Повідомлення"}. ++{"Filter Selected", "Відфільтрувати виділені"}. ++{"Do Not Log Messages", "Не зберігати повідомлення"}. ++{"Log Messages", "Зберігати повідомлення"}. ++{"Messages logging engine", "Система збереження повідомлень"}. ++{"Default", "За замовчуванням"}. ++{"Set logging preferences", "Вкажіть налагоджування збереження повідомлень"}. ++{"Messages logging engine users", "Користувачі системи збереження повідомлень"}. ++{"Messages logging engine settings", "Налагоджування системи збереження повідомлень"}. ++{"Set run-time settings", "Вкажіть поточні налагоджування"}. ++{"Groupchat messages logging", "Збереження повідомлень типу groupchat"}. ++{"Jids/Domains to ignore", "Ігнорувати наступні jids/домени"}. ++{"Purge messages older than (days)", "Видаляти повідомлення старіші ніж (дні)"}. ++{"Poll users settings (seconds)", "Оновлювати налагоджування користувачів кожні (секунд)"}. ++{"Drop", "Видаляти"}. ++{"Do not drop", "Не видаляти"}. ++{"Drop messages on user removal", "Видаляти повідомлення під час видалення користувача"}. +diff --git a/rebar.config.script b/rebar.config.script +index f342a6c..2ad3f1f 100644 +--- a/rebar.config.script ++++ b/rebar.config.script +@@ -81,9 +81,9 @@ PostHooks = [ConfigureCmd("p1_tls", ""), + + CfgDeps = lists:flatmap( + fun({mysql, true}) -> +- [{p1_mysql, ".*", {git, "git://github.com/processone/mysql"}}]; ++ [{p1_mysql, ".*", {git, "git://github.com/paleg/mysql", {branch, "multi"}}}]; + ({pgsql, true}) -> +- [{p1_pgsql, ".*", {git, "git://github.com/processone/pgsql"}}]; ++ [{p1_pgsql, ".*", {git, "git://github.com/paleg/pgsql", {branch, "errordescr_fix"}}}]; + ({pam, true}) -> + [{p1_pam, ".*", {git, "git://github.com/processone/epam"}}]; + ({zlib, true}) -> +diff --git a/src/gen_logdb.erl b/src/gen_logdb.erl new file mode 100644 index 0000000..06a894b --- /dev/null -+++ src/gen_logdb.erl ++++ b/src/gen_logdb.erl @@ -0,0 +1,164 @@ +%%%---------------------------------------------------------------------- +%%% File : gen_logdb.erl @@ -168,12 +316,12 @@ index 0000000..06a894b + ]; +behaviour_info(_) -> + undefined. -diff --git src/mod_logdb.erl src/mod_logdb.erl +diff --git a/src/mod_logdb.erl b/src/mod_logdb.erl new file mode 100644 -index 0000000..7de346f +index 0000000..516f92b --- /dev/null -+++ src/mod_logdb.erl -@@ -0,0 +1,2087 @@ ++++ b/src/mod_logdb.erl +@@ -0,0 +1,2152 @@ +%%%---------------------------------------------------------------------- +%%% File : mod_logdb.erl +%%% Author : Oleg Palij (mailto,xmpp:o.palij@gmail.com) @@ -241,8 +389,9 @@ index 0000000..7de346f +-include("jlib.hrl"). +-include("ejabberd_ctl.hrl"). +-include("adhoc.hrl"). -+-include("web/ejabberd_web_admin.hrl"). -+-include("web/ejabberd_http.hrl"). ++-include("ejabberd_web_admin.hrl"). ++-include("ejabberd_http.hrl"). ++-include("logger.hrl"). + +-define(PROCNAME, ejabberd_mod_logdb). +% gen_server call timeout @@ -250,7 +399,7 @@ index 0000000..7de346f + +-record(state, {vhost, dbmod, backendPid, monref, purgeRef, pollRef, dbopts, dbs, dolog_default, ignore_jids, groupchat, purge_older_days, poll_users_settings, drop_messages_on_user_removal}). + -+ets_settings_table(VHost) -> list_to_atom("ets_logdb_settings_" ++ VHost). ++ets_settings_table(VHost) -> list_to_atom("ets_logdb_settings_" ++ binary_to_list(VHost)). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% @@ -277,17 +426,32 @@ index 0000000..7de346f + {ok, Pid}. + +init([VHost, Opts]) -> -+ ?MYDEBUG("Starting mod_logdb", []), + process_flag(trap_exit, true), -+ DBs = gen_mod:get_opt(dbs, Opts, [{mnesia, []}]), -+ VHostDB = gen_mod:get_opt(vhosts, Opts, [{VHost, mnesia}]), ++ DBsRaw = gen_mod:get_opt(dbs, Opts, fun(A) -> A end, [{mnesia, []}]), ++ DBs = case lists:keysearch(mnesia, 1, DBsRaw) of ++ false -> lists:append(DBsRaw, [{mnesia,[]}]); ++ DBsResult -> DBsResult ++ end, ++ VHostDB = gen_mod:get_opt(vhosts, Opts, fun(A) -> A end, [{VHost, mnesia}]), + % 10 is default becouse of using in clustered environment -+ PollUsersSettings = gen_mod:get_opt(poll_users_settings, Opts, 10), ++ PollUsersSettings = gen_mod:get_opt(poll_users_settings, Opts, fun(A) -> A end, 10), + -+ {value,{_, DBName}} = lists:keysearch(VHost, 1, VHostDB), -+ {value, {DBName, DBOpts}} = lists:keysearch(DBName, 1, DBs), ++ {DBName, DBOpts} = ++ case lists:keysearch(VHost, 1, VHostDB) of ++ false -> ++ ?WARNING_MSG("There is no logging backend defined for '~s', switching to mnesia", [VHost]), ++ {mnesia, []}; ++ {value,{_, DBNameResult}} -> ++ case lists:keysearch(DBNameResult, 1, DBs) of ++ false -> ++ ?WARNING_MSG("There is no such logging backend '~s' defined for '~s', switching to mnesia", [DBNameResult, VHost]), ++ {mnesia, []}; ++ {value, {_, DBOptsResult}} -> ++ {DBNameResult, DBOptsResult} ++ end ++ end, + -+ ?MYDEBUG("Starting mod_logdb for ~p with ~p backend", [VHost, DBName]), ++ ?MYDEBUG("Starting mod_logdb for ~s with ~s backend", [VHost, DBName]), + + DBMod = list_to_atom(atom_to_list(?MODULE) ++ "_" ++ atom_to_list(DBName)), + @@ -296,11 +460,11 @@ index 0000000..7de346f + dbopts=DBOpts, + % dbs used for convert messages from one backend to other + dbs=DBs, -+ dolog_default=gen_mod:get_opt(dolog_default, Opts, true), -+ drop_messages_on_user_removal=gen_mod:get_opt(drop_messages_on_user_removal, Opts, true), -+ ignore_jids=gen_mod:get_opt(ignore_jids, Opts, []), -+ groupchat=gen_mod:get_opt(groupchat, Opts, none), -+ purge_older_days=gen_mod:get_opt(purge_older_days, Opts, never), ++ dolog_default=gen_mod:get_opt(dolog_default, Opts, fun(A) -> A end, true), ++ drop_messages_on_user_removal=gen_mod:get_opt(drop_messages_on_user_removal, Opts, fun(A) -> A end, true), ++ ignore_jids=gen_mod:get_opt(ignore_jids, Opts, fun(A) -> A end, []), ++ groupchat=gen_mod:get_opt(groupchat, Opts, fun(A) -> A end, none), ++ purge_older_days=gen_mod:get_opt(purge_older_days, Opts, fun(A) -> A end, never), + poll_users_settings=PollUsersSettings}}. + +cleanup(#state{vhost=VHost} = _State) -> @@ -313,14 +477,14 @@ index 0000000..7de346f + ejabberd_hooks:delete(user_receive_packet, VHost, ?MODULE, receive_packet, 90), + %ejabberd_hooks:delete(adhoc_sm_commands, VHost, ?MODULE, adhoc_sm_commands, 110), + %ejabberd_hooks:delete(adhoc_sm_items, VHost, ?MODULE, adhoc_sm_items, 110), -+ ejabberd_hooks:delete(adhoc_local_commands, VHost, ?MODULE, adhoc_local_commands, 110), -+ ejabberd_hooks:delete(adhoc_local_items, VHost, ?MODULE, adhoc_local_items, 110), -+ %ejabberd_hooks:delete(disco_sm_identity, VHost, ?MODULE, get_sm_identity, 110), -+ %ejabberd_hooks:delete(disco_sm_features, VHost, ?MODULE, get_sm_features, 110), -+ %ejabberd_hooks:delete(disco_sm_items, VHost, ?MODULE, get_sm_items, 110), -+ ejabberd_hooks:delete(disco_local_identity, VHost, ?MODULE, get_local_identity, 110), -+ ejabberd_hooks:delete(disco_local_features, VHost, ?MODULE, get_local_features, 110), -+ ejabberd_hooks:delete(disco_local_items, VHost, ?MODULE, get_local_items, 110), ++ ejabberd_hooks:delete(adhoc_local_commands, VHost, ?MODULE, adhoc_local_commands, 50), ++ ejabberd_hooks:delete(adhoc_local_items, VHost, ?MODULE, adhoc_local_items, 50), ++ %ejabberd_hooks:delete(disco_sm_identity, VHost, ?MODULE, get_sm_identity, 50), ++ %ejabberd_hooks:delete(disco_sm_features, VHost, ?MODULE, get_sm_features, 50), ++ %ejabberd_hooks:delete(disco_sm_items, VHost, ?MODULE, get_sm_items, 50), ++ ejabberd_hooks:delete(disco_local_identity, VHost, ?MODULE, get_local_identity, 50), ++ ejabberd_hooks:delete(disco_local_features, VHost, ?MODULE, get_local_features, 50), ++ ejabberd_hooks:delete(disco_local_items, VHost, ?MODULE, get_local_items, 50), + + ejabberd_hooks:delete(webadmin_menu_host, VHost, ?MODULE, webadmin_menu, 70), + ejabberd_hooks:delete(webadmin_user, VHost, ?MODULE, webadmin_user, 50), @@ -358,10 +522,10 @@ index 0000000..7de346f +% ejabberd_web_admin callbacks +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +handle_call({delete_messages_by_user_at, PMsgs, Date}, _From, #state{dbmod=DBMod, vhost=VHost}=State) -> -+ Reply = DBMod:delete_messages_by_user_at(VHost, PMsgs, Date), ++ Reply = DBMod:delete_messages_by_user_at(VHost, PMsgs, binary_to_list(Date)), + {reply, Reply, State}; +handle_call({delete_all_messages_by_user_at, User, Date}, _From, #state{dbmod=DBMod, vhost=VHost}=State) -> -+ Reply = DBMod:delete_all_messages_by_user_at(User, VHost, Date), ++ Reply = DBMod:delete_all_messages_by_user_at(binary_to_list(User), VHost, binary_to_list(Date)), + {reply, Reply, State}; +handle_call({delete_messages_at, Date}, _From, #state{dbmod=DBMod, vhost=VHost}=State) -> + Reply = DBMod:delete_messages_at(VHost, Date), @@ -370,13 +534,13 @@ index 0000000..7de346f + Reply = DBMod:get_vhost_stats(VHost), + {reply, Reply, State}; +handle_call({get_vhost_stats_at, Date}, _From, #state{dbmod=DBMod, vhost=VHost}=State) -> -+ Reply = DBMod:get_vhost_stats_at(VHost, Date), ++ Reply = DBMod:get_vhost_stats_at(VHost, binary_to_list(Date)), + {reply, Reply, State}; +handle_call({get_user_stats, User}, _From, #state{dbmod=DBMod, vhost=VHost}=State) -> -+ Reply = DBMod:get_user_stats(User, VHost), ++ Reply = DBMod:get_user_stats(binary_to_list(User), VHost), + {reply, Reply, State}; +handle_call({get_user_messages_at, User, Date}, _From, #state{dbmod=DBMod, vhost=VHost}=State) -> -+ Reply = DBMod:get_user_messages_at(User, VHost, Date), ++ Reply = DBMod:get_user_messages_at(binary_to_list(User), VHost, binary_to_list(Date)), + {reply, Reply, State}; +handle_call({get_user_settings, User}, _From, #state{dbmod=_DBMod, vhost=VHost}=State) -> + Reply = case ets:match_object(ets_settings_table(VHost), @@ -395,10 +559,9 @@ index 0000000..7de346f + case ets:match_object(ets_settings_table(VHost), + #user_settings{owner_name=User, _='_'}) of + [Set] -> -+ ?MYDEBUG("Settings is equal", []), + ok; + _ -> -+ case DBMod:set_user_settings(User, VHost, Set) of ++ case DBMod:set_user_settings(binary_to_list(User), VHost, Set) of + error -> + error; + ok -> @@ -474,7 +637,7 @@ index 0000000..7de346f +handle_cast({remove_user, User}, #state{dbmod=DBMod, vhost=VHost}=State) -> + case State#state.drop_messages_on_user_removal of + true -> -+ DBMod:drop_user(User, VHost), ++ DBMod:drop_user(binary_to_list(User), VHost), + ?INFO_MSG("Launched ~s@~s removal", [User, VHost]); + false -> + ?INFO_MSG("Message removing is disabled. Keeping messages for ~s@~s", [User, VHost]) @@ -535,7 +698,10 @@ index 0000000..7de346f + MonRef = erlang:monitor(process, SPid), + + ets:new(ets_settings_table(VHost), [named_table,public,set,{keypos, #user_settings.owner_name}]), -+ {ok, DoLog} = DBMod:get_users_settings(VHost), ++ DoLog = case DBMod:get_users_settings(VHost) of ++ {ok, Settings} -> [Sett#user_settings{owner_name = iolist_to_binary(Sett#user_settings.owner_name)} || Sett <- Settings]; ++ {error, _Reason} -> [] ++ end, + ets:insert(ets_settings_table(VHost), DoLog), + + TrefPurge = set_purge_timer(State#state.purge_older_days), @@ -545,16 +711,16 @@ index 0000000..7de346f + ejabberd_hooks:add(user_send_packet, VHost, ?MODULE, send_packet, 90), + ejabberd_hooks:add(user_receive_packet, VHost, ?MODULE, receive_packet, 90), + -+ ejabberd_hooks:add(disco_local_items, VHost, ?MODULE, get_local_items, 110), -+ ejabberd_hooks:add(disco_local_features, VHost, ?MODULE, get_local_features, 110), -+ ejabberd_hooks:add(disco_local_identity, VHost, ?MODULE, get_local_identity, 110), -+ %ejabberd_hooks:add(disco_sm_items, VHost, ?MODULE, get_sm_items, 110), -+ %ejabberd_hooks:add(disco_sm_features, VHost, ?MODULE, get_sm_features, 110), -+ %ejabberd_hooks:add(disco_sm_identity, VHost, ?MODULE, get_sm_identity, 110), -+ ejabberd_hooks:add(adhoc_local_items, VHost, ?MODULE, adhoc_local_items, 110), -+ ejabberd_hooks:add(adhoc_local_commands, VHost, ?MODULE, adhoc_local_commands, 110), -+ %ejabberd_hooks:add(adhoc_sm_items, VHost, ?MODULE, adhoc_sm_items, 110), -+ %ejabberd_hooks:add(adhoc_sm_commands, VHost, ?MODULE, adhoc_sm_commands, 110), ++ ejabberd_hooks:add(disco_local_items, VHost, ?MODULE, get_local_items, 50), ++ ejabberd_hooks:add(disco_local_features, VHost, ?MODULE, get_local_features, 50), ++ ejabberd_hooks:add(disco_local_identity, VHost, ?MODULE, get_local_identity, 50), ++ %ejabberd_hooks:add(disco_sm_items, VHost, ?MODULE, get_sm_items, 50), ++ %ejabberd_hooks:add(disco_sm_features, VHost, ?MODULE, get_sm_features, 50), ++ %ejabberd_hooks:add(disco_sm_identity, VHost, ?MODULE, get_sm_identity, 50), ++ ejabberd_hooks:add(adhoc_local_items, VHost, ?MODULE, adhoc_local_items, 50), ++ ejabberd_hooks:add(adhoc_local_commands, VHost, ?MODULE, adhoc_local_commands, 50), ++ %ejabberd_hooks:add(adhoc_sm_items, VHost, ?MODULE, adhoc_sm_items, 50), ++ %ejabberd_hooks:add(adhoc_sm_commands, VHost, ?MODULE, adhoc_sm_commands, 50), + + ejabberd_hooks:add(webadmin_menu_host, VHost, ?MODULE, webadmin_menu, 70), + ejabberd_hooks:add(webadmin_user, VHost, ?MODULE, webadmin_user, 50), @@ -682,22 +848,23 @@ index 0000000..7de346f +% handle_cast({addlog, E}, _) +% raw packet -> #msg +packet_parse(Owner, Peer, Packet, Direction, State) -> -+ case xml:get_subtag(Packet, "body") of ++ case xml:get_subtag(Packet, <<"body">>) of + false -> + ignore; + Body_xml -> + Message_type = -+ case xml:get_tag_attr_s("type", Packet) of -+ [] -> "normal"; -+ MType -> MType ++ case xml:get_tag_attr_s(<<"type">>, Packet) of ++ <<"error">> -> throw(ignore); ++ [] -> <<"normal">>; ++ MType -> MType + end, + + case Message_type of -+ "groupchat" when State#state.groupchat == send, Direction == to -> ++ <<"groupchat">> when State#state.groupchat == send, Direction == to -> + ok; -+ "groupchat" when State#state.groupchat == send, Direction == from -> ++ <<"groupchat">> when State#state.groupchat == send, Direction == from -> + throw(ignore); -+ "groupchat" when State#state.groupchat == half -> ++ <<"groupchat">> when State#state.groupchat == half -> + Rooms = ets:match(muc_online_room, '$1'), + Ni=lists:foldl(fun([{muc_online_room, {GName, GHost}, Pid}], Names) -> + case gen_fsm:sync_send_all_state_event(Pid, {get_jid_nick,Owner}) of @@ -712,7 +879,7 @@ index 0000000..7de346f + _ -> + ok + end; -+ "groupchat" when State#state.groupchat == none -> ++ <<"groupchat">> when State#state.groupchat == none -> + throw(ignore); + _ -> + ok @@ -720,9 +887,9 @@ index 0000000..7de346f + + Message_body = xml:get_tag_cdata(Body_xml), + Message_subject = -+ case xml:get_subtag(Packet, "subject") of ++ case xml:get_subtag(Packet, <<"subject">>) of + false -> -+ ""; ++ <<"">>; + Subject_xml -> + xml:get_tag_cdata(Subject_xml) + end, @@ -732,31 +899,32 @@ index 0000000..7de346f + PServer = stringprep:tolower(Peer#jid.server), + PResource = Peer#jid.resource, + -+ #msg{timestamp=get_timestamp(), -+ owner_name=OwnerName, -+ peer_name=PName, -+ peer_server=PServer, -+ peer_resource=PResource, -+ direction=Direction, -+ type=Message_type, -+ subject=Message_subject, -+ body=Message_body} ++ #msg{timestamp = get_timestamp(), ++ owner_name = OwnerName, ++ peer_name = PName, ++ peer_server = PServer, ++ peer_resource = PResource, ++ direction = Direction, ++ type = Message_type, ++ subject = Message_subject, ++ body = Message_body} + end. + +% called from handle_cast({addlog, _}, _) -> true (log messages) | false (do not log messages) +filter(Owner, Peer, State) -> -+ OwnerStr = Owner#jid.luser++"@"++Owner#jid.lserver, -+ OwnerServ = "@"++Owner#jid.lserver, -+ PeerStr = Peer#jid.luser++"@"++Peer#jid.lserver, -+ PeerServ = "@"++Peer#jid.lserver, ++ OwnerBin = << (Owner#jid.luser)/binary, "@", (Owner#jid.lserver)/binary >>, ++ OwnerServ = << "@", (Owner#jid.lserver)/binary >>, ++ PeerBin = << (Peer#jid.luser)/binary, "@", (Peer#jid.lserver)/binary >>, ++ PeerServ = << "@", (Peer#jid.lserver)/binary >>, + + LogTo = case ets:match_object(ets_settings_table(State#state.vhost), + #user_settings{owner_name=Owner#jid.luser, _='_'}) of + [#user_settings{dolog_default=Default, + dolog_list=DLL, + donotlog_list=DNLL}] -> -+ A = lists:member(PeerStr, DLL), -+ B = lists:member(PeerStr, DNLL), ++ ++ A = lists:member(PeerBin, DLL), ++ B = lists:member(PeerBin, DNLL), + if + A -> true; + B -> false; @@ -766,10 +934,9 @@ index 0000000..7de346f + end; + _ -> State#state.dolog_default + end, -+ + lists:all(fun(O) -> O end, -+ [not lists:member(OwnerStr, State#state.ignore_jids), -+ not lists:member(PeerStr, State#state.ignore_jids), ++ [not lists:member(OwnerBin, State#state.ignore_jids), ++ not lists:member(PeerBin, State#state.ignore_jids), + not lists:member(OwnerServ, State#state.ignore_jids), + not lists:member(PeerServ, State#state.ignore_jids), + LogTo]). @@ -782,8 +949,8 @@ index 0000000..7de346f + DateDiff = list_to_integer(Days)*24*60*60, + ?MYDEBUG("Purging tables older than ~s days", [Days]), + lists:foreach(fun(Date) -> -+ [Year, Month, Day] = ejabberd_regexp:split(Date, "[^0-9]+"), -+ DateInSec = calendar:datetime_to_gregorian_seconds({{list_to_integer(Year), list_to_integer(Month), list_to_integer(Day)}, {0,0,1}}), ++ [Year, Month, Day] = ejabberd_regexp:split(iolist_to_binary(Date), <<"[^0-9]+">>), ++ DateInSec = calendar:datetime_to_gregorian_seconds({{binary_to_integer(Year), binary_to_integer(Month), binary_to_integer(Day)}, {0,0,1}}), + if + (DateNow - DateInSec) > DateDiff -> + gen_server:call(Proc, {delete_messages_at, Date}); @@ -796,8 +963,8 @@ index 0000000..7de346f +sort_stats(Stats) -> + % Stats = [{"2003-4-15",1}, {"2006-8-18",1}, ... ] + CFun = fun({TableName, Count}) -> -+ [Year, Month, Day] = ejabberd_regexp:split(TableName, "[^0-9]+"), -+ { calendar:datetime_to_gregorian_seconds({{list_to_integer(Year), list_to_integer(Month), list_to_integer(Day)}, {0,0,1}}), Count } ++ [Year, Month, Day] = ejabberd_regexp:split(iolist_to_binary(TableName), <<"[^0-9]+">>), ++ { calendar:datetime_to_gregorian_seconds({{binary_to_integer(Year), binary_to_integer(Month), binary_to_integer(Day)}, {0,0,1}}), Count } + end, + % convert to [{63364377601,1}, {63360662401,1}, ... ] + CStats = lists:map(CFun, Stats), @@ -888,12 +1055,12 @@ index 0000000..7de346f +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +user_messages_at_parse_query(VHost, Date, Msgs, Query) -> -+ case lists:keysearch("delete", 1, Query) of ++ case lists:keysearch(<<"delete">>, 1, Query) of + {value, _} -> + PMsgs = lists:filter( + fun(Msg) -> -+ ID = jlib:encode_base64(binary_to_list(term_to_binary(Msg#msg.timestamp))), -+ lists:member({"selected", ID}, Query) ++ ID = jlib:encode_base64(term_to_binary(Msg#msg.timestamp)), ++ lists:member({<<"selected">>, ID}, Query) + end, Msgs), + Proc = gen_mod:get_module_proc(VHost, ?PROCNAME), + gen_server:call(Proc, {delete_messages_by_user_at, PMsgs, Date}, ?CALL_TIMEOUT); @@ -902,20 +1069,20 @@ index 0000000..7de346f + end. + +user_messages_parse_query(User, VHost, Query) -> -+ case lists:keysearch("delete", 1, Query) of ++ case lists:keysearch(<<"delete">>, 1, Query) of + {value, _} -> + Dates = get_dates(VHost), + PDates = lists:filter( + fun(Date) -> -+ ID = jlib:encode_base64(binary_to_list(term_to_binary(User++Date))), -+ lists:member({"selected", ID}, Query) ++ ID = jlib:encode_base64( << User/binary, (iolist_to_binary(Date))/binary >> ), ++ lists:member({<<"selected">>, ID}, Query) + end, Dates), + Proc = gen_mod:get_module_proc(VHost, ?PROCNAME), + Rez = lists:foldl( + fun(Date, Acc) -> + lists:append(Acc, + [gen_server:call(Proc, -+ {delete_all_messages_by_user_at, User, Date}, ++ {delete_all_messages_by_user_at, User, iolist_to_binary(Date)}, + ?CALL_TIMEOUT)]) + end, [], PDates), + case lists:member(error, Rez) of @@ -929,13 +1096,13 @@ index 0000000..7de346f + end. + +vhost_messages_parse_query(VHost, Query) -> -+ case lists:keysearch("delete", 1, Query) of ++ case lists:keysearch(<<"delete">>, 1, Query) of + {value, _} -> + Dates = get_dates(VHost), + PDates = lists:filter( + fun(Date) -> -+ ID = jlib:encode_base64(binary_to_list(term_to_binary(VHost++Date))), -+ lists:member({"selected", ID}, Query) ++ ID = jlib:encode_base64( << VHost/binary, (iolist_to_binary(Date))/binary >> ), ++ lists:member({<<"selected">>, ID}, Query) + end, Dates), + Proc = gen_mod:get_module_proc(VHost, ?PROCNAME), + Rez = lists:foldl(fun(Date, Acc) -> @@ -954,18 +1121,18 @@ index 0000000..7de346f + end. + +vhost_messages_at_parse_query(VHost, Date, Stats, Query) -> -+ case lists:keysearch("delete", 1, Query) of ++ case lists:keysearch(<<"delete">>, 1, Query) of + {value, _} -> + PStats = lists:filter( + fun({User, _Count}) -> -+ ID = jlib:encode_base64(binary_to_list(term_to_binary(User++VHost))), -+ lists:member({"selected", ID}, Query) ++ ID = jlib:encode_base64( << (iolist_to_binary(User))/binary, VHost/binary >> ), ++ lists:member({<<"selected">>, ID}, Query) + end, Stats), + Proc = gen_mod:get_module_proc(VHost, ?PROCNAME), + Rez = lists:foldl(fun({User, _Count}, Acc) -> + lists:append(Acc, [gen_server:call(Proc, + {delete_all_messages_by_user_at, -+ User, Date}, ++ iolist_to_binary(User), iolist_to_binary(Date)}, + ?CALL_TIMEOUT)]) + end, [], PStats), + case lists:member(error, Rez) of @@ -1035,9 +1202,9 @@ index 0000000..7de346f +copy_messages_int_tc([FromDBMod, ToDBMod, VHost, Date]) -> + ?INFO_MSG("Going to copy messages from ~p for ~p at ~p", [FromDBMod, VHost, Date]), + -+ ok = FromDBMod:rebuild_stats_at(VHost, Date), ++ ok = FromDBMod:rebuild_stats_at(VHost, binary_to_list(Date)), + catch mod_logdb:rebuild_stats_at(VHost, Date), -+ {ok, FromStats} = FromDBMod:get_vhost_stats_at(VHost, Date), ++ {ok, FromStats} = FromDBMod:get_vhost_stats_at(VHost, binary_to_list(Date)), + ToStats = case mod_logdb:get_vhost_stats_at(VHost, Date) of + {ok, Stats} -> Stats; + {error, _} -> [] @@ -1052,7 +1219,7 @@ index 0000000..7de346f + % destination table is empty + FromDBMod /= mod_logdb_mnesia_old, ToStats == [] -> + fun({User, _Count}, Acc) -> -+ {ok, Msgs} = FromDBMod:get_user_messages_at(User, VHost, Date), ++ {ok, Msgs} = FromDBMod:get_user_messages_at(binary_to_list(User), VHost, binary_to_list(Date)), + MAcc = + lists:foldl(fun(Msg, MFAcc) -> + ok = ToDBMod:log_message(VHost, Msg), @@ -1066,7 +1233,7 @@ index 0000000..7de346f + % destination table is not empty + FromDBMod /= mod_logdb_mnesia_old, ToStats /= [] -> + fun({User, _Count}, Acc) -> -+ {ok, ToMsgs} = ToDBMod:get_user_messages_at(User, VHost, Date), ++ {ok, ToMsgs} = ToDBMod:get_user_messages_at(binary_to_list(User), VHost, binary_to_list(Date)), + lists:foreach(fun(#msg{timestamp=Tst}) when length(Tst) == 16 -> + ets:insert(mod_logdb_temp, {Tst}); + % mysql, pgsql removes final zeros after decimal point @@ -1075,7 +1242,7 @@ index 0000000..7de346f + [T] = io_lib:format("~.5f", [F]), + ets:insert(mod_logdb_temp, {T}) + end, ToMsgs), -+ {ok, Msgs} = FromDBMod:get_user_messages_at(User, VHost, Date), ++ {ok, Msgs} = FromDBMod:get_user_messages_at(binary_to_list(User), VHost, binary_to_list(Date)), + MAcc = + lists:foldl(fun(#msg{timestamp=ToTimestamp} = Msg, MFAcc) -> + case ets:member(mod_logdb_temp, ToTimestamp) of @@ -1097,7 +1264,7 @@ index 0000000..7de346f + true -> + fun({User, _Count}, Acc) -> + ToStats = -+ case ToDBMod:get_user_messages_at(User, VHost, Date) of ++ case ToDBMod:get_user_messages_at(binary_to_list(User), VHost, binary_to_list(Date)) of + {ok, []} -> + ok; + {ok, ToMsgs} -> @@ -1112,7 +1279,7 @@ index 0000000..7de346f + {error, _} -> + ok + end, -+ {ok, Msgs} = FromDBMod:get_user_messages_at(User, VHost, Date), ++ {ok, Msgs} = FromDBMod:get_user_messages_at(binary_to_list(User), VHost, binary_to_list(Date)), + + MAcc = + lists:foldl( @@ -1173,13 +1340,15 @@ index 0000000..7de346f + ?INFO_MSG("Stats are equal at ~p", [Date]); + FromStatsS /= ToStatsS -> + lists:foldl(CopyFun, 0, FromStats), -+ ok = ToDBMod:rebuild_stats_at(VHost, Date) ++ ok = ToDBMod:rebuild_stats_at(VHost, binary_to_list(Date)) + %timer:sleep(1000) + end, + + ok. + -+list_to_bool(Num) -> ++list_to_bool(Num) when is_binary(Num) -> ++ list_to_bool(binary_to_list(Num)); ++list_to_bool(Num) when is_list(Num) -> + case lists:member(Num, ["t", "true", "y", "yes", "1"]) of + true -> + true; @@ -1200,7 +1369,11 @@ index 0000000..7de346f +list_to_string([]) -> + ""; +list_to_string(List) when is_list(List) -> -+ Str = lists:flatmap(fun(Elm) -> Elm ++ "\n" end, List), ++ Str = lists:flatmap(fun(Elm) when is_binary(Elm) -> ++ binary_to_list(Elm) ++ "\n"; ++ (Elm) when is_list(Elm) -> ++ Elm ++ "\n" ++ end, List), + lists:sublist(Str, length(Str)-1). + +string_to_list(null) -> @@ -1208,7 +1381,7 @@ index 0000000..7de346f +string_to_list([]) -> + []; +string_to_list(String) -> -+ ejabberd_regexp:split(String, "\n"). ++ ejabberd_regexp:split(iolist_to_binary(String), <<"\n">>). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% @@ -1229,7 +1402,7 @@ index 0000000..7de346f + end + end). + -+get_local_items(Acc, From, #jid{lserver = LServer} = To, "", Lang) -> ++get_local_items(Acc, From, #jid{lserver = LServer} = To, <<"">>, Lang) -> + case gen_mod:is_loaded(LServer, mod_adhoc) of + false -> + Acc; @@ -1258,54 +1431,58 @@ index 0000000..7de346f + false -> + Acc; + _ -> -+ LNode = string:tokens(Node, "/"), ++ LNode = str:tokens(Node, <<"/">>), + AllowAdmin = acl:match_rule(LServer, mod_logdb_admin, From), + case LNode of -+ ["mod_logdb"] -> ++ [<<"mod_logdb">>] -> + ?ITEMS_RESULT(AllowAdmin, LNode, {error, ?ERR_FORBIDDEN}); -+ ["mod_logdb_users"] -> ++ [<<"mod_logdb_users">>] -> + ?ITEMS_RESULT(AllowAdmin, LNode, {error, ?ERR_FORBIDDEN}); -+ ["mod_logdb_users", [$@ | _]] -> ++ [<<"mod_logdb_users">>, <<$@, _/binary>>] -> + ?ITEMS_RESULT(AllowAdmin, LNode, {error, ?ERR_FORBIDDEN}); -+ ["mod_logdb_users", _User] -> ++ [<<"mod_logdb_users">>, _User] -> + ?ITEMS_RESULT(AllowAdmin, LNode, {error, ?ERR_FORBIDDEN}); -+ ["mod_logdb_settings"] -> ++ [<<"mod_logdb_settings">>] -> + ?ITEMS_RESULT(AllowAdmin, LNode, {error, ?ERR_FORBIDDEN}); + _ -> + Acc + end + end. + ++-define(T(Lang, Text), translate:translate(Lang, Text)). ++ +-define(NODE(Name, Node), -+ {xmlelement, "item", -+ [{"jid", Server}, -+ {"name", translate:translate(Lang, Name)}, -+ {"node", Node}], []}). ++ #xmlel{name = <<"item">>, ++ attrs = ++ [{<<"jid">>, Server}, {<<"name">>, ?T(Lang, Name)}, ++ {<<"node">>, Node}], ++ children = []}). + +get_local_items(_Host, [], Server, Lang) -> + {result, -+ [?NODE("Messages logging engine", "mod_logdb")] ++ [?NODE(<<"Messages logging engine">>, <<"mod_logdb">>)] + }; -+get_local_items(_Host, ["mod_logdb"], Server, Lang) -> ++get_local_items(_Host, [<<"mod_logdb">>], Server, Lang) -> + {result, -+ [?NODE("Messages logging engine users", "mod_logdb_users"), -+ ?NODE("Messages logging engine settings", "mod_logdb_settings")] ++ [?NODE(<<"Messages logging engine users">>, <<"mod_logdb_users">>), ++ ?NODE(<<"Messages logging engine settings">>, <<"mod_logdb_settings">>)] + }; -+get_local_items(Host, ["mod_logdb_users"], Server, Lang) -> ++get_local_items(Host, [<<"mod_logdb_users">>], Server, Lang) -> + {result, get_all_vh_users(Host, Server, Lang)}; -+get_local_items(_Host, ["mod_logdb_users", [$@ | Diap]], Server, Lang) -> -+ case catch ejabberd_auth:dirty_get_registered_users() of ++get_local_items(Host, [<<"mod_logdb_users">>, <<$@, Diap/binary>>], Server, Lang) -> ++ case catch ejabberd_auth:get_vh_registered_users(Host) of + {'EXIT', _Reason} -> + ?ERR_INTERNAL_SERVER_ERROR; + Users -> + SUsers = lists:sort([{S, U} || {U, S} <- Users]), + case catch begin -+ [S1, S2] = ejabberd_regexp:split(Diap, "-"), -+ N1 = list_to_integer(S1), -+ N2 = list_to_integer(S2), ++ [S1, S2] = ejabberd_regexp:split(Diap, <<"-">>), ++ N1 = jlib:binary_to_integer(S1), ++ N2 = jlib:binary_to_integer(S2), + Sub = lists:sublist(SUsers, N1, N2 - N1 + 1), + lists:map(fun({S, U}) -> -+ ?NODE(U ++ "@" ++ S, "mod_logdb_users/" ++ U ++ "@" ++ S) ++ ?NODE(<< U/binary, "@", S/binary >>, ++ << (iolist_to_binary("mod_logdb_users/"))/binary, U/binary, "@", S/binary >>) + end, Sub) + end of + {'EXIT', _Reason} -> @@ -1314,9 +1491,9 @@ index 0000000..7de346f + {result, Res} + end + end; -+get_local_items(_Host, ["mod_logdb_users", _User], _Server, _Lang) -> ++get_local_items(_Host, [<<"mod_logdb_users">>, _User], _Server, _Lang) -> + {result, []}; -+get_local_items(_Host, ["mod_logdb_settings"], _Server, _Lang) -> ++get_local_items(_Host, [<<"mod_logdb_settings">>], _Server, _Lang) -> + {result, []}; +get_local_items(_Host, Item, _Server, _Lang) -> + ?MYDEBUG("asked for items in ~p", [Item]), @@ -1324,10 +1501,8 @@ index 0000000..7de346f + +-define(INFO_RESULT(Allow, Feats), + case Allow of -+ deny -> -+ {error, ?ERR_FORBIDDEN}; -+ allow -> -+ {result, Feats} ++ deny -> {error, ?ERR_FORBIDDEN}; ++ allow -> {result, Feats} + end). + +get_local_features(Acc, From, #jid{lserver = LServer} = _To, Node, _Lang) -> @@ -1335,52 +1510,53 @@ index 0000000..7de346f + false -> + Acc; + _ -> -+ LNode = string:tokens(Node, "/"), ++ LNode = str:tokens(Node, <<"/">>), + AllowUser = acl:match_rule(LServer, mod_logdb, From), + AllowAdmin = acl:match_rule(LServer, mod_logdb_admin, From), + case LNode of -+ ["mod_logdb"] when AllowUser == allow; AllowAdmin == allow -> ++ [<<"mod_logdb">>] when AllowUser == allow; AllowAdmin == allow -> + ?INFO_RESULT(allow, [?NS_COMMANDS]); -+ ["mod_logdb"] -> ++ [<<"mod_logdb">>] -> + ?INFO_RESULT(deny, [?NS_COMMANDS]); -+ ["mod_logdb_users"] -> ++ [<<"mod_logdb_users">>] -> + ?INFO_RESULT(AllowAdmin, []); -+ ["mod_logdb_users", [$@ | _]] -> ++ [<<"mod_logdb_users">>, [$@ | _]] -> + ?INFO_RESULT(AllowAdmin, []); -+ ["mod_logdb_users", _User] -> ++ [<<"mod_logdb_users">>, _User] -> + ?INFO_RESULT(AllowAdmin, [?NS_COMMANDS]); -+ ["mod_logdb_settings"] -> ++ [<<"mod_logdb_settings">>] -> + ?INFO_RESULT(AllowAdmin, [?NS_COMMANDS]); + [] -> + Acc; + _ -> -+ %?MYDEBUG("asked for ~p features: ~p", [LNode, Allow]), + Acc + end + end. + +-define(INFO_IDENTITY(Category, Type, Name, Lang), -+ [{xmlelement, "identity", -+ [{"category", Category}, -+ {"type", Type}, -+ {"name", translate:translate(Lang, Name)}], []}]). ++ [#xmlel{name = <<"identity">>, ++ attrs = ++ [{<<"category">>, Category}, {<<"type">>, Type}, ++ {<<"name">>, ?T(Lang, Name)}], ++ children = []}]). + +-define(INFO_COMMAND(Name, Lang), -+ ?INFO_IDENTITY("automation", "command-node", Name, Lang)). ++ ?INFO_IDENTITY(<<"automation">>, <<"command-node">>, ++ Name, Lang)). + +get_local_identity(Acc, _From, _To, Node, Lang) -> -+ LNode = string:tokens(Node, "/"), ++ LNode = str:tokens(Node, <<"/">>), + case LNode of -+ ["mod_logdb"] -> -+ ?INFO_COMMAND("Messages logging engine", Lang); -+ ["mod_logdb_users"] -> -+ ?INFO_COMMAND("Messages logging engine users", Lang); -+ ["mod_logdb_users", [$@ | _]] -> ++ [<<"mod_logdb">>] -> ++ ?INFO_COMMAND(<<"Messages logging engine">>, Lang); ++ [<<"mod_logdb_users">>] -> ++ ?INFO_COMMAND(<<"Messages logging engine users">>, Lang); ++ [<<"mod_logdb_users">>, [$@ | _]] -> + Acc; -+ ["mod_logdb_users", User] -> ++ [<<"mod_logdb_users">>, User] -> + ?INFO_COMMAND(User, Lang); -+ ["mod_logdb_settings"] -> -+ ?INFO_COMMAND("Messages logging engine settings", Lang); ++ [<<"mod_logdb_settings">>] -> ++ ?INFO_COMMAND(<<"Messages logging engine settings">>, Lang); + [] -> + Acc; + _ -> @@ -1419,10 +1595,10 @@ index 0000000..7de346f + end, Nodes), + {result, Items ++ Nodes1}. + -+recursively_get_local_items(_LServer, "mod_logdb_users", _Server, _Lang) -> ++recursively_get_local_items(_LServer, <<"mod_logdb_users">>, _Server, _Lang) -> + []; +recursively_get_local_items(LServer, Node, Server, Lang) -> -+ LNode = string:tokens(Node, "/"), ++ LNode = str:tokens(Node, <<"/">>), + Items = case get_local_items(LServer, LNode, Server, Lang) of + {result, Res} -> + Res; @@ -1453,15 +1629,15 @@ index 0000000..7de346f + +adhoc_local_commands(Acc, From, #jid{lserver = LServer} = To, + #adhoc_request{node = Node} = Request) -> -+ LNode = string:tokens(Node, "/"), ++ LNode = str:tokens(Node, <<"/">>), + AllowUser = acl:match_rule(LServer, mod_logdb, From), + AllowAdmin = acl:match_rule(LServer, mod_logdb_admin, From), + case LNode of -+ ["mod_logdb"] when AllowUser == allow; AllowAdmin == allow -> ++ [<<"mod_logdb">>] when AllowUser == allow; AllowAdmin == allow -> + ?COMMANDS_RESULT(allow, From, To, Request); -+ ["mod_logdb_users", _User] when AllowAdmin == allow -> ++ [<<"mod_logdb_users">>, _User] when AllowAdmin == allow -> + ?COMMANDS_RESULT(allow, From, To, Request); -+ ["mod_logdb_settings"] when AllowAdmin == allow -> ++ [<<"mod_logdb_settings">>] when AllowAdmin == allow -> + ?COMMANDS_RESULT(allow, From, To, Request); + _ -> + Acc @@ -1473,19 +1649,19 @@ index 0000000..7de346f + sessionid = SessionID, + action = Action, + xdata = XData} = Request) -> -+ LNode = string:tokens(Node, "/"), ++ LNode = str:tokens(Node, <<"/">>), + %% If the "action" attribute is not present, it is + %% understood as "execute". If there was no + %% element in the first response (which there isn't in our + %% case), "execute" and "complete" are equivalent. + ActionIsExecute = lists:member(Action, -+ ["", "execute", "complete"]), -+ if Action == "cancel" -> ++ [<<"">>, <<"execute">>, <<"complete">>]), ++ if Action == <<"cancel">> -> + %% User cancels request + adhoc:produce_response( + Request, + #adhoc_response{status = canceled}); -+ XData == false, ActionIsExecute -> ++ XData == false, ActionIsExecute -> + %% User requests form + case get_form(LServer, LNode, From, Lang) of + {result, Form} -> @@ -1496,74 +1672,84 @@ index 0000000..7de346f + {error, Error} -> + {error, Error} + end; -+ XData /= false, ActionIsExecute -> ++ XData /= false, ActionIsExecute -> + %% User returns form. + case jlib:parse_xdata_submit(XData) of + invalid -> + {error, ?ERR_BAD_REQUEST}; + Fields -> -+ case set_form(From, LServer, LNode, Lang, Fields) of ++ case catch set_form(From, LServer, LNode, Lang, Fields) of + {result, _Res} -> + adhoc:produce_response( + #adhoc_response{lang = Lang, + node = Node, + sessionid = SessionID, + status = completed}); -+ {error, Error} -> -+ {error, Error} ++ {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; ++ {error, Error} -> {error, Error} + end + end; -+ true -> ++ true -> + {error, ?ERR_BAD_REQUEST} + end. + +-define(LISTLINE(Label, Value), -+ {xmlelement, "option", [{"label", Label}], -+ [{xmlelement, "value", [], [{xmlcdata, Value}]}]}). -+-define(DEFVAL(Value), {xmlelement, "value", [], [{xmlcdata, Value}]}). ++ #xmlel{name = <<"option">>, ++ attrs = [{<<"label">>, ?T(Lang, Label)}], ++ children = [#xmlel{name = <<"value">>, attrs = [], ++ children = [{xmlcdata, Value}] ++ }]}). ++-define(DEFVAL(Value), #xmlel{name = <<"value">>, attrs = [], ++ children = [{xmlcdata, Value}]}). + +get_user_form(LUser, LServer, Lang) -> + %From = jlib:jid_to_string(jlib:jid_remove_resource(Jid)), + #user_settings{dolog_default=DLD, + dolog_list=DLL, + donotlog_list=DNLL} = get_user_settings(LUser, LServer), -+ {result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}], -+ [{xmlelement, "title", [], -+ [{xmlcdata, -+ translate:translate( -+ Lang, "Messages logging engine settings")}]}, -+ {xmlelement, "instructions", [], -+ [{xmlcdata, -+ translate:translate( -+ Lang, "Set logging preferences")++ ": " ++ LUser ++ "@" ++ LServer}]}, -+ % default to log -+ {xmlelement, "field", [{"type", "list-single"}, -+ {"label", -+ translate:translate(Lang, "Default")}, -+ {"var", "dolog_default"}], -+ [?DEFVAL(atom_to_list(DLD)), -+ ?LISTLINE(translate:translate(Lang, "Log Messages"), "true"), -+ ?LISTLINE(translate:translate(Lang, "Do Not Log Messages"), "false") -+ ]}, -+ % do log list -+ {xmlelement, "field", [{"type", "text-multi"}, -+ {"label", -+ translate:translate( -+ Lang, "Log Messages")}, -+ {"var", "dolog_list"}], -+ [{xmlelement, "value", [], [{xmlcdata, list_to_string(DLL)}]}]}, -+ % do not log list -+ {xmlelement, "field", [{"type", "text-multi"}, -+ {"label", -+ translate:translate( -+ Lang, "Do Not Log Messages")}, -+ {"var", "donotlog_list"}], -+ [{xmlelement, "value", [], [{xmlcdata, list_to_string(DNLL)}]}]} ++ {result, ++ [#xmlel{name = <<"x">>, ++ attrs = [{<<"xmlns">>, ?NS_XDATA}], ++ children = [ ++ #xmlel{name = <<"title">>, attrs = [], ++ children = ++ [{xmlcdata, ++ ?T(Lang, <<"Messages logging engine settings">>)}]}, ++ #xmlel{name = <<"instructions">>, attrs = [], ++ children = ++ [{xmlcdata, ++ << (?T(Lang, <<"Set logging preferences">>))/binary, (iolist_to_binary(": "))/binary, ++ LUser/binary, "@", LServer/binary >> }]}, ++ #xmlel{name = <<"field">>, ++ attrs = [{<<"type">>, <<"list-single">>}, ++ {<<"label">>, ?T(Lang, <<"Default">>)}, ++ {<<"var">>, <<"dolog_default">>}], ++ children = ++ [?DEFVAL(jlib:atom_to_binary(DLD)), ++ ?LISTLINE(<<"Log Messages">>, <<"true">>), ++ ?LISTLINE(<<"Do Not Log Messages">>, <<"false">>) ++ ]}, ++ #xmlel{name = <<"field">>, ++ attrs = [{<<"type">>, <<"text-multi">>}, ++ {<<"label">>, ?T(Lang, <<"Log Messages">>)}, ++ {<<"var">>, <<"dolog_list">>}], ++ children = [#xmlel{name = <<"value">>, attrs = [], ++ children = [{xmlcdata, iolist_to_binary(list_to_string(DLL))}]} ++ ] ++ }, ++ #xmlel{name = <<"field">>, ++ attrs = [{<<"type">>, <<"text-multi">>}, ++ {<<"label">>, ?T(Lang, <<"Do Not Log Messages">>)}, ++ {<<"var">>, <<"donotlog_list">>}], ++ children = [#xmlel{name = <<"value">>, attrs = [], ++ children = [{xmlcdata, iolist_to_binary(list_to_string(DNLL))}]} ++ ] ++ } + ]}]}. + +get_settings_form(Host, Lang) -> -+ #state{dbmod=DBMod, -+ dbs=DBs, ++ #state{dbmod=_DBMod, ++ dbs=_DBs, + dolog_default=DLD, + ignore_jids=IgnoreJids, + groupchat=GroupChat, @@ -1571,107 +1757,117 @@ index 0000000..7de346f + drop_messages_on_user_removal=MRemoval, + poll_users_settings=PollTime} = mod_logdb:get_module_settings(Host), + -+ Backends = lists:map(fun({Backend, _Opts}) -> -+ ?LISTLINE(atom_to_list(Backend), atom_to_list(Backend)) -+ end, DBs), -+ DB = lists:sublist(atom_to_list(DBMod), length(atom_to_list(?MODULE)) + 2, length(atom_to_list(DBMod))), -+ DBsL = lists:append([?DEFVAL(DB)], Backends), ++ %Backends = lists:map(fun({Backend, _Opts}) -> ++ % ?LISTLINE(jlib:atom_to_binary(Backend), jlib:atom_to_binary(Backend)) ++ % end, DBs), ++ %DB = iolist_to_binary(lists:sublist(atom_to_list(DBMod), length(atom_to_list(?MODULE)) + 2, length(atom_to_list(DBMod)))), ++ %DBsL = lists:append([?DEFVAL(DB)], Backends), + + PurgeDays = + case PurgeDaysT of -+ never -> "never"; -+ Num when is_integer(Num) -> integer_to_list(Num); -+ _ -> "unknown" ++ never -> <<"never">>; ++ Num when is_integer(Num) -> integer_to_binary(Num); ++ _ -> <<"unknown">> + end, -+ {result, [{xmlelement, "x", [{"xmlns", ?NS_XDATA}], -+ [{xmlelement, "title", [], -+ [{xmlcdata, -+ translate:translate( -+ Lang, "Messages logging engine settings") ++ " (run-time)"}]}, -+ {xmlelement, "instructions", [], -+ [{xmlcdata, -+ translate:translate( -+ Lang, "Set run-time settings")}]}, -+ % backends -+ {xmlelement, "field", [{"type", "list-single"}, -+ {"label", -+ translate:translate(Lang, "Backend")}, -+ {"var", "backend"}], -+ DBsL}, -+ % dbs -+ {xmlelement, "field", [{"type", "text-multi"}, -+ {"label", -+ translate:translate( -+ Lang, "dbs")}, -+ {"var", "dbs"}], -+ [{xmlelement, "value", [], [{xmlcdata, lists:flatten(io_lib:format("~p.",[DBs]))}]}]}, -+ % default to log -+ {xmlelement, "field", [{"type", "list-single"}, -+ {"label", -+ translate:translate(Lang, "Default")}, -+ {"var", "dolog_default"}], -+ [?DEFVAL(atom_to_list(DLD)), -+ ?LISTLINE(translate:translate(Lang, "Log Messages"), "true"), -+ ?LISTLINE(translate:translate(Lang, "Do Not Log Messages"), "false") -+ ]}, -+ % drop_messages_on_user_removal -+ {xmlelement, "field", [{"type", "list-single"}, -+ {"label", -+ translate:translate(Lang, "Drop messages on user removal")}, -+ {"var", "drop_messages_on_user_removal"}], -+ [?DEFVAL(atom_to_list(MRemoval)), -+ ?LISTLINE(translate:translate(Lang, "Drop"), "true"), -+ ?LISTLINE(translate:translate(Lang, "Do not drop"), "false") -+ ]}, -+ % groupchat -+ {xmlelement, "field", [{"type", "list-single"}, -+ {"label", -+ translate:translate(Lang, "Groupchat messages logging")}, -+ {"var", "groupchat"}], -+ [?DEFVAL(atom_to_list(GroupChat)), -+ ?LISTLINE("all", "all"), -+ ?LISTLINE("none", "none"), -+ ?LISTLINE("send", "send"), -+ ?LISTLINE("half", "half") -+ ]}, -+ % ignore_jids -+ {xmlelement, "field", [{"type", "text-multi"}, -+ {"label", -+ translate:translate( -+ Lang, "Jids/Domains to ignore")}, -+ {"var", "ignore_list"}], -+ [{xmlelement, "value", [], [{xmlcdata, list_to_string(IgnoreJids)}]}]}, -+ % purge older days -+ {xmlelement, "field", [{"type", "text-single"}, -+ {"label", -+ translate:translate( -+ Lang, "Purge messages older than (days)")}, -+ {"var", "purge_older_days"}], -+ [{xmlelement, "value", [], [{xmlcdata, PurgeDays}]}]}, -+ % poll users settings -+ {xmlelement, "field", [{"type", "text-single"}, -+ {"label", -+ translate:translate( -+ Lang, "Poll users settings (seconds)")}, -+ {"var", "poll_users_settings"}], -+ [{xmlelement, "value", [], [{xmlcdata, integer_to_list(PollTime)}]}]} -+ ]}]}. -+ -+get_form(_Host, ["mod_logdb"], #jid{luser = LUser, lserver = LServer} = _Jid, Lang) -> -+ get_user_form(LUser, LServer, Lang); -+get_form(_Host, ["mod_logdb_users", User], _JidFrom, Lang) -> ++ {result, ++ [#xmlel{name = <<"x">>, ++ attrs = [{<<"xmlns">>, ?NS_XDATA}], ++ children = [#xmlel{name = <<"title">>, attrs = [], ++ children = ++ [{xmlcdata, ++ <<(?T(Lang, <<"Messages logging engine settings">>))/binary, ++ (iolist_to_binary(" (run-time)"))/binary >>}]}, ++ #xmlel{name = <<"instructions">>, attrs = [], ++ children = ++ [{xmlcdata, ?T(Lang, <<"Set run-time settings">>)}]}, ++% #xmlel{name = <<"field">>, ++% attrs = [{<<"type">>, <<"list-single">>}, ++% {<<"label">>, ?T(Lang, <<"Backend">>)}, ++% {<<"var">>, <<"backend">>}], ++% children = DBsL}, ++% #xmlel{name = <<"field">>, ++% attrs = [{<<"type">>, <<"text-multi">>}, ++% {<<"label">>, ?T(Lang, <<"dbs">>)}, ++% {<<"var">>, <<"dbs">>}], ++% children = [#xmlel{name = <<"value">>, attrs = [], ++% children = [{xmlcdata, iolist_to_binary(lists:flatten(io_lib:format("~p.",[DBs])))}]} ++% ] ++% }, ++ #xmlel{name = <<"field">>, ++ attrs = [{<<"type">>, <<"list-single">>}, ++ {<<"label">>, ?T(Lang, <<"Default">>)}, ++ {<<"var">>, <<"dolog_default">>}], ++ children = ++ [?DEFVAL(jlib:atom_to_binary(DLD)), ++ ?LISTLINE(<<"Log Messages">>, <<"true">>), ++ ?LISTLINE(<<"Do Not Log Messages">>, <<"false">>) ++ ]}, ++ #xmlel{name = <<"field">>, ++ attrs = [{<<"type">>, <<"list-single">>}, ++ {<<"label">>, ?T(Lang, <<"Drop messages on user removal">>)}, ++ {<<"var">>, <<"drop_messages_on_user_removal">>}], ++ children = ++ [?DEFVAL(jlib:atom_to_binary(MRemoval)), ++ ?LISTLINE(<<"Drop">>, <<"true">>), ++ ?LISTLINE(<<"Do not drop">>, <<"false">>) ++ ]}, ++ #xmlel{name = <<"field">>, ++ attrs = [{<<"type">>, <<"list-single">>}, ++ {<<"label">>, ?T(Lang, <<"Groupchat messages logging">>)}, ++ {<<"var">>, <<"groupchat">>}], ++ children = ++ [?DEFVAL(jlib:atom_to_binary(GroupChat)), ++ ?LISTLINE(<<"all">>, <<"all">>), ++ ?LISTLINE(<<"none">>, <<"none">>), ++ ?LISTLINE(<<"send">>, <<"send">>), ++ ?LISTLINE(<<"half">>, <<"half">>) ++ ]}, ++ #xmlel{name = <<"field">>, ++ attrs = [{<<"type">>, <<"text-multi">>}, ++ {<<"label">>, ?T(Lang, <<"Jids/Domains to ignore">>)}, ++ {<<"var">>, <<"ignore_list">>}], ++ children = [#xmlel{name = <<"value">>, attrs = [], ++ children = [{xmlcdata, iolist_to_binary(list_to_string(IgnoreJids))}]} ++ ] ++ }, ++ #xmlel{name = <<"field">>, ++ attrs = [{<<"type">>, <<"text-single">>}, ++ {<<"label">>, ?T(Lang, <<"Purge messages older than (days)">>)}, ++ {<<"var">>, <<"purge_older_days">>}], ++ children = [#xmlel{name = <<"value">>, attrs = [], ++ children = [{xmlcdata, iolist_to_binary(PurgeDays)}]} ++ ] ++ }, ++ #xmlel{name = <<"field">>, ++ attrs = [{<<"type">>, <<"text-single">>}, ++ {<<"label">>, ?T(Lang, <<"Poll users settings (seconds)">>)}, ++ {<<"var">>, <<"poll_users_settings">>}], ++ children = [#xmlel{name = <<"value">>, attrs = [], ++ children = [{xmlcdata, integer_to_binary(PollTime)}]} ++ ] ++ } ++ ]} ++ ]}. ++ ++%get_form(_Host, [<<"mod_logdb">>], #jid{luser = LUser, lserver = LServer} = _Jid, Lang) -> ++% get_user_form(LUser, LServer, Lang); ++get_form(_Host, [<<"mod_logdb_users">>, User], _JidFrom, Lang) -> + #jid{luser=LUser, lserver=LServer} = jlib:string_to_jid(User), + get_user_form(LUser, LServer, Lang); -+get_form(Host, ["mod_logdb_settings"], _JidFrom, Lang) -> ++get_form(Host, [<<"mod_logdb_settings">>], _JidFrom, Lang) -> + get_settings_form(Host, Lang); +get_form(_Host, Command, _, _Lang) -> + ?MYDEBUG("asked for form ~p", [Command]), + {error, ?ERR_SERVICE_UNAVAILABLE}. + ++check_log_list([]) -> ++ ok; ++check_log_list([<<>>]) -> ++ ok; +check_log_list([Head | Tail]) -> -+ case lists:member($@, Head) of -+ true -> ok; -+ false -> throw(error) ++ case binary:match(Head, <<$@>>) of ++ nomatch -> throw(error); ++ {_, _} -> ok + end, + % this check for Head to be valid jid + case jlib:string_to_jid(Head) of @@ -1679,42 +1875,44 @@ index 0000000..7de346f + throw(error); + _ -> + check_log_list(Tail) -+ end; -+check_log_list([]) -> -+ ok. ++ end. + ++check_ignore_list([]) -> ++ ok; ++check_ignore_list([<<>>]) -> ++ ok; ++check_ignore_list([<<>> | Tail]) -> ++ check_ignore_list(Tail); +check_ignore_list([Head | Tail]) -> -+ case lists:member($@, Head) of -+ true -> ok; -+ false -> throw(error) ++ case binary:match(Head, <<$@>>) of ++ {_, _} -> ok; ++ nomatch -> throw(error) + end, + % this check for Head to be valid jid + case jlib:string_to_jid(Head) of + error -> + % this check for Head to be valid domain "@domain.org" -+ case lists:nth(1, Head) of -+ $@ -> ++ case Head of ++ << $@, Rest/binary >> -> + % TODO: this allows spaces and special characters in Head. May be change to nodeprep? -+ case jlib:nameprep(lists:delete($@, Head)) of ++ case jlib:nameprep(Rest) of + error -> throw(error); -+ _ -> check_log_list(Tail) ++ _ -> check_ignore_list(Tail) + end; + _ -> throw(error) + end; + _ -> + check_ignore_list(Tail) -+ end; -+check_ignore_list([]) -> -+ ok. ++ end. + +parse_users_settings(XData) -> -+ DLD = case lists:keysearch("dolog_default", 1, XData) of -+ {value, {_, [String]}} when String == "true"; String == "false" -> ++ DLD = case lists:keysearch(<<"dolog_default">>, 1, XData) of ++ {value, {_, [String]}} when String == <<"true">>; String == <<"false">> -> + list_to_bool(String); + _ -> + throw(bad_request) + end, -+ DLL = case lists:keysearch("dolog_list", 1, XData) of ++ DLL = case lists:keysearch(<<"dolog_list">>, 1, XData) of + false -> + throw(bad_request); + {value, {_, [[]]}} -> @@ -1727,7 +1925,7 @@ index 0000000..7de346f + List1 + end + end, -+ DNLL = case lists:keysearch("donotlog_list", 1, XData) of ++ DNLL = case lists:keysearch(<<"donotlog_list">>, 1, XData) of + false -> + throw(bad_request); + {value, {_, [[]]}} -> @@ -1745,28 +1943,28 @@ index 0000000..7de346f + donotlog_list=DNLL}. + +parse_module_settings(XData) -> -+ DLD = case lists:keysearch("dolog_default", 1, XData) of -+ {value, {_, [Str1]}} when Str1 == "true"; Str1 == "false" -> ++ DLD = case lists:keysearch(<<"dolog_default">>, 1, XData) of ++ {value, {_, [Str1]}} when Str1 == <<"true">>; Str1 == <<"false">> -> + list_to_bool(Str1); + _ -> + throw(bad_request) + end, -+ MRemoval = case lists:keysearch("drop_messages_on_user_removal", 1, XData) of -+ {value, {_, [Str5]}} when Str5 == "true"; Str5 == "false" -> ++ MRemoval = case lists:keysearch(<<"drop_messages_on_user_removal">>, 1, XData) of ++ {value, {_, [Str5]}} when Str5 == <<"true">>; Str5 == <<"false">> -> + list_to_bool(Str5); + _ -> + throw(bad_request) + end, -+ GroupChat = case lists:keysearch("groupchat", 1, XData) of -+ {value, {_, [Str2]}} when Str2 == "none"; -+ Str2 == "all"; -+ Str2 == "send"; -+ Str2 == "half" -> -+ list_to_atom(Str2); ++ GroupChat = case lists:keysearch(<<"groupchat">>, 1, XData) of ++ {value, {_, [Str2]}} when Str2 == <<"none">>; ++ Str2 == <<"all">>; ++ Str2 == <<"send">>; ++ Str2 == <<"half">> -> ++ jlib:binary_to_atom(Str2); + _ -> + throw(bad_request) + end, -+ Ignore = case lists:keysearch("ignore_list", 1, XData) of ++ Ignore = case lists:keysearch(<<"ignore_list">>, 1, XData) of + {value, {_, List}} -> + case catch check_ignore_list(List) of + ok -> @@ -1777,20 +1975,20 @@ index 0000000..7de346f + _ -> + throw(bad_request) + end, -+ Purge = case lists:keysearch("purge_older_days", 1, XData) of -+ {value, {_, ["never"]}} -> ++ Purge = case lists:keysearch(<<"purge_older_days">>, 1, XData) of ++ {value, {_, [<<"never">>]}} -> + never; + {value, {_, [Str3]}} -> -+ case catch list_to_integer(Str3) of ++ case catch binary_to_integer(Str3) of + {'EXIT', {badarg, _}} -> throw(bad_request); + Int1 -> Int1 + end; + _ -> + throw(bad_request) + end, -+ Poll = case lists:keysearch("poll_users_settings", 1, XData) of ++ Poll = case lists:keysearch(<<"poll_users_settings">>, 1, XData) of + {value, {_, [Str4]}} -> -+ case catch list_to_integer(Str4) of ++ case catch binary_to_integer(Str4) of + {'EXIT', {badarg, _}} -> throw(bad_request); + Int2 -> Int2 + end; @@ -1804,11 +2002,14 @@ index 0000000..7de346f + drop_messages_on_user_removal=MRemoval, + poll_users_settings=Poll}. + -+set_form(From, _Host, ["mod_logdb"], _Lang, XData) -> ++set_form(From, _Host, [<<"mod_logdb">>], _Lang, XData) -> + #jid{luser=LUser, lserver=LServer} = From, + case catch parse_users_settings(XData) of + bad_request -> + {error, ?ERR_BAD_REQUEST}; ++ {'EXIT', Reason} -> ++ ?ERROR_MSG("Failed to set form ~p", [Reason]), ++ {error, ?ERR_BAD_REQUEST}; + UserSettings -> + case mod_logdb:set_user_settings(LUser, LServer, UserSettings) of + ok -> @@ -1817,10 +2018,13 @@ index 0000000..7de346f + {error, ?ERR_INTERNAL_SERVER_ERROR} + end + end; -+set_form(_From, _Host, ["mod_logdb_users", User], _Lang, XData) -> ++set_form(_From, _Host, [<<"mod_logdb_users">>, User], _Lang, XData) -> + #jid{luser=LUser, lserver=LServer} = jlib:string_to_jid(User), + case catch parse_users_settings(XData) of + bad_request -> {error, ?ERR_BAD_REQUEST}; ++ {'EXIT', Reason} -> ++ ?ERROR_MSG("Failed to set form ~p", [Reason]), ++ {error, ?ERR_BAD_REQUEST}; + UserSettings -> + case mod_logdb:set_user_settings(LUser, LServer, UserSettings) of + ok -> @@ -1829,9 +2033,12 @@ index 0000000..7de346f + {error, ?ERR_INTERNAL_SERVER_ERROR} + end + end; -+set_form(_From, Host, ["mod_logdb_settings"], _Lang, XData) -> ++set_form(_From, Host, [<<"mod_logdb_settings">>], _Lang, XData) -> + case catch parse_module_settings(XData) of + bad_request -> {error, ?ERR_BAD_REQUEST}; ++ {'EXIT', Reason} -> ++ ?ERROR_MSG("Failed to set form ~p", [Reason]), ++ {error, ?ERR_BAD_REQUEST}; + Settings -> + case mod_logdb:set_module_settings(Host, Settings) of + ok -> @@ -1848,7 +2055,7 @@ index 0000000..7de346f +%adhoc_sm_items(Acc, From, To, Request) -> +% ?MYDEBUG("adhoc_sm_items Acc=~p From=~p To=~p Request=~p", [Acc, From, To, Request]), +% Acc. -+ ++% +%adhoc_sm_commands(Acc, From, To, Request) -> +% ?MYDEBUG("adhoc_sm_commands Acc=~p From=~p To=~p Request=~p", [Acc, From, To, Request]), +% Acc. @@ -1862,26 +2069,30 @@ index 0000000..7de346f + case length(SUsers) of + N when N =< 100 -> + lists:map(fun({S, U}) -> -+ ?NODE(U ++ "@" ++ S, "mod_logdb_users/" ++ U ++ "@" ++ S) -+ end, SUsers); ++ ?NODE(<< U/binary, "@", S/binary >>, ++ << (iolist_to_binary("mod_logdb_users/"))/binary, U/binary, "@", S/binary >>) ++ end, ++ SUsers); + N -> + NParts = trunc(math:sqrt(N * 0.618)) + 1, + M = trunc(N / NParts) + 1, + lists:map(fun(K) -> + L = K + M - 1, -+ Node = -+ "@" ++ integer_to_list(K) ++ -+ "-" ++ integer_to_list(L), ++ Node = <<"@", ++ (iolist_to_binary(integer_to_list(K)))/binary, ++ "-", ++ (iolist_to_binary(integer_to_list(L)))/binary ++ >>, + {FS, FU} = lists:nth(K, SUsers), + {LS, LU} = + if L < N -> lists:nth(L, SUsers); + true -> lists:last(SUsers) + end, + Name = -+ FU ++ "@" ++ FS ++ -+ " -- " ++ -+ LU ++ "@" ++ LS, -+ ?NODE(Name, "mod_logdb_users/" ++ Node) ++ <>, ++ ?NODE(Name, << (iolist_to_binary("mod_logdb_users/"))/binary, Node/binary >>) + end, lists:seq(1, N, M)) + end + end. @@ -1892,52 +2103,52 @@ index 0000000..7de346f +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +webadmin_menu(Acc, _Host, Lang) -> -+ [{"messages", ?T("Users Messages")} | Acc]. ++ [{<<"messages">>, ?T(<<"Users Messages">>)} | Acc]. + +webadmin_user(Acc, User, Server, Lang) -> + Sett = get_user_settings(User, Server), + Log = + case Sett#user_settings.dolog_default of + false -> -+ ?INPUTT("submit", "dolog", "Log Messages"); ++ ?INPUTT(<<"submit">>, <<"dolog">>, <<"Log Messages">>); + true -> -+ ?INPUTT("submit", "donotlog", "Do Not Log Messages"); ++ ?INPUTT(<<"submit">>, <<"donotlog">>, <<"Do Not Log Messages">>); + _ -> [] + end, -+ Acc ++ [?XE("h3", [?ACT("messages/", "Messages"), ?C(" "), Log])]. ++ Acc ++ [?XE(<<"h3">>, [?ACT(<<"messages/">>, <<"Messages">>), ?C(<<" ">>), Log])]. + +webadmin_page(_, Host, -+ #request{path = ["messages"], ++ #request{path = [<<"messages">>], + q = Query, -+ lang = Lang}) when is_list(Host) -> ++ lang = Lang}) -> + Res = vhost_messages_stats(Host, Query, Lang), + {stop, Res}; +webadmin_page(_, Host, -+ #request{path = ["messages", Date], ++ #request{path = [<<"messages">>, Date], + q = Query, -+ lang = Lang}) when is_list(Host) -> ++ lang = Lang}) -> + Res = vhost_messages_stats_at(Host, Query, Lang, Date), + {stop, Res}; +webadmin_page(_, Host, -+ #request{path = ["user", U, "messages"], ++ #request{path = [<<"user">>, U, <<"messages">>], + q = Query, + lang = Lang}) -> + Res = user_messages_stats(U, Host, Query, Lang), + {stop, Res}; +webadmin_page(_, Host, -+ #request{path = ["user", U, "messages", Date], ++ #request{path = [<<"user">>, U, <<"messages">>, Date], + q = Query, + lang = Lang}) -> + Res = mod_logdb:user_messages_stats_at(U, Host, Query, Lang, Date), + {stop, Res}; -+webadmin_page(Acc, _, _) -> Acc. ++webadmin_page(Acc, _Host, _R) -> Acc. + -+user_parse_query(_, "dolog", User, Server, _Query) -> ++user_parse_query(_, <<"dolog">>, User, Server, _Query) -> + Sett = get_user_settings(User, Server), + % TODO: check returned value + set_user_settings(User, Server, Sett#user_settings{dolog_default=true}), + {stop, ok}; -+user_parse_query(_, "donotlog", User, Server, _Query) -> ++user_parse_query(_, <<"donotlog">>, User, Server, _Query) -> + Sett = get_user_settings(User, Server), + % TODO: check returned value + set_user_settings(User, Server, Sett#user_settings{dolog_default=false}), @@ -1963,40 +2174,43 @@ index 0000000..7de346f + case Value of + {'EXIT', CReason} -> + ?ERROR_MSG("Failed to get_vhost_stats: ~p", [CReason]), -+ [?XC("h1", ?T("Error occupied while fetching list"))]; ++ [?XC(<<"h1">>, ?T(<<"Error occupied while fetching list">>))]; + {error, GReason} -> + ?ERROR_MSG("Failed to get_vhost_stats: ~p", [GReason]), -+ [?XC("h1", ?T("Error occupied while fetching list"))]; ++ [?XC(<<"h1">>, ?T(<<"Error occupied while fetching list">>))]; + {ok, []} -> -+ [?XC("h1", ?T("No logged messages for ") ++ Server)]; ++ [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"No logged messages for ~s">>), [Server])))]; + {ok, Dates} -> + Fun = fun({Date, Count}) -> -+ ID = jlib:encode_base64(binary_to_list(term_to_binary(Server++Date))), -+ ?XE("tr", -+ [?XE("td", [?INPUT("checkbox", "selected", ID)]), -+ ?XE("td", [?AC(Date, Date)]), -+ ?XC("td", integer_to_list(Count)) ++ DateBin = iolist_to_binary(Date), ++ ID = jlib:encode_base64( << Server/binary, DateBin/binary >> ), ++ ?XE(<<"tr">>, ++ [?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], ++ [?INPUT(<<"checkbox">>, <<"selected">>, ID)]), ++ ?XE(<<"td">>, [?AC(DateBin, DateBin)]), ++ ?XC(<<"td">>, integer_to_binary(Count)) + ]) + end, -+ [?XC("h1", ?T("Logged messages for ") ++ Server)] ++ ++ ++ [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Logged messages for ~s">>), [Server])))] ++ + case Res of -+ ok -> [?CT("Submitted"), ?P]; -+ error -> [?CT("Bad format"), ?P]; ++ ok -> [?CT(<<"Submitted">>), ?P]; ++ error -> [?CT(<<"Bad format">>), ?P]; + nothing -> [] + end ++ -+ [?XAE("form", [{"action", ""}, {"method", "post"}], -+ [?XE("table", -+ [?XE("thead", -+ [?XE("tr", -+ [?X("td"), -+ ?XCT("td", "Date"), -+ ?XCT("td", "Count") ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], ++ [?XE(<<"table">>, ++ [?XE(<<"thead">>, ++ [?XE(<<"tr">>, ++ [?X(<<"td">>), ++ ?XCT(<<"td">>, <<"Date">>), ++ ?XCT(<<"td">>, <<"Count">>) + ])]), -+ ?XE("tbody", ++ ?XE(<<"tbody">>, + lists:map(Fun, Dates) + )]), + ?BR, -+ ?INPUTT("submit", "delete", "Delete Selected") ++ ?INPUTT(<<"submit">>, <<"delete">>, <<"Delete Selected">>) + ])] + end. + @@ -2007,46 +2221,48 @@ index 0000000..7de346f + case Value of + {'EXIT', CReason} -> + ?ERROR_MSG("Failed to get_vhost_stats_at: ~p", [CReason]), -+ [?XC("h1", ?T("Error occupied while fetching list"))]; ++ [?XC(<<"h1">>, ?T(<<"Error occupied while fetching list">>))]; + {error, GReason} -> + ?ERROR_MSG("Failed to get_vhost_stats_at: ~p", [GReason]), -+ [?XC("h1", ?T("Error occupied while fetching list"))]; ++ [?XC(<<"h1">>, ?T(<<"Error occupied while fetching list">>))]; + {ok, []} -> -+ [?XC("h1", ?T("No logged messages for ") ++ Server ++ ?T(" at ") ++ Date)]; -+ {ok, Users} -> -+ Res = case catch vhost_messages_at_parse_query(Server, Date, Users, Query) of ++ [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"No logged messages for ~s at ~s">>), [Server, Date])))]; ++ {ok, Stats} -> ++ Res = case catch vhost_messages_at_parse_query(Server, Date, Stats, Query) of + {'EXIT', Reason} -> + ?ERROR_MSG("~p", [Reason]), + error; + VResult -> VResult + end, + Fun = fun({User, Count}) -> -+ ID = jlib:encode_base64(binary_to_list(term_to_binary(User++Server))), -+ ?XE("tr", -+ [?XE("td", [?INPUT("checkbox", "selected", ID)]), -+ ?XE("td", [?AC("../user/"++User++"/messages/"++Date, User)]), -+ ?XC("td", integer_to_list(Count)) ++ UserBin = iolist_to_binary(User), ++ ID = jlib:encode_base64( << UserBin/binary, Server/binary >> ), ++ ?XE(<<"tr">>, ++ [?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], ++ [?INPUT(<<"checkbox">>, <<"selected">>, ID)]), ++ ?XE(<<"td">>, [?AC(<< <<"../user/">>/binary, UserBin/binary, <<"/messages/">>/binary, Date/binary >>, UserBin)]), ++ ?XC(<<"td">>, integer_to_binary(Count)) + ]) + end, -+ [?XC("h1", ?T("Logged messages for ") ++ Server ++ ?T(" at ") ++ Date)] ++ ++ [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Logged messages for ~s at ~s">>), [Server, Date])))] ++ + case Res of -+ ok -> [?CT("Submitted"), ?P]; -+ error -> [?CT("Bad format"), ?P]; ++ ok -> [?CT(<<"Submitted">>), ?P]; ++ error -> [?CT(<<"Bad format">>), ?P]; + nothing -> [] + end ++ -+ [?XAE("form", [{"action", ""}, {"method", "post"}], -+ [?XE("table", -+ [?XE("thead", -+ [?XE("tr", -+ [?X("td"), -+ ?XCT("td", "User"), -+ ?XCT("td", "Count") ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], ++ [?XE(<<"table">>, ++ [?XE(<<"thead">>, ++ [?XE(<<"tr">>, ++ [?X(<<"td">>), ++ ?XCT(<<"td">>, <<"User">>), ++ ?XCT(<<"td">>, <<"Count">>) + ])]), -+ ?XE("tbody", -+ lists:map(Fun, Users) ++ ?XE(<<"tbody">>, ++ lists:map(Fun, Stats) + )]), + ?BR, -+ ?INPUTT("submit", "delete", "Delete Selected") ++ ?INPUTT(<<"submit">>, <<"delete">>, <<"Delete Selected">>) + ])] + end. + @@ -2066,41 +2282,42 @@ index 0000000..7de346f + case Value of + {'EXIT', CReason} -> + ?ERROR_MSG("Failed to get_user_stats: ~p", [CReason]), -+ [?XC("h1", ?T("Error occupied while fetching days"))]; ++ [?XC(<<"h1">>, ?T(<<"Error occupied while fetching days">>))]; + {error, GReason} -> + ?ERROR_MSG("Failed to get_user_stats: ~p", [GReason]), -+ [?XC("h1", ?T("Error occupied while fetching days"))]; ++ [?XC(<<"h1">>, ?T(<<"Error occupied while fetching days">>))]; + {ok, []} -> -+ [?XC("h1", ?T("No logged messages for ") ++ Jid)]; ++ [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"No logged messages for ~s">>), [Jid])))]; + {ok, Dates} -> + Fun = fun({Date, Count}) -> -+ ID = jlib:encode_base64(binary_to_list(term_to_binary(User++Date))), -+ ?XE("tr", -+ [?XE("td", [?INPUT("checkbox", "selected", ID)]), -+ ?XE("td", [?AC(Date, Date)]), -+ ?XC("td", integer_to_list(Count)) ++ DateBin = iolist_to_binary(Date), ++ ID = jlib:encode_base64( << User/binary, DateBin/binary >> ), ++ ?XE(<<"tr">>, ++ [?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], ++ [?INPUT(<<"checkbox">>, <<"selected">>, ID)]), ++ ?XE(<<"td">>, [?AC(DateBin, DateBin)]), ++ ?XC(<<"td">>, iolist_to_binary(integer_to_list(Count))) + ]) -+ %[?AC(Date, Date ++ " (" ++ integer_to_list(Count) ++ ")"), ?BR] + end, -+ [?XC("h1", ?T("Logged messages for ") ++ Jid)] ++ ++ [?XC(<<"h1">>, list_to_binary(io_lib:format(?T("Logged messages for ~s"), [Jid])))] ++ + case Res of -+ ok -> [?CT("Submitted"), ?P]; -+ error -> [?CT("Bad format"), ?P]; ++ ok -> [?CT(<<"Submitted">>), ?P]; ++ error -> [?CT(<<"Bad format">>), ?P]; + nothing -> [] + end ++ -+ [?XAE("form", [{"action", ""}, {"method", "post"}], -+ [?XE("table", -+ [?XE("thead", -+ [?XE("tr", -+ [?X("td"), -+ ?XCT("td", "Date"), -+ ?XCT("td", "Count") ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], ++ [?XE(<<"table">>, ++ [?XE(<<"thead">>, ++ [?XE(<<"tr">>, ++ [?X(<<"td">>), ++ ?XCT(<<"td">>, <<"Date">>), ++ ?XCT(<<"td">>, <<"Count">>) + ])]), -+ ?XE("tbody", ++ ?XE(<<"tbody">>, + lists:map(Fun, Dates) + )]), + ?BR, -+ ?INPUTT("submit", "delete", "Delete Selected") ++ ?INPUTT(<<"submit">>, <<"delete">>, <<"Delete Selected">>) + ])] + end. + @@ -2122,17 +2339,17 @@ index 0000000..7de346f + case Value of + {'EXIT', CReason} -> + ?ERROR_MSG("Failed to get_user_messages_at: ~p", [CReason]), -+ [?XC("h1", ?T("Error occupied while fetching messages"))]; ++ [?XC(<<"h1">>, ?T(<<"Error occupied while fetching messages">>))]; + {error, GReason} -> + ?ERROR_MSG("Failed to get_user_messages_at: ~p", [GReason]), -+ [?XC("h1", ?T("Error occupied while fetching messages"))]; ++ [?XC(<<"h1">>, ?T(<<"Error occupied while fetching messages">>))]; + {ok, []} -> -+ [?XC("h1", ?T("No logged messages for ") ++ Jid ++ ?T(" at ") ++ Date)]; ++ [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"No logged messages for ~s at ~s">>), [Jid, Date])))]; + {ok, User_messages} -> + Res = case catch user_messages_at_parse_query(Server, -+ Date, -+ User_messages, -+ Query) of ++ Date, ++ User_messages, ++ Query) of + {'EXIT', Reason} -> + ?ERROR_MSG("~p", [Reason]), + error; @@ -2143,7 +2360,7 @@ index 0000000..7de346f + UserRoster = + lists:map(fun(Item) -> + {jlib:jid_to_string(Item#roster.jid), Item#roster.name} -+ end, UR), ++ end, UR), + + UniqUsers = lists:foldl(fun(#msg{peer_name=PName, peer_server=PServer}, List) -> + ToAdd = PName++"@"++PServer, @@ -2154,31 +2371,31 @@ index 0000000..7de346f + end, [], User_messages), + + % Users to filter (sublist of UniqUsers) -+ CheckedUsers = case lists:keysearch("filter", 1, Query) of ++ CheckedUsers = case lists:keysearch(<<"filter">>, 1, Query) of + {value, _} -> + lists:filter(fun(UFUser) -> -+ ID = jlib:encode_base64(binary_to_list(term_to_binary(UFUser))), -+ lists:member({"selected", ID}, Query) ++ ID = jlib:encode_base64(term_to_binary(UFUser)), ++ lists:member({<<"selected">>, ID}, Query) + end, UniqUsers); + false -> [] + end, + + % UniqUsers in html (noone selected -> everyone selected) + Users = lists:map(fun(UHUser) -> -+ ID = jlib:encode_base64(binary_to_list(term_to_binary(UHUser))), ++ ID = jlib:encode_base64(term_to_binary(UHUser)), + Input = case lists:member(UHUser, CheckedUsers) of -+ true -> [?INPUTC("checkbox", "selected", ID)]; -+ false when CheckedUsers == [] -> [?INPUTC("checkbox", "selected", ID)]; -+ false -> [?INPUT("checkbox", "selected", ID)] ++ true -> [?INPUTC(<<"checkbox">>, <<"selected">>, ID)]; ++ false when CheckedUsers == [] -> [?INPUTC(<<"checkbox">>, <<"selected">>, ID)]; ++ false -> [?INPUT(<<"checkbox">>, <<"selected">>, ID)] + end, + Nick = + case search_user_nick(UHUser, UserRoster) of -+ nothing -> ""; -+ N -> " ("++ N ++")" ++ nothing -> <<"">>; ++ N -> iolist_to_binary( " ("++ N ++")" ) + end, -+ ?XE("tr", -+ [?XE("td", Input), -+ ?XC("td", UHUser++Nick)]) ++ ?XE(<<"tr">>, ++ [?XE(<<"td">>, Input), ++ ?XC(<<"td">>, iolist_to_binary(UHUser++Nick))]) + end, lists:sort(UniqUsers)), + % Messages to show (based on Users) + User_messages_filtered = case CheckedUsers of @@ -2194,15 +2411,10 @@ index 0000000..7de346f + peer_name=PName, peer_server=PServer, peer_resource=PRes, + type=Type, + body=Body}) -> -+ TextRaw = case Subject of -+ "" -> Body; -+ _ -> [?T("Subject"),": ",Subject,"
", Body] -+ end, -+ ID = jlib:encode_base64(binary_to_list(term_to_binary(Timestamp))), -+ % replace \n with
-+ Text = lists:map(fun(10) -> "
"; -+ (A) -> A -+ end, TextRaw), ++ Text = case Subject of ++ "" -> iolist_to_binary(Body); ++ _ -> iolist_to_binary([binary_to_list(?T(<<"Subject">>)) ++ ": " ++ Subject ++ "\n" ++ Body]) ++ end, + Resource = case PRes of + [] -> []; + undefined -> []; @@ -2218,54 +2430,55 @@ index 0000000..7de346f + PName++"@"++PServer; + N -> N + end, -+ ?XE("tr", -+ [?XE("td", [?INPUT("checkbox", "selected", ID)]), -+ ?XC("td", convert_timestamp(Timestamp)), -+ ?XC("td", atom_to_list(Direction)++": "++UserNick), -+ ?XC("td", Text)]) ++ ID = jlib:encode_base64(term_to_binary(Timestamp)), ++ ?XE(<<"tr">>, ++ [?XE(<<"td">>, [?INPUT(<<"checkbox">>, <<"selected">>, ID)]), ++ ?XC(<<"td">>, iolist_to_binary(convert_timestamp(Timestamp))), ++ ?XC(<<"td">>, iolist_to_binary(atom_to_list(Direction)++": "++UserNick)), ++ ?XE(<<"td">>, [?XC(<<"pre">>, Text)])]) + end, + % Filtered user messages in html + Msgs = lists:map(Msgs_Fun, lists:sort(User_messages_filtered)), + -+ [?XC("h1", ?T("Logged messages for ") ++ Jid ++ ?T(" at ") ++ Date)] ++ ++ [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Logged messages for ~s at ~s">>), [Jid, Date])))] ++ + case Res of -+ ok -> [?CT("Submitted"), ?P]; -+ error -> [?CT("Bad format"), ?P]; ++ ok -> [?CT(<<"Submitted">>), ?P]; ++ error -> [?CT(<<"Bad format">>), ?P]; + nothing -> [] + end ++ -+ [?XAE("form", [{"action", ""}, {"method", "post"}], -+ [?XE("table", -+ [?XE("thead", -+ [?X("td"), -+ ?XCT("td", "User") ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], ++ [?XE(<<"table">>, ++ [?XE(<<"thead">>, ++ [?X(<<"td">>), ++ ?XCT(<<"td">>, <<"User">>) + ] + ), -+ ?XE("tbody", ++ ?XE(<<"tbody">>, + Users + )]), -+ ?INPUTT("submit", "filter", "Filter Selected") ++ ?INPUTT(<<"submit">>, <<"filter">>, <<"Filter Selected">>) + ] ++ -+ [?XE("table", -+ [?XE("thead", -+ [?XE("tr", -+ [?X("td"), -+ ?XCT("td", "Date, Time"), -+ ?XCT("td", "Direction: Jid"), -+ ?XCT("td", "Body") ++ [?XE(<<"table">>, ++ [?XE(<<"thead">>, ++ [?XE(<<"tr">>, ++ [?X(<<"td">>), ++ ?XCT(<<"td">>, <<"Date, Time">>), ++ ?XCT(<<"td">>, <<"Direction: Jid">>), ++ ?XCT(<<"td">>, <<"Body">>) + ])]), -+ ?XE("tbody", ++ ?XE(<<"tbody">>, + Msgs + )]), -+ ?INPUTT("submit", "delete", "Delete Selected"), ++ ?INPUTT(<<"submit">>, <<"delete">>, <<"Delete Selected">>), + ?BR + ] + )] + end. -diff --git src/mod_logdb.hrl src/mod_logdb.hrl +diff --git a/src/mod_logdb.hrl b/src/mod_logdb.hrl new file mode 100644 -index 0000000..50db897 +index 0000000..d44f0df --- /dev/null -+++ src/mod_logdb.hrl ++++ b/src/mod_logdb.hrl @@ -0,0 +1,35 @@ +%%%---------------------------------------------------------------------- +%%% File : mod_logdb.hrl @@ -2298,16 +2511,16 @@ index 0000000..50db897 + donotlog_list=[]}). + +-define(INPUTC(Type, Name, Value), -+ ?XA("input", [{"type", Type}, -+ {"name", Name}, -+ {"value", Value}, -+ {"checked", "true"}])). -diff --git src/mod_logdb_mnesia.erl src/mod_logdb_mnesia.erl ++ ?XA(<<"input">>, [{<<"type">>, Type}, ++ {<<"name">>, Name}, ++ {<<"value">>, Value}, ++ {<<"checked">>, <<"true">>}])). +diff --git a/src/mod_logdb_mnesia.erl b/src/mod_logdb_mnesia.erl new file mode 100644 -index 0000000..783aaeb +index 0000000..a8ae766 --- /dev/null -+++ src/mod_logdb_mnesia.erl -@@ -0,0 +1,546 @@ ++++ b/src/mod_logdb_mnesia.erl +@@ -0,0 +1,557 @@ +%%%---------------------------------------------------------------------- +%%% File : mod_logdb_mnesia.erl +%%% Author : Oleg Palij (mailto,xmpp:o.palij@gmail.com) @@ -2323,6 +2536,7 @@ index 0000000..783aaeb +-include("mod_logdb.hrl"). +-include("ejabberd.hrl"). +-include("jlib.hrl"). ++-include("logger.hrl"). + +-behaviour(gen_logdb). +-behaviour(gen_server). @@ -2352,7 +2566,7 @@ index 0000000..783aaeb + "logdb_". + +suffix(VHost) -> -+ "_" ++ VHost. ++ "_" ++ binary_to_list(VHost). + +stats_table(VHost) -> + list_to_atom(prefix() ++ "stats" ++ suffix(VHost)). @@ -2600,9 +2814,19 @@ index 0000000..783aaeb +% internals +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -+log_message_int(VHost, #msg{timestamp=Timestamp}=Msg) -> ++log_message_int(VHost, #msg{timestamp=Timestamp}=MsgBin) -> + Date = mod_logdb:convert_timestamp_brief(Timestamp), + ++ Msg = #msg{timestamp = MsgBin#msg.timestamp, ++ owner_name = binary_to_list(MsgBin#msg.owner_name), ++ peer_name = binary_to_list(MsgBin#msg.peer_name), ++ peer_server = binary_to_list(MsgBin#msg.peer_server), ++ peer_resource = binary_to_list(MsgBin#msg.peer_resource), ++ direction = MsgBin#msg.direction, ++ type = binary_to_list(MsgBin#msg.type), ++ subject = binary_to_list(MsgBin#msg.subject), ++ body = binary_to_list(MsgBin#msg.body)}, ++ + ATable = table_name(VHost, Date), + Fun = fun() -> + mnesia:write_lock_table(ATable), @@ -2617,15 +2841,15 @@ index 0000000..783aaeb + ?ERROR_MSG("Failed to log message: ~p", [CReason]), + error; + {atomic, ok} -> -+ ?MYDEBUG("Created msg table for ~p at ~p", [VHost, Date]), -+ log_message_int(VHost, Msg) ++ ?MYDEBUG("Created msg table for ~s at ~s", [VHost, Date]), ++ log_message_int(VHost, MsgBin) + end; + {aborted, TReason} -> + ?ERROR_MSG("Failed to log message: ~p", [TReason]), + error; + {atomic, _} -> -+ ?MYDEBUG("Logged ok for ~p, peer: ~p", [Msg#msg.owner_name++"@"++VHost, -+ Msg#msg.peer_name++"@"++Msg#msg.peer_server]), ++ ?MYDEBUG("Logged ok for ~s, peer: ~s", [ [Msg#msg.owner_name, <<"@">>, VHost], ++ [Msg#msg.peer_name, <<"@">>, Msg#msg.peer_server] ]), + increment_user_stats(Msg#msg.owner_name, VHost, Date) + end. + @@ -2667,12 +2891,12 @@ index 0000000..783aaeb +get_dates_int(VHost) -> + Tables = mnesia:system_info(tables), + lists:foldl(fun(ATable, Dates) -> -+ Table = atom_to_list(ATable), -+ case ejabberd_regexp:run(Table, VHost++"$") of ++ Table = term_to_binary(ATable), ++ case ejabberd_regexp:run( Table, << VHost/binary, <<"$">>/binary >> ) of + match -> + case re:run(Table, "_[0-9]+-[0-9]+-[0-9]+_") of + {match, [{S, E}]} -> -+ lists:append(Dates, [lists:sublist(Table,S+1,E-2)]); ++ lists:append(Dates, [lists:sublist(binary_to_list(Table), S+2, E-2)]); + nomatch -> + Dates + end; @@ -2702,12 +2926,12 @@ index 0000000..783aaeb + case mnesia:transaction(fun() -> + mnesia:write_lock_table(Table), + mnesia:write_lock_table(STable), ++ % Delete all stats for VHost at Date ++ mnesia:foldl(DFun, [], STable), + % Calc stats for VHost at Date + case mnesia:foldl(CFun, [], Table) of + [] -> empty; + AStats -> -+ % Delete all stats for VHost at Date -+ mnesia:foldl(DFun, [], STable), + % Write new calc'ed stats + lists:foreach(fun({Owner, Count}) -> + WStat = #stats{user=Owner, at=Date, count=Count}, @@ -2854,12 +3078,12 @@ index 0000000..783aaeb + {type, bag}, + {attributes, record_info(fields, msg)}, + {record_name, msg}]). -diff --git src/mod_logdb_mnesia_old.erl src/mod_logdb_mnesia_old.erl +diff --git a/src/mod_logdb_mnesia_old.erl b/src/mod_logdb_mnesia_old.erl new file mode 100644 -index 0000000..aef9956 +index 0000000..e962d9a --- /dev/null -+++ src/mod_logdb_mnesia_old.erl -@@ -0,0 +1,258 @@ ++++ b/src/mod_logdb_mnesia_old.erl +@@ -0,0 +1,259 @@ +%%%---------------------------------------------------------------------- +%%% File : mod_logdb_mnesia_old.erl +%%% Author : Oleg Palij (mailto,xmpp:o.palij@gmail.com) @@ -2874,6 +3098,7 @@ index 0000000..aef9956 + +-include("ejabberd.hrl"). +-include("jlib.hrl"). ++-include("logger.hrl"). + +-behaviour(gen_logdb). + @@ -3118,12 +3343,12 @@ index 0000000..aef9956 + ?ERROR_MSG("Failed to create stats table: ~p", [Reason]), + error + end. -diff --git src/mod_logdb_mysql.erl src/mod_logdb_mysql.erl +diff --git a/src/mod_logdb_mysql.erl b/src/mod_logdb_mysql.erl new file mode 100644 -index 0000000..7c473ce +index 0000000..62f437c --- /dev/null -+++ src/mod_logdb_mysql.erl -@@ -0,0 +1,1052 @@ ++++ b/src/mod_logdb_mysql.erl +@@ -0,0 +1,1055 @@ +%%%---------------------------------------------------------------------- +%%% File : mod_logdb_mysql.erl +%%% Author : Oleg Palij (mailto,xmpp:o.palij@gmail.com) @@ -3139,6 +3364,7 @@ index 0000000..7c473ce +-include("mod_logdb.hrl"). +-include("ejabberd.hrl"). +-include("jlib.hrl"). ++-include("logger.hrl"). + +-behaviour(gen_logdb). +-behaviour(gen_server). @@ -3172,7 +3398,7 @@ index 0000000..7c473ce +% replace "." with "_" +escape_vhost(VHost) -> lists:map(fun(46) -> 95; + (A) -> A -+ end, VHost). ++ end, binary_to_list(VHost)). +prefix() -> + "`logdb_". + @@ -3198,9 +3424,9 @@ index 0000000..7c473ce +resources_table(VHost) -> + prefix() ++ "resources" ++ suffix(VHost). + -+ets_users_table(VHost) -> list_to_atom("logdb_users_" ++ VHost). -+ets_servers_table(VHost) -> list_to_atom("logdb_servers_" ++ VHost). -+ets_resources_table(VHost) -> list_to_atom("logdb_resources_" ++ VHost). ++ets_users_table(VHost) -> list_to_atom("logdb_users_" ++ binary_to_list(VHost)). ++ets_servers_table(VHost) -> list_to_atom("logdb_servers_" ++ binary_to_list(VHost)). ++ets_resources_table(VHost) -> list_to_atom("logdb_resources_" ++ binary_to_list(VHost)). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% @@ -3223,11 +3449,11 @@ index 0000000..7c473ce +init([VHost, Opts]) -> + crypto:start(), + -+ Server = gen_mod:get_opt(server, Opts, "localhost"), -+ Port = gen_mod:get_opt(port, Opts, 3306), -+ DB = gen_mod:get_opt(db, Opts, "logdb"), -+ User = gen_mod:get_opt(user, Opts, "root"), -+ Password = gen_mod:get_opt(password, Opts, ""), ++ Server = gen_mod:get_opt(server, Opts, fun(A) -> A end, <<"localhost">>), ++ Port = gen_mod:get_opt(port, Opts, fun(A) -> A end, 3306), ++ DB = gen_mod:get_opt(db, Opts, fun(A) -> A end, <<"logdb">>), ++ User = gen_mod:get_opt(user, Opts, fun(A) -> A end, <<"root">>), ++ Password = gen_mod:get_opt(password, Opts, fun(A) -> A end, <<"">>), + + St = #state{vhost=VHost, + server=Server, port=Port, db=DB, @@ -3262,20 +3488,22 @@ index 0000000..7c473ce + ?MYDEBUG(Format, Argument) + end, + ?INFO_MSG("Opening mysql connection ~s@~s:~p/~s", [DBUser, Server, Port, DB]), -+ mysql_conn:start(Server, Port, DBUser, Password, DB, LogFun). ++ p1_mysql_conn:start(binary_to_list(Server), Port, ++ binary_to_list(DBUser), binary_to_list(Password), ++ binary_to_list(DB), LogFun). + +close_mysql_connection(DBRef) -> + ?MYDEBUG("Closing ~p mysql connection", [DBRef]), -+ mysql_conn:stop(DBRef). ++ catch p1_mysql_conn:stop(DBRef). + +handle_call({log_message, Msg}, _From, #state{dbref=DBRef, vhost=VHost}=State) -> + Date = convert_timestamp_brief(Msg#msg.timestamp), + + Table = messages_table(VHost, Date), -+ Owner_id = get_user_id(DBRef, VHost, Msg#msg.owner_name), -+ Peer_name_id = get_user_id(DBRef, VHost, Msg#msg.peer_name), -+ Peer_server_id = get_server_id(DBRef, VHost, Msg#msg.peer_server), -+ Peer_resource_id = get_resource_id(DBRef, VHost, Msg#msg.peer_resource), ++ Owner_id = get_user_id(DBRef, VHost, binary_to_list(Msg#msg.owner_name)), ++ Peer_name_id = get_user_id(DBRef, VHost, binary_to_list(Msg#msg.peer_name)), ++ Peer_server_id = get_server_id(DBRef, VHost, binary_to_list(Msg#msg.peer_server)), ++ Peer_resource_id = get_resource_id(DBRef, VHost, binary_to_list(Msg#msg.peer_resource)), + + Query = ["INSERT INTO ",Table," ", + "(owner_id,", @@ -3293,19 +3521,19 @@ index 0000000..7c473ce + "'", Peer_server_id, "',", + "'", Peer_resource_id, "',", + "'", atom_to_list(Msg#msg.direction), "',", -+ "'", Msg#msg.type, "',", -+ "'", ejabberd_odbc:escape(Msg#msg.subject), "',", -+ "'", ejabberd_odbc:escape(Msg#msg.body), "',", ++ "'", binary_to_list(Msg#msg.type), "',", ++ "'", binary_to_list( ejabberd_odbc:escape(Msg#msg.subject) ), "',", ++ "'", binary_to_list( ejabberd_odbc:escape(Msg#msg.body) ), "',", + "'", Msg#msg.timestamp, "');"], + + Reply = + case sql_query_internal_silent(DBRef, Query) of + {updated, _} -> -+ ?MYDEBUG("Logged ok for ~p, peer: ~p", [Msg#msg.owner_name++"@"++VHost, -+ Msg#msg.peer_name++"@"++Msg#msg.peer_server]), ++ ?MYDEBUG("Logged ok for ~s, peer: ~s", [ [Msg#msg.owner_name, <<"@">>, VHost], ++ [Msg#msg.peer_name, <<"@">>, Msg#msg.peer_server] ]), + increment_user_stats(DBRef, Msg#msg.owner_name, Owner_id, VHost, Peer_name_id, Peer_server_id, Date); + {error, Reason} -> -+ case ejabberd_regexp:run(Reason, "#42S02") of ++ case ejabberd_regexp:run(iolist_to_binary(Reason), <<"#42S02">>) of + % Table doesn't exist + match -> + case create_msg_table(DBRef, VHost, Date) of @@ -3313,7 +3541,7 @@ index 0000000..7c473ce + error; + ok -> + {updated, _} = sql_query_internal(DBRef, Query), -+ increment_user_stats(DBRef, Msg#msg.owner_name, Owner_id, VHost, Peer_name_id, Peer_server_id, Date) ++ increment_user_stats(DBRef, binary_to_list(Msg#msg.owner_name), Owner_id, VHost, Peer_name_id, Peer_server_id, Date) + end; + _ -> + ?ERROR_MSG("Failed to log message: ~p", [Reason]), @@ -3514,7 +3742,7 @@ index 0000000..7c473ce + ?MYDEBUG("New settings for ~s@~s", [User, VHost]), + ok; + {error, Reason} -> -+ case ejabberd_regexp:run(Reason, "#23000") of ++ case ejabberd_regexp:run(iolist_to_binary(Reason), <<"#23000">>) of + % Already exists + match -> + ok; @@ -3888,7 +4116,7 @@ index 0000000..7c473ce + rebuild_all_stats_int(State), + ok; + {error, Reason} -> -+ case ejabberd_regexp:run(Reason, "#42S01") of ++ case ejabberd_regexp:run(iolist_to_binary(Reason), <<"#42S01">>) of + match -> + ?MYDEBUG("Stats table for ~p already exists", [VHost]), + CheckQuery = ["SHOW COLUMNS FROM ",SName," LIKE 'peer_%_id';"], @@ -4077,7 +4305,7 @@ index 0000000..7c473ce + NewId; + {error, Reason} -> + % this can be in clustered environment -+ match = ejabberd_regexp:run(Reason, "#23000"), ++ match = ejabberd_regexp:run(iolist_to_binary(Reason), <<"#23000">>), + ?ERROR_MSG("Duplicate key name for ~p", [User]), + {ok, ClID} = get_user_id_from_db(DBRef, VHost, User), + ClID @@ -4102,7 +4330,7 @@ index 0000000..7c473ce + Id; + {error, Reason} -> + % this can be in clustered environment -+ match = ejabberd_regexp:run(Reason, "#23000"), ++ match = ejabberd_regexp:run(iolist_to_binary(Reason), <<"#23000">>), + ?ERROR_MSG("Duplicate key name for ~p", [Server]), + update_servers_from_db(DBRef, VHost), + [[Id1]] = ets:match(ets_servers_table(VHost), {Server, '$1'}), @@ -4113,7 +4341,7 @@ index 0000000..7c473ce + +get_resource_id_from_db(DBRef, VHost, Resource) -> + SQuery = ["SELECT resource_id FROM ",resources_table(VHost)," ", -+ "WHERE resource=\"",ejabberd_odbc:escape(Resource),"\";"], ++ "WHERE resource=\"",binary_to_list(ejabberd_odbc:escape(iolist_to_binary(Resource))),"\";"], + case sql_query_internal(DBRef, SQuery) of + % no such resource in db + {data, []} -> @@ -4132,15 +4360,15 @@ index 0000000..7c473ce + % no such resource in db + {ok, []} -> + IQuery = ["INSERT INTO ",resources_table(VHost)," ", -+ "SET resource=\"",ejabberd_odbc:escape(Resource),"\";"], ++ "SET resource=\"",binary_to_list(ejabberd_odbc:escape(iolist_to_binary(Resource))),"\";"], + case sql_query_internal_silent(DBRef, IQuery) of + {updated, _} -> + {ok, NewId} = get_resource_id_from_db(DBRef, VHost, Resource), + NewId; + {error, Reason} -> + % this can be in clustered environment -+ match = ejabberd_regexp:run(Reason, "#23000"), -+ ?ERROR_MSG("Duplicate key name for ~p", [Resource]), ++ match = ejabberd_regexp:run(iolist_to_binary(Reason), <<"#23000">>), ++ ?ERROR_MSG("Duplicate key name for ~s", [Resource]), + {ok, ClID} = get_resource_id_from_db(DBRef, VHost, Resource), + ClID + end; @@ -4165,23 +4393,23 @@ index 0000000..7c473ce + +sql_query_internal_silent(DBRef, Query) -> + ?MYDEBUG("DOING: \"~s\"", [lists:append(Query)]), -+ get_result(mysql_conn:fetch(DBRef, Query, self(), ?MYSQL_TIMEOUT)). ++ get_result(p1_mysql_conn:fetch(DBRef, Query, self(), ?MYSQL_TIMEOUT)). + +get_result({updated, MySQLRes}) -> -+ {updated, mysql:get_result_affected_rows(MySQLRes)}; ++ {updated, p1_mysql:get_result_affected_rows(MySQLRes)}; +get_result({data, MySQLRes}) -> -+ {data, mysql:get_result_rows(MySQLRes)}; ++ {data, p1_mysql:get_result_rows(MySQLRes)}; +get_result({error, "query timed out"}) -> + {error, "query timed out"}; +get_result({error, MySQLRes}) -> -+ Reason = mysql:get_result_reason(MySQLRes), ++ Reason = p1_mysql:get_result_reason(MySQLRes), + {error, Reason}. -diff --git src/mod_logdb_mysql5.erl src/mod_logdb_mysql5.erl +diff --git a/src/mod_logdb_mysql5.erl b/src/mod_logdb_mysql5.erl new file mode 100644 -index 0000000..59efc77 +index 0000000..d1f399f --- /dev/null -+++ src/mod_logdb_mysql5.erl -@@ -0,0 +1,979 @@ ++++ b/src/mod_logdb_mysql5.erl +@@ -0,0 +1,983 @@ +%%%---------------------------------------------------------------------- +%%% File : mod_logdb_mysql5.erl +%%% Author : Oleg Palij (mailto,xmpp:o.palij@gmail.com) @@ -4197,6 +4425,7 @@ index 0000000..59efc77 +-include("mod_logdb.hrl"). +-include("ejabberd.hrl"). +-include("jlib.hrl"). ++-include("logger.hrl"). + +-behaviour(gen_logdb). +-behaviour(gen_server). @@ -4230,7 +4459,7 @@ index 0000000..59efc77 +% replace "." with "_" +escape_vhost(VHost) -> lists:map(fun(46) -> 95; + (A) -> A -+ end, VHost). ++ end, binary_to_list(VHost)). +prefix() -> + "`logdb_". + @@ -4286,11 +4515,11 @@ index 0000000..59efc77 +init([VHost, Opts]) -> + crypto:start(), + -+ Server = gen_mod:get_opt(server, Opts, "localhost"), -+ Port = gen_mod:get_opt(port, Opts, 3306), -+ DB = gen_mod:get_opt(db, Opts, "logdb"), -+ User = gen_mod:get_opt(user, Opts, "root"), -+ Password = gen_mod:get_opt(password, Opts, ""), ++ Server = gen_mod:get_opt(server, Opts, fun(A) -> A end, <<"localhost">>), ++ Port = gen_mod:get_opt(port, Opts, fun(A) -> A end, 3306), ++ DB = gen_mod:get_opt(db, Opts, fun(A) -> A end, <<"logdb">>), ++ User = gen_mod:get_opt(user, Opts, fun(A) -> A end, <<"root">>), ++ Password = gen_mod:get_opt(password, Opts, fun(A) -> A end, <<"">>), + + St = #state{vhost=VHost, + server=Server, port=Port, db=DB, @@ -4324,11 +4553,13 @@ index 0000000..59efc77 + ?MYDEBUG(Format, Argument) + end, + ?INFO_MSG("Opening mysql connection ~s@~s:~p/~s", [DBUser, Server, Port, DB]), -+ mysql_conn:start(Server, Port, DBUser, Password, DB, [65536, 131072], LogFun). ++ p1_mysql_conn:start(binary_to_list(Server), Port, ++ binary_to_list(DBUser), binary_to_list(Password), ++ binary_to_list(DB), LogFun). + +close_mysql_connection(DBRef) -> + ?MYDEBUG("Closing ~p mysql connection", [DBRef]), -+ mysql_conn:stop(DBRef). ++ catch p1_mysql_conn:stop(DBRef). + +handle_call({rebuild_stats_at, Date}, _From, #state{dbref=DBRef, vhost=VHost}=State) -> + Reply = rebuild_stats_at_int(DBRef, VHost, Date), @@ -4513,7 +4744,7 @@ index 0000000..59efc77 + ?MYDEBUG("New settings for ~s@~s", [User, VHost]), + ok; + {error, Reason} -> -+ case ejabberd_regexp:run(Reason, "#23000") of ++ case ejabberd_regexp:run(iolist_to_binary(Reason), <<"#23000">>) of + % Already exists + match -> + ok; @@ -4544,20 +4775,20 @@ index 0000000..59efc77 + Query = [ "CALL ",logmessage_name(VHost)," " + "('", TableName, "',", + "'", Date, "',", -+ "'", Msg#msg.owner_name, "',", -+ "'", Msg#msg.peer_name, "',", -+ "'", Msg#msg.peer_server, "',", -+ "'", ejabberd_odbc:escape(Msg#msg.peer_resource), "',", ++ "'", binary_to_list(Msg#msg.owner_name), "',", ++ "'", binary_to_list(Msg#msg.peer_name), "',", ++ "'", binary_to_list(Msg#msg.peer_server), "',", ++ "'", binary_to_list( ejabberd_odbc:escape(Msg#msg.peer_resource) ), "',", + "'", atom_to_list(Msg#msg.direction), "',", -+ "'", Msg#msg.type, "',", -+ "'", ejabberd_odbc:escape(Msg#msg.subject), "',", -+ "'", ejabberd_odbc:escape(Msg#msg.body), "',", ++ "'", binary_to_list(Msg#msg.type), "',", ++ "'", binary_to_list( ejabberd_odbc:escape(Msg#msg.subject) ), "',", ++ "'", binary_to_list( ejabberd_odbc:escape(Msg#msg.body) ), "',", + "'", Msg#msg.timestamp, "');"], + + case sql_query_internal(DBRef, Query) of + {updated, _} -> -+ ?MYDEBUG("Logged ok for ~p, peer: ~p", [Msg#msg.owner_name++"@"++VHost, -+ Msg#msg.peer_name++"@"++Msg#msg.peer_server]), ++ ?MYDEBUG("Logged ok for ~s, peer: ~s", [ [Msg#msg.owner_name, <<"@">>, VHost], ++ [Msg#msg.peer_name, <<"@">>, Msg#msg.peer_server] ]), + ok; + {error, _Reason} -> + error @@ -4725,9 +4956,10 @@ index 0000000..59efc77 + Count = sql_query_internal(DBRef, ["SELECT count(*) FROM ",Table,";"]), + case Count of + {data, [["0"]]} -> -+ {updated, _} = sql_query_internal(DBRef, ["DROP VIEW IF EXISTS ",view_table(VHost,Date),";"]), + {updated, _} = sql_query_internal(DBRef, ["DROP TABLE ",Table,";"]), -+ {updated, _} = sql_query_internal(DBRef, ["LOCK TABLE ",STable," WRITE;"]), ++ sql_query_internal(DBRef, ["UNLOCK TABLES;"]), ++ {updated, _} = sql_query_internal(DBRef, ["DROP VIEW IF EXISTS ",view_table(VHost,Date),";"]), ++ {updated, _} = sql_query_internal(DBRef, ["LOCK TABLE ",STable," WRITE, ",TempTable," WRITE;"]), + {updated, _} = sql_query_internal(DBRef, DQuery), + ok; + _ -> @@ -4886,7 +5118,7 @@ index 0000000..59efc77 + rebuild_all_stats_int(State), + ok; + {error, Reason} -> -+ case ejabberd_regexp:run(Reason, "#42S01") of ++ case ejabberd_regexp:run(iolist_to_binary(Reason), <<"#42S01">>) of + match -> + ?MYDEBUG("Stats table for ~p already exists", [VHost]), + CheckQuery = ["SHOW COLUMNS FROM ",SName," LIKE 'peer_%_id';"], @@ -5000,16 +5232,16 @@ index 0000000..59efc77 + +sql_query_internal_silent(DBRef, Query) -> + ?MYDEBUG("DOING: \"~s\"", [lists:append(Query)]), -+ get_result(mysql_conn:fetch(DBRef, Query, self(), ?MYSQL_TIMEOUT)). ++ get_result(p1_mysql_conn:fetch(DBRef, Query, self(), ?MYSQL_TIMEOUT)). + +get_result({updated, MySQLRes}) -> -+ {updated, mysql:get_result_affected_rows(MySQLRes)}; ++ {updated, p1_mysql:get_result_affected_rows(MySQLRes)}; +get_result({data, MySQLRes}) -> -+ {data, mysql:get_result_rows(MySQLRes)}; ++ {data, p1_mysql:get_result_rows(MySQLRes)}; +get_result({error, "query timed out"}) -> + {error, "query timed out"}; +get_result({error, MySQLRes}) -> -+ Reason = mysql:get_result_reason(MySQLRes), ++ Reason = p1_mysql:get_result_reason(MySQLRes), + {error, Reason}. + +get_user_id(DBRef, VHost, User) -> @@ -5025,7 +5257,7 @@ index 0000000..59efc77 + DBIdNew; + {error, Reason} -> + % this can be in clustered environment -+ match = ejabberd_regexp:run(Reason, "#23000"), ++ match = ejabberd_regexp:run(iolist_to_binary(Reason), <<"#23000">>), + ?ERROR_MSG("Duplicate key name for ~p", [User]), + {data, [[ClID]]} = sql_query_internal(DBRef, SQuery), + ClID @@ -5161,12 +5393,15 @@ index 0000000..59efc77 + END IF; + END IF; +END;", [logmessage_name(VHost),UName,UName,UName,UName,SName,SName,RName,RName,UName,UName,SName,RName,StName,StName]). -diff --git src/mod_logdb_pgsql.erl src/mod_logdb_pgsql.erl +diff --git a/src/mod_logdb_pgsql.erl b/src/mod_logdb_pgsql.erl new file mode 100644 -index 0000000..1227519 +index 0000000..3c2ae95 --- /dev/null -+++ src/mod_logdb_pgsql.erl -@@ -0,0 +1,1104 @@ ++++ b/src/mod_logdb_pgsql.erl +@@ -0,0 +1,1108 @@ ++% {ok, DBRef} = pgsql:connect([{host, "127.0.0.1"}, {database, "logdb"}, {user, "logdb"}, {password, "logdb"}, {port, 5432}, {as_binary, true}]). ++% Schema = "test". ++% pgsql:squery(DBRef, "CREATE TABLE test.\"logdb_stats_test\" (owner_id INTEGER, peer_name_id INTEGER, peer_server_id INTEGER, at VARCHAR(20), count integer);" ). +%%%---------------------------------------------------------------------- +%%% File : mod_logdb_pgsql.erl +%%% Author : Oleg Palij (mailto,xmpp:o.palij@gmail.com) @@ -5182,6 +5417,7 @@ index 0000000..1227519 +-include("mod_logdb.hrl"). +-include("ejabberd.hrl"). +-include("jlib.hrl"). ++-include("logger.hrl"). + +-behaviour(gen_logdb). +-behaviour(gen_server). @@ -5216,7 +5452,7 @@ index 0000000..1227519 +% replace "." with "_" +escape_vhost(VHost) -> lists:map(fun(46) -> 95; + (A) -> A -+ end, VHost). ++ end, binary_to_list(VHost)). + +prefix(Schema) -> + Schema ++ ".\"" ++ "logdb_". @@ -5270,14 +5506,14 @@ index 0000000..1227519 +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init([VHost, Opts]) -> -+ Server = gen_mod:get_opt(server, Opts, "localhost"), -+ DB = gen_mod:get_opt(db, Opts, "ejabberd_logdb"), -+ User = gen_mod:get_opt(user, Opts, "root"), -+ Port = gen_mod:get_opt(port, Opts, 5432), -+ Password = gen_mod:get_opt(password, Opts, ""), -+ Schema = gen_mod:get_opt(schema, Opts, "public"), ++ Server = gen_mod:get_opt(server, Opts, fun(A) -> A end, <<"localhost">>), ++ DB = gen_mod:get_opt(db, Opts, fun(A) -> A end, <<"ejabberd_logdb">>), ++ User = gen_mod:get_opt(user, Opts, fun(A) -> A end, <<"root">>), ++ Port = gen_mod:get_opt(port, Opts, fun(A) -> A end, 5432), ++ Password = gen_mod:get_opt(password, Opts, fun(A) -> A end, <<"">>), ++ Schema = binary_to_list(gen_mod:get_opt(schema, Opts, fun(A) -> A end, <<"public">>)), + -+ ?MYDEBUG("Starting pgsql backend for ~p", [VHost]), ++ ?MYDEBUG("Starting pgsql backend for ~s", [VHost]), + + St = #state{vhost=VHost, + server=Server, port=Port, db=DB, @@ -5325,21 +5561,21 @@ index 0000000..1227519 + "('", TableName, "',", + "'", ViewName, "',", + "'", Date, "',", -+ "'", Msg#msg.owner_name, "',", -+ "'", Msg#msg.peer_name, "',", -+ "'", Msg#msg.peer_server, "',", -+ "'", ejabberd_odbc:escape(Msg#msg.peer_resource), "',", ++ "'", binary_to_list(Msg#msg.owner_name), "',", ++ "'", binary_to_list(Msg#msg.peer_name), "',", ++ "'", binary_to_list(Msg#msg.peer_server), "',", ++ "'", binary_to_list( ejabberd_odbc:escape(Msg#msg.peer_resource) ), "',", + "'", atom_to_list(Msg#msg.direction), "',", -+ "'", Msg#msg.type, "',", -+ "'", ejabberd_odbc:escape(Msg#msg.subject), "',", -+ "'", ejabberd_odbc:escape(Msg#msg.body), "',", ++ "'", binary_to_list(Msg#msg.type), "',", ++ "'", binary_to_list( ejabberd_odbc:escape(Msg#msg.subject) ), "',", ++ "'", binary_to_list( ejabberd_odbc:escape(Msg#msg.body) ), "',", + "'", Msg#msg.timestamp, "');"], + + case sql_query_internal_silent(DBRef, Query) of + % TODO: change this + {data, [{"0"}]} -> -+ ?MYDEBUG("Logged ok for ~p, peer: ~p", [Msg#msg.owner_name++"@"++VHost, -+ Msg#msg.peer_name++"@"++Msg#msg.peer_server]), ++ ?MYDEBUG("Logged ok for ~s, peer: ~s", [ [Msg#msg.owner_name, <<"@">>, VHost], ++ [Msg#msg.peer_name, <<"@">>, Msg#msg.peer_server] ]), + ok; + {error, _Reason} -> + error @@ -5503,7 +5739,7 @@ index 0000000..1227519 + dolog_list=string_to_list(DoLogL), + donotlog_list=string_to_list(DoNotLogL)}}; + {error, Reason} -> -+ ?ERROR_MSG("Failed to get_user_settings for ~p@~p: ~p", [User, VHost, Reason]), ++ ?ERROR_MSG("Failed to get_user_settings for ~s@~s: ~p", [User, VHost, Reason]), + error + end, + {reply, Reply, State}; @@ -5742,7 +5978,7 @@ index 0000000..1227519 + + case sql_transaction_internal(DBRef, Fun) of + {atomic, _} -> -+ ?INFO_MSG("Rebuilded stats for ~p at ~p", [VHost, Date]), ++ ?INFO_MSG("Rebuilded stats for ~s at ~s", [VHost, Date]), + ok; + {aborted, Reason} -> + ?ERROR_MSG("Failed to rebuild stats for ~s table: ~p.", [Date, Reason]), @@ -5879,20 +6115,20 @@ index 0000000..1227519 + {value, {code, "42P07"}} -> + exists; + _ -> -+ ?ERROR_MSG("Failed to create stats table for ~p: ~p", [VHost, Reason]), ++ ?ERROR_MSG("Failed to create stats table for ~s: ~p", [VHost, Reason]), + error + end + end + end, + case sql_transaction_internal(DBRef, Fun) of + {atomic, created} -> -+ ?MYDEBUG("Created stats table for ~p", [VHost]), ++ ?MYDEBUG("Created stats table for ~s", [VHost]), + rebuild_all_stats_int(State), + ok; + {atomic, exists} -> -+ ?MYDEBUG("Stats table for ~p already exists", [VHost]), ++ ?MYDEBUG("Stats table for ~s already exists", [VHost]), + {match, [{F, L}]} = re:run(SName, "\".*\""), -+ QTable = lists:sublist(SName, F+1, L-2), ++ QTable = lists:sublist(SName, F+2, L-2), + OIDQuery = ["SELECT c.oid FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relname='",QTable,"' AND pg_catalog.pg_table_is_visible(c.oid);"], + {data,[{OID}]} = sql_query_internal(DBRef, OIDQuery), + CheckQuery = ["SELECT a.attname FROM pg_catalog.pg_attribute a WHERE a.attrelid = '",OID,"' AND a.attnum > 0 AND NOT a.attisdropped AND a.attname ~ '^peer_.*_id$';"], @@ -5924,15 +6160,15 @@ index 0000000..1227519 + ], + case sql_query_internal_silent(DBRef, Query) of + {updated, _} -> -+ ?MYDEBUG("Created settings table for ~p", [VHost]), ++ ?MYDEBUG("Created settings table for ~s", [VHost]), + ok; + {error, Reason} -> + case lists:keysearch(code, 1, Reason) of + {value, {code, "42P07"}} -> -+ ?MYDEBUG("Settings table for ~p already exists", [VHost]), ++ ?MYDEBUG("Settings table for ~s already exists", [VHost]), + ok; + _ -> -+ ?ERROR_MSG("Failed to create settings table for ~p: ~p", [VHost, Reason]), ++ ?ERROR_MSG("Failed to create settings table for ~s: ~p", [VHost, Reason]), + error + end + end. @@ -5956,17 +6192,17 @@ index 0000000..1227519 + {value, {code, "42P07"}} -> + exists; + _ -> -+ ?ERROR_MSG("Failed to create users table for ~p: ~p", [VHost, Reason]), ++ ?ERROR_MSG("Failed to create users table for ~s: ~p", [VHost, Reason]), + error + end + end + end, + case sql_transaction_internal(DBRef, Fun) of + {atomic, created} -> -+ ?MYDEBUG("Created users table for ~p", [VHost]), ++ ?MYDEBUG("Created users table for ~s", [VHost]), + ok; + {atomic, exists} -> -+ ?MYDEBUG("Users table for ~p already exists", [VHost]), ++ ?MYDEBUG("Users table for ~s already exists", [VHost]), + ok; + {aborted, _} -> error + end. @@ -5989,17 +6225,17 @@ index 0000000..1227519 + {value, {code, "42P07"}} -> + exists; + _ -> -+ ?ERROR_MSG("Failed to create servers table for ~p: ~p", [VHost, Reason]), ++ ?ERROR_MSG("Failed to create servers table for ~s: ~p", [VHost, Reason]), + error + end + end + end, + case sql_transaction_internal(DBRef, Fun) of + {atomic, created} -> -+ ?MYDEBUG("Created servers table for ~p", [VHost]), ++ ?MYDEBUG("Created servers table for ~s", [VHost]), + ok; + {atomic, exists} -> -+ ?MYDEBUG("Servers table for ~p already exists", [VHost]), ++ ?MYDEBUG("Servers table for ~s already exists", [VHost]), + ok; + {aborted, _} -> error + end. @@ -6021,17 +6257,17 @@ index 0000000..1227519 + {value, {code, "42P07"}} -> + exists; + _ -> -+ ?ERROR_MSG("Failed to create users table for ~p: ~p", [VHost, Reason]), ++ ?ERROR_MSG("Failed to create users table for ~s: ~p", [VHost, Reason]), + error + end + end + end, + case sql_transaction_internal(DBRef, Fun) of + {atomic, created} -> -+ ?MYDEBUG("Created resources table for ~p", [VHost]), ++ ?MYDEBUG("Created resources table for ~s", [VHost]), + ok; + {atomic, exists} -> -+ ?MYDEBUG("Resources table for ~p already exists", [VHost]), ++ ?MYDEBUG("Resources table for ~s already exists", [VHost]), + ok; + {aborted, _} -> error + end. @@ -6228,7 +6464,7 @@ index 0000000..1227519 + {updated, 1}; +get_result({ok, ["CREATE FUNCTION"]}) -> + {updated, 1}; -+get_result({ok, [{"SELECT", _Rows, Recs}]}) -> ++get_result({ok, [{[$S, $E, $L, $E, $C, $T, $ | _Rest], _Rows, Recs}]}) -> + Fun = fun(Rec) -> + list_to_tuple( + lists:map(fun(Elem) when is_binary(Elem) -> @@ -6271,13 +6507,13 @@ index 0000000..1227519 +get_result(Rez) -> + {error, undefined, Rez}. + -diff --git src/mod_muc/mod_muc_room.erl src/mod_muc/mod_muc_room.erl -index 02c83ed..7693b66 100644 ---- src/mod_muc/mod_muc_room.erl -+++ src/mod_muc/mod_muc_room.erl -@@ -726,6 +726,12 @@ handle_sync_event({change_config, Config}, _From, StateName, StateData) -> - {reply, {ok, NSD#state.config}, StateName, NSD}; - handle_sync_event({change_state, NewStateData}, _From, StateName, _StateData) -> +diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl +index b1c5c92..df99681 100644 +--- a/src/mod_muc_room.erl ++++ b/src/mod_muc_room.erl +@@ -743,6 +743,12 @@ handle_sync_event({change_config, Config}, _From, + handle_sync_event({change_state, NewStateData}, _From, + StateName, _StateData) -> {reply, {ok, NewStateData}, StateName, NewStateData}; +handle_sync_event({get_jid_nick, Jid}, _From, StateName, StateData) -> + R = case ?DICT:find(jlib:jid_tolower(Jid), StateData#state.users) of @@ -6285,24 +6521,24 @@ index 02c83ed..7693b66 100644 + {ok, {user, _, Nick, _, _}} -> Nick + end, + {reply, R, StateName, StateData}; - handle_sync_event(_Event, _From, StateName, StateData) -> - Reply = ok, - {reply, Reply, StateName, StateData}. -diff --git src/mod_roster.erl src/mod_roster.erl -index b15497f..ace8ba7 100644 ---- src/mod_roster.erl -+++ src/mod_roster.erl -@@ -62,6 +62,8 @@ - -include("web/ejabberd_http.hrl"). - -include("web/ejabberd_web_admin.hrl"). + handle_sync_event(_Event, _From, StateName, + StateData) -> + Reply = ok, {reply, Reply, StateName, StateData}. +diff --git a/src/mod_roster.erl b/src/mod_roster.erl +index 7415aa3..f2a69f9 100644 +--- a/src/mod_roster.erl ++++ b/src/mod_roster.erl +@@ -60,6 +60,8 @@ + + -include("ejabberd_web_admin.hrl"). +-include("mod_logdb.hrl"). + + -export_type([subscription/0]). start(Host, Opts) -> - IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), -@@ -1334,6 +1336,14 @@ user_roster(User, Server, Query, Lang) -> - Res = user_roster_parse_query(User, Server, Items1, Query), +@@ -1358,6 +1360,14 @@ user_roster(User, Server, Query, Lang) -> + Query), Items = get_roster(LUser, LServer), SItems = lists:sort(Items), + @@ -6313,213 +6549,87 @@ index b15497f..ace8ba7 100644 + [] + end, + - FItems = - case SItems of - [] -> -@@ -1381,7 +1391,33 @@ user_roster(User, Server, Query, Lang) -> - [?INPUTT("submit", - "remove" ++ - ejabberd_web_admin:term_to_id(R#roster.jid), -- "Remove")])]) -+ "Remove")]), -+ case gen_mod:is_loaded(Server, mod_logdb) of -+ true -> -+ Peer = jlib:jid_to_string(R#roster.jid), -+ A = lists:member(Peer, Settings#user_settings.dolog_list), -+ B = lists:member(Peer, Settings#user_settings.donotlog_list), -+ {Name, Value} = -+ if -+ A -> -+ {"donotlog", "Do Not Log Messages"}; -+ B -> -+ {"dolog", "Log Messages"}; -+ Settings#user_settings.dolog_default == true -> -+ {"donotlog", "Do Not Log Messages"}; -+ Settings#user_settings.dolog_default == false -> -+ {"dolog", "Log Messages"} -+ end, -+ -+ ?XAE("td", [{"class", "valign"}], -+ [?INPUTT("submit", -+ Name ++ -+ ejabberd_web_admin:term_to_id(R#roster.jid), -+ Value)]); -+ false -> -+ ?X([]) -+ end -+ ]) - end, SItems))])] - end, - [?XC("h1", ?T("Roster of ") ++ us_to_list(US))] ++ -@@ -1481,11 +1517,42 @@ user_roster_item_parse_query(User, Server, Items, Query) -> - {"subscription", "remove"}], - []}]}}), - throw(submitted); -- false -> -- ok -- end -- -- end -+ false -> -+ case lists:keysearch( -+ "donotlog" ++ ejabberd_web_admin:term_to_id(JID), 1, Query) of -+ {value, _} -> -+ Peer = jlib:jid_to_string(JID), -+ Settings = mod_logdb:get_user_settings(User, Server), -+ DNLL = case lists:member(Peer, Settings#user_settings.donotlog_list) of -+ false -> lists:append(Settings#user_settings.donotlog_list, [Peer]); -+ true -> Settings#user_settings.donotlog_list -+ end, -+ DLL = lists:delete(jlib:jid_to_string(JID), Settings#user_settings.dolog_list), -+ Sett = Settings#user_settings{donotlog_list=DNLL, dolog_list=DLL}, -+ % TODO: check returned value -+ ok = mod_logdb:set_user_settings(User, Server, Sett), -+ throw(nothing); -+ false -> -+ case lists:keysearch( -+ "dolog" ++ ejabberd_web_admin:term_to_id(JID), 1, Query) of -+ {value, _} -> -+ Peer = jlib:jid_to_string(JID), -+ Settings = mod_logdb:get_user_settings(User, Server), -+ DLL = case lists:member(Peer, Settings#user_settings.dolog_list) of -+ false -> lists:append(Settings#user_settings.dolog_list, [Peer]); -+ true -> Settings#user_settings.dolog_list -+ end, -+ DNLL = lists:delete(jlib:jid_to_string(JID), Settings#user_settings.donotlog_list), -+ Sett = Settings#user_settings{donotlog_list=DNLL, dolog_list=DLL}, -+ % TODO: check returned value -+ ok = mod_logdb:set_user_settings(User, Server, Sett), -+ throw(nothing); -+ false -> -+ ok -+ end % dolog -+ end % donotlog -+ end % remove + FItems = case SItems of + [] -> [?CT(<<"None">>)]; + _ -> +@@ -1415,7 +1425,33 @@ user_roster(User, Server, Query, Lang) -> + [?INPUTT(<<"submit">>, + <<"remove", + (ejabberd_web_admin:term_to_id(R#roster.jid))/binary>>, +- <<"Remove">>)])]) ++ <<"Remove">>)]), ++ case gen_mod:is_loaded(Server, mod_logdb) of ++ true -> ++ Peer = jlib:jid_to_string(R#roster.jid), ++ A = lists:member(Peer, Settings#user_settings.dolog_list), ++ B = lists:member(Peer, Settings#user_settings.donotlog_list), ++ {Name, Value} = ++ if ++ A -> ++ {<<"donotlog">>, <<"Do Not Log Messages">>}; ++ B -> ++ {<<"dolog">>, <<"Log Messages">>}; ++ Settings#user_settings.dolog_default == true -> ++ {<<"donotlog">>, <<"Do Not Log Messages">>}; ++ Settings#user_settings.dolog_default == false -> ++ {<<"dolog">>, <<"Log Messages">>} ++ end, ++ ++ ?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], ++ [?INPUTT(<<"submit">>, ++ <>, ++ Value)]); ++ false -> ++ ?X([]) ++ end ++ ]) + end, + SItems)))])] + end, +@@ -1540,9 +1576,42 @@ user_roster_item_parse_query(User, Server, Items, + = + []}]}}), + throw(submitted); +- false -> ok +- end +- end ++ false -> ++ case lists:keysearch( ++ <<"donotlog">>, (ejabberd_web_admin:term_to_id(JID))/binary, 1, Query) of ++ {value, _} -> ++ Peer = jlib:jid_to_string(JID), ++ Settings = mod_logdb:get_user_settings(User, Server), ++ DNLL = case lists:member(Peer, Settings#user_settings.donotlog_list) of ++ false -> lists:append(Settings#user_settings.donotlog_list, [Peer]); ++ true -> Settings#user_settings.donotlog_list ++ end, ++ DLL = lists:delete(jlib:jid_to_string(JID), Settings#user_settings.dolog_list), ++ Sett = Settings#user_settings{donotlog_list=DNLL, dolog_list=DLL}, ++ % TODO: check returned value ++ ok = mod_logdb:set_user_settings(User, Server, Sett), ++ throw(nothing); ++ false -> ++ case lists:keysearch( ++ <<"dolog">>, (ejabberd_web_admin:term_to_id(JID))/binary, 1, Query) of ++ {value, _} -> ++ Peer = jlib:jid_to_string(JID), ++ Settings = mod_logdb:get_user_settings(User, Server), ++ DLL = case lists:member(Peer, Settings#user_settings.dolog_list) of ++ false -> lists:append(Settings#user_settings.dolog_list, [Peer]); ++ true -> Settings#user_settings.dolog_list ++ end, ++ DNLL = lists:delete(jlib:jid_to_string(JID), Settings#user_settings.donotlog_list), ++ Sett = Settings#user_settings{donotlog_list=DNLL, dolog_list=DLL}, ++ % TODO: check returned value ++ ok = mod_logdb:set_user_settings(User, Server, Sett), ++ throw(nothing); ++ false -> ++ ok ++ end % dolog ++ end % donotlog ++ end % remove + end % validate - end, Items), + end, + Items), nothing. - -diff --git src/msgs/nl.msg src/msgs/nl.msg -index 70e739f..019b7b4 100644 ---- src/msgs/nl.msg -+++ src/msgs/nl.msg -@@ -419,3 +419,15 @@ - {"Your Jabber account was successfully created.","Uw Jabber-account is succesvol gecreeerd."}. - {"Your Jabber account was successfully deleted.","Uw Jabber-account is succesvol verwijderd."}. - {"Your messages to ~s are being blocked. To unblock them, visit ~s","Uw berichten aan ~s worden geblokkeerd. Om ze te deblokkeren, ga naar ~s"}. -+% mod_logdb -+{"Users Messages", "Gebruikersberichten"}. -+{"Date", "Datum"}. -+{"Count", "Aantal"}. -+{"Logged messages for ", "Gelogde berichten van "}. -+{" at ", " op "}. -+{"No logged messages for ", "Geen gelogde berichten van "}. -+{"Date, Time", "Datum en tijd"}. -+{"Direction: Jid", "Richting: Jabber ID"}. -+{"Subject", "Onderwerp"}. -+{"Body", "Berichtveld"}. -+{"Messages", "Berichten"}. -diff --git src/msgs/pl.msg src/msgs/pl.msg -index 4bc2063..4395f3c 100644 ---- src/msgs/pl.msg -+++ src/msgs/pl.msg -@@ -419,3 +419,27 @@ - {"Your Jabber account was successfully created.","Twoje konto zostało stworzone."}. - {"Your Jabber account was successfully deleted.","Twoje konto zostało usunięte."}. - {"Your messages to ~s are being blocked. To unblock them, visit ~s","Twoje wiadomości do ~s są blokowane. Aby je odblokować, odwiedź ~s"}. -+% mod_logdb -+{"Users Messages", "Wiadomości użytkownika"}. -+{"Date", "Data"}. -+{"Count", "Liczba"}. -+{"Logged messages for ", "Zapisane wiadomości dla "}. -+{" at ", " o "}. -+{"No logged messages for ", "Brak zapisanych wiadomości dla "}. -+{"Date, Time", "Data, Godzina"}. -+{"Direction: Jid", "Kierunek: Jid"}. -+{"Subject", "Temat"}. -+{"Body", "Treść"}. -+{"Messages","Wiadomości"}. -+{"Filter Selected", "Odfiltruj zaznaczone"}. -+{"Do Not Log Messages", "Nie zapisuj wiadomości"}. -+{"Log Messages", "Zapisuj wiadomości"}. -+{"Messages logging engine", "System zapisywania historii rozmów"}. -+{"Default", "Domyślne"}. -+{"Set logging preferences", "Ustaw preferencje zapisywania"}. -+{"Messages logging engine settings", "Ustawienia systemu logowania"}. -+{"Set run-time settings", "Zapisz ustawienia systemu logowania"}. -+{"Groupchat messages logging", "Zapisywanie rozmów z konferencji"}. -+{"Jids/Domains to ignore", "JID/Domena która ma być ignorowana"}. -+{"Purge messages older than (days)", "Usuń wiadomości starsze niż (w dniach)"}. -+{"Poll users settings (seconds)", "Czas aktualizacji preferencji użytkowników (sekundy)"}. -diff --git src/msgs/ru.msg src/msgs/ru.msg -index ece7348..99879ec 100644 ---- src/msgs/ru.msg -+++ src/msgs/ru.msg -@@ -419,3 +419,31 @@ - {"Your Jabber account was successfully created.","Ваш Jabber-аккаунт был успешно создан."}. - {"Your Jabber account was successfully deleted.","Ваш Jabber-аккаунт был успешно удален."}. - {"Your messages to ~s are being blocked. To unblock them, visit ~s","Ваши сообщения к ~s блокируются. Для снятия блокировки перейдите по ссылке ~s"}. -+% mod_logdb.erl -+{"Users Messages", "Сообщения пользователей"}. -+{"Date", "Дата"}. -+{"Count", "Количество"}. -+{"Logged messages for ", "Сохранённые cообщения для "}. -+{" at ", " за "}. -+{"No logged messages for ", "Отсутствуют сообщения для "}. -+{"Date, Time", "Дата, Время"}. -+{"Direction: Jid", "Направление: Jid"}. -+{"Subject", "Тема"}. -+{"Body", "Текст"}. -+{"Messages", "Сообщения"}. -+{"Filter Selected", "Отфильтровать выделенные"}. -+{"Do Not Log Messages", "Не сохранять сообщения"}. -+{"Log Messages", "Сохранять сообщения"}. -+{"Messages logging engine", "Система логирования сообщений"}. -+{"Default", "По умолчанию"}. -+{"Set logging preferences", "Задайте настройки логирования"}. -+{"Messages logging engine users", "Пользователи системы логирования сообщений"}. -+{"Messages logging engine settings", "Настройки системы логирования сообщений"}. -+{"Set run-time settings", "Задайте текущие настройки"}. -+{"Groupchat messages logging", "Логирование сообщений типа groupchat"}. -+{"Jids/Domains to ignore", "Игнорировать следующие jids/домены"}. -+{"Purge messages older than (days)", "Удалять сообщения старее чем (дни)"}. -+{"Poll users settings (seconds)", "Обновлять настройки пользователей через (секунд)"}. -+{"Drop", "Удалять"}. -+{"Do not drop", "Не удалять"}. -+{"Drop messages on user removal", "Удалять сообщения при удалении пользователя"}. -diff --git src/msgs/uk.msg src/msgs/uk.msg -index 6e21c90..1cdd1ea 100644 ---- src/msgs/uk.msg -+++ src/msgs/uk.msg -@@ -407,3 +407,31 @@ - {"Your Jabber account was successfully created.","Ваш Jabber-акаунт було успішно створено."}. - {"Your Jabber account was successfully deleted.","Ваш Jabber-акаунт було успішно видалено."}. - {"Your messages to ~s are being blocked. To unblock them, visit ~s","Ваші повідомлення до ~s блокуються. Для розблокування відвідайте ~s"}. -+% mod_logdb -+{"Users Messages", "Повідомлення користувачів"}. -+{"Date", "Дата"}. -+{"Count", "Кількість"}. -+{"Logged messages for ", "Збережені повідомлення для "}. -+{" at ", " за "}. -+{"No logged messages for ", "Відсутні повідомлення для "}. -+{"Date, Time", "Дата, Час"}. -+{"Direction: Jid", "Напрямок: Jid"}. -+{"Subject", "Тема"}. -+{"Body", "Текст"}. -+{"Messages", "Повідомлення"}. -+{"Filter Selected", "Відфільтрувати виділені"}. -+{"Do Not Log Messages", "Не зберігати повідомлення"}. -+{"Log Messages", "Зберігати повідомлення"}. -+{"Messages logging engine", "Система збереження повідомлень"}. -+{"Default", "За замовчуванням"}. -+{"Set logging preferences", "Вкажіть налагоджування збереження повідомлень"}. -+{"Messages logging engine users", "Користувачі системи збереження повідомлень"}. -+{"Messages logging engine settings", "Налагоджування системи збереження повідомлень"}. -+{"Set run-time settings", "Вкажіть поточні налагоджування"}. -+{"Groupchat messages logging", "Збереження повідомлень типу groupchat"}. -+{"Jids/Domains to ignore", "Ігнорувати наступні jids/домени"}. -+{"Purge messages older than (days)", "Видаляти повідомлення старіші ніж (дні)"}. -+{"Poll users settings (seconds)", "Оновлювати налагоджування користувачів кожні (секунд)"}. -+{"Drop", "Видаляти"}. -+{"Do not drop", "Не видаляти"}. -+{"Drop messages on user removal", "Видаляти повідомлення під час видалення користувача"}. diff --git a/ejabberd.spec b/ejabberd.spec index 9f2a9f2..2722a74 100644 --- a/ejabberd.spec +++ b/ejabberd.spec @@ -1,14 +1,14 @@ # Conditional build: %bcond_with pam # PAM authentication support -%bcond_with logdb # enable mod_logdb (server-side message logging) +%bcond_without logdb # enable mod_logdb (server-side message logging) %bcond_with weaker_crypto # enable SSLv3 Summary: Fault-tolerant distributed Jabber/XMPP server Summary(pl.UTF-8): Odporny na awarie rozproszony serwer Jabbera/XMPP Name: ejabberd Version: 13.12 -Release: 1 +Release: 2 License: GPL Group: Applications/Communications Source0: http://www.process-one.net/downloads/ejabberd/%{version}/%{name}-%{version}.tgz @@ -54,7 +54,11 @@ Patch0: %{name}-paths.patch Patch1: %{name}-config.patch # not available for 13.10 #Patch2: %{name}-vcard-access-get.patch +# OLD: # http://www.dp.uz.gov.ua/o.palij/mod_logdb/patch-mod_logdb-2.1.12.diff +# CURRENT: +# git tree: https://github.com/paleg/ejabberd/tree/13.12-mod_logdb +# git diff d03de1bb436760afd9cb80f51d367009985fffba > patch Patch3: %{name}-mod_logdb.patch Patch4: %{name}-no_sslv3_or_3des.patch URL: http://www.ejabberd.im/ @@ -107,7 +111,7 @@ Server-side logging module. %patch1 -p1 #%%patch2 -p1 %if %{with logdb} -%patch3 -p0 +%patch3 -p1 %endif %if %{without weaker_crypto} %patch4 -p1 -- 2.44.0