mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-20 17:27:00 +01:00
Update SQL escaping
This commit is contained in:
parent
be2a9e35ae
commit
792f47b4bd
@ -43,6 +43,7 @@
|
||||
escape/1,
|
||||
escape_like/1,
|
||||
escape_like_arg/1,
|
||||
escape_like_arg_circumflex/1,
|
||||
to_bool/1,
|
||||
sqlite_db/1,
|
||||
sqlite_file/1,
|
||||
@ -200,6 +201,7 @@ escape_like(S) when is_binary(S) ->
|
||||
<< <<(escape_like(C))/binary>> || <<C>> <= S >>;
|
||||
escape_like($%) -> <<"\\%">>;
|
||||
escape_like($_) -> <<"\\_">>;
|
||||
escape_like($\\) -> <<"\\\\\\\\">>;
|
||||
escape_like(C) when is_integer(C), C >= 0, C =< 255 -> sql_queries:escape(C).
|
||||
|
||||
escape_like_arg(S) when is_binary(S) ->
|
||||
@ -209,6 +211,13 @@ escape_like_arg($_) -> <<"\\_">>;
|
||||
escape_like_arg($\\) -> <<"\\\\">>;
|
||||
escape_like_arg(C) when is_integer(C), C >= 0, C =< 255 -> <<C>>.
|
||||
|
||||
escape_like_arg_circumflex(S) when is_binary(S) ->
|
||||
<< <<(escape_like_arg_circumflex(C))/binary>> || <<C>> <= S >>;
|
||||
escape_like_arg_circumflex($%) -> <<"^%">>;
|
||||
escape_like_arg_circumflex($_) -> <<"^_">>;
|
||||
escape_like_arg_circumflex($^) -> <<"^^">>;
|
||||
escape_like_arg_circumflex(C) when is_integer(C), C >= 0, C =< 255 -> <<C>>.
|
||||
|
||||
to_bool(<<"t">>) -> true;
|
||||
to_bool(<<"true">>) -> true;
|
||||
to_bool(<<"1">>) -> true;
|
||||
@ -508,7 +517,7 @@ sql_query_internal(#sql_query{} = Query) ->
|
||||
odbc ->
|
||||
generic_sql_query(Query);
|
||||
mssql ->
|
||||
generic_sql_query(Query);
|
||||
mssql_sql_query(Query);
|
||||
pgsql ->
|
||||
Key = {?PREPARE_KEY, Query#sql_query.hash},
|
||||
case get(Key) of
|
||||
@ -534,7 +543,7 @@ sql_query_internal(#sql_query{} = Query) ->
|
||||
mysql ->
|
||||
generic_sql_query(Query);
|
||||
sqlite ->
|
||||
generic_sql_query(Query)
|
||||
sqlite_sql_query(Query)
|
||||
end
|
||||
catch
|
||||
Class:Reason ->
|
||||
@ -623,6 +632,32 @@ generic_escape() ->
|
||||
end
|
||||
}.
|
||||
|
||||
sqlite_sql_query(SQLQuery) ->
|
||||
sql_query_format_res(
|
||||
sql_query_internal(sqlite_sql_query_format(SQLQuery)),
|
||||
SQLQuery).
|
||||
|
||||
sqlite_sql_query_format(SQLQuery) ->
|
||||
Args = (SQLQuery#sql_query.args)(sqlite_escape()),
|
||||
(SQLQuery#sql_query.format_query)(Args).
|
||||
|
||||
sqlite_escape() ->
|
||||
#sql_escape{string = fun(X) -> <<"'", (standard_escape(X))/binary, "'">> end,
|
||||
integer = fun(X) -> integer_to_binary(X) end,
|
||||
boolean = fun(true) -> <<"1">>;
|
||||
(false) -> <<"0">>
|
||||
end
|
||||
}.
|
||||
|
||||
standard_escape(S) ->
|
||||
<< <<(case Char of
|
||||
$' -> << "''" >>;
|
||||
_ -> << Char >>
|
||||
end)/binary>> || <<Char>> <= S >>.
|
||||
|
||||
mssql_sql_query(SQLQuery) ->
|
||||
sqlite_sql_query(SQLQuery).
|
||||
|
||||
pgsql_prepare(SQLQuery, State) ->
|
||||
Escape = #sql_escape{_ = fun(X) -> X end},
|
||||
N = length((SQLQuery#sql_query.args)(Escape)),
|
||||
|
@ -227,9 +227,11 @@ make_val(Match, Field, Val) ->
|
||||
Condition = case str:suffix(<<"*">>, Val) of
|
||||
true ->
|
||||
Val1 = str:substr(Val, 1, byte_size(Val) - 1),
|
||||
SVal = <<(ejabberd_sql:escape_like(Val1))/binary,
|
||||
SVal = <<(ejabberd_sql:escape(
|
||||
ejabberd_sql:escape_like_arg_circumflex(
|
||||
Val1)))/binary,
|
||||
"%">>,
|
||||
[Field, <<" LIKE '">>, SVal, <<"'">>];
|
||||
[Field, <<" LIKE '">>, SVal, <<"' ESCAPE '^'">>];
|
||||
_ ->
|
||||
SVal = ejabberd_sql:escape(Val),
|
||||
[Field, <<" = '">>, SVal, <<"'">>]
|
||||
|
@ -51,9 +51,11 @@
|
||||
get_entity_subscriptions_for_send_last/2, get_last_items/3]).
|
||||
|
||||
-export([decode_jid/1, encode_jid/1,
|
||||
encode_jid_like/1,
|
||||
decode_affiliation/1, decode_subscriptions/1,
|
||||
encode_affiliation/1, encode_subscriptions/1,
|
||||
encode_host/1]).
|
||||
encode_host/1,
|
||||
encode_host_like/1]).
|
||||
|
||||
init(_Host, _ServerHost, _Opts) ->
|
||||
%%pubsub_subscription_sql:init(),
|
||||
@ -350,11 +352,13 @@ get_entity_subscriptions(Host, Owner) ->
|
||||
H = encode_host(Host),
|
||||
SJ = encode_jid(SubKey),
|
||||
GJ = encode_jid(GenKey),
|
||||
GJLike = encode_jid_like(GenKey),
|
||||
Query = case SubKey of
|
||||
GenKey ->
|
||||
[<<"select node, type, i.nodeid, jid, subscriptions "
|
||||
"from pubsub_state i, pubsub_node n "
|
||||
"where i.nodeid = n.nodeid and jid like '">>, GJ, <<"%' and host='">>, H, <<"';">>];
|
||||
"where i.nodeid = n.nodeid and jid like '">>, GJLike,
|
||||
<<"%' escape '^' and host='">>, H, <<"';">>];
|
||||
_ ->
|
||||
[<<"select node, type, i.nodeid, jid, subscriptions "
|
||||
"from pubsub_state i, pubsub_node n "
|
||||
@ -399,12 +403,14 @@ get_entity_subscriptions_for_send_last(Host, Owner) ->
|
||||
H = encode_host(Host),
|
||||
SJ = encode_jid(SubKey),
|
||||
GJ = encode_jid(GenKey),
|
||||
GJLike = encode_jid_like(GenKey),
|
||||
Query = case SubKey of
|
||||
GenKey ->
|
||||
[<<"select node, type, i.nodeid, jid, subscriptions "
|
||||
"from pubsub_state i, pubsub_node n, pubsub_node_option o "
|
||||
"where i.nodeid = n.nodeid and n.nodeid = o.nodeid and name='send_last_published_item' "
|
||||
"and val='on_sub_and_presence' and jid like '">>, GJ, <<"%' and host='">>, H, <<"';">>];
|
||||
"and val='on_sub_and_presence' and jid like '">>, GJLike,
|
||||
<<"%' escape '^' and host='">>, H, <<"';">>];
|
||||
_ ->
|
||||
[<<"select node, type, i.nodeid, jid, subscriptions "
|
||||
"from pubsub_state i, pubsub_node n, pubsub_node_option o "
|
||||
@ -568,8 +574,9 @@ get_states(Nidx) ->
|
||||
[<<"jid">>, <<"affiliation">>, <<"subscriptions">>], RItems} ->
|
||||
{result,
|
||||
lists:map(fun ([SJID, Aff, Subs]) ->
|
||||
#pubsub_state{stateid = {decode_jid(SJID), Nidx},
|
||||
items = itemids(Nidx, SJID),
|
||||
JID = decode_jid(SJID),
|
||||
#pubsub_state{stateid = {JID, Nidx},
|
||||
items = itemids(Nidx, JID),
|
||||
affiliation = decode_affiliation(Aff),
|
||||
subscriptions = decode_subscriptions(Subs)}
|
||||
end,
|
||||
@ -899,13 +906,12 @@ first_in_list(Pred, [H | T]) ->
|
||||
_ -> first_in_list(Pred, T)
|
||||
end.
|
||||
|
||||
itemids(Nidx, {U, S, R}) ->
|
||||
itemids(Nidx, encode_jid({U, S, R}));
|
||||
itemids(Nidx, SJID) ->
|
||||
itemids(Nidx, {_U, _S, _R} = JID) ->
|
||||
SJID = encode_jid_like(JID),
|
||||
case catch
|
||||
ejabberd_sql:sql_query_t([<<"select itemid from pubsub_item where "
|
||||
"nodeid='">>, Nidx, <<"' and publisher like '">>, SJID,
|
||||
<<"%' order by modification desc;">>])
|
||||
<<"%' escape '^' order by modification desc;">>])
|
||||
of
|
||||
{selected, [<<"itemid">>], RItems} ->
|
||||
[ItemId || [ItemId] <- RItems];
|
||||
@ -1011,6 +1017,10 @@ decode_subscriptions(Subscriptions) ->
|
||||
encode_jid(JID) ->
|
||||
ejabberd_sql:escape(jid:to_string(JID)).
|
||||
|
||||
-spec(encode_jid_like/1 :: (JID :: ljid()) -> binary()).
|
||||
encode_jid_like(JID) ->
|
||||
ejabberd_sql:escape(ejabberd_sql:escape_like_arg_circumflex(jid:to_string(JID))).
|
||||
|
||||
-spec(encode_host/1 ::
|
||||
( Host :: host())
|
||||
-> binary()
|
||||
@ -1018,6 +1028,14 @@ encode_jid(JID) ->
|
||||
encode_host({_U, _S, _R} = LJID) -> encode_jid(LJID);
|
||||
encode_host(Host) -> ejabberd_sql:escape(Host).
|
||||
|
||||
-spec(encode_host_like/1 ::
|
||||
( Host :: host())
|
||||
-> binary()
|
||||
).
|
||||
encode_host_like({_U, _S, _R} = LJID) -> encode_jid_like(LJID);
|
||||
encode_host_like(Host) ->
|
||||
ejabberd_sql:escape(ejabberd_sql:escape_like_arg_circumflex(Host)).
|
||||
|
||||
-spec(encode_affiliation/1 ::
|
||||
( Arg :: atom())
|
||||
-> binary()
|
||||
|
@ -114,20 +114,21 @@ set_affiliation(Nidx, Owner, Affiliation) ->
|
||||
get_entity_subscriptions(_Host, Owner) ->
|
||||
SubKey = jid:tolower(Owner),
|
||||
GenKey = jid:remove_resource(SubKey),
|
||||
Host = node_flat_sql:encode_host(element(2, SubKey)),
|
||||
HostLike = node_flat_sql:encode_host_like(element(2, SubKey)),
|
||||
SJ = node_flat_sql:encode_jid(SubKey),
|
||||
GJ = node_flat_sql:encode_jid(GenKey),
|
||||
GJLike = node_flat_sql:encode_jid_like(GenKey),
|
||||
Query = case SubKey of
|
||||
GenKey ->
|
||||
[<<"select host, node, type, i.nodeid, jid, "
|
||||
"subscriptions from pubsub_state i, pubsub_node n "
|
||||
"where i.nodeid = n.nodeid and jid "
|
||||
"like '">>, GJ, <<"%' and host like '%@">>, Host, <<"';">>];
|
||||
"like '">>, GJLike, <<"%' escape '^' and host like '%@">>, HostLike, <<"' escape '^';">>];
|
||||
_ ->
|
||||
[<<"select host, node, type, i.nodeid, jid, "
|
||||
"subscriptions from pubsub_state i, pubsub_node n "
|
||||
"where i.nodeid = n.nodeid and jid "
|
||||
"in ('">>, SJ, <<"', '">>, GJ, <<"') and host like '%@">>, Host, <<"';">>]
|
||||
"in ('">>, SJ, <<"', '">>, GJ, <<"') and host like '%@">>, HostLike, <<"' escape '^';">>]
|
||||
end,
|
||||
Reply = case catch ejabberd_sql:sql_query_t(Query) of
|
||||
{selected,
|
||||
@ -149,9 +150,10 @@ get_entity_subscriptions(_Host, Owner) ->
|
||||
get_entity_subscriptions_for_send_last(_Host, Owner) ->
|
||||
SubKey = jid:tolower(Owner),
|
||||
GenKey = jid:remove_resource(SubKey),
|
||||
Host = node_flat_sql:encode_host(element(2, SubKey)),
|
||||
HostLike = node_flat_sql:encode_host_like(element(2, SubKey)),
|
||||
SJ = node_flat_sql:encode_jid(SubKey),
|
||||
GJ = node_flat_sql:encode_jid(GenKey),
|
||||
GJLike = node_flat_sql:encode_jid_like(GenKey),
|
||||
Query = case SubKey of
|
||||
GenKey ->
|
||||
[<<"select host, node, type, i.nodeid, jid, "
|
||||
@ -159,14 +161,14 @@ get_entity_subscriptions_for_send_last(_Host, Owner) ->
|
||||
"pubsub_node_option o where i.nodeid = n.nodeid "
|
||||
"and n.nodeid = o.nodeid and name='send_last_published_item' and "
|
||||
"val='on_sub_and_presence' and jid like '">>,
|
||||
GJ, <<"%' and host like '%@">>, Host, <<"';">>];
|
||||
GJLike, <<"%' escape '^' and host like '%@">>, HostLike, <<"' escape '^';">>];
|
||||
_ ->
|
||||
[<<"select host, node, type, i.nodeid, jid, "
|
||||
"subscriptions from pubsub_state i, pubsub_node n, "
|
||||
"pubsub_node_option o where i.nodeid = n.nodeid "
|
||||
"and n.nodeid = o.nodeid and name='send_last_published_item' and "
|
||||
"val='on_sub_and_presence' and jid in ",
|
||||
"('">>, SJ, <<"', '">>, GJ, <<"') and host like '%@">>, Host, <<"';">>]
|
||||
"('">>, SJ, <<"', '">>, GJ, <<"') and host like '%@">>, HostLike, <<"' escape '^';">>]
|
||||
end,
|
||||
Reply = case catch ejabberd_sql:sql_query_t(Query) of
|
||||
{selected,
|
||||
|
@ -196,11 +196,11 @@ get_subnodes_tree(Host, Node, _From) ->
|
||||
|
||||
get_subnodes_tree(Host, Node) ->
|
||||
H = node_flat_sql:encode_host(Host),
|
||||
N = ejabberd_sql:escape(Node),
|
||||
N = ejabberd_sql:escape(ejabberd_sql:escape_like_arg_circumflex(Node)),
|
||||
case catch
|
||||
ejabberd_sql:sql_query_t([<<"select node, parent, type, nodeid from "
|
||||
"pubsub_node where host='">>,
|
||||
H, <<"' and node like '">>, N, <<"%';">>])
|
||||
H, <<"' and node like '">>, N, <<"%' escape '^';">>])
|
||||
of
|
||||
{selected,
|
||||
[<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], RItems} ->
|
||||
@ -256,10 +256,10 @@ create_node(Host, Node, Type, Owner, Options, Parents) ->
|
||||
|
||||
delete_node(Host, Node) ->
|
||||
H = node_flat_sql:encode_host(Host),
|
||||
N = ejabberd_sql:escape(Node),
|
||||
N = ejabberd_sql:escape(ejabberd_sql:escape_like_arg_circumflex(Node)),
|
||||
Removed = get_subnodes_tree(Host, Node),
|
||||
catch ejabberd_sql:sql_query_t([<<"delete from pubsub_node where host='">>,
|
||||
H, <<"' and node like '">>, N, <<"%';">>]),
|
||||
H, <<"' and node like '">>, N, <<"%' escape '^';">>]),
|
||||
Removed.
|
||||
|
||||
%% helpers
|
||||
|
@ -231,12 +231,12 @@ list_users(LServer,
|
||||
[{prefix, Prefix}, {limit, Limit}, {offset, Offset}])
|
||||
when is_binary(Prefix) and is_integer(Limit) and
|
||||
is_integer(Offset) ->
|
||||
SPrefix = ejabberd_sql:escape_like_arg(Prefix),
|
||||
SPrefix = ejabberd_sql:escape_like_arg_circumflex(Prefix),
|
||||
SPrefix2 = <<SPrefix/binary, $%>>,
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL("select @(username)s from users "
|
||||
"where username like %(SPrefix2)s "
|
||||
"where username like %(SPrefix2)s escape '^' "
|
||||
"order by username "
|
||||
"limit %(Limit)d offset %(Offset)d")).
|
||||
|
||||
@ -264,12 +264,12 @@ users_number(LServer) ->
|
||||
|
||||
users_number(LServer, [{prefix, Prefix}])
|
||||
when is_binary(Prefix) ->
|
||||
SPrefix = ejabberd_sql:escape_like_arg(Prefix),
|
||||
SPrefix = ejabberd_sql:escape_like_arg_circumflex(Prefix),
|
||||
SPrefix2 = <<SPrefix/binary, $%>>,
|
||||
ejabberd_sql:sql_query(
|
||||
LServer,
|
||||
?SQL("select @(count(*))d from users "
|
||||
"where username like %(SPrefix2)s"));
|
||||
"where username like %(SPrefix2)s escape '^'"));
|
||||
users_number(LServer, []) ->
|
||||
users_number(LServer).
|
||||
|
||||
|
@ -66,7 +66,7 @@ init_config(Config) ->
|
||||
{resource, <<"resource">>},
|
||||
{master_resource, <<"master_resource">>},
|
||||
{slave_resource, <<"slave_resource">>},
|
||||
{password, <<"password">>},
|
||||
{password, <<"password!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>}
|
||||
{backends, get_config_backends()}
|
||||
|Config].
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user