25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

* (all): Changed JID storage format, added support for stringprep

* src/stringprep/: Added support for Unicode normalization form KC

* src/stringprep/: Added support for case convertion to multiple
characters

* src/cyrsasl_digest.erl: Temporary removed "auth-int" QOP

SVN Revision: 144
This commit is contained in:
Alexey Shchepin 2003-10-07 20:31:44 +00:00
parent e1de741cfc
commit 61875f80b3
26 changed files with 1328 additions and 1200 deletions

View File

@ -1,3 +1,16 @@
2003-10-07 Alexey Shchepin <alexey@sevcom.net>
* (all): Changed JID storage format, added support for stringprep
* src/stringprep/: Added support for Unicode normalization form KC
2003-10-05 Alexey Shchepin <alexey@sevcom.net>
* src/stringprep/: Added support for case convertion to multiple
characters
* src/cyrsasl_digest.erl: Temporary removed "auth-int" QOP
2003-09-28 Alexey Shchepin <alexey@sevcom.net>
* src/stringprep/stringprep_drv.c: Added support for nameprep,

View File

@ -49,7 +49,7 @@ check_authzid(State, Props) ->
error ->
{error, "invalid-authzid"};
JID ->
LUser = xml:get_attr_s(username, Props),
LUser = jlib:nodeprep(xml:get_attr_s(username, Props)),
{U, S, R} = jlib:jid_tolower(JID),
case R of
"" ->

View File

