--- /dev/null
+-define(T(S), <<S>>).
-include("logger.hrl").
-include("eldap.hrl").
-include("xmpp.hrl").
+-include("translate.hrl").
-define(PROCNAME, ejabberd_mod_vcard_ldap).
{<<"PHOTO">>, <<"%s">>, [<<"jpegPhoto">>]}].
default_search_fields() ->
- [{translate:mark(<<"User">>), <<"%u">>},
- {translate:mark(<<"Full Name">>), <<"displayName">>},
- {translate:mark(<<"Given Name">>), <<"givenName">>},
- {translate:mark(<<"Middle Name">>), <<"initials">>},
- {translate:mark(<<"Family Name">>), <<"sn">>},
- {translate:mark(<<"Nickname">>), <<"%u">>},
- {translate:mark(<<"Birthday">>), <<"birthDay">>},
- {translate:mark(<<"Country">>), <<"c">>},
- {translate:mark(<<"City">>), <<"l">>},
- {translate:mark(<<"Email">>), <<"mail">>},
- {translate:mark(<<"Organization Name">>), <<"o">>},
- {translate:mark(<<"Organization Unit">>), <<"ou">>}].
+ [{?T("User"), <<"%u">>},
+ {?T("Full Name"), <<"displayName">>},
+ {?T("Given Name"), <<"givenName">>},
+ {?T("Middle Name"), <<"initials">>},
+ {?T("Family Name"), <<"sn">>},
+ {?T("Nickname"), <<"%u">>},
+ {?T("Birthday"), <<"birthDay">>},
+ {?T("Country"), <<"c">>},
+ {?T("City"), <<"l">>},
+ {?T("Email"), <<"mail">>},
+ {?T("Organization Name"), <<"o">>},
+ {?T("Organization Unit"), <<"ou">>}].
default_search_reported() ->
- [{translate:mark(<<"Full Name">>), <<"FN">>},
- {translate:mark(<<"Given Name">>), <<"FIRST">>},
- {translate:mark(<<"Middle Name">>), <<"MIDDLE">>},
- {translate:mark(<<"Family Name">>), <<"LAST">>},
- {translate:mark(<<"Nickname">>), <<"NICK">>},
- {translate:mark(<<"Birthday">>), <<"BDAY">>},
- {translate:mark(<<"Country">>), <<"CTRY">>},
- {translate:mark(<<"City">>), <<"LOCALITY">>},
- {translate:mark(<<"Email">>), <<"EMAIL">>},
- {translate:mark(<<"Organization Name">>), <<"ORGNAME">>},
- {translate:mark(<<"Organization Unit">>), <<"ORGUNIT">>}].
+ [{?T("Full Name"), <<"FN">>},
+ {?T("Given Name"), <<"FIRST">>},
+ {?T("Middle Name"), <<"MIDDLE">>},
+ {?T("Family Name"), <<"LAST">>},
+ {?T("Nickname"), <<"NICK">>},
+ {?T("Birthday"), <<"BDAY">>},
+ {?T("Country"), <<"CTRY">>},
+ {?T("City"), <<"LOCALITY">>},
+ {?T("Email"), <<"EMAIL">>},
+ {?T("Organization Name"), <<"ORGNAME">>},
+ {?T("Organization Unit"), <<"ORGUNIT">>}].
parse_options(Host, Opts) ->
MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"vjud.@HOST@">>),
-include("xmpp.hrl").
-include("mod_vcard.hrl").
-include("logger.hrl").
+-include("translate.hrl").
%%%===================================================================
%%% API
end.
search_fields(_LServer) ->
- [{translate:mark(<<"User">>), <<"user">>},
- {translate:mark(<<"Full Name">>), <<"fn">>},
- {translate:mark(<<"Name">>), <<"first">>},
- {translate:mark(<<"Middle Name">>), <<"middle">>},
- {translate:mark(<<"Family Name">>), <<"last">>},
- {translate:mark(<<"Nickname">>), <<"nick">>},
- {translate:mark(<<"Birthday">>), <<"bday">>},
- {translate:mark(<<"Country">>), <<"ctry">>},
- {translate:mark(<<"City">>), <<"locality">>},
- {translate:mark(<<"Email">>), <<"email">>},
- {translate:mark(<<"Organization Name">>), <<"orgname">>},
- {translate:mark(<<"Organization Unit">>), <<"orgunit">>}].
+ [{?T("User"), <<"user">>},
+ {?T("Full Name"), <<"fn">>},
+ {?T("Name"), <<"first">>},
+ {?T("Middle Name"), <<"middle">>},
+ {?T("Family Name"), <<"last">>},
+ {?T("Nickname"), <<"nick">>},
+ {?T("Birthday"), <<"bday">>},
+ {?T("Country"), <<"ctry">>},
+ {?T("City"), <<"locality">>},
+ {?T("Email"), <<"email">>},
+ {?T("Organization Name"), <<"orgname">>},
+ {?T("Organization Unit"), <<"orgunit">>}].
search_reported(_LServer) ->
- [{translate:mark(<<"Jabber ID">>), <<"jid">>},
- {translate:mark(<<"Full Name">>), <<"fn">>},
- {translate:mark(<<"Name">>), <<"first">>},
- {translate:mark(<<"Middle Name">>), <<"middle">>},
- {translate:mark(<<"Family Name">>), <<"last">>},
- {translate:mark(<<"Nickname">>), <<"nick">>},
- {translate:mark(<<"Birthday">>), <<"bday">>},
- {translate:mark(<<"Country">>), <<"ctry">>},
- {translate:mark(<<"City">>), <<"locality">>},
- {translate:mark(<<"Email">>), <<"email">>},
- {translate:mark(<<"Organization Name">>), <<"orgname">>},
- {translate:mark(<<"Organization Unit">>), <<"orgunit">>}].
+ [{?T("Jabber ID"), <<"jid">>},
+ {?T("Full Name"), <<"fn">>},
+ {?T("Name"), <<"first">>},
+ {?T("Middle Name"), <<"middle">>},
+ {?T("Family Name"), <<"last">>},
+ {?T("Nickname"), <<"nick">>},
+ {?T("Birthday"), <<"bday">>},
+ {?T("Country"), <<"ctry">>},
+ {?T("City"), <<"locality">>},
+ {?T("Email"), <<"email">>},
+ {?T("Organization Name"), <<"orgname">>},
+ {?T("Organization Unit"), <<"orgunit">>}].
remove_user(LUser, LServer) ->
US = {LUser, LServer},
-include("mod_vcard.hrl").
-include("logger.hrl").
-include("ejabberd_sql_pt.hrl").
+-include("translate.hrl").
%%%===================================================================
%%% API
end.
search_fields(_LServer) ->
- [{translate:mark(<<"User">>), <<"user">>},
- {translate:mark(<<"Full Name">>), <<"fn">>},
- {translate:mark(<<"Name">>), <<"first">>},
- {translate:mark(<<"Middle Name">>), <<"middle">>},
- {translate:mark(<<"Family Name">>), <<"last">>},
- {translate:mark(<<"Nickname">>), <<"nick">>},
- {translate:mark(<<"Birthday">>), <<"bday">>},
- {translate:mark(<<"Country">>), <<"ctry">>},
- {translate:mark(<<"City">>), <<"locality">>},
- {translate:mark(<<"Email">>), <<"email">>},
- {translate:mark(<<"Organization Name">>), <<"orgname">>},
- {translate:mark(<<"Organization Unit">>), <<"orgunit">>}].
+ [{?T("User"), <<"user">>},
+ {?T("Full Name"), <<"fn">>},
+ {?T("Name"), <<"first">>},
+ {?T("Middle Name"), <<"middle">>},
+ {?T("Family Name"), <<"last">>},
+ {?T("Nickname"), <<"nick">>},
+ {?T("Birthday"), <<"bday">>},
+ {?T("Country"), <<"ctry">>},
+ {?T("City"), <<"locality">>},
+ {?T("Email"), <<"email">>},
+ {?T("Organization Name"), <<"orgname">>},
+ {?T("Organization Unit"), <<"orgunit">>}].
search_reported(_LServer) ->
- [{translate:mark(<<"Jabber ID">>), <<"jid">>},
- {translate:mark(<<"Full Name">>), <<"fn">>},
- {translate:mark(<<"Name">>), <<"first">>},
- {translate:mark(<<"Middle Name">>), <<"middle">>},
- {translate:mark(<<"Family Name">>), <<"last">>},
- {translate:mark(<<"Nickname">>), <<"nick">>},
- {translate:mark(<<"Birthday">>), <<"bday">>},
- {translate:mark(<<"Country">>), <<"ctry">>},
- {translate:mark(<<"City">>), <<"locality">>},
- {translate:mark(<<"Email">>), <<"email">>},
- {translate:mark(<<"Organization Name">>), <<"orgname">>},
- {translate:mark(<<"Organization Unit">>), <<"orgunit">>}].
+ [{?T("Jabber ID"), <<"jid">>},
+ {?T("Full Name"), <<"fn">>},
+ {?T("Name"), <<"first">>},
+ {?T("Middle Name"), <<"middle">>},
+ {?T("Family Name"), <<"last">>},
+ {?T("Nickname"), <<"nick">>},
+ {?T("Birthday"), <<"bday">>},
+ {?T("Country"), <<"ctry">>},
+ {?T("City"), <<"locality">>},
+ {?T("Email"), <<"email">>},
+ {?T("Organization Name"), <<"orgname">>},
+ {?T("Organization Unit"), <<"orgunit">>}].
remove_user(LUser, LServer) ->
ejabberd_sql:sql_transaction(
-behaviour(gen_server).
--export([start_link/0, reload/0, translate/2, mark/1]).
+-export([start_link/0, reload/0, translate/2]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
end
end.
--spec mark(binary()) -> binary().
-mark(Msg) ->
- Msg.
-
ascii_tolower(B) ->
iolist_to_binary(ascii_tolower_s(binary_to_list(B))).
Txts =
filelib:fold_files(
Dir, ".+\.beam\$", false,
- fun(FileIn, Res) ->
- case get_forms(FileIn) of
- {ok, Forms} ->
- Tree = erl_syntax:form_list(Forms),
- Mod = mod(FileIn),
- erl_syntax_lib:fold_subtrees(
- fun(Form, Acc) ->
- case erl_syntax:type(Form) of
- function ->
- case map(Form, Mod) of
- [] ->
- Acc;
- Vars ->
- Vars ++ Acc
- end;
- _ ->
- Acc
- end
- end, [], Tree) ++ Res;
+ fun(BeamFile, Res) ->
+ Mod = mod(BeamFile),
+ ErlFile = filename:join("src", Mod ++ ".erl"),
+ case get_forms(BeamFile, ErlFile) of
+ {ok, BeamForms, ErlForms} ->
+ process_forms(BeamForms, Mod, application) ++
+ process_forms(ErlForms, Mod, macro) ++ Res;
_Err ->
Res
end
end, dict:new(), Txts),
generate_pot(Dict).
-map(Tree, Mod) ->
+process_forms(Forms, Mod, Type) ->
+ Tree = erl_syntax:form_list(Forms),
+ erl_syntax_lib:fold_subtrees(
+ fun(Form, Acc) ->
+ case erl_syntax:type(Form) of
+ function ->
+ case map(Form, Mod, Type) of
+ [] ->
+ Acc;
+ Vars ->
+ Vars ++ Acc
+ end;
+ _ ->
+ Acc
+ end
+ end, [], Tree).
+
+map(Tree, Mod, Type) ->
Vars = erl_syntax_lib:fold(
fun(Form, Acc) ->
case erl_syntax:type(Form) of
- application ->
+ Type when Type == application ->
analyze_app(Form, Mod) ++ Acc;
+ Type when Type == macro ->
+ analyze_macro(Form, Mod) ++ Acc;
_ ->
Acc
end
{xmpp, "err_" ++ _, 2, [T|_]} -> T;
{xmpp, "serr_" ++ _, 2, [T|_]} -> T;
{xmpp, "mk_text", 2, [T|_]} -> T;
- {translate, "translate", 2, [_,T|_]} -> T;
- {translate, "mark", 1, [T]} -> T
+ {translate, "translate", 2, [_,T|_]} -> T
end,
Pos = erl_syntax:get_pos(Txt),
case erl_syntax:type(Txt) of
[]
end.
+analyze_macro(Form, Mod) ->
+ try
+ Name = erl_syntax:macro_name(Form),
+ variable = erl_syntax:type(Name),
+ 'T' = erl_syntax:variable_name(Name),
+ [Txt] = erl_syntax:macro_arguments(Form),
+ string = erl_syntax:type(Txt),
+ Pos = erl_syntax:get_pos(Txt),
+ try [{list_to_binary(erl_syntax:string_value(Txt)), Pos}]
+ catch _:_ ->
+ log("~s:~p: not a binary: ~s~n",
+ [Mod, Pos, erl_prettypr:format(Txt)]),
+ []
+ end
+ catch _:{badmatch, _} ->
+ []
+ end.
+
generate_pot(Dict) ->
io:format("~s~n~n", [pot_header()]),
lists:foreach(
io_lib:nl()).
mod(Path) ->
- filename:rootname(filename:basename(Path)) ++ ".erl".
+ filename:rootname(filename:basename(Path)).
log(Format, Args) ->
io:format(standard_error, Format, Args).
-get_forms(File) ->
+get_forms(BeamFile, ErlFile) ->
+ try
+ {ok, BeamForms} = get_beam_forms(BeamFile),
+ {ok, ErlForms} = get_erl_forms(ErlFile),
+ {ok, BeamForms, ErlForms}
+ catch _:{badmatch, error} ->
+ error
+ end.
+
+get_beam_forms(File) ->
case beam_lib:chunks(File, [abstract_code]) of
{ok, {_, List}} ->
case lists:keyfind(abstract_code, 1, List) of
{abstract_code, {raw_abstract_v1, Abstr}} ->
{ok, Abstr};
- _ ->
+ _Err ->
+ log("failed to get abstract code from ~s~n", [File]),
error
end;
- _ ->
+ Err ->
+ log("failed to read chunks from ~s: ~p~n", [File, Err]),
+ error
+ end.
+
+get_erl_forms(Path) ->
+ case file:open(Path, [read]) of
+ {ok, Fd} ->
+ parse(Path, Fd, 1, []);
+ {error, Why} ->
+ log("failed to read ~s: ~s~n", [Path, file:format_error(Why)]),
error
end.
+
+parse(Path, Fd, Line, Acc) ->
+ {ok, Pos} = file:position(Fd, cur),
+ case epp_dodger:parse_form(Fd, Line) of
+ {ok, Form, NewLine} ->
+ {ok, NewPos} = file:position(Fd, cur),
+ {ok, RawForm} = file:pread(Fd, Pos, NewPos - Pos),
+ file:position(Fd, {bof, NewPos}),
+ AnnForm = erl_syntax:set_ann(Form, RawForm),
+ parse(Path, Fd, NewLine, [AnnForm|Acc]);
+ {eof, _} ->
+ {ok, NewPos} = file:position(Fd, cur),
+ if NewPos > Pos ->
+ {ok, RawForm} = file:pread(Fd, Pos, NewPos - Pos),
+ Form = erl_syntax:text(""),
+ AnnForm = erl_syntax:set_ann(Form, RawForm),
+ {ok, lists:reverse([AnnForm|Acc])};
+ true ->
+ {ok, lists:reverse(Acc)}
+ end;
+ Err ->
+ log("failed to parse ~s: ~p~n", [Path, Err]),
+ error
+ end.