@ -34,7 +34,8 @@ mech_new() ->
mech_step(#state{step = 1, nonce = Nonce} = State, "") ->
{continue,
"nonce=\"" ++ jlib:encode_base64(Nonce) ++
"\",qop=\"auth,auth-int\",charset=utf-8,algorithm=md5-sess",
"\",qop=\"auth\",charset=utf-8,algorithm=md5-sess",
%"\",qop=\"auth,auth-int\",charset=utf-8,algorithm=md5-sess",
State#state{step = 3}};
mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
case parse(ClientIn) of

View File

@ -109,7 +109,7 @@ terminate(Reason, State) ->
%%%----------------------------------------------------------------------
check_password(User, Password) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read({passwd, LUser}) of
[#passwd{password = Password}] ->
true;
@ -118,7 +118,7 @@ check_password(User, Password) ->
end.
check_password(User, Password, StreamID, Digest) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
case mnesia:read({passwd, LUser}) of
[E] ->
@ -144,14 +144,14 @@ check_password(User, Password, StreamID, Digest) ->
set_password(User, Password) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
mnesia:write(#passwd{user = LUser, password = Password})
end,
mnesia:transaction(F).
try_register(User, Password) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
case mnesia:read({passwd, LUser}) of
[] ->
@ -168,7 +168,7 @@ dirty_get_registered_users() ->
mnesia:dirty_all_keys(passwd).
get_password(User) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read(passwd, LUser) of
[#passwd{password = Password}] ->
Password;
@ -177,7 +177,7 @@ get_password(User) ->
end.
get_password_s(User) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read(passwd, LUser) of
[#passwd{password = Password}] ->
Password;
@ -186,7 +186,7 @@ get_password_s(User) ->
end.
is_user_exists(User) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read({passwd, LUser}) of
[] ->
false;
@ -197,14 +197,14 @@ is_user_exists(User) ->
end.
remove_user(User) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
mnesia:delete({passwd, LUser})
end,
mnesia:transaction(F).
remove_user(User, Password) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
case mnesia:read({passwd, LUser}) of
[#passwd{password = Password}] ->

View File

@ -45,6 +45,7 @@
access,
shaper,
authentificated = false,
jid,
user = "", server = ?MYNAME, resource = "",
pres_t = ?SETS:new(),
pres_f = ?SETS:new(),
@ -205,7 +206,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
{next_state, wait_for_auth, StateData};
{auth, ID, set, {U, P, D, R}} ->
io:format("AUTH: ~p~n", [{U, P, D, R}]),
JID = {U, ?MYNAME, R},
JID = jlib:make_jid(U, StateData#state.server, R),
case acl:match_rule(StateData#state.access, JID) of
allow ->
case ejabberd_auth:check_password(
@ -224,6 +225,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
{next_state, session_established,
StateData#state{user = U,
resource = R,
jid = JID,
pres_f = ?SETS:from_list(Fs),
pres_t = ?SETS:from_list(Ts),
privacy_list = PrivList}};
@ -281,12 +283,14 @@ wait_for_sasl_auth({xmlstreamelement, El}, StateData) ->
send_element(StateData,
{xmlelement, "success",
[{"xmlns", ?NS_SASL}], []}),
{U, _, R} = jlib:string_to_jid(
JID = #jid{user = U, resource = R} =
jlib:string_to_jid(
xml:get_attr_s(authzid, Props)),
{next_state, wait_for_stream,
StateData#state{authentificated = true,
user = U,
resource = R
resource = R,
jid = JID
}};
{continue, ServerOut, NewSASLState} ->
send_element(StateData,
@ -344,12 +348,13 @@ wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
send_element(StateData,
{xmlelement, "success",
[{"xmlns", ?NS_SASL}], []}),
{U, _, R} = jlib:string_to_jid(
xml:get_attr_s(authzid, Props)),
JID = #jid{user = U, resource = R} =
jlib:string_to_jid(xml:get_attr_s(authzid, Props)),
{next_state, wait_for_stream,
StateData#state{authentificated = true,
user = U,
resource = R
resource = R,
jid = JID
}};
{continue, ServerOut, NewSASLState} ->
send_element(StateData,
@ -402,7 +407,7 @@ wait_for_session({xmlstreamelement, El}, StateData) ->
U = StateData#state.user,
R = StateData#state.resource,
io:format("SASLAUTH: ~p~n", [{U, R}]),
JID = {U, ?MYNAME, R},
JID = jlib:make_jid(U, StateData#state.server, R),
case acl:match_rule(StateData#state.access, JID) of
allow ->
ejabberd_sm:open_session(U, R),
@ -457,13 +462,14 @@ session_established({xmlstreamelement, El}, StateData) ->
{xmlelement, Name, Attrs, Els} = El,
User = StateData#state.user,
Server = StateData#state.server,
FromJID = {User,
Server,
StateData#state.resource},
%FromJID = {User,
% Server,
% StateData#state.resource},
FromJID = StateData#state.jid,
To = xml:get_attr_s("to", Attrs),
ToJID = case To of
"" ->
{User, Server, ""};
jlib:make_jid(User, Server, "");
_ ->
jlib:string_to_jid(To)
end,
@ -476,7 +482,9 @@ session_established({xmlstreamelement, El}, StateData) ->
case Name of
"presence" ->
case ToJID of
{User, Server, ""} ->
#jid{user = User,
server = Server,
resource = ""} ->
?DEBUG("presence_update(~p,~n\t~p,~n\t~p)",
[FromJID, El, StateData]),
presence_update(FromJID, El, StateData);
@ -573,7 +581,6 @@ handle_info(replaced, StateName, StateData) ->
{stop, normal, StateData#state{user = ""}};
handle_info({route, From, To, Packet}, StateName, StateData) ->
{xmlelement, Name, Attrs, Els} = Packet,
{FU, FS, FR} = From,
{Pass, NewAttrs, NewState} =
case Name of
"presence" ->
@ -694,9 +701,7 @@ terminate(Reason, StateName, StateData) ->
_ ->
ejabberd_sm:close_session(StateData#state.user,
StateData#state.resource),
From = {StateData#state.user,
StateData#state.server,
StateData#state.resource},
From = StateData#state.jid,
Packet = {xmlelement, "presence", [{"type", "unavailable"}], []},
ejabberd_sm:unset_presence(StateData#state.user,
StateData#state.resource),
@ -797,16 +802,17 @@ get_auth_tags([], U, P, D, R) ->
process_presence_probe(From, To, StateData) ->
LFrom = jlib:jid_tolower(From),
case StateData#state.pres_last of
undefined ->
ok;
_ ->
Cond1 = (not StateData#state.pres_invis)
and ?SETS:is_element(From, StateData#state.pres_f)
and (not ?SETS:is_element(From, StateData#state.pres_i)),
and ?SETS:is_element(LFrom, StateData#state.pres_f)
and (not ?SETS:is_element(LFrom, StateData#state.pres_i)),
Cond2 = StateData#state.pres_invis
and ?SETS:is_element(From, StateData#state.pres_f)
and ?SETS:is_element(From, StateData#state.pres_a),
and ?SETS:is_element(LFrom, StateData#state.pres_f)
and ?SETS:is_element(LFrom, StateData#state.pres_a),
if
Cond1 ->
ejabberd_router:route(To, From,
@ -934,14 +940,16 @@ presence_track(From, To, Packet, StateData) ->
presence_broadcast(From, JIDSet, Packet) ->
lists:foreach(fun(JID) ->
ejabberd_router:route(From, JID, Packet)
ejabberd_router:route(
From, jlib:make_jid(JID), Packet)
end, ?SETS:to_list(JIDSet)).
presence_broadcast_to_trusted(From, T, A, Packet) ->
lists:foreach(fun(JID) ->
case ?SETS:is_element(JID, T) of
true ->
ejabberd_router:route(From, JID, Packet);
ejabberd_router:route(
From, jlib:make_jid(JID), Packet);
_ ->
ok
end
@ -949,9 +957,10 @@ presence_broadcast_to_trusted(From, T, A, Packet) ->
presence_broadcast_first(From, StateData, Packet) ->
{U, S, _} = From,
?SETS:fold(fun(JID, X) ->
ejabberd_router:route({U, S, ""}, JID,
ejabberd_router:route(
jlib:jid_replace_resource(From, ""),
jlib:make_jid(JID),
{xmlelement, "presence",
[{"type", "probe"}],
[]}),
@ -964,7 +973,9 @@ presence_broadcast_first(From, StateData, Packet) ->
StateData;
true ->
As = ?SETS:fold(fun(JID, A) ->
ejabberd_router:route(From, JID, Packet),
ejabberd_router:route(From,
jlib:make_jid(JID),
Packet),
?SETS:add_element(JID, A)
end,
StateData#state.pres_a,
@ -1003,9 +1014,7 @@ roster_change(IJID, ISubscription, StateData) ->
StateData#state{pres_f = FSet, pres_t = TSet};
P ->
?DEBUG("roster changed for ~p~n", [StateData#state.user]),
From = {StateData#state.user,
StateData#state.server,
StateData#state.resource},
From = StateData#state.jid,
Cond1 = (not StateData#state.pres_invis) and IsFrom,
Cond2 = (not IsFrom)
and (?SETS:is_element(LIJID, StateData#state.pres_a) or
@ -1013,7 +1022,7 @@ roster_change(IJID, ISubscription, StateData) ->
if
Cond1 ->
?DEBUG("C1: ~p~n", [LIJID]),
ejabberd_router:route(From, IJID, P),
ejabberd_router:route(From, jlib:make_jid(IJID), P),
A = ?SETS:add_element(LIJID,
StateData#state.pres_a),
StateData#state{pres_a = A,
@ -1021,7 +1030,7 @@ roster_change(IJID, ISubscription, StateData) ->
pres_t = TSet};
Cond2 ->
?DEBUG("C2: ~p~n", [LIJID]),
ejabberd_router:route(From, IJID,
ejabberd_router:route(From, jlib:make_jid(IJID),
{xmlelement, "presence",
[{"type", "unavailable"}], []}),
I = remove_element(LIJID,

View File

@ -71,7 +71,7 @@ do_route(State, From, To, Packet) ->
?DEBUG("local route~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
[From, To, Packet, 8]),
case To of
{"", _, ""} ->
#jid{luser = "", lresource = ""} ->
{xmlelement, Name, Attrs, Els} = Packet,
case Name of
"iq" ->
@ -83,11 +83,12 @@ do_route(State, From, To, Packet) ->
_ ->
ok
end;
{"", _, _} ->
#jid{luser = ""} ->
Err = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND),
ejabberd_router ! {route,
{"", State#state.mydomain, ""}, From, Err},
ok;
jlib:make_jid("", State#state.mydomain, ""),
From,
Err};
_ ->
ejabberd_sm ! {route, From, To, Packet}
end.

View File

@ -22,6 +22,7 @@
-export([start_link/0, init/0]).
-include("ejabberd.hrl").
-include("jlib.hrl").
-record(route, {domain, node, pid}).
-record(local_route, {domain, pid}).
@ -101,8 +102,7 @@ loop() ->
do_route(From, To, Packet) ->
?DEBUG("route~n\tfrom ~p~n\tto ~p~n\tpacket ~p~n", [From, To, Packet]),
{DstNode, DstDomain, DstResourse} = To,
LDstDomain = jlib:tolower(DstDomain),
#jid{lserver = LDstDomain} = To,
case mnesia:dirty_read({local_route, LDstDomain}) of
[] ->
case mnesia:dirty_read({route, LDstDomain}) of

View File

@ -18,6 +18,7 @@
-include_lib("mnemosyne/include/mnemosyne.hrl").
-include("ejabberd.hrl").
-include("jlib.hrl").
-record(s2s, {fromto, node, key}).
-record(local_s2s, {fromto, pid}).
@ -148,8 +149,8 @@ try_register(FromTo) ->
do_route(From, To, Packet) ->
?DEBUG("s2s manager~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
[From, To, Packet, 8]),
{_, MyServer, _} = From,
{User, Server, Resource} = To,
#jid{lserver = MyServer} = From,
#jid{lserver = Server} = To,
FromTo = {MyServer, Server},
Key = randoms:get_string(),
case find_connection(FromTo, Key) of

View File

@ -266,7 +266,7 @@ stream_established({xmlstreamelement, El}, StateData) ->
From = xml:get_attr_s("from", Attrs),
FromJID1 = jlib:string_to_jid(From),
FromJID = case FromJID1 of
{Node, Server, Resource} ->
#jid{lserver = Server} ->
if Server == StateData#state.server -> FromJID1;
true -> error
end;

View File

@ -102,7 +102,7 @@ close_session(User, Resource) ->
register_connection(User, Resource, Pid) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
UR = {LUser, Resource},
F = fun() ->
Ss = mnesia:wread({session, UR}),
@ -132,7 +132,7 @@ register_connection(User, Resource, Pid) ->
replace_my_connection(User, Resource) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
UR = {LUser, Resource},
Es = mnesia:read({local_session, UR}),
@ -151,7 +151,7 @@ replace_my_connection(User, Resource) ->
remove_connection(User, Resource) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
UR = {LUser, Resource},
mnesia:delete({local_session, UR}),
@ -177,33 +177,34 @@ clean_table_from_bad_node(Node) ->
do_route(From, To, Packet) ->
?DEBUG("session manager~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
[From, To, Packet, 8]),
{User, Server, Resource} = To,
#jid{user = User, server = Server, resource = Resource,
luser = LUser, lserver = LServer, lresource = LResource} = To,
{xmlelement, Name, Attrs, Els} = Packet,
case Resource of
"" ->
case Name of
"presence" ->
{FU, FS, FR} = From,
FromU = jlib:jid_replace_resource(From, ""),
{Pass, Subsc} =
case xml:get_attr_s("type", Attrs) of
"subscribe" ->
{mod_roster:in_subscription(User,
{FU, FS, ""},
FromU,
subscribe),
true};
"subscribed" ->
{mod_roster:in_subscription(User,
{FU, FS, ""},
FromU,
subscribed),
true};
"unsubscribe" ->
{mod_roster:in_subscription(User,
{FU, FS, ""},
FromU,
unsubscribe),
true};
"unsubscribed" ->
{mod_roster:in_subscription(User,
{FU, FS, ""},
FromU,
unsubscribed),
true};
_ ->
@ -211,8 +212,6 @@ do_route(From, To, Packet) ->
end,
if Pass ->
LFrom = jlib:jid_tolower(From),
LUser = jlib:tolower(User),
LServer = jlib:tolower(Server),
Resources = get_user_resources(User),
if
Resources /= [] ->
@ -223,7 +222,7 @@ do_route(From, To, Packet) ->
ejabberd_sm !
{route,
From,
{User, Server, R},
jlib:jid_replace_resource(To, R),
Packet};
true ->
ok
@ -250,21 +249,25 @@ do_route(From, To, Packet) ->
fun(R) ->
ejabberd_sm ! {route,
From,
{User, Server, R},
jlib:jid_replace_resource(To, R),
Packet}
end, get_user_resources(User));
_ ->
ok
end;
_ ->
LUR = {jlib:tolower(User), Resource},
LUR = {LUser, LResource},
Sess = mnesia:dirty_read({session, LUR}),
case Sess of
[] ->
if
Name == "message" ->
case Name of
"message" ->
route_message(From, To, Packet);
true ->
"iq" ->
Err = jlib:make_error_reply(
Packet, ?ERR_RECIPIENT_UNAVAILABLE),
ejabberd_router:route(To, From, Err);
_ ->
?DEBUG("packet droped~n", [])
end;
[Ses] ->
@ -282,10 +285,10 @@ do_route(From, To, Packet) ->
end.
route_message(From, To, Packet) ->
{User, Server, Resource} = To,
case catch lists:max(get_user_present_resources(User)) of
#jid{luser = LUser} = To,
case catch lists:max(get_user_present_resources(LUser)) of
{'EXIT', _} ->
case ejabberd_auth:is_user_exists(User) of
case ejabberd_auth:is_user_exists(LUser) of
true ->
case catch mod_offline:store_packet(From, To, Packet) of
{'EXIT', _} ->
@ -303,7 +306,7 @@ route_message(From, To, Packet) ->
{_, R} ->
ejabberd_sm ! {route,
From,
{User, Server, R},
jlib:jid_replace_resource(To, R),
Packet}
end.
@ -311,7 +314,7 @@ route_message(From, To, Packet) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_user_resources(User) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_index_read(session, LUser, #session.user) of
{'EXIT', Reason} ->
[];
@ -325,7 +328,7 @@ get_user_resources(User) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
set_presence(User, Resource, Priority) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
UR = {User, Resource},
mnesia:write(#presence{ur = UR, user = LUser,
@ -334,15 +337,14 @@ set_presence(User, Resource, Priority) ->
mnesia:transaction(F).
unset_presence(User, Resource) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
UR = {User, Resource},
mnesia:delete({presence, UR})
end,
mnesia:transaction(F).
get_user_present_resources(User) ->
LUser = jlib:tolower(User),
get_user_present_resources(LUser) ->
case catch mnesia:dirty_index_read(presence, LUser, #presence.user) of
{'EXIT', Reason} ->
[];
@ -367,7 +369,7 @@ process_iq(From, To, Packet) ->
{iq, ID, Type, XMLNS, SubEl} ->
case ets:lookup(sm_iqtable, XMLNS) of
[{_, Module, Function}] ->
ResIQ = apply(Module, Function, [From, To, IQ]),
ResIQ = Module:Function(From, To, IQ),
if
ResIQ /= ignore ->
ejabberd_router ! {route,

View File

@ -18,12 +18,18 @@
replace_from_to_attrs/3,
replace_from_to/3,
remove_attr/2,
make_jid/3,
make_jid/1,
string_to_jid/1,
jid_to_string/1,
is_nodename/1,
tolower/1,
nodeprep/1,
nameprep/1,
resourceprep/1,
jid_tolower/1,
jid_remove_resource/1,
jid_replace_resource/2,
get_iq_namespace/1,
iq_query_info/1,
is_iq_request_type/1,
@ -130,6 +136,30 @@ remove_attr(Attr, {xmlelement, Name, Attrs, Els}) ->
NewAttrs = lists:keydelete(Attr, 1, Attrs),
{xmlelement, Name, NewAttrs, Els}.
make_jid(User, Server, Resource) ->
case stringprep:nodeprep(User) of
error -> error;
LUser ->
case stringprep:nameprep(Server) of
error -> error;
LServer ->
case stringprep:resourceprep(Resource) of
error -> error;
LResource ->
#jid{user = User,
server = Server,
resource = Resource,
luser = LUser,
lserver = LServer,
lresource = LResource}
end
end
end.
make_jid({User, Server, Resource}) ->
make_jid(User, Server, Resource).
string_to_jid(J) ->
string_to_jid1(J, "").
@ -157,7 +187,7 @@ string_to_jid1([C | J], N) ->
string_to_jid1([], "") ->
error;
string_to_jid1([], N) ->
{"", lists:reverse(N), ""}.
make_jid("", lists:reverse(N), "").
string_to_jid2([$/ | J], N, "") ->
error;
@ -168,13 +198,15 @@ string_to_jid2([C | J], N, S) ->
string_to_jid2([], N, "") ->
error;
string_to_jid2([], N, S) ->
{N, lists:reverse(S), ""}.
make_jid(N, lists:reverse(S), "").
string_to_jid3([C | J], N, S, R) ->
string_to_jid3(J, N, S, [C | R]);
string_to_jid3([], N, S, R) ->
{N, S, lists:reverse(R)}.
make_jid(N, S, lists:reverse(R)).
jid_to_string(#jid{user = User, server = Server, resource = Resource}) ->
jid_to_string({User, Server, Resource});
jid_to_string({Node, Server, Resource}) ->
S1 = case Node of
"" ->
@ -256,13 +288,34 @@ tolower([]) ->
% [].
nodeprep(S) ->
stringprep:nodeprep(S).
nameprep(S) ->
stringprep:nameprep(S).
resourceprep(S) ->
stringprep:resourceprep(S).
jid_tolower(#jid{luser = U, lserver = S, lresource = R}) ->
{U, S, R};
jid_tolower({U, S, R}) ->
{tolower(U), tolower(S), R}.
jid_remove_resource(#jid{} = JID) ->
JID#jid{resource = "", lresource = ""};
jid_remove_resource({U, S, R}) ->
{U, S, ""}.
jid_replace_resource(JID, Resource) ->
case stringprep:resourceprep(Resource) of
error -> error;
LResource ->
JID#jid{resource = Resource, lresource = LResource}
end.
get_iq_namespace({xmlelement, Name, Attrs, Els}) when Name == "iq" ->
case xml:remove_cdata(Els) of
[{xmlelement, Name2, Attrs2, Els2}] ->
@ -276,9 +329,6 @@ get_iq_namespace(_) ->
iq_query_info({xmlelement, Name, Attrs, Els}) when Name == "iq" ->
ID = xml:get_attr_s("id", Attrs),
Type = xml:get_attr_s("type", Attrs),
case xml:remove_cdata(Els) of
[{xmlelement, Name2, Attrs2, Els2}] ->
XMLNS = xml:get_attr_s("xmlns", Attrs2),
Type1 = case Type of
"set" -> set;
"get" -> get;
@ -287,19 +337,22 @@ iq_query_info({xmlelement, Name, Attrs, Els}) when Name == "iq" ->
_ -> invalid
end,
if
(Type1 /= invalid) and (Type1 /= reply) and (XMLNS /= "") ->
(Type1 /= invalid) and (Type1 /= reply) ->
case xml:remove_cdata(Els) of
[{xmlelement, Name2, Attrs2, Els2}] ->
XMLNS = xml:get_attr_s("xmlns", Attrs2),
if
XMLNS /= "" ->
{iq, ID, Type1, XMLNS, {xmlelement, Name2, Attrs2, Els2}};
true ->
if
Type1 == reply ->
reply;
true ->
invalid
end
end;
_ ->
invalid
end;
true ->
Type1
end;
iq_query_info(_) ->
not_iq.

View File

@ -138,4 +138,6 @@
% ?STREAM_ERROR("")).
-record(jid, {user, server, resource,
luser, lserver, lresource}).

View File

@ -436,7 +436,7 @@ get_stopped_nodes(Lang) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
process_sm_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
{User, _, _} = To,
#jid{user = User} = To,
case {acl:match_rule(configure, From), Type} of
{deny, _} ->
{iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]};

View File

@ -57,7 +57,7 @@ loop(Host) ->
do_route(Host, From, To, Packet) ->
{ChanServ, _, Resource} = To,
#jid{user = ChanServ, resource = Resource} = To,
case ChanServ of
"" ->
case Resource of
@ -75,12 +75,11 @@ do_route(Host, From, To, Packet) ->
iq_data(From, To, ID, XMLNS, Type, SubEl);
_ ->
Err = jlib:make_error_reply(
Packet, "503", "Service Unavailable"),
Packet, ?ERR_SERVICE_UNAVAILABLE),
ejabberd_router:route(To, From, Err)
end;
_ ->
Err = jlib:make_error_reply(Packet,
"406", "Not Acceptable"),
Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST),
ejabberd_router:route(To, From, Err)
end;
_ ->
@ -115,8 +114,7 @@ do_route(Host, From, To, Packet) ->
case ets:lookup(irc_connection, {From, Server}) of
[] ->
Err = jlib:make_error_reply(
Packet,
"503", "Service Unavailable"),
Packet, ?ERR_SERVICE_UNAVAILABLE),
ejabberd_router:route(To, From, Err);
[R] ->
Pid = R#irc_connection.pid,
@ -128,7 +126,7 @@ do_route(Host, From, To, Packet) ->
end;
_ ->
Err = jlib:make_error_reply(
Packet, "406", "Not Acceptable"),
Packet, ?ERR_BAD_REQUEST),
ejabberd_router:route(To, From, Err)
end
end
@ -185,9 +183,7 @@ process_iq_data(From, To, ID, XMLNS, Type, SubEl) ->
case XData of
invalid ->
{iq, ID, error, XMLNS,
[SubEl, {xmlelement, "error",
[{"code", "400"}],
[{xmlcdata, "Bad Request"}]}]};
[SubEl, ?ERR_BAD_REQUEST]};
_ ->
Node =
string:tokens(
@ -227,8 +223,8 @@ process_iq_data(From, To, ID, XMLNS, Type, SubEl) ->
get_form(From, [], Lang) ->
{User, Server, _} = From,
{LUser, LServer, _} = jlib:jid_tolower(From),
#jid{user = User, server = Server,
luser = LUser, lserver = LServer} = From,
Customs =
case catch mnesia:dirty_read({irc_custom, {LUser, LServer}}) of
{'EXIT', Reason} ->
@ -345,8 +341,8 @@ set_form(_, _, Lang, XData) ->
get_user_and_encoding(From, IRCServer) ->
{User, Server, _} = From,
{LUser, LServer, _} = jlib:jid_tolower(From),
#jid{user = User, server = Server,
luser = LUser, lserver = LServer} = From,
case catch mnesia:dirty_read({irc_custom, {LUser, LServer}}) of
{'EXIT', Reason} ->
{User, ?DEFAULT_IRC_ENCODING};

View File

@ -36,7 +36,7 @@
channels = dict:new(),
inbuf = "", outbuf = ""}).
-define(DBGFSM, true).
%-define(DBGFSM, true).
-ifdef(DBGFSM).
-define(FSMOPTS, [{debug, [trace]}]).
@ -411,7 +411,7 @@ handle_info({ircstring, [$: | String]}, StateName, StateData) ->
[From, "NICK", Nick | _] ->
process_nick(StateData, From, Nick);
_ ->
io:format("unknown irc command '~s'~n", [String]),
?DEBUG("unknown irc command '~s'~n", [String]),
StateData
end,
NewStateData1 =
@ -431,7 +431,7 @@ handle_info({ircstring, [$E, $R, $R, $O, $R | _] = String},
handle_info({ircstring, String}, StateName, StateData) ->
io:format("unknown irc command '~s'~n", [String]),
?DEBUG("unknown irc command '~s'~n", [String]),
{next_state, StateName, StateData};
@ -441,7 +441,7 @@ handle_info({send_text, Text}, StateName, StateData) ->
handle_info({tcp, Socket, Data}, StateName, StateData) ->
Buf = StateData#state.inbuf ++ binary_to_list(Data),
{ok, Strings} = regexp:split([C || C <- Buf, C /= $\r], "\n"),
io:format("strings=~p~n", [Strings]),
?DEBUG("strings=~p~n", [Strings]),
NewBuf = process_lines(StateData#state.encoding, Strings),
{next_state, StateName, StateData#state{inbuf = NewBuf}};
handle_info({tcp_closed, Socket}, StateName, StateData) ->
@ -499,7 +499,7 @@ receiver(Socket, C2SPid, XMLStreamPid) ->
send_text(#state{socket = Socket, encoding = Encoding}, Text) ->
CText = iconv:convert("utf-8", Encoding, lists:flatten(Text)),
%io:format("IRC OUTu: ~s~nIRC OUTk: ~s~n", [Text, CText]),
%?DEBUG("IRC OUTu: ~s~nIRC OUTk: ~s~n", [Text, CText]),
gen_tcp:send(Socket, CText).

View File

@ -59,6 +59,7 @@
-record(state, {room,
host,
jid,
config = #config{},
users = ?DICT:new(),
affiliations = ?DICT:new(),
@ -117,11 +118,13 @@ init([Host, Room, Creator, Nick]) ->
LCreator = jlib:jid_tolower(Creator),
State = set_affiliation(Creator, owner,
#state{host = Host,
room = Room}),
room = Room,
jid = jlib:make_jid(Room, Host, "")}),
{ok, normal_state, State};
init([Host, Room, Opts]) ->
State = set_opts(Opts, #state{host = Host,
room = Room}),
room = Room,
jid = jlib:make_jid(Room, Host, "")}),
{ok, normal_state, State}.
%%----------------------------------------------------------------------
@ -173,9 +176,9 @@ normal_state({route, From, "",
lists:foreach(
fun({LJID, Info}) ->
ejabberd_router:route(
{StateData#state.room,
StateData#state.host,
FromNick},
jlib:jid_replace_resource(
StateData#state.jid,
FromNick),
Info#user.jid,
Packet)
end,
@ -189,8 +192,7 @@ normal_state({route, From, "",
Err = jlib:make_error_reply(
Packet, ?ERR_NOT_ALLOWED),
ejabberd_router:route(
{StateData#state.room,
StateData#state.host, ""},
StateData#state.jid,
From, Err),
{next_state, normal_state, StateData}
end;
@ -198,7 +200,7 @@ normal_state({route, From, "",
Err = jlib:make_error_reply(
Packet, ?ERR_NOT_ALLOWED),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, ""},
StateData#state.jid,
From, Err),
{next_state, normal_state, StateData}
end;
@ -223,7 +225,7 @@ normal_state({route, From, "",
Err = jlib:make_error_reply(
Packet, ?ERR_NOT_ALLOWED),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, ""},
StateData#state.jid,
From, Err),
{next_state, normal_state, StateData};
IJID ->
@ -249,15 +251,14 @@ normal_state({route, From, "",
Err = jlib:make_error_reply(
Packet, ?ERR_NOT_ALLOWED),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, ""},
StateData#state.jid,
From, Err),
{next_state, normal_state, StateData}
end;
_ ->
Err = jlib:make_error_reply(
Packet, ?ERR_NOT_ALLOWED),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, ""}, From, Err),
ejabberd_router:route(StateData#state.jid, From, Err),
{next_state, normal_state, StateData}
end;
@ -293,9 +294,7 @@ normal_state({route, From, "",
[SubEl, Error]},
StateData}
end,
ejabberd_router:route({StateData#state.room,
StateData#state.host,
""},
ejabberd_router:route(StateData#state.jid,
From,
jlib:iq_to_xml(IQRes)),
case NewStateData of
@ -307,8 +306,7 @@ normal_state({route, From, "",
_ ->
Err = jlib:make_error_reply(
Packet, ?ERR_FEATURE_NOT_IMPLEMENTED),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, ""}, From, Err),
ejabberd_router:route(StateData#state.jid, From, Err),
{next_state, normal_state, StateData}
end;
@ -353,9 +351,9 @@ normal_state({route, From, Nick,
Packet,
?ERR_MUC_NICK_CHANGE_CONFLICT),
ejabberd_router:route(
{StateData#state.room,
StateData#state.host,
Nick}, % TODO: s/Nick/""/
jlib:jid_replace_resource(
StateData#state.jid,
Nick), % TODO: s/Nick/""/
From, Err),
StateData;
_ ->
@ -411,18 +409,18 @@ normal_state({route, From, ToNick,
Err = jlib:make_error_reply(
Packet, ?ERR_ITEM_NOT_FOUND),
ejabberd_router:route(
{StateData#state.room,
StateData#state.host,
ToNick},
jlib:jid_replace_resource(
StateData#state.jid,
ToNick),
From, Err);
ToJID ->
{ok, #user{nick = FromNick}} =
?DICT:find(jlib:jid_tolower(From),
StateData#state.users),
ejabberd_router:route(
{StateData#state.room,
StateData#state.host,
FromNick},
jlib:jid_replace_resource(
StateData#state.jid,
FromNick),
ToJID, Packet)
end,
{next_state, normal_state, StateData};
@ -430,9 +428,9 @@ normal_state({route, From, ToNick,
Err = jlib:make_error_reply(
Packet, ?ERR_NOT_ALLOWED),
ejabberd_router:route(
{StateData#state.room,
StateData#state.host,
ToNick}, From, Err),
jlib:jid_replace_resource(
StateData#state.jid,
ToNick), From, Err),
{next_state, normal_state, StateData}
end
end;
@ -448,21 +446,22 @@ normal_state({route, From, ToNick,
Err = jlib:make_error_reply(
Packet, ?ERR_ITEM_NOT_FOUND),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, ToNick},
jlib:jid_replace_resource(StateData#state.jid, ToNick),
From, Err);
ToJID ->
{ok, #user{nick = FromNick}} =
?DICT:find(jlib:jid_tolower(From),
StateData#state.users),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, FromNick},
jlib:jid_replace_resource(StateData#state.jid, FromNick),
ToJID, Packet)
end;
_ ->
Err = jlib:make_error_reply(
Packet, ?ERR_NOT_ALLOWED),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, ToNick}, From, Err)
jlib:jid_replace_resource(StateData#state.jid, ToNick), From,
Err)
end,
{next_state, normal_state, StateData};
@ -490,9 +489,7 @@ handle_event({service_message, Msg}, StateName, StateData) ->
lists:foreach(
fun({LJID, Info}) ->
ejabberd_router:route(
{StateData#state.room,
StateData#state.host,
""},
StateData#state.jid,
Info#user.jid,
MessagePkt)
end,
@ -792,9 +789,8 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
true ->
Err = jlib:make_error_reply(Packet, ?ERR_MUC_NICK_CONFLICT),
ejabberd_router:route(
{StateData#state.room,
StateData#state.host,
Nick}, % TODO: s/Nick/""/
% TODO: s/Nick/""/
jlib:jid_replace_resource(StateData#state.jid, Nick),
From, Err),
StateData;
_ ->
@ -809,7 +805,7 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
_ -> ?ERR_MUC_NOT_MEMBER
end),
ejabberd_router:route( % TODO: s/Nick/""/
{StateData#state.room, StateData#state.host, Nick},
jlib:jid_replace_resource(StateData#state.jid, Nick),
From, Err),
StateData;
_ ->
@ -833,7 +829,8 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
Err = jlib:make_error_reply(
Packet, ?ERR_MUC_BAD_PASSWORD),
ejabberd_router:route( % TODO: s/Nick/""/
{StateData#state.room, StateData#state.host, Nick},
jlib:jid_replace_resource(
StateData#state.jid, Nick),
From, Err),
StateData
end
@ -922,7 +919,7 @@ send_new_presence(NJID, StateData) ->
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
[{xmlelement, "item", ItemAttrs, []}]}]),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, Nick},
jlib:jid_replace_resource(StateData#state.jid, Nick),
Info#user.jid,
Packet)
end, ?DICT:to_list(StateData#state.users)).
@ -963,7 +960,8 @@ send_existing_presences(ToJID, StateData) ->
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
[{xmlelement, "item", ItemAttrs, []}]}]),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, FromNick},
jlib:jid_replace_resource(
StateData#state.jid, FromNick),
RealToJID,
Packet)
end
@ -1033,11 +1031,11 @@ send_nick_changing(JID, OldNick, StateData) ->
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
[{xmlelement, "item", ItemAttrs2, []}]}]),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, OldNick},
jlib:jid_replace_resource(StateData#state.jid, OldNick),
Info#user.jid,
Packet1),
ejabberd_router:route(
{StateData#state.room, StateData#state.host, Nick},
jlib:jid_replace_resource(StateData#state.jid, Nick),
Info#user.jid,
Packet2)
end, ?DICT:to_list(StateData#state.users)).
@ -1086,7 +1084,7 @@ send_history(JID, StateData) ->
lists:foldl(
fun({Nick, Packet, HaveSubject}, B) ->
ejabberd_router:route(
{StateData#state.room, StateData#state.host, Nick},
jlib:jid_replace_resource(StateData#state.jid, Nick),
JID,
Packet),
B or HaveSubject
@ -1105,7 +1103,7 @@ send_subject(JID, StateData) ->
[{xmlcdata,
Nick ++ " has set the topic to: " ++ Subject}]}]},
ejabberd_router:route(
{StateData#state.room, StateData#state.host, ""},
StateData#state.jid,
JID,
Packet)
end.
@ -1123,7 +1121,7 @@ send_join_messages_end(JID, StateData) ->
[{xmlelement, "body", [],
[{xmlcdata, "-"}]}]},
ejabberd_router:route(
{StateData#state.room, StateData#state.host, ""},
StateData#state.jid,
JID,
Packet).
@ -1550,7 +1548,7 @@ send_kickban_presence1(UJID, Reason, Code, StateData) ->
[{xmlelement, "item", ItemAttrs, ItemEls},
{xmlelement, "status", [{"code", Code}], []}]}]},
ejabberd_router:route(
{StateData#state.room, StateData#state.host, Nick},
jlib:jid_replace_resource(StateData#state.jid, Nick),
Info#user.jid,
Packet)
end, ?DICT:to_list(StateData#state.users)).
@ -1842,7 +1840,7 @@ destroy_room(DEls, StateData) ->
{xmlelement, "destroy", [],
DEls}]}]},
ejabberd_router:route(
{StateData#state.room, StateData#state.host, Nick},
jlib:jid_replace_resource(StateData#state.jid, Nick),
Info#user.jid,
Packet)
end, ?DICT:to_list(StateData#state.users)),
@ -1950,9 +1948,7 @@ check_invitation(From, Els, StateData) ->
""})}],
[{xmlcdata, Reason}]}]},
ejabberd_router:route(
{StateData#state.room,
StateData#state.host,
""},
StateData#state.jid,
JID,
Msg),
JID;

View File

@ -66,8 +66,7 @@ store_packet(From, To, Packet) ->
true = is_process_alive(whereis(?PROCNAME)),
case check_event(From, To, Packet) of
true ->
{User, Server, Resource} = To,
LUser = jlib:tolower(User),
#jid{luser = LUser} = To,
TimeStamp = now(),
?PROCNAME ! #offline_msg{user = LUser,
timestamp = TimeStamp,
@ -125,7 +124,7 @@ find_x_event([El | Els]) ->
resend_offline_messages(User) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
Rs = mnesia:read({offline_msg, LUser}),
mnesia:delete({offline_msg, LUser}),
@ -152,7 +151,7 @@ resend_offline_messages(User) ->
end.
remove_user(User) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
mnesia:delete({offline_msg, LUser})
end,

View File

@ -61,7 +61,7 @@ start(Opts) ->
%
process_iq(From, To, IQ) ->
{iq, ID, Type, XMLNS, SubEl} = IQ,
{_, Server, _} = From,
#jid{lserver = Server} = From,
Res =
case ?MYNAME of
Server ->
@ -85,16 +85,16 @@ process_iq(From, To, IQ) ->
process_iq_get(From, To, {iq, ID, Type, XMLNS, SubEl},
#userlist{name = Active}) ->
{User, _, _} = From,
#jid{luser = LUser} = From,
{xmlelement, _, _, Els} = SubEl,
case xml:remove_cdata(Els) of
[] ->
process_lists_get(User, Active);
process_lists_get(LUser, Active);
[{xmlelement, Name, Attrs, SubEls}] ->
case Name of
"list" ->
ListName = xml:get_attr("name", Attrs),
process_list_get(User, ListName);
process_list_get(LUser, ListName);
_ ->
{error, ?ERR_BAD_REQUEST}
end;
@ -103,8 +103,7 @@ process_iq_get(From, To, {iq, ID, Type, XMLNS, SubEl},
end.
process_lists_get(User, Active) ->
LUser = jlib:tolower(User),
process_lists_get(LUser, Active) ->
case catch mnesia:dirty_read(privacy, LUser) of
{'EXIT', Reason} ->
{error, ?ERR_INTERNAL_SERVER_ERROR};
@ -143,13 +142,13 @@ process_lists_get(User, Active) ->
end
end.
process_list_get(User, {value, Name}) ->
LUser = jlib:tolower(User),
case catch mnesia:dirty_read(privacy, User) of
process_list_get(LUser, {value, Name}) ->
case catch mnesia:dirty_read(privacy, LUser) of
{'EXIT', Reason} ->
{error, ?ERR_INTERNAL_SERVER_ERROR};
[] ->
{result, [{xmlelement, "query", [{"xmlns", ?NS_PRIVACY}], []}]};
{error, ?ERR_ITEM_NOT_FOUND};
%{result, [{xmlelement, "query", [{"xmlns", ?NS_PRIVACY}], []}]};
[#privacy{lists = Lists}] ->
case lists:keysearch(Name, 1, Lists) of
{value, {_, List}} ->
@ -163,7 +162,7 @@ process_list_get(User, {value, Name}) ->
end
end;
process_list_get(_User, false) ->
process_list_get(_LUser, false) ->
{error, ?ERR_BAD_REQUEST}.
item_to_xml(Item) ->
@ -250,18 +249,18 @@ list_to_action(S) ->
process_iq_set(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
{User, _, _} = From,
#jid{luser = LUser} = From,
{xmlelement, _, _, Els} = SubEl,
case xml:remove_cdata(Els) of
[{xmlelement, Name, Attrs, SubEls}] ->
ListName = xml:get_attr("name", Attrs),
case Name of
"list" ->
process_list_set(User, ListName, xml:remove_cdata(SubEls));
process_list_set(LUser, ListName, xml:remove_cdata(SubEls));
"active" ->
process_active_set(User, ListName);
process_active_set(LUser, ListName);
"default" ->
process_default_set(User, ListName);
process_default_set(LUser, ListName);
_ ->
{error, ?ERR_BAD_REQUEST}
end;
@ -270,8 +269,7 @@ process_iq_set(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
end.
process_default_set(User, {value, Name}) ->
LUser = jlib:tolower(User),
process_default_set(LUser, {value, Name}) ->
F = fun() ->
case mnesia:read({privacy, LUser}) of
[] ->
@ -296,8 +294,7 @@ process_default_set(User, {value, Name}) ->
{error, ?ERR_INTERNAL_SERVER_ERROR}
end;
process_default_set(User, false) ->
LUser = jlib:tolower(User),
process_default_set(LUser, false) ->
F = fun() ->
case mnesia:read({privacy, LUser}) of
[] ->
@ -317,8 +314,7 @@ process_default_set(User, false) ->
end.
process_active_set(User, {value, Name}) ->
LUser = jlib:tolower(User),
process_active_set(LUser, {value, Name}) ->
case catch mnesia:dirty_read(privacy, LUser) of
[] ->
{error, ?ERR_ITEM_NOT_FOUND};
@ -331,7 +327,7 @@ process_active_set(User, {value, Name}) ->
end
end;
process_active_set(User, false) ->
process_active_set(LUser, false) ->
{result, [], #userlist{}}.
@ -339,8 +335,7 @@ process_active_set(User, false) ->
process_list_set(User, {value, Name}, Els) ->
LUser = jlib:tolower(User),
process_list_set(LUser, {value, Name}, Els) ->
case parse_items(Els) of
false ->
{error, ?ERR_BAD_REQUEST};
@ -369,8 +364,8 @@ process_list_set(User, {value, Name}, Els) ->
Error;
{atomic, {result, _} = Res} ->
ejabberd_router:route(
{User, ?MYNAME, ""},
{User, ?MYNAME, ""},
jlib:make_jid(LUser, ?MYNAME, ""),
jlib:make_jid(LUser, ?MYNAME, ""),
{xmlelement, "broadcast", [],
[{privacy_list, #userlist{name = Name, list = []}}]}),
Res;
@ -398,8 +393,8 @@ process_list_set(User, {value, Name}, Els) ->
Error;
{atomic, {result, _} = Res} ->
ejabberd_router:route(
{User, ?MYNAME, ""},
{User, ?MYNAME, ""},
jlib:make_jid(LUser, ?MYNAME, ""),
jlib:make_jid(LUser, ?MYNAME, ""),
{xmlelement, "broadcast", [],
[{privacy_list, #userlist{name = Name, list = List}}]}),
Res;
@ -408,7 +403,7 @@ process_list_set(User, {value, Name}, Els) ->
end
end;
process_list_set(_User, false, _Els) ->
process_list_set(_LUser, false, _Els) ->
{error, ?ERR_BAD_REQUEST}.
@ -523,7 +518,7 @@ parse_matches1(Item, [{xmlelement, _, _, _} | Els]) ->
get_user_list(User) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
case catch mnesia:dirty_read(privacy, LUser) of
[] ->
#userlist{};

View File

@ -34,9 +34,7 @@ stop() ->
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
{User, Server, _} = From,
LUser = jlib:tolower(User),
LServer = jlib:tolower(Server),
#jid{luser = LUser, lserver = LServer} = From,
case ?MYNAME of
Server ->
{xmlelement, Name, Attrs, Els} = SubEl,

View File

@ -47,14 +47,16 @@ start(Opts) ->
proc_lib:spawn_link(?MODULE, init, [Host, ServedHosts, self()])).
-define(MYJID, #jid{user = "", server = Host, resource = "",
luser = "", lserver = Host, lresource = ""}).
init(Host, ServedHosts, Parent) ->
ejabberd_router:register_route(Host),
create_new_node(Host, ["pubsub"], {"", Host, ""}),
create_new_node(Host, ["pubsub", "nodes"], {"", Host, ""}),
create_new_node(Host, ["home"], {"", Host, ""}),
create_new_node(Host, ["pubsub"], ?MYJID),
create_new_node(Host, ["pubsub", "nodes"], ?MYJID),
create_new_node(Host, ["home"], ?MYJID),
lists:foreach(fun(H) ->
create_new_node(Host, ["home", H], {"", Host, ""})
create_new_node(Host, ["home", H], ?MYJID)
end, ServedHosts),
loop(Host, Parent).
@ -86,7 +88,7 @@ loop(Host, Parent) ->
do_route(Host, From, To, Packet) ->
{xmlelement, Name, Attrs, Els} = Packet,
case To of
{"", _, ""} ->
#jid{luser = "", lresource = ""} ->
case Name of
"iq" ->
case jlib:iq_query_info(Packet) of
@ -115,9 +117,7 @@ do_route(Host, From, To, Packet) ->
jlib:make_error_reply(
Packet, Error)
end,
ejabberd_router:route(To,
From,
Res);
ejabberd_router:route(To, From, Res);
%{iq, ID, get, ?NS_REGISTER = XMLNS, SubEl} ->
% Lang = xml:get_tag_attr_s(
% "xml:lang", SubEl),
@ -155,9 +155,7 @@ do_route(Host, From, To, Packet) ->
jlib:make_error_reply(
Packet, Error)
end,
ejabberd_router:route(To,
From,
Res);
ejabberd_router:route(To, From, Res);
{iq, ID, get, ?NS_VCARD = XMLNS, SubEl} ->
Lang = xml:get_tag_attr_s(
"xml:lang", SubEl),
@ -982,10 +980,10 @@ subscription_to_string(Subscription) ->
check_create_permission(Host, Node, Owner) ->
if
{"", Host, ""} == Owner ->
#jid{lserver = Host} == Owner ->
true;
true ->
{User, Server, _} = Owner,
#jid{luser = User, lserver = Server} = Owner,
case Node of
["home", Server, User | _] ->
true;
@ -1087,8 +1085,8 @@ broadcast_publish_item(Host, Node, ItemID, Payload) ->
[{xmlelement, "item",
ItemAttrs,
Payload}]}]}]},
ejabberd_router:route({"", Host, ""},
JID, Stanza);
ejabberd_router:route(
?MYJID, jlib:make_jid(JID), Stanza);
true ->
ok
end
@ -1118,8 +1116,8 @@ broadcast_retract_item(Host, Node, ItemID) ->
[{"node", node_to_string(Node)}],
[{xmlelement, "retract",
ItemAttrs, []}]}]}]},
ejabberd_router:route({"", Host, ""},
JID, Stanza);
ejabberd_router:route(
?MYJID, jlib:make_jid(JID), Stanza);
true ->
ok
end
@ -1144,8 +1142,8 @@ broadcast_removed_node(Host, Removed) ->
[{xmlelement, "delete",
[{"node", node_to_string(Node)}],
[]}]}]},
ejabberd_router:route({"", Host, ""},
JID, Stanza);
ejabberd_router:route(
?MYJID, jlib:make_jid(JID), Stanza);
true ->
ok
end

View File

@ -39,7 +39,7 @@ process_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
(UTag /= false) and (RTag /= false) ->
User = xml:get_tag_cdata(UTag),
case From of
{User, Server, _} ->
#jid{user = User, lserver = Server} ->
ejabberd_auth:remove_user(User),
{iq, ID, result, XMLNS, [SubEl]};
_ ->
@ -71,14 +71,18 @@ process_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
end
end;
(UTag == false) and (RTag /= false) ->
{User, Server, _} = From,
case From of
#jid{user = User, lserver = Server} ->
ejabberd_auth:remove_user(User),
{iq, ID, result, XMLNS, [SubEl]};
_ ->
{iq, ID, error, XMLNS, [SubEl, ?ERR_NOT_ALLOWED]}
end;
(UTag /= false) and (PTag /= false) ->
User = xml:get_tag_cdata(UTag),
Password = xml:get_tag_cdata(PTag),
case From of
{User, Server, _} ->
#jid{user = User, lserver = Server} ->
ejabberd_auth:set_password(User, Password),
{iq, ID, result, XMLNS, [SubEl]};
_ ->
@ -117,7 +121,7 @@ try_register(User, Password) ->
ok;
{atomic, exists} ->
% TODO: replace to "username unavailable"
{error, ?ERR_BAD_REQUEST};
{error, ?ERR_NOT_ALLOWED};
{error, Reason} ->
{error, ?ERR_INTERNAL_SERVER_ERROR}
end

View File

@ -46,9 +46,9 @@ start(Opts) ->
process_iq(From, To, IQ) ->
{iq, ID, Type, XMLNS, SubEl} = IQ,
{_, Server, _} = From,
#jid{lserver = LServer} = From,
case ?MYNAME of
Server ->
LServer ->
process_local_iq(From, To, IQ);
_ ->
{iq, ID, error, XMLNS,
@ -67,8 +67,7 @@ process_local_iq(From, To, {iq, _, Type, _, _} = IQ) ->
process_iq_get(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
{User, _, _} = From,
LUser = jlib:tolower(User),
#jid{luser = LUser} = From,
F = fun() ->
mnesia:index_read(roster, LUser, #roster.user)
end,
@ -120,19 +119,19 @@ item_to_xml(Item) ->
process_iq_set(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
{User, _, _} = From,
{xmlelement, Name, Attrs, Els} = SubEl,
lists:foreach(fun(El) -> process_item_set(User, From, To, El) end, Els),
lists:foreach(fun(El) -> process_item_set(From, To, El) end, Els),
{iq, ID, result, XMLNS, []}.
process_item_set(User, From, To, {xmlelement, Name, Attrs, Els} = XItem) ->
JID = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)),
LUser = jlib:tolower(User),
case JID of
process_item_set(From, To, {xmlelement, Name, Attrs, Els} = XItem) ->
JID1 = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)),
#jid{user = User, luser = LUser} = From,
case JID1 of
error ->
ok;
_ ->
LJID = jlib:jid_tolower(JID),
JID = {JID1#jid.user, JID1#jid.server, JID1#jid.resource},
LJID = jlib:jid_tolower(JID1),
F = fun() ->
Res = mnesia:read({roster, {LUser, LJID}}),
Item = case Res of
@ -175,7 +174,7 @@ process_item_set(User, From, To, {xmlelement, Name, Attrs, Els} = XItem) ->
end,
if IsTo ->
ejabberd_router:route(
From, OldItem#roster.jid,
From, jlib:make_jid(OldItem#roster.jid),
{xmlelement, "presence",
[{"type", "unsubscribe"}],
[]});
@ -183,7 +182,7 @@ process_item_set(User, From, To, {xmlelement, Name, Attrs, Els} = XItem) ->
end,
if IsFrom ->
ejabberd_router:route(
From, OldItem#roster.jid,
From, jlib:make_jid(OldItem#roster.jid),
{xmlelement, "presence",
[{"type", "unsubscribed"}],
[]});
@ -198,7 +197,7 @@ process_item_set(User, From, To, {xmlelement, Name, Attrs, Els} = XItem) ->
ok
end
end;
process_item_set(User, From, To, _) ->
process_item_set(From, To, _) ->
ok.
process_item_attrs(Item, [{Attr, Val} | Attrs]) ->
@ -207,7 +206,8 @@ process_item_attrs(Item, [{Attr, Val} | Attrs]) ->
case jlib:string_to_jid(Val) of
error ->
process_item_attrs(Item, Attrs);
JID ->
JID1 ->
JID = {JID1#jid.user, JID1#jid.server, JID1#jid.resource},
process_item_attrs(Item#roster{jid = JID}, Attrs)
end;
"name" ->
@ -252,7 +252,9 @@ process_item_els(Item, []) ->
push_item(User, From, Item) ->
ejabberd_sm ! {route, {"", "", ""}, {User, "", ""},
ejabberd_sm ! {route,
jlib:make_jid("", "", ""),
jlib:make_jid(User, "", ""),
{xmlelement, "broadcast", [],
[{item,
Item#roster.jid,
@ -269,12 +271,12 @@ push_item(User, Resource, From, Item) ->
[item_to_xml(Item)]}]},
ejabberd_router ! {route,
From,
{User, ?MYNAME, Resource},
jlib:make_jid(User, ?MYNAME, Resource),
jlib:iq_to_xml(ResIQ)}.
get_subscription_lists(User) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
mnesia:index_read(roster, LUser, #roster.user)
end,
@ -286,7 +288,6 @@ get_subscription_lists(User) ->
end.
fill_subscription_lists([I | Is], F, T) ->
%J = I#roster.jid,
J = element(2, I#roster.uj),
case I#roster.subscription of
both ->
@ -303,9 +304,8 @@ fill_subscription_lists([], F, T) ->
in_subscription(User, From, Type) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
LFrom = jlib:jid_tolower(From),
{FU, FS, FR} = From,
F = fun() ->
case mnesia:read({roster, {LUser, LFrom}}) of
[] ->
@ -317,6 +317,9 @@ in_subscription(User, From, Type) ->
unsubscribed ->
false;
subscribed ->
JID = {From#jid.user,
From#jid.server,
From#jid.resource},
NewItem = #roster{uj = {LUser, LFrom},
user = LUser,
jid = From},
@ -376,8 +379,12 @@ in_subscription(User, From, Type) ->
{atomic, false} ->
false;
{atomic, {update, Presence, Item}} ->
ejabberd_router:route({User, ?MYNAME, ""}, {FU, FS, ""}, Presence),
ejabberd_sm ! {route, {"", "", ""}, {User, "", ""},
ejabberd_router:route({User, ?MYNAME, ""},
jlib:jid_replace_resource(From, ""),
Presence),
ejabberd_sm ! {route,
jlib:make_jid("", "", ""),
jlib:make_jid(User, "", ""),
{xmlelement, "broadcast", [],
[{item,
Item#roster.jid,
@ -390,9 +397,9 @@ in_subscription(User, From, Type) ->
false
end.
out_subscription(User, JID, Type) ->
LUser = jlib:tolower(User),
LJID = jlib:jid_tolower(JID),
out_subscription(User, JID1, Type) ->
LUser = jlib:nodeprep(User),
LJID = jlib:jid_tolower(JID1),
F = fun() ->
Item = case mnesia:read({roster, {LUser, LJID}}) of
[] ->
@ -400,6 +407,9 @@ out_subscription(User, JID, Type) ->
(Type == unsubscribed) ->
false;
true ->
JID = {JID1#jid.user,
JID1#jid.server,
JID1#jid.resource},
#roster{uj = {LUser, LJID},
user = LUser,
jid = JID}
@ -448,7 +458,9 @@ out_subscription(User, JID, Type) ->
push_item(User, {"", ?MYNAME, ""}, Item),
if
Update ->
ejabberd_sm ! {route, {"", "", ""}, {User, "", ""},
ejabberd_sm ! {route,
jlib:make_jid("", "", ""),
jlib:make_jid(User, "", ""),
{xmlelement, "broadcast", [],
[{item,
Item#roster.jid,
@ -461,7 +473,7 @@ out_subscription(User, JID, Type) ->
end.
remove_user(User) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
lists:foreach(fun(R) ->
mnesia:delete_object(R)
@ -480,12 +492,13 @@ set_items(User, SubEl) ->
mnesia:transaction(F).
process_item_set_t(User, {xmlelement, Name, Attrs, Els} = XItem) ->
JID = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)),
LUser = jlib:tolower(User),
case JID of
JID1 = jlib:string_to_jid(xml:get_attr_s("jid", Attrs)),
LUser = jlib:nodeprep(User),
case JID1 of
error ->
ok;
_ ->
JID = {JID1#jid.user, JID1#jid.server, JID1#jid.resource},
LJID = jlib:jid_tolower(JID),
Res = mnesia:read({roster, {LUser, LJID}}),
Item = #roster{uj = {LUser, LJID},
@ -509,7 +522,8 @@ process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) ->
case jlib:string_to_jid(Val) of
error ->
process_item_attrs_ws(Item, Attrs);
JID ->
JID1 ->
JID = {JID1#jid.user, JID1#jid.server, JID1#jid.resource},
process_item_attrs_ws(Item#roster{jid = JID}, Attrs)
end;
"name" ->
@ -548,7 +562,7 @@ process_item_attrs_ws(Item, []) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_jid_info(User, JID) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
LJID = jlib:jid_tolower(JID),
case catch mnesia:dirty_read(roster, {LUser, LJID}) of
[#roster{subscription = Subscription, groups = Groups}] ->

View File

@ -72,7 +72,12 @@ init(Host) ->
loop() ->
receive
{route, From, To, Packet} ->
do_route(From, To, Packet),
case catch do_route(From, To, Packet) of
{'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]);
_ ->
ok
end,
loop();
_ ->
loop()
@ -104,9 +109,7 @@ process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
process_sm_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
case Type of
set ->
{User, Server, _} = From,
LUser = jlib:tolower(User),
LServer = jlib:tolower(Server),
#jid{user = User, lserver = LServer, luser = LUser} = From,
case ?MYNAME of
LServer ->
set_vcard(User, SubEl),
@ -116,8 +119,7 @@ process_sm_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
[SubEl, ?ERR_NOT_ALLOWED]}
end;
get ->
{User, _, _} = To,
LUser = jlib:tolower(User),
#jid{luser = LUser} = To,
F = fun() ->
mnesia:read({vcard, LUser})
end,
@ -145,18 +147,18 @@ set_vcard(User, VCARD) ->
OrgName = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGNAME"}, cdata]),
OrgUnit = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGUNIT"}, cdata]),
LUser = jlib:tolower(User),
LFN = jlib:tolower(FN),
LFamily = jlib:tolower(Family),
LGiven = jlib:tolower(Given),
LMiddle = jlib:tolower(Middle),
LNickname = jlib:tolower(Nickname),
LBDay = jlib:tolower(BDay),
LCTRY = jlib:tolower(CTRY),
LLocality = jlib:tolower(Locality),
LEMail = jlib:tolower(EMail),
LOrgName = jlib:tolower(OrgName),
LOrgUnit = jlib:tolower(OrgUnit),
LUser = jlib:nodeprep(User),
LFN = stringprep:tolower(FN),
LFamily = stringprep:tolower(Family),
LGiven = stringprep:tolower(Given),
LMiddle = stringprep:tolower(Middle),
LNickname = stringprep:tolower(Nickname),
LBDay = stringprep:tolower(BDay),
LCTRY = stringprep:tolower(CTRY),
LLocality = stringprep:tolower(Locality),
LEMail = stringprep:tolower(EMail),
LOrgName = stringprep:tolower(OrgName),
LOrgUnit = stringprep:tolower(OrgUnit),
F = fun() ->
mnesia:write(#vcard{user = LUser, vcard = VCARD}),
@ -210,7 +212,7 @@ set_vcard(User, VCARD) ->
do_route(From, To, Packet) ->
{User, Server, Resource} = To,
#jid{user = User, resource = Resource} = To,
if
(User /= "") or (Resource /= "") ->
Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE),
@ -400,7 +402,7 @@ filter_fields([], Match) ->
Match;
filter_fields([{SVar, [Val]} | Ds], Match)
when is_list(Val) and (Val /= "") ->
LVal = jlib:tolower(Val),
LVal = stringprep:tolower(Val),
NewMatch = case SVar of
"user" -> Match#vcard_search{luser = LVal};
"fn" -> Match#vcard_search{lfn = LVal};
@ -439,18 +441,18 @@ set_vcard_t(R, _) ->
OrgName = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGNAME"}, cdata]),
OrgUnit = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGUNIT"}, cdata]),
LUser = jlib:tolower(User),
LFN = jlib:tolower(FN),
LFamily = jlib:tolower(Family),
LGiven = jlib:tolower(Given),
LMiddle = jlib:tolower(Middle),
LNickname = jlib:tolower(Nickname),
LBDay = jlib:tolower(BDay),
LCTRY = jlib:tolower(CTRY),
LLocality = jlib:tolower(Locality),
LEMail = jlib:tolower(EMail),
LOrgName = jlib:tolower(OrgName),
LOrgUnit = jlib:tolower(OrgUnit),
LUser = jlib:nodeprep(User),
LFN = stringprep:tolower(FN),
LFamily = stringprep:tolower(Family),
LGiven = stringprep:tolower(Given),
LMiddle = stringprep:tolower(Middle),
LNickname = stringprep:tolower(Nickname),
LBDay = stringprep:tolower(BDay),
LCTRY = stringprep:tolower(CTRY),
LLocality = stringprep:tolower(Locality),
LEMail = stringprep:tolower(EMail),
LOrgName = stringprep:tolower(OrgName),
LOrgUnit = stringprep:tolower(OrgUnit),
mnesia:write(
#vcard_search{user = User, luser = LUser,
@ -476,7 +478,7 @@ reindex_vcards() ->
remove_user(User) ->
LUser = jlib:tolower(User),
LUser = jlib:nodeprep(User),
F = fun() ->
mnesia:delete({vcard, LUser}),
lists:foreach(fun(R) ->

View File

@ -32,8 +32,38 @@ static void stringprep_erl_stop(ErlDrvData handle)
driver_free((char*)handle);
}
/*
* "canonical_ordering" and "compose" functions are based on nfkc.c from Gnome
* library
*/
static int combine(int ch1, int ch2)
void canonical_ordering(int *str, int len)
{
int i, j, t;
int last, next;
last = GetUniCharCClass(str[0]);
for (i = 0; i < len - 1; i++)
{
next = GetUniCharCClass(str[i + 1]);
if (next != 0 && last > next)
{
for(j = i; j > 0; j--)
{
if (GetUniCharCClass(str[j]) <= next)
break;
t = str[j + 1];
str[j + 1] = str[j];
str[j] = t;
}
next = last;
}
last = next;
}
}
static int compose(int ch1, int ch2)
{
int info1, info2;
@ -90,6 +120,29 @@ static int combine(int ch1, int ch2)
pos += 3; \
}
#define ADD_UCHAR32(str, pos, len, ch) \
if(pos >= len) { \
len = 2*len + 1; \
str = driver_realloc(str, len * sizeof(int)); \
} \
str[pos] = ch; \
pos++;
#define ADD_DECOMP(ruc) \
info = GetUniCharDecompInfo(ruc); \
if(info >= 0) { \
decomp_len = GetDecompLen(info); \
decomp_shift = GetDecompShift(info); \
for(j = 0; j < decomp_len; j++) { \
ADD_UCHAR32(str32, str32pos, str32len, \
decompList[decomp_shift + j]); \
} \
} else { \
ADD_UCHAR32(str32, str32pos, str32len, ruc); \
}
static int stringprep_erl_control(ErlDrvData drv_data,
unsigned int command,
@ -105,12 +158,22 @@ static int stringprep_erl_control(ErlDrvData drv_data,
int prohibit, tolower;
char *rstring;
int *mc;
int *str32;
int str32len, str32pos = 0;
int decomp_len, decomp_shift;
int comp_pos;
int cclass1, cclass2;
int ch1, ch2;
size = len + 1;
rstring = driver_alloc(size);
rstring[0] = 0;
str32len = len + 1;
str32 = driver_alloc(str32len * sizeof(int));
switch (command)
{
case 0:
@ -164,12 +227,14 @@ static int stringprep_erl_control(ErlDrvData drv_data,
if(bad) {
*rbuf = rstring;
driver_free(str32);
return 1;
}
info = GetUniCharInfo(uc);
if(info & prohibit) {
*rbuf = rstring;
driver_free(str32);
return 1;
}
@ -180,6 +245,19 @@ static int stringprep_erl_control(ErlDrvData drv_data,
if(!(info & MCMask))
{
ruc = uc + GetDelta(info);
ADD_DECOMP(ruc);
//info = GetUniCharDecompInfo(ruc);
//if(info >= 0) {
// decomp_len = GetDecompLen(info);
// decomp_shift = GetDecompShift(info);
// for(j = 0; j < decomp_len; j++) {
// ADD_UCHAR32(str32, str32pos, str32len,
// decompList[decomp_shift + j]);
// }
//} else {
// ADD_UCHAR32(str32, str32pos, str32len, ruc);
//}
//info = GetUniCharDecompInfo(ruc);
//if(info >= 0) {
@ -190,26 +268,63 @@ static int stringprep_erl_control(ErlDrvData drv_data,
// printf("\r\n");
//}
ADD_UCHAR(ruc);
//ADD_UCHAR(ruc);
} else {
mc = GetMC(info);
for(j = 1; j <= mc[0]; j++) {
ruc = mc[j];
//printf("Char %x cclass %d\r\n", ruc, GetUniCharCClass(ruc));
ADD_UCHAR(ruc);
ADD_DECOMP(ruc);
}
}
} else {
ruc = uc;
ADD_UCHAR(ruc);
ADD_DECOMP(ruc);
}
}
}
//printf("Combine: %x\r\n", combine(0x438, 0x301));
if (str32pos == 0) {
rstring[0] = 1;
*rbuf = rstring;
driver_free(str32);
return 1;
}
canonical_ordering(str32, str32pos);
comp_pos = 0;
ch1 = str32[0];
cclass1 = GetUniCharCClass(ch1);
for(i = 1; i < str32pos; i++)
{
ch2 = str32[i];
cclass2 = GetUniCharCClass(ch2);
//printf("Compose: %x + %x = %x\r\n", ch1, ch2, compose(ch1, ch2));
if(cclass1 == 0 && cclass1 < cclass2 && (ruc = compose(ch1, ch2))) {
ch1 = ruc;
} else {
str32[comp_pos] = ch1;
comp_pos++;
ch1 = ch2;
}
}
str32[comp_pos] = ch1;
str32pos = comp_pos+1;
for(i = 0; i < str32pos; i++)
{
ruc = str32[i];
ADD_UCHAR(ruc);
}
//printf("Compose: %x\r\n", compose(0x438, 0x301));
//printf("Pos: %d\r\n", pos);
rstring[0] = 1;
*rbuf = rstring;
driver_free(str32);
return pos;
}

File diff suppressed because it is too large Load Diff

View File

@ -283,6 +283,12 @@ proc uni::buildTables {} {
if {[info exists decomp_map($i)]} {
set decomp $decomp_map($i)
#puts -$decomp
while {[info exists decomp_map([set ch1 [lindex $decomp 0]])]} {
set decomp [concat $decomp_map($ch1) [lreplace $decomp 0 0]]
#puts +$decomp
}
if {[info exists decomp_used($decomp)]} {
lappend decomp_info $decomp_used($decomp)
} else {
@ -442,75 +448,6 @@ static unsigned char cclassGroupMap\[\] = {"
puts $f $line
puts $f "};
/*
* Each group represents a unique set of character attributes. The attributes
* are encoded into a 32-bit value as follows:
*
* Bits 0-4 Character category: see the constants listed below.
*
* Bits 5-7 Case delta type: 000 = identity
* 010 = add delta for lower
* 011 = add delta for lower, add 1 for title
* 100 = sutract delta for title/upper
* 101 = sub delta for upper, sub 1 for title
* 110 = sub delta for upper, add delta for lower
*
* Bits 8-21 Reserved for future use.
*
* Bits 22-31 Case delta: delta for case conversions. This should be the
* highest field so we can easily sign extend.
*/
static int cclass_groups\[\] = {"
set line " "
set last [expr {[llength $groups] - 1}]
for {set i 0} {$i <= $last} {incr i} {
foreach {type toupper tolower totitle} [split [lindex $groups $i] ,] {}
# Compute the case conversion type and delta
if {$totitle != ""} {
if {$totitle == $toupper} {
# subtract delta for title or upper
set case 4
set delta $toupper
} elseif {$toupper != ""} {
# subtract delta for upper, subtract 1 for title
set case 5
set delta $toupper
} else {
# add delta for lower, add 1 for title
set case 3
set delta $tolower
}
} elseif {$toupper != ""} {
# subtract delta for upper, add delta for lower
set case 6
set delta $toupper
} elseif {$tolower != ""} {
# add delta for lower
set case 2
set delta $tolower
} else {
# noop
set case 0
set delta 0
}
set val [expr {($delta << 22) | ($case << 5) | $type}]
append line [format "%d" $val]
if {$i != $last} {
append line ", "
}
if {[string length $line] > 65} {
puts $f $line
set line " "
}
}
puts $f $line
puts $f "};
#define GetUniCharCClass(ch) (cclassGroupMap\[(cclassPageMap\[(((int)(ch)) & 0xffff) >> CCLASS_OFFSET_BITS\] << CCLASS_OFFSET_BITS) | ((ch) & ((1 << CCLASS_OFFSET_BITS)-1))\])