diff options
author | Pablo Polvorin <pablo.polvorin@process-one.net> | 2010-10-12 17:57:07 +0400 |
---|---|---|
committer | Pablo Polvorin <pablo.polvorin@process-one.net> | 2010-10-12 17:57:07 +0400 |
commit | ce9ce8293ba7b5985535e37cfab59c466dc6790f (patch) | |
tree | 2d6ed1d1a0e069d4784a4430b20ed29eca94ef92 /src | |
parent | 0d5f20cae1be1ba37ebb443741c8fa6e477ef1e4 (diff) | |
parent | 82a8dc7b3ab20aafcfe5e94a219f05af4921b6c2 (diff) |
Merge branch 'master' of git+ssh://git@gitorious.process-one.net/ejabberd/mainline
Diffstat (limited to 'src')
62 files changed, 4460 insertions, 8207 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index 808137a3c..f03f7fae8 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -166,7 +166,7 @@ $(ERLSHLIBS): %.so: %.c $(DYNAMIC_LIB_CFLAGS) translations: - ../contrib/extract_translations/prepare-translation.sh -updateall + ../tools/extract_translations/prepare-translation.sh -updateall install: all # @@ -248,9 +248,11 @@ install: all # # Documentation install -d $(DOCDIR) - install -m 644 ../doc/dev.html $(DOCDIR) - install -m 644 ../doc/guide.html $(DOCDIR) - install -m 644 ../doc/*.png $(DOCDIR) + [ -f ../doc/guide.html ] \ + && install -m 644 ../doc/dev.html $(DOCDIR) \ + && install -m 644 ../doc/guide.html $(DOCDIR) \ + && install -m 644 ../doc/*.png $(DOCDIR) \ + || echo "No ../doc/guide.html was built" install -m 644 ../doc/*.txt $(DOCDIR) [ -f ../doc/guide.pdf ] \ && install -m 644 ../doc/guide.pdf $(DOCDIR) \ diff --git a/src/cache_tab.erl b/src/cache_tab.erl new file mode 100644 index 000000000..6140453ca --- /dev/null +++ b/src/cache_tab.erl @@ -0,0 +1,563 @@ +%%%------------------------------------------------------------------- +%%% File : cache_tab.erl +%%% Author : Evgeniy Khramtsov <ekhramtsov@process-one.net> +%%% Description : Caching key-value table +%%% +%%% Created : 29 Aug 2010 by Evgeniy Khramtsov <ekhramtsov@process-one.net> +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2010 ProcessOne +%%% +%%% This program is free software; you can redistribute it and/or +%%% modify it under the terms of the GNU General Public License as +%%% published by the Free Software Foundation; either version 2 of the +%%% License, or (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%%% General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program; if not, write to the Free Software +%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +%%% 02111-1307 USA +%%% +%%%------------------------------------------------------------------- +-module(cache_tab). + +-define(GEN_SERVER, gen_server). + +-behaviour(?GEN_SERVER). + +%% API +-export([start_link/4, new/2, delete/1, delete/3, lookup/3, + insert/4, info/2, tab2list/1, setopts/2, + dirty_lookup/3, dirty_insert/4, dirty_delete/3, + all/0, test/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-include("ejabberd.hrl"). + +-record(state, {tab = treap:empty(), + name, + size = 0, + owner, + max_size, + life_time, + warn, + hits = 0, + miss = 0, + procs_num, + cache_missed, + shrink_size}). + +-define(PROCNAME, ?MODULE). +-define(CALL_TIMEOUT, 60000). + +%% Defaults +-define(MAX_SIZE, 1000). +-define(WARN, true). +-define(CACHE_MISSED, true). +-define(LIFETIME, 600). %% 10 minutes + +%%==================================================================== +%% API +%%==================================================================== +start_link(Proc, Tab, Opts, Owner) -> + ?GEN_SERVER:start_link({local, Proc}, ?MODULE, + [Tab, Opts, get_proc_num(), Owner], []). + +new(Tab, Opts) -> + Res = lists:flatmap( + fun(Proc) -> + Spec = {{Tab, Proc}, + {?MODULE, start_link, + [Proc, Tab, Opts, self()]}, + permanent, + brutal_kill, + worker, + [?MODULE]}, + case supervisor:start_child(cache_tab_sup, Spec) of + {ok, _Pid} -> + [ok]; + R -> + [R] + end + end, get_all_procs(Tab)), + case lists:filter(fun(ok) -> false; (_) -> true end, Res) of + [] -> + ok; + Err -> + {error, Err} + end. + +delete(Tab) -> + lists:foreach( + fun(Proc) -> + supervisor:terminate_child(cache_tab_sup, {Tab, Proc}), + supervisor:delete_child(cache_tab_sup, {Tab, Proc}) + end, get_all_procs(Tab)). + +delete(Tab, Key, F) -> + ?GEN_SERVER:call( + get_proc_by_hash(Tab, Key), {delete, Key, F}, ?CALL_TIMEOUT). + +dirty_delete(Tab, Key, F) -> + F(), + ?GEN_SERVER:call( + get_proc_by_hash(Tab, Key), {dirty_delete, Key}, ?CALL_TIMEOUT). + +lookup(Tab, Key, F) -> + ?GEN_SERVER:call( + get_proc_by_hash(Tab, Key), {lookup, Key, F}, ?CALL_TIMEOUT). + +dirty_lookup(Tab, Key, F) -> + Proc = get_proc_by_hash(Tab, Key), + case ?GEN_SERVER:call(Proc, {dirty_lookup, Key}, ?CALL_TIMEOUT) of + {ok, '$cached_mismatch'} -> + error; + {ok, Val} -> + {ok, Val}; + _ -> + case F() of + {ok, Val} -> + ?GEN_SERVER:call( + Proc, {dirty_insert, Key, Val}, ?CALL_TIMEOUT), + {ok, Val}; + _ -> + error + end + end. + +insert(Tab, Key, Val, F) -> + ?GEN_SERVER:call( + get_proc_by_hash(Tab, Key), {insert, Key, Val, F}, ?CALL_TIMEOUT). + +dirty_insert(Tab, Key, Val, F) -> + F(), + ?GEN_SERVER:call( + get_proc_by_hash(Tab, Key), {dirty_insert, Key, Val}, ?CALL_TIMEOUT). + +info(Tab, Info) -> + case lists:map( + fun(Proc) -> + ?GEN_SERVER:call(Proc, {info, Info}, ?CALL_TIMEOUT) + end, get_all_procs(Tab)) of + Res when Info == size -> + {ok, lists:sum(Res)}; + Res when Info == all -> + {ok, Res}; + Res when Info == ratio -> + {H, M} = lists:foldl( + fun({Hits, Miss}, {HitsAcc, MissAcc}) -> + {HitsAcc + Hits, MissAcc + Miss} + end, {0, 0}, Res), + {ok, [{hits, H}, {miss, M}]}; + _ -> + {error, badarg} + end. + +setopts(Tab, Opts) -> + lists:foreach( + fun(Proc) -> + ?GEN_SERVER:call(Proc, {setopts, Opts}, ?CALL_TIMEOUT) + end, get_all_procs(Tab)). + +tab2list(Tab) -> + lists:flatmap( + fun(Proc) -> + ?GEN_SERVER:call(Proc, tab2list, ?CALL_TIMEOUT) + end, get_all_procs(Tab)). + +all() -> + lists:usort( + [Tab || {{Tab, _}, _, _, _} <- supervisor:which_children(cache_tab_sup)]). + +%%==================================================================== +%% gen_server callbacks +%%==================================================================== +init([Tab, Opts, N, Pid]) -> + State = #state{procs_num = N, + owner = Pid, + name = Tab}, + {ok, do_setopts(State, Opts)}. + +handle_call({lookup, Key, F}, _From, #state{tab = T} = State) -> + case treap:lookup(Key, T) of + {ok, _Prio, Val} -> + Hits = State#state.hits, + NewState = treap_update(Key, Val, State#state{hits = Hits + 1}), + case Val of + '$cached_mismatch' -> + {reply, error, NewState}; + _ -> + {reply, {ok, Val}, NewState} + end; + _ -> + case catch F() of + {ok, Val} -> + Miss = State#state.miss, + NewState = treap_insert(Key, Val, State), + {reply, {ok, Val}, NewState#state{miss = Miss + 1}}; + {'EXIT', Reason} -> + print_error(lookup, [Key], Reason, State), + {reply, error, State}; + _ -> + Miss = State#state.miss, + NewState = State#state{miss = Miss + 1}, + if State#state.cache_missed -> + {reply, error, + treap_insert(Key, '$cached_mismatch', NewState)}; + true -> + {reply, error, NewState} + end + end + end; +handle_call({dirty_lookup, Key}, _From, #state{tab = T} = State) -> + case treap:lookup(Key, T) of + {ok, _Prio, Val} -> + Hits = State#state.hits, + NewState = treap_update(Key, Val, State#state{hits = Hits + 1}), + {reply, {ok, Val}, NewState}; + _ -> + Miss = State#state.miss, + NewState = State#state{miss = Miss + 1}, + if State#state.cache_missed -> + {reply, error, + treap_insert(Key, '$cached_mismatch', NewState)}; + true -> + {reply, error, NewState} + end + end; +handle_call({insert, Key, Val, F}, _From, #state{tab = T} = State) -> + case treap:lookup(Key, T) of + {ok, _Prio, Val} -> + {reply, ok, State}; + Res -> + case catch F() of + {'EXIT', Reason} -> + print_error(insert, [Key, Val], Reason, State), + {reply, ok, State}; + _ -> + NewState = case Res of + {ok, _, _} -> + treap_update(Key, Val, State); + _ -> + treap_insert(Key, Val, State) + end, + {reply, ok, NewState} + end + end; +handle_call({dirty_insert, Key, Val}, _From, #state{tab = T} = State) -> + case treap:lookup(Key, T) of + {ok, _Prio, Val} -> + {reply, ok, State}; + {ok, _, _} -> + {reply, ok, treap_update(Key, Val, State)}; + _ -> + {reply, ok, treap_insert(Key, Val, State)} + end; +handle_call({delete, Key, F}, _From, State) -> + NewState = treap_delete(Key, State), + case catch F() of + {'EXIT', Reason} -> + print_error(delete, [Key], Reason, State); + _ -> + ok + end, + {reply, ok, NewState}; +handle_call({dirty_delete, Key}, _From, State) -> + NewState = treap_delete(Key, State), + {reply, ok, NewState}; +handle_call({info, Info}, _From, State) -> + Res = case Info of + size -> + State#state.size; + ratio -> + {State#state.hits, State#state.miss}; + all -> + [{max_size, State#state.max_size}, + {life_time, State#state.life_time}, + {shrink_size, State#state.shrink_size}, + {size, State#state.size}, + {owner, State#state.owner}, + {hits, State#state.hits}, + {miss, State#state.miss}, + {cache_missed, State#state.cache_missed}, + {warn, State#state.warn}]; + _ -> + badarg + end, + {reply, Res, State}; +handle_call(tab2list, _From, #state{tab = T} = State) -> + Res = treap:fold( + fun({Key, _, Val}, Acc) -> + [{Key, Val}|Acc] + end, [], T), + {reply, Res, State}; +handle_call({setopts, Opts}, _From, State) -> + {reply, ok, do_setopts(State, Opts)}; +handle_call(_Request, _From, State) -> + Reply = ok, + {reply, Reply, State}. + +handle_cast(_Msg, State) -> + {noreply, State}. + +handle_info(_Info, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%-------------------------------------------------------------------- +%%% Internal functions +%%-------------------------------------------------------------------- +do_setopts(#state{procs_num = N} = State, Opts) -> + MaxSize = case {proplists:get_value(max_size, Opts), + State#state.max_size} of + {MS, _} when is_integer(MS), MS > 0 -> + round(MS/N); + {unlimited, _} -> + unlimited; + {_, undefined} -> + round(?MAX_SIZE/N); + {_, MS} -> + MS + end, + LifeTime = case {proplists:get_value(life_time, Opts), + State#state.life_time} of + {LT, _} when is_integer(LT), LT > 0 -> + LT*1000*1000; + {unlimited, _} -> + unlimited; + {_, undefined} -> + ?LIFETIME*1000*1000; + {_, LT} -> + LT + end, + ShrinkSize = case {proplists:get_value(shrink_size, Opts), + State#state.shrink_size} of + {SS, _} when is_integer(SS), SS > 0 -> + round(SS/N); + _ when is_integer(MaxSize) -> + round(MaxSize/2); + _ -> + unlimited + end, + Warn = case {proplists:get_value(warn, Opts), + State#state.warn} of + {true, _} -> + true; + {false, _} -> + false; + {_, undefined} -> + ?WARN; + {_, W} -> + W + end, + CacheMissed = case proplists:get_value( + cache_missed, Opts, State#state.cache_missed) of + false -> + false; + true -> + true; + _ -> + ?CACHE_MISSED + end, + State#state{max_size = MaxSize, + warn = Warn, + life_time = LifeTime, + cache_missed = CacheMissed, + shrink_size = ShrinkSize}. + +get_proc_num() -> + erlang:system_info(logical_processors). + +get_proc_by_hash(Tab, Term) -> + N = erlang:phash2(Term, get_proc_num()) + 1, + get_proc(Tab, N). + +get_proc(Tab, N) -> + list_to_atom(atom_to_list(?PROCNAME) ++ "_" ++ + atom_to_list(Tab) ++ "_" ++ integer_to_list(N)). + +get_all_procs(Tab) -> + [get_proc(Tab, N) || N <- lists:seq(1, get_proc_num())]. + +now_priority() -> + {MSec, Sec, USec} = now(), + -((MSec*1000000 + Sec)*1000000 + USec). + +treap_update(Key, Val, #state{tab = T} = State) -> + Priority = now_priority(), + NewT = treap:insert(Key, Priority, Val, T), + State#state{tab = NewT}. + +treap_insert(Key, Val, State) -> + State1 = clean_treap(State), + #state{size = Size} = State2 = shrink_treap(State1), + treap_update(Key, Val, State2#state{size = Size+1}). + +treap_delete(Key, #state{tab = T, size = Size} = State) -> + case treap:lookup(Key, T) of + {ok, _, _} -> + NewT = treap:delete(Key, T), + clean_treap(State#state{tab = NewT, size = Size-1}); + _ -> + State + end. + +clean_treap(#state{tab = T, size = Size, life_time = LifeTime} = State) -> + if is_integer(LifeTime) -> + Priority = now_priority(), + {Cleaned, NewT} = clean_treap(T, Priority + LifeTime, 0), + State#state{size = Size - Cleaned, tab = NewT}; + true -> + State + end. + +clean_treap(Treap, CleanPriority, N) -> + case treap:is_empty(Treap) of + true -> + {N, Treap}; + false -> + {_Key, Priority, _Value} = treap:get_root(Treap), + if Priority > CleanPriority -> + clean_treap(treap:delete_root(Treap), CleanPriority, N+1); + true -> + {N, Treap} + end + end. + +shrink_treap(#state{tab = T, + max_size = MaxSize, + shrink_size = ShrinkSize, + warn = Warn, + size = Size} = State) when Size >= MaxSize -> + if Warn -> + ?WARNING_MSG("shrinking table:~n" + "** Table: ~p~n" + "** Processes Number: ~p~n" + "** Max Size: ~p items~n" + "** Shrink Size: ~p items~n" + "** Life Time: ~p microseconds~n" + "** Hits/Miss: ~p/~p~n" + "** Owner: ~p~n" + "** Cache Missed: ~p~n" + "** Instruction: you have to tune cacheing options" + " if this message repeats too frequently", + [State#state.name, State#state.procs_num, + MaxSize, ShrinkSize, State#state.life_time, + State#state.hits, State#state.miss, + State#state.owner, State#state.cache_missed]); + true -> + ok + end, + {Shrinked, NewT} = shrink_treap(T, ShrinkSize, 0), + State#state{tab = NewT, size = Size - Shrinked}; +shrink_treap(State) -> + State. + +shrink_treap(T, ShrinkSize, ShrinkSize) -> + {ShrinkSize, T}; +shrink_treap(T, ShrinkSize, N) -> + case treap:is_empty(T) of + true -> + {N, T}; + false -> + shrink_treap(treap:delete_root(T), ShrinkSize, N+1) + end. + +print_error(Operation, Args, Reason, State) -> + ?ERROR_MSG("callback failed:~n" + "** Tab: ~p~n" + "** Owner: ~p~n" + "** Operation: ~p~n" + "** Args: ~p~n" + "** Reason: ~p", + [State#state.name, State#state.owner, + Operation, Args, Reason]). + +%%-------------------------------------------------------------------- +%%% Tests +%%-------------------------------------------------------------------- +-define(lookup, dirty_lookup). +-define(delete, dirty_delete). +-define(insert, dirty_insert). +%% -define(lookup, lookup). +%% -define(delete, delete). +%% -define(insert, insert). + +test() -> + LifeTime = 2, + ok = new(test_tbl, [{life_time, LifeTime}, {max_size, unlimited}]), + check([]), + ok = ?insert(test_tbl, "key", "value", fun() -> ok end), + check([{"key", "value"}]), + {ok, "value"} = ?lookup(test_tbl, "key", fun() -> error end), + check([{"key", "value"}]), + io:format("** waiting for ~p seconds to check if cleaner works fine...~n", + [LifeTime+1]), + timer:sleep(timer:seconds(LifeTime+1)), + ok = ?insert(test_tbl, "key1", "value1", fun() -> ok end), + check([{"key1", "value1"}]), + ok = ?delete(test_tbl, "key1", fun() -> ok end), + {ok, "value"} = ?lookup(test_tbl, "key", fun() -> {ok, "value"} end), + check([{"key", "value"}]), + ok = ?delete(test_tbl, "key", fun() -> ok end), + check([]), + %% io:format("** testing buggy callbacks...~n"), + %% delete(test_tbl, "key", fun() -> erlang:error(badarg) end), + %% insert(test_tbl, "key", "val", fun() -> erlang:error(badarg) end), + %% lookup(test_tbl, "key", fun() -> erlang:error(badarg) end), + check([]), + delete(test_tbl), + test1(). + +test1() -> + MaxSize = 10, + ok = new(test_tbl, [{max_size, MaxSize}, {shrink_size, 1}, {warn, false}]), + lists:foreach( + fun(N) -> + ok = ?insert(test_tbl, N, N, fun() -> ok end) + end, lists:seq(1, MaxSize*get_proc_num())), + {ok, MaxSize} = info(test_tbl, size), + delete(test_tbl), + io:format("** testing speed, this may take a while...~n"), + test2(1000), + test2(10000), + test2(100000), + test2(1000000). + +test2(Iter) -> + ok = new(test_tbl, [{max_size, unlimited}, {life_time, unlimited}]), + L = lists:seq(1, Iter), + T1 = now(), + lists:foreach( + fun(N) -> + ok = ?insert(test_tbl, N, N, fun() -> ok end) + end, L), + io:format("** average insert (size = ~p): ~p usec~n", + [Iter, round(timer:now_diff(now(), T1)/Iter)]), + T2 = now(), + lists:foreach( + fun(N) -> + {ok, N} = ?lookup(test_tbl, N, fun() -> ok end) + end, L), + io:format("** average lookup (size = ~p): ~p usec~n", + [Iter, round(timer:now_diff(now(), T2)/Iter)]), + {ok, Iter} = info(test_tbl, size), + delete(test_tbl). + +check(List) -> + Size = length(List), + {ok, Size} = info(test_tbl, size), + List = tab2list(test_tbl). diff --git a/src/cache_tab_sup.erl b/src/cache_tab_sup.erl new file mode 100644 index 000000000..a49593f5e --- /dev/null +++ b/src/cache_tab_sup.erl @@ -0,0 +1,53 @@ +%%%------------------------------------------------------------------- +%%% File : cache_tab_sup.erl +%%% Author : Evgeniy Khramtsov <ekhramtsov@process-one.net> +%%% Description : Cache tables supervisor +%%% +%%% Created : 30 Aug 2010 by Evgeniy Khramtsov <ekhramtsov@process-one.net> +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2010 ProcessOne +%%% +%%% This program is free software; you can redistribute it and/or +%%% modify it under the terms of the GNU General Public License as +%%% published by the Free Software Foundation; either version 2 of the +%%% License, or (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%%% General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program; if not, write to the Free Software +%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +%%% 02111-1307 USA +%%% +%%%------------------------------------------------------------------- +-module(cache_tab_sup). + +-behaviour(supervisor). + +%% API +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). + +-define(SERVER, ?MODULE). + +%%==================================================================== +%% API functions +%%==================================================================== +start_link() -> + supervisor:start_link({local, ?SERVER}, ?MODULE, []). + +%%==================================================================== +%% Supervisor callbacks +%%==================================================================== +init([]) -> + {ok, {{one_for_one,10,1}, []}}. + +%%==================================================================== +%% Internal functions +%%==================================================================== diff --git a/src/configure b/src/configure deleted file mode 100755 index a71534543..000000000 --- a/src/configure +++ /dev/null @@ -1,5977 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.65 for ejabberd 3.0.0-alpha-x. -# -# Report bugs to <ejabberd@process-one.net>. -# -# -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. -# -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi -" - as_required="as_fn_return () { (exit \$1); } -as_fn_success () { as_fn_return 0; } -as_fn_failure () { as_fn_return 1; } -as_fn_ret_success () { return 0; } -as_fn_ret_failure () { return 1; } - -exitcode=0 -as_fn_success || { exitcode=1; echo as_fn_success failed.; } -as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } -as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } -as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : - -else - exitcode=1; echo positional parameters were not saved. -fi -test x\$exitcode = x0 || exit 1" - as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO - as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO - eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 -test \$(( 1 + 1 )) = 2 || exit 1" - if (eval "$as_required") 2>/dev/null; then : - as_have_required=yes -else - as_have_required=no -fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : - -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_found=false -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - as_found=: - case $as_dir in #( - /*) - for as_base in sh bash ksh sh5; do - # Try only shells that exist, to save several forks. - as_shell=$as_dir/$as_base - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : - CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : - break 2 -fi -fi - done;; - esac - as_found=false -done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } -IFS=$as_save_IFS - - - if test "x$CONFIG_SHELL" != x; then : - # We cannot yet assume a decent shell, so we have to provide a - # neutralization value for shells without unset; and this also - # works around shells that cannot unset nonexistent variables. - BASH_ENV=/dev/null - ENV=/dev/null - (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} -fi - - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." - else - $as_echo "$0: Please tell bug-autoconf@gnu.org and -$0: ejabberd@process-one.net about your system, including -$0: any error possibly output before this message. Then -$0: install a modern shell, or manually run the script -$0: under such a shell if you do have one." - fi - exit 1 -fi -fi -fi -SHELL=${CONFIG_SHELL-/bin/sh} -export SHELL -# Unset more variables known to interfere with behavior of common tools. -CLICOLOR_FORCE= GREP_OPTIONS= -unset CLICOLOR_FORCE GREP_OPTIONS - -## --------------------- ## -## M4sh Shell Functions. ## -## --------------------- ## -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -# as_fn_error ERROR [LINENO LOG_FD] -# --------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with status $?, using 1 if that was 0. -as_fn_error () -{ - as_status=$?; test $as_status -eq 0 && as_status=1 - if test "$3"; then - as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 - fi - $as_echo "$as_me: error: $1" >&2 - as_fn_exit $as_status -} # as_fn_error - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - - - as_lineno_1=$LINENO as_lineno_1a=$LINENO - as_lineno_2=$LINENO as_lineno_2a=$LINENO - eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && - test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { - # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -p' - fi -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -test -n "$DJDIR" || exec 7<&0 </dev/null -exec 6>&1 - -# Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= - -# Identity of this package. -PACKAGE_NAME='ejabberd' -PACKAGE_TARNAME='ejabberd' -PACKAGE_VERSION='3.0.0-alpha-x' -PACKAGE_STRING='ejabberd 3.0.0-alpha-x' -PACKAGE_BUGREPORT='ejabberd@process-one.net' -PACKAGE_URL='' - -ac_default_prefix=/ -# Factoring default headers for most tests. -ac_includes_default="\ -#include <stdio.h> -#ifdef HAVE_SYS_TYPES_H -# include <sys/types.h> -#endif -#ifdef HAVE_SYS_STAT_H -# include <sys/stat.h> -#endif -#ifdef STDC_HEADERS -# include <stdlib.h> -# include <stddef.h> -#else -# ifdef HAVE_STDLIB_H -# include <stdlib.h> -# endif -#endif -#ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include <memory.h> -# endif -# include <string.h> -#endif -#ifdef HAVE_STRINGS_H -# include <strings.h> -#endif -#ifdef HAVE_INTTYPES_H -# include <inttypes.h> -#endif -#ifdef HAVE_STDINT_H -# include <stdint.h> -#endif -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif" - -ac_subst_vars='LTLIBOBJS -ERLCFLAGS -target_os -target_vendor -target_cpu -target -host_os -host_vendor -host_cpu -host -build_os -build_vendor -build_cpu -build -md2 -INSTALLUSER -SSL_CFLAGS -SSL_LIBS -full_xml -transient_supervisors -db_type -roster_gateway_workaround -hipe -PAM_LIBS -PAM_CFLAGS -make_pam -pam -ZLIB_LIBS -ZLIB_CFLAGS -make_ejabberd_zlib -ejabberd_zlib -make_web -web -make_tls -tls -make_odbc -odbc -make_eldap -eldap -make_mod_pubsub -mod_pubsub -make_mod_proxy65 -mod_proxy65 -make_mod_muc -mod_muc -LIBOBJS -EGREP -GREP -CPP -ERLANG_EXMPP -ERLANG_LIBS -ERLANG_CFLAGS -ERL -ERLC -SET_MAKE -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC -target_alias -host_alias -build_alias -LIBS -ECHO_T -ECHO_N -ECHO_C -DEFS -mandir -localedir -libdir -psdir -pdfdir -dvidir -htmldir -infodir -docdir -oldincludedir -includedir -localstatedir -sharedstatedir -sysconfdir -datadir -datarootdir -libexecdir -sbindir -bindir -program_transform_name -prefix -exec_prefix -PACKAGE_URL -PACKAGE_BUGREPORT -PACKAGE_STRING -PACKAGE_VERSION -PACKAGE_TARNAME -PACKAGE_NAME -PATH_SEPARATOR -SHELL' -ac_subst_files='' -ac_user_opts=' -enable_option_checking -with_erlang -enable_mod_muc -enable_mod_proxy65 -enable_mod_pubsub -enable_eldap -enable_odbc -enable_tls -enable_web -enable_ejabberd_zlib -with_zlib -enable_pam -with_pam -enable_hipe -enable_roster_gateway_workaround -enable_mssql -enable_transient_supervisors -enable_full_xml -with_openssl -enable_user -' - ac_precious_vars='build_alias -host_alias -target_alias -CC -CFLAGS -LDFLAGS -LIBS -CPPFLAGS -CPP -ERLC -ERLCFLAGS' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -ac_unrecognized_opts= -ac_unrecognized_sep= -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *) ac_optarg=yes ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=\$ac_optarg ;; - - -without-* | --without-*) - ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) as_fn_error "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information." - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - case $ac_envvar in #( - '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error "invalid variable name: \`$ac_envvar'" ;; - esac - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error "missing argument to $ac_option" -fi - -if test -n "$ac_unrecognized_opts"; then - case $enable_option_checking in - no) ;; - fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; - *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; - esac -fi - -# Check all directory arguments for consistency. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir -do - eval ac_val=\$$ac_var - # Remove trailing slashes. - case $ac_val in - */ ) - ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` - eval $ac_var=\$ac_val;; - esac - # Be sure to have absolute directory names. - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error "working directory cannot be determined" -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error "pwd does not report name of working directory" - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$as_myself" || -$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_myself" : 'X\(//\)[^/]' \| \ - X"$as_myself" : 'X\(//\)$' \| \ - X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_myself" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" -fi -ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures ejabberd 3.0.0-alpha-x to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/ejabberd] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] - --target=TARGET configure for building compilers for TARGET [HOST] -_ACEOF -fi - -if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of ejabberd 3.0.0-alpha-x:";; - esac - cat <<\_ACEOF - -Optional Features: - --disable-option-checking ignore unrecognized --enable/--with options - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-mod_muc enable mod_muc (default: yes) - --enable-mod_proxy65 enable mod_proxy65 (default: yes) - --enable-mod_pubsub enable mod_pubsub (default: yes) - --enable-eldap enable eldap (default: yes) - --enable-odbc enable odbc (default: no) - --enable-tls enable tls (default: yes) - --enable-web enable web (default: yes) - --enable-ejabberd_zlib enable ejabberd_zlib (default: yes) - --enable-pam enable pam (default: no) - --enable-hipe compile natively with HiPE, not recommended - (default: no) - --enable-roster-gateway-workaround - turn on workaround for processing gateway - subscriptions (default: no) - --enable-mssql use Microsoft SQL Server database (default: no, - requires --enable-odbc) - --enable-transient_supervisors - use Erlang supervision for transient process - (default: yes) - --enable-full-xml use XML features in XMPP stream (ex: CDATA) - (default: no, requires XML compliant clients) - --enable-user[[[=USER]]] - allow this system user to start ejabberd (default: - no) - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-erlang=PREFIX path to erlc and erl - --with-zlib=PREFIX prefix where zlib is installed - --with-pam=PREFIX prefix where PAM is installed - --with-openssl=PREFIX prefix where OPENSSL is installed - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a - nonstandard directory <lib dir> - LIBS libraries to pass to the linker, e.g. -l<library> - CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if - you have headers in a nonstandard directory <include dir> - CPP C preprocessor - ERLC Erlang/OTP compiler command [autodetected] - ERLCFLAGS Erlang/OTP compiler flags [none] - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -Report bugs to <ejabberd@process-one.net>. -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || - { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || - continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -ejabberd configure 3.0.0-alpha-x -generated by GNU Autoconf 2.65 - -Copyright (C) 2009 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi - -## ------------------------ ## -## Autoconf initialization. ## -## ------------------------ ## - -# ac_fn_c_try_compile LINENO -# -------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_compile - -# ac_fn_c_try_cpp LINENO -# ---------------------- -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_cpp - -# ac_fn_c_try_run LINENO -# ---------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes -# that executables *can* be run. -ac_fn_c_try_run () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : - ac_retval=0 -else - $as_echo "$as_me: program exited with status $ac_status" >&5 - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=$ac_status -fi - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_run - -# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists, giving a warning if it cannot be compiled using -# the include files in INCLUDES and setting the cache variable VAR -# accordingly. -ac_fn_c_check_header_mongrel () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -else - # Is the header compilable? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 -$as_echo_n "checking $2 usability... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_header_compiler=yes -else - ac_header_compiler=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 -$as_echo_n "checking $2 presence... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <$2> -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - ac_header_preproc=yes -else - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( - yes:no: ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; - no:yes:* ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( cat <<\_ASBOX -## --------------------------------------- ## -## Report this to ejabberd@process-one.net ## -## --------------------------------------- ## -_ASBOX - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=\$ac_header_compiler" -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_header_mongrel - -# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists and can be compiled using the include files in -# INCLUDES, setting the cache variable VAR accordingly. -ac_fn_c_check_header_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_header_compile - -# ac_fn_c_try_link LINENO -# ----------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_c_try_link - -# ac_fn_erl_try_run LINENO -# ------------------------ -# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes -# that executables *can* be run. -ac_fn_erl_try_run () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : - ac_retval=0 -else - $as_echo "$as_me: program exited with status $ac_status" >&5 - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=$ac_status -fi - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - as_fn_set_status $ac_retval - -} # ac_fn_erl_try_run -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by ejabberd $as_me 3.0.0-alpha-x, which was -generated by GNU Autoconf 2.65. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" - done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; - 2) - as_fn_append ac_configure_args1 " '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - as_fn_append ac_configure_args " '$ac_arg'" - ;; - esac - done -done -{ ac_configure_args0=; unset ac_configure_args0;} -{ ac_configure_args1=; unset ac_configure_args1;} - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - cat <<\_ASBOX -## ---------------- ## -## Cache variables. ## -## ---------------- ## -_ASBOX - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - cat <<\_ASBOX -## ----------------- ## -## Output variables. ## -## ----------------- ## -_ASBOX - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------------- ## -## File substitutions. ## -## ------------------- ## -_ASBOX - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## -## confdefs.h. ## -## ----------- ## -_ASBOX - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -$as_echo "/* confdefs.h */" > confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE -if test -n "$CONFIG_SITE"; then - ac_site_file1=$CONFIG_SITE -elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site -else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site -fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" -do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special files - # actually), so we avoid doing that. DJGPP emulates it as a regular file. - if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) as_fn_append ac_configure_args " '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 -fi -## -------------------- ## -## Main body of script. ## -## -------------------- ## - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -# Checks for programs. -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "no acceptable C compiler found in \$PATH -See \`config.log' for more details." "$LINENO" 5; } - -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 -$as_echo_n "checking whether the C compiler works... " >&6; } -ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` - -# The possible output files: -ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" - -ac_rmfiles= -for ac_file in $ac_files -do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - * ) ac_rmfiles="$ac_rmfiles $ac_file";; - esac -done -rm -f $ac_rmfiles - -if { { ac_try="$ac_link_default" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link_default") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. -# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' -# in a Makefile. We should not override ac_cv_exeext if it was cached, -# so that the user can short-circuit this test for compilers unknown to -# Autoconf. -for ac_file in $ac_files '' -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; - then :; else - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - fi - # We set ac_cv_exeext here because the later test for it is not - # safe: cross compilers may not add the suffix if given an `-o' - # argument, so we may need to know it at that point already. - # Even if this section looks crufty: it has the advantage of - # actually working. - break;; - * ) - break;; - esac -done -test "$ac_cv_exeext" = no && ac_cv_exeext= - -else - ac_file='' -fi -if test -z "$ac_file"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -$as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "C compiler cannot create executables -See \`config.log' for more details." "$LINENO" 5; }; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 -$as_echo_n "checking for C compiler default output file name... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -$as_echo "$ac_file" >&6; } -ac_exeext=$ac_cv_exeext - -rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -$as_echo_n "checking for suffix of executables... " >&6; } -if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - break;; - * ) break;; - esac -done -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." "$LINENO" 5; } -fi -rm -f conftest conftest$ac_cv_exeext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -$as_echo "$ac_cv_exeext" >&6; } - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdio.h> -int -main () -{ -FILE *f = fopen ("conftest.out", "w"); - return ferror (f) || fclose (f) != 0; - - ; - return 0; -} -_ACEOF -ac_clean_files="$ac_clean_files conftest.out" -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -$as_echo_n "checking whether we are cross compiling... " >&6; } -if test "$cross_compiling" != yes; then - { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if { ac_try='./conftest$ac_cv_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." "$LINENO" 5; } - fi - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } - -rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -$as_echo_n "checking for suffix of object files... " >&6; } -if test "${ac_cv_objext+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - for ac_file in conftest.o conftest.obj conftest.*; do - test -f "$ac_file" || continue; - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot compute suffix of object files: cannot compile -See \`config.log' for more details." "$LINENO" 5; } -fi -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -$as_echo "$ac_cv_objext" >&6; } -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdarg.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg -fi -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } -set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -else - cat >conftest.make <<\_ACEOF -SHELL = /bin/sh -all: - @echo '@@@%%%=$(MAKE)=@@@%%%' -_ACEOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. -case `${MAKE-make} -f conftest.make 2>/dev/null` in - *@@@%%%=?*=@@@%%%*) - eval ac_cv_prog_make_${ac_make}_set=yes;; - *) - eval ac_cv_prog_make_${ac_make}_set=no;; -esac -rm -f conftest.make -fi -if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - SET_MAKE= -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - SET_MAKE="MAKE=${MAKE-make}" -fi - - -if test "x$GCC" = "xyes"; then - CFLAGS="$CFLAGS -Wall" -fi - -#locating erlang - -# Check whether --with-erlang was given. -if test "${with_erlang+set}" = set; then : - withval=$with_erlang; -fi - - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}erlc", so it can be a program name with args. -set dummy ${ac_tool_prefix}erlc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_ERLC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - case $ERLC in - [\\/]* | ?:[\\/]*) - ac_cv_path_ERLC="$ERLC" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_dummy="$with_erlang:$with_erlang/bin:$PATH" -for as_dir in $as_dummy -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_ERLC="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ERLC=$ac_cv_path_ERLC -if test -n "$ERLC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ERLC" >&5 -$as_echo "$ERLC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_ERLC"; then - ac_pt_ERLC=$ERLC - # Extract the first word of "erlc", so it can be a program name with args. -set dummy erlc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_ac_pt_ERLC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_ERLC in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_ERLC="$ac_pt_ERLC" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_dummy="$with_erlang:$with_erlang/bin:$PATH" -for as_dir in $as_dummy -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_ac_pt_ERLC="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_ERLC=$ac_cv_path_ac_pt_ERLC -if test -n "$ac_pt_ERLC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_ERLC" >&5 -$as_echo "$ac_pt_ERLC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_ERLC" = x; then - ERLC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - ERLC=$ac_pt_ERLC - fi -else - ERLC="$ac_cv_path_ERLC" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}erl", so it can be a program name with args. -set dummy ${ac_tool_prefix}erl; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_ERL+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - case $ERL in - [\\/]* | ?:[\\/]*) - ac_cv_path_ERL="$ERL" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_dummy="$with_erlang:$with_erlang/bin:$PATH" -for as_dir in $as_dummy -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_ERL="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ERL=$ac_cv_path_ERL -if test -n "$ERL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ERL" >&5 -$as_echo "$ERL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_ERL"; then - ac_pt_ERL=$ERL - # Extract the first word of "erl", so it can be a program name with args. -set dummy erl; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_ac_pt_ERL+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_ERL in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_ERL="$ac_pt_ERL" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_dummy="$with_erlang:$with_erlang/bin:$PATH" -for as_dir in $as_dummy -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_ac_pt_ERL="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_ERL=$ac_cv_path_ac_pt_ERL -if test -n "$ac_pt_ERL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_ERL" >&5 -$as_echo "$ac_pt_ERL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_ERL" = x; then - ERL="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - ERL=$ac_pt_ERL - fi -else - ERL="$ac_cv_path_ERL" -fi - - - if test "z$ERLC" = "z" || test "z$ERL" = "z"; then - as_fn_error "erlang not found" "$LINENO" 5 - fi - - - cat >>conftest.erl <<_EOF - --module(conftest). --author('alexey@sevcom.net'). - --export([start/0]). - -start() -> - EIDirS = code:lib_dir("erl_interface") ++ "\n", - EILibS = libpath("erl_interface") ++ "\n", - EXMPPDir = code:lib_dir("exmpp"), - case EXMPPDir of - {error, bad_name} -> exit("exmpp not found"); - _ -> ok - end, - EXMPPDirS = EXMPPDir ++ "\n", - RootDirS = code:root_dir() ++ "\n", - file:write_file("conftest.out", list_to_binary(EIDirS ++ EILibS ++ EXMPPDirS ++ RootDirS)), - halt(). - -%% return physical architecture based on OS/Processor -archname() -> - ArchStr = erlang:system_info(system_architecture), - case os:type() of - {win32, _} -> "windows"; - {unix,UnixName} -> - Specs = string:tokens(ArchStr,"-"), - Cpu = case lists:nth(2,Specs) of - "pc" -> "x86"; - _ -> hd(Specs) - end, - atom_to_list(UnixName) ++ "-" ++ Cpu; - _ -> "generic" - end. - -%% Return arch-based library path or a default value if this directory -%% does not exist -libpath(App) -> - PrivDir = code:priv_dir(App), - ArchDir = archname(), - LibArchDir = filename:join([PrivDir,"lib",ArchDir]), - case file:list_dir(LibArchDir) of - %% Arch lib dir exists: We use it - {ok, _List} -> LibArchDir; - %% Arch lib dir does not exist: Return the default value - %% ({error, enoent}): - _Error -> code:lib_dir("erl_interface") ++ "/lib" - end. - -_EOF - - if ! $ERLC conftest.erl; then - as_fn_error "could not compile sample program" "$LINENO" 5 - fi - - if ! $ERL -s conftest -noshell; then - as_fn_error "could not run sample program" "$LINENO" 5 - fi - - if ! test -f conftest.out; then - as_fn_error "erlang program was not properly executed, (conftest.out was not produced)" "$LINENO" 5 - fi - - # First line - ERLANG_EI_DIR=`cat conftest.out | head -n 1` - # Second line - ERLANG_EI_LIB=`cat conftest.out | head -n 2 | tail -n 1` - # Third line - ERLANG_EXMPP=`cat conftest.out | head -n 3 | tail -n 1` - # End line - ERLANG_DIR=`cat conftest.out | tail -n 1` - - ERLANG_CFLAGS="-I$ERLANG_EI_DIR/include -I$ERLANG_DIR/usr/include" - ERLANG_LIBS="-L$ERLANG_EI_LIB -lerl_interface -lei" - - - - - - - - -# Checks for typedefs, structures, and compiler characteristics. - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 -$as_echo_n "checking for an ANSI C-conforming const... " >&6; } -if test "${ac_cv_c_const+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -/* FIXME: Include the comments suggested by Paul. */ -#ifndef __cplusplus - /* Ultrix mips cc rejects this. */ - typedef int charset[2]; - const charset cs; - /* SunOS 4.1.1 cc rejects this. */ - char const *const *pcpcc; - char **ppc; - /* NEC SVR4.0.2 mips cc rejects this. */ - struct point {int x, y;}; - static struct point const zero = {0,0}; - /* AIX XL C 1.02.0.0 rejects this. - It does not let you subtract one const X* pointer from another in - an arm of an if-expression whose if-part is not a constant - expression */ - const char *g = "string"; - pcpcc = &g + (g ? g-g : 0); - /* HPUX 7.0 cc rejects these. */ - ++pcpcc; - ppc = (char**) pcpcc; - pcpcc = (char const *const *) ppc; - { /* SCO 3.2v4 cc rejects this. */ - char *t; - char const *s = 0 ? (char *) 0 : (char const *) 0; - - *t++ = 0; - if (s) return 0; - } - { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ - int x[] = {25, 17}; - const int *foo = &x[0]; - ++foo; - } - { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ - typedef const int *iptr; - iptr p = 0; - ++p; - } - { /* AIX XL C 1.02.0.0 rejects this saying - "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ - struct s { int j; const int *ap[3]; }; - struct s *b; b->j = 5; - } - { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ - const int foo = 10; - if (!foo) return 0; - } - return !cs[0] && !zero.x; -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_const=yes -else - ac_cv_c_const=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 -$as_echo "$ac_cv_c_const" >&6; } -if test $ac_cv_c_const = no; then - -$as_echo "#define const /**/" >>confdefs.h - -fi - - -# Check Erlang headers are installed -#AC_CHECK_HEADER(erl_driver.h,,[AC_MSG_ERROR([cannot find Erlang header files])]) - -# Change default prefix - - -# Checks for library functions. -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "checking how to run the C preprocessor... " >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - # <limits.h> exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <ac_nonexistent.h> -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - # <limits.h> exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <ac_nonexistent.h> -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." "$LINENO" 5; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -$as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if test "${ac_cv_path_GREP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$GREP"; then - ac_path_GREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue -# Check for GNU ac_path_GREP and select it if it is found. - # Check for GNU $ac_path_GREP -case `"$ac_path_GREP" --version 2>&1` in -*GNU*) - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'GREP' >> "conftest.nl" - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_GREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_GREP="$ac_path_GREP" - ac_path_GREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_GREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_GREP"; then - as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_GREP=$GREP -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -$as_echo "$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - if test -z "$EGREP"; then - ac_path_EGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue -# Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_EGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_EGREP"; then - as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_EGREP=$EGREP -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if test "${ac_cv_header_stdc+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <float.h> - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <string.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdlib.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <ctype.h> -#include <stdlib.h> -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - -for ac_header in stdlib.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" -if test "x$ac_cv_header_stdlib_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_STDLIB_H 1 -_ACEOF - -fi - -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 -$as_echo_n "checking for GNU libc compatible malloc... " >&6; } -if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - ac_cv_func_malloc_0_nonnull=no -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#if defined STDC_HEADERS || defined HAVE_STDLIB_H -# include <stdlib.h> -#else -char *malloc (); -#endif - -int -main () -{ -return ! malloc (0); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_func_malloc_0_nonnull=yes -else - ac_cv_func_malloc_0_nonnull=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 -$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } -if test $ac_cv_func_malloc_0_nonnull = yes; then : - -$as_echo "#define HAVE_MALLOC 1" >>confdefs.h - -else - $as_echo "#define HAVE_MALLOC 0" >>confdefs.h - - case " $LIBOBJS " in - *" malloc.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS malloc.$ac_objext" - ;; -esac - - -$as_echo "#define malloc rpl_malloc" >>confdefs.h - -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if test "${ac_cv_header_stdc+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <float.h> - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <string.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdlib.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <ctype.h> -#include <stdlib.h> -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - - - -mod_muc= -make_mod_muc= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build mod_muc" >&5 -$as_echo_n "checking whether build mod_muc... " >&6; } -# Check whether --enable-mod_muc was given. -if test "${enable_mod_muc+set}" = set; then : - enableval=$enable_mod_muc; mr_enable_mod_muc="$enableval" -else - mr_enable_mod_muc=yes -fi - -if test "$mr_enable_mod_muc" = "yes"; then -mod_muc=mod_muc -make_mod_muc=mod_muc/Makefile -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mr_enable_mod_muc" >&5 -$as_echo "$mr_enable_mod_muc" >&6; } - - - - - -mod_proxy65= -make_mod_proxy65= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build mod_proxy65" >&5 -$as_echo_n "checking whether build mod_proxy65... " >&6; } -# Check whether --enable-mod_proxy65 was given. -if test "${enable_mod_proxy65+set}" = set; then : - enableval=$enable_mod_proxy65; mr_enable_mod_proxy65="$enableval" -else - mr_enable_mod_proxy65=yes -fi - -if test "$mr_enable_mod_proxy65" = "yes"; then -mod_proxy65=mod_proxy65 -make_mod_proxy65=mod_proxy65/Makefile -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mr_enable_mod_proxy65" >&5 -$as_echo "$mr_enable_mod_proxy65" >&6; } - - - - - -mod_pubsub= -make_mod_pubsub= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build mod_pubsub" >&5 -$as_echo_n "checking whether build mod_pubsub... " >&6; } -# Check whether --enable-mod_pubsub was given. -if test "${enable_mod_pubsub+set}" = set; then : - enableval=$enable_mod_pubsub; mr_enable_mod_pubsub="$enableval" -else - mr_enable_mod_pubsub=yes -fi - -if test "$mr_enable_mod_pubsub" = "yes"; then -mod_pubsub=mod_pubsub -make_mod_pubsub=mod_pubsub/Makefile -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mr_enable_mod_pubsub" >&5 -$as_echo "$mr_enable_mod_pubsub" >&6; } - - - - - -eldap= -make_eldap= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build eldap" >&5 -$as_echo_n "checking whether build eldap... " >&6; } -# Check whether --enable-eldap was given. -if test "${enable_eldap+set}" = set; then : - enableval=$enable_eldap; mr_enable_eldap="$enableval" -else - mr_enable_eldap=yes -fi - -if test "$mr_enable_eldap" = "yes"; then -eldap=eldap -make_eldap=eldap/Makefile -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mr_enable_eldap" >&5 -$as_echo "$mr_enable_eldap" >&6; } - - - - - -odbc= -make_odbc= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build odbc" >&5 -$as_echo_n "checking whether build odbc... " >&6; } -# Check whether --enable-odbc was given. -if test "${enable_odbc+set}" = set; then : - enableval=$enable_odbc; mr_enable_odbc="$enableval" -else - mr_enable_odbc=no -fi - -if test "$mr_enable_odbc" = "yes"; then -odbc=odbc -make_odbc=odbc/Makefile -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mr_enable_odbc" >&5 -$as_echo "$mr_enable_odbc" >&6; } - - - - - -tls= -make_tls= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build tls" >&5 -$as_echo_n "checking whether build tls... " >&6; } -# Check whether --enable-tls was given. -if test "${enable_tls+set}" = set; then : - enableval=$enable_tls; mr_enable_tls="$enableval" -else - mr_enable_tls=yes -fi - -if test "$mr_enable_tls" = "yes"; then -tls=tls -make_tls=tls/Makefile -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mr_enable_tls" >&5 -$as_echo "$mr_enable_tls" >&6; } - - - - - -web= -make_web= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build web" >&5 -$as_echo_n "checking whether build web... " >&6; } -# Check whether --enable-web was given. -if test "${enable_web+set}" = set; then : - enableval=$enable_web; mr_enable_web="$enableval" -else - mr_enable_web=yes -fi - -if test "$mr_enable_web" = "yes"; then -web=web -make_web=web/Makefile -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mr_enable_web" >&5 -$as_echo "$mr_enable_web" >&6; } - - - - - - -ejabberd_zlib= -make_ejabberd_zlib= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build ejabberd_zlib" >&5 -$as_echo_n "checking whether build ejabberd_zlib... " >&6; } -# Check whether --enable-ejabberd_zlib was given. -if test "${enable_ejabberd_zlib+set}" = set; then : - enableval=$enable_ejabberd_zlib; mr_enable_ejabberd_zlib="$enableval" -else - mr_enable_ejabberd_zlib=yes -fi - -if test "$mr_enable_ejabberd_zlib" = "yes"; then -ejabberd_zlib=ejabberd_zlib -make_ejabberd_zlib=ejabberd_zlib/Makefile -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mr_enable_ejabberd_zlib" >&5 -$as_echo "$mr_enable_ejabberd_zlib" >&6; } - - - - -#locating zlib - -# Check whether --with-zlib was given. -if test "${with_zlib+set}" = set; then : - withval=$with_zlib; -fi - - -if test x"$ejabberd_zlib" != x; then - ZLIB_CFLAGS= - ZLIB_LIBS= - if test x"$with_zlib" != x; then - ZLIB_CFLAGS="-I$with_zlib/include" - ZLIB_LIBS="-L$with_zlib/lib" - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzgets in -lz" >&5 -$as_echo_n "checking for gzgets in -lz... " >&6; } -if test "${ac_cv_lib_z_gzgets+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lz "$ZLIB_LIBS" $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char gzgets (); -int -main () -{ -return gzgets (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_z_gzgets=yes -else - ac_cv_lib_z_gzgets=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzgets" >&5 -$as_echo "$ac_cv_lib_z_gzgets" >&6; } -if test "x$ac_cv_lib_z_gzgets" = x""yes; then : - ZLIB_LIBS="$ZLIB_LIBS -lz" - zlib_found=yes -else - zlib_found=no -fi - - if test $zlib_found = no; then - as_fn_error "Could not find development files of zlib library. Install them or disable \`ejabberd_zlib' with: --disable-ejabberd_zlib" "$LINENO" 5 - fi - zlib_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $ZLIB_CFLAGS" - zlib_save_CPPFLAGS="$CFLAGS" - CPPFLAGS="$CPPFLAGS $ZLIB_CFLAGS" - for ac_header in zlib.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" -if test "x$ac_cv_header_zlib_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_ZLIB_H 1 -_ACEOF - -else - zlib_found=no -fi - -done - - if test $zlib_found = no; then - as_fn_error "Could not find zlib.h. Install it or disable \`ejabberd_zlib' with: --disable-ejabberd_zlib" "$LINENO" 5 - fi - CFLAGS="$zlib_save_CFLAGS" - CPPFLAGS="$zlib_save_CPPFLAGS" - - - -fi - - - -pam= -make_pam= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build pam" >&5 -$as_echo_n "checking whether build pam... " >&6; } -# Check whether --enable-pam was given. -if test "${enable_pam+set}" = set; then : - enableval=$enable_pam; mr_enable_pam="$enableval" -else - mr_enable_pam=no -fi - -if test "$mr_enable_pam" = "yes"; then -pam=pam -make_pam=pam/Makefile -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mr_enable_pam" >&5 -$as_echo "$mr_enable_pam" >&6; } - - - - -#locating PAM - -# Check whether --with-pam was given. -if test "${with_pam+set}" = set; then : - withval=$with_pam; -fi - -if test x"$pam" != x; then - PAM_CFLAGS= - PAM_LIBS= - if test x"$with_pam" != x; then - PAM_CFLAGS="-I$with_pam/include" - PAM_LIBS="-L$with_pam/lib" - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pam_start in -lpam" >&5 -$as_echo_n "checking for pam_start in -lpam... " >&6; } -if test "${ac_cv_lib_pam_pam_start+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpam "$PAM_LIBS" $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char pam_start (); -int -main () -{ -return pam_start (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_pam_pam_start=yes -else - ac_cv_lib_pam_pam_start=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pam_pam_start" >&5 -$as_echo "$ac_cv_lib_pam_pam_start" >&6; } -if test "x$ac_cv_lib_pam_pam_start" = x""yes; then : - PAM_LIBS="$PAM_LIBS -lpam" - pam_found=yes -else - pam_found=no -fi - - if test $pam_found = no; then - as_fn_error "Could not find development files of PAM library. Install them or disable \`pam' with: --disable-pam" "$LINENO" 5 - fi - pam_save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PAM_CFLAGS" - pam_save_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $PAM_CFLAGS" - for ac_header in security/pam_appl.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "security/pam_appl.h" "ac_cv_header_security_pam_appl_h" "$ac_includes_default" -if test "x$ac_cv_header_security_pam_appl_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_SECURITY_PAM_APPL_H 1 -_ACEOF - -else - pam_found=no -fi - -done - - if test $pam_found = no; then - as_fn_error "Could not find security/pam_appl.h. Install it or disable \`pam' with: --disable-pam" "$LINENO" 5 - fi - CFLAGS="$pam_save_CFLAGS" - CPPFLAGS="$pam_save_CPPFLAGS" - - - -fi - - -# Check whether --enable-hipe was given. -if test "${enable_hipe+set}" = set; then : - enableval=$enable_hipe; case "${enableval}" in - yes) hipe=true ;; - no) hipe=false ;; - *) as_fn_error "bad value ${enableval} for --enable-hipe" "$LINENO" 5 ;; -esac -else - hipe=false -fi - - - -# Check whether --enable-roster_gateway_workaround was given. -if test "${enable_roster_gateway_workaround+set}" = set; then : - enableval=$enable_roster_gateway_workaround; case "${enableval}" in - yes) roster_gateway_workaround=true ;; - no) roster_gateway_workaround=false ;; - *) as_fn_error "bad value ${enableval} for --enable-roster-gateway-workaround" "$LINENO" 5 ;; -esac -else - roster_gateway_workaround=false -fi - - - -# Check whether --enable-mssql was given. -if test "${enable_mssql+set}" = set; then : - enableval=$enable_mssql; case "${enableval}" in - yes) db_type=mssql ;; - no) db_type=generic ;; - *) as_fn_error "bad value ${enableval} for --enable-mssql" "$LINENO" 5 ;; -esac -else - db_type=generic -fi - - - -# Check whether --enable-transient_supervisors was given. -if test "${enable_transient_supervisors+set}" = set; then : - enableval=$enable_transient_supervisors; case "${enableval}" in - yes) transient_supervisors=true ;; - no) transient_supervisors=false ;; - *) as_fn_error "bad value ${enableval} for --enable-transient_supervisors" "$LINENO" 5 ;; -esac -else - transient_supervisors=true -fi - - - -# Check whether --enable-full_xml was given. -if test "${enable_full_xml+set}" = set; then : - enableval=$enable_full_xml; case "${enableval}" in - yes) full_xml=true ;; - no) full_xml=false ;; - *) as_fn_error "bad value ${enableval} for --enable-full-xml" "$LINENO" 5 ;; -esac -else - full_xml=false -fi - - - -ac_config_files="$ac_config_files Makefile $make_mod_muc $make_mod_pubsub $make_mod_proxy65 $make_eldap $make_pam $make_web stun/Makefile $make_tls $make_odbc $make_ejabberd_zlib" - -#openssl - -# Check whether --with-openssl was given. -if test "${with_openssl+set}" = set; then : - withval=$with_openssl; -fi - -unset SSL_LIBS; -unset SSL_CFLAGS; -have_openssl=no -if test x"$tls" != x; then - for ssl_prefix in $withval /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr; do - printf "looking for openssl in $ssl_prefix...\n" - SSL_CFLAGS="-I$ssl_prefix/include" - SSL_LIBS="-L$ssl_prefix/lib -lcrypto" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_new in -lssl" >&5 -$as_echo_n "checking for SSL_new in -lssl... " >&6; } -if test "${ac_cv_lib_ssl_SSL_new+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lssl $SSL_LIBS $SSL_CFLAGS $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char SSL_new (); -int -main () -{ -return SSL_new (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_ssl_SSL_new=yes -else - ac_cv_lib_ssl_SSL_new=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_new" >&5 -$as_echo "$ac_cv_lib_ssl_SSL_new" >&6; } -if test "x$ac_cv_lib_ssl_SSL_new" = x""yes; then : - have_openssl=yes -else - have_openssl=no -fi - - if test x"$have_openssl" = xyes; then - save_CPPFLAGS=$CPPFLAGS - CPPFLAGS="-I$ssl_prefix/include $CPPFLAGS" - for ac_header in openssl/ssl.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default" -if test "x$ac_cv_header_openssl_ssl_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_OPENSSL_SSL_H 1 -_ACEOF - have_openssl_h=yes -fi - -done - - CPPFLAGS=$save_CPPFLAGS - if test x"$have_openssl_h" = xyes; then - have_openssl=yes - printf "openssl found in $ssl_prefix\n"; - SSL_LIBS="-L$ssl_prefix/lib -lssl -lcrypto" - CPPFLAGS="-I$ssl_prefix/include $CPPFLAGS" - SSL_CFLAGS="-DHAVE_SSL" - break - fi - else - # Clear this from the autoconf cache, so in the next pass of - # this loop with different -L arguments, it will test again. - unset ac_cv_lib_ssl_SSL_new - fi - done -if test x${have_openssl} != xyes; then - as_fn_error "Could not find development files of OpenSSL library. Install them or disable \`tls' with: --disable-tls" "$LINENO" 5 -fi - - -fi - -# If ssl is kerberized it need krb5.h -# On RedHat and OpenBSD, krb5.h is in an unsual place: -KRB5_INCLUDE="`krb5-config --cflags 2>/dev/null`" -if test -n "$KRB5_INCLUDE" ; then - CPPFLAGS="$CPPFLAGS $KRB5_INCLUDE" -else - # For RedHat For BSD - for D in /usr/kerberos/include /usr/include/kerberos /usr/include/kerberosV - do - if test -d $D ; then - CPPFLAGS="$CPPFLAGS -I$D" - fi - done -fi -ac_fn_c_check_header_mongrel "$LINENO" "krb5.h" "ac_cv_header_krb5_h" "$ac_includes_default" -if test "x$ac_cv_header_krb5_h" = x""yes; then : - -fi - - - -ENABLEUSER="" -# Check whether --enable-user was given. -if test "${enable_user+set}" = set; then : - enableval=$enable_user; case "${enableval}" in - yes) ENABLEUSER=`whoami` ;; - no) ENABLEUSER="" ;; - *) ENABLEUSER=$enableval - esac -fi - -if test "$ENABLEUSER" != ""; then - echo "allow this system user to start ejabberd: $ENABLEUSER" - INSTALLUSER=$ENABLEUSER - -fi - -ac_fn_c_check_header_mongrel "$LINENO" "openssl/md2.h" "ac_cv_header_openssl_md2_h" "$ac_includes_default" -if test "x$ac_cv_header_openssl_md2_h" = x""yes; then : - md2=true -else - md2=false -fi - - - - -ac_aux_dir= -for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - for ac_t in install-sh install.sh shtool; do - if test -f "$ac_dir/$ac_t"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/$ac_t -c" - break 2 - fi - done -done -if test -z "$ac_aux_dir"; then - as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if test "${ac_cv_build+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) as_fn_error "invalid value of canonical build" "$LINENO" 5;; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if test "${ac_cv_host+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) as_fn_error "invalid value of canonical host" "$LINENO" 5;; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 -$as_echo_n "checking target system type... " >&6; } -if test "${ac_cv_target+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test "x$target_alias" = x; then - ac_cv_target=$ac_cv_host -else - ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || - as_fn_error "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 -$as_echo "$ac_cv_target" >&6; } -case $ac_cv_target in -*-*-*) ;; -*) as_fn_error "invalid value of canonical target" "$LINENO" 5;; -esac -target=$ac_cv_target -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_target -shift -target_cpu=$1 -target_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -target_os=$* -IFS=$ac_save_IFS -case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac - - -# The aliases save the names the user supplied, while $host etc. -# will get canonicalized. -test -n "$target_alias" && - test "$program_prefix$program_suffix$program_transform_name" = \ - NONENONEs,x,x, && - program_prefix=${target_alias}- - -#AC_DEFINE_UNQUOTED(CPU_VENDOR_OS, "$target") -#AC_SUBST(target_os) - - -case "$target_os" in - *darwin10*) - echo "Target OS is 'Darwin10'" - ac_ext=erl -ac_compile='$ERLC $ERLCFLAGS -b beam conftest.$ac_ext >&5' -ac_link='$ERLC $ERLCFLAGS -b beam conftest.$ac_ext >&5 && echo "#!/bin/sh" > conftest$ac_exeext && $as_echo "\"$ERL\" -run conftest start -run init stop -noshell" >> conftest$ac_exeext && chmod +x conftest$ac_exeext' - - if test -n "$ERLC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for erlc" >&5 -$as_echo_n "checking for erlc... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ERLC" >&5 -$as_echo "$ERLC" >&6; } -else - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}erlc", so it can be a program name with args. -set dummy ${ac_tool_prefix}erlc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_ERLC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - case $ERLC in - [\\/]* | ?:[\\/]*) - ac_cv_path_ERLC="$ERLC" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_ERLC="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ERLC=$ac_cv_path_ERLC -if test -n "$ERLC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ERLC" >&5 -$as_echo "$ERLC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_ERLC"; then - ac_pt_ERLC=$ERLC - # Extract the first word of "erlc", so it can be a program name with args. -set dummy erlc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_ac_pt_ERLC+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_ERLC in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_ERLC="$ac_pt_ERLC" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_ac_pt_ERLC="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_ERLC=$ac_cv_path_ac_pt_ERLC -if test -n "$ac_pt_ERLC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_ERLC" >&5 -$as_echo "$ac_pt_ERLC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_ERLC" = x; then - ERLC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - ERLC=$ac_pt_ERLC - fi -else - ERLC="$ac_cv_path_ERLC" -fi - -fi - - -if test "$cross_compiling" = yes; then : - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot run test program while cross compiling -See \`config.log' for more details." "$LINENO" 5; } -else - cat > conftest.$ac_ext <<_ACEOF --module(conftest). --export([start/0]). - -start() -> - halt(case erlang:system_info(wordsize) of - 8 -> 0; 4 -> 1 end) -. - -_ACEOF -if ac_fn_erl_try_run "$LINENO"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: found 64-bit Erlang" >&5 -$as_echo "$as_me: found 64-bit Erlang" >&6;} - CBIT=-m64 -else - { $as_echo "$as_me:${as_lineno-$LINENO}: found 32-bit Erlang" >&5 -$as_echo "$as_me: found 32-bit Erlang" >&6;} - CBIT=-m32 -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - - ;; - *) - echo "Target OS is '$target_os'" - CBIT="" - ;; -esac -CFLAGS="$CFLAGS $CBIT" -LD_SHARED="$LD_SHARED $CBIT" -echo "CBIT is set to '$CBIT'" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file - else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -:mline -/\\$/{ - N - s,\\\n,, - b mline -} -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - - -ac_libobjs= -ac_ltlibobjs= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - -: ${CONFIG_STATUS=./config.status} -ac_write_fail=0 -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error ERROR [LINENO LOG_FD] -# --------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with status $?, using 1 if that was 0. -as_fn_error () -{ - as_status=$?; test $as_status -eq 0 && as_status=1 - if test "$3"; then - as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 - fi - $as_echo "$as_me: error: $1" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -p' - fi -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by ejabberd $as_me 3.0.0-alpha-x, which was -generated by GNU Autoconf 2.65. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -case $ac_config_files in *" -"*) set x $ac_config_files; shift; ac_config_files=$*;; -esac - - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# Files that config.status was made for. -config_files="$ac_config_files" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Report bugs to <ejabberd@process-one.net>." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -ac_cs_version="\\ -ejabberd config.status 3.0.0-alpha-x -configured by $0, generated by GNU Autoconf 2.65, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2009 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -test -n "\$AWK" || AWK=awk -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -if \$ac_cs_recheck; then - set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' - export CONFIG_SHELL - exec "\$@" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "$make_mod_muc") CONFIG_FILES="$CONFIG_FILES $make_mod_muc" ;; - "$make_mod_pubsub") CONFIG_FILES="$CONFIG_FILES $make_mod_pubsub" ;; - "$make_mod_proxy65") CONFIG_FILES="$CONFIG_FILES $make_mod_proxy65" ;; - "$make_eldap") CONFIG_FILES="$CONFIG_FILES $make_eldap" ;; - "$make_pam") CONFIG_FILES="$CONFIG_FILES $make_pam" ;; - "$make_web") CONFIG_FILES="$CONFIG_FILES $make_web" ;; - "stun/Makefile") CONFIG_FILES="$CONFIG_FILES stun/Makefile" ;; - "$make_tls") CONFIG_FILES="$CONFIG_FILES $make_tls" ;; - "$make_odbc") CONFIG_FILES="$CONFIG_FILES $make_odbc" ;; - "$make_ejabberd_zlib") CONFIG_FILES="$CONFIG_FILES $make_ejabberd_zlib" ;; - - *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= - trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$tmp/subs1.awk" && -_ACEOF - - -{ - echo "cat >conf$$subs.awk <<_ACEOF" && - echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && - echo "_ACEOF" -} >conf$$subs.sh || - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - . ./conf$$subs.sh || - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 - - ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` - if test $ac_delim_n = $ac_delim_num; then - break - elif $ac_last_try; then - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done -rm -f conf$$subs.sh - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$tmp/subs1.awk" <<\\_ACAWK && -_ACEOF -sed -n ' -h -s/^/S["/; s/!.*/"]=/ -p -g -s/^[^!]*!// -:repl -t repl -s/'"$ac_delim"'$// -t delim -:nl -h -s/\(.\{148\}\)..*/\1/ -t more1 -s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ -p -n -b repl -:more1 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t nl -:delim -h -s/\(.\{148\}\)..*/\1/ -t more2 -s/["\\]/\\&/g; s/^/"/; s/$/"/ -p -b -:more2 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t delim -' <conf$$subs.awk | sed ' -/^[^""]/{ - N - s/\n// -} -' >>$CONFIG_STATUS || ac_write_fail=1 -rm -f conf$$subs.awk -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACAWK -cat >>"\$tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ - || as_fn_error "could not setup config files machinery" "$LINENO" 5 -_ACEOF - -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/ -s/:*\${srcdir}:*/:/ -s/:*@srcdir@:*/:/ -s/^\([^=]*=[ ]*\):*/\1/ -s/:*$// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -fi # test -n "$CONFIG_FILES" - - -eval set X " :F $CONFIG_FILES " -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_sed_extra="$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&2;} - - rm -f "$tmp/stdin" - case $ac_file in - -) cat "$tmp/out" && rm -f "$tmp/out";; - *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; - esac \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 - ;; - - - - esac - -done # for ac_tag - - -as_fn_exit 0 -_ACEOF -ac_clean_files=$ac_clean_files_save - -test $ac_write_fail = 0 || - as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit $? -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - - -echo -echo "********************** WARNING ! ************************" -echo "* ejabberd master is NOT ready for real usage yet, *" -echo "* because it is still in heavy development. *" -echo "* Don't use ejabberd master, it is still alpha code! *" -echo "* Please use ejabberd 2.1.x branch instead. *" -echo "*********************************************************" -echo diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index 6818e8c04..33728e877 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -261,8 +261,7 @@ get_sasl_error_logger_type () -> stop_kindly(DelaySeconds, AnnouncementText) -> Subject = io_lib:format("Server stop in ~p seconds!", [DelaySeconds]), WaitingDesc = io_lib:format("Waiting ~p seconds", [DelaySeconds]), - Steps = [ - {"Stopping ejabberd port listeners", + Steps = [{"Stopping ejabberd port listeners", ejabberd_listener, stop_listeners, []}, {"Sending announcement to connected users", mod_announce, send_announcement_to_all, @@ -388,11 +387,11 @@ import_dir(Path) -> %%% delete_expired_messages() -> - {atomic, ok} = mod_offline:remove_expired_messages(), + mod_offline:remove_expired_messages(), ok. delete_old_messages(Days) -> - {atomic, _} = mod_offline:remove_old_messages(Days), + mod_offline:remove_old_messages(Days), ok. diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index 1f5041f46..bd69964a4 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -140,8 +140,8 @@ anonymous_protocol(Host) when is_list(Host) -> %% defaults to false allow_multiple_connections(Host) when is_list(Host) -> - ejabberd_config:get_local_option( - {allow_multiple_connections, Host}) =:= true. + ejabberd_config:get_local_option({allow_multiple_connections, Host}) + =:= true. %% @spec (User, Server) -> bool() %% User = string() diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index 54419374e..fbdebeb16 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -440,10 +440,10 @@ is_valid_dn(DN, Server, Attrs, State) -> end ++ [{"%d", State#state.host}, {"%D", DN}], case eldap_filter:parse(State#state.dn_filter, SubstValues) of {ok, EldapFilter} -> - case eldap_pool:search(State#state.eldap_id, [ - {base, State#state.base}, - {filter, EldapFilter}, - {attributes, ["dn"]}]) of + case eldap_pool:search(State#state.eldap_id, + [{base, State#state.base}, + {filter, EldapFilter}, + {attributes, ["dn"]}]) of #eldap_search_result{entries = [_|_]} -> DN; _ -> diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 0a3cfe6b5..074564225 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -71,6 +71,9 @@ -include("ejabberd.hrl"). -include("mod_privacy.hrl"). +%% Copied from ejabberd_socket.erl +-record(socket_state, {sockmod, socket, receiver}). + -define(SETS, gb_sets). -define(DICT, dict). @@ -528,6 +531,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> "(~w) Accepted legacy authentication for ~s by ~s", [StateData#state.socket, exmpp_jid:to_binary(JID), AuthModule]), + erlang:link((StateData#state.socket)#socket_state.receiver), SID = {now(), self()}, Conn = get_conn_type(StateData), %% Info = [{ip, StateData#state.ip}, {conn, Conn}, @@ -664,8 +668,8 @@ wait_for_feature_request({xmlstreamelement, #xmlel{ns = NS, name = Name} = El}, TLSEnabled == false, SockMod == gen_tcp -> ServerString = binary_to_list(StateData#state.server), - TLSOpts = case ejabberd_config:get_local_option( - {domain_certfile, ServerString}) of + TLSOpts = case ejabberd_config:get_local_option + ({domain_certfile, ServerString}) of undefined -> StateData#state.tls_options; CertFile -> @@ -1595,9 +1599,6 @@ get_auth_tags([_ | L], U, P, D, R) -> get_auth_tags([], U, P, D, R) -> {U, P, D, R}. -%% Copied from ejabberd_socket.erl --record(socket_state, {sockmod, socket, receiver}). - get_conn_type(StateData) -> case (StateData#state.sockmod):get_sockmod(StateData#state.socket) of gen_tcp -> c2s; @@ -1606,8 +1607,8 @@ get_conn_type(StateData) -> if is_pid(StateData#state.socket) -> unknown; true -> - case ejabberd_zlib:get_sockmod( - (StateData#state.socket)#socket_state.socket) of + case ejabberd_zlib:get_sockmod + ((StateData#state.socket)#socket_state.socket) of gen_tcp -> c2s_compressed; tls -> c2s_compressed_tls end diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index bb75308f9..64bb74b3a 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -24,6 +24,22 @@ %%% %%%------------------------------------------------------------------- +%%% Database schema (version / storage / table) +%%% +%%% 2.1.x / mnesia / captcha +%%% id = string() +%%% pid = pid() +%%% key = string() +%%% tref = any() +%%% args = any() +%%% +%%% 3.0.0-alpha / ets / captcha +%%% id = string() +%%% pid = pid() +%%% key = string() +%%% tref = any() +%%% args = any() + -module(ejabberd_captcha). -behaviour(gen_server). @@ -47,23 +63,20 @@ -define(VFIELD(Type, Var, Value), #xmlel{name = 'field', attrs = [ - #xmlattr{ - name = 'type', + #xmlattr{name = 'type', value = Type }, - #xmlattr{ - name = 'var', + #xmlattr{name = 'var', value = Var } ], children = [ - #xmlel{ - name = 'value', + #xmlel{name = 'value', children = [Value] } ]}). --define(CAPTCHA_TEXT(Lang), translate:translate(Lang, "Enter the text you see")). +-define(CAPTCHA_TEXT(Lang), list_to_binary(translate:translate(Lang, "Enter the text you see"))). -define(CAPTCHA_LIFETIME, 120000). % two minutes -define(RPC_TIMEOUT, 5000). @@ -81,13 +94,13 @@ start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). create_captcha(SID, From, To, Lang, Args) - when is_binary(Lang), is_list(SID) -> + when is_binary(Lang), is_binary(SID) -> case create_image() of {ok, Type, Key, Image} -> Id = randoms:get_string() ++ "-" ++ ejabberd_cluster:node_id(), - B64Image = jlib:encode_base64(binary_to_list(Image)), + B64Image = list_to_binary(jlib:encode_base64(binary_to_list(Image))), JID = exmpp_jid:to_list(From), - CID = "sha1+" ++ sha:sha(Image) ++ "@bob.xmpp.org", + CID = list_to_binary(["sha1+", sha:sha(Image), "@bob.xmpp.org"]), % Data = {xmlelement, "data", % [{"xmlns", ?NS_BOB}, {"cid", CID}, % {"max-age", "0"}, {"type", Type}], @@ -97,16 +110,13 @@ create_captcha(SID, From, To, Lang, Args) name = 'data', ns = ?NS_BOB, attrs = [ - #xmlattr{ - name = 'cid', + #xmlattr{name = 'cid', value = CID }, - #xmlattr{ - name = 'max-age', - value = "0" + #xmlattr{name = 'max-age', + value = <<"0">> }, - #xmlattr{ - name = 'type', + #xmlattr{name = 'type', value = Type } ], @@ -128,47 +138,39 @@ create_captcha(SID, From, To, Lang, Args) name = 'captcha', ns = ?NS_CAPTCHA, children = [ - #xmlel{ - name = 'x', + #xmlel{name = 'x', ns = ?NS_DATA_FORMS_s, attrs = [ - #xmlattr{ - name = 'type', - value = "form" + #xmlattr{name = 'type', + value = <<"form">> } ], children = [ - ?VFIELD("hidden", "FORM_TYPE", #xmlcdata{cdata = ?NS_CAPTCHA}), - ?VFIELD("hidden", "from", #xmlcdata{cdata = exmpp_jid:to_list(To)}), - ?VFIELD("hidden", "challenge", #xmlcdata{cdata = Id}), - ?VFIELD("hidden", "sid", #xmlcdata{cdata = SID}), - #xmlel{ - name = 'field', + ?VFIELD(<<"hidden">>, <<"FORM_TYPE">>, #xmlcdata{cdata = ?NS_CAPTCHA_b}), + ?VFIELD(<<"hidden">>, <<"from">>, #xmlcdata{cdata = exmpp_jid:to_binary(To)}), + ?VFIELD(<<"hidden">>, <<"challenge">>, #xmlcdata{cdata = list_to_binary(Id)}), + ?VFIELD(<<"hidden">>, <<"sid">>, #xmlcdata{cdata = SID}), + #xmlel{name = 'field', attrs = [ - #xmlattr{ - name = 'var', - value = "ocr" + #xmlattr{name = 'var', + value = <<"ocr">> }, - #xmlattr{ - name = 'label', + #xmlattr{name = 'label', value = ?CAPTCHA_TEXT(Lang) } ], children = [ - #xmlel{ - name = 'media', + #xmlel{name = 'media', ns = ?NS_DATA_FORMS_MEDIA_s, children = [ - #xmlel{ - name = 'uri', + #xmlel{name = 'uri', attrs = [ - #xmlattr{ - name = 'type', + #xmlattr{name = 'type', value = Type } ], children = [ - #xmlcdata{cdata = "cid:" ++ CID} + #xmlcdata{cdata = list_to_binary(["cid:", CID])} ] } ] @@ -182,24 +184,19 @@ create_captcha(SID, From, To, Lang, Args) BodyString1 = translate:translate(Lang, "Your messages to ~s are being blocked. To unblock them, visit ~s"), BodyString = io_lib:format(BodyString1, [JID, get_url(Id)]), Body = - #xmlel{ - name = 'body', + #xmlel{name = 'body', children = [ - #xmlcdata{ - cdata = BodyString + #xmlcdata{cdata = list_to_binary(BodyString) } ] }, OOB = - #xmlel{ - name = 'x', + #xmlel{name = 'x', ns = ?NS_OOBD_X_s, children = [ - #xmlel{ - name = 'url', + #xmlel{name = 'url', children = [ - #xmlcdata{ - cdata = get_url(Id)} + #xmlcdata{cdata = list_to_binary(get_url(Id))} ] } ] @@ -227,12 +224,10 @@ build_captcha_html(Id, Lang) -> {ok, _} -> %ImgEl = {xmlelement, "img", [{"src", get_url(Id ++ "/image")}], []}, ImgEl = - #xmlel{ - name = 'img', + #xmlel{name = 'img', attrs = [ - #xmlattr{ - name = 'src', - value = get_url(Id ++ "/image") + #xmlattr{name = 'src', + value = list_to_binary(get_url(Id ++ "/image")) } ] }, @@ -242,20 +237,16 @@ build_captcha_html(Id, Lang) -> % {"name", "id"}, % {"value", Id}], []}, IdEl = - #xmlel{ - name = 'input', + #xmlel{name = 'input', attrs = [ - #xmlattr{ - name = 'type', - value = "hidden" + #xmlattr{name = 'type', + value = <<"hidden">> }, - #xmlattr{ - name = 'name', - value = "id" + #xmlattr{name = 'name', + value = <<"id">> }, - #xmlattr{ - name = 'value', - value = Id + #xmlattr{name = 'value', + value = list_to_binary(Id) } ] }, @@ -263,20 +254,16 @@ build_captcha_html(Id, Lang) -> % {"name", "key"}, % {"size", "10"}], []}, KeyEl = - #xmlel{ - name = 'input', + #xmlel{name = 'input', attrs = [ - #xmlattr{ - name = 'type', - value = "text" + #xmlattr{name = 'type', + value = <<"text">> }, - #xmlattr{ - name = 'name', - value = "key" + #xmlattr{name = 'name', + value = <<"key">> }, - #xmlattr{ - name = 'size', - value = "10" + #xmlattr{name = 'size', + value = <<"10">> } ] }, @@ -295,50 +282,39 @@ build_captcha_html(Id, Lang) -> % {"value", "OK"}], []} % ]}, FormEl = - #xmlel{ - name = 'form', + #xmlel{name = 'form', attrs = [ - #xmlattr{ - name = 'action', - value = get_url(Id) + #xmlattr{name = 'action', + value = list_to_binary(get_url(Id)) }, - #xmlattr{ - name = 'name', - value = "captcha" + #xmlattr{name = 'name', + value = <<"captcha">> }, - #xmlattr{ - name = 'method', - value = "POST" + #xmlattr{name = 'method', + value = <<"POST">> } ], children = [ ImgEl, - #xmlel{ - name = 'br' + #xmlel{name = 'br' }, TextEl, - #xmlel{ - name = 'br' + #xmlel{name = 'br' }, IdEl, KeyEl, - #xmlel{ - name = 'br' + #xmlel{name = 'br' }, - #xmlel{ - name = 'input', + #xmlel{name = 'input', attrs = [ - #xmlattr{ - name = 'type', - value = "submit" + #xmlattr{name = 'type', + value = <<"submit">> }, - #xmlattr{ - name = 'name', - value = "enter" + #xmlattr{name = 'name', + value = <<"enter">> }, - #xmlattr{ - name = 'value', - value = "OK" + #xmlattr{name = 'value', + value = <<"OK">> } ] } @@ -399,16 +375,14 @@ process_reply(El) -> process(_Handlers, #request{method='GET', lang=Lang, path=[_, Id]}) -> case build_captcha_html(Id, Lang) of - {FormEl, _} when is_tuple(FormEl) -> + {FormEl, CaptchaTuple} when is_tuple(CaptchaTuple) -> Form = %{xmlelement, "div", [{"align", "center"}], %[FormEl]}, - #xmlel{ - name = 'div', + #xmlel{name = 'div', attrs = [ - #xmlattr{ - name = 'align', - value = "center" + #xmlattr{name = 'align', + value = <<"center">> } ], children = [FormEl] @@ -444,11 +418,9 @@ process(_Handlers, #request{method='POST', q=Q, lang=Lang, path=[_, Id]}) -> % [{xmlcdata, % translate:translate(Lang, "The captcha is valid.") % }]}, - #xmlel{ - name = 'p', + #xmlel{name = 'p', children = [ - #xmlcdata{ - cdata = translate:translate(Lang, "The captcha is valid.")} + #xmlcdata{cdata = translate:translate(Lang, "The captcha is valid.")} ] }, ejabberd_web:make_xhtml([Form]); @@ -502,7 +474,7 @@ code_change(_OldVsn, State, _Extra) -> %%-------------------------------------------------------------------- %% Function: create_image() -> {ok, Type, Key, Image} | {error, Reason} %% Type = "image/png" | "image/jpeg" | "image/gif" -%% Key = string() +%% Key = binary() %% Image = binary() %% Reason = atom() %%-------------------------------------------------------------------- @@ -516,11 +488,11 @@ create_image(Key) -> Cmd = lists:flatten(io_lib:format("~s ~s", [FileName, Key])), case cmd(Cmd) of {ok, <<16#89, $P, $N, $G, $\r, $\n, 16#1a, $\n, _/binary>> = Img} -> - {ok, "image/png", Key, Img}; + {ok, <<"image/png">>, Key, Img}; {ok, <<16#ff, 16#d8, _/binary>> = Img} -> - {ok, "image/jpeg", Key, Img}; + {ok, <<"image/jpeg">>, Key, Img}; {ok, <<$G, $I, $F, $8, X, $a, _/binary>> = Img} when X==$7; X==$9 -> - {ok, "image/gif", Key, Img}; + {ok, <<"image/gif">>, Key, Img}; {error, enodata = Reason} -> ?ERROR_MSG("Failed to process output from \"~s\". " "Maybe ImageMagick's Convert program is not installed.", @@ -547,6 +519,7 @@ get_prog_name() -> throw({error, option_not_configured_captcha_cmd}) end. +%% @doc (Str::string()) -> string() get_url(Str) -> case ejabberd_config:get_local_option(captcha_host) of Host when is_list(Host) -> diff --git a/src/ejabberd_check.erl b/src/ejabberd_check.erl index 8b315861a..637009980 100644 --- a/src/ejabberd_check.erl +++ b/src/ejabberd_check.erl @@ -88,8 +88,8 @@ get_db_used() -> DBs = lists:foldr( fun([Domain, DB], Acc) -> case check_odbc_option( - ejabberd_config:get_local_option( - {auth_method, Domain})) of + ejabberd_config:get_local_option + ({auth_method, Domain})) of true -> [get_db_type(DB)|Acc]; _ -> Acc end diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index 528b50aa5..e9bca6b21 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -438,8 +438,7 @@ print_usage() -> print_usage(dual, MaxC, ShCode). print_usage(HelpMode, MaxC, ShCode) -> AllCommands = - [ - {"status", [], "Get ejabberd status"}, + [{"status", [], "Get ejabberd status"}, {"stop", [], "Stop ejabberd"}, {"restart", [], "Restart ejabberd"}, {"help", ["[--tags [tag] | com?*]"], "Show help (try: ejabberdctl help help)"}, diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index ebcad372d..b6ae0a9f3 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -64,9 +64,8 @@ % These are the namespace already declared by the stream opening. This is % used at serialization time. -define(DEFAULT_NS, ?NS_JABBER_CLIENT). --define(PREFIXED_NS, [ - {?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx} -]). +-define(PREFIXED_NS, + [{?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx}]). %%==================================================================== %% API diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl index f0cef9fe8..76a24c542 100644 --- a/src/ejabberd_receiver.erl +++ b/src/ejabberd_receiver.erl @@ -440,14 +440,12 @@ do_reset_stream(#state{xml_stream_state = XMLStreamState}) -> new_xmlstream(C2SPid, MaxStanzaSize) -> - Parser = exmpp_xml:start_parser([ - {names_as_atom, true}, - {check_nss, xmpp}, - {check_elems, xmpp}, - {check_attrs, xmpp}, - {max_size, MaxStanzaSize} - ]), - exmpp_xmlstream:start( - {gen_fsm, C2SPid}, Parser, - [{xmlstreamstart, new}] - ). + Parser = exmpp_xml:start_parser([{names_as_atom, true}, + {check_nss, xmpp}, + {check_elems, xmpp}, + {check_attrs, xmpp}, + {max_size, MaxStanzaSize} + ]), + exmpp_xmlstream:start({gen_fsm, C2SPid}, Parser, + [{xmlstreamstart, new}] + ). diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index be3a6401f..f9bc0ab76 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -427,8 +427,8 @@ do_route(OrigFrom, OrigTo, OrigPacket) -> drop end; Rs -> - Value = case ejabberd_config:get_local_option( - {domain_balancing, LDstDomain}) of + Value = case ejabberd_config:get_local_option + ({domain_balancing, LDstDomain}) of undefined -> now(); random -> now(); source -> jlib:short_prepd_jid(From); @@ -477,8 +477,8 @@ do_route(OrigFrom, OrigTo, OrigPacket) -> end. get_component_number(LDomain) -> - case ejabberd_config:get_local_option( - {domain_balancing_component_number, LDomain}) of + case ejabberd_config:get_local_option + ({domain_balancing_component_number, LDomain}) of N when is_integer(N), N > 1 -> N; diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 59af8d9aa..8a69bcb04 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -61,9 +61,8 @@ % These are the namespace already declared by the stream opening. This is % used at serialization time. -define(DEFAULT_NS, ?NS_JABBER_CLIENT). --define(PREFIXED_NS, [ - {?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx} -]). +-define(PREFIXED_NS, + [{?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx}]). -record(s2s, {fromto, pid, key}). -record(state, {}). diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index b1b87c8df..e61e770a8 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -89,9 +89,8 @@ % These are the namespace already declared by the stream opening. This is % used at serialization time. -define(DEFAULT_NS, ?NS_JABBER_SERVER). --define(PREFIXED_NS, [ - {?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx} -]). +-define(PREFIXED_NS, + [{?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx}]). %%%---------------------------------------------------------------------- %%% API @@ -524,8 +523,7 @@ handle_sync_event(get_state_infos, _From, StateName, StateData) -> [D || {{D, _}, established} <- dict:to_list(Connections)] end, - Infos = [ - {direction, in}, + Infos = [{direction, in}, {statename, StateName}, {addr, Addr}, {port, Port}, diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 37d20651b..7e686cce5 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -106,9 +106,8 @@ % These are the namespace already declared by the stream opening. This is % used at serialization time. -define(DEFAULT_NS, ?NS_JABBER_SERVER). --define(PREFIXED_NS, [ - {?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx} -]). +-define(PREFIXED_NS, + [{?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx}]). -define(SOCKET_DEFAULT_RESULT, {error, badarg}). @@ -606,9 +605,8 @@ wait_for_starttls_proceed({xmlstreamelement, El}, StateData) -> ?DEBUG("starttls: ~p", [{StateData#state.myname, StateData#state.server}]), Socket = StateData#state.socket, - TLSOpts = case ejabberd_config:get_local_option( - {domain_certfile, - StateData#state.server}) of + TLSOpts = case ejabberd_config:get_local_option + ({domain_certfile, StateData#state.server}) of undefined -> StateData#state.tls_options; CertFile -> @@ -763,8 +761,7 @@ handle_sync_event(get_state_infos, _From, StateName, StateData) -> _:_ -> {unknown,unknown} end, - Infos = [ - {direction, out}, + Infos = [{direction, out}, {statename, StateName}, {addr, Addr}, {port, Port}, @@ -862,8 +859,8 @@ terminate(Reason, StateName, StateData) -> false -> ok; Key -> - ejabberd_s2s:remove_connection( - {StateData#state.myname, StateData#state.server}, self(), Key) + ejabberd_s2s:remove_connectio + ({StateData#state.myname, StateData#state.server}, self(), Key) end, %% bounce queue manage by process and Erlang message queue bounce_queue(StateData#state.queue, 'remote-server-not-found'), @@ -953,8 +950,8 @@ send_db_request(StateData) -> Server = StateData#state.server, New = case StateData#state.new of false -> - case ejabberd_s2s:try_register( - {StateData#state.myname, Server}) of + case ejabberd_s2s:try_register + ({StateData#state.myname, Server}) of {key, Key} -> Key; false -> diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index a786a217f..943ce4e55 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -349,6 +349,9 @@ handle_info({route, From, To, Packet}, StateName, StateData) -> Err = exmpp_stanza:reply_with_error(Packet, 'not-allowed'), ejabberd_router:route_error(To, From, Err, Packet) end, + {next_state, StateName, StateData}; +handle_info(Info, StateName, StateData) -> + ?ERROR_MSG("Unexpected info: ~p", [Info]), {next_state, StateName, StateData}. diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index f6d09276f..4afeb08e7 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -80,9 +80,8 @@ % These are the namespace already declared by the stream opening. This is % used at serialization time. -define(DEFAULT_NS, ?NS_JABBER_CLIENT). --define(PREFIXED_NS, [ - {?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx} -]). +-define(PREFIXED_NS, + [{?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx}]). -define(IS_BINARY_OR_UNDEF(X), @@ -211,10 +210,12 @@ get_user_info(User, Server, Resource) end, if is_list(Ss), Ss /= [] -> Session = lists:max(Ss), - N = node(element(2, Session#session.sid)), Conn = proplists:get_value(conn, Session#session.info), IP = proplists:get_value(ip, Session#session.info), - [{node, N}, {conn, Conn}, {ip, IP}]; + Priority = Session#session.priority, %% integer() + {CreationNow, Pid} = Session#session.sid, + CreationString = jlib:now_to_utc_string(CreationNow), + [{node, Node}, {conn, Conn}, {ip, IP}, {priority, Priority}, {pid, Pid}, {creation, CreationString}]; true -> offline end. diff --git a/src/ejabberd_sup.erl b/src/ejabberd_sup.erl index e088c032b..7523eed2d 100644 --- a/src/ejabberd_sup.erl +++ b/src/ejabberd_sup.erl @@ -191,6 +191,13 @@ init([]) -> brutal_kill, worker, [ejabberd_cluster]}, + CacheTabSupervisor = + {cache_tab_sup, + {cache_tab_sup, start_link, []}, + permanent, + infinity, + supervisor, + [cache_tab_sup]}, {ok, {{one_for_one, 10, 1}, [Hooks, GlobalRouter, @@ -212,6 +219,7 @@ init([]) -> IQSupervisor, STUNSupervisor, FrontendSocketSupervisor, + CacheTabSupervisor, Listener]}}. diff --git a/src/eldap/eldap.erl b/src/eldap/eldap.erl index 7868f6036..7b14ae5c9 100644 --- a/src/eldap/eldap.erl +++ b/src/eldap/eldap.erl @@ -423,8 +423,8 @@ get_handle(Name) when is_list(Name) -> list_to_atom("eldap_" ++ Name). %%---------------------------------------------------------------------- init([]) -> case get_config() of - {ok, Hosts, Rootdn, Passwd, Opts} -> - init({Hosts, Rootdn, Passwd, Opts}); + {ok, Hosts, Port, Rootdn, Passwd, Opts} -> + init({Hosts, Port, Rootdn, Passwd, Opts}); {error, Reason} -> {stop, Reason} end; @@ -440,8 +440,6 @@ init({Hosts, Port, Rootdn, Passwd, Opts}) -> case Encrypt of tls -> ?LDAPS_PORT; - starttls -> - ?LDAP_PORT; _ -> ?LDAP_PORT end; @@ -886,14 +884,9 @@ cancel_timer(Timer) -> %%% Sanity check of received packet check_tag(Data) -> - case asn1rt_ber_bin:decode_tag(Data) of - {_Tag, Data1, _Rb} -> - case asn1rt_ber_bin:decode_length(Data1) of - {{_Len,_Data2}, _Rb2} -> ok; - _ -> throw({error,decoded_tag_length}) - end; - _ -> throw({error,decoded_tag}) - end. + {_Tag, Data1, _Rb} = asn1rt_ber_bin:decode_tag(Data), + {{_Len,_Data2}, _Rb2} = asn1rt_ber_bin:decode_length(Data1), + ok. close_and_retry(S, Timeout) -> catch (S#eldap.sockmod):close(S#eldap.fd), diff --git a/src/gen_mod.erl b/src/gen_mod.erl index d13b348d0..08ae0f88d 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -246,6 +246,8 @@ get_hosts(Opts, Prefix) -> Hosts end. +get_module_proc(Host, Base) when is_binary(Host) -> + get_module_proc(binary_to_list(Host), Base); get_module_proc(global, Base) -> list_to_atom(atom_to_list(Base) ++ "__global"); get_module_proc(Host, {frontend, Base}) -> diff --git a/src/gen_storage.erl b/src/gen_storage.erl index 99af489fe..541bcd776 100644 --- a/src/gen_storage.erl +++ b/src/gen_storage.erl @@ -58,14 +58,21 @@ behaviour_info(_) -> -include("ejabberd.hrl"). % This is used for ERROR_MSG %% Returns all hosts where the table Tab is defined --spec all_table_hosts(atom()) -> +-spec all_table_hosts(storage_table()) -> [storage_host()]. all_table_hosts(Tab) -> - mnesia:dirty_select(table, [{{table, {'$1', '$2'}, '_', '_'}, + TT = setelement(2, {table, {<<"hidding_from_dialyzer">>, '$2'}, '_', '_'}, {'$1', '$2'}), + Res = (catch mnesia:dirty_select(table, [{TT, [{'=:=', '$2', {const, Tab}}], - ['$1']}]). + ['$1']}])), + case Res of + Res when is_list(Res) -> + [HostB || HostB <- Res, is_binary(HostB)]; + _ -> + [] + end. --spec table_info(storage_host, storage_table, atom()) -> +-spec table_info(storage_host(), storage_table(), atom()) -> any(). table_info(Host, Tab, InfoKey) -> Info = @@ -108,7 +115,7 @@ table_info(Host, Tab, InfoKey) -> %% option() is any mnesia option %% columndef() defaults to text for all unspecified attributes --spec create_table(atom(), storage_host(), storage_table(), #table{}) -> +-spec create_table(atom(), storage_host(), storage_table(), list()) -> tuple(). create_table(mnesia, Host, Tab, Def) -> @@ -130,9 +137,9 @@ define_table(Backend, Host, Name, Def) -> backend = Backend, def = Def}). -%% @spec (#table{}) -> [{atom(), any()}] +%% @spec (list()) -> [{atom(), any()}] --spec filter_mnesia_tabdef(#table{}) -> +-spec filter_mnesia_tabdef(list()) -> [any()]. filter_mnesia_tabdef(TabDef) -> @@ -202,6 +209,7 @@ dirty_read(Host, Tab, Key) -> | {'or', matchrule(), matchrule()} | {'orelse', matchrule(), matchrule()} | {'=', Attribute::atom(), matchvalue()} + | {'<', Attribute::atom(), matchvalue()} | {'=/=', Attribute::atom(), matchvalue()} | {like, Attribute::atom(), matchvalue()}). diff --git a/src/gen_storage_odbc.erl b/src/gen_storage_odbc.erl index 6da489da2..9fd56b4a7 100644 --- a/src/gen_storage_odbc.erl +++ b/src/gen_storage_odbc.erl @@ -22,7 +22,7 @@ attributes :: [string()], % Columns columns :: string(), % "\"col1\", \"col2\" ,..." column_names :: [{string(), [string()]}], % [{string(), [string()]}] (already quoted) - types :: [{string(), atom()}], + types :: [{string(), atom() | tuple()}], host :: string() }). -record(odbc_cont, {tabdef, sql, offset = 0, limit}). diff --git a/src/mod_caps.erl b/src/mod_caps.erl index b338243a7..5cd8e274d 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -99,11 +99,12 @@ get_features(#caps{node = Node, version = Version, exts = Exts}) -> SubNodes = [Version | Exts], lists:foldl( fun(SubNode, Acc) -> - case mnesia:dirty_read({caps_features, - node_to_binary(Node, SubNode)}) of - [] -> + BinaryNode = node_to_binary(Node, SubNode), + case cache_tab:lookup(caps_features, BinaryNode, + caps_read_fun(BinaryNode)) of + error -> Acc; - [#caps_features{features = Features}] -> + {ok, Features} -> binary_to_features(Features) ++ Acc end end, [], SubNodes). @@ -189,13 +190,23 @@ disco_info(Acc, _Host, _Module, _Node, _Lang) -> %%==================================================================== %% gen_server callbacks %%==================================================================== - -init([Host, _Opts]) -> +init([Host, Opts]) -> + case catch mnesia:table_info(caps_features, storage_type) of + {'EXIT', _} -> + ok; + disc_only_copies -> + ok; + _ -> + mnesia:delete_table(caps_features) + end, mnesia:create_table(caps_features, - [{disc_copies, [node()]}, + [{disc_only_copies, [node()]}, {local_content, true}, {attributes, record_info(fields, caps_features)}]), - mnesia:add_table_copy(caps_features, node(), disc_copies), + mnesia:add_table_copy(caps_features, node(), disc_only_copies), + MaxSize = gen_mod:get_opt(cache_size, Opts, 1000), + LifeTime = gen_mod:get_opt(cache_life_time, Opts, timer:hours(24) div 1000), + cache_tab:new(caps_features, [{max_size, MaxSize}, {life_time, LifeTime}]), HostB = list_to_binary(Host), ejabberd_hooks:add(user_send_packet, HostB, ?MODULE, user_send_packet, 75), ejabberd_hooks:add(c2s_stream_features, HostB, @@ -245,8 +256,9 @@ code_change(_OldVsn, State, _Extra) -> feature_request(Host, From, Caps, [SubNode | Tail] = SubNodes) -> Node = Caps#caps.node, BinaryNode = node_to_binary(Node, SubNode), - case mnesia:dirty_read({caps_features, BinaryNode}) of - [] -> + case cache_tab:lookup(caps_features, BinaryNode, + caps_read_fun(BinaryNode)) of + error -> IQ = #iq{type = get, iq_ns = ?NS_JABBER_CLIENT, payload = #xmlel{ns = ?NS_DISCO_INFO, name = 'query', @@ -272,8 +284,10 @@ feature_response(#iq{type = result, payload = El}, [] end, El#xmlel.children), BinaryNode = node_to_binary(Caps#caps.node, SubNode), - mnesia:dirty_write(#caps_features{node_pair = BinaryNode, - features = features_to_binary(Features)}), + BinaryFeatures = features_to_binary(Features), + cache_tab:insert( + caps_features, BinaryNode, BinaryFeatures, + caps_write_fun(BinaryNode, BinaryFeatures)), feature_request(Host, From, Caps, SubNodes); feature_response(timeout, _Host, _From, _Caps, _SubNodes) -> ok; @@ -281,7 +295,8 @@ feature_response(_IQResult, Host, From, Caps, [SubNode | SubNodes]) -> %% We got type=error or invalid type=result stanza, so %% we cache empty feature not to probe the client permanently BinaryNode = node_to_binary(Caps#caps.node, SubNode), - mnesia:dirty_write(#caps_features{node_pair = BinaryNode}), + cache_tab:insert(caps_features, BinaryNode, [], + caps_write_fun(BinaryNode, [])), feature_request(Host, From, Caps, SubNodes). node_to_binary(Node, SubNode) -> @@ -290,6 +305,23 @@ node_to_binary(Node, SubNode) -> features_to_binary(L) -> [list_to_binary(I) || I <- L]. binary_to_features(L) -> [binary_to_list(I) || I <- L]. +caps_read_fun(Node) -> + fun() -> + case mnesia:dirty_read({caps_features, Node}) of + [#caps_features{features = Features}] -> + {ok, Features}; + _ -> + error + end + end. + +caps_write_fun(Node, Features) -> + fun() -> + mnesia:dirty_write( + #caps_features{node_pair = Node, + features = Features}) + end. + make_my_disco_hash(Host) -> JID = exmpp_jid:make(Host), case {ejabberd_hooks:run_fold(disco_local_features, diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl index 157073389..cb8ec1cd8 100644 --- a/src/mod_muc/mod_muc_room.erl +++ b/src/mod_muc/mod_muc_room.erl @@ -232,9 +232,9 @@ normal_state({route, From, undefined, message_time = Now, message_shaper = MessageShaper, message = Packet}, - RoomQueue = queue:in( - {message, From}, - StateData#state.room_queue), + RoomQueue = + queue:in({message, From}, + StateData#state.room_queue), StateData2 = store_user_activity( From, NewActivity, StateData1), @@ -1684,7 +1684,7 @@ add_new_user(From, Nick, Packet, StateData) -> StateData; captcha_required -> SID = case exmpp_stanza:get_id(Packet) of - undefined -> ""; + undefined -> <<"">>; SID1 -> SID1 end, RoomJID = StateData#state.jid, @@ -1693,7 +1693,7 @@ add_new_user(From, Nick, Packet, StateData) -> SID, RoomJID, To, Lang, From) of {ok, ID, CaptchaEls} -> MsgPkt = #xmlel{name = 'message', - attrs = [#xmlattr{name = 'id', value = ID}], + attrs = [#xmlattr{name = 'id', value = list_to_binary(ID)}], children = CaptchaEls}, Robots = ?DICT:store(From, {Nick, Packet}, StateData#state.robots), @@ -3042,8 +3042,8 @@ get_config(Lang, StateData, From) -> true -> [#xmlel{name = 'option', attrs = [?XMLATTR('label', translate:translate(Lang, "No limit"))], - children = [#xmlel{name = 'value', children = [#xmlcdata{ - cdata = <<"none">>}]}]}] + children = [#xmlel{name = 'value', + children = [#xmlcdata{cdata = <<"none">>}]}]}] end ++ [#xmlel{name = 'option', attrs = [?XMLATTR('label', N)], children = [#xmlel{name = 'value', children = [ diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index e1b882e72..1e95553b9 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -157,8 +157,8 @@ start(Host, Opts) -> {match_presence_out, atom} ]}]), update_tables(Host, Backend), - gen_storage:add_table_index(Host, privacy_list, name), - gen_storage:add_table_index(Host, privacy_list_data, name), + gen_storage:add_table_index(HostB, privacy_list, name), + gen_storage:add_table_index(HostB, privacy_list_data, name), ejabberd_hooks:add(privacy_iq_get, HostB, ?MODULE, process_iq_get, 50), ejabberd_hooks:add(privacy_iq_set, HostB, @@ -215,20 +215,21 @@ process_iq_get(_, From, _To, #iq{payload = SubEl}, process_lists_get(LUser, LServer, Active) -> + LServerB = list_to_binary(LServer), F = fun() -> Default = - case gen_storage:read(LServer, {privacy_default_list, {LUser, LServer}}) of + case gen_storage:read(LServerB, {privacy_default_list, {LUser, LServer}}) of [#privacy_default_list{name = Name}] -> Name; _ -> none end, Lists = [List#privacy_list.name - || List <- gen_storage:read(LServer, {privacy_list, {LUser, LServer}})], + || List <- gen_storage:read(LServerB, {privacy_list, {LUser, LServer}})], {Default, Lists} end, - case gen_storage:transaction(LServer, privacy_list, F) of - {'EXIT', _Reason} -> + case gen_storage:transaction(LServerB, privacy_list, F) of + {aborted, _Reason} -> {error, 'internal-server-error'}; {atomic, {Default, Lists}} -> case Lists of @@ -258,19 +259,20 @@ process_list_get(_LUser, _LServer, false) -> {error, 'bad-request'}; process_list_get(LUser, LServer, Name) -> + LServerB = list_to_binary(LServer), F = fun() -> - case gen_storage:select(LServer, privacy_list, + case gen_storage:select(LServerB, privacy_list, [{'=', user_host, {LUser, LServer}}, {'=', name, Name}]) of [] -> none; [#privacy_list{}] -> - gen_storage:select(LServer, privacy_list_data, + gen_storage:select(LServerB, privacy_list_data, [{'=', user_host, {LUser, LServer}}, {'=', name, Name}]) end end, - case gen_storage:transaction(LServer, privacy_list, F) of + case gen_storage:transaction(LServerB, privacy_list, F) of {aborted, _Reason} -> {error, 'internal-server-error'}; {atomic, none} -> @@ -375,10 +377,11 @@ process_iq_set(_, From, _To, #iq{payload = SubEl}) -> process_default_set(LUser, LServer, false) -> + LServerB = list_to_binary(LServer), F = fun() -> - gen_storage:delete(LServer, {privacy_default_list, {LUser, LServer}}) + gen_storage:delete(LServerB, {privacy_default_list, {LUser, LServer}}) end, - case gen_storage:transaction(LServer, privacy_default_list, F) of + case gen_storage:transaction(LServerB, privacy_default_list, F) of {atomic, _} -> {result, []}; _ -> @@ -386,20 +389,21 @@ process_default_set(LUser, LServer, false) -> end; process_default_set(LUser, LServer, Name) -> + LServerB = list_to_binary(LServer), F = fun() -> - case gen_storage:select(LServer, privacy_list, + case gen_storage:select(LServerB, privacy_list, [{'=', user_host, {LUser, LServer}}, {'=', name, Name}]) of [] -> {error, 'item-not-found'}; [#privacy_list{}] -> - gen_storage:write(LServer, + gen_storage:write(LServerB, #privacy_default_list{user_host = {LUser, LServer}, name = Name}), {result, []} end end, - case gen_storage:transaction(LServer, privacy_list, F) of + case gen_storage:transaction(LServerB, privacy_list, F) of {atomic, {error, _} = Error} -> Error; {atomic, {result, _} = Res} -> @@ -413,21 +417,25 @@ process_active_set(_LUser, _LServer, false) -> {result, [], #userlist{}}; process_active_set(LUser, LServer, Name) -> + LServerB = list_to_binary(LServer), F = fun() -> - case gen_storage:select(LServer, privacy_list, + case gen_storage:select(LServerB, privacy_list, [{'=', user_host, {LUser, LServer}}, {'=', name, Name}]) of [#privacy_list{}] -> - List = gen_storage:select(LServer, privacy_list_data, + Data = gen_storage:select(LServerB, privacy_list_data, [{'=', user_host, {LUser, LServer}}, {'=', name, Name}]), + List = list_data_to_items(Data), + NeedDb = is_list_needdb(List), {result, [], #userlist{name = Name, - list = list_data_to_items(List)}}; + needdb = NeedDb, + list = List}}; [] -> {error, 'item-not-found'} end end, - case gen_storage:transaction(LServer, privacy_list, F) of + case gen_storage:transaction(LServerB, privacy_list, F) of {atomic, Res} -> Res; _ -> @@ -440,26 +448,27 @@ process_list_set(_LUser, _LServer, false, _Els) -> {error, 'bad-request'}; process_list_set(LUser, LServer, Name, Els) -> + LServerB = list_to_binary(LServer), case parse_items(Els) of false -> {error, 'bad-request'}; remove -> F = fun() -> - case gen_storage:read(LServer, + case gen_storage:read(LServerB, {privacy_default_list, {LUser, LServer}}) of [#privacy_default_list{name = Default}] when Name == Default -> {error, 'conflict'}; _ -> - gen_storage:delete_where(LServer, privacy_list, + gen_storage:delete_where(LServerB, privacy_list, [{'=', user_host, {LUser, LServer}}, {'=', name, Name}]), - gen_storage:delete_where(LServer, privacy_list_data, + gen_storage:delete_where(LServerB, privacy_list_data, [{'=', user_host, {LUser, LServer}}, {'=', name, Name}]), {result, []} end end, - case gen_storage:transaction(LServer, privacy_list, F) of + case gen_storage:transaction(LServerB, privacy_list, F) of {atomic, {error, _} = Error} -> Error; {atomic, {result, _} = Res} -> @@ -477,24 +486,24 @@ process_list_set(LUser, LServer, Name, Els) -> List -> F = fun() -> OldData = - gen_storage:select(LServer, privacy_list_data, + gen_storage:select(LServerB, privacy_list_data, [{'=', user_host, {LUser, LServer}}, {'=', name, Name}]), lists:foreach( fun(Data1) -> - gen_storage:delete_object(LServer, Data1) + gen_storage:delete_object(LServerB, Data1) end, OldData), - gen_storage:write(LServer, #privacy_list{user_host = {LUser, LServer}, + gen_storage:write(LServerB, #privacy_list{user_host = {LUser, LServer}, name = Name}), NewData = list_items_to_data(LUser, LServer, Name, List), lists:foreach( fun(Data1) -> - gen_storage:write(LServer, Data1) + gen_storage:write(LServerB, Data1) end, NewData), {result, []} end, - case gen_storage:transaction(LServer, privacy_list, F) of + case gen_storage:transaction(LServerB, privacy_list, F) of {atomic, {error, _} = Error} -> Error; {atomic, {result, _} = Res} -> @@ -647,17 +656,17 @@ is_list_needdb(Items) -> end end, Items). -get_user_list(_, User, Server) - when is_binary(User), is_binary(Server) -> +get_user_list(_, User, LServerB) + when is_binary(User), is_binary(LServerB) -> LUser = binary_to_list(User), - LServer = binary_to_list(Server), + LServer = binary_to_list(LServerB), F = fun() -> - case gen_storage:read(LServer, + case gen_storage:read(LServerB, {privacy_default_list, {LUser, LServer}}) of [] -> #userlist{}; [#privacy_default_list{name = Default}] -> - Data = gen_storage:select(LServer, privacy_list_data, + Data = gen_storage:select(LServerB, privacy_list_data, [{'=', user_host, {LUser, LServer}}, {'=', name, Default}]), List = list_data_to_items(Data), @@ -667,7 +676,7 @@ get_user_list(_, User, Server) list = List} end end, - {atomic, Res} = gen_storage:transaction(LServer, privacy_default_list, F), + {atomic, Res} = gen_storage:transaction(LServerB, privacy_default_list, F), Res. @@ -768,9 +777,9 @@ is_ptype_match(Item, PType) -> %% TODO: Investigate this: sometimes Value has binaries, other times has strings is_type_match(jid, Value, JID, _Subscription, _Groups) -> {User, Server, Resource} = exmpp_jid:to_lower(exmpp_jid:parse(Value)), - ((User == undefined) orelse (User == []) orelse (User == exmpp_jid:prep_node(JID))) - andalso ((Server == undefined) orelse (Server == []) orelse (Server == exmpp_jid:prep_domain(JID))) - andalso ((Resource == undefined) orelse (Resource == []) orelse (Resource == exmpp_jid:prep_resource(JID))); + ((User == undefined) orelse (User == exmpp_jid:prep_node(JID))) + andalso ((Server == undefined) orelse (Server == exmpp_jid:prep_domain(JID))) + andalso ((Resource == undefined) orelse (Resource == exmpp_jid:prep_resource(JID))); is_type_match(subscription, Value, _JID, Subscription, _Groups) -> Value == Subscription; is_type_match(group, Value, _JID, _Subscription, Groups) -> @@ -780,10 +789,11 @@ is_type_match(group, Value, _JID, _Subscription, Groups) -> remove_user(User, Server) -> LUser = exmpp_stringprep:nodeprep(User), LServer = exmpp_stringprep:nameprep(Server), + LServerB = list_to_binary(LServer), F = fun() -> - gen_storage:delete(LServer, {privacy_list, {LUser, LServer}}) + gen_storage:delete(LServerB, {privacy_list, {LUser, LServer}}) end, - case gen_storage:transaction(LServer, privacy_list, F) of + case gen_storage:transaction(LServerB, privacy_list, F) of {atomic, _} -> {result, []}; _ -> diff --git a/src/mod_pubsub/mod_pubsub.erl b/src/mod_pubsub/mod_pubsub.erl index 9ece1fe53..77737b44d 100644 --- a/src/mod_pubsub/mod_pubsub.erl +++ b/src/mod_pubsub/mod_pubsub.erl @@ -49,8 +49,6 @@ -behaviour(gen_server). -behaviour(gen_mod). --include_lib("exmpp/include/exmpp.hrl"). - -include("ejabberd.hrl"). -include("adhoc.hrl"). -include("pubsub.hrl"). @@ -296,18 +294,18 @@ update_node_database(Host, ServerHost) -> ?INFO_MSG("upgrade node pubsub tables",[]), F = fun() -> {Result, LastIdx} = lists:foldl( - fun({pubsub_node, NodeId, ParentId, {nodeinfo, Items, Options, Entities}}, {RecList, NodeIdx}) -> + fun({pubsub_node, NodeId, ParentId, {nodeinfo, Items, Options, Entities}}, {RecList, Nidx}) -> ItemsList = lists:foldl( - fun({item, IID, Publisher, Payload}, Acc) -> + fun({item, ItemName, Publisher, Payload}, Acc) -> C = {unknown, Publisher}, M = {now(), Publisher}, mnesia:write( - #pubsub_item{itemid = {IID, NodeIdx}, + #pubsub_item{id = {ItemName, Nidx}, creation = C, modification = M, payload = Payload}), - [{Publisher, IID} | Acc] + [{Publisher, ItemName} | Acc] end, [], Items), Owners = dict:fold( @@ -321,7 +319,7 @@ update_node_database(Host, ServerHost) -> end end, [], ItemsList), mnesia:write({pubsub_state, - {JID, NodeIdx}, + {JID, Nidx}, UsrItems, Aff, Sub}), @@ -331,15 +329,15 @@ update_node_database(Host, ServerHost) -> end end, [], Entities), mnesia:delete({pubsub_node, NodeId}), - {[#pubsub_node{nodeid = NodeId, - id = NodeIdx, + {[#pubsub_node{id = NodeId, + idx = Nidx, parents = [element(2, ParentId)], owners = Owners, options = Options} | - RecList], NodeIdx + 1} + RecList], Nidx + 1} end, {[], 1}, - mnesia:match_object( - {pubsub_node, {Host, '_'}, '_', '_'})), + mnesia:match_object + ({pubsub_node, {Host, '_'}, '_', '_'})), mnesia:write(#pubsub_index{index = node, last = LastIdx, free = []}), Result end, @@ -361,36 +359,37 @@ update_node_database(Host, ServerHost) -> [nodeid, parentid, type, owners, options] -> F = fun({pubsub_node, NodeId, {_, Parent}, Type, Owners, Options}) -> #pubsub_node{ - nodeid = NodeId, - id = 0, + id = NodeId, + idx = 0, parents = [Parent], type = Type, owners = Owners, options = Options} end, + %% TODO : to change nodeid/id and id/idx or not to change ? mnesia:transform_table(pubsub_node, F, [nodeid, id, parents, type, owners, options]), FNew = fun() -> - LastIdx = lists:foldl(fun(#pubsub_node{nodeid = NodeId} = PubsubNode, NodeIdx) -> - mnesia:write(PubsubNode#pubsub_node{id = NodeIdx}), - lists:foreach(fun(#pubsub_state{stateid = StateId} = State) -> + LastIdx = lists:foldl(fun(#pubsub_node{id = NodeId} = PubsubNode, Nidx) -> + mnesia:write(PubsubNode#pubsub_node{idx = Nidx}), + lists:foreach(fun(#pubsub_state{id = StateId} = State) -> {JID, _} = StateId, mnesia:delete({pubsub_state, StateId}), - mnesia:write(State#pubsub_state{stateid = {JID, NodeIdx}}) - end, mnesia:match_object(#pubsub_state{stateid = {'_', NodeId}, _ = '_'})), - lists:foreach(fun(#pubsub_item{itemid = ItemId} = Item) -> - {IID, _} = ItemId, + mnesia:write(State#pubsub_state{id = {JID, Nidx}}) + end, mnesia:match_object(#pubsub_state{id = {'_', NodeId}, _ = '_'})), + lists:foreach(fun(#pubsub_item{id = ItemId} = Item) -> + {ItemName, _} = ItemId, {M1, M2} = Item#pubsub_item.modification, {C1, C2} = Item#pubsub_item.creation, mnesia:delete({pubsub_item, ItemId}), - mnesia:write(Item#pubsub_item{itemid = {IID, NodeIdx}, + mnesia:write(Item#pubsub_item{id = {ItemName, Nidx}, modification = {M2, M1}, creation = {C2, C1}}) - end, mnesia:match_object(#pubsub_item{itemid = {'_', NodeId}, _ = '_'})), - NodeIdx + 1 - end, 1, mnesia:match_object( - {pubsub_node, {Host, '_'}, '_', '_', '_', '_', '_'}) - ++ mnesia:match_object( - {pubsub_node, {{'_', ServerHost, '_'}, '_'}, '_', '_', '_', '_', '_'})), + end, mnesia:match_object(#pubsub_item{id = {'_', NodeId}, _ = '_'})), + Nidx + 1 + end, 1, mnesia:match_object + ({pubsub_node, {Host, '_'}, '_', '_', '_', '_', '_'}) + ++ mnesia:match_object + ({pubsub_node, {{'_', ServerHost, '_'}, '_'}, '_', '_', '_', '_', '_'})), mnesia:write(#pubsub_index{index = node, last = LastIdx, free = []}) end, case mnesia:transaction(FNew) of @@ -403,13 +402,14 @@ update_node_database(Host, ServerHost) -> [nodeid, id, parent, type, owners, options] -> F = fun({pubsub_node, NodeId, Id, Parent, Type, Owners, Options}) -> #pubsub_node{ - nodeid = NodeId, - id = Id, + id = NodeId, + idx = Id, parents = [Parent], type = Type, owners = Owners, options = Options} end, + %% TODO : to change nodeid/id and id/idx or not to change ? mnesia:transform_table(pubsub_node, F, [nodeid, id, parents, type, owners, options]), rename_default_nodeplugin(); _ -> @@ -427,7 +427,7 @@ update_node_database(Host, ServerHost) -> [<<>>] -> []; Parents -> Parents end, - mnesia:write(Node#pubsub_node{nodeid={H, BN}, parents=BP}), + mnesia:write(Node#pubsub_node{id={H, BN}, parents=BP}), mnesia:delete({pubsub_node, {H, N}}); (_) -> ok @@ -446,15 +446,15 @@ update_state_database(_Host, _ServerHost) -> case catch mnesia:table_info(pubsub_state, attributes) of [stateid, items, affiliation, subscription] -> ?INFO_MSG("upgrade state pubsub tables", []), - F = fun ({pubsub_state, {JID, NodeID}, Items, Aff, Sub}, Acc) -> + F = fun ({pubsub_state, {JID, NodeId}, Items, Aff, Sub}, Acc) -> Subs = case Sub of none -> []; _ -> - {result, SubID} = pubsub_subscription:subscribe_node(JID, NodeID, []), - [{Sub, SubID}] + {result, SubId} = pubsub_subscription:subscribe_node(JID, NodeId, []), + [{Sub, SubId}] end, - NewState = #pubsub_state{stateid = {JID, NodeID}, + NewState = #pubsub_state{id = {JID, NodeId}, items = Items, affiliation = Aff, subscriptions = Subs}, @@ -495,10 +495,10 @@ send_loop(State) -> lists:foreach( fun({Node, subscribed, _, SubJID}) -> if (SubJID == LJID) or (SubJID == BJID) -> - #pubsub_node{nodeid = {H, N}, type = Type, id = NodeId, options = Options} = Node, + #pubsub_node{id = {H, N}, type = Type, idx = Nidx, options = Options} = Node, case get_option(Options, send_last_published_item) of on_sub_and_presence -> - send_items(H, N, NodeId, Type, LJID, last); + send_items(H, N, Nidx, Type, LJID, last); _ -> ok end; @@ -548,7 +548,7 @@ send_loop(State) -> spawn(fun() -> Host = State#state.host, Owner = jlib:short_prepd_bare_jid(JID), - lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, type = Type, id = NodeId, options = Options}) -> + lists:foreach(fun(#pubsub_node{id = {_, Node}, type = Type, idx = Nidx, options = Options}) -> case get_option(Options, send_last_published_item) of on_sub_and_presence -> lists:foreach(fun(Resource) -> @@ -563,7 +563,7 @@ send_loop(State) -> {OU, OS, _} = Owner, element(2, get_roster_info(OU, OS, LJID, Grps)) end, - if Subscribed -> send_items(Owner, Node, NodeId, Type, LJID, last); + if Subscribed -> send_items(Owner, Node, Nidx, Type, LJID, last); true -> ok end end, Resources); @@ -616,8 +616,8 @@ disco_identity(_Host, <<>>, _From) -> [#xmlel{name = 'identity', ns = ?NS_DISCO_INFO, attrs = [?XMLATTR('category', <<"pubsub">>), ?XMLATTR('type', <<"pep">>)]}]; disco_identity(Host, Node, From) -> - Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) -> + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, _} -> {result, [#xmlel{name = 'identity', ns = ?NS_DISCO_INFO, @@ -647,8 +647,8 @@ disco_features(_Host, <<>>, _From) -> [?NS_PUBSUB_s | [?NS_PUBSUB_s++"#"++Feature || Feature <- features("pep")]]; disco_features(Host, Node, From) -> - Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) -> + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, _} -> {result, [?NS_PUBSUB_s | [?NS_PUBSUB_s ++ "#" ++ Feature || Feature <- features("pep")]]}; @@ -666,12 +666,12 @@ disco_sm_items({result, OtherItems}, From, To, Node, _Lang) -> {result, disco_items(To, Node, From) ++ OtherItems}. disco_items(Host, <<>>, From) -> - Action = fun(#pubsub_node{nodeid ={_, NodeID}, options = Options, type = Type, id = Idx, owners = Owners}, Acc) -> - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of + Action = fun(#pubsub_node{id ={_, NodeId}, options = Options, type = Type, idx = Nidx, owners = Owners}, Acc) -> + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, _} -> [#xmlel{name = 'item', ns = ?NS_DISCO_INFO, attrs = [?XMLATTR('jid', exmpp_jid:to_binary(Host)), - ?XMLATTR('node', NodeID) | + ?XMLATTR('node', NodeId) | case get_option(Options, title) of false -> []; [Title] -> [?XMLATTR('title', Title)] @@ -686,14 +686,14 @@ disco_items(Host, <<>>, From) -> end; disco_items(Host, Node, From) -> - Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) -> + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, Items} -> {result, [#xmlel{name = 'item', ns = ?NS_DISCO_INFO, attrs = [?XMLATTR('jid', exmpp_jid:to_binary(Host)), - ?XMLATTR('name', ItemID)]} - || #pubsub_item{itemid = {ItemID,_}} <- Items]}; + ?XMLATTR('name', ItemId)]} + || #pubsub_item{id = {ItemId,_}} <- Items]}; _ -> {result, []} end end, @@ -723,6 +723,7 @@ presence_probe(Peer, JID, Pid) -> presence(Host, {presence, User, Server, [Resource], JID}) end end. + presence(ServerHost, Presence) when is_binary(ServerHost) -> presence(binary_to_list(ServerHost), Presence); presence(ServerHost, Presence) -> @@ -771,12 +772,12 @@ unsubscribe_user(Entity, Owner) -> lists:foreach(fun(PType) -> {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Entity]), lists:foreach(fun - ({#pubsub_node{options = Options, owners = Owners, id = NodeId}, subscribed, _, JID}) -> + ({#pubsub_node{options = Options, owners = Owners, idx = Nidx}, subscribed, _, JID}) -> case get_option(Options, access_model) of presence -> case lists:member(BJID, Owners) of true -> - node_action(Host, PType, unsubscribe_node, [NodeId, Entity, JID, all]); + node_action(Host, PType, unsubscribe_node, [Nidx, Entity, JID, all]); false -> {result, ok} end; @@ -807,13 +808,13 @@ remove_user(UserB, ServerB) -> lists:foreach(fun(PType) -> {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Entity]), lists:foreach(fun - ({#pubsub_node{id = NodeId}, _, _, JID}) -> node_action(Host, PType, unsubscribe_node, [NodeId, Entity, JID, all]) + ({#pubsub_node{idx = Nidx}, _, _, JID}) -> node_action(Host, PType, unsubscribe_node, [Nidx, Entity, JID, all]) end, Subscriptions), {result, Affiliations} = node_action(Host, PType, get_entity_affiliations, [Host, Entity]), lists:foreach(fun - ({#pubsub_node{nodeid = {H, N}, parents = []}, owner}) -> delete_node(H, N, Entity); - ({#pubsub_node{nodeid = {H, N}, type = "hometree"}, owner}) when N == HomeTreeBase -> delete_node(H, N, Entity); - ({#pubsub_node{id = NodeId}, publisher}) -> node_action(Host, PType, set_affiliation, [NodeId, Entity, none]); + ({#pubsub_node{id = {H, N}, parents = []}, owner}) -> delete_node(H, N, Entity); + ({#pubsub_node{id = {H, N}, type = "hometree"}, owner}) when N == HomeTreeBase -> delete_node(H, N, Entity); + ({#pubsub_node{idx = Nidx}, publisher}) -> node_action(Host, PType, set_affiliation, [Nidx, Entity, none]); (_) -> ok end, Affiliations) end, plugins(Host)) @@ -1079,7 +1080,7 @@ node_disco_info(Host, Node, From) -> node_disco_info(Host, Node, From, true, true). node_disco_info(Host, Node, From, Identity, Features) -> Action = - fun(#pubsub_node{type = Type, id = NodeId}) -> + fun(#pubsub_node{type = Type, idx = Nidx}) -> I = case Identity of false -> []; @@ -1089,7 +1090,7 @@ node_disco_info(Host, Node, From, Identity, Features) -> [] -> ["leaf"]; %% No sub-nodes: it's a leaf node _ -> - case node_call(Type, get_items, [NodeId, From]) of + case node_call(Type, get_items, [Nidx, From]) of {result, []} -> ["collection"]; {result, _} -> ["leaf", "collection"]; _ -> [] @@ -1150,7 +1151,7 @@ iq_disco_items(Host, [], From) -> case tree_action(Host, get_subnodes, [Host, <<>>, From]) of Nodes when is_list(Nodes) -> {result, lists:map( - fun(#pubsub_node{nodeid = {_, SubNode}, options = Options}) -> + fun(#pubsub_node{id = {_, SubNode}, options = Options}) -> Attrs = case get_option(Options, title) of false -> @@ -1177,17 +1178,17 @@ iq_disco_items(_Host, ?NS_PUBSUB_GET_PENDING, _From) -> {result, CommandItems}; iq_disco_items(Host, Item, From) -> case string:tokens(Item, "!") of - [_SNode, _ItemID] -> + [_SNode, _ItemId] -> {result, []}; [SNode] -> Node = string_to_node(SNode), - Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> - NodeItems = case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) -> + NodeItems = case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, R} -> R; _ -> [] end, Nodes = lists:map( - fun(#pubsub_node{nodeid = {_, SubNode}, options = SubOptions}) -> + fun(#pubsub_node{id = {_, SubNode}, options = SubOptions}) -> Attrs = case get_option(SubOptions, title) of false -> @@ -1198,7 +1199,7 @@ iq_disco_items(Host, Item, From) -> #xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = Attrs} end, tree_call(Host, get_subnodes, [Host, Node, From])), Items = lists:map( - fun(#pubsub_item{itemid = {RN, _}}) -> + fun(#pubsub_item{id = {RN, _}}) -> {result, Name} = node_call(Type, get_item_name, [Host, Node, RN]), #xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host), ?XMLATTR('name', Name)]} end, NodeItems), @@ -1210,11 +1211,11 @@ iq_disco_items(Host, Item, From) -> end end. -get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) -> +get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) -> AccessModel = get_option(Options, access_model), AllowedGroups = get_option(Options, roster_groups_allowed, []), {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups), - node_call(Type, get_items, [NodeIdx, From, AccessModel, PresenceSubscription, RosterGroup, undefined]). + node_call(Type, get_items, [Nidx, From, AccessModel, PresenceSubscription, RosterGroup, undefined]). get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups) -> if (AccessModel == presence) or (AccessModel == roster) -> @@ -1324,28 +1325,28 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) -> {get, 'items'} -> MaxItems = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'max_items', ""), SubId = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'subid', ""), - ItemIDs = lists:foldl(fun + ItemIds = lists:foldl(fun (#xmlel{name = 'item', attrs = ItemAttrs}, Acc) -> case exmpp_xml:get_attribute_from_list_as_list(ItemAttrs, 'id', "") of "" -> Acc; - ItemID -> [ItemID|Acc] + ItemId -> [ItemId|Acc] end; (_, Acc) -> Acc end, [], exmpp_xml:remove_cdata_from_list(Els)), - get_items(Host, Node, From, SubId, MaxItems, ItemIDs); + get_items(Host, Node, From, SubId, MaxItems, ItemIds); {get, 'subscriptions'} -> get_subscriptions(Host, Node, From, Plugins); {get, 'affiliations'} -> get_affiliations(Host, From, Plugins); {get, 'options'} -> - SubID = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'subid', ""), + SubId = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'subid', ""), JID = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'jid', ""), - get_options(Host, Node, JID, SubID, Lang); + get_options(Host, Node, JID, SubId, Lang); {set, 'options'} -> - SubID = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'subid', ""), + SubId = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'subid', ""), JID = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'jid', ""), - set_options(Host, Node, JID, SubID, Els); + set_options(Host, Node, JID, SubId, Els); _ -> {error, 'feature-not-implemented'} end; @@ -1503,12 +1504,12 @@ send_pending_auth_events(Host, Node, Owner) -> ?DEBUG("Sending pending auth events for ~s on ~s:~s", [exmpp_jid:to_list(Owner), Host, node_to_string(Node)]), Action = - fun(#pubsub_node{id = NodeID, type = Type}) -> + fun(#pubsub_node{idx = Nidx, type = Type}) -> case lists:member("get-pending", features(Type)) of true -> - case node_call(Type, get_affiliation, [NodeID, Owner]) of + case node_call(Type, get_affiliation, [Nidx, Owner]) of {result, owner} -> - node_call(Type, get_node_subscriptions, [NodeID]); + node_call(Type, get_node_subscriptions, [Nidx]); _ -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'forbidden')} end; @@ -1518,7 +1519,7 @@ send_pending_auth_events(Host, Node, Owner) -> end, case transaction(Host, Node, Action, sync_dirty) of {result, {N, Subscriptions}} -> - lists:foreach(fun({J, pending, _SubID}) -> + lists:foreach(fun({J, pending, _SubId}) -> {U, S, R} = J, send_authorization_request(N, exmpp_jid:make(U,S,R)); ({J, pending}) -> @@ -1534,7 +1535,7 @@ send_pending_auth_events(Host, Node, Owner) -> %%% authorization handling -send_authorization_request(#pubsub_node{owners = Owners, nodeid = {Host, Node}}, Subscriber) -> +send_authorization_request(#pubsub_node{owners = Owners, id = {Host, Node}}, Subscriber) -> Lang = <<"en">>, %% TODO fix {U, S, R} = Subscriber, Stanza = #xmlel{ns = ?NS_JABBER_CLIENT, name = 'message', children = @@ -1623,14 +1624,14 @@ handle_authorization_response(Host, From, To, Packet, XFields) -> "true" -> true; _ -> false end, - Action = fun(#pubsub_node{type = Type, owners = Owners, id = NodeId}) -> + Action = fun(#pubsub_node{type = Type, owners = Owners, idx = Nidx}) -> IsApprover = lists:member(jlib:short_prepd_bare_jid(From), Owners), - {result, Subscriptions} = node_call(Type, get_subscriptions, [NodeId, Subscriber]), + {result, Subscriptions} = node_call(Type, get_subscriptions, [Nidx, Subscriber]), if not IsApprover -> {error, 'forbidden'}; true -> - update_auth(Host, SNode, Type, NodeId, + update_auth(Host, SNode, Type, Nidx, Subscriber, Allow, Subscriptions) end @@ -1650,19 +1651,19 @@ handle_authorization_response(Host, From, To, Packet, XFields) -> exmpp_stanza:reply_with_error(Packet, 'not-acceptable')) end. -update_auth(Host, Node, Type, NodeId, Subscriber, +update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subscriptions) -> Subscription = lists:filter(fun({pending, _}) -> true; (_) -> false end, Subscriptions), case Subscription of - [{pending, SubID}] -> %% TODO does not work if several pending + [{pending, SubId}] -> %% TODO does not work if several pending NewSubscription = case Allow of true -> subscribed; false -> none end, node_call(Type, set_subscriptions, - [NodeId, Subscriber, NewSubscription, SubID]), + [Nidx, Subscriber, NewSubscription, SubId]), send_authorization_approval(Host, Subscriber, Node, NewSubscription), {result, ok}; @@ -1734,8 +1735,8 @@ update_auth(Host, Node, Type, NodeId, Subscriber, %%<li>The service does not support node creation.</li> %%<li>Only entities that are registered with the service are allowed to create nodes but the requesting entity is not registered.</li> %%<li>The requesting entity does not have sufficient privileges to create nodes.</li> -%%<li>The requested NodeID already exists.</li> -%%<li>The request did not include a NodeID and "instant nodes" are not supported.</li> +%%<li>The requested NodeId already exists.</li> +%%<li>The request did not include a NodeId and "instant nodes" are not supported.</li> %%</ul> %%<p>ote: node creation is a particular case, error return code is evaluated at many places:</p> %%<ul> @@ -1861,8 +1862,8 @@ delete_node(_Host, <<>>, _Owner) -> %% Node is the root {error, 'not-allowed'}; delete_node(Host, Node, Owner) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - case node_call(Type, get_affiliation, [NodeId, Owner]) of + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> + case node_call(Type, get_affiliation, [Nidx, Owner]) of {result, owner} -> ParentTree = tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]), SubsByDepth = [{Depth, [{N, get_node_subs(N)} || N <- Nodes]} || {Depth, Nodes} <- ParentTree], @@ -1880,12 +1881,12 @@ delete_node(Host, Node, Owner) -> case transaction(Host, Node, Action, transaction) of {result, {_, {SubsByDepth, {Result, broadcast, Removed}}}} -> lists:foreach(fun({RNode, _RSubscriptions}) -> - {RH, RN} = RNode#pubsub_node.nodeid, - NodeId = RNode#pubsub_node.id, + {RH, RN} = RNode#pubsub_node.id, + Nidx = RNode#pubsub_node.idx, Type = RNode#pubsub_node.type, Options = RNode#pubsub_node.options, - broadcast_removed_node(RH, RN, NodeId, Type, Options, SubsByDepth), - unset_cached_item(RH, NodeId) + broadcast_removed_node(RH, RN, Nidx, Type, Options, SubsByDepth), + unset_cached_item(RH, Nidx) end, Removed), case Result of default -> {result, Reply}; @@ -1937,7 +1938,7 @@ subscribe_node(Host, Node, From, JID, Configuration) -> _:_ -> {undefined, undefined, undefined} end, - Action = fun(#pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{options = Options, owners = Owners, type = Type, idx = Nidx}) -> Features = features(Type), SubscribeFeature = lists:member("subscribe", Features), OptionsFeature = lists:member("subscription-options", Features), @@ -1962,7 +1963,7 @@ subscribe_node(Host, Node, From, JID, Configuration) -> {error, extended_error('bad-request', "invalid-options")}; true -> node_call(Type, subscribe_node, - [NodeId, From, Subscriber, + [Nidx, From, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, SubOpts]) @@ -1984,9 +1985,9 @@ subscribe_node(Host, Node, From, JID, Configuration) -> end, case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, subscribed, SubId, send_last}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, - send_items(Host, Node, NodeId, Type, Subscriber, last), + send_items(Host, Node, Nidx, Type, Subscriber, last), notify_owners(get_option(TNode#pubsub_node.options, notify_sub), Subscriber, Host, Node, TNode#pubsub_node.owners, "subscribed"), case Result of default -> {result, Reply({subscribed, SubId})}; @@ -2037,8 +2038,8 @@ unsubscribe_node(Host, Node, From, JID, SubId) when is_list(JID) -> end, unsubscribe_node(Host, Node, From, Subscriber, SubId); unsubscribe_node(Host, Node, From, Subscriber, SubId) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, unsubscribe_node, [NodeId, From, Subscriber, SubId]) + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> + node_call(Type, unsubscribe_node, [Nidx, From, Subscriber, SubId]) end, case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, default}} -> @@ -2069,7 +2070,7 @@ publish_item(Host, ServerHost, Node, Publisher, "", Payload) -> %% if publisher does not specify an ItemId, the service MUST generate the ItemId publish_item(Host, ServerHost, Node, Publisher, uniqid(), Payload); publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> - Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> Features = features(Type), PublishFeature = lists:member("publish", Features), PublishModel = get_option(Options, publish_model), @@ -2107,7 +2108,7 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> %% Publisher attempts to publish to persistent node with no item {error, extended_error('bad-request', "item-required")}; true -> - node_call(Type, publish_item, [NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload]) + node_call(Type, publish_item, [Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload]) end end, ServerHostB = list_to_binary(ServerHost), @@ -2117,7 +2118,7 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> [#xmlel{ns = ?NS_PUBSUB, name = 'item', attrs = itemAttr(ItemId)}]}]}, case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, Broadcast, Removed}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, BroadcastPayload = case Broadcast of @@ -2125,25 +2126,25 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> broadcast -> Payload; PluginPayload -> PluginPayload end, - broadcast_publish_item(Host, Node, NodeId, Type, Options, Removed, ItemId, jlib:short_prepd_jid(Publisher), BroadcastPayload), - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), + broadcast_publish_item(Host, Node, Nidx, Type, Options, Removed, ItemId, jlib:short_prepd_jid(Publisher), BroadcastPayload), + set_cached_item(Host, Nidx, ItemId, Publisher, Payload), case Result of default -> {result, Reply}; _ -> {result, Result} end; {result, {TNode, {default, Removed}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, Options, Removed), - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), + broadcast_retract_items(Host, Node, Nidx, Type, Options, Removed), + set_cached_item(Host, Nidx, ItemId, Publisher, Payload), {result, Reply}; {result, {TNode, {Result, Removed}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, Options, Removed), - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), + broadcast_retract_items(Host, Node, Nidx, Type, Options, Removed), + set_cached_item(Host, Nidx, ItemId, Publisher, Payload), {result, Result}; {result, {_, default}} -> {result, Reply}; @@ -2189,7 +2190,7 @@ delete_item(_, "", _, _, _) -> %% Request does not specify a node {error, extended_error('bad-request', "node-required")}; delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> - Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> Features = features(Type), PersistentFeature = lists:member("persistent-items", Features), DeleteFeature = lists:member("delete-items", Features), @@ -2205,18 +2206,18 @@ delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> %% Service does not support item deletion {error, extended_error('feature-not-implemented', unsupported, "delete-items")}; true -> - node_call(Type, delete_item, [NodeId, Publisher, PublishModel, ItemId]) + node_call(Type, delete_item, [Nidx, Publisher, PublishModel, ItemId]) end end, Reply = [], case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, broadcast}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, Options, [ItemId], ForceNotify), - case get_cached_item(Host, NodeId) of - #pubsub_item{itemid = {ItemId, NodeId}, _ = '_'} -> unset_cached_item(Host, NodeId); + broadcast_retract_items(Host, Node, Nidx, Type, Options, [ItemId], ForceNotify), + case get_cached_item(Host, Nidx) of + #pubsub_item{id = {ItemId, Nidx}} -> unset_cached_item(Host, Nidx); _ -> ok end, case Result of @@ -2246,7 +2247,7 @@ delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> %%<li>The specified node does not exist.</li> %%</ul> purge_node(Host, Node, Owner) -> - Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> Features = features(Type), PurgeFeature = lists:member("purge-nodes", Features), PersistentFeature = lists:member("persistent-items", Features), @@ -2262,17 +2263,17 @@ purge_node(Host, Node, Owner) -> %% Node is not configured for persistent items {error, extended_error('feature-not-implemented', unsupported, "persistent-items")}; true -> - node_call(Type, purge_node, [NodeId, Owner]) + node_call(Type, purge_node, [Nidx, Owner]) end end, Reply = [], case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, broadcast}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_purge_node(Host, Node, NodeId, Type, Options), - unset_cached_item(Host, NodeId), + broadcast_purge_node(Host, Node, Nidx, Type, Options), + unset_cached_item(Host, Nidx), case Result of default -> {result, Reply}; _ -> {result, Result} @@ -2290,7 +2291,7 @@ purge_node(Host, Node, Owner) -> %% <p>The permission are not checked in this function.</p> %% @todo We probably need to check that the user doing the query has the right %% to read the items. -get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) -> +get_items(Host, Node, From, SubId, SMaxItems, ItemIds) -> MaxItems = if SMaxItems == "" -> get_max_items_node(Host); @@ -2304,7 +2305,7 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) -> {error, Error} -> {error, Error}; _ -> - Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId, owners = Owners}) -> + Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx, owners = Owners}) -> Features = features(Type), RetreiveFeature = lists:member("retrieve-items", Features), PersistentFeature = lists:member("persistent-items", Features), @@ -2320,19 +2321,19 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) -> {error, extended_error('feature-not-implemented', unsupported, "persistent-items")}; true -> node_call(Type, get_items, - [NodeId, From, + [Nidx, From, AccessModel, PresenceSubscription, RosterGroup, SubId]) end end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Items}} -> - SendItems = case ItemIDs of + SendItems = case ItemIds of [] -> Items; _ -> - lists:filter(fun(#pubsub_item{itemid = {ItemId, _}}) -> - lists:member(ItemId, ItemIDs) + lists:filter(fun(#pubsub_item{id = {ItemId, _}}) -> + lists:member(ItemId, ItemIds) end, Items) end, %% Generate the XML response (Item list), limiting the @@ -2344,17 +2345,19 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) -> Error end end. + get_items(Host, Node) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, get_items, [NodeId, service_jid(Host)]) + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> + node_call(Type, get_items, [Nidx, service_jid(Host)]) end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Items}} -> Items; Error -> Error end. + get_item(Host, Node, ItemId) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, get_item, [NodeId, ItemId]) + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> + node_call(Type, get_item, [Nidx, ItemId]) end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Items}} -> Items; @@ -2431,7 +2434,7 @@ get_affiliations(Host, JID, Plugins) when is_list(Plugins) -> {ok, Affiliations} -> Entities = lists:flatmap( fun({_, none}) -> []; - ({#pubsub_node{nodeid = {_, Node}}, Affiliation}) -> + ({#pubsub_node{id = {_, Node}}, Affiliation}) -> [#xmlel{ns = ?NS_PUBSUB, name = 'affiliation', attrs = [?XMLATTR('node', node_to_string(Node)), ?XMLATTR('affiliation', affiliation_to_string(Affiliation))]}] @@ -2443,10 +2446,10 @@ get_affiliations(Host, JID, Plugins) when is_list(Plugins) -> Error end; get_affiliations(Host, Node, JID) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> Features = features(Type), RetrieveFeature = lists:member("modify-affiliations", Features), - {result, Affiliation} = node_call(Type, get_affiliation, [NodeId, JID]), + {result, Affiliation} = node_call(Type, get_affiliation, [Nidx, JID]), if not RetrieveFeature -> %% Service does not support modify affiliations @@ -2455,7 +2458,7 @@ get_affiliations(Host, Node, JID) -> %% Entity is not an owner {error, 'forbidden'}; true -> - node_call(Type, get_node_affiliations, [NodeId]) + node_call(Type, get_node_affiliations, [Nidx]) end end, case transaction(Host, Node, Action, sync_dirty) of @@ -2507,7 +2510,7 @@ set_affiliations(Host, Node, From, EntitiesEls) -> error -> {error, 'bad-request'}; _ -> - Action = fun(#pubsub_node{owners = Owners, type = Type, id = NodeId}=N) -> + Action = fun(#pubsub_node{owners = Owners, type = Type, idx = Nidx}=N) -> case lists:member(Owner, Owners) of true -> OwnerJID = exmpp_jid:make(Owner), @@ -2517,7 +2520,7 @@ set_affiliations(Host, Node, From, EntitiesEls) -> end, lists:foreach( fun({JID, Affiliation}) -> - {result, _} = node_call(Type, set_affiliation, [NodeId, JID, Affiliation]), + {result, _} = node_call(Type, set_affiliation, [Nidx, JID, Affiliation]), case Affiliation of owner -> NewOwner = jlib:short_prepd_bare_jid(JID), @@ -2547,11 +2550,11 @@ set_affiliations(Host, Node, From, EntitiesEls) -> end end. -get_options(Host, Node, JID, SubID, Lang) -> - Action = fun(#pubsub_node{type = Type, id = NodeID}) -> +get_options(Host, Node, JID, SubId, Lang) -> + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> case lists:member("subscription-options", features(Type)) of true -> - get_options_helper(JID, Lang, Node, NodeID, SubID, Type); + get_options_helper(JID, Lang, Node, Nidx, SubId, Type); false -> {error, extended_error( 'feature-not-implemented', @@ -2563,7 +2566,7 @@ get_options(Host, Node, JID, SubID, Lang) -> Error -> Error end. -get_options_helper(JID, Lang, Node, NodeID, SubID, Type) -> +get_options_helper(JID, Lang, Node, NodeId, SubId, Type) -> Subscriber = try exmpp_jid:parse(JID) of J -> jlib:short_jid(J) catch @@ -2571,43 +2574,43 @@ get_options_helper(JID, Lang, Node, NodeID, SubID, Type) -> exmpp_jid:make("", "", "") %% TODO, check if use <<>> instead of "" end, {result, Subs} = node_call(Type, get_subscriptions, - [NodeID, Subscriber]), - SubIDs = lists:foldl(fun({subscribed, SID}, Acc) -> + [NodeId, Subscriber]), + SubIds = lists:foldl(fun({subscribed, SID}, Acc) -> [SID | Acc]; (_, Acc) -> Acc end, [], Subs), - case {SubID, SubIDs} of + case {SubId, SubIds} of {_, []} -> {error, extended_error('not-acceptable', "not-subscribed")}; {[], [SID]} -> - read_sub(Subscriber, Node, NodeID, SID, Lang); + read_sub(Subscriber, Node, NodeId, SID, Lang); {[], _} -> {error, extended_error('not-acceptable', "subid-required")}; {_, _} -> - read_sub(Subscriber, Node, NodeID, SubID, Lang) + read_sub(Subscriber, Node, NodeId, SubId, Lang) end. -read_sub(Subscriber, Node, NodeID, SubID, Lang) -> - case pubsub_subscription:get_subscription(Subscriber, NodeID, SubID) of +read_sub(Subscriber, Node, NodeId, SubId, Lang) -> + case pubsub_subscription:get_subscription(Subscriber, NodeId, SubId) of {error, notfound} -> {error, extended_error('not-acceptable', "invalid-subid")}; {result, #pubsub_subscription{options = Options}} -> {result, XdataEl} = pubsub_subscription:get_options_xform(Lang, Options), OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options', attrs = [ ?XMLATTR('jid', exmpp_jid:to_binary(Subscriber)), - ?XMLATTR('subid', SubID) | nodeAttr(Node)], + ?XMLATTR('subid', SubId) | nodeAttr(Node)], children = [XdataEl]}, PubsubEl = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [OptionsEl]}, {result, PubsubEl} end. -set_options(Host, Node, JID, SubID, Configuration) -> - Action = fun(#pubsub_node{type = Type, id = NodeID}) -> +set_options(Host, Node, JID, SubId, Configuration) -> + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> case lists:member("subscription-options", features(Type)) of true -> - set_options_helper(Configuration, JID, NodeID, - SubID, Type); + set_options_helper(Configuration, JID, Nidx, + SubId, Type); false -> {error, extended_error( 'feature-not-implemented', @@ -2619,7 +2622,7 @@ set_options(Host, Node, JID, SubID, Configuration) -> Error -> Error end. -set_options_helper(Configuration, JID, NodeID, SubID, Type) -> +set_options_helper(Configuration, JID, NodeId, SubId, Type) -> SubOpts = case pubsub_subscription:parse_options_xform(Configuration) of {result, GoodSubOpts} -> GoodSubOpts; _ -> invalid @@ -2630,27 +2633,27 @@ set_options_helper(Configuration, JID, NodeID, SubID, Type) -> _ -> exmpp_jid:make("", "", "") %% TODO, check if use <<>> instead of "" end, {result, Subs} = node_call(Type, get_subscriptions, - [NodeID, Subscriber]), - SubIDs = lists:foldl(fun({subscribed, SID}, Acc) -> + [NodeId, Subscriber]), + SubIds = lists:foldl(fun({subscribed, SID}, Acc) -> [SID | Acc]; (_, Acc) -> Acc end, [], Subs), - case {SubID, SubIDs} of + case {SubId, SubIds} of {_, []} -> {error, extended_error('not-acceptable', "not-subscribed")}; {[], [SID]} -> - write_sub(Subscriber, NodeID, SID, SubOpts); + write_sub(Subscriber, NodeId, SID, SubOpts); {[], _} -> {error, extended_error('not-acceptable', "subid-required")}; {_, _} -> - write_sub(Subscriber, NodeID, SubID, SubOpts) + write_sub(Subscriber, NodeId, SubId, SubOpts) end. -write_sub(_Subscriber, _NodeID, _SubID, invalid) -> +write_sub(_Subscriber, _NodeId, _SubId, invalid) -> {error, extended_error('bad-request', "invalid-options")}; -write_sub(Subscriber, NodeID, SubID, Options) -> - case pubsub_subscription:set_subscription(Subscriber, NodeID, SubID, Options) of +write_sub(Subscriber, NodeId, SubId, Options) -> + case pubsub_subscription:set_subscription(Subscriber, NodeId, SubId, Options) of {error, notfound} -> {error, extended_error('not-acceptable', "invalid-subid")}; {result, _} -> @@ -2685,7 +2688,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> Entities = lists:flatmap( fun({_, none}) -> []; - ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription}) -> + ({#pubsub_node{id = {_, SubsNode}}, Subscription}) -> case Node of <<>> -> [#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs = @@ -2699,22 +2702,22 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> end; ({_, none, _}) -> []; - ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubID, SubJID}) -> + ({#pubsub_node{id = {_, SubsNode}}, Subscription, SubId, SubJID}) -> case Node of <<>> -> [#xmlel{ns = ?NS_PUBSUB, name='subscription', attrs = [?XMLATTR('jid', exmpp_jid:to_binary(SubJID)), - ?XMLATTR('subid', SubID), + ?XMLATTR('subid', SubId), ?XMLATTR('subscription', subscription_to_string(Subscription)) | nodeAttr(SubsNode)]}]; SubsNode -> [#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs = [?XMLATTR('jid', exmpp_jid:to_binary(SubJID)), - ?XMLATTR('subid', SubID), + ?XMLATTR('subid', SubId), ?XMLATTR('subscription', subscription_to_string(Subscription))]}]; _ -> [] end; - ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubJID}) -> + ({#pubsub_node{id = {_, SubsNode}}, Subscription, SubJID}) -> case Node of <<>> -> [#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs = @@ -2736,10 +2739,10 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> Error end. get_subscriptions(Host, Node, JID) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> Features = features(Type), RetrieveFeature = lists:member("manage-subscriptions", Features), - {result, Affiliation} = node_call(Type, get_affiliation, [NodeId, JID]), + {result, Affiliation} = node_call(Type, get_affiliation, [Nidx, JID]), if not RetrieveFeature -> %% Service does not support manage subscriptions @@ -2748,7 +2751,7 @@ get_subscriptions(Host, Node, JID) -> %% Entity is not an owner {error, 'forbidden'}; true -> - node_call(Type, get_node_subscriptions, [NodeId]) + node_call(Type, get_node_subscriptions, [Nidx]) end end, case transaction(Host, Node, Action, sync_dirty) of @@ -2824,12 +2827,12 @@ set_subscriptions(Host, Node, From, EntitiesEls) -> ?XMLATTR('subsription', subscription_to_string(Sub)) | nodeAttr(Node)]}]}]}, ejabberd_router:route(service_jid(Host), JID, Stanza) end, - Action = fun(#pubsub_node{owners = Owners, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{owners = Owners, type = Type, idx = Nidx}) -> case lists:member(Owner, Owners) of true -> Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) -> - case node_call(Type, set_subscriptions, [NodeId, JID, Subscription, SubId]) of + case node_call(Type, set_subscriptions, [Nidx, JID, Subscription, SubId]) of {error, Err} -> [{error, Err} | Acc]; _ -> Notify(JID, Subscription, SubId), Acc end @@ -3179,18 +3182,17 @@ get_collection_subscriptions(Host, Node) -> _ -> [] end. -get_node_subs(#pubsub_node{type = Type, - id = NodeID}) -> - case node_call(Type, get_node_subscriptions, [NodeID]) of - {result, Subs} -> get_options_for_subs(NodeID, Subs); +get_node_subs(#pubsub_node{type = Type, idx = Nidx}) -> + case node_call(Type, get_node_subscriptions, [Nidx]) of + {result, Subs} -> get_options_for_subs(Nidx, Subs); Other -> Other end. -get_options_for_subs(NodeID, Subs) -> - lists:foldl(fun({JID, subscribed, SubID}, Acc) -> - case pubsub_subscription:read_subscription(JID, NodeID, SubID) of - {error, notfound} -> [{JID, SubID, []} | Acc]; - #pubsub_subscription{options = Options} -> [{JID, SubID, Options} | Acc]; +get_options_for_subs(Nidx, Subs) -> + lists:foldl(fun({JID, subscribed, SubId}, Acc) -> + case pubsub_subscription:read_subscription(JID, Nidx, SubId) of + {error, notfound} -> [{JID, SubId, []} | Acc]; + #pubsub_subscription{options = Options} -> [{JID, SubId, Options} | Acc]; _ -> Acc end; (_, Acc) -> @@ -3224,8 +3226,8 @@ broadcast_stanza(Host, _Node, _NodeId, _Type, NodeOptions, SubsByDepth, NotifyTy MsgType -> add_message_type(BaseStanza, atom_to_list(MsgType)) end, %% Handles explicit subscriptions - SubIDsByJID = subscribed_nodes_by_jid(NotifyType, SubsByDepth), - lists:foreach(fun ({LJID, NodeName, SubIDs}) -> + SubIdsByJID = subscribed_nodes_by_jid(NotifyType, SubsByDepth), + lists:foreach(fun ({LJID, NodeName, SubIds}) -> LJIDs = case BroadcastAll of true -> {U, S, _} = LJID, @@ -3233,19 +3235,19 @@ broadcast_stanza(Host, _Node, _NodeId, _Type, NodeOptions, SubsByDepth, NotifyTy false -> [LJID] end, - %% Determine if the stanza should have SHIM ('SubID' and 'name') headers - StanzaToSend = case {SHIM, SubIDs} of + %% Determine if the stanza should have SHIM ('SubId' and 'name') headers + StanzaToSend = case {SHIM, SubIds} of {false, _} -> Stanza; {true, [_]} -> add_shim_headers(Stanza, collection_shim(NodeName)); - {true, SubIDs} -> - add_shim_headers(Stanza, lists:append(collection_shim(NodeName), subid_shim(SubIDs))) + {true, SubIds} -> + add_shim_headers(Stanza, lists:append(collection_shim(NodeName), subid_shim(SubIds))) end, lists:foreach(fun(To) -> ejabberd_router:route(From, exmpp_jid:make(To), StanzaToSend) end, LJIDs) - end, SubIDsByJID). + end, SubIdsByJID). broadcast_stanza({LUser, LServer, LResource}, Publisher, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM) -> broadcast_stanza({LUser, LServer, LResource}, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM), @@ -3296,12 +3298,12 @@ broadcast_stanza(Host, _Publisher, Node, NodeId, Type, NodeOptions, SubsByDepth, subscribed_nodes_by_jid(NotifyType, SubsByDepth) -> NodesToDeliver = fun(Depth, Node, Subs, Acc) -> - NodeName = case Node#pubsub_node.nodeid of + NodeName = case Node#pubsub_node.id of {_, N} -> N; Other -> Other end, NodeOptions = Node#pubsub_node.options, - lists:foldl(fun({LJID, SubID, SubOptions}, {JIDs, Recipients}) -> + lists:foldl(fun({LJID, SubId, SubOptions}, {JIDs, Recipients}) -> case is_to_deliver(LJID, NotifyType, Depth, NodeOptions, SubOptions) of true -> %% If is to deliver : @@ -3311,26 +3313,26 @@ subscribed_nodes_by_jid(NotifyType, SubsByDepth) -> lists:foldl( fun(JIDToDeliver, {JIDsAcc, RecipientsAcc}) -> case lists:member(JIDToDeliver, JIDs) of - %% check if the JIDs co-accumulator contains the Subscription Jid, + %% check if the JIDs co-accumulator contains the Subscription JID, false -> %% - if not, - %% - add the Jid to JIDs list co-accumulator ; - %% - create a tuple of the Jid, NodeId, and SubID (as list), + %% - add the JID to JIDs list co-accumulator ; + %% - create a tuple of the JID, NodeId, and SubId (as list), %% and add the tuple to the Recipients list co-accumulator - {[JIDToDeliver | JIDsAcc], [{JIDToDeliver, NodeName, [SubID]} | RecipientsAcc]}; + {[JIDToDeliver | JIDsAcc], [{JIDToDeliver, NodeName, [SubId]} | RecipientsAcc]}; true -> - %% - if the JIDs co-accumulator contains the Jid - %% get the tuple containing the Jid from the Recipient list co-accumulator - {_, {JIDToDeliver, NodeName1, SubIDs}} = lists:keysearch(JIDToDeliver, 1, RecipientsAcc), + %% - if the JIDs co-accumulator contains the JID + %% get the tuple containing the JID from the Recipient list co-accumulator + {_, {JIDToDeliver, NodeName1, SubIds}} = lists:keysearch(JIDToDeliver, 1, RecipientsAcc), %% delete the tuple from the Recipients list % v1 : Recipients1 = lists:keydelete(LJID, 1, Recipients), - % v2 : Recipients1 = lists:keyreplace(LJID, 1, Recipients, {LJID, NodeId1, [SubID | SubIDs]}), - %% add the SubID to the SubIDs list in the tuple, + % v2 : Recipients1 = lists:keyreplace(LJID, 1, Recipients, {LJID, NodeId1, [SubId | SubIds]}), + %% add the SubId to the SubIds list in the tuple, %% and add the tuple back to the Recipients list co-accumulator - % v1.1 : {JIDs, lists:append(Recipients1, [{LJID, NodeId1, lists:append(SubIDs, [SubID])}])} - % v1.2 : {JIDs, [{LJID, NodeId1, [SubID | SubIDs]} | Recipients1]} + % v1.1 : {JIDs, lists:append(Recipients1, [{LJID, NodeId1, lists:append(SubIds, [SubId])}])} + % v1.2 : {JIDs, [{LJID, NodeId1, [SubId | SubIds]} | Recipients1]} % v2: {JIDs, Recipients1} - {JIDsAcc, lists:keyreplace(JIDToDeliver, 1, RecipientsAcc, {JIDToDeliver, NodeName1, [SubID | SubIDs]})} + {JIDsAcc, lists:keyreplace(JIDToDeliver, 1, RecipientsAcc, {JIDToDeliver, NodeName1, [SubId | SubIds]})} end end, {JIDs, Recipients}, JIDsToDeliver) end; @@ -3360,8 +3362,8 @@ user_resources(User, Server) -> get_configure(Host, ServerHost, Node, From, Lang) -> ServerHostB = list_to_binary(ServerHost), Action = - fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> - case node_call(Type, get_affiliation, [NodeId, From]) of + fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> + case node_call(Type, get_affiliation, [Nidx, From]) of {result, owner} -> Groups = ejabberd_hooks:run_fold(roster_groups, ServerHostB, [], [ServerHostB]), {result, @@ -3518,8 +3520,8 @@ set_configure(Host, Node, From, Els, Lang) -> {result, []}; "submit" -> Action = - fun(#pubsub_node{options = Options, type = Type, id = NodeId} = N) -> - case node_call(Type, get_affiliation, [NodeId, From]) of + fun(#pubsub_node{options = Options, type = Type, idx = Nidx} = N) -> + case node_call(Type, get_affiliation, [Nidx, From]) of {result, owner} -> case jlib:parse_xdata_submit(XEl) of invalid -> @@ -3545,10 +3547,10 @@ set_configure(Host, Node, From, Els, Lang) -> end, case transaction(Host, Node, Action, transaction) of {result, {TNode, ok}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_config_notification(Host, Node, NodeId, Type, Options, Lang), + broadcast_config_notification(Host, Node, Nidx, Type, Options, Lang), {result, []}; Other -> Other @@ -3695,7 +3697,7 @@ get_cached_item(Host, NodeId) -> true -> case mnesia:dirty_read({pubsub_last_item, NodeId}) of [{pubsub_last_item, NodeId, ItemId, Creation, Payload}] -> - #pubsub_item{itemid = {ItemId, NodeId}, payload = Payload, + #pubsub_item{id = {ItemId, NodeId}, payload = Payload, creation = Creation, modification = Creation}; _ -> undefined @@ -3906,7 +3908,7 @@ itemAttr(ItemId) -> [?XMLATTR('id', ItemId)]. % build item elements from item list itemsEls(Items) -> - lists:map(fun(#pubsub_item{itemid = {ItemId, _}, payload = Payload}) -> + lists:map(fun(#pubsub_item{id = {ItemId, _}, payload = Payload}) -> #xmlel{ns = ?NS_PUBSUB, name = 'item', attrs = itemAttr(ItemId), children = Payload} end, Items). @@ -3946,17 +3948,17 @@ collection_shim(Node) -> attrs = [?XMLATTR('name', <<"Collection">>)], children = [?XMLCDATA(node_to_string(Node))]}]. -subid_shim(SubIDs) -> +subid_shim(SubIds) -> [#xmlel{ns = ?NS_PUBSUB, name ='header', - attrs = [?XMLATTR('name', <<"SubID">>)], - children = [?XMLCDATA(SubID)]} - || SubID <- SubIDs]. + attrs = [?XMLATTR('name', <<"SubId">>)], + children = [?XMLCDATA(SubId)]} + || SubId <- SubIds]. -extended_headers(Jids) -> +extended_headers(JIDs) -> [#xmlel{ns = ?NS_ADDRESS, name = 'address', - attrs = [?XMLATTR('type', <<"replyto">>), ?XMLATTR('jid', Jid)]} - || Jid <- Jids]. + attrs = [?XMLATTR('type', <<"replyto">>), ?XMLATTR('jid', JID)]} + || JID <- JIDs]. feature_check_packet(allow, _User, Server, Pres, {From, _To, El}, in) -> Host = list_to_binary(host(Server)), @@ -4012,10 +4014,10 @@ purge_offline({User, Server, _} = LJID) -> case Result of {ok, Affiliations} -> lists:foreach( - fun({#pubsub_node{nodeid = {_, NodeId}, options = Options, type = Type}, Affiliation}) + fun({#pubsub_node{id = {_, NodeId}, options = Options, type = Type}, Affiliation}) when Affiliation == 'owner' orelse Affiliation == 'publisher' -> - Action = fun(#pubsub_node{type = NType, id = NodeIdx}) -> - node_call(NType, get_items, [NodeIdx, service_jid(Host)]) + Action = fun(#pubsub_node{type = NType, idx = Nidx}) -> + node_call(NType, get_items, [Nidx, service_jid(Host)]) end, case transaction(Host, NodeId, Action, sync_dirty) of {result, {_, []}} -> @@ -4031,7 +4033,7 @@ purge_offline({User, Server, _} = LJID) -> {true, true, true, true} -> ForceNotify = get_option(Options, notify_retract), lists:foreach( - fun(#pubsub_item{itemid = {ItemId, _}, modification = {_, Modification}}) -> + fun(#pubsub_item{id = {ItemId, _}, modification = {_, Modification}}) -> case Modification of {User, Server, _} -> delete_item(Host, NodeId, LJID, ItemId, ForceNotify); diff --git a/src/mod_pubsub/mod_pubsub_odbc.erl b/src/mod_pubsub/mod_pubsub_odbc.erl index e49971c03..f8b72155f 100644 --- a/src/mod_pubsub/mod_pubsub_odbc.erl +++ b/src/mod_pubsub/mod_pubsub_odbc.erl @@ -49,8 +49,6 @@ -behaviour(gen_server). -behaviour(gen_mod). --include_lib("exmpp/include/exmpp.hrl"). - -include("ejabberd.hrl"). -include("adhoc.hrl"). -include("pubsub.hrl"). @@ -281,13 +279,11 @@ init_nodes(Host, ServerHost, _NodeTree, Plugins) -> case lists:member("hometree_odbc", Plugins) of true -> create_node(Host, ServerHost, string_to_node("/home"), service_jid(Host), "hometree_odbc"), - create_node(Host, ServerHost, string_to_node("/home/" ++ ServerHost), service_jid(Host), "hometree_odbc"); + create_node(Host, ServerHost, string_to_node("/home/" ++ ServerHost), service_jid(Host), "hometree_odbc"); false -> ok end. - - send_loop(State) -> receive {presence, JID, Pid} -> @@ -305,10 +301,10 @@ send_loop(State) -> lists:foreach( fun({Node, subscribed, _, SubJID}) -> if (SubJID == LJID) or (SubJID == BJID) -> - #pubsub_node{nodeid = {H, N}, type = Type, id = NodeId, options = Options} = Node, + #pubsub_node{id = {H, N}, type = Type, idx = Nidx, options = Options} = Node, case get_option(Options, send_last_published_item) of on_sub_and_presence -> - send_items(H, N, NodeId, Type, LJID, last); + send_items(H, N, Nidx, Type, LJID, last); _ -> ok end; @@ -358,7 +354,7 @@ send_loop(State) -> spawn(fun() -> Host = State#state.host, Owner = jlib:short_prepd_bare_jid(JID), - lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, type = Type, id = NodeId, options = Options}) -> + lists:foreach(fun(#pubsub_node{id = {_, Node}, type = Type, idx = Nidx, options = Options}) -> case get_option(Options, send_last_published_item) of on_sub_and_presence -> lists:foreach(fun(Resource) -> @@ -373,7 +369,7 @@ send_loop(State) -> {OU, OS, _} = Owner, element(2, get_roster_info(OU, OS, LJID, Grps)) end, - if Subscribed -> send_items(Owner, Node, NodeId, Type, LJID, last); + if Subscribed -> send_items(Owner, Node, Nidx, Type, LJID, last); true -> ok end end, Resources); @@ -426,9 +422,9 @@ disco_identity(_Host, <<>>, _From) -> [#xmlel{name = 'identity', ns = ?NS_DISCO_INFO, attrs = [?XMLATTR('category', <<"pubsub">>), ?XMLATTR('type', <<"pep">>)]}]; disco_identity(Host, Node, From) -> - Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> - Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) -> + Owners = node_owners_call(Type, Nidx), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, _} -> {result, [#xmlel{name = 'identity', ns = ?NS_DISCO_INFO, @@ -458,9 +454,9 @@ disco_features(_Host, <<>>, _From) -> [?NS_PUBSUB_s | [?NS_PUBSUB_s++"#"++Feature || Feature <- features("pep")]]; disco_features(Host, Node, From) -> - Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> - Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) -> + Owners = node_owners_call(Type, Nidx), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, _} -> {result, [?NS_PUBSUB_s | [?NS_PUBSUB_s ++ "#" ++ Feature || Feature <- features("pep")]]}; @@ -478,13 +474,13 @@ disco_sm_items({result, OtherItems}, From, To, Node, _Lang) -> {result, disco_items(To, Node, From) ++ OtherItems}. disco_items(Host, <<>>, From) -> - Action = fun(#pubsub_node{nodeid ={_, NodeID}, options = Options, type = Type, id = Idx}, Acc) -> - Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of + Action = fun(#pubsub_node{id ={_, NodeId}, options = Options, type = Type, idx = Nidx}, Acc) -> + Owners = node_owners_call(Type, Nidx), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, _} -> [#xmlel{name = 'item', ns = ?NS_DISCO_INFO, attrs = [?XMLATTR('jid', exmpp_jid:to_binary(Host)), - ?XMLATTR('node', NodeID) | + ?XMLATTR('node', NodeId) | case get_option(Options, title) of false -> []; [Title] -> [?XMLATTR('title', Title)] @@ -499,15 +495,15 @@ disco_items(Host, <<>>, From) -> end; disco_items(Host, Node, From) -> - Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> - Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) -> + Owners = node_owners_call(Type, Nidx), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, Items} -> {result, [#xmlel{name = 'item', ns = ?NS_DISCO_INFO, attrs = [?XMLATTR('jid', exmpp_jid:to_binary(Host)), - ?XMLATTR('name', ItemID)]} - || #pubsub_item{itemid = {ItemID,_}} <- Items]}; + ?XMLATTR('name', ItemId)]} + || #pubsub_item{id = {ItemId,_}} <- Items]}; _ -> {result, []} end end, @@ -537,6 +533,7 @@ presence_probe(Peer, JID, Pid) -> presence(Host, {presence, User, Server, [Resource], JID}) end end. + presence(ServerHost, Presence) when is_binary(ServerHost) -> presence(binary_to_list(ServerHost), Presence); presence(ServerHost, Presence) -> @@ -585,12 +582,12 @@ unsubscribe_user(Entity, Owner) -> lists:foreach(fun(PType) -> {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Entity]), lists:foreach(fun - ({#pubsub_node{options = Options, id = NodeId}, subscribed, _, JID}) -> + ({#pubsub_node{options = Options, idx = Nidx}, subscribed, _, JID}) -> case get_option(Options, access_model) of presence -> - case lists:member(BJID, node_owners(Host, PType, NodeId)) of + case lists:member(BJID, node_owners(Host, PType, Nidx)) of true -> - node_action(Host, PType, unsubscribe_node, [NodeId, Entity, JID, all]); + node_action(Host, PType, unsubscribe_node, [Nidx, Entity, JID, all]); false -> {result, ok} end; @@ -621,13 +618,13 @@ remove_user(UserB, ServerB) -> lists:foreach(fun(PType) -> {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Entity]), lists:foreach(fun - ({#pubsub_node{id = NodeId}, _, _, JID}) -> node_action(Host, PType, unsubscribe_node, [NodeId, Entity, JID, all]) + ({#pubsub_node{idx = Nidx}, _, _, JID}) -> node_action(Host, PType, unsubscribe_node, [Nidx, Entity, JID, all]) end, Subscriptions), {result, Affiliations} = node_action(Host, PType, get_entity_affiliations, [Host, Entity]), lists:foreach(fun - ({#pubsub_node{nodeid = {H, N}, parents = []}, owner}) -> delete_node(H, N, Entity); - ({#pubsub_node{nodeid = {H, N}, type = "hometree"}, owner}) when N == HomeTreeBase -> delete_node(H, N, Entity); - ({#pubsub_node{id = NodeId}, publisher}) -> node_action(Host, PType, set_affiliation, [NodeId, Entity, none]); + ({#pubsub_node{id = {H, N}, parents = []}, owner}) -> delete_node(H, N, Entity); + ({#pubsub_node{id = {H, N}, type = "hometree"}, owner}) when N == HomeTreeBase -> delete_node(H, N, Entity); + ({#pubsub_node{idx = Nidx}, publisher}) -> node_action(Host, PType, set_affiliation, [Nidx, Entity, none]); (_) -> ok end, Affiliations) end, plugins(Host)) @@ -894,7 +891,7 @@ node_disco_info(Host, Node, From) -> node_disco_info(Host, Node, From, true, true). node_disco_info(Host, Node, From, Identity, Features) -> Action = - fun(#pubsub_node{type = Type, id = NodeId}) -> + fun(#pubsub_node{type = Type, idx = Nidx}) -> I = case Identity of false -> []; @@ -904,7 +901,7 @@ node_disco_info(Host, Node, From, Identity, Features) -> [] -> ["leaf"]; %% No sub-nodes: it's a leaf node _ -> - case node_call(Type, get_items, [NodeId, From, none]) of + case node_call(Type, get_items, [Nidx, From, none]) of {result, []} -> ["collection"]; {result, _} -> ["leaf", "collection"]; _ -> [] @@ -967,7 +964,7 @@ iq_disco_items(Host, [], From, _RSM) -> case tree_action(Host, get_subnodes, [Host, <<>>, From]) of Nodes when is_list(Nodes) -> {result, lists:map( - fun(#pubsub_node{nodeid = {_, SubNode}, options = Options}) -> + fun(#pubsub_node{id = {_, SubNode}, options = Options}) -> Attrs = case get_option(Options, title) of false -> @@ -994,18 +991,18 @@ iq_disco_items(_Host, ?NS_PUBSUB_GET_PENDING, _From, _RSM) -> {result, CommandItems}; iq_disco_items(Host, Item, From, RSM) -> case string:tokens(Item, "!") of - [_SNode, _ItemID] -> + [_SNode, _ItemId] -> {result, []}; [SNode] -> Node = string_to_node(SNode), - Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> - Owners = node_owners_call(Type, Idx), - {NodeItems, RsmOut} = case get_allowed_items_call(Host, Idx, From, Type, Options, Owners, RSM) of + Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) -> + Owners = node_owners_call(Type, Nidx), + {NodeItems, RsmOut} = case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners, RSM) of {result, R} -> R; _ -> {[], none} end, Nodes = lists:map( - fun(#pubsub_node{nodeid = {_, SubNode}, options = SubOptions}) -> + fun(#pubsub_node{id = {_, SubNode}, options = SubOptions}) -> Attrs = case get_option(SubOptions, title) of false -> @@ -1016,7 +1013,7 @@ iq_disco_items(Host, Item, From, RSM) -> #xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = Attrs} end, tree_call(Host, get_subnodes, [Host, Node, From])), Items = lists:map( - fun(#pubsub_item{itemid = {RN, _}}) -> + fun(#pubsub_item{id = {RN, _}}) -> {result, Name} = node_call(Type, get_item_name, [Host, Node, RN]), #xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host), ?XMLATTR('name', Name)]} end, NodeItems), @@ -1136,29 +1133,28 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) -> {get, 'items'} -> MaxItems = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'max_items', ""), SubId = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'subid', ""), - ItemIDs = lists:foldl(fun + ItemIds = lists:foldl(fun (#xmlel{name = 'item', attrs = ItemAttrs}, Acc) -> case exmpp_xml:get_attribute_from_list_as_list(ItemAttrs, 'id', "") of "" -> Acc; - ItemID -> [ItemID|Acc] + ItemId -> [ItemId|Acc] end; (_, Acc) -> Acc end, [], exmpp_xml:remove_cdata_from_list(Els)), - RSM = jlib:rsm_decode(SubEl), - get_items(Host, Node, From, SubId, MaxItems, ItemIDs, RSM); + get_items(Host, Node, From, SubId, MaxItems, ItemIds, jlib:rsm_decode(SubEl)); {get, 'subscriptions'} -> get_subscriptions(Host, Node, From, Plugins); {get, 'affiliations'} -> get_affiliations(Host, From, Plugins); {get, 'options'} -> - SubID = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'subid', ""), + SubId = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'subid', ""), JID = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'jid', ""), - get_options(Host, Node, JID, SubID, Lang); + get_options(Host, Node, JID, SubId, Lang); {set, 'options'} -> - SubID = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'subid', ""), + SubId = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'subid', ""), JID = exmpp_xml:get_attribute_from_list_as_list(Attrs, 'jid', ""), - set_options(Host, Node, JID, SubID, Els); + set_options(Host, Node, JID, SubId, Els); _ -> {error, 'feature-not-implemented'} end; @@ -1317,12 +1313,12 @@ send_pending_auth_events(Host, Node, Owner) -> ?DEBUG("Sending pending auth events for ~s on ~s:~s", [exmpp_jid:to_list(Owner), Host, node_to_string(Node)]), Action = - fun(#pubsub_node{id = NodeID, type = Type}) -> + fun(#pubsub_node{idx = Nidx, type = Type}) -> case lists:member("get-pending", features(Type)) of true -> - case node_call(Type, get_affiliation, [NodeID, Owner]) of + case node_call(Type, get_affiliation, [Nidx, Owner]) of {result, owner} -> - node_call(Type, get_node_subscriptions, [NodeID]); + node_call(Type, get_node_subscriptions, [Nidx]); _ -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'forbidden')} end; @@ -1332,7 +1328,7 @@ send_pending_auth_events(Host, Node, Owner) -> end, case transaction(Host, Node, Action, sync_dirty) of {result, {N, Subscriptions}} -> - lists:foreach(fun({J, pending, _SubID}) -> + lists:foreach(fun({J, pending, _SubId}) -> {U, S, R} = J, send_authorization_request(N, exmpp_jid:make(U,S,R)); ({J, pending}) -> @@ -1348,7 +1344,7 @@ send_pending_auth_events(Host, Node, Owner) -> %%% authorization handling -send_authorization_request(#pubsub_node{nodeid = {Host, Node}, type = Type, id = NodeId}, Subscriber) -> +send_authorization_request(#pubsub_node{id = {Host, Node}, type = Type, idx = Nidx}, Subscriber) -> Lang = <<"en">>, %% TODO fix {U, S, R} = Subscriber, Stanza = #xmlel{ns = ?NS_JABBER_CLIENT, name = 'message', children = @@ -1378,7 +1374,7 @@ send_authorization_request(#pubsub_node{nodeid = {Host, Node}, type = Type, id = lists:foreach(fun(Owner) -> {U, S, R} = Owner, ejabberd_router:route(service_jid(Host), exmpp_jid:make(U, S, R), Stanza) - end, node_owners(Host, Type, NodeId)). + end, node_owners(Host, Type, Nidx)). find_authorization_response(Packet) -> Els = Packet#xmlel.children, @@ -1437,14 +1433,14 @@ handle_authorization_response(Host, From, To, Packet, XFields) -> "true" -> true; _ -> false end, - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - IsApprover = lists:member(jlib:short_prepd_bare_jid(From), node_owners_call(Type, NodeId)), - {result, Subscriptions} = node_call(Type, get_subscriptions, [NodeId, Subscriber]), + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> + IsApprover = lists:member(jlib:short_prepd_bare_jid(From), node_owners_call(Type, Nidx)), + {result, Subscriptions} = node_call(Type, get_subscriptions, [Nidx, Subscriber]), if not IsApprover -> {error, 'forbidden'}; true -> - update_auth(Host, SNode, Type, NodeId, + update_auth(Host, SNode, Type, Nidx, Subscriber, Allow, Subscriptions) end @@ -1464,19 +1460,19 @@ handle_authorization_response(Host, From, To, Packet, XFields) -> exmpp_stanza:reply_with_error(Packet, 'not-acceptable')) end. -update_auth(Host, Node, Type, NodeId, Subscriber, +update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subscriptions) -> Subscription = lists:filter(fun({pending, _}) -> true; (_) -> false end, Subscriptions), case Subscription of - [{pending, SubID}] -> %% TODO does not work if several pending + [{pending, SubId}] -> %% TODO does not work if several pending NewSubscription = case Allow of true -> subscribed; false -> none end, node_call(Type, set_subscriptions, - [NodeId, Subscriber, NewSubscription, SubID]), + [Nidx, Subscriber, NewSubscription, SubId]), send_authorization_approval(Host, Subscriber, Node, NewSubscription), {result, ok}; @@ -1548,8 +1544,8 @@ update_auth(Host, Node, Type, NodeId, Subscriber, %%<li>The service does not support node creation.</li> %%<li>Only entities that are registered with the service are allowed to create nodes but the requesting entity is not registered.</li> %%<li>The requesting entity does not have sufficient privileges to create nodes.</li> -%%<li>The requested NodeID already exists.</li> -%%<li>The request did not include a NodeID and "instant nodes" are not supported.</li> +%%<li>The requested NodeId already exists.</li> +%%<li>The request did not include a NodeId and "instant nodes" are not supported.</li> %%</ul> %%<p>ote: node creation is a particular case, error return code is evaluated at many places:</p> %%<ul> @@ -1675,8 +1671,8 @@ delete_node(_Host, <<>>, _Owner) -> %% Node is the root {error, 'not-allowed'}; delete_node(Host, Node, Owner) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - case node_call(Type, get_affiliation, [NodeId, Owner]) of + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> + case node_call(Type, get_affiliation, [Nidx, Owner]) of {result, owner} -> ParentTree = tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]), SubsByDepth = [{Depth, [{N, get_node_subs(N)} || N <- Nodes]} || {Depth, Nodes} <- ParentTree], @@ -1694,12 +1690,12 @@ delete_node(Host, Node, Owner) -> case transaction(Host, Node, Action, transaction) of {result, {_, {SubsByDepth, {Result, broadcast, Removed}}}} -> lists:foreach(fun({RNode, _RSubscriptions}) -> - {RH, RN} = RNode#pubsub_node.nodeid, - NodeId = RNode#pubsub_node.id, + {RH, RN} = RNode#pubsub_node.id, + Nidx = RNode#pubsub_node.idx, Type = RNode#pubsub_node.type, Options = RNode#pubsub_node.options, - broadcast_removed_node(RH, RN, NodeId, Type, Options, SubsByDepth), - unset_cached_item(RH, NodeId) + broadcast_removed_node(RH, RN, Nidx, Type, Options, SubsByDepth), + unset_cached_item(RH, Nidx) end, Removed), case Result of default -> {result, Reply}; @@ -1751,7 +1747,7 @@ subscribe_node(Host, Node, From, JID, Configuration) -> _:_ -> {undefined, undefined, undefined} end, - Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> Features = features(Type), SubscribeFeature = lists:member("subscribe", Features), OptionsFeature = lists:member("subscription-options", Features), @@ -1760,7 +1756,7 @@ subscribe_node(Host, Node, From, JID, Configuration) -> AccessModel = get_option(Options, access_model), SendLast = get_option(Options, send_last_published_item), AllowedGroups = get_option(Options, roster_groups_allowed, []), - Owners = node_owners_call(Type, NodeId), + Owners = node_owners_call(Type, Nidx), {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, Subscriber, Owners, AccessModel, AllowedGroups), if not SubscribeFeature -> @@ -1777,7 +1773,7 @@ subscribe_node(Host, Node, From, JID, Configuration) -> {error, extended_error('bad-request', "invalid-options")}; true -> node_call(Type, subscribe_node, - [NodeId, From, Subscriber, + [Nidx, From, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, SubOpts]) @@ -1799,9 +1795,9 @@ subscribe_node(Host, Node, From, JID, Configuration) -> end, case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, subscribed, SubId, send_last}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, - send_items(Host, Node, NodeId, Type, Subscriber, last), + send_items(Host, Node, Nidx, Type, Subscriber, last), notify_owners(get_option(TNode#pubsub_node.options, notify_sub), Subscriber, Host, Node, TNode#pubsub_node.owners, "subscribed"), case Result of default -> {result, Reply({subscribed, SubId})}; @@ -1852,8 +1848,8 @@ unsubscribe_node(Host, Node, From, JID, SubId) when is_list(JID) -> end, unsubscribe_node(Host, Node, From, Subscriber, SubId); unsubscribe_node(Host, Node, From, Subscriber, SubId) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, unsubscribe_node, [NodeId, From, Subscriber, SubId]) + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> + node_call(Type, unsubscribe_node, [Nidx, From, Subscriber, SubId]) end, case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, default}} -> @@ -1884,7 +1880,7 @@ publish_item(Host, ServerHost, Node, Publisher, "", Payload) -> %% if publisher does not specify an ItemId, the service MUST generate the ItemId publish_item(Host, ServerHost, Node, Publisher, uniqid(), Payload); publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> - Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> Features = features(Type), PublishFeature = lists:member("publish", Features), PublishModel = get_option(Options, publish_model), @@ -1922,7 +1918,7 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> %% Publisher attempts to publish to persistent node with no item {error, extended_error('bad-request', "item-required")}; true -> - node_call(Type, publish_item, [NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload]) + node_call(Type, publish_item, [Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload]) end end, ServerHostB = list_to_binary(ServerHost), @@ -1932,7 +1928,7 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> [#xmlel{ns = ?NS_PUBSUB, name = 'item', attrs = itemAttr(ItemId)}]}]}, case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, Broadcast, Removed}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, BroadcastPayload = case Broadcast of @@ -1940,25 +1936,25 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> broadcast -> Payload; PluginPayload -> PluginPayload end, - broadcast_publish_item(Host, Node, NodeId, Type, Options, Removed, ItemId, jlib:short_prepd_jid(Publisher), BroadcastPayload), - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), + broadcast_publish_item(Host, Node, Nidx, Type, Options, Removed, ItemId, jlib:short_prepd_jid(Publisher), BroadcastPayload), + set_cached_item(Host, Nidx, ItemId, Publisher, Payload), case Result of default -> {result, Reply}; _ -> {result, Result} end; {result, {TNode, {default, Removed}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, Options, Removed), - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), + broadcast_retract_items(Host, Node, Nidx, Type, Options, Removed), + set_cached_item(Host, Nidx, ItemId, Publisher, Payload), {result, Reply}; {result, {TNode, {Result, Removed}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, Options, Removed), - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), + broadcast_retract_items(Host, Node, Nidx, Type, Options, Removed), + set_cached_item(Host, Nidx, ItemId, Publisher, Payload), {result, Result}; {result, {_, default}} -> {result, Reply}; @@ -2004,7 +2000,7 @@ delete_item(_, "", _, _, _) -> %% Request does not specify a node {error, extended_error('bad-request', "node-required")}; delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> - Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> Features = features(Type), PersistentFeature = lists:member("persistent-items", Features), DeleteFeature = lists:member("delete-items", Features), @@ -2020,18 +2016,18 @@ delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> %% Service does not support item deletion {error, extended_error('feature-not-implemented', unsupported, "delete-items")}; true -> - node_call(Type, delete_item, [NodeId, Publisher, PublishModel, ItemId]) + node_call(Type, delete_item, [Nidx, Publisher, PublishModel, ItemId]) end end, Reply = [], case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, broadcast}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, Options, [ItemId], ForceNotify), - case get_cached_item(Host, NodeId) of - #pubsub_item{itemid = {ItemId, NodeId}, _ = '_'} -> unset_cached_item(Host, NodeId); + broadcast_retract_items(Host, Node, Nidx, Type, Options, [ItemId], ForceNotify), + case get_cached_item(Host, Nidx) of + #pubsub_item{id = {ItemId, Nidx}} -> unset_cached_item(Host, Nidx); _ -> ok end, case Result of @@ -2061,7 +2057,7 @@ delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> %%<li>The specified node does not exist.</li> %%</ul> purge_node(Host, Node, Owner) -> - Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> Features = features(Type), PurgeFeature = lists:member("purge-nodes", Features), PersistentFeature = lists:member("persistent-items", Features), @@ -2077,17 +2073,17 @@ purge_node(Host, Node, Owner) -> %% Node is not configured for persistent items {error, extended_error('feature-not-implemented', unsupported, "persistent-items")}; true -> - node_call(Type, purge_node, [NodeId, Owner]) + node_call(Type, purge_node, [Nidx, Owner]) end end, Reply = [], case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, broadcast}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_purge_node(Host, Node, NodeId, Type, Options), - unset_cached_item(Host, NodeId), + broadcast_purge_node(Host, Node, Nidx, Type, Options), + unset_cached_item(Host, Nidx), case Result of default -> {result, Reply}; _ -> {result, Result} @@ -2105,7 +2101,7 @@ purge_node(Host, Node, Owner) -> %% <p>The permission are not checked in this function.</p> %% @todo We probably need to check that the user doing the query has the right %% to read the items. -get_items(Host, Node, From, SubId, SMaxItems, ItemIDs, RSM) -> +get_items(Host, Node, From, SubId, SMaxItems, ItemIds, RSM) -> MaxItems = if SMaxItems == "" -> get_max_items_node(Host); @@ -2119,13 +2115,13 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIDs, RSM) -> {error, Error} -> {error, Error}; _ -> - Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> Features = features(Type), RetreiveFeature = lists:member("retrieve-items", Features), PersistentFeature = lists:member("persistent-items", Features), AccessModel = get_option(Options, access_model), AllowedGroups = get_option(Options, roster_groups_allowed, []), - Owners = node_owners_call(Type, NodeId), + Owners = node_owners_call(Type, Nidx), {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups), if not RetreiveFeature -> @@ -2136,19 +2132,19 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIDs, RSM) -> {error, extended_error('feature-not-implemented', unsupported, "persistent-items")}; true -> node_call(Type, get_items, - [NodeId, From, + [Nidx, From, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM]) end end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Items, RSMOut}} -> - SendItems = case ItemIDs of + SendItems = case ItemIds of [] -> Items; _ -> - lists:filter(fun(#pubsub_item{itemid = {ItemId, _}}) -> - lists:member(ItemId, ItemIDs) + lists:filter(fun(#pubsub_item{id = {ItemId, _}}) -> + lists:member(ItemId, ItemIds) end, Items) end, %% Generate the XML response (Item list), limiting the @@ -2160,17 +2156,19 @@ get_items(Host, Node, From, SubId, SMaxItems, ItemIDs, RSM) -> Error end end. + get_items(Host, Node) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, get_items, [NodeId, service_jid(Host)]) + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> + node_call(Type, get_items, [Nidx, service_jid(Host)]) end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Items}} -> Items; Error -> Error end. + get_item(Host, Node, ItemId) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, get_item, [NodeId, ItemId]) + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> + node_call(Type, get_item, [Nidx, ItemId]) end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Items}} -> Items; @@ -2271,7 +2269,7 @@ get_affiliations(Host, JID, Plugins) when is_list(Plugins) -> {ok, Affiliations} -> Entities = lists:flatmap( fun({_, none}) -> []; - ({#pubsub_node{nodeid = {_, Node}}, Affiliation}) -> + ({#pubsub_node{id = {_, Node}}, Affiliation}) -> [#xmlel{ns = ?NS_PUBSUB, name = 'affiliation', attrs = [?XMLATTR('node', node_to_string(Node)), ?XMLATTR('affiliation', affiliation_to_string(Affiliation))]}] @@ -2283,10 +2281,10 @@ get_affiliations(Host, JID, Plugins) when is_list(Plugins) -> Error end; get_affiliations(Host, Node, JID) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> Features = features(Type), RetrieveFeature = lists:member("modify-affiliations", Features), - {result, Affiliation} = node_call(Type, get_affiliation, [NodeId, JID]), + {result, Affiliation} = node_call(Type, get_affiliation, [Nidx, JID]), if not RetrieveFeature -> %% Service does not support modify affiliations @@ -2295,7 +2293,7 @@ get_affiliations(Host, Node, JID) -> %% Entity is not an owner {error, 'forbidden'}; true -> - node_call(Type, get_node_affiliations, [NodeId]) + node_call(Type, get_node_affiliations, [Nidx]) end end, case transaction(Host, Node, Action, sync_dirty) of @@ -2347,8 +2345,8 @@ set_affiliations(Host, Node, From, EntitiesEls) -> error -> {error, 'bad-request'}; _ -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - Owners = node_owners_call(Type, NodeId), + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> + Owners = node_owners_call(Type, Nidx), case lists:member(Owner, Owners) of true -> OwnerJID = exmpp_jid:make(Owner), @@ -2359,7 +2357,7 @@ set_affiliations(Host, Node, From, EntitiesEls) -> lists:foreach( fun({JID, Affiliation}) -> % TODO, check if nothing missing here about new owners - node_call(Type, set_affiliation, [NodeId, JID, Affiliation]) + node_call(Type, set_affiliation, [Nidx, JID, Affiliation]) end, FilteredEntities), {result, []}; _ -> @@ -2372,11 +2370,11 @@ set_affiliations(Host, Node, From, EntitiesEls) -> end end. -get_options(Host, Node, JID, SubID, Lang) -> - Action = fun(#pubsub_node{type = Type, id = NodeID}) -> +get_options(Host, Node, JID, SubId, Lang) -> + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> case lists:member("subscription-options", features(Type)) of true -> - get_options_helper(JID, Lang, Node, NodeID, SubID, Type); + get_options_helper(JID, Lang, Node, Nidx, SubId, Type); false -> {error, extended_error( 'feature-not-implemented', @@ -2388,7 +2386,7 @@ get_options(Host, Node, JID, SubID, Lang) -> Error -> Error end. -get_options_helper(JID, Lang, Node, NodeID, SubID, Type) -> +get_options_helper(JID, Lang, Node, NodeId, SubId, Type) -> Subscriber = try exmpp_jid:parse(JID) of J -> jlib:short_jid(J) catch @@ -2396,43 +2394,43 @@ get_options_helper(JID, Lang, Node, NodeID, SubID, Type) -> exmpp_jid:make("", "", "") %% TODO, check if use <<>> instead of "" end, {result, Subs} = node_call(Type, get_subscriptions, - [NodeID, Subscriber]), - SubIDs = lists:foldl(fun({subscribed, SID}, Acc) -> + [NodeId, Subscriber]), + SubIds = lists:foldl(fun({subscribed, SID}, Acc) -> [SID | Acc]; (_, Acc) -> Acc end, [], Subs), - case {SubID, SubIDs} of + case {SubId, SubIds} of {_, []} -> {error, extended_error('not-acceptable', "not-subscribed")}; {[], [SID]} -> - read_sub(Subscriber, Node, NodeID, SID, Lang); + read_sub(Subscriber, Node, NodeId, SID, Lang); {[], _} -> {error, extended_error('not-acceptable', "subid-required")}; {_, _} -> - read_sub(Subscriber, Node, NodeID, SubID, Lang) + read_sub(Subscriber, Node, NodeId, SubId, Lang) end. -read_sub(Subscriber, Node, NodeID, SubID, Lang) -> - case pubsub_subscription_odbc:get_subscription(Subscriber, NodeID, SubID) of +read_sub(Subscriber, Node, NodeId, SubId, Lang) -> + case pubsub_subscription_odbc:get_subscription(Subscriber, NodeId, SubId) of {error, notfound} -> {error, extended_error('not-acceptable', "invalid-subid")}; {result, #pubsub_subscription{options = Options}} -> {result, XdataEl} = pubsub_subscription_odbc:get_options_xform(Lang, Options), OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options', attrs = [ ?XMLATTR('jid', exmpp_jid:to_binary(Subscriber)), - ?XMLATTR('subid', SubID) | nodeAttr(Node)], + ?XMLATTR('subid', SubId) | nodeAttr(Node)], children = [XdataEl]}, PubsubEl = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [OptionsEl]}, {result, PubsubEl} end. -set_options(Host, Node, JID, SubID, Configuration) -> - Action = fun(#pubsub_node{type = Type, id = NodeID}) -> +set_options(Host, Node, JID, SubId, Configuration) -> + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> case lists:member("subscription-options", features(Type)) of true -> - set_options_helper(Configuration, JID, NodeID, - SubID, Type); + set_options_helper(Configuration, JID, Nidx, + SubId, Type); false -> {error, extended_error( 'feature-not-implemented', @@ -2444,7 +2442,7 @@ set_options(Host, Node, JID, SubID, Configuration) -> Error -> Error end. -set_options_helper(Configuration, JID, NodeID, SubID, Type) -> +set_options_helper(Configuration, JID, NodeId, SubId, Type) -> SubOpts = case pubsub_subscription_odbc:parse_options_xform(Configuration) of {result, GoodSubOpts} -> GoodSubOpts; _ -> invalid @@ -2455,27 +2453,27 @@ set_options_helper(Configuration, JID, NodeID, SubID, Type) -> _ -> exmpp_jid:make("", "", "") %% TODO, check if use <<>> instead of "" end, {result, Subs} = node_call(Type, get_subscriptions, - [NodeID, Subscriber]), - SubIDs = lists:foldl(fun({subscribed, SID}, Acc) -> + [NodeId, Subscriber]), + SubIds = lists:foldl(fun({subscribed, SID}, Acc) -> [SID | Acc]; (_, Acc) -> Acc end, [], Subs), - case {SubID, SubIDs} of + case {SubId, SubIds} of {_, []} -> {error, extended_error('not-acceptable', "not-subscribed")}; {[], [SID]} -> - write_sub(Subscriber, NodeID, SID, SubOpts); + write_sub(Subscriber, NodeId, SID, SubOpts); {[], _} -> {error, extended_error('not-acceptable', "subid-required")}; {_, _} -> - write_sub(Subscriber, NodeID, SubID, SubOpts) + write_sub(Subscriber, NodeId, SubId, SubOpts) end. -write_sub(_Subscriber, _NodeID, _SubID, invalid) -> +write_sub(_Subscriber, _NodeId, _SubId, invalid) -> {error, extended_error('bad-request', "invalid-options")}; -write_sub(Subscriber, NodeID, SubID, Options) -> - case pubsub_subscription_odbc:set_subscription(Subscriber, NodeID, SubID, Options) of +write_sub(Subscriber, NodeId, SubId, Options) -> + case pubsub_subscription_odbc:set_subscription(Subscriber, NodeId, SubId, Options) of {error, notfound} -> {error, extended_error('not-acceptable', "invalid-subid")}; {result, _} -> @@ -2510,7 +2508,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> Entities = lists:flatmap( fun({_, none}) -> []; - ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription}) -> + ({#pubsub_node{id = {_, SubsNode}}, Subscription}) -> case Node of <<>> -> [#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs = @@ -2524,22 +2522,22 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> end; ({_, none, _}) -> []; - ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubID, SubJID}) -> + ({#pubsub_node{id = {_, SubsNode}}, Subscription, SubId, SubJID}) -> case Node of <<>> -> [#xmlel{ns = ?NS_PUBSUB, name='subscription', attrs = [?XMLATTR('jid', exmpp_jid:to_binary(SubJID)), - ?XMLATTR('subid', SubID), + ?XMLATTR('subid', SubId), ?XMLATTR('subscription', subscription_to_string(Subscription)) | nodeAttr(SubsNode)]}]; SubsNode -> [#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs = [?XMLATTR('jid', exmpp_jid:to_binary(SubJID)), - ?XMLATTR('subid', SubID), + ?XMLATTR('subid', SubId), ?XMLATTR('subscription', subscription_to_string(Subscription))]}]; _ -> [] end; - ({#pubsub_node{nodeid = {_, SubsNode}}, Subscription, SubJID}) -> + ({#pubsub_node{id = {_, SubsNode}}, Subscription, SubJID}) -> case Node of <<>> -> [#xmlel{ns = ?NS_PUBSUB, name = 'subscription', attrs = @@ -2561,10 +2559,10 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> Error end. get_subscriptions(Host, Node, JID) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> Features = features(Type), RetrieveFeature = lists:member("manage-subscriptions", Features), - {result, Affiliation} = node_call(Type, get_affiliation, [NodeId, JID]), + {result, Affiliation} = node_call(Type, get_affiliation, [Nidx, JID]), if not RetrieveFeature -> %% Service does not support manage subscriptions @@ -2573,7 +2571,7 @@ get_subscriptions(Host, Node, JID) -> %% Entity is not an owner {error, 'forbidden'}; true -> - node_call(Type, get_node_subscriptions, [NodeId]) + node_call(Type, get_node_subscriptions, [Nidx]) end end, case transaction(Host, Node, Action, sync_dirty) of @@ -2649,12 +2647,12 @@ set_subscriptions(Host, Node, From, EntitiesEls) -> ?XMLATTR('subsription', subscription_to_string(Sub)) | nodeAttr(Node)]}]}]}, ejabberd_router:route(service_jid(Host), JID, Stanza) end, - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - case lists:member(Owner, node_owners_call(Type, NodeId)) of + Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> + case lists:member(Owner, node_owners_call(Type, Nidx)) of true -> Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) -> - case node_call(Type, set_subscriptions, [NodeId, JID, Subscription, SubId]) of + case node_call(Type, set_subscriptions, [Nidx, JID, Subscription, SubId]) of {error, Err} -> [{error, Err} | Acc]; _ -> Notify(JID, Subscription, SubId), Acc end @@ -3004,18 +3002,17 @@ get_collection_subscriptions(Host, Node) -> _ -> [] end. -get_node_subs(#pubsub_node{type = Type, - id = NodeID}) -> - case node_call(Type, get_node_subscriptions, [NodeID]) of - {result, Subs} -> get_options_for_subs(NodeID, Subs); +get_node_subs(#pubsub_node{type = Type, idx = Nidx}) -> + case node_call(Type, get_node_subscriptions, [Nidx]) of + {result, Subs} -> get_options_for_subs(Nidx, Subs); Other -> Other end. -get_options_for_subs(NodeID, Subs) -> - lists:foldl(fun({JID, subscribed, SubID}, Acc) -> - case pubsub_subscription_odbc:get_subscription(JID, NodeID, SubID) of - {error, notfound} -> [{JID, SubID, []} | Acc]; - {result, #pubsub_subscription{options = Options}} -> [{JID, SubID, Options} | Acc]; +get_options_for_subs(Nidx, Subs) -> + lists:foldl(fun({JID, subscribed, SubId}, Acc) -> + case pubsub_subscription_odbc:read_subscription(JID, Nidx, SubId) of + {error, notfound} -> [{JID, SubId, []} | Acc]; + #pubsub_subscription{options = Options} -> [{JID, SubId, Options} | Acc]; _ -> Acc end; (_, Acc) -> @@ -3049,8 +3046,8 @@ broadcast_stanza(Host, _Node, _NodeId, _Type, NodeOptions, SubsByDepth, NotifyTy MsgType -> add_message_type(BaseStanza, atom_to_list(MsgType)) end, %% Handles explicit subscriptions - SubIDsByJID = subscribed_nodes_by_jid(NotifyType, SubsByDepth), - lists:foreach(fun ({LJID, NodeName, SubIDs}) -> + SubIdsByJID = subscribed_nodes_by_jid(NotifyType, SubsByDepth), + lists:foreach(fun ({LJID, NodeName, SubIds}) -> LJIDs = case BroadcastAll of true -> {U, S, _} = LJID, @@ -3058,19 +3055,19 @@ broadcast_stanza(Host, _Node, _NodeId, _Type, NodeOptions, SubsByDepth, NotifyTy false -> [LJID] end, - %% Determine if the stanza should have SHIM ('SubID' and 'name') headers - StanzaToSend = case {SHIM, SubIDs} of + %% Determine if the stanza should have SHIM ('SubId' and 'name') headers + StanzaToSend = case {SHIM, SubIds} of {false, _} -> Stanza; {true, [_]} -> add_shim_headers(Stanza, collection_shim(NodeName)); - {true, SubIDs} -> - add_shim_headers(Stanza, lists:append(collection_shim(NodeName), subid_shim(SubIDs))) + {true, SubIds} -> + add_shim_headers(Stanza, lists:append(collection_shim(NodeName), subid_shim(SubIds))) end, lists:foreach(fun(To) -> ejabberd_router:route(From, exmpp_jid:make(To), StanzaToSend) end, LJIDs) - end, SubIDsByJID). + end, SubIdsByJID). broadcast_stanza({LUser, LServer, LResource}, Publisher, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM) -> broadcast_stanza({LUser, LServer, LResource}, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM), @@ -3121,12 +3118,12 @@ broadcast_stanza(Host, _Publisher, Node, NodeId, Type, NodeOptions, SubsByDepth, subscribed_nodes_by_jid(NotifyType, SubsByDepth) -> NodesToDeliver = fun(Depth, Node, Subs, Acc) -> - NodeName = case Node#pubsub_node.nodeid of + NodeName = case Node#pubsub_node.id of {_, N} -> N; Other -> Other end, NodeOptions = Node#pubsub_node.options, - lists:foldl(fun({LJID, SubID, SubOptions}, {JIDs, Recipients}) -> + lists:foldl(fun({LJID, SubId, SubOptions}, {JIDs, Recipients}) -> case is_to_deliver(LJID, NotifyType, Depth, NodeOptions, SubOptions) of true -> %% If is to deliver : @@ -3136,26 +3133,26 @@ subscribed_nodes_by_jid(NotifyType, SubsByDepth) -> lists:foldl( fun(JIDToDeliver, {JIDsAcc, RecipientsAcc}) -> case lists:member(JIDToDeliver, JIDs) of - %% check if the JIDs co-accumulator contains the Subscription Jid, + %% check if the JIDs co-accumulator contains the Subscription JID, false -> %% - if not, - %% - add the Jid to JIDs list co-accumulator ; - %% - create a tuple of the Jid, NodeId, and SubID (as list), + %% - add the JID to JIDs list co-accumulator ; + %% - create a tuple of the JID, NodeId, and SubId (as list), %% and add the tuple to the Recipients list co-accumulator - {[JIDToDeliver | JIDsAcc], [{JIDToDeliver, NodeName, [SubID]} | RecipientsAcc]}; + {[JIDToDeliver | JIDsAcc], [{JIDToDeliver, NodeName, [SubId]} | RecipientsAcc]}; true -> - %% - if the JIDs co-accumulator contains the Jid - %% get the tuple containing the Jid from the Recipient list co-accumulator - {_, {JIDToDeliver, NodeName1, SubIDs}} = lists:keysearch(JIDToDeliver, 1, RecipientsAcc), + %% - if the JIDs co-accumulator contains the JID + %% get the tuple containing the JID from the Recipient list co-accumulator + {_, {JIDToDeliver, NodeName1, SubIds}} = lists:keysearch(JIDToDeliver, 1, RecipientsAcc), %% delete the tuple from the Recipients list % v1 : Recipients1 = lists:keydelete(LJID, 1, Recipients), - % v2 : Recipients1 = lists:keyreplace(LJID, 1, Recipients, {LJID, NodeId1, [SubID | SubIDs]}), - %% add the SubID to the SubIDs list in the tuple, + % v2 : Recipients1 = lists:keyreplace(LJID, 1, Recipients, {LJID, NodeId1, [SubId | SubIds]}), + %% add the SubId to the SubIds list in the tuple, %% and add the tuple back to the Recipients list co-accumulator - % v1.1 : {JIDs, lists:append(Recipients1, [{LJID, NodeId1, lists:append(SubIDs, [SubID])}])} - % v1.2 : {JIDs, [{LJID, NodeId1, [SubID | SubIDs]} | Recipients1]} + % v1.1 : {JIDs, lists:append(Recipients1, [{LJID, NodeId1, lists:append(SubIds, [SubId])}])} + % v1.2 : {JIDs, [{LJID, NodeId1, [SubId | SubIds]} | Recipients1]} % v2: {JIDs, Recipients1} - {JIDsAcc, lists:keyreplace(JIDToDeliver, 1, RecipientsAcc, {JIDToDeliver, NodeName1, [SubID | SubIDs]})} + {JIDsAcc, lists:keyreplace(JIDToDeliver, 1, RecipientsAcc, {JIDToDeliver, NodeName1, [SubId | SubIds]})} end end, {JIDs, Recipients}, JIDsToDeliver) end; @@ -3185,8 +3182,8 @@ user_resources(User, Server) -> get_configure(Host, ServerHost, Node, From, Lang) -> ServerHostB = list_to_binary(ServerHost), Action = - fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> - case node_call(Type, get_affiliation, [NodeId, From]) of + fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> + case node_call(Type, get_affiliation, [Nidx, From]) of {result, owner} -> Groups = ejabberd_hooks:run_fold(roster_groups, ServerHostB, [], [ServerHostB]), {result, @@ -3367,8 +3364,8 @@ set_configure(Host, Node, From, Els, Lang) -> {result, []}; "submit" -> Action = - fun(#pubsub_node{options = Options, type = Type, id = NodeId} = N) -> - case node_call(Type, get_affiliation, [NodeId, From]) of + fun(#pubsub_node{options = Options, type = Type, idx = Nidx} = N) -> + case node_call(Type, get_affiliation, [Nidx, From]) of {result, owner} -> case jlib:parse_xdata_submit(XEl) of invalid -> @@ -3394,10 +3391,10 @@ set_configure(Host, Node, From, Els, Lang) -> end, case transaction(Host, Node, Action, transaction) of {result, {TNode, ok}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.idx, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_config_notification(Host, Node, NodeId, Type, Options, Lang), + broadcast_config_notification(Host, Node, Nidx, Type, Options, Lang), {result, []}; Other -> Other @@ -3544,7 +3541,7 @@ get_cached_item(Host, NodeId) -> true -> case mnesia:dirty_read({pubsub_last_item, NodeId}) of [{pubsub_last_item, NodeId, ItemId, Creation, Payload}] -> - #pubsub_item{itemid = {ItemId, NodeId}, payload = Payload, + #pubsub_item{id = {ItemId, NodeId}, payload = Payload, creation = Creation, modification = Creation}; _ -> undefined @@ -3787,7 +3784,7 @@ itemAttr(ItemId) -> [?XMLATTR('id', ItemId)]. % build item elements from item list itemsEls(Items) -> - lists:map(fun(#pubsub_item{itemid = {ItemId, _}, payload = Payload}) -> + lists:map(fun(#pubsub_item{id = {ItemId, _}, payload = Payload}) -> #xmlel{ns = ?NS_PUBSUB, name = 'item', attrs = itemAttr(ItemId), children = Payload} end, Items). @@ -3827,17 +3824,17 @@ collection_shim(Node) -> attrs = [?XMLATTR('name', <<"Collection">>)], children = [?XMLCDATA(node_to_string(Node))]}]. -subid_shim(SubIDs) -> +subid_shim(SubIds) -> [#xmlel{ns = ?NS_PUBSUB, name ='header', - attrs = [?XMLATTR('name', <<"SubID">>)], - children = [?XMLCDATA(SubID)]} - || SubID <- SubIDs]. + attrs = [?XMLATTR('name', <<"SubId">>)], + children = [?XMLCDATA(SubId)]} + || SubId <- SubIds]. -extended_headers(Jids) -> +extended_headers(JIDs) -> [#xmlel{ns = ?NS_ADDRESS, name = 'address', - attrs = [?XMLATTR('type', <<"replyto">>), ?XMLATTR('jid', Jid)]} - || Jid <- Jids]. + attrs = [?XMLATTR('type', <<"replyto">>), ?XMLATTR('jid', JID)]} + || JID <- JIDs]. feature_check_packet(allow, _User, Server, Pres, {From, _To, El}, in) -> Host = list_to_binary(host(Server)), @@ -3893,10 +3890,10 @@ purge_offline({User, Server, _} = LJID) -> case Result of {ok, Affiliations} -> lists:foreach( - fun({#pubsub_node{nodeid = {_, NodeId}, options = Options, type = Type}, Affiliation}) + fun({#pubsub_node{id = {_, NodeId}, options = Options, type = Type}, Affiliation}) when Affiliation == 'owner' orelse Affiliation == 'publisher' -> - Action = fun(#pubsub_node{type = NType, id = NodeIdx}) -> - node_call(NType, get_items, [NodeIdx, service_jid(Host)]) + Action = fun(#pubsub_node{type = NType, idx = Nidx}) -> + node_call(NType, get_items, [Nidx, service_jid(Host)]) end, case transaction(Host, NodeId, Action, sync_dirty) of {result, {_, []}} -> @@ -3912,7 +3909,7 @@ purge_offline({User, Server, _} = LJID) -> {true, true, true, true} -> ForceNotify = get_option(Options, notify_retract), lists:foreach( - fun(#pubsub_item{itemid = {ItemId, _}, modification = {_, Modification}}) -> + fun(#pubsub_item{id = {ItemId, _}, modification = {_, Modification}}) -> case Modification of {User, Server, _} -> delete_item(Host, NodeId, LJID, ItemId, ForceNotify); diff --git a/src/mod_pubsub/node.template b/src/mod_pubsub/node.template index 0efe75418..b6f39e6d2 100644 --- a/src/mod_pubsub/node.template +++ b/src/mod_pubsub/node.template @@ -75,8 +75,7 @@ terminate(Host, ServerHost) -> node_flat:terminate(Host, ServerHost). options() -> - [{node_type, __TO_BE_DEFINED__}, - {deliver_payloads, true}, + [{deliver_payloads, true}, {notify_config, false}, {notify_delete, false}, {notify_retract, true}, @@ -123,8 +122,8 @@ delete_node(Removed) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) -> node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubId) -> + node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId). publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). diff --git a/src/mod_pubsub/node_buddy.erl b/src/mod_pubsub/node_buddy.erl index 78af0a00e..46f63ecdf 100644 --- a/src/mod_pubsub/node_buddy.erl +++ b/src/mod_pubsub/node_buddy.erl @@ -26,8 +26,6 @@ -module(node_buddy). -author('christophe.romain@process-one.net'). --include_lib("exmpp/include/exmpp.hrl"). - -include("pubsub.hrl"). -behaviour(gen_pubsub_node). @@ -130,8 +128,8 @@ delete_node(Removed) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubId) -> + node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId). publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). diff --git a/src/mod_pubsub/node_club.erl b/src/mod_pubsub/node_club.erl index a8988819f..b7bb7cd4e 100644 --- a/src/mod_pubsub/node_club.erl +++ b/src/mod_pubsub/node_club.erl @@ -27,7 +27,6 @@ -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). --include_lib("exmpp/include/exmpp.hrl"). -behaviour(gen_pubsub_node). @@ -128,8 +127,8 @@ delete_node(Removed) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubId) -> + node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId). publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). diff --git a/src/mod_pubsub/node_dag.erl b/src/mod_pubsub/node_dag.erl index 768e50cbd..7f92cbc57 100644 --- a/src/mod_pubsub/node_dag.erl +++ b/src/mod_pubsub/node_dag.erl @@ -53,128 +53,417 @@ get_item/2, set_item/1, get_item_name/3, - node_to_path/1, - path_to_node/1]). + node_to_path/1, + path_to_node/1]). +-spec(init/3 :: + ( + Host :: string(), + ServerHost :: string(), + Opts :: [{Key::atom(), Value::term()}]) + -> 'ok' + ). + init(Host, ServerHost, Opts) -> node_flat:init(Host, ServerHost, Opts). + +-spec(terminate/2 :: + ( + Host :: string(), + ServerHost :: string()) + -> 'ok' + ). + terminate(Host, ServerHost) -> node_flat:terminate(Host, ServerHost). + +-spec(options/0 :: () -> [nodeOption()]). + options() -> - [{node_type, leaf} | node_flat:options()]. + [{'node_type', 'leaf'} | node_flat:options()]. + + +-spec(features/0 :: () -> [Feature::string()]). features() -> ["multi-collection" | node_flat:features()]. -create_node_permission(_Host, _ServerHost, _Node, _ParentNode, - _Owner, _Access) -> - {result, true}. -create_node(NodeID, Owner) -> - node_flat:create_node(NodeID, Owner). +-spec(create_node_permission/6 :: + ( + Host :: hostPubsub(), + ServerHost :: string(), + NodeId :: nodeId(), + ParentNodeId :: nodeId(), + JID :: jidEntity(), + Access :: atom()) + -> {'result', 'true'} + ). -delete_node(Removed) -> - node_flat:delete_node(Removed). +create_node_permission(_Host, _ServerHost, _NodeId, _ParentNodeId, + _JID, _Access) -> + {result, true}. -subscribe_node(NodeID, Sender, Subscriber, AccessModel, + +-spec(create_node/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', {'default', 'broadcast'}} + ). + +create_node(NodeIdx, JID) -> + node_flat:create_node(NodeIdx, JID). + + +-spec(delete_node/1 :: + ( + Nodes :: [Node::pubsubNode()]) + -> {result, {'default', 'broadcast', + Reply :: [{Node :: pubsubNode(), + [{Owner :: bareUsr(), + Subscriptions :: [{Subscription :: subscription(), + SubId :: subId()}]}]}]}} + ). + +delete_node(Nodes) -> + node_flat:delete_node(Nodes). + + +-spec(subscribe_node/8 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Subscriber :: jidEntity(), + AccessModel :: accessModel(), + SendLast :: atom(), + PresenceSubscription :: boolean(), + RosterGroup :: boolean(), + Options :: [nodeOption()]) + -> {'result', {'default', + Subscription :: 'subscribed', + SubId :: subId()}} + | {'result', {'default', + Subscription :: 'subscribed', + SubId :: subId(), + SendLast ::' send_last'}} + | {'result', {'default', + Subscription :: 'pending', + SubId :: subId()}} + | {'error', _} %% TODO add all error cases + ). + +subscribe_node(NodeIdx, JID, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - node_flat:subscribe_node(NodeID, Sender, Subscriber, AccessModel, + node_flat:subscribe_node(NodeIdx, JID, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeID, Sender, Subscriber, SubID) -> - node_flat:unsubscribe_node(NodeID, Sender, Subscriber, SubID). -publish_item(NodeID, Publisher, Model, MaxItems, ItemID, Payload) -> +-spec(unsubscribe_node/4 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Subscriber :: jidEntity(), + SubId :: subId()) + -> {'result', 'default'} | {'error', _} %% TODO : add all error cases + ). + +unsubscribe_node(NodeIdx, JID, Subscriber, SubId) -> + node_flat:unsubscribe_node(NodeIdx, JID, Subscriber, SubId). + + +-spec(publish_item/6 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + PublishModel :: atom(), %% TODO : make a generic publishMod() type + MaxItems :: 'unlimited' | integer(), + ItemId :: itemId(), + Payload :: payload()) + -> {'result', {'default', 'broadcast', ItemIds :: [] | [itemId()]}} + | {'error', _} + ). + +publish_item(NodeIdx, JID, PublishModel, MaxItems, ItemId, Payload) -> %% TODO: should look up the NodeTree plugin here. There's no %% access to the Host of the request at this level, so for now we %% just use nodetree_dag. - case nodetree_dag:get_node(NodeID) of + case nodetree_dag:get_node(NodeIdx) of #pubsub_node{options = Options} -> - case find_opt(node_type, Options) of - collection -> + case find_opt('node_type', Options) of + 'collection' -> {error, mod_pubsub:extended_error('not-allowed', "publish")}; _ -> - node_flat:publish_item(NodeID, Publisher, Model, - MaxItems, ItemID, Payload) + node_flat:publish_item(NodeIdx, JID, PublishModel, + MaxItems, ItemId, Payload) end; - Err -> - Err + Error -> + Error end. -find_opt(_, []) -> false; -find_opt(Option, [{Option, Value} | _]) -> Value; -find_opt(Option, [_ | T]) -> find_opt(Option, T). -remove_extra_items(NodeID, MaxItems, ItemIDs) -> - node_flat:remove_extra_items(NodeID, MaxItems, ItemIDs). +-spec(find_opt/2 :: + ( + Key :: atom(), + Options :: [] | [Option::nodeOption()]) + -> Value :: 'false' | term() + ). -delete_item(NodeID, Publisher, PublishModel, ItemID) -> - node_flat:delete_item(NodeID, Publisher, PublishModel, ItemID). +find_opt(_, []) -> false; +find_opt(Key, [{Key, Value} | _]) -> Value; +find_opt(Key, [_ | Options]) -> find_opt(Key, Options). -purge_node(NodeID, Owner) -> - node_flat:purge_node(NodeID, Owner). -get_entity_affiliations(Host, Owner) -> - node_flat:get_entity_affiliations(Host, Owner). +-spec(remove_extra_items/3 :: + ( + NodeIdx :: nodeIdx(), + MaxItems :: 'unlimited' | integer(), + ItemsIds :: [ItemId::itemId()]) + -> {'result', + {OldItems :: [] | [ItemId::itemId()], + NewItems :: [] | [ItemId::itemId()]}} + ). -get_node_affiliations(NodeID) -> - node_flat:get_node_affiliations(NodeID). +remove_extra_items(NodeIdx, MaxItems, ItemIds) -> + node_flat:remove_extra_items(NodeIdx, MaxItems, ItemIds). -get_affiliation(NodeID, Owner) -> - node_flat:get_affiliation(NodeID, Owner). -set_affiliation(NodeID, Owner, Affiliation) -> - node_flat:set_affiliation(NodeID, Owner, Affiliation). +-spec(delete_item/4 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + PublishModel :: atom(), + ItemId :: itemId()) + -> {'result', {'default', 'broadcast'}} | {'error', _} + ). -get_entity_subscriptions(Host, Owner) -> - node_flat:get_entity_subscriptions(Host, Owner). +delete_item(NodeIdx, JID, PublishModel, ItemId) -> + node_flat:delete_item(NodeIdx, JID, PublishModel, ItemId). -get_node_subscriptions(NodeID) -> - node_flat:get_node_subscriptions(NodeID). -get_subscriptions(NodeID, Owner) -> - node_flat:get_subscriptions(NodeID, Owner). +-spec(purge_node/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', {'default', 'broadcast'}} | {'error', 'forbidden'} + ). -set_subscriptions(NodeID, Owner, Subscription, SubID) -> - node_flat:set_subscriptions(NodeID, Owner, Subscription, SubID). +purge_node(NodeIdx, JID) -> + node_flat:purge_node(NodeIdx, JID). -get_pending_nodes(Host, Owner) -> - node_flat:get_pending_nodes(Host, Owner). -get_states(NodeID) -> - node_flat:get_states(NodeID). +-spec(get_entity_affiliations/2 :: + ( + Host :: binary(), + JID :: jidEntity()) + -> {'result', Reply :: [] | [{Node::pubsubNode(), Affiliation::affiliation()}]} + ). -get_state(NodeID, JID) -> - node_flat:get_state(NodeID, JID). +get_entity_affiliations(Host, JID) -> + node_flat:get_entity_affiliations(Host, JID). -set_state(State) -> - node_flat:set_state(State). -get_items(NodeID, From) -> - node_flat:get_items(NodeID, From). +-spec(get_node_affiliations/1 :: + ( + NodeIdx :: nodeIdx()) + -> {'result', [] | [{Entity::fullUsr(), Affiliation::affiliation()}]} + ). + +get_node_affiliations(NodeIdx) -> + node_flat:get_node_affiliations(NodeIdx). + + +-spec(get_affiliation/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', Affiliation::affiliation()} + ). + +get_affiliation(NodeIdx, JID) -> + node_flat:get_affiliation(NodeIdx, JID). + + +-spec(set_affiliation/3 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Affiliation :: affiliation()) + -> 'ok' | {error, 'internal-server-error'} + ). + +set_affiliation(NodeIdx, JID, Affiliation) -> + node_flat:set_affiliation(NodeIdx, JID, Affiliation). + + +-spec(get_entity_subscriptions/2 :: + ( + Host :: hostPubsub(), + JID :: jidEntity()) + -> {'result', [] + | [{Node :: pubsubNode(), + Subscription :: subscription(), + SubId :: subId(), + Entity :: fullUsr()}]} + ). + +get_entity_subscriptions(Host, JID) -> + node_flat:get_entity_subscriptions(Host, JID). -get_items(NodeID, JID, AccessModel, PresenceSubscription, - RosterGroup, SubID) -> - node_flat:get_items(NodeID, JID, AccessModel, PresenceSubscription, - RosterGroup, SubID). -get_item(NodeID, ItemID) -> - node_flat:get_item(NodeID, ItemID). +-spec(get_node_subscriptions/1 :: + ( + NodeIdx :: nodeIdx()) + -> {'result', [] + | [{Entity::fullUsr(), 'none'}] + | [{Entity::fullUsr(), Subscription::subscription(), SubId::subId()}]} + ). + +get_node_subscriptions(NodeIdx) -> + node_flat:get_node_subscriptions(NodeIdx). + + +-spec(get_subscriptions/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', Subscriptions :: [] | [{Subscription::subscription(), SubId::subId()}]} + ). + +get_subscriptions(NodeIdx, JID) -> + node_flat:get_subscriptions(NodeIdx, JID). + + +-spec(set_subscriptions/4 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Subscription :: subscription(), + SubId :: subId()) + -> 'ok' + | {Subscription::subscription(), SubId::subId()} + | {error, _} + ). + +set_subscriptions(NodeIdx, JID, Subscription, SubId) -> + node_flat:set_subscriptions(NodeIdx, JID, Subscription, SubId). + + +-spec(get_pending_nodes/2 :: + ( + Host :: hostPubsub(), + JID :: jidEntity()) + -> 'false' | {'value', NodeId::nodeId()} + ). + +get_pending_nodes(Host, JID) -> + node_flat:get_pending_nodes(Host, JID). + + +-spec(get_states/1 :: + ( + NodeIdx :: nodeIdx()) + -> {'result', States :: [] | [State::pubsubState()]} + ). + +get_states(NodeIdx) -> + node_flat:get_states(NodeIdx). + + +-spec(get_state/2 :: + ( + NodeIdx :: nodeIdx(), + Entity :: fullUsr()) + -> State::pubsubState() + ). + +get_state(NodeIdx, Entity) -> + node_flat:get_state(NodeIdx, Entity). + + +-spec(set_state/1 :: + ( + State :: pubsubState()) + -> 'ok' | {error, 'internal-server-error'} + ). + +set_state(State) -> + node_flat:set_state(State). + -get_item(NodeID, ItemID, JID, AccessModel, PresenceSubscription, - RosterGroup, SubID) -> - node_flat:get_item(NodeID, ItemID, JID, AccessModel, - PresenceSubscription, RosterGroup, SubID). +-spec(get_items/2 :: + ( + NodeIdx :: nodeIdx(), + Entity :: fullUsr()) + -> {'result', Items :: [] | [Item::pubsubItem()]} + ). + +get_items(NodeIdx, Entity) -> + node_flat:get_items(NodeIdx, Entity). + + +-spec(get_items/6 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + AccessModel :: accessModel(), + PresenceSubscription :: boolean(), + RosterGroup :: boolean(), + SubId :: subId()) + -> {'result', Items :: [] | [Item::pubsubItem()]} + | {'error', _} + ). + +get_items(NodeIdx, JID, AccessModel, PresenceSubscription, + RosterGroup, SubId) -> + node_flat:get_items(NodeIdx, JID, AccessModel, PresenceSubscription, + RosterGroup, SubId). + + +-spec(get_item/2 :: + ( + NodeIdx :: nodeIdx(), + ItemId :: itemId()) + -> {'result', Item::pubsubItem()} | {'error', 'item-not-found'} + ). + +get_item(NodeIdx, ItemId) -> + node_flat:get_item(NodeIdx, ItemId). + + +-spec(get_item/7 :: + ( + NodeIdx :: nodeIdx(), + ItemId :: itemId(), + JID :: jidEntity(), + AccessModel :: accessModel(), + PresenceSubscription :: boolean(), + RosterGroup :: boolean(), + SubId :: subId()) + -> {'result', Item::pubsubItem()} | {'error', 'item-not-found'} + ). + +get_item(NodeIdx, ItemId, JID, AccessModel, PresenceSubscription, + RosterGroup, SubId) -> + node_flat:get_item(NodeIdx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). + + +-spec(set_item/1 :: + ( + Item :: pubsubItem()) + -> 'ok' | {error, 'internal-server-error'} + ). set_item(Item) -> node_flat:set_item(Item). -get_item_name(Host, Node, ID) -> - node_flat:get_item_name(Host, Node, ID). +get_item_name(Host, Node, ItemId) -> + node_flat:get_item_name(Host, Node, ItemId). node_to_path(Node) -> node_flat:node_to_path(Node). diff --git a/src/mod_pubsub/node_dispatch.erl b/src/mod_pubsub/node_dispatch.erl index 1876d0c06..b5b8419c6 100644 --- a/src/mod_pubsub/node_dispatch.erl +++ b/src/mod_pubsub/node_dispatch.erl @@ -27,7 +27,6 @@ -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). --include_lib("exmpp/include/exmpp.hrl"). -behaviour(gen_pubsub_node). @@ -126,13 +125,13 @@ subscribe_node(_NodeId, _Sender, _Subscriber, _AccessModel, _SendLast, _PresenceSubscription, _RosterGroup, _Options) -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'forbidden')}. -unsubscribe_node(_NodeId, _Sender, _Subscriber, _SubID) -> +unsubscribe_node(_NodeId, _Sender, _Subscriber, _SubId) -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'forbidden')}. publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> lists:foreach(fun(SubNode) -> node_flat:publish_item( - SubNode#pubsub_node.id, Publisher, Model, + SubNode#pubsub_node.idx, Publisher, Model, MaxItems, ItemId, Payload) end, nodetree_tree:get_subnodes(NodeId, Publisher, Publisher)). diff --git a/src/mod_pubsub/node_flat.erl b/src/mod_pubsub/node_flat.erl index 985bc9421..1d1096461 100644 --- a/src/mod_pubsub/node_flat.erl +++ b/src/mod_pubsub/node_flat.erl @@ -42,13 +42,15 @@ -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). --include_lib("exmpp/include/exmpp.hrl"). -behaviour(gen_pubsub_node). %% API definition --export([init/3, terminate/2, - options/0, features/0, +-export([ + init/3, + terminate/2, + options/0, + features/0, create_node_permission/6, create_node/2, delete_node/1, @@ -80,6 +82,7 @@ path_to_node/1 ]). + %% ================ %% API definition %% ================ @@ -93,6 +96,14 @@ %% <p>This function is mainly used to trigger the setup task necessary for the %% plugin. It can be used for example by the developer to create the specific %% module database schema if it does not exists yet.</p> +-spec(init/3 :: + ( + Host :: string(), + ServerHost :: string(), + Opts :: [{Key::atom(), Value::term()}]) + -> 'ok' + ). + init(_Host, _ServerHost, _Opts) -> pubsub_subscription:init(), mnesia:create_table(pubsub_state, @@ -104,8 +115,7 @@ init(_Host, _ServerHost, _Opts) -> ItemsFields = record_info(fields, pubsub_item), case mnesia:table_info(pubsub_item, attributes) of ItemsFields -> ok; - _ -> - mnesia:transform_table(pubsub_item, ignore, ItemsFields) + _ -> mnesia:transform_table(pubsub_item, ignore, ItemsFields) end, ok. @@ -114,6 +124,13 @@ init(_Host, _ServerHost, _Opts) -> %% ServerHost = host() %% @doc <p>Called during pubsub modules termination. Any pubsub plugin must %% implement this function. It can return anything.</p> +-spec(terminate/2 :: + ( + Host :: string(), + ServerHost :: string()) + -> 'ok' + ). + terminate(_Host, _ServerHost) -> ok. @@ -134,27 +151,31 @@ terminate(_Host, _ServerHost) -> %% {max_payload_size, 100000}, %% {send_last_published_item, never}, %% {presence_based_delivery, false}]''' +-spec(options/0 :: () -> [nodeOption()]). + options() -> - [{deliver_payloads, true}, - {notify_config, false}, - {notify_delete, false}, - {notify_retract, true}, - {notify_sub, false}, - {purge_offline, false}, - {persist_items, true}, - {max_items, ?MAXITEMS}, - {subscribe, true}, - {access_model, open}, - {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, on_sub_and_presence}, - {deliver_notifications, true}, - {presence_based_delivery, false}]. + [{'deliver_payloads', true}, + {'notify_config', false}, + {'notify_delete', false}, + {'notify_retract', true}, + {'notify_sub', false}, + {'purge_offline', false}, + {'persist_items', true}, + {'max_items', ?MAXITEMS}, + {'subscribe', true}, + {'access_model', open}, + {'roster_groups_allowed', []}, + {'publish_model', publishers}, + {'notification_type', headline}, + {'max_payload_size', ?MAX_PAYLOAD_SIZE}, + {'send_last_published_item', on_sub_and_presence}, + {'deliver_notifications', true}, + {'presence_based_delivery', false}]. %% @spec () -> [] %% @doc Returns the node features +-spec(features/0 :: () -> [Feature::string()]). + features() -> ["create-nodes", "auto-create", @@ -182,47 +203,67 @@ features() -> %% use same code as node_flat, but do not limite node to %% the home/localhost/user/... hierarchy %% any node is allowed -create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> - LOwner = jlib:short_prepd_jid(Owner), - Allowed = case LOwner of - {undefined, Host, undefined} -> - true; % pubsub service always allowed - _ -> - {LU, LS, LR} = LOwner, - acl:match_rule(ServerHost, Access, exmpp_jid:make(LU, LS, LR)) =:= allow - end, - {result, Allowed}. +-spec(create_node_permission/6 :: + ( + Host :: hostPubsub(), + ServerHost :: string(), + NodeId :: nodeId(), + ParentNodeId :: nodeId(), + JID :: jidEntity(), + Access :: atom()) + -> {'result', IsAllowed::boolean()} + ). + +create_node_permission(Host, ServerHost, _NodeId, _ParentNodeId, #jid{node = U, domain = S, resource = R} = JID, Access) -> + Owner = {U,S,R}, + IsAllowed = case Owner of + {undefined, Host, undefined} -> true; % pubsub service always allowed + _ -> acl:match_rule(ServerHost, Access, JID) =:= 'allow' + end, + {result, IsAllowed}. %% @spec (NodeId, Owner) -> %% {result, Result} | exit -%% NodeId = mod_pubsub:pubsubNodeId() -%% Owner = mod_pubsub:jid() +%% NodeId = nodeidx() +%% Owner = ljid() %% @doc <p></p> -create_node(NodeId, Owner) -> - OwnerKey = jlib:short_prepd_bare_jid(Owner), - set_state(#pubsub_state{stateid = {OwnerKey, NodeId}, affiliation = owner}), - {result, {default, broadcast}}. +-spec(create_node/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', {'default', 'broadcast'}} + ). + +create_node(NodeIdx, #jid{node = U, domain = S} = _JID) -> + set_state(#pubsub_state{id = {{U,S,undefined}, NodeIdx}, affiliation = 'owner'}), + {'result', {'default', 'broadcast'}}. %% @spec (Removed) -> ok -%% Removed = [mod_pubsub:pubsubNode()] +%% Removed = [mod_pubsub:pubsub_node()] %% @doc <p>purge items of deleted nodes after effective deletion.</p> -delete_node(Removed) -> - Tr = fun(#pubsub_state{stateid = {J, _}, subscriptions = Ss}) -> - lists:map(fun(S) -> - {J, S} - end, Ss) - end, - Reply = lists:map( - fun(#pubsub_node{id = NodeId} = PubsubNode) -> - {result, States} = get_states(NodeId), - lists:foreach( - fun(#pubsub_state{stateid = {LJID, _}, items = Items}) -> - del_items(NodeId, Items), - del_state(NodeId, LJID) - end, States), - {PubsubNode, lists:flatmap(Tr, States)} - end, Removed), - {result, {default, broadcast, Reply}}. +-spec(delete_node/1 :: + ( + Nodes :: [Node::pubsubNode()]) + -> {result, {'default', 'broadcast', + Reply :: [{Node :: pubsubNode(), + [{Owner :: bareUsr(), + Subscriptions :: [{Subscription :: subscription(), + SubId :: subId()}]}]}]}} + ). + +delete_node(Nodes) -> + Fun = fun(#pubsub_state{id = {Entity, _}, subscriptions = Subscriptions}) -> + [{Entity, Subscription} || Subscription <- Subscriptions] + end, + Reply = lists:map(fun(#pubsub_node{idx = NodeIdx} = Node) -> + {result, States} = get_states(NodeIdx), + lists:foreach(fun(#pubsub_state{id = {Owner, _}, items = ItemIds}) -> + del_items(NodeIdx, ItemIds), + del_state(NodeIdx, Owner), + {Node, lists:flatmap(Fun, States)} + end, States) + end, Nodes), + {'result', {'default', 'broadcast', Reply}}. %% @spec (NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> %% {error, Reason} | {result, Result} @@ -257,153 +298,189 @@ delete_node(Removed) -> %% to completly disable persistance.</li></ul> %% </p> %% <p>In the default plugin module, the record is unchanged.</p> -subscribe_node(NodeId, Sender, {U,S,R} = Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> +-spec(subscribe_node/8 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Subscriber :: jidEntity(), + AccessModel :: accessModel(), + SendLast :: atom(), + PresenceSubscription :: boolean(), + RosterGroup :: boolean(), + Options :: [nodeOption()]) + -> {'result', {'default', + Subscription :: 'subscribed', + SubId :: subId()}} + | {'result', {'default', + Subscription :: 'subscribed', + SubId :: subId(), + SendLast ::' send_last'}} + | {'result', {'default', + Subscription :: 'pending', + SubId :: subId()}} + | {'error', _} %% TODO add all error cases + ). + +subscribe_node(NodeIdx, #jid{node = Usender, domain = Ssender} = _Sender, #jid{node = U, domain = S, resource = R} = Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> SubKey = {U, S, R}, GenKey = {U, S, undefined}, - Authorized = (jlib:short_prepd_bare_jid(Sender) == GenKey), - GenState = get_state(NodeId, GenKey), - SubState = case SubKey of - GenKey -> GenState; - _ -> get_state(NodeId, SubKey) - end, - Affiliation = GenState#pubsub_state.affiliation, - Subscriptions = SubState#pubsub_state.subscriptions, - Whitelisted = lists:member(Affiliation, [member, publisher, owner]), - PendingSubscription = lists:any(fun({pending, _}) -> true; - (_) -> false - end, Subscriptions), + Authorized = ({Usender, Ssender, undefined} == GenKey), + GenState = #pubsub_state{affiliation = Affiliation} = get_state(NodeIdx, GenKey), + SubState = #pubsub_state{subscriptions = Subscriptions} = case SubKey of + GenKey -> GenState; + _ -> get_state(NodeIdx, SubKey) + end, + Whitelisted = lists:member(Affiliation, ['member', 'publisher', 'owner']), + PendingSubscription = lists:any(fun + ({'pending', _}) -> true; + (_) -> false + end, Subscriptions), if not Authorized -> %% JIDs do not match - {error, ?ERR_EXTENDED('bad-request', "invalid-jid")}; - Affiliation == outcast -> + {'error', ?ERR_EXTENDED('bad-request', "invalid-jid")}; + Affiliation == 'outcast' -> %% Requesting entity is blocked - {error, 'forbidden'}; + {'error', 'forbidden'}; PendingSubscription -> %% Requesting entity has pending subscription - {error, ?ERR_EXTENDED('not-authorized', "pending-subscription")}; - (AccessModel == presence) and (not PresenceSubscription) -> + {'error', ?ERR_EXTENDED('not-authorized', "pending-subscription")}; + (AccessModel == 'presence') and (not PresenceSubscription) -> %% Entity is not authorized to create a subscription (presence subscription required) - {error, ?ERR_EXTENDED('not-authorized', "presence-subscription-required")}; - (AccessModel == roster) and (not RosterGroup) -> + {'error', ?ERR_EXTENDED('not-authorized', "presence-subscription-required")}; + (AccessModel == 'roster') and (not RosterGroup) -> %% Entity is not authorized to create a subscription (not in roster group) - {error, ?ERR_EXTENDED('not-authorized', "not-in-roster-group")}; - (AccessModel == whitelist) and (not Whitelisted) -> + {'error', ?ERR_EXTENDED('not-authorized', "not-in-roster-group")}; + (AccessModel == 'whitelist') and (not Whitelisted) -> %% Node has whitelist access model and entity lacks required affiliation - {error, ?ERR_EXTENDED('not-allowed', "closed-node")}; + {'error', ?ERR_EXTENDED('not-allowed', "closed-node")}; %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; + %% Payment is required for a subscription + %% {'error', ?ERR_PAYMENT_REQUIRED}; %%ForbiddenAnonymous -> - %% % Requesting entity is anonymous - %% {error, 'forbidden'}; + %% Requesting entity is anonymous + %% {'error', 'forbidden'}; true -> - case pubsub_subscription:subscribe_node(Subscriber, NodeId, Options) of - {result, SubId} -> - NewSub = case AccessModel of - authorize -> pending; - _ -> subscribed - end, - set_state(SubState#pubsub_state{subscriptions = [{NewSub, SubId} | Subscriptions]}), - case {NewSub, SendLast} of - {subscribed, never} -> - {result, {default, subscribed, SubId}}; - {subscribed, _} -> - {result, {default, subscribed, SubId, send_last}}; - {_, _} -> - {result, {default, pending, SubId}} + case pubsub_subscription:subscribe_node(Subscriber, NodeIdx, Options) of + {'result', SubId} -> + NewSubscription = case AccessModel of + 'authorize' -> 'pending'; + _ -> 'subscribed' + end, + set_state(SubState#pubsub_state{subscriptions = [{NewSubscription, SubId} | Subscriptions]}), + case {NewSubscription, SendLast} of + {'subscribed', 'never'} -> {'result', {'default', 'subscribed', SubId}}; + {'subscribed', _} -> {'result', {'default', 'subscribed', SubId, 'send_last'}}; + {_, _} -> {'result', {'default', 'pending', SubId}} end; _ -> - {error, 'internal-server-error'} + {'error', 'internal-server-error'} end end. %% @spec (NodeId, Sender, Subscriber, SubId) -> %% {error, Reason} | {result, []} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Sender = mod_pubsub:jid() -%% Subscriber = mod_pubsub:jid() +%% NodeId = nodeidx() +%% Sender = ljid() +%% Subscriber = ljid() %% SubId = mod_pubsub:subid() %% Reason = mod_pubsub:stanzaError() %% @doc <p>Unsubscribe the <tt>Subscriber</tt> from the <tt>Node</tt>.</p> -unsubscribe_node(NodeId, Sender, {U, S, R} = Subscriber, SubId) -> +-spec(unsubscribe_node/4 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Subscriber :: jidEntity(), + SubId :: subId()) + -> {'result', 'default'} | {'error', _} %% TODO : add all error cases + ). + +unsubscribe_node(NodeIdx, #jid{node = Usender, domain = Ssender} = _Sender, #jid{node = U, domain = S, resource = R} = _Subscriber, SubId) -> SubKey = {U, S, R}, GenKey = {U, S, undefined}, - Authorized = (jlib:short_prepd_bare_jid(Sender) == GenKey), - GenState = get_state(NodeId, GenKey), + Authorized = ({Usender, Ssender, undefined} == GenKey), + GenState = get_state(NodeIdx, GenKey), SubState = case SubKey of - GenKey -> GenState; - _ -> get_state(NodeId, SubKey) - end, - Subscriptions = lists:filter(fun({_Sub, _SubId}) -> true; - (_SubId) -> false - end, SubState#pubsub_state.subscriptions), + GenKey -> GenState; + _ -> get_state(NodeIdx, SubKey) + end, + Subscriptions = SubState#pubsub_state.subscriptions, SubIdExists = case SubId of - [] -> false; - List when is_list(List) -> true; - _ -> false + <<>> -> false; + SubId when is_binary(SubId) -> true; + _ -> false end, if %% Requesting entity is prohibited from unsubscribing entity not Authorized -> - {error, 'forbidden'}; + {'error', 'forbidden'}; %% Entity did not specify SubId %%SubId == "", ?? -> - %% {error, ?ERR_EXTENDED('bad-request', "subid-required")}; + %% {'error', ?ERR_EXTENDED('bad-request', "subid-required")}; %% Invalid subscription identifier %%InvalidSubId -> - %% {error, ?ERR_EXTENDED('not-acceptable', "invalid-subid")}; + %% {'error', ?ERR_EXTENDED('not-acceptable', "invalid-subid")}; %% Requesting entity is not a subscriber Subscriptions == [] -> - {error, ?ERR_EXTENDED('unexpected-request', "not-subscribed")}; + {'error', ?ERR_EXTENDED('unexpected-request', "not-subscribed")}; %% Subid supplied, so use that. SubIdExists -> - Sub = first_in_list(fun({_, Id}) when Id == SubId -> true; - (_) -> false - end, Subscriptions), - case Sub of - {value, Subscribed} -> - delete_subscriptions(Subscriber, NodeId, [Subscribed], SubState), - {result, default}; + OldSubscription = first_in_list(fun + ({_, OldSubId}) when OldSubId == SubId -> true; + (_) -> false + end, Subscriptions), + case OldSubscription of + {'value', Subscribed} -> + delete_subscriptions(SubKey, NodeIdx, [Subscribed], SubState), + {'result', 'default'}; false -> - {error, ?ERR_EXTENDED('unexpected-request', "not-subscribed")} + {'error', ?ERR_EXTENDED('unexpected-request', "not-subscribed")} end; %% Asking to remove all subscriptions to the given node - SubId == all -> - delete_subscriptions(SubKey, NodeId, Subscriptions, SubState), - {result, default}; + SubId == 'all' -> + delete_subscriptions(SubKey, NodeIdx, Subscriptions, SubState), + {'result', 'default'}; %% No subid supplied, but there's only one matching %% subscription, so use that. length(Subscriptions) == 1 -> - delete_subscriptions(SubKey, NodeId, Subscriptions, SubState), - {result, default}; + delete_subscriptions(SubKey, NodeIdx, Subscriptions, SubState), + {'result', 'default'}; true -> - {error, ?ERR_EXTENDED('bad-request', "subid-required")} + {'error', ?ERR_EXTENDED('bad-request', "subid-required")} end. -delete_subscriptions(SubKey, NodeId, Subscriptions, SubState) -> - NewSubs = lists:foldl(fun({Subscription, SubId}, Acc) -> - pubsub_subscription:delete_subscription(SubKey, NodeId, SubId), - Acc -- [{Subscription, SubId}] - end, SubState#pubsub_state.subscriptions, Subscriptions), - case {SubState#pubsub_state.affiliation, NewSubs} of - {none, []} -> - % Just a regular subscriber, and this is final item, so - % delete the state. - del_state(NodeId, SubKey); + +-spec(delete_subscriptions/4 :: + ( + Entity :: fullUsr(), + NodeIdx :: nodeIdx(), + Subscriptions :: [{Subscription::subscription(), SubId::subId()}], + State :: pubsubState()) + -> 'ok' | {error, 'internal-server-error'} + ). + +delete_subscriptions(Entity, NodeIdx, Subscriptions, State) -> + NewSubscriptions = lists:foldl(fun({Subscription, SubId}, Acc) -> + pubsub_subscription:delete_subscription(Entity, NodeIdx, SubId), + Acc -- [{Subscription, SubId}] + end, State#pubsub_state.subscriptions, Subscriptions), + case {State#pubsub_state.affiliation, NewSubscriptions} of + {'none', []} -> + % Just a regular subscriber, and this is final item, so + % delete the state. + del_state(NodeIdx, Entity); _ -> - set_state(SubState#pubsub_state{subscriptions = NewSubs}) + set_state(State#pubsub_state{subscriptions = NewSubscriptions}) end. %% @spec (NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% {true, PubsubItem} | {result, Reply} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Publisher = mod_pubsub:jid() +%% NodeId = nodeidx() +%% Publisher = ljid() %% PublishModel = atom() %% MaxItems = integer() -%% ItemId = string() +%% ItemId = item() %% Payload = term() %% @doc <p>Publishes the item passed as parameter.</p> %% <p>The mechanism works as follow: @@ -435,53 +512,64 @@ delete_subscriptions(SubKey, NodeId, Subscriptions, SubState) -> %% to completly disable persistance.</li></ul> %% </p> %% <p>In the default plugin module, the record is unchanged.</p> -publish_item(NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) -> - SubKey = jlib:short_prepd_jid(Publisher), - GenKey = jlib:short_prepd_bare_jid(Publisher), - GenState = get_state(NodeId, GenKey), +-spec(publish_item/6 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + PublishModel :: atom(), %% TODO : make a generic publishMod() type + MaxItems :: 'unlimited' | integer(), + ItemId :: itemId(), + Payload :: payload()) + -> {'result', {'default', 'broadcast', ItemIds :: [] | [itemId()]}} + | {'error', _} + ). + +publish_item(NodeIdx, #jid{node = U, domain = S, resource = R} = _JID, PublishModel, MaxItems, ItemId, Payload) -> + SubKey = {U,S,R}, + GenKey = {U,S,undefined}, + GenState = get_state(NodeIdx, GenKey), SubState = case SubKey of - GenKey -> GenState; - _ -> get_state(NodeId, SubKey) - end, + GenKey -> GenState; + _ -> get_state(NodeIdx, SubKey) + end, Affiliation = GenState#pubsub_state.affiliation, Subscribed = case PublishModel of - subscribers -> is_subscribed(SubState#pubsub_state.subscriptions); - _ -> undefined - end, + 'subscribers' -> is_subscribed(SubState#pubsub_state.subscriptions); + _ -> undefined + end, if - not ((PublishModel == open) - or ((PublishModel == publishers) - and ((Affiliation == owner) or (Affiliation == publisher))) - or (Subscribed == true)) -> + not ((PublishModel == 'open') or ((PublishModel == 'publishers') + and ((Affiliation == 'owner') or (Affiliation == 'publisher'))) + or (Subscribed == 'true')) -> %% Entity does not have sufficient privileges to publish to node - {error, 'forbidden'}; + {'error', 'forbidden'}; true -> %% TODO: check creation, presence, roster if MaxItems > 0 -> - Now = now(), - PubId = {Now, SubKey}, - Item = case get_item(NodeId, ItemId) of - {result, OldItem} -> - OldItem#pubsub_item{modification = PubId, - payload = Payload}; - _ -> - #pubsub_item{itemid = {ItemId, NodeId}, - creation = {Now, GenKey}, - modification = PubId, - payload = Payload} - end, - Items = [ItemId | GenState#pubsub_state.items--[ItemId]], - {result, {NI, OI}} = remove_extra_items(NodeId, MaxItems, Items), - set_item(Item), - set_state(GenState#pubsub_state{items = NI}), - {result, {default, broadcast, OI}}; + Now = now(), + Modification = {Now, SubKey}, + Item = case get_item(NodeIdx, ItemId) of + {'result', OldItem} -> + OldItem#pubsub_item{modification = Modification, payload = Payload}; + _ -> + #pubsub_item{ + id = {ItemId, NodeIdx}, + creation = {Now, GenKey}, % TODO, better use {Now, SubKey} ? + modification = Modification, + payload = Payload} + end, + Items = [ItemId | GenState#pubsub_state.items--[ItemId]], + {result, {NewItems, OldItems}} = remove_extra_items(NodeIdx, MaxItems, Items), + set_item(Item), + set_state(GenState#pubsub_state{items = NewItems}), + {'result', {'default', 'broadcast', OldItems}}; true -> - {result, {default, broadcast, []}} + {'result', {'default', 'broadcast', []}} end end. %% @spec (NodeId, MaxItems, ItemIds) -> {NewItemIds,OldItemIds} -%% NodeId = mod_pubsub:pubsubNodeId() +%% NodeId = nodeidx() %% MaxItems = integer() | unlimited %% ItemIds = [ItemId::string()] %% NewItemIds = [ItemId::string()] @@ -495,67 +583,84 @@ publish_item(NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% plugin is using the default pubsub storage), it can implements this function like this: %% ```remove_extra_items(NodeId, MaxItems, ItemIds) -> %% node_default:remove_extra_items(NodeId, MaxItems, ItemIds).'''</p> -remove_extra_items(_NodeId, unlimited, ItemIds) -> - {result, {ItemIds, []}}; -remove_extra_items(NodeId, MaxItems, ItemIds) -> +-spec(remove_extra_items/3 :: + ( + NodeIdx :: nodeIdx(), + MaxItems :: 'unlimited' | integer(), + ItemsIds :: [ItemId::itemId()]) + -> {'result', + {OldItems :: [] | [ItemId::itemId()], + NewItems :: [] | [ItemId::itemId()]}} + ). + +remove_extra_items(_NodeIdx, 'unlimited', ItemIds) -> + {'result', {ItemIds, []}}; +remove_extra_items(NodeIdx, MaxItems, ItemIds) -> NewItems = lists:sublist(ItemIds, MaxItems), OldItems = lists:nthtail(length(NewItems), ItemIds), %% Remove extra items: - del_items(NodeId, OldItems), + del_items(NodeIdx, OldItems), %% Return the new items list: - {result, {NewItems, OldItems}}. + {'result', {NewItems, OldItems}}. %% @spec (NodeId, Publisher, PublishModel, ItemId) -> %% {error, Reason::stanzaError()} | %% {result, []} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Publisher = mod_pubsub:jid() +%% NodeId = nodeidx() +%% Publisher = ljid() %% PublishModel = atom() -%% ItemId = string() +%% ItemId = item() %% @doc <p>Triggers item deletion.</p> %% <p>Default plugin: The user performing the deletion must be the node owner %% or a publisher, or PublishModel being open.</p> -delete_item(NodeId, Publisher, PublishModel, ItemId) -> - GenKey = jlib:short_prepd_bare_jid(Publisher), - GenState = get_state(NodeId, GenKey), - #pubsub_state{affiliation = Affiliation, items = Items} = GenState, - Allowed = (Affiliation == publisher) orelse (Affiliation == owner) - orelse (PublishModel == open) - orelse case get_item(NodeId, ItemId) of +-spec(delete_item/4 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + PublishModel :: atom(), + ItemId :: itemId()) + -> {'result', {'default', 'broadcast'}} | {'error', _} + ). + +delete_item(NodeIdx, #jid{node = U, domain = S} = _JID, PublishModel, ItemId) -> + GenKey = {U,S,undefined}, + GenState = #pubsub_state{affiliation = Affiliation, items = Items} = get_state(NodeIdx, GenKey), + Allowed = (Affiliation == 'publisher') + orelse (Affiliation == 'owner') + orelse (PublishModel == 'open') + orelse case get_item(NodeIdx, ItemId) of {result, #pubsub_item{creation = {_, GenKey}}} -> true; - _ -> false + _ -> false end, if not Allowed -> %% Requesting entity does not have sufficient privileges - {error, 'forbidden'}; + {'error', 'forbidden'}; true -> case lists:member(ItemId, Items) of true -> - del_item(NodeId, ItemId), + del_item(NodeIdx, ItemId), set_state(GenState#pubsub_state{items = lists:delete(ItemId, Items)}), - {result, {default, broadcast}}; + {'result', {'default', 'broadcast'}}; false -> case Affiliation of - owner -> + 'owner' -> %% Owner can delete other publishers items as well - {result, States} = get_states(NodeId), - lists:foldl( - fun(#pubsub_state{items = PI, affiliation = publisher} = S, Res) -> - case lists:member(ItemId, PI) of - true -> - del_item(NodeId, ItemId), - set_state(S#pubsub_state{items = lists:delete(ItemId, PI)}), - {result, {default, broadcast}}; - false -> - Res - end; - (_, Res) -> - Res - end, {error, 'item-not-found'}, States); + {'result', States} = get_states(NodeIdx), + lists:foldl(fun + (#pubsub_state{items = ItemIds, affiliation = publisher} = State, Result) -> + case lists:member(ItemId, ItemIds) of + true -> + del_item(NodeIdx, ItemId), + set_state(State#pubsub_state{items = lists:delete(ItemId, ItemIds)}), + {'result', {'default', 'broadcast'}}; + false -> Result + end; + (_, Result) -> Result + end, {'error', 'item-not-found'}, States); _ -> %% Non-existent node or item - {error, 'item-not-found'} + {'error', 'item-not-found'} end end end. @@ -563,30 +668,36 @@ delete_item(NodeId, Publisher, PublishModel, ItemId) -> %% @spec (NodeId, Owner) -> %% {error, Reason::stanzaError()} | %% {result, {default, broadcast}} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Owner = mod_pubsub:jid() -purge_node(NodeId, Owner) -> - GenKey = jlib:short_prepd_bare_jid(Owner), - GenState = get_state(NodeId, GenKey), - case GenState of - #pubsub_state{affiliation = owner} -> - {result, States} = get_states(NodeId), - lists:foreach( - fun(#pubsub_state{items = []}) -> - ok; - (#pubsub_state{items = Items} = S) -> - del_items(NodeId, Items), - set_state(S#pubsub_state{items = []}) - end, States), - {result, {default, broadcast}}; - _ -> - %% Entity is not owner - {error, 'forbidden'} +%% NodeId = nodeidx() +%% Owner = ljid() +-spec(purge_node/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', {'default', 'broadcast'}} | {'error', 'forbidden'} + ). + +purge_node(NodeIdx, #jid{node = U, domain = S} = _JID) -> + %GenKey = {U,S,undefined} + %GenState = get_state(NodeIdx, _GenKey = {U,S,undefined}), + case _GenState = get_state(NodeIdx, _GenKey = {U,S,undefined}) of % experimental + #pubsub_state{affiliation = 'owner'} -> + {'result', States} = get_states(NodeIdx), + lists:foreach(fun + (#pubsub_state{items = []}) -> + ok; + (#pubsub_state{items = Items} = State) -> + del_items(NodeIdx, Items), + set_state(State#pubsub_state{items = []}) + end, States), + {'result', {'default', 'broadcast'}}; + _ -> %% Entity is not owner + {'error', 'forbidden'} end. %% @spec (Host, JID) -> [{Node,Affiliation}] %% Host = host() -%% JID = mod_pubsub:jid() +%% JID = ljid() %% @doc <p>Return the current affiliations for the given user</p> %% <p>The default module reads affiliations in the main Mnesia %% <tt>pubsub_state</tt> table. If a plugin stores its data in the same @@ -594,46 +705,74 @@ purge_node(NodeId, Owner) -> %% the default PubSub module. Otherwise, it should return its own affiliation, %% that will be added to the affiliation stored in the main %% <tt>pubsub_state</tt> table.</p> -get_entity_affiliations(Host, Owner) -> - GenKey = jlib:short_prepd_bare_jid(Owner), - States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), - NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of - [{nodetree, N}] -> N; - _ -> nodetree_tree - end, - Reply = lists:foldl(fun(#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {Host, _}} = Node -> [{Node, A}|Acc]; - _ -> Acc - end - end, [], States), +-spec(get_entity_affiliations/2 :: + ( + Host :: binary(), + JID :: jidEntity()) + -> {'result', Reply :: [] | [{Node::pubsubNode(), Affiliation::affiliation()}]} + ). + +get_entity_affiliations(Host, #jid{node = U, domain = S} = _JID) -> + States = mnesia:match_object(#pubsub_state{id = {{U,S,undefined}, '_'}, _ = '_'}), + NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, 'config'), 'nodetree') of + [{'nodetree', Tree}] -> Tree; + _ -> 'nodetree_tree' + end, + Reply = lists:foldl(fun + (#pubsub_state{id = {_, NodeIdx}, affiliation = Affiliation}, Acc) -> + case NodeTree:get_node(NodeIdx) of + #pubsub_node{id = {Host, _}} = Node -> [{Node, Affiliation}|Acc]; + _ -> Acc + end + end, [], States), {result, Reply}. -get_node_affiliations(NodeId) -> - {result, States} = get_states(NodeId), - Tr = fun(#pubsub_state{stateid = {J, _}, affiliation = A}) -> - {J, A} - end, - {result, lists:map(Tr, States)}. - -get_affiliation(NodeId, Owner) -> - GenKey = jlib:short_prepd_bare_jid(Owner), - GenState = get_state(NodeId, GenKey), - {result, GenState#pubsub_state.affiliation}. - -set_affiliation(NodeId, Owner, Affiliation) when ?IS_JID(Owner)-> - GenKey = jlib:short_prepd_bare_jid(Owner), - GenState = get_state(NodeId, GenKey), - case {Affiliation, GenState#pubsub_state.subscriptions} of - {none, none} -> - del_state(NodeId, GenKey); - _ -> - set_state(GenState#pubsub_state{affiliation = Affiliation}) + +-spec(get_node_affiliations/1 :: + ( + NodeIdx :: nodeIdx()) + -> {'result', [] | [{Entity::fullUsr(), Affiliation::affiliation()}]} + ). + +get_node_affiliations(NodeIdx) -> + {result, States} = get_states(NodeIdx), + Fun = fun(#pubsub_state{id = {Entity, _}, affiliation = Affiliation}) -> + {Entity, Affiliation} + end, + {result, lists:map(Fun, States)}. + + +-spec(get_affiliation/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', Affiliation::affiliation()} + ). + +get_affiliation(NodeIdx, #jid{node = U, domain = S} = _JID) -> + #pubsub_state{affiliation = Affiliation} = get_state(NodeIdx, _GenKey = {U,S,undefined}), + {'result', Affiliation}. + + +-spec(set_affiliation/3 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Affiliation :: affiliation()) + -> 'ok' | {error, 'internal-server-error'} + ). + +set_affiliation(NodeIdx, #jid{node = U, domain = S} = _JID, Affiliation) -> + GenKey = {U,S,undefined}, + GenState = #pubsub_state{subscriptions = Subscriptions} = get_state(NodeIdx, GenKey), + case {Affiliation, Subscriptions} of + {'none', []} -> del_state(NodeIdx, GenKey); + _ -> set_state(GenState#pubsub_state{affiliation = Affiliation}) end. %% @spec (Host, Owner) -> [{Node,Subscription}] %% Host = host() -%% Owner = mod_pubsub:jid() +%% Owner = ljid() %% @doc <p>Return the current subscriptions for the given user</p> %% <p>The default module reads subscriptions in the main Mnesia %% <tt>pubsub_state</tt> table. If a plugin stores its data in the same @@ -641,157 +780,228 @@ set_affiliation(NodeId, Owner, Affiliation) when ?IS_JID(Owner)-> %% the default PubSub module. Otherwise, it should return its own affiliation, %% that will be added to the affiliation stored in the main %% <tt>pubsub_state</tt> table.</p> -get_entity_subscriptions(Host, Owner) -> - {U, D, _} = SubKey = jlib:short_prepd_jid(Owner), - GenKey = jlib:short_prepd_bare_jid(Owner), +-spec(get_entity_subscriptions/2 :: + ( + Host :: hostPubsub(), + JID :: jidEntity()) + -> {'result', [] + | [{Node :: pubsubNode(), + Subscription :: subscription(), + SubId :: subId(), + Entity :: fullUsr()}]} + ). + +get_entity_subscriptions(Host, #jid{node = U, domain = S, resource = R} = _JID) -> + SubKey = {U,S,R}, + GenKey = {U,S,undefined}, States = case SubKey of - GenKey -> mnesia:match_object( - #pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); - _ -> mnesia:match_object( - #pubsub_state{stateid = {GenKey, '_'}, _ = '_'}) - ++ mnesia:match_object( - #pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) - end, - NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of - [{nodetree, N}] -> N; - _ -> nodetree_tree - end, - Reply = lists:foldl(fun(#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {Host, _}} = Node -> - lists:foldl(fun({Sub, SubId}, Acc2) -> - [{Node, Sub, SubId, J} | Acc2]; - (S, Acc2) -> - [{Node, S, J} | Acc2] - end, Acc, Ss); - _ -> Acc - end - end, [], States), + GenKey -> + mnesia:match_object(#pubsub_state{id = {{U, S, '_'}, '_'}, _ = '_'}); + _ -> + mnesia:match_object(#pubsub_state{id = {GenKey, '_'}, _ = '_'}) + ++ + mnesia:match_object(#pubsub_state{id = {SubKey, '_'}, _ = '_'}) + end, + NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, 'config'), 'nodetree') of + [{'nodetree', Tree}] -> Tree; + _ -> 'nodetree_tree' + end, + Reply = lists:foldl(fun + (#pubsub_state{id = {Entity, NodeIdx}, subscriptions = Subscriptions}, Acc) -> + case NodeTree:get_node(NodeIdx) of + #pubsub_node{id = {Host, _}} = Node -> + lists:foldl(fun + ({Subscription, SubId}, Acc2) -> [{Node, Subscription, SubId, Entity} | Acc2] + %(Subscriptions, Acc2) -> [{Node, Subscription, Entity} | Acc2] + end, Acc, Subscriptions); + _ -> Acc + end + end, [], States), {result, Reply}. -get_node_subscriptions(NodeId) -> - {result, States} = get_states(NodeId), - Tr = fun(#pubsub_state{stateid = {J, _}, subscriptions = Subscriptions}) -> - %% TODO: get rid of cases to handle non-list subscriptions - case Subscriptions of - [_|_] -> - lists:foldl(fun({S, SubId}, Acc) -> - [{J, S, SubId} | Acc]; - (S, Acc) -> - [{J, S} | Acc] - end, [], Subscriptions); - [] -> - []; - _ -> - [{J, none}] - end - end, - {result, lists:flatmap(Tr, States)}. - -get_subscriptions(NodeId, Owner) -> - SubKey = jlib:short_prepd_jid(Owner), - SubState = get_state(NodeId, SubKey), - {result, SubState#pubsub_state.subscriptions}. - -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - SubKey = jlib:short_prepd_jid(Owner), - SubState = get_state(NodeId, SubKey), - case {SubId, SubState#pubsub_state.subscriptions} of + +-spec(get_node_subscriptions/1 :: + ( + NodeIdx :: nodeIdx()) + -> {'result', [] + | [{Entity::fullUsr(), 'none'}] + %| [{Entity::fullUsr(), Subscription::subscription()}] %% still useful case ? + | [{Entity::fullUsr(), Subscription::subscription(), SubId::subId()}]} + ). + +get_node_subscriptions(NodeIdx) -> + {result, States} = get_states(NodeIdx), + Fun = fun(#pubsub_state{id = {Entity, _}, subscriptions = Subscriptions}) -> + [{Entity, Subscription, SubId} || {Subscription, SubId} <- Subscriptions] + end, + {result, lists:flatmap(Fun, States)}. + + +-spec(get_subscriptions/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', Subscriptions :: [] | [{Subscription::subscription(), SubId::subId()}]} + ). + +get_subscriptions(NodeIdx, #jid{node = U, domain = S, resource = R} = _JID) -> + #pubsub_state{subscriptions = Subscriptions} = get_state(NodeIdx, _SubKey = {U,S,R}), + {result, Subscriptions}. + + +-spec(set_subscriptions/4 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Subscription :: subscription(), + SubId :: subId()) + -> 'ok' + | {Subscription::subscription(), SubId::subId()} + | {error, _} + ). + +set_subscriptions(NodeIdx, #jid{node = U, domain = S, resource = R} = JID, Subscription, SubId) -> + SubKey = {U,S,R}, + SubState = #pubsub_state{subscriptions = Subscriptions} = get_state(NodeIdx, SubKey), + case {SubId, Subscriptions} of {_, []} -> case Subscription of - none -> {error, ?ERR_EXTENDED('bad_request', "not-subscribed")}; - _ -> new_subscription(NodeId, Owner, Subscription, SubState) + 'none' -> {'error', ?ERR_EXTENDED('bad_request', "not-subscribed")}; + _ -> new_subscription(NodeIdx, JID, Subscription, SubState) end; - {"", [{_, SID}]} -> + {<<>>, [{_, OtherSubId}]} -> case Subscription of - none -> unsub_with_subid(NodeId, SID, SubState); - _ -> replace_subscription({Subscription, SID}, SubState) + 'none' -> unsub_with_subid(NodeIdx, OtherSubId, SubState); + _ -> replace_subscription({Subscription, OtherSubId}, SubState) end; - {"", [_|_]} -> + {<<>>, [_|_]} -> {error, ?ERR_EXTENDED('bad_request', "subid-required")}; _ -> case Subscription of - none -> unsub_with_subid(NodeId, SubId, SubState); - _ -> replace_subscription({Subscription, SubId}, SubState) + 'none' -> unsub_with_subid(NodeIdx, SubId, SubState); + _ -> replace_subscription({Subscription, SubId}, SubState) end end. -replace_subscription(NewSub, SubState) -> - NewSubs = replace_subscription(NewSub, - SubState#pubsub_state.subscriptions, []), - set_state(SubState#pubsub_state{subscriptions = NewSubs}). +-spec(replace_subscription/2 :: + ( + NewSubscription :: {Subscription::subscription(), SubId::subId()}, + SubState :: pubsubState()) + -> 'ok' | {error, 'internal-server-error'} + ). + +replace_subscription(NewSubcription, #pubsub_state{subscriptions = Subscriptions} = SubState) -> + NewSubcriptions = replace_subscription(NewSubcription, Subscriptions, []), + set_state(SubState#pubsub_state{subscriptions = NewSubcriptions}). + + +-spec(replace_subscription/3 :: + ( + NewSubscription :: {Subscription::subscription(), SubId::subId()}, + Subscriptions :: [{Subscription::subscription(), SubId::subId()}], + Acc :: [] | [{Subscription::subscription(), SubId::subId()}]) + -> NewSubscriptions :: [] | [{Subscription::subscription(), SubId::subId()}] + ). +%% TODO : add clause case in -spec replace_subscription(_, [], Acc) -> Acc; -replace_subscription({Sub, SubId}, [{_, SubID} | T], Acc) -> - replace_subscription({Sub, SubId}, T, [{Sub, SubID} | Acc]). +replace_subscription({Subcription, SubId}, [{_, SubId} | OtherSubcriptions], Acc) -> + replace_subscription({Subcription, SubId}, OtherSubcriptions, [{Subcription, SubId} | Acc]). -new_subscription(NodeId, Owner, Subscription, SubState) -> - SubId = pubsub_subscription:add_subscription(Owner, NodeId, []), - Subscriptions = SubState#pubsub_state.subscriptions, + +-spec(new_subscription/4 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Subscriptions :: subscription(), + SubState :: pubsubState()) + -> {Subscription::subscription(), SubId::subId()} + ). + +new_subscription(NodeIdx, #jid{node = U, domain = S, resource = R} = _JID, Subscription, #pubsub_state{subscriptions = Subscriptions} = SubState) -> + SubId = pubsub_subscription:add_subscription({U,S,R}, NodeIdx, []), set_state(SubState#pubsub_state{subscriptions = [{Subscription, SubId} | Subscriptions]}), {Subscription, SubId}. -unsub_with_subid(NodeId, SubId, SubState) -> - pubsub_subscription:delete_subscription(SubState#pubsub_state.stateid, - NodeId, SubId), - NewSubs = lists:filter(fun ({_, SID}) -> SubId =/= SID end, - SubState#pubsub_state.subscriptions), - case {NewSubs, SubState#pubsub_state.affiliation} of - {[], none} -> - del_state(NodeId, element(1, SubState#pubsub_state.stateid)); - _ -> - set_state(SubState#pubsub_state{subscriptions = NewSubs}) + +-spec(unsub_with_subid/3 :: + ( + NodeIdx :: nodeIdx(), + SubId :: subId(), + SubState :: pubsubState()) + -> 'ok' | {'error', 'internal-server-error'} + ). + +unsub_with_subid(NodeIdx, SubId, #pubsub_state{id = {Entity, _}} = SubState) -> + pubsub_subscription:delete_subscription(Entity, NodeIdx, SubId), + NewSubcriptions = lists:filter(fun + ({_, SID}) -> SubId =/= SID + end, SubState#pubsub_state.subscriptions), + case {NewSubcriptions, SubState#pubsub_state.affiliation} of + {[], 'none'} -> del_state(NodeIdx, Entity); + _ -> set_state(SubState#pubsub_state{subscriptions = NewSubcriptions}) end. + %% @spec (Host, Owner) -> {result, [Node]} | {error, Reason} %% Host = host() %% Owner = jid() -%% Node = pubsubNode() +%% Node = node() %% @doc <p>Returns a list of Owner's nodes on Host with pending %% subscriptions.</p> -get_pending_nodes(Host, Owner) -> - GenKey = jlib:short_prepd_bare_jid(Owner), - States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, - affiliation = owner, - _ = '_'}), - NodeIDs = [ID || #pubsub_state{stateid = {_, ID}} <- States], - NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of - [{nodetree, N}] -> N; - _ -> nodetree_tree +-spec(get_pending_nodes/2 :: + ( + Host :: hostPubsub(), + JID :: jidEntity()) + -> 'false' | {'value', NodeId::nodeId()} + ). + +get_pending_nodes(Host, #jid{node = U, domain = S} = _JID) -> + States = mnesia:match_object( + #pubsub_state{id = {{U,S,undefined}, '_'}, affiliation = 'owner', _ = '_'}), + NodeIdxs = [NodeIdx || #pubsub_state{id = {_, NodeIdx}} <- States], + NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, 'config'), 'nodetree') of + [{'nodetree', Tree}] -> Tree; + _ -> 'nodetree_tree' end, - Reply = mnesia:foldl(fun(#pubsub_state{stateid = {_, NID}} = S, Acc) -> - case lists:member(NID, NodeIDs) of - true -> - case get_nodes_helper(NodeTree, S) of - {value, Node} -> [Node | Acc]; - false -> Acc - end; - false -> - Acc - end - end, [], pubsub_state), + Reply = mnesia:foldl(fun + (#pubsub_state{id = {_, NodeIdx}} = State, Acc) -> + case lists:member(NodeIdx, NodeIdxs) of + true -> + case get_nodes_helper(NodeTree, State) of + {value, NodeId} -> [NodeId | Acc]; + false -> Acc + end; + false -> Acc + end + end, [], pubsub_state), {result, Reply}. -get_nodes_helper(NodeTree, - #pubsub_state{stateid = {_, N}, subscriptions = Subs}) -> - HasPending = fun ({pending, _}) -> true; - (pending) -> true; - (_) -> false - end, - case lists:any(HasPending, Subs) of - true -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {_, Node}} -> - {value, Node}; - _ -> - false - end; - false -> - false - end. + +-spec(get_nodes_helper/2 :: + ( + NodeTree :: atom(), + State :: pubsubState()) + -> 'false' | {'value', NodeId::nodeId()} + ). + +get_nodes_helper(NodeTree, #pubsub_state{id = {_, NodeIdx}, subscriptions = Subscriptions}) -> + HasPending = fun + ({'pending', _}) -> 'true'; + %('pending') -> 'true'; %% Not useful anymore + (_) -> 'false' + end, +case lists:any(HasPending, Subscriptions) of + true -> + case NodeTree:get_node(NodeIdx) of + #pubsub_node{id = {_, NodeId}} -> {value, NodeId}; + _ -> false + end; + false -> false +end. %% @spec (NodeId) -> {result, [State] | []} -%% NodeId = mod_pubsub:pubsubNodeId() +%% NodeId = nodeidx() %% State = mod_pubsub:pubsubState() %% @doc Returns the list of stored states for a given node. %% <p>For the default PubSub module, states are stored in Mnesia database.</p> @@ -803,43 +1013,66 @@ get_nodes_helper(NodeTree, %% they can implement this function like this: %% ```get_states(NodeId) -> %% node_default:get_states(NodeId).'''</p> -get_states(NodeId) -> - States = case catch mnesia:match_object( - #pubsub_state{stateid = {'_', NodeId}, _ = '_'}) of - List when is_list(List) -> List; - _ -> [] - end, +-spec(get_states/1 :: + ( + NodeIdx :: nodeIdx()) + -> {'result', States :: [] | [State::pubsubState()]} + ). + +get_states(NodeIdx) -> + States = case + catch mnesia:match_object(#pubsub_state{id = {'_', NodeIdx}, _ = '_'}) + of + PubsubStates when is_list(PubsubStates) -> PubsubStates; %% is_list(PubsubStates) useful ? + _ -> [] + end, {result, States}. %% @spec (NodeId, JID) -> [State] | [] -%% NodeId = mod_pubsub:pubsubNodeId() -%% JID = mod_pubsub:jid() -%% State = mod_pubsub:pubsubItems() +%% NodeId = nodeidx() +%% JID = ljid() +%% State = mod_pubsub:pubsub_item() %% @doc <p>Returns a state (one state list), given its reference.</p> -get_state(NodeId, JID) -> - StateId = {JID, NodeId}, - case catch mnesia:read({pubsub_state, StateId}) of - [State] when is_record(State, pubsub_state) -> State; - _ -> #pubsub_state{stateid=StateId} +-spec(get_state/2 :: + ( + NodeIdx :: nodeIdx(), + Entity :: fullUsr()) + -> State::pubsubState() + ). + +get_state(NodeIdx, Entity) -> + case catch mnesia:read({pubsub_state, {Entity, NodeIdx}}) of + [#pubsub_state{} = State] -> State; + _ -> #pubsub_state{id = {Entity, NodeIdx}} end. %% @spec (State) -> ok | {error, Reason::stanzaError()} -%% State = mod_pubsub:pubsubStates() +%% State = mod_pubsub:pubsub_state() %% @doc <p>Write a state into database.</p> -set_state(State) when is_record(State, pubsub_state) -> - mnesia:write(State); -set_state(_) -> - {error, 'internal-server-error'}. +-spec(set_state/1 :: + ( + State :: pubsubState()) + -> 'ok' | {error, 'internal-server-error'} + ). +set_state(#pubsub_state{} = State) -> mnesia:write(State); +set_state(_) -> {error, 'internal-server-error'}. %% @spec (NodeId, JID) -> ok | {error, Reason::stanzaError()} -%% NodeId = mod_pubsub:pubsubNodeId() +%% NodeId = nodeidx() %% @doc <p>Delete a state from database.</p> -del_state(NodeId, JID) -> - mnesia:delete({pubsub_state, {JID, NodeId}}). +-spec(del_state/2 :: + ( + NodeIdx :: nodeIdx(), + Entity :: fullUsr()) + -> 'ok' + ). + +del_state(NodeIdx, Entity) -> + mnesia:delete({pubsub_state, {Entity, NodeIdx}}). %% @spec (NodeId, From) -> [Items] | [] -%% NodeId = mod_pubsub:pubsubNodeId() -%% Items = mod_pubsub:pubsubItems() +%% NodeId = nodeidx() +%% Items = mod_pubsub:pubsub_item() %% @doc Returns the list of stored items for a given node. %% <p>For the default PubSub module, items are stored in Mnesia database.</p> %% <p>We can consider that the pubsub_item table have been created by the main @@ -850,111 +1083,171 @@ del_state(NodeId, JID) -> %% they can implement this function like this: %% ```get_items(NodeId, From) -> %% node_default:get_items(NodeId, From).'''</p> -get_items(NodeId, _From) -> - Items = mnesia:match_object(#pubsub_item{itemid = {'_', NodeId}, _ = '_'}), +-spec(get_items/2 :: + ( + NodeIdx :: nodeIdx(), + Entity :: fullUsr()) + -> {'result', Items :: [] | [Item::pubsubItem()]} + ). + +get_items(NodeIdx, _Entity) -> + Items = mnesia:match_object(#pubsub_item{id = {'_', NodeIdx}, _ = '_'}), {result, lists:reverse(lists:keysort(#pubsub_item.modification, Items))}. -get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> - SubKey = jlib:short_prepd_jid(JID), - GenKey = jlib:short_prepd_bare_jid(JID), - GenState = get_state(NodeId, GenKey), - SubState = get_state(NodeId, SubKey), + + +-spec(get_items/6 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + AccessModel :: accessModel(), + PresenceSubscription :: boolean(), + RosterGroup :: boolean(), + SubId :: subId()) + -> {'result', Items :: [] | [Item::pubsubItem()]} + | {'error', _} + ). + +get_items(NodeIdx, #jid{node = U, domain = S, resource = R} = _JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> + SubKey = {U,S,R}, + GenKey = {U,S,undefined}, + GenState = get_state(NodeIdx, GenKey), + SubState = get_state(NodeIdx, SubKey), Affiliation = GenState#pubsub_state.affiliation, Subscriptions = SubState#pubsub_state.subscriptions, Whitelisted = can_fetch_item(Affiliation, Subscriptions), if %%SubId == "", ?? -> - %% Entity has multiple subscriptions to the node but does not specify a subscription ID - %{error, ?ERR_EXTENDED('bad-request', "subid-required")}; + %% Entity has multiple subscriptions to the node but does not specify a subscription ID + %{error, ?ERR_EXTENDED('bad-request', "subid-required")}; %%InvalidSubId -> - %% Entity is subscribed but specifies an invalid subscription ID - %{error, ?ERR_EXTENDED('not-acceptable', "invalid-subid")}; - Affiliation == outcast -> + %% Entity is subscribed but specifies an invalid subscription ID + %{error, ?ERR_EXTENDED('not-acceptable', "invalid-subid")}; + Affiliation == 'outcast' -> %% Requesting entity is blocked - {error, 'forbidden'}; - (AccessModel == presence) and (not PresenceSubscription) -> + {'error', 'forbidden'}; + (AccessModel == 'presence') and (not PresenceSubscription) -> %% Entity is not authorized to create a subscription (presence subscription required) - {error, ?ERR_EXTENDED('not-authorized', "presence-subscription-required")}; - (AccessModel == roster) and (not RosterGroup) -> + {'error', ?ERR_EXTENDED('not-authorized', "presence-subscription-required")}; + (AccessModel == 'roster') and (not RosterGroup) -> %% Entity is not authorized to create a subscription (not in roster group) - {error, ?ERR_EXTENDED('not-authorized', "not-in-roster-group")}; - (AccessModel == whitelist) and (not Whitelisted) -> + {'error', ?ERR_EXTENDED('not-authorized', "not-in-roster-group")}; + (AccessModel == 'whitelist') and (not Whitelisted) -> %% Node has whitelist access model and entity lacks required affiliation - {error, ?ERR_EXTENDED('not-allowed', "closed-node")}; - (AccessModel == authorize) and (not Whitelisted) -> + {'error', ?ERR_EXTENDED('not-allowed', "closed-node")}; + (AccessModel == 'authorize') and (not Whitelisted) -> %% Node has authorize access model - {error, 'forbidden'}; + {'error', 'forbidden'}; %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; true -> - get_items(NodeId, JID) + get_items(NodeIdx, {U,S,R}) end. %% @spec (NodeId, ItemId) -> [Item] | [] -%% NodeId = mod_pubsub:pubsubNodeId() -%% ItemId = string() -%% Item = mod_pubsub:pubsubItems() +%% NodeId = nodeidx() +%% ItemId = item() +%% Item = mod_pubsub:pubsub_item() %% @doc <p>Returns an item (one item list), given its reference.</p> -get_item(NodeId, ItemId) -> - case mnesia:read({pubsub_item, {ItemId, NodeId}}) of - [Item] when is_record(Item, pubsub_item) -> - {result, Item}; - _ -> - {error, 'item-not-found'} +-spec(get_item/2 :: + ( + NodeIdx :: nodeIdx(), + ItemId :: itemId()) + -> {'result', Item::pubsubItem()} | {'error', 'item-not-found'} + ). + +get_item(NodeIdx, ItemId) -> + case mnesia:read({pubsub_item, {ItemId, NodeIdx}}) of + [#pubsub_item{} = Item] -> {result, Item}; + _ -> {error, 'item-not-found'} end. -get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> - GenKey = jlib:short_prepd_bare_jid(JID), - GenState = get_state(NodeId, GenKey), + + +-spec(get_item/7 :: + ( + NodeIdx :: nodeIdx(), + ItemId :: itemId(), + JID :: jidEntity(), + AccessModel :: accessModel(), + PresenceSubscription :: boolean(), + RosterGroup :: boolean(), + SubId :: subId()) + -> {'result', Item::pubsubItem()} | {'error', 'item-not-found'} + ). + +get_item(NodeIdx, ItemId, #jid{node = U, domain = S} = _JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> + GenKey = {U,S,undefined}, + GenState = get_state(NodeIdx, GenKey), Affiliation = GenState#pubsub_state.affiliation, Subscriptions = GenState#pubsub_state.subscriptions, Whitelisted = can_fetch_item(Affiliation, Subscriptions), if %%SubId == "", ?? -> - %% Entity has multiple subscriptions to the node but does not specify a subscription ID - %{error, ?ERR_EXTENDED('bad-request', "subid-required")}; - %%InvalidSubID -> - %% Entity is subscribed but specifies an invalid subscription ID - %{error, ?ERR_EXTENDED('not-acceptable', "invalid-subid")}; - Affiliation == outcast -> + %% Entity has multiple subscriptions to the node but does not specify a subscription ID + %{error, ?ERR_EXTENDED('bad-request', "subid-required")}; + %%InvalidSubId -> + %% Entity is subscribed but specifies an invalid subscription ID + %{error, ?ERR_EXTENDED('not-acceptable', "invalid-subid")}; + Affiliation == 'outcast' -> %% Requesting entity is blocked - {error, 'forbidden'}; - (AccessModel == presence) and (not PresenceSubscription) -> + {'error', 'forbidden'}; + (AccessModel == 'presence') and (not PresenceSubscription) -> %% Entity is not authorized to create a subscription (presence subscription required) - {error, ?ERR_EXTENDED('not-authorized', "presence-subscription-required")}; - (AccessModel == roster) and (not RosterGroup) -> + {'error', ?ERR_EXTENDED('not-authorized', "presence-subscription-required")}; + (AccessModel == 'roster') and (not RosterGroup) -> %% Entity is not authorized to create a subscription (not in roster group) - {error, ?ERR_EXTENDED('not-authorized', "not-in-roster-group")}; - (AccessModel == whitelist) and (not Whitelisted) -> + {'error', ?ERR_EXTENDED('not-authorized', "not-in-roster-group")}; + (AccessModel == 'whitelist') and (not Whitelisted) -> %% Node has whitelist access model and entity lacks required affiliation - {error, ?ERR_EXTENDED('not-allowed', "closed-node")}; - (AccessModel == authorize) and (not Whitelisted) -> + {'error', ?ERR_EXTENDED('not-allowed', "closed-node")}; + (AccessModel == 'authorize') and (not Whitelisted) -> %% Node has authorize access model - {error, 'forbidden'}; + {'error', 'forbidden'}; %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; true -> - get_item(NodeId, ItemId) + get_item(NodeIdx, ItemId) end. %% @spec (Item) -> ok | {error, Reason::stanzaError()} -%% Item = mod_pubsub:pubsubItems() +%% Item = mod_pubsub:pubsub_item() %% @doc <p>Write an item into database.</p> -set_item(Item) when is_record(Item, pubsub_item) -> - mnesia:write(Item); -set_item(_) -> - {error, 'internal-server-error'}. +-spec(set_item/1 :: + ( + Item :: pubsubItem()) + -> 'ok' | {error, 'internal-server-error'} + ). + +set_item(#pubsub_item{} = Item) -> mnesia:write(Item); +set_item(_) -> {error, 'internal-server-error'}. %% @spec (NodeId, ItemId) -> ok | {error, Reason::stanzaError()} -%% NodeId = mod_pubsub:pubsubNodeId() -%% ItemId = string() +%% NodeId = nodeidx() +%% ItemId = item() %% @doc <p>Delete an item from database.</p> -del_item(NodeId, ItemId) -> - mnesia:delete({pubsub_item, {ItemId, NodeId}}). -del_items(NodeId, ItemIds) -> +-spec(del_item/2 :: + ( + NodeIdx :: nodeIdx(), + ItemId :: itemId()) + -> 'ok' + ). + +del_item(NodeIdx, ItemId) -> + mnesia:delete({pubsub_item, {ItemId, NodeIdx}}). + + +-spec(del_items/2 :: + ( + NodeIdx :: nodeIdx(), + ItemIds :: [itemId()]) + -> 'ok' + ). + +del_items(NodeIdx, ItemIds) -> lists:foreach(fun(ItemId) -> - del_item(NodeId, ItemId) - end, ItemIds). + del_item(NodeIdx, ItemId) + end, ItemIds). %% @doc <p>Return the name of the node if known: Default is to return %% node id.</p> @@ -968,12 +1261,12 @@ path_to_node([]) -> <<>>; path_to_node(Path) -> case Path of - % default slot - [Node] -> Node; - % handle old possible entries, used when migrating database content to new format - [Node|_] when is_list(Node) -> list_to_binary(string:join([""|Path], "/")); - % default case (used by PEP for example) - _ -> list_to_binary(Path) + % default slot + [Node] -> Node; + % handle old possible entries, used when migrating database content to new format + [Node|_] when is_list(Node) -> list_to_binary(string:join([""|Path], "/")); + % default case (used by PEP for example) + _ -> list_to_binary(Path) end. %% @spec (Affiliation, Subscription) -> true | false @@ -981,24 +1274,45 @@ path_to_node(Path) -> %% Subscription = subscribed | none %% @doc Determines if the combination of Affiliation and Subscribed %% are allowed to get items from a node. -can_fetch_item(owner, _) -> true; -can_fetch_item(member, _) -> true; -can_fetch_item(publisher, _) -> true; -can_fetch_item(outcast, _) -> false; -can_fetch_item(none, Subscriptions) -> is_subscribed(Subscriptions); +-spec(can_fetch_item/2 :: + ( + Affiliation :: affiliation(), + Subscriptions :: [{subscription(), subId()}]) + -> CanFetchItem::boolean() + ). +%% TODO : add 'publish-only' case +can_fetch_item('owner', _) -> true; +can_fetch_item('member', _) -> true; +can_fetch_item('publisher',_) -> true; +can_fetch_item('outcast', _) -> false; +can_fetch_item('none', Subscriptions) -> is_subscribed(Subscriptions); can_fetch_item(_Affiliation, _Subscription) -> false. + +-spec(is_subscribed/1 :: + ( + Subscriptions :: [{Subscription::subscription(), SubId::subId()}]) + -> IsSubscribed::boolean() + ). + is_subscribed(Subscriptions) -> - lists:any(fun ({subscribed, _SubId}) -> true; - (_) -> false - end, Subscriptions). + lists:any(fun + ({'subscribed', _SubId}) -> true; + (_) -> false + end, Subscriptions). + %% Returns the first item where Pred() is true in List -first_in_list(_Pred, []) -> - false; -first_in_list(Pred, [H | T]) -> - case Pred(H) of - true -> {value, H}; - _ -> first_in_list(Pred, T) - end. +-spec(first_in_list/2 :: + ( + Predicate :: fun(), + Subscriptions :: [{Subscription::subscription(), SubId::subId()}]) + -> 'false' | {'value', {Subscription::subscription(), SubId::subId()}} + ). +first_in_list(_Predicate, []) -> false; +first_in_list(Predicate, [Subscription | OtherSubscriptions]) -> + case Predicate(Subscription) of + true -> {'value', Subscription}; + _ -> first_in_list(Predicate, OtherSubscriptions) + end. diff --git a/src/mod_pubsub/node_flat_odbc.erl b/src/mod_pubsub/node_flat_odbc.erl index 2a15af325..fa249df69 100644 --- a/src/mod_pubsub/node_flat_odbc.erl +++ b/src/mod_pubsub/node_flat_odbc.erl @@ -37,12 +37,11 @@ %%% development is still a work in progress. However, the system is already %%% useable and useful as is. Please, send us comments, feedback and %%% improvements.</p> - +%%TODO : fix SQL requests with nodeid/id and id/idx changes -module(node_flat_odbc). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). --include_lib("exmpp/include/exmpp.hrl"). -include("jlib.hrl"). %% for rsm_in and rsm_out records definitions -define(PUBSUB, mod_pubsub_odbc). @@ -191,9 +190,9 @@ features() -> %% @spec (Host, ServerHost, Node, ParentNode, Owner, Access) -> bool() %% Host = mod_pubsub:host() %% ServerHost = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% ParentNode = mod_pubsub:pubsubNode() -%% Owner = mod_pubsub:jid() +%% Node = mod_pubsub:node() +%% ParentNode = mod_pubsub:node() +%% Owner = ljid() %% Access = all | atom() %% @doc Checks if the current user has the permission to create the requested node %% <p>In {@link node_default}, the permission is decided by the place in the @@ -212,34 +211,27 @@ create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> %% @spec (NodeId, Owner) -> %% {result, Result} | exit -%% NodeId = mod_pubsub:pubsubNodeId() -%% Owner = mod_pubsub:jid() +%% NodeId = nodeidx() +%% Owner = ljid() %% @doc <p></p> create_node(NodeId, Owner) -> OwnerKey = jlib:short_prepd_bare_jid(Owner), - State = #pubsub_state{stateid = {OwnerKey, NodeId}, affiliation = owner}, + State = #pubsub_state{id = {OwnerKey, NodeId}, affiliation = owner}, catch ejabberd_odbc:sql_query_t( ["insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " "values(", state_to_raw(NodeId, State), ");"]), {result, {default, broadcast}}. %% @spec (Removed) -> ok -%% Removed = [mod_pubsub:pubsubNode()] +%% Removed = [mod_pubsub:node()] %% @doc <p>purge items of deleted nodes after effective deletion.</p> delete_node(Removed) -> -%% pablo: TODO, this is present on trunk/node_flat but not on trunk/node_flat_odbc. -%% check what is the desired behaviour -%% Tr = fun(#pubsub_state{stateid = {J, _}, subscriptions = Ss}) -> -%% lists:map(fun(S) -> -%% {J, S} -%% end, Ss) -%% end, Reply = lists:map( - fun(#pubsub_node{id = NodeId} = PubsubNode) -> + fun(#pubsub_node{idx = Nidx} = PubsubNode) -> Subscriptions = case catch ejabberd_odbc:sql_query_t( ["select jid, subscriptions " "from pubsub_state " - "where nodeid='", NodeId, ";"]) of + "where nodeid='", Nidx, ";"]) of {selected, ["jid", "subscriptions"], RItems} -> lists:map(fun({SJID, Subscriptions}) -> {decode_jid(SJID), decode_subscriptions(Subscriptions)} @@ -345,9 +337,9 @@ subscribe_node(NodeId, Sender, Subscriber, AccessModel, %% @spec (NodeId, Sender, Subscriber, SubId) -> %% {error, Reason} | {result, []} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Sender = mod_pubsub:jid() -%% Subscriber = mod_pubsub:jid() +%% NodeId = nodeidx() +%% Sender = ljid() +%% Subscriber = ljid() %% SubId = mod_pubsub:subid() %% Reason = mod_pubsub:stanzaError() %% @doc <p>Unsubscribe the <tt>Subscriber</tt> from the <tt>Node</tt>.</p> @@ -417,11 +409,11 @@ delete_subscription(SubKey, NodeId, {Subscription, SubId}, Affiliation, Subscrip %% @spec (NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% {true, PubsubItem} | {result, Reply} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Publisher = mod_pubsub:jid() +%% NodeId = nodeidx() +%% Publisher = ljid() %% PublishModel = atom() %% MaxItems = integer() -%% ItemId = string() +%% ItemId = item() %% Payload = term() %% @doc <p>Publishes the item passed as parameter.</p> %% <p>The mechanism works as follow: @@ -474,7 +466,7 @@ publish_item(NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% Note: this works cause set_item tries an update before %% the insert, and the update just ignore creation field. PubId = {now(), SubKey}, - set_item(#pubsub_item{itemid = {ItemId, NodeId}, + set_item(#pubsub_item{id = {ItemId, NodeId}, creation = {now(), GenKey}, modification = PubId, payload = Payload}), @@ -488,10 +480,10 @@ publish_item(NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) -> end. %% @spec (NodeId, MaxItems, ItemIds) -> {NewItemIds,OldItemIds} -%% NodeId = mod_pubsub:pubsubNodeId() +%% NodeId = nodeidx() %% MaxItems = integer() | unlimited -%% ItemIds = [ItemId::string()] -%% NewItemIds = [ItemId::string()] +%% ItemIds = [item()] +%% NewItemIds = [item()] %% @doc <p>This function is used to remove extra items, most notably when the %% maximum number of items has been reached.</p> %% <p>This function is used internally by the core PubSub module, as no @@ -515,10 +507,10 @@ remove_extra_items(NodeId, MaxItems, ItemIds) -> %% @spec (NodeId, Publisher, PublishModel, ItemId) -> %% {error, Reason::stanzaError()} | %% {result, []} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Publisher = mod_pubsub:jid() +%% NodeId = nodeidx() +%% Publisher = ljid() %% PublishModel = atom() -%% ItemId = string() +%% ItemId = item() %% @doc <p>Triggers item deletion.</p> %% <p>Default plugin: The user performing the deletion must be the node owner %% or a publisher, or PublishModel being open.</p> @@ -549,8 +541,8 @@ delete_item(NodeId, Publisher, PublishModel, ItemId) -> %% @spec (NodeId, Owner) -> %% {error, Reason::stanzaError()} | %% {result, {default, broadcast}} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Owner = mod_pubsub:jid() +%% NodeId = nodeidx() +%% Owner = ljid() purge_node(NodeId, Owner) -> GenKey = jlib:short_prepd_bare_jid(Owner), GenState = get_state(NodeId, GenKey), @@ -569,7 +561,7 @@ purge_node(NodeId, Owner) -> %% @spec (Host, JID) -> [{Node,Affiliation}] %% Host = host() -%% JID = mod_pubsub:jid() +%% JID = ljid() %% @doc <p>Return the current affiliations for the given user</p> %% <p>The default module reads affiliations in the main Mnesia %% <tt>pubsub_state</tt> table. If a plugin stores its data in the same @@ -632,7 +624,7 @@ set_affiliation(NodeId, Owner, Affiliation) when ?IS_JID(Owner)-> %% @spec (Host, Owner) -> [{Node,Subscription}] %% Host = host() -%% Owner = mod_pubsub:jid() +%% Owner = ljid() %% @doc <p>Return the current subscriptions for the given user</p> %% <p>The default module reads subscriptions in the main Mnesia %% <tt>pubsub_state</tt> table. If a plugin stores its data in the same @@ -664,13 +656,13 @@ get_entity_subscriptions(Host, Owner) -> {selected, ["node", "type", "nodeid", "jid", "subscriptions"], RItems} -> lists:foldl(fun({N, T, I, J, S}, Acc) -> Node = nodetree_tree_odbc:raw_to_node(Host, {N, "", T, I}), - Jid = decode_jid(J), + JID = decode_jid(J), case decode_subscriptions(S) of [] -> - [{Node, none, Jid}|Acc]; + [{Node, none, JID}|Acc]; Subs -> - lists:foldl(fun({Sub, SubId}, Acc2) -> [{Node, Sub, SubId, Jid}|Acc2]; - (Sub, Acc2) -> [{Node, Sub, Jid}|Acc2] + lists:foldl(fun({Sub, SubId}, Acc2) -> [{Node, Sub, SubId, JID}|Acc2]; + (Sub, Acc2) -> [{Node, Sub, JID}|Acc2] end, Acc, Subs) end end, [], RItems); @@ -707,13 +699,13 @@ get_entity_subscriptions_for_send_last(Host, Owner) -> {selected, ["node", "type", "nodeid", "jid", "subscriptions"], RItems} -> lists:foldl(fun({N, T, I, J, S}, Acc) -> Node = nodetree_tree_odbc:raw_to_node(Host, {N, "", T, I}), - Jid = decode_jid(J), + JID = decode_jid(J), case decode_subscriptions(S) of [] -> - [{Node, none, Jid}|Acc]; + [{Node, none, JID}|Acc]; Subs -> - lists:foldl(fun({Sub, SubId}, Acc2) -> [{Node, Sub, SubId, Jid}|Acc2]; - (Sub, Acc2) -> [{Node, Sub, Jid}|Acc2] + lists:foldl(fun({Sub, SubId}, Acc2) -> [{Node, Sub, SubId, JID}|Acc2]; + (Sub, Acc2) -> [{Node, Sub, JID}|Acc2] end, Acc, Subs) end end, [], RItems); @@ -729,13 +721,13 @@ get_node_subscriptions(NodeId) -> "where nodeid='", NodeId, "';"]) of {selected, ["jid", "subscriptions"], RItems} -> lists:foldl(fun({J, S}, Acc) -> - Jid = decode_jid(J), + JID = decode_jid(J), case decode_subscriptions(S) of [] -> - [{Jid, none}|Acc]; + [{JID, none}|Acc]; Subs -> - lists:foldl(fun({Sub, SubId}, Acc2) -> [{Jid, Sub, SubId}|Acc2]; - (Sub, Acc2) -> [{Jid, Sub}|Acc2] + lists:foldl(fun({Sub, SubId}, Acc2) -> [{JID, Sub, SubId}|Acc2]; + (Sub, Acc2) -> [{JID, Sub}|Acc2] end, Acc, Subs) end end, [], RItems); @@ -786,8 +778,8 @@ replace_subscription(NewSub, SubState) -> replace_subscription(_, [], Acc) -> Acc; -replace_subscription({Sub, SubId}, [{_, SubID} | T], Acc) -> - replace_subscription({Sub, SubId}, T, [{Sub, SubID} | Acc]). +replace_subscription({Sub, SubId}, [{_, SubId} | T], Acc) -> + replace_subscription({Sub, SubId}, T, [{Sub, SubId} | Acc]). new_subscription(NodeId, Owner, Subscription, SubState) -> case pubsub_subscription_odbc:subscribe_node(Owner, NodeId, []) of @@ -800,13 +792,13 @@ new_subscription(NodeId, Owner, Subscription, SubState) -> end. unsub_with_subid(NodeId, SubId, SubState) -> - pubsub_subscription_odbc:unsubscribe_node(SubState#pubsub_state.stateid, + pubsub_subscription_odbc:unsubscribe_node(SubState#pubsub_state.id, NodeId, SubId), NewSubs = lists:filter(fun ({_, SID}) -> SubId =/= SID end, SubState#pubsub_state.subscriptions), case {NewSubs, SubState#pubsub_state.affiliation} of {[], none} -> - del_state(NodeId, element(1, SubState#pubsub_state.stateid)); + del_state(NodeId, element(1, SubState#pubsub_state.id)); _ -> set_state(SubState#pubsub_state{subscriptions = NewSubs}) end. @@ -814,21 +806,21 @@ unsub_with_subid(NodeId, SubId, SubState) -> %% @spec (Host, Owner) -> {result, [Node]} | {error, Reason} %% Host = host() %% Owner = jid() -%% Node = pubsubNode() +%% Node = node() %% @doc <p>Returns a list of Owner's nodes on Host with pending %% subscriptions.</p> get_pending_nodes(Host, Owner) -> GenKey = jlib:short_prepd_bare_jid(Owner), - States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, + States = mnesia:match_object(#pubsub_state{id = {GenKey, '_'}, affiliation = owner, _ = '_'}), - NodeIDs = [ID || #pubsub_state{stateid = {_, ID}} <- States], + Nidxs = [Nidx || #pubsub_state{id = {_, Nidx}} <- States], NodeTree = case catch ets:lookup(gen_mod:get_module_proc(Host, config), nodetree) of [{nodetree, N}] -> N; _ -> nodetree_tree_odbc end, - Reply = mnesia:foldl(fun(#pubsub_state{stateid = {_, NID}} = S, Acc) -> - case lists:member(NID, NodeIDs) of + Reply = mnesia:foldl(fun(#pubsub_state{id = {_, Nidx}} = S, Acc) -> + case lists:member(Nidx, Nidxs) of true -> case get_nodes_helper(NodeTree, S) of {value, Node} -> [Node | Acc]; @@ -841,7 +833,7 @@ get_pending_nodes(Host, Owner) -> {result, Reply}. get_nodes_helper(NodeTree, - #pubsub_state{stateid = {_, N}, subscriptions = Subs}) -> + #pubsub_state{id = {_, N}, subscriptions = Subs}) -> HasPending = fun ({pending, _}) -> true; (pending) -> true; (_) -> false @@ -849,7 +841,7 @@ get_nodes_helper(NodeTree, case lists:any(HasPending, Subs) of true -> case NodeTree:get_node(N) of - #pubsub_node{nodeid = {_, Node}} -> + #pubsub_node{id = {_, Node}} -> {value, Node}; _ -> false @@ -859,7 +851,7 @@ get_nodes_helper(NodeTree, end. %% @spec (NodeId) -> {result, [State] | []} -%% NodeId = mod_pubsub:pubsubNodeId() +%% NodeId = nodeidx() %% State = mod_pubsub:pubsubState() %% @doc Returns the list of stored states for a given node. %% <p>For the default PubSub module, states are stored in Mnesia database.</p> @@ -878,7 +870,7 @@ get_states(NodeId) -> "where nodeid='", NodeId, "';"]) of {selected, ["jid", "affiliation", "subscriptions"], RItems} -> {result, lists:map(fun({SJID, Affiliation, Subscriptions}) -> - #pubsub_state{stateid = {decode_jid(SJID), NodeId}, + #pubsub_state{id = {decode_jid(SJID), NodeId}, items = itemids(NodeId, SJID), affiliation = decode_affiliation(Affiliation), subscriptions = decode_subscriptions(Subscriptions)} @@ -889,13 +881,13 @@ get_states(NodeId) -> %% @spec (NodeId, JID) -> [State] | [] -%% NodeId = mod_pubsub:pubsubNodeId() -%% JID = mod_pubsub:jid() -%% State = mod_pubsub:pubsubItems() +%% NodeId = nodeidx() +%% JID = ljid() +%% State = mod_pubsub:pubsub_state() %% @doc <p>Returns a state (one state list), given its reference.</p> get_state(NodeId, JID) -> State = get_state_without_itemids(NodeId, JID), - {SJID, _} = State#pubsub_state.stateid, + {SJID, _} = State#pubsub_state.id, State#pubsub_state{items = itemids(NodeId, SJID)}. get_state_without_itemids(NodeId, JID) -> J = encode_jid(JID), @@ -905,25 +897,25 @@ get_state_without_itemids(NodeId, JID) -> "where jid='", J, "' " "and nodeid='", NodeId, "';"]) of {selected, ["jid", "affiliation", "subscriptions"], [{SJID, Affiliation, Subscriptions}]} -> - #pubsub_state{stateid = {decode_jid(SJID), NodeId}, + #pubsub_state{id = {decode_jid(SJID), NodeId}, affiliation = decode_affiliation(Affiliation), subscriptions = decode_subscriptions(Subscriptions)}; _ -> - #pubsub_state{stateid={JID, NodeId}} + #pubsub_state{id={JID, NodeId}} end. %% @spec (State) -> ok | {error, Reason::stanzaError()} %% State = mod_pubsub:pubsubStates() %% @doc <p>Write a state into database.</p> set_state(State) when is_record(State, pubsub_state) -> - {_, NodeId} = State#pubsub_state.stateid, + {_, NodeId} = State#pubsub_state.id, set_state(NodeId, State). set_state(NodeId, State) -> %% NOTE: in odbc version, as we do not handle item list, %% we just need to update affiliation and subscription %% cause {JID,NodeId} is the key. if it does not exists, then we insert it. %% MySQL can be optimized using INSERT ... ON DUPLICATE KEY as well - {JID, _} = State#pubsub_state.stateid, + {JID, _} = State#pubsub_state.id, J = encode_jid(JID), S = encode_subscriptions(State#pubsub_state.subscriptions), A = encode_affiliation(State#pubsub_state.affiliation), @@ -941,7 +933,7 @@ set_state(NodeId, State) -> {result, []}. %% @spec (NodeId, JID) -> ok | {error, Reason::stanzaError()} -%% NodeId = mod_pubsub:pubsubNodeId() +%% NodeId = nodeidx() %% @doc <p>Delete a state from database.</p> del_state(NodeId, JID) -> J = encode_jid(JID), @@ -952,8 +944,8 @@ del_state(NodeId, JID) -> ok. %% @spec (NodeId, From) -> {[Items], RsmOut} | [] -%% NodeId = mod_pubsub:pubsubNodeId() -%% Items = mod_pubsub:pubsubItems() +%% NodeId = nodeidx() +%% Items = mod_pubsub:pubsub_item() %% @doc Returns the list of stored items for a given node. %% <p>For the default PubSub module, items are stored in Mnesia database.</p> %% <p>We can consider that the pubsub_item table have been created by the main @@ -1100,9 +1092,9 @@ get_last_items(NodeId, _From, Count) -> end. %% @spec (NodeId, ItemId) -> [Item] | [] -%% NodeId = mod_pubsub:pubsubNodeId() -%% ItemId = string() -%% Item = mod_pubsub:pubsubItems() +%% NodeId = nodeidx() +%% ItemId = item() +%% Item = mod_pubsub:pubsub_item() %% @doc <p>Returns an item (one item list), given its reference.</p> get_item(NodeId, ItemId) -> I = ?PUBSUB:escape(ItemId), @@ -1126,7 +1118,7 @@ get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _S %%SubId == "", ?? -> %% Entity has multiple subscriptions to the node but does not specify a subscription ID %{error, ?ERR_EXTENDED('bad-request', "subid-required")}; - %%InvalidSubID -> + %%InvalidSubId -> %% Entity is subscribed but specifies an invalid subscription ID %{error, ?ERR_EXTENDED('not-acceptable', "invalid-subid")}; Affiliation == outcast -> @@ -1152,10 +1144,10 @@ get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _S end. %% @spec (Item) -> ok | {error, Reason::stanzaError()} -%% Item = mod_pubsub:pubsubItems() +%% Item = mod_pubsub:pubsub_item() %% @doc <p>Write an item into database.</p> set_item(Item) -> - {ItemId, NodeId} = Item#pubsub_item.itemid, + {ItemId, NodeId} = Item#pubsub_item.id, I = ?PUBSUB:escape(ItemId), {C, _} = Item#pubsub_item.creation, {M, JID} = Item#pubsub_item.modification, @@ -1182,8 +1174,8 @@ set_item(Item) -> {result, []}. %% @spec (NodeId, ItemId) -> ok | {error, Reason::stanzaError()} -%% NodeId = mod_pubsub:pubsubNodeId() -%% ItemId = string() +%% NodeId = nodeidx() +%% ItemId = item() %% @doc <p>Delete an item from database.</p> del_item(NodeId, ItemId) -> I = ?PUBSUB:escape(ItemId), @@ -1337,7 +1329,7 @@ encode_subscriptions(Subscriptions) -> %%% record getter/setter state_to_raw(NodeId, State) -> - {JID, _} = State#pubsub_state.stateid, + {JID, _} = State#pubsub_state.id, J = encode_jid(JID), A = encode_affiliation(State#pubsub_state.affiliation), S = encode_subscriptions(State#pubsub_state.subscriptions), @@ -1353,7 +1345,7 @@ raw_to_item(NodeId, {ItemId, SJID, Creation, Modification, XML}) -> {error, _Reason} -> []; [El] -> [El] end, - #pubsub_item{itemid = {ItemId, NodeId}, + #pubsub_item{id = {ItemId, NodeId}, creation={ToTime(Creation), JID}, modification={ToTime(Modification), JID}, payload = Payload}. diff --git a/src/mod_pubsub/node_hometree.erl b/src/mod_pubsub/node_hometree.erl index 069f38599..901e6cc72 100644 --- a/src/mod_pubsub/node_hometree.erl +++ b/src/mod_pubsub/node_hometree.erl @@ -26,7 +26,6 @@ -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). --include_lib("exmpp/include/exmpp.hrl"). -behaviour(gen_pubsub_node). @@ -140,8 +139,8 @@ delete_node(Removed) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubId) -> + node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId). publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). diff --git a/src/mod_pubsub/node_hometree_odbc.erl b/src/mod_pubsub/node_hometree_odbc.erl index 2dd0503c5..711914511 100644 --- a/src/mod_pubsub/node_hometree_odbc.erl +++ b/src/mod_pubsub/node_hometree_odbc.erl @@ -26,7 +26,6 @@ -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). --include_lib("exmpp/include/exmpp.hrl"). -behaviour(gen_pubsub_node). @@ -111,8 +110,8 @@ delete_node(Removed) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> node_flat_odbc:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_flat_odbc:unsubscribe_node(NodeId, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubId) -> + node_flat_odbc:unsubscribe_node(NodeId, Sender, Subscriber, SubId). publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> node_flat_odbc:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). diff --git a/src/mod_pubsub/node_mb.erl b/src/mod_pubsub/node_mb.erl index 57d155558..162a1e96e 100644 --- a/src/mod_pubsub/node_mb.erl +++ b/src/mod_pubsub/node_mb.erl @@ -36,8 +36,6 @@ -module(node_mb). -author('eric@ohmforce.com'). --include_lib("exmpp/include/exmpp.hrl"). - -include("ejabberd.hrl"). -include("pubsub.hrl"). @@ -137,8 +135,8 @@ subscribe_node(NodeId, Sender, Subscriber, AccessModel, NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_pep:unsubscribe_node(NodeId, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubId) -> + node_pep:unsubscribe_node(NodeId, Sender, Subscriber, SubId). publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> node_pep:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). diff --git a/src/mod_pubsub/node_pep.erl b/src/mod_pubsub/node_pep.erl index 66522460b..1a4fb2aa5 100644 --- a/src/mod_pubsub/node_pep.erl +++ b/src/mod_pubsub/node_pep.erl @@ -29,8 +29,6 @@ -module(node_pep). -author('christophe.romain@process-one.net'). --include_lib("exmpp/include/exmpp.hrl"). - -include("ejabberd.hrl"). -include("pubsub.hrl"). @@ -70,15 +68,35 @@ path_to_node/1 ]). + +-spec(init/3 :: + ( + Host :: string(), + ServerHost :: string(), + Opts :: [{Key::atom(), Value::term()}]) + -> 'ok' + ). + init(Host, ServerHost, Opts) -> node_flat:init(Host, ServerHost, Opts), complain_if_modcaps_disabled(ServerHost), ok. + +-spec(terminate/2 :: + ( + Host :: string(), + ServerHost :: string()) + -> 'ok' + ). + terminate(Host, ServerHost) -> node_flat:terminate(Host, ServerHost), ok. + +-spec(options/0 :: () -> [nodeOption()]). + options() -> [{deliver_payloads, true}, {notify_config, false}, @@ -98,6 +116,9 @@ options() -> {deliver_notifications, true}, {presence_based_delivery, true}]. + +-spec(features/0 :: () -> [Feature::string()]). + features() -> ["create-nodes", %* "auto-create", %* @@ -117,165 +138,429 @@ features() -> "subscribe" %* ]. -create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> - LOwner = jlib:short_prepd_jid(Owner), - {User, Server, Resource} = LOwner, - Allowed = case LOwner of + +-spec(create_node_permission/6 :: + ( + Host :: hostPEP(), + ServerHost :: string(), + NodeId :: nodeId(), + ParentNodeId :: nodeId(), + JID :: jidEntity(), + Access :: atom()) + -> {'result', IsAllowed::boolean()} + ). + +create_node_permission(Host, ServerHost, _NodeId, _ParentNodeId, #jid{node = U, domain = S, resource = R} = JID, Access) -> + Owner = {U,S,R}, + Allowed = case Owner of {undefined, Host, undefined} -> true; % pubsub service always allowed _ -> - JID = exmpp_jid:make(User, Server, Resource), case acl:match_rule(ServerHost, Access, JID) of - allow -> + 'allow' -> case Host of - {User, Server, _} -> true; + {_, _, _} -> true; _ -> false end; - E -> - ?DEBUG("Create not allowed : ~p~n", [E]), + Error -> + ?DEBUG("Create not allowed : ~p~n", [Error]), false end end, {result, Allowed}. -create_node(NodeId, Owner) -> - case node_flat:create_node(NodeId, Owner) of - {result, _} -> {result, []}; - Error -> Error - end. -delete_node(Removed) -> - case node_flat:delete_node(Removed) of - {result, {_, _, Removed}} -> {result, {[], Removed}}; - Error -> Error - end. - -subscribe_node(NodeId, Sender, Subscriber, AccessModel, +-spec(create_node/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', []}% | {'error', 'internal-server-error'} + ). + +create_node(NodeIdx, JID) -> + {result, _} = node_flat:create_node(NodeIdx, JID), + {result, []}. +% case node_flat:create_node(NodeIdx, JID) of +% {result, _} -> {result, []}; +% Error -> Error +% end. + + +-spec(delete_node/1 :: + ( + Nodes :: [Node::pubsubNode()]) + -> {result, {[], + Removed :: [] | [{Node :: pubsubNode(), + [{Owner :: bareUsr(), + Subscriptions :: [{Subscription :: subscription(), + SubId :: subId()}]}]}]}} + %| {'error', 'internal-server-error'} + ). + +delete_node(Nodes) -> + {result, {_, _, Nodes}} = node_flat:delete_node(Nodes), + {result, {[], Nodes}}. +% case node_flat:delete_node(Nodes) of +% {result, {_, _, Nodes}} -> {result, {[], Nodes}}; +% Error -> Error +% end. + + +-spec(subscribe_node/8 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Subscriber :: jidEntity(), + AccessModel :: accessModel(), + SendLast :: atom(), + PresenceSubscription :: boolean(), + RosterGroup :: boolean(), + Options :: [nodeOption()]) + -> {'result', {'default', + Subscription :: 'subscribed', + SubId :: subId()}} + | {'result', {'default', + Subscription :: 'subscribed', + SubId :: subId(), + SendLast ::' send_last'}} + | {'result', {'default', + Subscription :: 'pending', + SubId :: subId()}} + | {'error', _} %% TODO add all error cases + ). + +subscribe_node(NodeIdx, JID, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> node_flat:subscribe_node( - NodeId, Sender, Subscriber, AccessModel, SendLast, + NodeIdx, JID, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - case node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID) of + +-spec(unsubscribe_node/4 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Subscriber :: jidEntity(), + SubId :: subId()) + -> {'result', []} | {'error', _} %% TODO : add all error cases + ). + +unsubscribe_node(NodeIdx, JID, Subscriber, SubId) -> + case node_flat:unsubscribe_node(NodeIdx, JID, Subscriber, SubId) of {error, Error} -> {error, Error}; {result, _} -> {result, []} end. -publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> - node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). - -remove_extra_items(NodeId, MaxItems, ItemIds) -> - node_flat:remove_extra_items(NodeId, MaxItems, ItemIds). - -delete_item(NodeId, Publisher, PublishModel, ItemId) -> - node_flat:delete_item(NodeId, Publisher, PublishModel, ItemId). - -purge_node(NodeId, Owner) -> - node_flat:purge_node(NodeId, Owner). -get_entity_affiliations(_Host, Owner) -> - {_, D, _} = jlib:short_prepd_jid(Owner), - GenKey = jlib:short_prepd_bare_jid(Owner), - States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), - NodeTree = case catch ets:lookup(gen_mod:get_module_proc(D, config), nodetree) of - [{nodetree, N}] -> N; - _ -> nodetree_tree +-spec(publish_item/6 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + PublishModel :: atom(), %% TODO : make a generic publishMod() type + MaxItems :: 'unlimited' | integer(), + ItemId :: itemId(), + Payload :: payload()) + -> {'result', {'default', 'broadcast', ItemIds :: [] | [itemId()]}} + | {'error', _} + ). + +publish_item(NodeIdx, JID, PublishModel, MaxItems, ItemId, Payload) -> + node_flat:publish_item(NodeIdx, JID, PublishModel, MaxItems, ItemId, Payload). + + +-spec(remove_extra_items/3 :: + ( + NodeIdx :: nodeIdx(), + MaxItems :: 'unlimited' | integer(), + ItemsIds :: [ItemId::itemId()]) + -> {'result', + {OldItems :: [] | [ItemId::itemId()], + NewItems :: [] | [ItemId::itemId()]}} + ). + +remove_extra_items(NodeIdx, MaxItems, ItemIds) -> + node_flat:remove_extra_items(NodeIdx, MaxItems, ItemIds). + + +-spec(delete_item/4 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + PublishModel :: atom(), + ItemId :: itemId()) + -> {'result', {'default', 'broadcast'}} | {'error', _} + ). + +delete_item(NodeIdx, JID, PublishModel, ItemId) -> + node_flat:delete_item(NodeIdx, JID, PublishModel, ItemId). + + +-spec(purge_node/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', {'default', 'broadcast'}} | {'error', 'forbidden'} + ). + +purge_node(NodeIdx, JID) -> + node_flat:purge_node(NodeIdx, JID). + + +-spec(get_entity_affiliations/2 :: + ( + Host :: binary(), + JID :: jidEntity()) + -> {'result', Reply :: [] | [{Node::pubsubNode(), Affiliation::affiliation()}]} + ). + +get_entity_affiliations(_Host, #jid{node = U, domain = S} = _JID) -> + States = mnesia:match_object(#pubsub_state{id = {_GenKey = {U,S,undefined}, '_'}, _ = '_'}), + NodeTree = case catch ets:lookup(gen_mod:get_module_proc(S, 'config'), 'nodetree') of + [{'nodetree', Tree}] -> Tree; + _ -> 'nodetree_tree' end, - Reply = lists:foldl(fun(#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {{_, D, _}, _}} = Node -> [{Node, A}|Acc]; + Reply = lists:foldl(fun(#pubsub_state{id = {_, NodeIdx}, affiliation = Affiliation}, Acc) -> + case NodeTree:get_node(NodeIdx) of + #pubsub_node{id = {{_, S, _}, _}} = Node -> [{Node, Affiliation}|Acc]; _ -> Acc end end, [], States), {result, Reply}. -get_node_affiliations(NodeId) -> - node_flat:get_node_affiliations(NodeId). -get_affiliation(NodeId, Owner) -> - node_flat:get_affiliation(NodeId, Owner). +-spec(get_node_affiliations/1 :: + ( + NodeIdx :: nodeIdx()) + -> {'result', [] | [{Entity::fullUsr(), Affiliation::affiliation()}]} + ). + +get_node_affiliations(NodeIdx) -> + node_flat:get_node_affiliations(NodeIdx). + + +-spec(get_affiliation/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', Affiliation::affiliation()} + ). -set_affiliation(NodeId, Owner, Affiliation) -> - node_flat:set_affiliation(NodeId, Owner, Affiliation). +get_affiliation(NodeIdx, JID) -> + node_flat:get_affiliation(NodeIdx, JID). -get_entity_subscriptions(_Host, Owner) -> - {U, D, _} = SubKey = jlib:short_prepd_jid(Owner), - GenKey = jlib:short_prepd_bare_jid(Owner), + +-spec(set_affiliation/3 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Affiliation :: affiliation()) + -> 'ok' | {error, 'internal-server-error'} + ). + +set_affiliation(NodeIdx, JID, Affiliation) -> + node_flat:set_affiliation(NodeIdx, JID, Affiliation). + + +-spec(get_entity_subscriptions/2 :: + ( + Host :: hostPEP(), + JID :: jidEntity()) + -> {'result', [] + | [{Node :: pubsubNode(), + Subscription :: subscription(), + SubId :: subId(), + Entity :: fullUsr()}]} + ). + +get_entity_subscriptions(_Host, #jid{node = U, domain = S, resource = R} = _JID) -> + SubKey = {U,S,R}, + GenKey = {U,S,undefined}, States = case SubKey of GenKey -> mnesia:match_object( - #pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); + #pubsub_state{id = {{U, S, '_'}, '_'}, _ = '_'}); _ -> mnesia:match_object( - #pubsub_state{stateid = {GenKey, '_'}, _ = '_'}) + #pubsub_state{id = {GenKey, '_'}, _ = '_'}) ++ mnesia:match_object( - #pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) + #pubsub_state{id = {SubKey, '_'}, _ = '_'}) end, - NodeTree = case catch ets:lookup(gen_mod:get_module_proc(D, config), nodetree) of - [{nodetree, N}] -> N; - _ -> nodetree_tree + NodeTree = case catch ets:lookup(gen_mod:get_module_proc(S, 'config'), 'nodetree') of + [{nodetree, Tree}] -> Tree; + _ -> 'nodetree_tree' end, - Reply = lists:foldl(fun(#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {{_, D, _}, _}} = Node -> - lists:foldl(fun({subscribed, SubID}, Acc2) -> - [{Node, subscribed, SubID, J} | Acc2]; - ({pending, _SubID}, Acc2) -> - [{Node, pending, J} | Acc2]; - (S, Acc2) -> - [{Node, S, J} | Acc2] - end, Acc, Ss); + Reply = lists:foldl(fun(#pubsub_state{id = {Entity, NodeIdx}, subscriptions = Subscriptions}, Acc) -> + case NodeTree:get_node(NodeIdx) of + #pubsub_node{id = {{_, S, _}, _}} = Node -> + lists:foldl(fun({subscribed, SubId}, Acc2) -> + [{Node, subscribed, SubId, Entity} | Acc2]; + ({pending, _SubId}, Acc2) -> + [{Node, pending, Entity} | Acc2]; + (Subscription, Acc2) -> + [{Node, Subscription, Entity} | Acc2] + end, Acc, Subscriptions); _ -> Acc end end, [], States), {result, Reply}. -get_node_subscriptions(NodeId) -> + +-spec(get_node_subscriptions/1 :: + ( + NodeIdx :: nodeIdx()) + -> {'result', [] + | [{Entity::fullUsr(), 'none'}] + %| [{Entity::fullUsr(), Subscription::subscription()}] %% still useful case ? + | [{Entity::fullUsr(), Subscription::subscription(), SubId::subId()}]} + ). + +get_node_subscriptions(NodeIdx) -> %% note: get_node_subscriptions is used for broadcasting %% there should not have any subscriptions %% but that call returns also all subscription to none %% and this is required for broadcast to occurs %% DO NOT REMOVE - node_flat:get_node_subscriptions(NodeId). + node_flat:get_node_subscriptions(NodeIdx). + + +-spec(get_subscriptions/2 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity()) + -> {'result', Subscriptions :: [] | [{Subscription::subscription(), SubId::subId()}]} + ). + +get_subscriptions(NodeIdx, JID) -> + node_flat:get_subscriptions(NodeIdx, JID). + + +-spec(set_subscriptions/4 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + Subscription :: subscription(), + SubId :: subId()) + -> 'ok' + | {Subscription::subscription(), SubId::subId()} + | {error, _} + ). + +set_subscriptions(NodeIdx, JID, Subscription, SubId) -> + node_flat:set_subscriptions(NodeIdx, JID, Subscription, SubId). -get_subscriptions(NodeId, Owner) -> - node_flat:get_subscriptions(NodeId, Owner). -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - node_flat:set_subscriptions(NodeId, Owner, Subscription, SubId). +-spec(get_pending_nodes/2 :: + ( + Host :: hostPEP(), + JID :: jidEntity()) + -> 'false' | {'value', NodeId::nodeId()} + ). -get_pending_nodes(Host, Owner) -> - node_flat:get_pending_nodes(Host, Owner). +get_pending_nodes(Host, JID) -> + node_flat:get_pending_nodes(Host, JID). -get_states(NodeId) -> - node_flat:get_states(NodeId). -get_state(NodeId, JID) -> - node_flat:get_state(NodeId, JID). +-spec(get_states/1 :: + ( + NodeIdx :: nodeIdx()) + -> {'result', States :: [] | [State::pubsubState()]} + ). + +get_states(NodeIdx) -> + node_flat:get_states(NodeIdx). + + +-spec(get_state/2 :: + ( + NodeIdx :: nodeIdx(), + Entity :: fullUsr()) + -> State::pubsubState() + ). + +get_state(NodeIdx, Entity) -> + node_flat:get_state(NodeIdx, Entity). + + +-spec(set_state/1 :: + ( + State :: pubsubState()) + -> 'ok' | {'error', 'internal-server-error'} + ). set_state(State) -> node_flat:set_state(State). -get_items(NodeId, From) -> - node_flat:get_items(NodeId, From). -get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_flat:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +-spec(get_items/2 :: + ( + NodeIdx :: nodeIdx(), + Entity :: fullUsr()) + -> {'result', Items :: [] | [Item::pubsubItem()]} + ). + +get_items(NodeIdx, Entity) -> + node_flat:get_items(NodeIdx, Entity). -get_item(NodeId, ItemId) -> - node_flat:get_item(NodeId, ItemId). -get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_flat:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). +-spec(get_items/6 :: + ( + NodeIdx :: nodeIdx(), + JID :: jidEntity(), + AccessModel :: accessModel(), + PresenceSubscription :: boolean(), + RosterGroup :: boolean(), + SubId :: subId()) + -> {'result', Items :: [] | [Item::pubsubItem()]} + | {'error', _} + ). + +get_items(NodeIdx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_flat:get_items(NodeIdx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). + + +-spec(get_item/2 :: + ( + NodeIdx :: nodeIdx(), + ItemId :: itemId()) + -> {'result', Item::pubsubItem()} | {'error', 'item-not-found'} + ). + +get_item(NodeIdx, ItemId) -> + node_flat:get_item(NodeIdx, ItemId). + + +-spec(get_item/7 :: + ( + NodeIdx :: nodeIdx(), + ItemId :: itemId(), + JID :: jidEntity(), + AccessModel :: accessModel(), + PresenceSubscription :: boolean(), + RosterGroup :: boolean(), + SubId :: subId()) + -> {'result', Item::pubsubItem()} | {'error', 'item-not-found'} + ). + +get_item(NodeIdx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_flat:get_item(NodeIdx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). + + +-spec(set_item/1 :: + ( + Item :: pubsubItem()) + -> 'ok' | {error, 'internal-server-error'} + ). set_item(Item) -> node_flat:set_item(Item). + get_item_name(Host, Node, Id) -> node_flat:get_item_name(Host, Node, Id). + node_to_path(Node) -> node_flat:node_to_path(Node). + path_to_node(Path) -> node_flat:path_to_node(Path). @@ -288,6 +573,12 @@ path_to_node(Path) -> %% The PEP plugin for mod_pubsub requires mod_caps to be enabled in the host. %% Check that the mod_caps module is enabled in that Jabber Host %% If not, show a warning message in the ejabberd log file. +-spec(complain_if_modcaps_disabled/1 :: + ( + ServerHost :: string()) + -> 'ok' | true + ). + complain_if_modcaps_disabled(ServerHost) -> Modules = ejabberd_config:get_local_option({modules, ServerHost}), ModCaps = [mod_caps_enabled || {mod_caps, _Opts} <- Modules], diff --git a/src/mod_pubsub/node_pep_odbc.erl b/src/mod_pubsub/node_pep_odbc.erl index b567d9f19..14d0875cc 100644 --- a/src/mod_pubsub/node_pep_odbc.erl +++ b/src/mod_pubsub/node_pep_odbc.erl @@ -25,12 +25,10 @@ %%% @doc The module <strong>{@module}</strong> is the pep PubSub plugin. %%% <p>PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.</p> - +%%TODO : fix SQL requests with nodeid/id and id/idx changes -module(node_pep_odbc). -author('christophe.romain@process-one.net'). --include_lib("exmpp/include/exmpp.hrl"). - -include("ejabberd.hrl"). -include("pubsub.hrl"). @@ -86,7 +84,6 @@ terminate(Host, ServerHost) -> options() -> [{odbc, true}, - {node_type, pep}, {deliver_payloads, true}, {notify_config, false}, {notify_delete, false}, @@ -163,8 +160,8 @@ subscribe_node(NodeId, Sender, Subscriber, AccessModel, NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - case node_flat_odbc:unsubscribe_node(NodeId, Sender, Subscriber, SubID) of +unsubscribe_node(NodeId, Sender, Subscriber, SubId) -> + case node_flat_odbc:unsubscribe_node(NodeId, Sender, Subscriber, SubId) of {error, Error} -> {error, Error}; {result, _} -> {result, []} end. diff --git a/src/mod_pubsub/node_private.erl b/src/mod_pubsub/node_private.erl index cbde859e1..c069ad1b2 100644 --- a/src/mod_pubsub/node_private.erl +++ b/src/mod_pubsub/node_private.erl @@ -26,8 +26,6 @@ -module(node_private). -author('christophe.romain@process-one.net'). --include_lib("exmpp/include/exmpp.hrl"). - -include("pubsub.hrl"). -behaviour(gen_pubsub_node). @@ -133,8 +131,8 @@ subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, SendLast, PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubId) -> + node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId). publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). diff --git a/src/mod_pubsub/node_public.erl b/src/mod_pubsub/node_public.erl index 720ab706b..b5719b5e7 100644 --- a/src/mod_pubsub/node_public.erl +++ b/src/mod_pubsub/node_public.erl @@ -26,8 +26,6 @@ -module(node_public). -author('christophe.romain@process-one.net'). --include_lib("exmpp/include/exmpp.hrl"). - -include("pubsub.hrl"). -behaviour(gen_pubsub_node). @@ -82,8 +80,7 @@ terminate(Host, ServerHost) -> node_flat:terminate(Host, ServerHost). options() -> - [{node_type, public}, - {deliver_payloads, true}, + [{deliver_payloads, true}, {notify_config, false}, {notify_delete, false}, {notify_retract, true}, @@ -130,8 +127,8 @@ delete_node(Removed) -> subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> node_flat:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubID). +unsubscribe_node(NodeId, Sender, Subscriber, SubId) -> + node_flat:unsubscribe_node(NodeId, Sender, Subscriber, SubId). publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> node_flat:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). diff --git a/src/mod_pubsub/nodetree_dag.erl b/src/mod_pubsub/nodetree_dag.erl index 6713720bc..890934557 100644 --- a/src/mod_pubsub/nodetree_dag.erl +++ b/src/mod_pubsub/nodetree_dag.erl @@ -39,7 +39,6 @@ -include("ejabberd.hrl"). -include("pubsub.hrl"). --include_lib("exmpp/include/exmpp.hrl"). -behaviour(gen_pubsub_nodetree). @@ -52,130 +51,265 @@ %%==================================================================== %% API %%==================================================================== +-spec(init/3 :: + ( + Host :: string(), + ServerHost :: string(), + Opts :: [{Key::atom(), Value::term()}]) + -> 'ok' + ). + init(Host, ServerHost, Opts) -> nodetree_tree:init(Host, ServerHost, Opts). + +-spec(terminate/2 :: + ( + Host :: string(), + ServerHost :: string()) + -> 'ok' + ). + terminate(Host, ServerHost) -> nodetree_tree:terminate(Host, ServerHost). -create_node(Key, NodeID, Type, Owner, Options, Parents) -> - OwnerJID = jlib:short_prepd_bare_jid(Owner), - case find_node(Key, NodeID) of + +-spec(create_node/6 :: + ( + Host :: hostPubsub(), + NodeId :: nodeId(), + Type :: nodeType(), + JID :: jidEntity(), + Options :: [nodeOption()], + ParentNodeIds :: [] | [nodeId()]) + -> {'ok', NodeIdx::nodeIdx()} | {'error', _} + ). + +create_node(Host, NodeId, Type, #jid{node = U, domain = S} = _JID, Options, ParentNodeIds) -> + case find_node(Host, NodeId) of false -> - ID = pubsub_index:new(node), - N = #pubsub_node{nodeid = oid(Key, NodeID), - id = ID, + NodeIdx = pubsub_index:new(node), + Node = #pubsub_node{id = {Host, NodeId}, + idx = NodeIdx, type = Type, - parents = Parents, - owners = [OwnerJID], + parents = ParentNodeIds, + owners = [_Owner = {U,S,undefined}], options = Options}, - case set_node(N) of - ok -> {ok, ID}; + case set_node(Node) of + ok -> {ok, NodeIdx}; Other -> Other end; _ -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'conflict')} end. -set_node(#pubsub_node{nodeid = {Key, _}, + +-spec(set_node/1 :: + ( + Node :: pubsubNode()) + -> 'ok' | {'error', _} + ). + +set_node(#pubsub_node{id = {Host, _}, owners = Owners, options = Options} = Node) -> - Parents = find_opt(collection, ?DEFAULT_PARENTS, Options), - case validate_parentage(Key, Owners, Parents) of + ParentNodeIds = find_opt('collection', ?DEFAULT_PARENTS, Options), + case validate_parentage(Host, Owners, ParentNodeIds) of true -> %% Update parents whenever the config changes. - mnesia:write(Node#pubsub_node{parents = Parents}); + mnesia:write(Node#pubsub_node{parents = ParentNodeIds}); Other -> Other end. -delete_node(Key, NodeID) -> - case find_node(Key, NodeID) of + +-spec(delete_node/2 :: + ( + Host :: hostPubsub(), + NodeId :: nodeId()) + -> [pubsubNode()] | {'error', _} + ). + +delete_node(Host, NodeId) -> + case find_node(Host, NodeId) of false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')}; - Node -> + ParentNode -> %% Find all of N's children, update their configs to %% remove N from the collection setting. - lists:foreach(fun (#pubsub_node{options = Opts} = Child) -> - NewOpts = remove_config_parent(NodeID, Opts), - Parents = find_opt(collection, ?DEFAULT_PARENTS, NewOpts), + lists:foreach(fun (#pubsub_node{options = Options} = Node) -> + NewOptions = remove_config_parent(NodeId, Options), + Parents = find_opt('collection', ?DEFAULT_PARENTS, NewOptions), ok = mnesia:write(pubsub_node, - Child#pubsub_node{ + Node#pubsub_node{ parents = Parents, - options = NewOpts}, + options = NewOptions}, write) - end, get_subnodes(Key, NodeID)), + end, get_subnodes(Host, NodeId)), %% Remove and return the requested node. - pubsub_index:free(node, Node#pubsub_node.id), - mnesia:delete_object(pubsub_node, Node, write), - [Node] + pubsub_index:free(node, ParentNode#pubsub_node.idx), + mnesia:delete_object(pubsub_node, ParentNode, write), + [ParentNode] end. -options() -> - nodetree_tree:options(). -get_node(Host, NodeID, _From) -> - get_node(Host, NodeID). +-spec(options/0 :: () -> Options::[Option::nodeOption()]). + %Options::[{'virtual_tree', 'false'}]) + +options() -> nodetree_tree:options(). + + +-spec(get_node/3 :: + ( + Host :: hostPubsub(), + NodeId :: nodeId(), + JID :: jidEntity()) + -> pubsubNode() | {'error', _} + ). -get_node(Host, NodeID) -> - case find_node(Host, NodeID) of +get_node(Host, NodeId, _JID) -> + get_node(Host, NodeId). + + +-spec(get_node/2 :: + ( + Host :: hostPubsub(), + NodeId :: nodeId()) + -> pubsubNode() | {'error', _} + ). + +get_node(Host, NodeId) -> + case find_node(Host, NodeId) of false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')}; - Node -> Node + Node -> Node end. -get_node(NodeId) -> - nodetree_tree:get_node(NodeId). -get_nodes(Key, From) -> - nodetree_tree:get_nodes(Key, From). +-spec(get_node/1 :: + ( + NodeIdx :: nodeIdx()) + -> pubsubNode() | {'error', 'item-not-found'} + ). + +get_node(NodeIdx) -> + nodetree_tree:get_node(NodeIdx). + + +-spec(get_nodes/2 :: + ( + Host :: hostPubsub(), + JID :: jidEntity()) + -> Nodes :: [] | [Node::pubsubNode()] + ). + +get_nodes(Host, JID) -> + nodetree_tree:get_nodes(Host, JID). + + +-spec(get_nodes/1 :: + ( + Host :: hostPubsub()) + -> Nodes :: [] | [Node::pubsubNode()] + ). + +get_nodes(Host) -> + nodetree_tree:get_nodes(Host). + -get_nodes(Key) -> - nodetree_tree:get_nodes(Key). +-spec(get_parentnodes/3 :: + ( + Host :: hostPubsub(), + NodeId :: nodeId(), + JID :: jidEntity()) + -> ParentNodes :: [] | [ParentNode::pubsubNode()] + ). -get_parentnodes(Host, NodeID, _From) -> - case find_node(Host, NodeID) of +get_parentnodes(Host, NodeId, _JID) -> + case find_node(Host, NodeId) of false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')}; - #pubsub_node{parents = Parents} -> - Q = qlc:q([N || #pubsub_node{nodeid = {NHost, NNode}} = N <- mnesia:table(pubsub_node), - Parent <- Parents, + #pubsub_node{parents = ParentNodeIds} -> + Q = qlc:q([Node || #pubsub_node{id = {NHost, NNodeId}} = Node + <- mnesia:table(pubsub_node), + ParentNodeId <- ParentNodeIds, Host == NHost, - Parent == NNode]), + ParentNodeId == NNodeId]), qlc:e(Q) end. -get_parentnodes_tree(Host, NodeID, _From) -> - Pred = fun (NID, #pubsub_node{nodeid = {_, NNodeID}}) -> - NID == NNodeID - end, + +-spec(get_parentnodes_tree/3 :: + ( + Host :: hostPubsub(), + NodeId :: nodeId(), + JID :: jidEntity()) + -> [] | [{Depth::integer(), Nodes :: [] | [Node::pubsubNode()]}] + ). + +get_parentnodes_tree(Host, NodeId, _JID) -> + Pred = fun (Name, #pubsub_node{id = {_, NodeName}}) -> Name == NodeName end, Tr = fun (#pubsub_node{parents = Parents}) -> Parents end, - traversal_helper(Pred, Tr, Host, [NodeID]). + traversal_helper(Pred, Tr, Host, [NodeId]). + + +-spec(get_subnodes/3 :: + ( + ParentNodeHost :: hostPubsub(), + ParentNodeId :: nodeId(), + JID :: jidEntity()) + -> [] | [Node::pubsubNode()] | {'error', _} + ). + +get_subnodes(Host, Node, _JID) -> + get_subnodes(Host, Node). -get_subnodes(Host, NodeID, _From) -> - get_subnodes(Host, NodeID). -get_subnodes(Host, <<>>) -> - get_subnodes_helper(Host, <<>>); -get_subnodes(Host, NodeID) -> - case find_node(Host, NodeID) of +-spec(get_subnodes/2 :: + ( + ParentNodeHost :: hostPubsub(), + ParentNodeId :: nodeId()) + -> [] | [Node::pubsubNode()] | {'error', _} + ). + +get_subnodes(ParentNodeHost, <<>>) -> + get_subnodes_helper(ParentNodeHost, <<>>); +get_subnodes(ParentNodeHost, ParentNodeId) -> + case find_node(ParentNodeHost, ParentNodeId) of false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item-not-found')}; - _ -> get_subnodes_helper(Host, NodeID) + _ -> get_subnodes_helper(ParentNodeHost, ParentNodeId) end. -get_subnodes_helper(Host, NodeID) -> - Q = qlc:q([Node || #pubsub_node{nodeid = {NHost, _}, - parents = Parents} = Node <- mnesia:table(pubsub_node), - Host == NHost, - lists:member(NodeID, Parents)]), + +-spec(get_subnodes_helper/2 :: + ( + ParentNodeHost :: hostPubsub(), + ParentNodeId :: nodeId()) + -> SubNodes :: [] | [Node::pubsubNode()] + ). + +get_subnodes_helper(ParentNodeHost, ParentNodeId) -> + Q = qlc:q([Node || #pubsub_node{id = {Host, _}, + parents = ParentNodeIds} = Node <- mnesia:table(pubsub_node), + ParentNodeHost == Host, + lists:member(ParentNodeId, ParentNodeIds)]), qlc:e(Q). -get_subnodes_tree(Host, NodeID, From) -> - Pred = fun (NID, #pubsub_node{parents = Parents}) -> - lists:member(NID, Parents) + +-spec(get_subnodes_tree/3 :: + ( + ParentNodeHost :: hostPubsub(), + ParentNodeId :: nodeId(), + JID :: jidEntity()) + -> [] | [{Depth::integer(), Nodes :: [] | [Node::pubsubNode()]}] + ). + +get_subnodes_tree(Host, ParentNodeId, JID) -> + Pred = fun(NodeId, #pubsub_node{parents = ParentNodeIds}) -> + lists:member(NodeId, ParentNodeIds) end, - Tr = fun (#pubsub_node{nodeid = {_, N}}) -> [N] end, - traversal_helper(Pred, Tr, 1, Host, [NodeID], - [{0, [get_node(Host, NodeID, From)]}]). + Tr = fun (#pubsub_node{id = {_, NodeId}}) -> [NodeId] end, + traversal_helper(Pred, Tr, 1, Host, [ParentNodeId], + [{0, [get_node(Host, ParentNodeId, JID)]}]). %%==================================================================== %% Internal functions @@ -183,9 +317,16 @@ get_subnodes_tree(Host, NodeID, From) -> oid(Key, Name) -> {Key, Name}. %% Key = jlib:jid() | host() -%% NodeID = string() -find_node(Key, NodeID) -> - case mnesia:read(pubsub_node, oid(Key, NodeID), read) of +%% Node = string() +-spec(find_node/2 :: + ( + Host :: hostPubsub(), + NodeId :: nodeId()) + -> pubsubNode() | 'false' + ). + +find_node(Host, NodeId) -> + case mnesia:read({pubsub_node, {Host, NodeId}}) of [] -> false; [Node] -> Node end. @@ -193,53 +334,109 @@ find_node(Key, NodeID) -> %% Key = jlib:jid() | host() %% Default = term() %% Options = [{Key = atom(), Value = term()}] +-spec(find_opt/3 :: + ( + Key :: atom(), + Default :: term(), + Options :: [Option::nodeOption()]) + -> Value::term() + ). + find_opt(Key, Default, Options) -> case lists:keysearch(Key, 1, Options) of - {value, {Key, Val}} -> Val; + {value, {Key, Value}} -> Value; _ -> Default end. -traversal_helper(Pred, Tr, Host, NodeIDs) -> - traversal_helper(Pred, Tr, 0, Host, NodeIDs, []). + +-spec(traversal_helper/4 :: + ( + Pred :: fun(), + Tr :: fun(), + ParentNodeHost :: hostPubsub(), + ParentNodeIds :: [] | [ParentNodeId::nodeId()]) + -> [] | [{Depth::integer(), Nodes :: [] | [Node::pubsubNode()]}] + ). + +traversal_helper(Pred, Tr, ParentNodeHost, ParentNodeIds) -> + traversal_helper(Pred, Tr, 0, ParentNodeHost, ParentNodeIds, []). + + +-spec(traversal_helper/6 :: + ( + Pred :: fun(), + Tr :: fun(), + Depth :: integer(), + ParentNodeHost :: hostPubsub(), + ParentNodeIds :: [] | [ParentNodeId::nodeId()], + Acc :: [] | [{Depth::integer(), Nodes :: [] | [Node::pubsubNode()]}]) + -> [] | [{Depth::integer(), Nodes :: [] | [Node::pubsubNode()]}] + ). traversal_helper(_Pred, _Tr, _Depth, _Host, [], Acc) -> Acc; -traversal_helper(Pred, Tr, Depth, Host, NodeIDs, Acc) -> - Q = qlc:q([Node || #pubsub_node{nodeid = {NHost, _}} = Node <- mnesia:table(pubsub_node), - NodeID <- NodeIDs, - Host == NHost, - Pred(NodeID, Node)]), +traversal_helper(Pred, Tr, Depth, ParentNodeHost, ParentNodeIds, Acc) -> + Q = qlc:q([Node || #pubsub_node{id = {Host, _}} = Node <- mnesia:table(pubsub_node), + ParentNodeId <- ParentNodeIds, + ParentNodeHost == Host, + Pred(ParentNodeId, Node)]), Nodes = qlc:e(Q), - IDs = lists:flatmap(Tr, Nodes), - traversal_helper(Pred, Tr, Depth + 1, Host, IDs, [{Depth, Nodes} | Acc]). + Ids = lists:flatmap(Tr, Nodes), + traversal_helper(Pred, Tr, Depth + 1, ParentNodeHost, Ids, [{Depth, Nodes} | Acc]). -remove_config_parent(NodeID, Options) -> - remove_config_parent(NodeID, Options, []). -remove_config_parent(_NodeID, [], Acc) -> - lists:reverse(Acc); -remove_config_parent(NodeID, [{collection, Parents} | T], Acc) -> - remove_config_parent(NodeID, T, - [{collection, lists:delete(NodeID, Parents)} | Acc]); -remove_config_parent(NodeID, [H | T], Acc) -> - remove_config_parent(NodeID, T, [H | Acc]). +-spec(remove_config_parent/2 :: + ( + NodeId :: nodeId(), + Options :: [Option::nodeOption()]) + -> [Option::nodeOption()] + ). -validate_parentage(_Key, _Owners, []) -> +remove_config_parent(NodeId, Options) -> + remove_config_parent(NodeId, Options, []). + + +-spec(remove_config_parent/3 :: + ( + NodeId :: nodeId(), + Options :: [] | [Option::nodeOption()], + Acc :: [Option::nodeOption()]) + -> [Option::nodeOption()] + ). + +remove_config_parent(_NodeId, [], Acc) -> + lists:reverse(Acc); +remove_config_parent(NodeId, [{'collection', ParentNodeIds} | Options], Acc) -> + remove_config_parent(NodeId, Options, + [{'collection', lists:delete(NodeId, ParentNodeIds)} | Acc]); +remove_config_parent(NodeId, [Option | Options], Acc) -> + remove_config_parent(NodeId, Options, [Option | Acc]). + + +-spec(validate_parentage/3 :: + ( + Host :: hostPubsub(), + Owners :: [Owner::bareUsr()], + ParentNodeIds :: [] | [ParentNodeId::nodeId()] | [ParentNodeId :: nodeId() | []]) + -> 'true' | {'error', _} + ). + +validate_parentage(_Host, _Owners, []) -> true; -validate_parentage(Key, Owners, [[] | T]) -> - validate_parentage(Key, Owners, T); -validate_parentage(Key, Owners, [<<>> | T]) -> - validate_parentage(Key, Owners, T); -validate_parentage(Key, Owners, [ParentID | T]) -> - case find_node(Key, ParentID) of +validate_parentage(Host, Owners, [[] | ParentNodeIds]) -> + validate_parentage(Host, Owners, ParentNodeIds); +validate_parentage(Host, Owners, [<<>> | ParentNodeIds]) -> + validate_parentage(Host, Owners, ParentNodeIds); +validate_parentage(Host, Owners, [ParentNodeId | ParentNodeIds]) -> + case find_node(Host, ParentNodeId) of false -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'item_not_found')}; - #pubsub_node{owners = POwners, options = POptions} -> - NodeType = find_opt(node_type, ?DEFAULT_NODETYPE, POptions), - MutualOwners = [O || O <- Owners, PO <- POwners, - O == PO], + #pubsub_node{owners = ParentNodeOwners, options = Options} -> + NodeType = find_opt('node_type', ?DEFAULT_NODETYPE, Options), + MutualOwners = [Owner || Owner <- Owners, ParentNodeOwner <- ParentNodeOwners, + Owner == ParentNodeOwner], case {MutualOwners, NodeType} of {[], _} -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'forbidden')}; - {_, collection} -> validate_parentage(Key, Owners, T); + {_, 'collection'} -> validate_parentage(Host, Owners, ParentNodeIds); {_, _} -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'not-allowed')} end end. @@ -247,6 +444,12 @@ validate_parentage(Key, Owners, [ParentID | T]) -> %% @spec (Host) -> jid() %% Host = host() %% @doc <p>Generate pubsub service JID.</p> +-spec(service_jid/1 :: + ( + Host :: hostPubsub()) + -> ServiceJID :: jidContact() | jidComponent() %% should only return jidContact() + ). + service_jid(Host) -> case Host of {U,S,_} -> exmpp_jid:make(U, S); diff --git a/src/mod_pubsub/nodetree_tree.erl b/src/mod_pubsub/nodetree_tree.erl index 6c6329482..d46452f24 100644 --- a/src/mod_pubsub/nodetree_tree.erl +++ b/src/mod_pubsub/nodetree_tree.erl @@ -37,13 +37,13 @@ -author('christophe.romain@process-one.net'). -include_lib("stdlib/include/qlc.hrl"). --include_lib("exmpp/include/exmpp.hrl"). -include("pubsub.hrl"). -behaviour(gen_pubsub_nodetree). --export([init/3, +-export([ + init/3, terminate/2, options/0, set_node/1, @@ -61,6 +61,7 @@ ]). + %% ================ %% API definition %% ================ @@ -74,182 +75,309 @@ %% <p>This function is mainly used to trigger the setup task necessary for the %% plugin. It can be used for example by the developer to create the specific %% module database schema if it does not exists yet.</p> +-spec(init/3 :: + ( + Host :: string(), + ServerHost :: string(), + Opts :: [{Key::atom(), Value::term()}]) + -> 'ok' + ). + init(_Host, _ServerHost, _Opts) -> mnesia:create_table(pubsub_node, [{disc_copies, [node()]}, {attributes, record_info(fields, pubsub_node)}]), - mnesia:add_table_index(pubsub_node, id), + mnesia:add_table_index(pubsub_node, idx), NodesFields = record_info(fields, pubsub_node), case mnesia:table_info(pubsub_node, attributes) of NodesFields -> ok; - _ -> - ok - %% mnesia:transform_table(pubsub_state, ignore, StatesFields) + _ -> ok %% mnesia:transform_table(pubsub_state, ignore, StatesFields) end, ok. + + +-spec(terminate/2 :: + ( + Host :: string(), + ServerHost :: string()) + -> 'ok' + ). + terminate(_Host, _ServerHost) -> ok. %% @spec () -> [Option] %% Option = mod_pubsub:nodetreeOption() %% @doc Returns the default pubsub node tree options. -options() -> - [{virtual_tree, false}]. +-spec(options/0 :: () -> Options::[{'virtual_tree', 'false'}]). + +options() -> [{'virtual_tree', 'false'}]. %% @spec (NodeRecord) -> ok | {error, Reason} %% Record = mod_pubsub:pubsub_node() -set_node(Record) when is_record(Record, pubsub_node) -> - mnesia:write(Record); -set_node(_) -> - {error, 'internal-server-error'}. + %( + % Node :: pubsubNode() -> 'ok' | {'error', Reason::_}; + % Node :: any() -> {'error', 'internal-server-error'} + %). +%% -spec breaks compilation + +set_node(#pubsub_node{} = Node) -> mnesia:write(Node); +set_node(_) -> {error, 'internal-server-error'}. %% @spec (Host, Node, From) -> pubsubNode() | {error, Reason} %% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -get_node(Host, Node, _From) -> - get_node(Host, Node). -get_node(Host, Node) -> - case catch mnesia:read({pubsub_node, {Host, Node}}) of - [Record] when is_record(Record, pubsub_node) -> Record; - [] -> {error, 'item-not-found'}; - Error -> Error +%% Node = node() +-spec(get_node/3 :: + ( + Host :: host(), % hostPubsub | hostPEP() + NodeId :: nodeId(), + JID :: jidEntity()) + -> pubsubNode() | {error, 'item-not-found'} | any() + ). + +get_node(Host, NodeId, _JID) -> + get_node(Host, NodeId). + + +-spec(get_node/2 :: + ( + Host :: host(), % hostPubsub | hostPEP() + NodeId :: nodeId()) + -> pubsubNode() | {error, 'item-not-found'} | any() + ). + +get_node(Host, NodeId) -> + case catch mnesia:read({pubsub_node, {Host, NodeId}}) of + [#pubsub_node{} = Node] -> Node; + [] -> {error, 'item-not-found'}; + Error -> Error end. -get_node(NodeId) -> - case catch mnesia:index_read(pubsub_node, NodeId, #pubsub_node.id) of - [Record] when is_record(Record, pubsub_node) -> Record; - [] -> {error, 'item-not-found'}; - Error -> Error + + +-spec(get_node/1 :: + ( + NodeIdx :: nodeIdx()) + -> pubsubNode() | {'error', 'item-not-found'} + ). + +get_node(NodeIdx) -> + case catch mnesia:index_read(pubsub_node, NodeIdx, #pubsub_node.idx) of + [#pubsub_node{} = Node] -> Node; + [] -> {error, 'item-not-found'}; + Error -> Error end. %% @spec (Host, From) -> [pubsubNode()] | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() -get_nodes(Host, _From) -> +%% Host = mod_pubsub:host() | ljid() +-spec(get_nodes/2 :: + ( + Host :: host(), % hostPubsub | hostPEP() + JID :: jidEntity()) + -> Nodes :: [] | [Node::pubsubNode()] + ). + +get_nodes(Host, _JID) -> get_nodes(Host). + + +-spec(get_nodes/1 :: + ( + Host :: host()) % hostPubsub | hostPEP() + -> Nodes :: [] | [Node::pubsubNode()] + ). + get_nodes(Host) -> - mnesia:match_object(#pubsub_node{nodeid = {Host, '_'}, _ = '_'}). + mnesia:match_object(#pubsub_node{id = {Host, '_'}, _ = '_'}). %% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() +%% Host = mod_pubsub:host() | ljid() +%% Node = node() +%% From = ljid() %% Depth = integer() %% Record = pubsubNode() %% @doc <p>Default node tree does not handle parents, return empty list.</p> -get_parentnodes(_Host, _Node, _From) -> +-spec(get_parentnodes/3 :: + ( + Host :: host(), % hostPubsub | hostPEP() + NodeId :: nodeId(), + JID :: jidEntity()) + -> ParentNodes :: [] + ). + +get_parentnodes(_Host, _NodeId, _JID) -> []. %% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() +%% Host = mod_pubsub:host() | ljid() +%% Node = node() +%% From = ljid() %% Depth = integer() %% Record = pubsubNode() %% @doc <p>Default node tree does not handle parents, return a list %% containing just this node.</p> -get_parentnodes_tree(Host, Node, From) -> - case get_node(Host, Node, From) of - N when is_record(N, pubsub_node) -> [{0, [N]}]; - _Error -> [] +-spec(get_parentnodes_tree/3 :: + ( + Host :: host(), % hostPubsub | hostPEP() + NodeId :: nodeId(), + JID :: jidEntity()) + -> ParentNodesTree :: [] | [{0, [ParentNode::pubsubNode()]}] + ). + +get_parentnodes_tree(Host, NodeId, JID) -> + case get_node(Host, NodeId, JID) of + #pubsub_node{} = ParentNode -> [{0, [ParentNode]}]; + _Error -> [] end. %% @spec (Host, Node, From) -> [pubsubNode()] | {error, Reason} %% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() -get_subnodes(Host, Node, _From) -> - get_subnodes(Host, Node). -get_subnodes(Host, <<>>) -> - Q = qlc:q([N || #pubsub_node{nodeid = {NHost, _}, - parents = Parents} = N <- mnesia:table(pubsub_node), - Host == NHost, - Parents == []]), +%% Node = node() +%% From = ljid() +-spec(get_subnodes/3 :: + ( + Host :: host(), % hostPubsub | hostPEP() + NodeId :: nodeId(), + JID :: jidEntity()) + -> SubNodes :: [] | [Node::pubsubNode()] + ). + +get_subnodes(Host, NodeId, _JID) -> + get_subnodes(Host, NodeId). + + +-spec(get_subnodes/2 :: + ( + ParentNodeHost :: host(), % hostPubsub | hostPEP() + ParentNodeId :: nodeId()) + -> SubNodes :: [] | [Node::pubsubNode()] + ). + +get_subnodes(ParentNodeHost, <<>>) -> + Q = qlc:q( + [Node + || #pubsub_node{id = {Host, _}, parents = ParentNodeIds} = Node + <- mnesia:table(pubsub_node), + ParentNodeHost == Host, + ParentNodeIds == []]), qlc:e(Q); -get_subnodes(Host, Node) -> - Q = qlc:q([N || #pubsub_node{nodeid = {NHost, _}, - parents = Parents} = N <- mnesia:table(pubsub_node), - Host == NHost, - lists:member(Node, Parents)]), +get_subnodes(ParentNodeHost, ParentNodeId) -> + Q = qlc:q( + [Node + || #pubsub_node{id = {Host, _}, parents = ParentNodeIds} = Node + <- mnesia:table(pubsub_node), + ParentNodeHost == Host, + lists:member(ParentNodeId, ParentNodeIds)]), qlc:e(Q). -%% @spec (Host, Index, From) -> [pubsubNodeIdx()] | {error, Reason} +%% @spec (Host, Index, From) -> [nodeidx()] | {error, Reason} %% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() -get_subnodes_tree(Host, Node, _From) -> - get_subnodes_tree(Host, Node). -get_subnodes_tree(Host, Node) -> - case get_node(Host, Node) of - {error, _} -> - []; - Rec -> - BasePlugin = list_to_atom("node_"++Rec#pubsub_node.type), - BasePath = BasePlugin:node_to_path(Node), - mnesia:foldl(fun(#pubsub_node{nodeid = {H, N}} = R, Acc) -> - Plugin = list_to_atom("node_"++R#pubsub_node.type), - Path = Plugin:node_to_path(N), - case lists:prefix(BasePath, Path) and (H == Host) of - true -> [R | Acc]; - false -> Acc - end - end, [], pubsub_node) +%% Node = node() +%% From = ljid() +-spec(get_subnodes_tree/3 :: + ( + Host :: host(), % hostPubsub | hostPEP() + ParentNodeId :: nodeId(), + JID :: jidEntity()) + -> SubNodes :: [] | [Node::pubsubNode()] + ). + +get_subnodes_tree(Host, ParentNodeId, _JID) -> + get_subnodes_tree(Host, ParentNodeId). + + +-spec(get_subnodes_tree/2 :: + ( + Host :: host(), % hostPubsub | hostPEP() + ParentNodeId :: nodeId()) + -> SubNodes :: [] | [Node::pubsubNode()] + ). + +get_subnodes_tree(ParentNodeHost, ParentNodeId) -> + case get_node(ParentNodeHost, ParentNodeId) of + {error, _} -> []; + #pubsub_node{type = ParentNodeType} = _ParentNode -> + BasePlugin = list_to_atom("node_"++ParentNodeType), + BasePath = BasePlugin:node_to_path(ParentNodeId), + mnesia:foldl(fun + (#pubsub_node{id = {Host, NodeId}, type = Type} = Node, Acc) -> + Plugin = list_to_atom("node_"++Type), + Path = Plugin:node_to_path(NodeId), + case lists:prefix(BasePath, Path) and (Host == ParentNodeHost) of + true -> [Node | Acc]; + false -> Acc + end + end, [], pubsub_node) end. %% @spec (Host, Node, Type, Owner, Options, Parents) -> ok | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() -%% NodeType = mod_pubsub:nodeType() -%% Owner = mod_pubsub:jid() +%% Host = mod_pubsub:host() | ljid() +%% Node = node() +%% NodeType = nodeType() +%% Owner = ljid() %% Options = list() -create_node(Host, Node, Type, Owner, Options, Parents) -> - BJID = jlib:short_prepd_bare_jid(Owner), - case mnesia:read({pubsub_node, {Host, Node}}) of +-spec(create_node/6 :: + ( + Host :: host(), % hostPubsub | hostPEP() + NodeId :: nodeId(), + Type :: nodeType(), + JID :: jidEntity(), + Options :: [nodeOption()], + ParentNodeIds :: [] | [nodeId()]) + -> {'ok', NodeIdx::nodeIdx()} + | {'error', 'conflict' | 'forbidden'} + ). + +create_node(Host, NodeId, Type, #jid{node = U, domain = S} = _JID, Options, ParentNodeIds) -> + Owner = {U,S,undefined}, + case mnesia:read({pubsub_node, {Host, NodeId}}) of [] -> - ParentExists = - case Host of - {_U, _S, _R} -> - %% This is special case for PEP handling - %% PEP does not uses hierarchy - true; - _ -> - case Parents of - [] -> true; - [Parent | _] -> - BHost = list_to_binary(Host), - case mnesia:read({pubsub_node, {Host, Parent}}) of - [#pubsub_node{owners = [{undefined, BHost, undefined}]}] -> true; - [#pubsub_node{owners = Owners}] -> lists:member(BJID, Owners); - _ -> false - end; - _ -> - false - end - end, + ParentExists = case Host of + %% This is special case for PEP handling, PEP does not uses hierarchy + {_, _, _} -> true; + _ -> + case ParentNodeIds of + [] -> true; + [ParentNodeId | _] -> + case mnesia:read({pubsub_node, {Host, ParentNodeId}}) of + [#pubsub_node{owners = [{undefined, Host, undefined}]}] -> true; + [#pubsub_node{owners = Owners}] -> lists:member(Owner, Owners); + _ -> false + end; + _ -> false + end + end, case ParentExists of true -> - NodeId = pubsub_index:new(node), - mnesia:write(#pubsub_node{nodeid = {Host, Node}, - id = NodeId, - parents = Parents, - type = Type, - owners = [BJID], - options = Options}), - {ok, NodeId}; - false -> - %% Requesting entity is prohibited from creating nodes - {error, 'forbidden'} - end; - _ -> - %% NodeID already exists - {error, 'conflict'} + NodeIdx = pubsub_index:new(node), + mnesia:write( + #pubsub_node{id = {Host, NodeId}, + idx = NodeIdx, + parents = ParentNodeIds, + type = Type, + owners = [Owner], + options = Options}), + {ok, NodeIdx}; + false -> %% Requesting entity is prohibited from creating nodes + {error, 'forbidden'} + end; + _ -> %% Node already exists + {error, 'conflict'} end. %% @spec (Host, Node) -> [mod_pubsub:node()] -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() -delete_node(Host, Node) -> - Removed = get_subnodes_tree(Host, Node), - lists:foreach(fun(#pubsub_node{nodeid = {_, N}, id = I}) -> - pubsub_index:free(node, I), - mnesia:delete({pubsub_node, {Host, N}}) - end, Removed), - Removed. +%% Host = mod_pubsub:host() | ljid() +%% Node = node() +-spec(delete_node/2 :: +( + Host :: host(), % hostPubsub | hostPEP() + ParentNodeId :: nodeId()) + -> DeletedNodes :: [] | [Node::pubsubNode()] +). + +delete_node(Host, ParentNodeId) -> + DeletedNodes = get_subnodes_tree(Host, ParentNodeId), + lists:foreach(fun(#pubsub_node{id = {_, NodeId}, idx = NodeIdx}) -> + pubsub_index:free(node, NodeIdx), + mnesia:delete({pubsub_node, {Host, NodeId}}) + end, DeletedNodes), + DeletedNodes. diff --git a/src/mod_pubsub/nodetree_tree_odbc.erl b/src/mod_pubsub/nodetree_tree_odbc.erl index 55c611345..4c2efa7f4 100644 --- a/src/mod_pubsub/nodetree_tree_odbc.erl +++ b/src/mod_pubsub/nodetree_tree_odbc.erl @@ -32,12 +32,10 @@ %%% development is still a work in progress. However, the system is already %%% useable and useful as is. Please, send us comments, feedback and %%% improvements.</p> - -module(nodetree_tree_odbc). -author('christophe.romain@process-one.net'). -include_lib("stdlib/include/qlc.hrl"). --include_lib("exmpp/include/exmpp.hrl"). -include("pubsub.hrl"). @@ -84,16 +82,16 @@ terminate(_Host, _ServerHost) -> ok. %% @spec () -> [Option] -%% Option = mod_pubsub:nodetreeOption() +%% Option = nodetreeOption() %% @doc Returns the default pubsub node tree options. options() -> [{virtual_tree, false}, {odbc, true}]. -%% @spec (Host, Node, From) -> pubsubNode() | {error, Reason} +%% @spec (Host, Node, From) -> node() | {error, Reason} %% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% Node = node() get_node(Host, Node, _From) -> get_node(Host, Node). get_node(Host, Node) -> @@ -111,22 +109,22 @@ get_node(Host, Node) -> _ -> {error, 'item_not_found'} end. -get_node(NodeId) -> +get_node(Nidx) -> case catch ejabberd_odbc:sql_query_t( ["select host, node, parent, type " "from pubsub_node " - "where nodeid='", NodeId, "';"]) + "where nodeid='", Nidx, "';"]) of {selected, ["host", "node", "parent", "type"], [{Host, Node, Parent, Type}]} -> - raw_to_node(Host, {Node, Parent, Type, NodeId}); + raw_to_node(Host, {Node, Parent, Type, Nidx}); {'EXIT', _Reason} -> {error, 'internal_server_error'}; _ -> {error, 'item_not_found'} end. -%% @spec (Host, From) -> [pubsubNode()] | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() +%% @spec (Host, From) -> [node()] | {error, Reason} +%% Host = mod_pubsub:host() | ljid() get_nodes(Host, _From) -> get_nodes(Host). get_nodes(Host) -> @@ -143,21 +141,21 @@ get_nodes(Host) -> end. %% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() -%% Depth = integer() -%% Record = pubsubNode() +%% Host = mod_pubsub:host() | ljid() +%% Node = node() +%% From = ljid() +%% Depth = int() +%% Record = mod_pubsub:pubsub_node() %% @doc <p>Default node tree does not handle parents, return empty list.</p> get_parentnodes(_Host, _Node, _From) -> []. %% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() -%% Depth = integer() -%% Record = pubsubNode() +%% Host = mod_pubsub:host() | ljid() +%% Node = node() +%% From = ljid() +%% Depth = int() +%% Record = mod_pubsub:pubsub_node() %% @doc <p>Default node tree does not handle parents, return a list %% containing just this node.</p> get_parentnodes_tree(Host, Node, From) -> @@ -182,10 +180,10 @@ get_subnodes(Host, Node) -> [] end. -%% @spec (Host, Index, From) -> [pubsubNodeIdx()] | {error, Reason} +%% @spec (Host, Index, From) -> [nodeidx()] | {error, Reason} %% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() +%% Node = node() +%% From = ljid() get_subnodes_tree(Host, Node, _From) -> get_subnodes_tree(Host, Node). get_subnodes_tree(Host, Node) -> @@ -203,10 +201,10 @@ get_subnodes_tree(Host, Node) -> end. %% @spec (Host, Node, Type, Owner, Options, Parents) -> ok | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() -%% NodeType = mod_pubsub:nodeType() -%% Owner = mod_pubsub:jid() +%% Host = mod_pubsub:host() | ljid() +%% Node = node() +%% NodeType = nodeType() +%% Owner = ljid() %% Options = list() create_node(Host, Node, Type, Owner, Options, Parents) -> BJID = jlib:short_prepd_bare_jid(Owner), @@ -223,9 +221,9 @@ create_node(Host, Node, Type, Owner, Options, Parents) -> true; [Parent | _] -> case nodeid(Host, Parent) of - {result, PNodeId} -> + {result, Pidx} -> BHost = list_to_binary(Host), - case nodeowners(PNodeId) of + case nodeowners(Pidx) of [{undefined, BHost, undefined}] -> true; Owners -> lists:member(BJID, Owners) end; @@ -238,12 +236,11 @@ create_node(Host, Node, Type, Owner, Options, Parents) -> end, case ParentExists of true -> - case set_node(#pubsub_node{ - nodeid={Host, Node}, - parents=Parents, - type=Type, - options=Options}) of - {result, NodeId} -> {ok, NodeId}; + case set_node(#pubsub_node{id={Host, Node}, + parents=Parents, + type=Type, + options=Options}) of + {result, Nidx} -> {ok, Nidx}; Other -> Other end; false -> @@ -251,16 +248,16 @@ create_node(Host, Node, Type, Owner, Options, Parents) -> {error, 'forbidden'} end; {result, _} -> - %% NodeID already exists + %% Node already exists {error, 'conflict'}; Error -> Error end. -%% @spec (Host, Node) -> [mod_pubsub:node()] -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() +%% @spec (Host, Node) -> [node()] +%% Host = mod_pubsub:host() | ljid() +%% Node = node() delete_node(Host, Node) -> H = ?PUBSUB:escape(Host), N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)), @@ -273,11 +270,11 @@ delete_node(Host, Node) -> %% helpers -raw_to_node(Host, {Node, Parent, Type, NodeId}) -> +raw_to_node(Host, {Node, Parent, Type, Nidx}) -> Options = case catch ejabberd_odbc:sql_query_t( ["select name,val " "from pubsub_node_option " - "where nodeid='", NodeId, "';"]) + "where nodeid='", Nidx, "';"]) of {selected, ["name", "val"], ROptions} -> DbOpts = lists:map(fun({Key, Value}) -> @@ -295,16 +292,16 @@ raw_to_node(Host, {Node, Parent, Type, NodeId}) -> [] end, #pubsub_node{ - nodeid = {Host, ?PUBSUB:string_to_node(Node)}, + id = {Host, ?PUBSUB:string_to_node(Node)}, parents = [?PUBSUB:string_to_node(Parent)], - id = NodeId, + idx = Nidx, type = Type, options = Options}. %% @spec (NodeRecord) -> ok | {error, Reason} %% Record = mod_pubsub:pubsub_node() set_node(Record) -> - {Host, Node} = Record#pubsub_node.nodeid, + {Host, Node} = Record#pubsub_node.id, Parent = case Record#pubsub_node.parents of [] -> <<>>; [First | _] -> First @@ -313,29 +310,29 @@ set_node(Record) -> H = ?PUBSUB:escape(Host), N = ?PUBSUB:escape(?PUBSUB:node_to_string(Node)), P = ?PUBSUB:escape(?PUBSUB:node_to_string(Parent)), - NodeId = case nodeid(Host, Node) of - {result, OldNodeId} -> + Nidx = case nodeid(Host, Node) of + {result, OldNidx} -> catch ejabberd_odbc:sql_query_t( ["delete from pubsub_node_option " - "where nodeid='", OldNodeId, "';"]), + "where nodeid='", OldNidx, "';"]), catch ejabberd_odbc:sql_query_t( ["update pubsub_node " "set host='", H, "' " "node='", N, "' " "parent='", P, "' " "type='", Type, "' " - "where nodeid='", OldNodeId, "';"]), - OldNodeId; + "where nodeid='", OldNidx, "';"]), + OldNidx; _ -> catch ejabberd_odbc:sql_query_t( ["insert into pubsub_node(host, node, parent, type) " "values('", H, "', '", N, "', '", P, "', '", Type, "');"]), case nodeid(Host, Node) of - {result, NewNodeId} -> NewNodeId; - _ -> none % this should not happen + {result, NewNidx} -> NewNidx; + _ -> none % this should not happe end end, - case NodeId of + case Nidx of none -> {error, 'internal_server_error'}; _ -> @@ -344,9 +341,9 @@ set_node(Record) -> SValue = ?PUBSUB:escape(lists:flatten(io_lib:fwrite("~p",[Value]))), catch ejabberd_odbc:sql_query_t( ["insert into pubsub_node_option(nodeid, name, val) " - "values('", NodeId, "', '", SKey, "', '", SValue, "');"]) + "values('", Nidx, "', '", SKey, "', '", SValue, "');"]) end, Record#pubsub_node.options), - {result, NodeId} + {result, Nidx} end. nodeid(Host, Node) -> @@ -357,16 +354,16 @@ nodeid(Host, Node) -> "from pubsub_node " "where host='", H, "' and node='", N, "';"]) of - {selected, ["nodeid"], [{NodeId}]} -> - {result, NodeId}; + {selected, ["nodeid"], [{Nidx}]} -> + {result, Nidx}; {'EXIT', _Reason} -> {error, 'internal_server_error'}; _ -> {error, 'item_not_found'} end. -nodeowners(NodeId) -> - {result, Res} = node_flat_odbc:get_node_affiliations(NodeId), +nodeowners(Nidx) -> + {result, Res} = node_flat_odbc:get_node_affiliations(Nidx), lists:foldl(fun({LJID, owner}, Acc) -> [LJID|Acc]; (_, Acc) -> Acc end, [], Res). diff --git a/src/mod_pubsub/nodetree_virtual.erl b/src/mod_pubsub/nodetree_virtual.erl index 8433b9b54..c23ec82f9 100644 --- a/src/mod_pubsub/nodetree_virtual.erl +++ b/src/mod_pubsub/nodetree_virtual.erl @@ -33,8 +33,6 @@ -module(nodetree_virtual). -author('christophe.romain@process-one.net'). --include_lib("exmpp/include/exmpp.hrl"). - -include("pubsub.hrl"). -behaviour(gen_pubsub_nodetree). @@ -86,18 +84,19 @@ set_node(_NodeRecord) -> %% @spec (Host, Node, From) -> pubsubNode() %% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% Node = node() %% @doc <p>Virtual node tree does not handle a node database. Any node is considered %% as existing. Node record contains default values.</p> get_node(Host, Node, _From) -> get_node(Host, Node). get_node(Host, Node) -> - #pubsub_node{nodeid = {Host, Node}, id = {Host, Node}, owners = [{undefined, list_to_binary(Host), undefined}]}. + %% TODO : to fix idx + #pubsub_node{id = {Host, Node}, idx = {Host, Node}, owners = [{undefined, list_to_binary(Host), undefined}]}. get_node({Host, _} = NodeId) -> - #pubsub_node{nodeid = NodeId, id = NodeId, owners = [{undefined, list_to_binary(Host), undefined}]}. + #pubsub_node{id = NodeId, idx = NodeId, owners = [{undefined, list_to_binary(Host), undefined}]}. %% @spec (Host, From) -> [pubsubNode()] -%% Host = mod_pubsub:host() | mod_pubsub:jid() +%% Host = mod_pubsub:host() | ljid() %% @doc <p>Virtual node tree does not handle a node database. Any node is considered %% as existing. Nodes list can not be determined.</p> get_nodes(Host, _From) -> @@ -107,8 +106,8 @@ get_nodes(_Host) -> %% @spec (Host, Node, From) -> [pubsubNode()] %% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() +%% Node = node() +%% From = ljid() %% @doc <p>Virtual node tree does not handle parent/child. Child list is empty.</p> get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node). @@ -117,7 +116,7 @@ get_subnodes(_Host, _Node) -> %% @spec (Host, Index, From) -> [pubsubNode()] %% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% Node = node() %% @doc <p>Virtual node tree does not handle parent/child. Child list is empty.</p> get_subnodes_tree(Host, Node, _From) -> get_subnodes_tree(Host, Node). @@ -126,9 +125,9 @@ get_subnodes_tree(_Host, _Node) -> %% @spec (Host, Node, Type, Owner, Options, Parents) -> ok %% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% Type = mod_pubsub:nodeType() -%% Owner = mod_pubsub:jid() +%% Node = node() +%% Type = nodeType() +%% Owner = ljid() %% Options = list() %% @doc <p>No node record is stored on database. Any valid node %% is considered as already created.</p> @@ -143,7 +142,7 @@ create_node(Host, Node, _Type, Owner, _Options, _Parents) -> %% @spec (Host, Node) -> [mod_pubsub:node()] %% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() +%% Node = node() %% @doc <p>Virtual node tree does not handle parent/child. %% node deletion just affects the corresponding node.</p> delete_node(Host, Node) -> diff --git a/src/mod_pubsub/pubsub.hrl b/src/mod_pubsub/pubsub.hrl index 9fd5ebd1c..832b4d8c4 100644 --- a/src/mod_pubsub/pubsub.hrl +++ b/src/mod_pubsub/pubsub.hrl @@ -21,6 +21,11 @@ %%% This file contains pubsub types definition. %%% ==================================================================== + +-include_lib("exmpp/include/exmpp.hrl"). +-include_lib("exmpp/include/exmpp_jid.hrl"). + + %% ------------------------------- %% Pubsub constants -define(ERR_EXTENDED(E,C), mod_pubsub:extended_error(E,C)). @@ -32,19 +37,176 @@ %% Would be nice to have it configurable. -define(MAX_PAYLOAD_SIZE, 60000). -%% ------------------------------- + +%% ------------ %% Pubsub types +%% ------------ + +%%% @type hostPubsub() = binary(). +%%% +%%% <p><tt>hostPubsub</tt> is the name of the PubSub service. For example, it can be +%%% <tt>pubsub.localhost</tt>.</p> + +-type(hostPubsub() :: binary()). + + +%%% @type hostPEP() = {User, Server, Resource} +%%% User = binary() +%%% Server = binary() +%%% Resource = undefined. + +-type(hostPEP() :: {User::binary(), Server::binary, Resource::undefined}). + + +%%% @type host() = hostPubsub() | hostPEP(). + +-type(host() :: hostPubsub() | hostPEP()). + + +%% TODO : move upper in exmpp +%%% @type nodeId() = binary(). +%%% +%%% <p>A <tt>nodeId</tt> is the name of a Node. It can be anything and may represent +%%% some hierarchical tree depending of the node type. +%%% For example: +%%% /home/localhost/user/node +%%% princely_musings +%%% http://jabber.org/protocol/tune +%%% My-Own_Node</p> + +-type(nodeId() :: binary()). + + +%%% @type itemId() = binary(). +%%% +%%% <p>An <tt>itemId</tt> is the name of an Item. It can be anything. +%%% For example: +%%% 38964 +%%% my-tune +%%% FD6SBE6a27d</p> + +-type(itemId() :: binary()). + + +%%% @type subId() = binary(). + +-type(subId() :: binary()). + + +%%% @type nodeType() = string(). +%%% +%%% <p>The <tt>nodeType</tt> is a string containing the name of the PubSub +%%% plugin to use to manage a given node. For example, it can be +%%% <tt>"flat"</tt>, <tt>"hometree"</tt> or <tt>"blog"</tt>.</p> + +-type(nodeType() :: string()). + + +%%% @type ljid() = {User, Server, Resource} +%%% User = undefined | binary() +%%% Server = binary() +%%% Resource = undefined | binary(). + +-type(ljid() :: {User::binary(), Server::binary(), Resource::binary()}). + + +%% TODO : move upper in exmpp +%%% @type jidComponent() = {jid, Raw, Node, Domain, Resource} +%%% Raw = binary() +%%% Node = undefined +%%% Domain = binary() +%%% Resource = undefined. + +-type(jidComponent() :: + #jid{raw::binary(), node::undefined, domain::binary(), resource::undefined}). + + +%% TODO : move upper in exmpp +%%% @type jidContact() = {jid, Raw, Node, Domain, Resource} +%%% Raw = binary() +%%% Node = binary() +%%% Domain = binary() +%%% Resource = undefined. + +-type(jidContact() :: + #jid{raw::binary(), node::binary(), domain::binary(), resource::undefined}). + + +%% TODO : move upper in exmpp +%%% @type jidEntity() = {jid, Raw, Node, Domain, Resource} +%%% Raw = binary() +%%% Node = undefined | binary() +%%% Domain = binary() +%%% Resource = undefined | binary(). + + +-type(jidEntity() :: + %% Contact bare JID + #jid{raw::binary(), node::binary(), domain::binary(), resource::undefined} | + %% Contact full JID + #jid{raw::binary(), node::binary(), domain::binary(), resource::binary()} | + %% Component bare JID + #jid{raw::binary(), node::undefined, domain::binary(), resource::undefined} | + %% Component full JID + #jid{raw::binary(), node::undefined, domain::binary(), resource::binary()}). + + +%%% @type bareUsr() = {User, Server, Resource} +%%% User = undefined | binary() +%%% Server = binary() +%%% Resource = undefined. + +-type(bareUsr() :: {User::binary(), Server::binary(), Resource::undefined} + | {User::undefined, Server::binary(), Resource::undefined}). + + +%%% @type fullUsr() = {User, Server, Resource} +%%% User = undefined | binary() +%%% Server = binary() +%%% Resource = undefined | binary(). + + +-type(fullUsr() :: {User::binary(), Server::binary(), Resource::undefined} + | {User::binary(), Server::binary(), Resource::binary()} + | {User::undefined, Server::binary(), Resource::undefined} + | {User::undefined, Server::binary(), Resource::binary()}). + + +%%% @type nodeIdx() = integer(). -%%% @type host() = string(). -%%% <p><tt>host</tt> is the name of the PubSub service. For example, it can be -%%% <tt>"pubsub.localhost"</tt>.</p> +-type(nodeIdx() :: integer()). + + +%%% @type now() = {Megaseconds, Seconds, Microseconds} +%%% Megaseconds = integer() +%%% Seconds = integer() +%%% Microseconds = integer(). + +-type(now() :: {Megaseconds::integer(), Seconds::integer(), Microseconds::integer()}). + + +%%% @type affiliation() = 'none' | 'owner' | 'publisher' |'publish-only' | 'member' | 'outcast'. + +-type(affiliation() :: 'none' | 'owner' | 'publisher' |'publish-only' | 'member' | 'outcast'). + + +%%% @type subscription() = 'none' | 'pending' | 'unconfigured' | 'subscribed'. + +-type(subscription() :: 'none' | 'pending' | 'unconfigured' | 'subscribed'). + + +%%% @type accessModel() = 'open' | 'presence' | 'roster' | 'authorize' | 'whitelist'. + +-type(accessModel() :: 'open' | 'presence' | 'roster' | 'authorize' | 'whitelist'). + + +%%% @type payload() = [] | [#xmlel{}]. + +-type(payload() :: [] | [#xmlel{}]). -%%% @type pubsubNode() = [string()]. -%%% <p>A node is defined by a list of its ancestors. The last element is the name -%%% of the current node. For example: -%%% ```["home", "localhost", "cromain", "node1"]'''</p> %%% @type stanzaError() = #xmlel{}. +%%% %%% Example: %%% ```#xmlel{name = 'error' %%% ns = ?NS_STANZAS, @@ -62,7 +224,11 @@ %%% } %%% ]}''' +-type(stanzaError() :: #xmlel{}). + + %%% @type pubsubIQResponse() = #xmlel{}. +%%% %%% Example: %%% ```#xmlel{name = 'pubsub', %%% ns = ?NS_PUBSUB, @@ -73,89 +239,145 @@ %%% ] %%% }''' -%%% @type nodeOption() = {Option::atom(), Value::term()}. +-type(pubsubIQResponse() :: #xmlel{}). + + +%%% @type features() = [Feature] +%%% Feature = string(). + +-type(features() :: [Feature::string()]). + +%%% @type nodeOption() = {Option, Value}. +%%% Option = atom() +%%% Value = term(). +%%% %%% Example: %%% ```{deliver_payloads, true}''' -%%% @type nodeType() = string(). -%%% <p>The <tt>nodeType</tt> is a string containing the name of the PubSub -%%% plugin to use to manage a given node. For example, it can be -%%% <tt>"flat"</tt>, <tt>"hometree"</tt> or <tt>"blog"</tt>.</p> +-type(nodeOption() :: {Option::atom(), Value::term()}). -%%% @type jid() = #jid{ -%%% user = string(), -%%% server = string(), -%%% resource = string(), -%%% luser = string(), -%%% lserver = string(), -%%% lresource = string()}. -%%% @type ljid() = {User::string(), Server::string(), Resource::string()}. +%%% @type subOption() = {Option, Value}. +%%% Option = atom() +%%% Value = term(). -%%% @type affiliation() = none | owner | publisher | outcast. -%%% @type subscription() = none | pending | unconfigured | subscribed. +-type(subOption() :: {Option::atom(), Value::term()}). -%%% internal pubsub index table --record(pubsub_index, {index, last, free}). -%%% @type pubsubNode() = #pubsub_node{ -%%% nodeid = {Host::host(), Node::pubsubNode()}, -%%% parentid = Node::pubsubNode(), -%%% nodeidx = int(), -%%% type = nodeType(), -%%% options = [nodeOption()]}. +%%% @type pubsubIndex() = {pubsub_index, Index, Last, Free}. +%%% Index = atom() +%%% Last = nodeIdx() +%%% Free = [nodeIdx()]. +%%% +%%% Internal pubsub index table. + +-record(pubsub_index, + { + index :: atom(), + last :: integer(), + free :: [integer()] + }). + +-type(pubsubIndex() :: #pubsub_index{}). + + +%%% @type pubsubNode() = {pubsub_node, Id, Idx, Parents, Type, Owners, Options} +%%% Id = {host(), nodeId()} +%%% Idx = nodeIdx() +%%% Parents = [nodeId()] +%%% Type = nodeType() +%%% Owners = [bareUsr()] +%%% Options = [nodeOption()]. +%%% %%% <p>This is the format of the <tt>nodes</tt> table. The type of the table %%% is: <tt>set</tt>,<tt>ram/disc</tt>.</p> -%%% <p>The <tt>parentid</tt> and <tt>type</tt> fields are indexed.</p> -%%% <p><tt>nodeidx</tt> can be anything you want.</p> --record(pubsub_node, {nodeid, - id, - parents = [], - type = "flat", - owners = [], - options = [] - }). - -%%% @type pubsubState() = #pubsub_state{ -%%% stateid = {ljid(), nodeidx()}, -%%% items = [ItemId::string()], -%%% affiliation = affiliation(), -%%% subscriptions = [subscription()]}. +%%% <p>The <tt>parents</tt> and <tt>type</tt> fields are indexed.</p> +%%% <p><tt>idx</tt> is an integer.</p> + +-record(pubsub_node, + { + id :: {host(), nodeId()}, + idx :: nodeIdx(), + parents = [] :: [nodeId()], + type = "flat" :: nodeType(), + owners = [] :: [bareUsr()], + options = [] :: [nodeOption()] + }). + +-type(pubsubNode() :: #pubsub_node{}). + + +%%% @type pubsubState() = {pubsub_state, Id, Items, Affiliation, Subscriptions} +%%% Id = {fullUsr(), nodeIdx()} +%%% Items = [itemId()] +%%% Affiliation = affiliation() +%%% Subscriptions = [{subscription(), subId()}]. +%%% %%% <p>This is the format of the <tt>affiliations</tt> table. The type of the %%% table is: <tt>set</tt>,<tt>ram/disc</tt>.</p> --record(pubsub_state, {stateid, - items = [], - affiliation = none, - subscriptions = [] -}). - -%%% @type pubsubItem() = #pubsub_item{ -%%% itemid = {ItemId::string(), nodeidx()}, -%%% creation = {now(), ljid()}, -%%% modification = {now(), ljid()}, -%%% payload = XMLContent::string()}. + +-record(pubsub_state, + { + id :: {fullUsr(), nodeIdx()}, + items = [] :: [itemId()], + affiliation = 'none' :: affiliation(), + subscriptions = [] :: [{subscription(), subId()}] + }). + +-type(pubsubState() :: #pubsub_state{}). + + +%%% @type pubsubItem() = {pubsub_item, Id, Creation, Modification, Payload} +%%% Id = {itemId(), nodeIdx()} +%%% Creation = {now(), bareUsr()} +%%% Modification = {now(), fullUsr()} +%%% Payload = payload(). +%%% %%% <p>This is the format of the <tt>published items</tt> table. The type of the %%% table is: <tt>set</tt>,<tt>disc</tt>,<tt>fragmented</tt>.</p> --record(pubsub_item, {itemid, - creation = {unknown,unknown}, - modification = {unknown,unknown}, - payload = [] - }). - -%% @type pubsubSubscription() = #pubsub_subscription{ -%% subid = string(), -%% state_key = {ljid(), pubsubNodeId()}, -%% options = [{atom(), term()}] -%% }. + +-record(pubsub_item, + { + id :: {itemId(), nodeIdx()}, + creation = {unknown,unknown} :: {now(), bareUsr()}, + modification = {unknown,unknown} :: {now(), fullUsr()}, + payload = [] :: payload() + }). + +-type(pubsubItem() :: #pubsub_item{}). + + +%%% @type pubsubSubscription() = {pubsub_subscription, SubId, Options} +%%% SubId = subId() +%%% Options = [nodeOption()]. +%%% %% <p>This is the format of the <tt>subscriptions</tt> table. The type of the %% table is: <tt>set</tt>,<tt>ram/disc</tt>.</p> --record(pubsub_subscription, {subid, options}). -%% @type pubsubLastItem() = #pubsub_last_item{ -%% nodeid = nodeidx(), -%% itemid = string(), -%% creation = {now(), ljid()}, -%% payload = XMLContent::string()}. +-record(pubsub_subscription, + { + subid :: subId(), + options :: [subOption()] + }). + +-type(pubsubSubscription() :: #pubsub_subscription{}). + + +%%% @type pubsubLastItem() = {pubsub_last_item, NodeId, ItemId, Creation, Payload} +%%% NodeId = nodeIdx() +%%% ItemId = itemId() +%%% Creation = {now(), bareUsr()} +%%% Payload = payload(). +%%% %% <p>This is the format of the <tt>last items</tt> table. it stores last item payload %% for every node</p> --record(pubsub_last_item, {nodeid, itemid, creation, payload}). + +-record(pubsub_last_item, + { + nodeid :: nodeIdx(), + itemid :: itemId(), + creation :: {now(), bareUsr()}, + payload :: payload() + }). + +-type(pubsubLastItem() :: #pubsub_last_item{}). diff --git a/src/mod_pubsub/pubsub_db_odbc.erl b/src/mod_pubsub/pubsub_db_odbc.erl index dfdcbbc2c..42811786b 100644 --- a/src/mod_pubsub/pubsub_db_odbc.erl +++ b/src/mod_pubsub/pubsub_db_odbc.erl @@ -32,27 +32,27 @@ %% Those -spec lines produce errors in old Erlang versions. %% They can be enabled again in ejabberd 3.0 because it uses R12B or higher. --spec read_subscription(SubID :: string()) -> {ok, #pubsub_subscription{}} | notfound. -read_subscription(SubID) -> +-spec read_subscription(SubId :: string()) -> {ok, #pubsub_subscription{}} | notfound. +read_subscription(SubId) -> case ejabberd_odbc:sql_query_t( ["select opt_name, opt_value " "from pubsub_subscription_opt " - "where subid = '", ejabberd_odbc:escape(SubID), "'"]) of + "where subid = '", ejabberd_odbc:escape(SubId), "'"]) of {selected, ["opt_name", "opt_value"], []} -> notfound; {selected, ["opt_name", "opt_value"], Options} -> - {ok, #pubsub_subscription{subid = SubID, + {ok, #pubsub_subscription{subid = SubId, options = lists:map(fun subscription_opt_from_odbc/1, Options)}} end. --spec delete_subscription(SubID :: string()) -> ok. -delete_subscription(SubID) -> +-spec delete_subscription(SubId :: string()) -> ok. +delete_subscription(SubId) -> ejabberd_odbc:sql_query_t(["delete from pubsub_subscription_opt " - "where subid = '", ejabberd_odbc:escape(SubID), "'"]), + "where subid = '", ejabberd_odbc:escape(SubId), "'"]), ok. diff --git a/src/mod_pubsub/pubsub_index.erl b/src/mod_pubsub/pubsub_index.erl index 6cde91dcc..3b1601bc8 100644 --- a/src/mod_pubsub/pubsub_index.erl +++ b/src/mod_pubsub/pubsub_index.erl @@ -31,35 +31,58 @@ -include("pubsub.hrl"). --export([init/3, new/1, free/2]). +-export([ + init/3, + new/1, + free/2 + ]). + + +-spec(init/3 :: + ( + Host :: string(), + ServerHost :: string(), + Opts :: [{Key::atom(), Value::term()}]) + -> 'ok' + ). init(_Host, _ServerHost, _Opts) -> mnesia:create_table(pubsub_index, [{disc_copies, [node()]}, {attributes, record_info(fields, pubsub_index)}]). + +-spec(new/1 :: + ( + Index::atom()) + -> Idx::integer() + ). + new(Index) -> case mnesia:read({pubsub_index, Index}) of - [I] -> - case I#pubsub_index.free of - [] -> - Id = I#pubsub_index.last + 1, - mnesia:write(I#pubsub_index{last = Id}), - Id; - [Id|Free] -> - mnesia:write(I#pubsub_index{free = Free}), - Id - end; - _ -> - mnesia:write(#pubsub_index{index = Index, last = 1, free = []}), - 1 + [#pubsub_index{free = [], last = Last} = PubsubIndex] -> + Idx = Last + 1, + mnesia:write(PubsubIndex#pubsub_index{last = Idx}), + Idx; + [#pubsub_index{free = [Idx|Free]} = PubsubIndex] -> + mnesia:write(PubsubIndex#pubsub_index{free = Free}), + Idx; + _ -> + mnesia:write(#pubsub_index{index = Index, last = 1, free = []}), + 1 end. -free(Index, Id) -> + +-spec(free/2 :: + ( + Index :: atom(), + Idx :: integer()) + -> 'ok' + ). + +free(Index, Idx) -> case mnesia:read({pubsub_index, Index}) of - [I] -> - Free = I#pubsub_index.free, - mnesia:write(I#pubsub_index{free = [Id|Free]}); - _ -> - ok + [#pubsub_index{free = Free} = PubsubIndex] -> + mnesia:write(PubsubIndex#pubsub_index{free = [Idx|Free]}); + _ -> ok end. diff --git a/src/mod_pubsub/pubsub_odbc.patch b/src/mod_pubsub/pubsub_odbc.patch index 4ca79a9bd..5309386ff 100644 --- a/src/mod_pubsub/pubsub_odbc.patch +++ b/src/mod_pubsub/pubsub_odbc.patch @@ -1,5 +1,5 @@ ---- mod_pubsub.erl 2010-08-04 18:28:18.000000000 +0200 -+++ mod_pubsub_odbc.erl 2010-08-04 18:29:41.000000000 +0200 +--- mod_pubsub.erl 2010-09-23 10:43:43.000000000 +0200 ++++ mod_pubsub_odbc.erl 2010-09-29 11:46:22.000000000 +0200 @@ -42,7 +42,7 @@ %%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see %%% XEP-0060 section 12.18. @@ -9,7 +9,7 @@ -author('christophe.romain@process-one.net'). -version('1.13-0'). -@@ -55,9 +55,9 @@ +@@ -53,9 +53,9 @@ -include("adhoc.hrl"). -include("pubsub.hrl"). @@ -22,7 +22,7 @@ %% exports for hooks -export([presence_probe/3, -@@ -104,7 +104,7 @@ +@@ -102,7 +102,7 @@ string_to_affiliation/1, extended_error/2, extended_error/3, @@ -31,7 +31,7 @@ ]). %% API and gen_server callbacks -@@ -123,7 +123,7 @@ +@@ -121,7 +121,7 @@ -export([send_loop/1 ]). @@ -40,7 +40,7 @@ -define(LOOPNAME, ejabberd_mod_pubsub_loop). -define(PLUGIN_PREFIX, "node_"). -define(TREE_PREFIX, "nodetree_"). -@@ -220,8 +220,6 @@ +@@ -218,8 +218,6 @@ ok end, ejabberd_router:register_route(Host), @@ -49,7 +49,7 @@ init_nodes(Host, ServerHost, NodeTree, Plugins), State = #state{host = Host, server_host = ServerHost, -@@ -280,206 +278,15 @@ +@@ -278,209 +276,14 @@ init_nodes(Host, ServerHost, _NodeTree, Plugins) -> %% TODO, this call should be done plugin side @@ -59,7 +59,7 @@ - create_node(Host, ServerHost, string_to_node("/home"), service_jid(Host), "hometree"), - create_node(Host, ServerHost, string_to_node("/home/" ++ ServerHost), service_jid(Host), "hometree"); + create_node(Host, ServerHost, string_to_node("/home"), service_jid(Host), "hometree_odbc"), -+ create_node(Host, ServerHost, string_to_node("/home/" ++ ServerHost), service_jid(Host), "hometree_odbc"); ++ create_node(Host, ServerHost, string_to_node("/home/" ++ ServerHost), service_jid(Host), "hometree_odbc"); false -> ok end. @@ -72,18 +72,18 @@ - ?INFO_MSG("upgrade node pubsub tables",[]), - F = fun() -> - {Result, LastIdx} = lists:foldl( -- fun({pubsub_node, NodeId, ParentId, {nodeinfo, Items, Options, Entities}}, {RecList, NodeIdx}) -> +- fun({pubsub_node, NodeId, ParentId, {nodeinfo, Items, Options, Entities}}, {RecList, Nidx}) -> - ItemsList = - lists:foldl( -- fun({item, IID, Publisher, Payload}, Acc) -> +- fun({item, ItemName, Publisher, Payload}, Acc) -> - C = {unknown, Publisher}, - M = {now(), Publisher}, - mnesia:write( -- #pubsub_item{itemid = {IID, NodeIdx}, +- #pubsub_item{id = {ItemName, Nidx}, - creation = C, - modification = M, - payload = Payload}), -- [{Publisher, IID} | Acc] +- [{Publisher, ItemName} | Acc] - end, [], Items), - Owners = - dict:fold( @@ -97,7 +97,7 @@ - end - end, [], ItemsList), - mnesia:write({pubsub_state, -- {JID, NodeIdx}, +- {JID, Nidx}, - UsrItems, - Aff, - Sub}), @@ -107,12 +107,12 @@ - end - end, [], Entities), - mnesia:delete({pubsub_node, NodeId}), -- {[#pubsub_node{nodeid = NodeId, -- id = NodeIdx, +- {[#pubsub_node{id = NodeId, +- idx = Nidx, - parents = [element(2, ParentId)], - owners = Owners, - options = Options} | -- RecList], NodeIdx + 1} +- RecList], Nidx + 1} - end, {[], 1}, - mnesia:match_object( - {pubsub_node, {Host, '_'}, '_', '_'})), @@ -137,32 +137,33 @@ - [nodeid, parentid, type, owners, options] -> - F = fun({pubsub_node, NodeId, {_, Parent}, Type, Owners, Options}) -> - #pubsub_node{ -- nodeid = NodeId, -- id = 0, +- id = NodeId, +- idx = 0, - parents = [Parent], - type = Type, - owners = Owners, - options = Options} - end, +- %% TODO : to change nodeid/id and id/idx or not to change ? - mnesia:transform_table(pubsub_node, F, [nodeid, id, parents, type, owners, options]), - FNew = fun() -> -- LastIdx = lists:foldl(fun(#pubsub_node{nodeid = NodeId} = PubsubNode, NodeIdx) -> -- mnesia:write(PubsubNode#pubsub_node{id = NodeIdx}), -- lists:foreach(fun(#pubsub_state{stateid = StateId} = State) -> +- LastIdx = lists:foldl(fun(#pubsub_node{id = NodeId} = PubsubNode, Nidx) -> +- mnesia:write(PubsubNode#pubsub_node{idx = Nidx}), +- lists:foreach(fun(#pubsub_state{id = StateId} = State) -> - {JID, _} = StateId, - mnesia:delete({pubsub_state, StateId}), -- mnesia:write(State#pubsub_state{stateid = {JID, NodeIdx}}) -- end, mnesia:match_object(#pubsub_state{stateid = {'_', NodeId}, _ = '_'})), -- lists:foreach(fun(#pubsub_item{itemid = ItemId} = Item) -> -- {IID, _} = ItemId, +- mnesia:write(State#pubsub_state{id = {JID, Nidx}}) +- end, mnesia:match_object(#pubsub_state{id = {'_', NodeId}, _ = '_'})), +- lists:foreach(fun(#pubsub_item{id = ItemId} = Item) -> +- {ItemName, _} = ItemId, - {M1, M2} = Item#pubsub_item.modification, - {C1, C2} = Item#pubsub_item.creation, - mnesia:delete({pubsub_item, ItemId}), -- mnesia:write(Item#pubsub_item{itemid = {IID, NodeIdx}, +- mnesia:write(Item#pubsub_item{id = {ItemName, Nidx}, - modification = {M2, M1}, - creation = {C2, C1}}) -- end, mnesia:match_object(#pubsub_item{itemid = {'_', NodeId}, _ = '_'})), -- NodeIdx + 1 +- end, mnesia:match_object(#pubsub_item{id = {'_', NodeId}, _ = '_'})), +- Nidx + 1 - end, 1, mnesia:match_object( - {pubsub_node, {Host, '_'}, '_', '_', '_', '_', '_'}) - ++ mnesia:match_object( @@ -179,13 +180,14 @@ - [nodeid, id, parent, type, owners, options] -> - F = fun({pubsub_node, NodeId, Id, Parent, Type, Owners, Options}) -> - #pubsub_node{ -- nodeid = NodeId, -- id = Id, +- id = NodeId, +- idx = Id, - parents = [Parent], - type = Type, - owners = Owners, - options = Options} - end, +- %% TODO : to change nodeid/id and id/idx or not to change ? - mnesia:transform_table(pubsub_node, F, [nodeid, id, parents, type, owners, options]), - rename_default_nodeplugin(); - _ -> @@ -203,7 +205,7 @@ - [<<>>] -> []; - Parents -> Parents - end, -- mnesia:write(Node#pubsub_node{nodeid={H, BN}, parents=BP}), +- mnesia:write(Node#pubsub_node{id={H, BN}, parents=BP}), - mnesia:delete({pubsub_node, {H, N}}); - (_) -> - ok @@ -222,15 +224,15 @@ - case catch mnesia:table_info(pubsub_state, attributes) of - [stateid, items, affiliation, subscription] -> - ?INFO_MSG("upgrade state pubsub tables", []), -- F = fun ({pubsub_state, {JID, NodeID}, Items, Aff, Sub}, Acc) -> +- F = fun ({pubsub_state, {JID, NodeId}, Items, Aff, Sub}, Acc) -> - Subs = case Sub of - none -> - []; - _ -> -- {result, SubID} = pubsub_subscription:subscribe_node(JID, NodeID, []), -- [{Sub, SubID}] +- {result, SubId} = pubsub_subscription:subscribe_node(JID, NodeId, []), +- [{Sub, SubId}] - end, -- NewState = #pubsub_state{stateid = {JID, NodeID}, +- NewState = #pubsub_state{id = {JID, NodeId}, - items = Items, - affiliation = Aff, - subscriptions = Subs}, @@ -256,11 +258,11 @@ - _ -> - ok - end. -+ - +- send_loop(State) -> receive -@@ -491,7 +298,10 @@ + {presence, JID, Pid} -> +@@ -491,7 +294,10 @@ %% for each node From is subscribed to %% and if the node is so configured, send the last published item to From lists:foreach(fun(PType) -> @@ -272,37 +274,37 @@ lists:foreach( fun({Node, subscribed, _, SubJID}) -> if (SubJID == LJID) or (SubJID == BJID) -> -@@ -616,7 +426,8 @@ +@@ -616,7 +422,8 @@ [#xmlel{name = 'identity', ns = ?NS_DISCO_INFO, attrs = [?XMLATTR('category', <<"pubsub">>), ?XMLATTR('type', <<"pep">>)]}]; disco_identity(Host, Node, From) -> -- Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> -+ Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> -+ Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of +- Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) -> ++ Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) -> ++ Owners = node_owners_call(Type, Nidx), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, _} -> {result, -@@ -647,7 +458,8 @@ +@@ -647,7 +454,8 @@ [?NS_PUBSUB_s | [?NS_PUBSUB_s++"#"++Feature || Feature <- features("pep")]]; disco_features(Host, Node, From) -> -- Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> -+ Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> -+ Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of +- Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) -> ++ Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) -> ++ Owners = node_owners_call(Type, Nidx), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, _} -> {result, [?NS_PUBSUB_s -@@ -666,7 +478,8 @@ +@@ -666,7 +474,8 @@ {result, disco_items(To, Node, From) ++ OtherItems}. disco_items(Host, <<>>, From) -> -- Action = fun(#pubsub_node{nodeid ={_, NodeID}, options = Options, type = Type, id = Idx, owners = Owners}, Acc) -> -+ Action = fun(#pubsub_node{nodeid ={_, NodeID}, options = Options, type = Type, id = Idx}, Acc) -> -+ Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of +- Action = fun(#pubsub_node{id ={_, NodeId}, options = Options, type = Type, idx = Nidx, owners = Owners}, Acc) -> ++ Action = fun(#pubsub_node{id ={_, NodeId}, options = Options, type = Type, idx = Nidx}, Acc) -> ++ Owners = node_owners_call(Type, Nidx), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, _} -> [#xmlel{name = 'item', ns = ?NS_DISCO_INFO, -@@ -680,13 +493,14 @@ +@@ -680,13 +489,14 @@ _ -> Acc end end, @@ -313,26 +315,26 @@ end; disco_items(Host, Node, From) -> -- Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> -+ Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> -+ Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of +- Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) -> ++ Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) -> ++ Owners = node_owners_call(Type, Nidx), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, Items} -> {result, -@@ -771,10 +585,10 @@ +@@ -772,10 +582,10 @@ lists:foreach(fun(PType) -> {result, Subscriptions} = node_action(Host, PType, get_entity_subscriptions, [Host, Entity]), lists:foreach(fun -- ({#pubsub_node{options = Options, owners = Owners, id = NodeId}, subscribed, _, JID}) -> -+ ({#pubsub_node{options = Options, id = NodeId}, subscribed, _, JID}) -> +- ({#pubsub_node{options = Options, owners = Owners, idx = Nidx}, subscribed, _, JID}) -> ++ ({#pubsub_node{options = Options, idx = Nidx}, subscribed, _, JID}) -> case get_option(Options, access_model) of presence -> - case lists:member(BJID, Owners) of -+ case lists:member(BJID, node_owners(Host, PType, NodeId)) of ++ case lists:member(BJID, node_owners(Host, PType, Nidx)) of true -> - node_action(Host, PType, unsubscribe_node, [NodeId, Entity, JID, all]); + node_action(Host, PType, unsubscribe_node, [Nidx, Entity, JID, all]); false -> -@@ -949,10 +763,11 @@ +@@ -950,10 +760,11 @@ end, ejabberd_router:route(To, From, Res); #iq{type = get, ns = ?NS_DISCO_ITEMS, @@ -346,16 +348,16 @@ {result, IQRes} -> Result = #xmlel{ns = ?NS_DISCO_ITEMS, name = 'query', attrs = QAttrs, -@@ -1089,7 +904,7 @@ +@@ -1090,7 +901,7 @@ [] -> ["leaf"]; %% No sub-nodes: it's a leaf node _ -> -- case node_call(Type, get_items, [NodeId, From]) of -+ case node_call(Type, get_items, [NodeId, From, none]) of +- case node_call(Type, get_items, [Nidx, From]) of ++ case node_call(Type, get_items, [Nidx, From, none]) of {result, []} -> ["collection"]; {result, _} -> ["leaf", "collection"]; _ -> [] -@@ -1105,8 +920,9 @@ +@@ -1106,8 +917,9 @@ []; true -> [#xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_PUBSUB_s)]} | @@ -367,7 +369,7 @@ end, features(Type))] end, %% TODO: add meta-data info (spec section 5.4) -@@ -1135,8 +951,9 @@ +@@ -1136,8 +948,9 @@ #xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_PUBSUB_s)]}, #xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_ADHOC_s)]}, #xmlel{ns = ?NS_DISCO_INFO, name = 'feature', attrs = [?XMLATTR('var', ?NS_VCARD_s)]}] ++ @@ -379,7 +381,7 @@ end, features(Host, Node))}; ?NS_ADHOC_b -> command_disco_info(Host, Node, From); -@@ -1146,7 +963,7 @@ +@@ -1147,7 +960,7 @@ node_disco_info(Host, Node, From) end. @@ -388,7 +390,7 @@ case tree_action(Host, get_subnodes, [Host, <<>>, From]) of Nodes when is_list(Nodes) -> {result, lists:map( -@@ -1163,7 +980,7 @@ +@@ -1164,7 +977,7 @@ Other -> Other end; @@ -397,7 +399,7 @@ %% TODO: support localization of this string CommandItems = [ #xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', -@@ -1172,19 +989,20 @@ +@@ -1173,19 +986,20 @@ ?XMLATTR('name', "Get Pending") ]}], {result, CommandItems}; @@ -408,22 +410,22 @@ -iq_disco_items(Host, Item, From) -> +iq_disco_items(Host, Item, From, RSM) -> case string:tokens(Item, "!") of - [_SNode, _ItemID] -> + [_SNode, _ItemId] -> {result, []}; [SNode] -> Node = string_to_node(SNode), -- Action = fun(#pubsub_node{id = Idx, type = Type, options = Options, owners = Owners}) -> -- NodeItems = case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of -+ Action = fun(#pubsub_node{id = Idx, type = Type, options = Options}) -> -+ Owners = node_owners_call(Type, Idx), -+ {NodeItems, RsmOut} = case get_allowed_items_call(Host, Idx, From, Type, Options, Owners, RSM) of +- Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options, owners = Owners}) -> +- NodeItems = case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of ++ Action = fun(#pubsub_node{idx = Nidx, type = Type, options = Options}) -> ++ Owners = node_owners_call(Type, Nidx), ++ {NodeItems, RsmOut} = case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners, RSM) of {result, R} -> R; - _ -> [] + _ -> {[], none} end, Nodes = lists:map( - fun(#pubsub_node{nodeid = {_, SubNode}, options = SubOptions}) -> -@@ -1202,7 +1020,7 @@ + fun(#pubsub_node{id = {_, SubNode}, options = SubOptions}) -> +@@ -1203,7 +1017,7 @@ {result, Name} = node_call(Type, get_item_name, [Host, Node, RN]), #xmlel{ns = ?NS_DISCO_ITEMS, name = 'item', attrs = [?XMLATTR('jid', Host), ?XMLATTR('name', Name)]} end, NodeItems), @@ -432,30 +434,29 @@ end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Result}} -> {result, Result}; -@@ -1210,12 +1028,6 @@ +@@ -1211,12 +1025,6 @@ end end. --get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) -> +-get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) -> - AccessModel = get_option(Options, access_model), - AllowedGroups = get_option(Options, roster_groups_allowed, []), - {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups), -- node_call(Type, get_items, [NodeIdx, From, AccessModel, PresenceSubscription, RosterGroup, undefined]). +- node_call(Type, get_items, [Nidx, From, AccessModel, PresenceSubscription, RosterGroup, undefined]). - get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups) -> if (AccessModel == presence) or (AccessModel == roster) -> case Host of -@@ -1333,7 +1145,8 @@ +@@ -1334,7 +1142,7 @@ (_, Acc) -> Acc end, [], exmpp_xml:remove_cdata_from_list(Els)), -- get_items(Host, Node, From, SubId, MaxItems, ItemIDs); -+ RSM = jlib:rsm_decode(SubEl), -+ get_items(Host, Node, From, SubId, MaxItems, ItemIDs, RSM); +- get_items(Host, Node, From, SubId, MaxItems, ItemIds); ++ get_items(Host, Node, From, SubId, MaxItems, ItemIds, jlib:rsm_decode(SubEl)); {get, 'subscriptions'} -> get_subscriptions(Host, Node, From, Plugins); {get, 'affiliations'} -> -@@ -1490,7 +1303,8 @@ +@@ -1491,7 +1299,8 @@ _ -> [] end end, @@ -465,36 +466,36 @@ sync_dirty) of {result, Res} -> Res; Err -> Err -@@ -1534,7 +1348,7 @@ +@@ -1535,7 +1344,7 @@ %%% authorization handling --send_authorization_request(#pubsub_node{owners = Owners, nodeid = {Host, Node}}, Subscriber) -> -+send_authorization_request(#pubsub_node{nodeid = {Host, Node}, type = Type, id = NodeId}, Subscriber) -> +-send_authorization_request(#pubsub_node{owners = Owners, id = {Host, Node}}, Subscriber) -> ++send_authorization_request(#pubsub_node{id = {Host, Node}, type = Type, idx = Nidx}, Subscriber) -> Lang = <<"en">>, %% TODO fix {U, S, R} = Subscriber, Stanza = #xmlel{ns = ?NS_JABBER_CLIENT, name = 'message', children = -@@ -1564,7 +1378,7 @@ +@@ -1565,7 +1374,7 @@ lists:foreach(fun(Owner) -> {U, S, R} = Owner, ejabberd_router:route(service_jid(Host), exmpp_jid:make(U, S, R), Stanza) - end, Owners). -+ end, node_owners(Host, Type, NodeId)). ++ end, node_owners(Host, Type, Nidx)). find_authorization_response(Packet) -> Els = Packet#xmlel.children, -@@ -1623,8 +1437,8 @@ +@@ -1624,8 +1433,8 @@ "true" -> true; _ -> false end, -- Action = fun(#pubsub_node{type = Type, owners = Owners, id = NodeId}) -> +- Action = fun(#pubsub_node{type = Type, owners = Owners, idx = Nidx}) -> - IsApprover = lists:member(jlib:short_prepd_bare_jid(From), Owners), -+ Action = fun(#pubsub_node{type = Type, id = NodeId}) -> -+ IsApprover = lists:member(jlib:short_prepd_bare_jid(From), node_owners_call(Type, NodeId)), - {result, Subscriptions} = node_call(Type, get_subscriptions, [NodeId, Subscriber]), ++ Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> ++ IsApprover = lists:member(jlib:short_prepd_bare_jid(From), node_owners_call(Type, Nidx)), + {result, Subscriptions} = node_call(Type, get_subscriptions, [Nidx, Subscriber]), if not IsApprover -> -@@ -1823,7 +1637,7 @@ +@@ -1824,7 +1633,7 @@ end, Reply = #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [#xmlel{ns = ?NS_PUBSUB, name = 'create', attrs = nodeAttr(Node)}]}, @@ -503,7 +504,7 @@ {result, {NodeId, SubsByDepth, {Result, broadcast}}} -> broadcast_created_node(Host, Node, NodeId, Type, NodeOptions, SubsByDepth), case Result of -@@ -1927,7 +1741,7 @@ +@@ -1928,7 +1737,7 @@ %%<li>The node does not exist.</li> %%</ul> subscribe_node(Host, Node, From, JID, Configuration) -> @@ -512,50 +513,50 @@ {result, GoodSubOpts} -> GoodSubOpts; _ -> invalid end, -@@ -1937,7 +1751,7 @@ +@@ -1938,7 +1747,7 @@ _:_ -> {undefined, undefined, undefined} end, -- Action = fun(#pubsub_node{options = Options, owners = Owners, type = Type, id = NodeId}) -> -+ Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> +- Action = fun(#pubsub_node{options = Options, owners = Owners, type = Type, idx = Nidx}) -> ++ Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> Features = features(Type), SubscribeFeature = lists:member("subscribe", Features), OptionsFeature = lists:member("subscription-options", Features), -@@ -1946,6 +1760,7 @@ +@@ -1947,6 +1756,7 @@ AccessModel = get_option(Options, access_model), SendLast = get_option(Options, send_last_published_item), AllowedGroups = get_option(Options, roster_groups_allowed, []), -+ Owners = node_owners_call(Type, NodeId), ++ Owners = node_owners_call(Type, Nidx), {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, Subscriber, Owners, AccessModel, AllowedGroups), if not SubscribeFeature -> -@@ -2290,7 +2105,7 @@ +@@ -2291,7 +2101,7 @@ %% <p>The permission are not checked in this function.</p> %% @todo We probably need to check that the user doing the query has the right %% to read the items. --get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) -> -+get_items(Host, Node, From, SubId, SMaxItems, ItemIDs, RSM) -> +-get_items(Host, Node, From, SubId, SMaxItems, ItemIds) -> ++get_items(Host, Node, From, SubId, SMaxItems, ItemIds, RSM) -> MaxItems = if SMaxItems == "" -> get_max_items_node(Host); -@@ -2304,12 +2119,13 @@ +@@ -2305,12 +2115,13 @@ {error, Error} -> {error, Error}; _ -> -- Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId, owners = Owners}) -> -+ Action = fun(#pubsub_node{options = Options, type = Type, id = NodeId}) -> +- Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx, owners = Owners}) -> ++ Action = fun(#pubsub_node{options = Options, type = Type, idx = Nidx}) -> Features = features(Type), RetreiveFeature = lists:member("retrieve-items", Features), PersistentFeature = lists:member("persistent-items", Features), AccessModel = get_option(Options, access_model), AllowedGroups = get_option(Options, roster_groups_allowed, []), -+ Owners = node_owners_call(Type, NodeId), ++ Owners = node_owners_call(Type, Nidx), {PresenceSubscription, RosterGroup} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups), if not RetreiveFeature -> -@@ -2322,11 +2138,11 @@ +@@ -2323,11 +2134,11 @@ node_call(Type, get_items, - [NodeId, From, + [Nidx, From, AccessModel, PresenceSubscription, RosterGroup, - SubId]) + SubId, RSM]) @@ -564,10 +565,10 @@ case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Items}} -> + {result, {_, Items, RSMOut}} -> - SendItems = case ItemIDs of + SendItems = case ItemIds of [] -> Items; -@@ -2339,7 +2155,7 @@ +@@ -2340,7 +2151,7 @@ %% number of items sent to MaxItems: {result, #xmlel{ns = ?NS_PUBSUB, name = 'pubsub', children = [#xmlel{ns = ?NS_PUBSUB, name = 'items', attrs = nodeAttr(Node), children = @@ -576,7 +577,7 @@ Error -> Error end -@@ -2360,6 +2176,17 @@ +@@ -2363,6 +2174,17 @@ {result, {_, Items}} -> Items; Error -> Error end. @@ -594,7 +595,7 @@ %% @spec (Host, Node, NodeId, Type, LJID, Number) -> any() %% Host = pubsubHost() -@@ -2371,16 +2198,29 @@ +@@ -2374,16 +2196,29 @@ %% @doc <p>Resend the items of a node to the user.</p> %% @todo use cache-last-item feature send_items(Host, Node, NodeId, Type, LJID, last) -> @@ -630,21 +631,21 @@ send_items(Host, Node, NodeId, Type, {LU, LS, LR} = LJID, Number) -> ToSend = case node_action(Host, Type, get_items, [NodeId, LJID]) of {result, []} -> -@@ -2507,7 +2347,8 @@ +@@ -2510,7 +2345,8 @@ error -> {error, 'bad-request'}; _ -> -- Action = fun(#pubsub_node{owners = Owners, type = Type, id = NodeId}=N) -> -+ Action = fun(#pubsub_node{type = Type, id = NodeId}) -> -+ Owners = node_owners_call(Type, NodeId), +- Action = fun(#pubsub_node{owners = Owners, type = Type, idx = Nidx}=N) -> ++ Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> ++ Owners = node_owners_call(Type, Nidx), case lists:member(Owner, Owners) of true -> OwnerJID = exmpp_jid:make(Owner), -@@ -2517,24 +2358,8 @@ +@@ -2520,24 +2356,8 @@ end, lists:foreach( fun({JID, Affiliation}) -> -- {result, _} = node_call(Type, set_affiliation, [NodeId, JID, Affiliation]), +- {result, _} = node_call(Type, set_affiliation, [Nidx, JID, Affiliation]), - case Affiliation of - owner -> - NewOwner = jlib:short_prepd_bare_jid(JID), @@ -663,16 +664,16 @@ - ok - end + % TODO, check if nothing missing here about new owners -+ node_call(Type, set_affiliation, [NodeId, JID, Affiliation]) ++ node_call(Type, set_affiliation, [Nidx, JID, Affiliation]) end, FilteredEntities), {result, []}; _ -> -@@ -2589,11 +2414,11 @@ +@@ -2592,11 +2412,11 @@ end. - read_sub(Subscriber, Node, NodeID, SubID, Lang) -> -- case pubsub_subscription:get_subscription(Subscriber, NodeID, SubID) of -+ case pubsub_subscription_odbc:get_subscription(Subscriber, NodeID, SubID) of + read_sub(Subscriber, Node, NodeId, SubId, Lang) -> +- case pubsub_subscription:get_subscription(Subscriber, NodeId, SubId) of ++ case pubsub_subscription_odbc:get_subscription(Subscriber, NodeId, SubId) of {error, notfound} -> {error, extended_error('not-acceptable', "invalid-subid")}; {result, #pubsub_subscription{options = Options}} -> @@ -680,37 +681,37 @@ + {result, XdataEl} = pubsub_subscription_odbc:get_options_xform(Lang, Options), OptionsEl = #xmlel{ns = ?NS_PUBSUB, name = 'options', attrs = [ ?XMLATTR('jid', exmpp_jid:to_binary(Subscriber)), - ?XMLATTR('subid', SubID) | nodeAttr(Node)], -@@ -2620,7 +2445,7 @@ + ?XMLATTR('subid', SubId) | nodeAttr(Node)], +@@ -2623,7 +2443,7 @@ end. - set_options_helper(Configuration, JID, NodeID, SubID, Type) -> + set_options_helper(Configuration, JID, NodeId, SubId, Type) -> - SubOpts = case pubsub_subscription:parse_options_xform(Configuration) of + SubOpts = case pubsub_subscription_odbc:parse_options_xform(Configuration) of {result, GoodSubOpts} -> GoodSubOpts; _ -> invalid end, -@@ -2650,7 +2475,7 @@ - write_sub(_Subscriber, _NodeID, _SubID, invalid) -> +@@ -2653,7 +2473,7 @@ + write_sub(_Subscriber, _NodeId, _SubId, invalid) -> {error, extended_error('bad-request', "invalid-options")}; - write_sub(Subscriber, NodeID, SubID, Options) -> -- case pubsub_subscription:set_subscription(Subscriber, NodeID, SubID, Options) of -+ case pubsub_subscription_odbc:set_subscription(Subscriber, NodeID, SubID, Options) of + write_sub(Subscriber, NodeId, SubId, Options) -> +- case pubsub_subscription:set_subscription(Subscriber, NodeId, SubId, Options) of ++ case pubsub_subscription_odbc:set_subscription(Subscriber, NodeId, SubId, Options) of {error, notfound} -> {error, extended_error('not-acceptable', "invalid-subid")}; {result, _} -> -@@ -2824,8 +2649,8 @@ +@@ -2827,8 +2647,8 @@ ?XMLATTR('subsription', subscription_to_string(Sub)) | nodeAttr(Node)]}]}]}, ejabberd_router:route(service_jid(Host), JID, Stanza) end, -- Action = fun(#pubsub_node{owners = Owners, type = Type, id = NodeId}) -> +- Action = fun(#pubsub_node{owners = Owners, type = Type, idx = Nidx}) -> - case lists:member(Owner, Owners) of -+ Action = fun(#pubsub_node{type = Type, id = NodeId}) -> -+ case lists:member(Owner, node_owners_call(Type, NodeId)) of ++ Action = fun(#pubsub_node{type = Type, idx = Nidx}) -> ++ case lists:member(Owner, node_owners_call(Type, Nidx)) of true -> Result = lists:foldl(fun({JID, Subscription, SubId}, Acc) -> -@@ -3174,7 +2999,7 @@ +@@ -3177,7 +2997,7 @@ {Depth, [{N, get_node_subs(N)} || N <- Nodes]} end, tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]))} end, @@ -719,19 +720,16 @@ {result, CollSubs} -> CollSubs; _ -> [] end. -@@ -3188,9 +3013,9 @@ +@@ -3190,7 +3010,7 @@ - get_options_for_subs(NodeID, Subs) -> - lists:foldl(fun({JID, subscribed, SubID}, Acc) -> -- case pubsub_subscription:read_subscription(JID, NodeID, SubID) of -+ case pubsub_subscription_odbc:get_subscription(JID, NodeID, SubID) of - {error, notfound} -> [{JID, SubID, []} | Acc]; -- #pubsub_subscription{options = Options} -> [{JID, SubID, Options} | Acc]; -+ {result, #pubsub_subscription{options = Options}} -> [{JID, SubID, Options} | Acc]; + get_options_for_subs(Nidx, Subs) -> + lists:foldl(fun({JID, subscribed, SubId}, Acc) -> +- case pubsub_subscription:read_subscription(JID, Nidx, SubId) of ++ case pubsub_subscription_odbc:read_subscription(JID, Nidx, SubId) of + {error, notfound} -> [{JID, SubId, []} | Acc]; + #pubsub_subscription{options = Options} -> [{JID, SubId, Options} | Acc]; _ -> Acc - end; - (_, Acc) -> -@@ -3412,6 +3237,30 @@ +@@ -3414,6 +3234,30 @@ Result end. @@ -762,7 +760,7 @@ %% @spec (Host, Options) -> MaxItems %% Host = host() %% Options = [Option] -@@ -3815,7 +3664,13 @@ +@@ -3817,7 +3661,13 @@ tree_action(Host, Function, Args) -> ?DEBUG("tree_action ~p ~p ~p",[Host,Function,Args]), Fun = fun() -> tree_call(Host, Function, Args) end, @@ -777,7 +775,7 @@ %% @doc <p>node plugin call.</p> node_call(Type, Function, Args) -> -@@ -3835,13 +3690,13 @@ +@@ -3837,13 +3687,13 @@ node_action(Host, Type, Function, Args) -> ?DEBUG("node_action ~p ~p ~p ~p",[Host,Type,Function,Args]), @@ -793,7 +791,7 @@ case tree_call(Host, get_node, [Host, Node]) of N when is_record(N, pubsub_node) -> case Action(N) of -@@ -3854,13 +3709,20 @@ +@@ -3856,13 +3706,20 @@ end end, Trans). @@ -818,7 +816,7 @@ {result, Result} -> {result, Result}; {error, Error} -> {error, Error}; {atomic, {result, Result}} -> {result, Result}; -@@ -3868,6 +3730,15 @@ +@@ -3870,6 +3727,15 @@ {aborted, Reason} -> ?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]), {error, 'internal-server-error'}; @@ -834,7 +832,7 @@ {'EXIT', Reason} -> ?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]), {error, 'internal-server-error'}; -@@ -3876,6 +3747,16 @@ +@@ -3878,6 +3744,16 @@ {error, 'internal-server-error'} end. diff --git a/src/mod_pubsub/pubsub_subscription.erl b/src/mod_pubsub/pubsub_subscription.erl index 72a721877..be33aa0ea 100644 --- a/src/mod_pubsub/pubsub_subscription.erl +++ b/src/mod_pubsub/pubsub_subscription.erl @@ -24,29 +24,32 @@ -author("bjc@kublai.com"). %% API --export([init/0, +-export([ + init/0, subscribe_node/3, unsubscribe_node/3, get_subscription/3, set_subscription/4, get_options_xform/2, - parse_options_xform/1]). + parse_options_xform/1 + ]). -% Internal function also exported for use in transactional bloc from pubsub plugins --export([add_subscription/3, + % Internal function also exported for use in transactional bloc from pubsub plugins +-export([ + add_subscription/3, delete_subscription/3, read_subscription/3, - write_subscription/4]). + write_subscription/4 + ]). -include("pubsub.hrl"). --include_lib("exmpp/include/exmpp.hrl"). --define(PUBSUB_DELIVER, "pubsub#deliver"). --define(PUBSUB_DIGEST, "pubsub#digest"). +-define(PUBSUB_DELIVER, "pubsub#deliver"). +-define(PUBSUB_DIGEST, "pubsub#digest"). -define(PUBSUB_DIGEST_FREQUENCY, "pubsub#digest_frequency"). --define(PUBSUB_EXPIRE, "pubsub#expire"). +-define(PUBSUB_EXPIRE, "pubsub#expire"). -define(PUBSUB_INCLUDE_BODY, "pubsub#include_body"). --define(PUBSUB_SHOW_VALUES, "pubsub#show-values"). +-define(PUBSUB_SHOW_VALUES, "pubsub#show-values"). -define(PUBSUB_SUBSCRIPTION_TYPE, "pubsub#subscription_type"). -define(PUBSUB_SUBSCRIPTION_DEPTH, "pubsub#subscription_depth"). @@ -55,11 +58,11 @@ -define(DIGEST_LABEL, "Whether an entity wants to receive digests (aggregations) of notifications or all notifications individually"). -define(DIGEST_FREQUENCY_LABEL, - "The minimum number of milliseconds between sending any two notification digests"). + "The minimum number of milliseconds between sending any two notification digests"). -define(EXPIRE_LABEL, "The DateTime at which a leased subscription will end or has ended"). -define(INCLUDE_BODY_LABEL, - "Whether an entity wants to receive an XMPP message body in addition to the payload format"). + "Whether an entity wants to receive an XMPP message body in addition to the payload format"). -define(SHOW_VALUES_LABEL, "The presence states for which an entity wants to receive notifications"). -define(SUBSCRIPTION_TYPE_LABEL, @@ -86,113 +89,194 @@ %%==================================================================== %% API %%==================================================================== +-spec(init/0 :: () -> 'ok'). + init() -> ok = create_table(). -subscribe_node(JID, NodeID, Options) -> - try mnesia:sync_dirty(fun add_subscription/3, - [JID, NodeID, Options]) of +-spec(subscribe_node/3 :: + ( + Entity :: jidEntity() | fullUsr(), + NodeIdx :: nodeIdx(), + Options :: [nodeOption()]) + -> {'result', SubId::subId()} | {'error', _} + ). + +subscribe_node(#jid{node = U, domain = S, resource = R}, NodeIdx, Options) -> + subscribe_node({U,S,R}, NodeIdx, Options); +subscribe_node(Entity, NodeIdx, Options) -> + try mnesia:sync_dirty(fun add_subscription/3, [Entity, NodeIdx, Options]) of {error, Error} -> {error, Error}; - Result -> {result, Result} + Result -> {result, Result} catch - Error -> Error + Error -> Error end. -unsubscribe_node(JID, NodeID, SubID) -> - try mnesia:sync_dirty(fun delete_subscription/3, - [JID, NodeID, SubID]) of + +-spec(unsubscribe_node/3 :: + ( + JID :: jidEntity(), + NodeIdx :: nodeIdx(), + SubId :: subId()) + -> {'result','ok'} | {'error', _} + ). + +unsubscribe_node(#jid{node = U, domain = S, resource = R} = _JID, NodeIdx, SubId) -> + try mnesia:sync_dirty(fun delete_subscription/3, [{U,S,R}, NodeIdx, SubId]) of {error, Error} -> {error, Error}; - Result -> {result, Result} + Result -> {result, Result} catch Error -> Error end. -get_subscription(JID, NodeID, SubID) -> - try mnesia:sync_dirty(fun read_subscription/3, - [JID, NodeID, SubID]) of + +-spec(get_subscription/3 :: + ( + JID :: jidEntity(), + NodeIdx :: nodeIdx(), + SubId :: subId()) + -> {'result', pubsubSubscription()} | {'error', _} + ). + +get_subscription(#jid{node = U, domain = S, resource = R} = _JID, NodeIdx, SubId) -> + try mnesia:sync_dirty(fun read_subscription/3, [{U,S,R}, NodeIdx, SubId]) of {error, Error} -> {error, Error}; - Result -> {result, Result} + Subscription -> {result, Subscription} catch Error -> Error end. -set_subscription(JID, NodeID, SubID, Options) -> - try mnesia:sync_dirty(fun write_subscription/4, - [JID, NodeID, SubID, Options]) of + +-spec(set_subscription/4 :: + ( + JID :: jidEntity(), + NodeIdx :: nodeIdx(), + SubId :: subId(), + Options :: [nodeOption()]) + -> {'result', 'ok'} | {'error', _} + ). + +set_subscription(#jid{node = U, domain = S, resource = R} = _JID, NodeIdx, SubId, Options) -> + try mnesia:sync_dirty(fun write_subscription/4, [{U,S,R}, NodeIdx, SubId, Options]) of {error, Error} -> {error, Error}; - Result -> {result, Result} + Result -> {result, Result} catch Error -> Error end. + +%% TODO : check input type data get_options_xform(Lang, Options) -> Keys = [deliver, digest, digest_frequency, expire, include_body, show_values, subscription_type, subscription_depth], XFields = [get_option_xfield(Lang, Key, Options) || Key <- Keys], - {result, #xmlel{ns = ?NS_DATA_FORMS, name = 'x', attrs = [?XMLATTR('type', <<"form">>)], children = - [#xmlel{ns = ?NS_DATA_FORMS, - name = 'field', - attrs = [?XMLATTR('var', <<"FORM_TYPE">>), ?XMLATTR('type', <<"hidden">>)], - children = [#xmlel{ns = ?NS_DATA_FORMS, - name = 'value', - children = [?XMLCDATA(?NS_PUBSUB_SUBSCRIBE_OPTIONS_s)]}]}] ++ XFields}}. + {result, #xmlel{ns = ?NS_DATA_FORMS, name = 'x', attrs = [?XMLATTR('type', <<"form">>)], children = + [#xmlel{ns = ?NS_DATA_FORMS, + name = 'field', + attrs = [?XMLATTR('var', <<"FORM_TYPE">>), ?XMLATTR('type', <<"hidden">>)], + children = [#xmlel{ns = ?NS_DATA_FORMS, + name = 'value', + children = [?XMLCDATA(?NS_PUBSUB_SUBSCRIBE_OPTIONS_s)]}]}] ++ XFields}}. +%% TODO : check input type data parse_options_xform(XFields) -> case XFields of - [] -> {result, []}; - _ -> case exmpp_xml:remove_cdata_from_list(XFields) of - [] -> {result, []}; - [#xmlel{name = 'x'} = XEl] -> - case jlib:parse_xdata_submit(XEl) of - XData when is_list(XData) -> - case set_xoption(XData, []) of - Opts when is_list(Opts) -> {result, Opts}; - Other -> Other - end; - Other -> - Other - end; - Other -> - Other - end + [] -> {result, []}; + _ -> case exmpp_xml:remove_cdata_from_list(XFields) of + [] -> {result, []}; + [#xmlel{name = 'x'} = XEl] -> + case jlib:parse_xdata_submit(XEl) of + XData when is_list(XData) -> + case set_xoption(XData, []) of + Opts when is_list(Opts) -> {result, Opts}; + Other -> Other + end; + Other -> + Other + end; + Other -> + Other + end end. %%==================================================================== %% Internal functions %%==================================================================== +-spec(create_table/0 :: () -> 'ok'). + create_table() -> case mnesia:create_table(pubsub_subscription, [{disc_copies, [node()]}, {attributes, record_info(fields, pubsub_subscription)}, - {type, set}]) of - {atomic, ok} -> ok; + {type, set}]) + of + {atomic, ok} -> ok; {aborted, {already_exists, _}} -> ok; - Other -> Other + Other -> Other + end. + +-spec(add_subscription/3 :: + ( + Entity :: fullUsr(), + NodeIdx :: nodeIdx(), + Options :: [nodeOption()]) + -> SubId::subId() + ). + +add_subscription(_Entity, _NodeIdx, Options) -> + SubId = make_subid(), + mnesia:write(#pubsub_subscription{subid = SubId, options = Options}), + SubId. + + +-spec(delete_subscription/3 :: + ( + Entity :: fullUsr(), + NodeIdx :: nodeIdx(), + SubId :: subId()) + -> 'ok' + ). + +delete_subscription(_Entity, _NodeIdx, SubId) -> + mnesia:delete({pubsub_subscription, SubId}). + + +-spec(read_subscription/3 :: + ( + Entity :: fullUsr(), + NodeIdx :: nodeIdx(), + SubId :: subId()) + -> pubsubSubscription() | {'error', 'notfound'} + ). + +read_subscription(_Entity, _NodeIdx, SubId) -> + case mnesia:read({pubsub_subscription, SubId}) of + [Subscription] -> Subscription; + _ -> {'error', 'notfound'} end. -add_subscription(_JID, _NodeID, Options) -> - SubID = make_subid(), - mnesia:write(#pubsub_subscription{subid = SubID, options = Options}), - SubID. -delete_subscription(_JID, _NodeID, SubID) -> - mnesia:delete({pubsub_subscription, SubID}). +-spec(write_subscription/4 :: + ( + Entity :: fullUsr(), + NodeIdx :: nodeIdx(), + SubId :: subId(), + Options :: [nodeOption()]) + -> 'ok' | {'error', 'notfound'} + ). -read_subscription(_JID, _NodeID, SubID) -> - case mnesia:read({pubsub_subscription, SubID}) of - [Sub] -> Sub; - _ -> {error, notfound} +write_subscription(Entity, NodeIdx, SubId, Options) -> + case read_subscription(Entity, NodeIdx, SubId) of + {error, 'notfound'} -> {error, 'notfound'}; + Subscription -> mnesia:write(Subscription#pubsub_subscription{options = Options}) end. -write_subscription(JID, NodeID, SubID, Options) -> - case read_subscription(JID, NodeID, SubID) of - {error, notfound} -> {error, notfound}; - Sub -> mnesia:write(Sub#pubsub_subscription{options = Options}) - end. + +-spec(make_subid/0 :: () -> SubId::subId()). make_subid() -> {T1, T2, T3} = now(), - lists:flatten(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])). + list_to_binary(lists:flatten(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3]))). %% %% Subscription XForm processing. @@ -200,6 +284,7 @@ make_subid() -> %% Return processed options, with types converted and so forth, using %% Opts as defaults. +%% TODO : check input type data set_xoption([], Opts) -> Opts; set_xoption([{Var, Value} | T], Opts) -> @@ -212,33 +297,36 @@ set_xoption([{Var, Value} | T], Opts) -> end, set_xoption(T, NewOpts). + %% Return the options list's key for an XForm var. -var_xfield(?PUBSUB_DELIVER) -> deliver; -var_xfield(?PUBSUB_DIGEST) -> digest; -var_xfield(?PUBSUB_DIGEST_FREQUENCY) -> digest_frequency; -var_xfield(?PUBSUB_EXPIRE) -> expire; -var_xfield(?PUBSUB_INCLUDE_BODY) -> include_body; -var_xfield(?PUBSUB_SHOW_VALUES) -> show_values; -var_xfield(?PUBSUB_SUBSCRIPTION_TYPE) -> subscription_type; -var_xfield(?PUBSUB_SUBSCRIPTION_DEPTH) -> subscription_depth; -var_xfield(_) -> {error, badarg}. +var_xfield(?PUBSUB_DELIVER) -> 'deliver'; +var_xfield(?PUBSUB_DIGEST) -> 'digest'; +var_xfield(?PUBSUB_DIGEST_FREQUENCY) -> 'digest_frequency'; +var_xfield(?PUBSUB_EXPIRE) -> 'expire'; +var_xfield(?PUBSUB_INCLUDE_BODY) -> 'include_body'; +var_xfield(?PUBSUB_SHOW_VALUES) -> 'show_values'; +var_xfield(?PUBSUB_SUBSCRIPTION_TYPE) -> 'subscription_type'; +var_xfield(?PUBSUB_SUBSCRIPTION_DEPTH) -> 'subscription_depth'; +var_xfield(_) -> {error, 'badarg'}. + %% Convert Values for option list's Key. -val_xfield(deliver, [Val]) -> xopt_to_bool(Val); -val_xfield(digest, [Val]) -> xopt_to_bool(Val); -val_xfield(digest_frequency, [Val]) -> list_to_integer(Val); -val_xfield(expire, [Val]) -> jlib:datetime_string_to_timestamp(Val); -val_xfield(include_body, [Val]) -> xopt_to_bool(Val); -val_xfield(show_values, Vals) -> Vals; -val_xfield(subscription_type, ["items"]) -> items; -val_xfield(subscription_type, ["nodes"]) -> nodes; -val_xfield(subscription_depth, ["all"]) -> all; -val_xfield(subscription_depth, [Depth]) -> +val_xfield('deliver', [Val]) -> xopt_to_bool(Val); +val_xfield('digest', [Val]) -> xopt_to_bool(Val); +val_xfield('digest_frequency', [Val]) -> list_to_integer(Val); +val_xfield('expire', [Val]) -> jlib:datetime_string_to_timestamp(Val); +val_xfield('include_body', [Val]) -> xopt_to_bool(Val); +val_xfield('show_values', Vals) -> Vals; +val_xfield('subscription_type', ["items"]) -> items; +val_xfield('subscription_type', ["nodes"]) -> nodes; +val_xfield('subscription_depth', ["all"]) -> all; +val_xfield('subscription_depth', [Depth]) -> case catch list_to_integer(Depth) of - N when is_integer(N) -> N; - _ -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'not-acceptable')} + Integer when is_integer(Integer) -> Integer; + _ -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'not-acceptable')} end. + %% Convert XForm booleans to Erlang booleans. xopt_to_bool("0") -> false; xopt_to_bool("1") -> true; @@ -248,6 +336,7 @@ xopt_to_bool(_) -> {error, exmpp_stanza:error(?NS_JABBER_CLIENT, 'not-acce %% Return a field for an XForm for Key, with data filled in, if %% applicable, from Options. +%% TODO : check input type data get_option_xfield(Lang, Key, Options) -> Var = xfield_var(Key), Label = xfield_label(Key), @@ -263,73 +352,76 @@ get_option_xfield(Lang, Key, Options) -> attrs = [?XMLATTR('var', Var), ?XMLATTR('type', Type), ?XMLATTR('label', translate:translate(Lang, Label))], children = OptEls ++ Vals}. +%% TODO : check input type data type_and_options({Type, Options}, Lang) -> {Type, [tr_xfield_options(O, Lang) || O <- Options]}; type_and_options(Type, _Lang) -> {Type, []}. +%% TODO : check input type data tr_xfield_options({Value, Label}, Lang) -> #xmlel{ns = ?NS_DATA_FORMS, - name = 'option', - attrs = [?XMLATTR('label', translate:translate(Lang, Label))], - children = [#xmlel{ns = ?NS_DATA_FORMS, - name = 'value', - children = [?XMLCDATA(Value)]}]}. + name = 'option', + attrs = [?XMLATTR('label', translate:translate(Lang, Label))], + children = [#xmlel{ns = ?NS_DATA_FORMS, + name = 'value', + children = [?XMLCDATA(Value)]}]}. +%% TODO : check input type data tr_xfield_values(Value) -> #xmlel{ns = ?NS_DATA_FORMS, name ='value', children = [?XMLCDATA(Value)]}. %% Return the XForm variable name for a subscription option key. -xfield_var(deliver) -> ?PUBSUB_DELIVER; -xfield_var(digest) -> ?PUBSUB_DIGEST; -xfield_var(digest_frequency) -> ?PUBSUB_DIGEST_FREQUENCY; -xfield_var(expire) -> ?PUBSUB_EXPIRE; -xfield_var(include_body) -> ?PUBSUB_INCLUDE_BODY; -xfield_var(show_values) -> ?PUBSUB_SHOW_VALUES; -xfield_var(subscription_type) -> ?PUBSUB_SUBSCRIPTION_TYPE; -xfield_var(subscription_depth) -> ?PUBSUB_SUBSCRIPTION_DEPTH. +xfield_var('deliver') -> ?PUBSUB_DELIVER; +xfield_var('digest') -> ?PUBSUB_DIGEST; +xfield_var('digest_frequency') -> ?PUBSUB_DIGEST_FREQUENCY; +xfield_var('expire') -> ?PUBSUB_EXPIRE; +xfield_var('include_body') -> ?PUBSUB_INCLUDE_BODY; +xfield_var('show_values') -> ?PUBSUB_SHOW_VALUES; +xfield_var('subscription_type') -> ?PUBSUB_SUBSCRIPTION_TYPE; +xfield_var('subscription_depth') -> ?PUBSUB_SUBSCRIPTION_DEPTH. %% Return the XForm variable type for a subscription option key. -xfield_type(deliver) -> "boolean"; -xfield_type(digest) -> "boolean"; -xfield_type(digest_frequency) -> "text-single"; -xfield_type(expire) -> "text-single"; -xfield_type(include_body) -> "boolean"; -xfield_type(show_values) -> +xfield_type('deliver') -> "boolean"; +xfield_type('digest') -> "boolean"; +xfield_type('digest_frequency') -> "text-single"; +xfield_type('expire') -> "text-single"; +xfield_type('include_body') -> "boolean"; +xfield_type('show_values') -> {"list-multi", [{"away", ?SHOW_VALUE_AWAY_LABEL}, {"chat", ?SHOW_VALUE_CHAT_LABEL}, {"dnd", ?SHOW_VALUE_DND_LABEL}, {"online", ?SHOW_VALUE_ONLINE_LABEL}, {"xa", ?SHOW_VALUE_XA_LABEL}]}; -xfield_type(subscription_type) -> +xfield_type(subscription_type) -> {"list-single", [{"items", ?SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL}, {"nodes", ?SUBSCRIPTION_TYPE_VALUE_NODES_LABEL}]}; xfield_type(subscription_depth) -> - {"list-single", [{"1", ?SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL}, + {"list-single", [{"1", ?SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL}, {"all", ?SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL}]}. %% Return the XForm variable label for a subscription option key. -xfield_label(deliver) -> ?DELIVER_LABEL; -xfield_label(digest) -> ?DIGEST_LABEL; -xfield_label(digest_frequency) -> ?DIGEST_FREQUENCY_LABEL; -xfield_label(expire) -> ?EXPIRE_LABEL; -xfield_label(include_body) -> ?INCLUDE_BODY_LABEL; -xfield_label(show_values) -> ?SHOW_VALUES_LABEL; -xfield_label(subscription_type) -> ?SUBSCRIPTION_TYPE_LABEL; -xfield_label(subscription_depth) -> ?SUBSCRIPTION_DEPTH_LABEL. +xfield_label('deliver') -> ?DELIVER_LABEL; +xfield_label('digest') -> ?DIGEST_LABEL; +xfield_label('digest_frequency') -> ?DIGEST_FREQUENCY_LABEL; +xfield_label('expire') -> ?EXPIRE_LABEL; +xfield_label('include_body') -> ?INCLUDE_BODY_LABEL; +xfield_label('show_values') -> ?SHOW_VALUES_LABEL; +xfield_label('subscription_type') -> ?SUBSCRIPTION_TYPE_LABEL; +xfield_label('subscription_depth') -> ?SUBSCRIPTION_DEPTH_LABEL. %% Return the XForm value for a subscription option key. -xfield_val(deliver, Val) -> [bool_to_xopt(Val)]; -xfield_val(digest, Val) -> [bool_to_xopt(Val)]; -xfield_val(digest_frequency, Val) -> [integer_to_list(Val)]; -xfield_val(expire, Val) -> [jlib:now_to_utc_string(Val)]; -xfield_val(include_body, Val) -> [bool_to_xopt(Val)]; -xfield_val(show_values, Val) -> Val; -xfield_val(subscription_type, items) -> ["items"]; -xfield_val(subscription_type, nodes) -> ["nodes"]; -xfield_val(subscription_depth, all) -> ["all"]; -xfield_val(subscription_depth, N) -> [integer_to_list(N)]. +xfield_val('deliver', Val) -> [bool_to_xopt(Val)]; +xfield_val('digest', Val) -> [bool_to_xopt(Val)]; +xfield_val('digest_frequency', Val) -> [integer_to_list(Val)]; +xfield_val('expire', Val) -> [jlib:now_to_utc_string(Val)]; +xfield_val('include_body', Val) -> [bool_to_xopt(Val)]; +xfield_val('show_values', Val) -> Val; +xfield_val('subscription_type', 'items') -> ["items"]; +xfield_val('subscription_type', 'nodes') -> ["nodes"]; +xfield_val('subscription_depth', 'all') -> ["all"]; +xfield_val('subscription_depth', Depth) -> [integer_to_list(Depth)]. %% Convert erlang booleans to XForms. -bool_to_xopt(false) -> "false"; -bool_to_xopt(true) -> "true". +bool_to_xopt('false') -> "false"; +bool_to_xopt('true') -> "true". diff --git a/src/mod_pubsub/pubsub_subscription_odbc.erl b/src/mod_pubsub/pubsub_subscription_odbc.erl index f5591e032..b03b10cd2 100644 --- a/src/mod_pubsub/pubsub_subscription_odbc.erl +++ b/src/mod_pubsub/pubsub_subscription_odbc.erl @@ -37,7 +37,6 @@ -include_lib("stdlib/include/qlc.hrl"). -include("pubsub.hrl"). --include_lib("exmpp/include/exmpp.hrl"). -define(PUBSUB_DELIVER, "pubsub#deliver"). -define(PUBSUB_DIGEST, "pubsub#digest"). @@ -89,33 +88,33 @@ init() -> ok = create_table(). -subscribe_node(_JID, _NodeID, Options) -> - SubID = make_subid(), - ?DB_MOD:add_subscription(#pubsub_subscription{subid = SubID, options = Options}), - {result, SubID}. +subscribe_node(_JID, _Nidx, Options) -> + SubId = make_subid(), + ?DB_MOD:add_subscription(#pubsub_subscription{subid = SubId, options = Options}), + {result, SubId}. -unsubscribe_node(_JID, _NodeID, SubID) -> - case ?DB_MOD:read_subscription(SubID) of +unsubscribe_node(_JID, _Nidx, SubId) -> + case ?DB_MOD:read_subscription(SubId) of {ok, Sub} -> - ?DB_MOD:delete_subscription(SubID), + ?DB_MOD:delete_subscription(SubId), {result, Sub}; notfound -> {error, notfound} end. -get_subscription(_JID, _NodeID, SubID) -> - case ?DB_MOD:read_subscription(SubID) of +get_subscription(_JID, _Nidx, SubId) -> + case ?DB_MOD:read_subscription(SubId) of {ok, Sub} -> {result, Sub}; notfound -> {error, notfound} end. -set_subscription(_JID, _NodeID, SubID, Options) -> - case ?DB_MOD:read_subscription(SubID) of +set_subscription(_JID, _Nidx, SubId, Options) -> + case ?DB_MOD:read_subscription(SubId) of {ok, _} -> - ?DB_MOD:update_subscription(#pubsub_subscription{subid = SubID, options = Options}), + ?DB_MOD:update_subscription(#pubsub_subscription{subid = SubId, options = Options}), {result, ok}; notfound -> - ?DB_MOD:add_subscription(#pubsub_subscription{subid = SubID, options = Options}), + ?DB_MOD:add_subscription(#pubsub_subscription{subid = SubId, options = Options}), {result, ok} end. diff --git a/src/mod_roster.erl b/src/mod_roster.erl index a0037151c..1a7756113 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -1183,15 +1183,15 @@ get_jid_info(_, User, Server, JID) LServer = exmpp_stringprep:nameprep(Server), try F = fun() -> - LJID = jlib:short_prepd_jid(JID), - case catch gen_storage:read(LServer, {rosteritem, {LUser, LServer, LJID}}) of + LJID = jlib:short_prepd_jid(JID), + LRJID = jlib:short_prepd_bare_jid(JID), + case catch gen_storage:read(LServer, {rosteritem, {LUser, LServer, LRJID}}) of [#rosteritem{subscription = Subscription}] -> Groups = [Group || #rostergroup{grp = Group} <- - gen_storage:read(LServer, {rostergroup, {LUser, LServer, LJID}})], + gen_storage:read(LServer, {rostergroup, {LUser, LServer, LRJID}})], {Subscription, Groups}; _ -> - LRJID = jlib:short_prepd_bare_jid(JID), if LRJID == LJID -> {none, []}; @@ -1202,7 +1202,7 @@ get_jid_info(_, User, Server, JID) [#rosteritem{subscription = Subscription}] -> Groups = [Group || #rostergroup{grp = Group} <- - gen_storage:read(LServer, {rostergroup, {LUser, LServer, LJID}})], + gen_storage:read(LServer, {rostergroup, {LUser, LServer, LRJID}})], {Subscription, Groups}; _ -> {none, []} @@ -1518,7 +1518,7 @@ user_roster_item_parse_query(User, Server, Items, Query) -> ns = ?NS_ROSTER, name = 'query', children = [Item]}, - process_iq( + process_iq_set( UJID, UJID, #iq{type = set, ns = ?NS_JABBER_CLIENT, payload = Request}), throw(submitted); diff --git a/src/mod_sic.erl b/src/mod_sic.erl index 3a3f14b02..c9756df73 100644 --- a/src/mod_sic.erl +++ b/src/mod_sic.erl @@ -62,8 +62,8 @@ process_local_iq(_From, _To, #iq{type = 'set'} = IQ) -> process_sm_iq( - #jid{prep_node = Node, prep_domain = Domain} = From, - #jid{prep_node = Node, prep_domain = Domain} = _To, + #jid{node = Node, domain = Domain} = From, + #jid{node = Node, domain = Domain} = _To, #iq{type = 'get'} = IQ) -> get_ip(From, IQ); diff --git a/src/mod_time.erl b/src/mod_time.erl index b7482bcda..4f2eb1ac3 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -59,7 +59,13 @@ process_local_iq(_From, _To, #iq{type = get} = IQ_Rec) -> {UTC, UTC_diff} = jlib:timestamp_to_iso(Now_universal, utc), Seconds_diff = calendar:datetime_to_gregorian_seconds(Now_local) - calendar:datetime_to_gregorian_seconds(Now_universal), - {Hd, Md, _} = calendar:seconds_to_time(Seconds_diff), + {Hd, Md, _} = case Seconds_diff >= 0 of + true -> + calendar:seconds_to_time(Seconds_diff); + false -> + {Hd0, Md0, Sd0} = calendar:seconds_to_time(-Seconds_diff), + {-Hd0, Md0, Sd0} + end, {_, TZO_diff} = jlib:timestamp_to_iso({{0, 0, 0}, {0, 0, 0}}, {Hd, Md}), Result = #xmlel{ns = ?NS_TIME, name = 'time', children = [ #xmlel{ns = ?NS_TIME, name = 'tzo', children = [ diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index e090ab112..79fe4d29a 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -218,8 +218,8 @@ process_local_iq(_From, _To, #iq{type = set} = IQ_Rec) -> process_sm_iq(_From, To, #iq{type = get} = IQ_Rec) -> - LUser = exmpp_jid:prep_node_as_list(To), - LServer = exmpp_jid:prep_domain_as_list(To), + LUser = exmpp_jid:prep_node(To), + LServer = exmpp_jid:prep_domain(To), case get_vcard(LUser, LServer) of {vcard, VCard} -> exmpp_iq:result(IQ_Rec, VCard); @@ -229,15 +229,16 @@ process_sm_iq(_From, To, #iq{type = get} = IQ_Rec) -> process_sm_iq(From, _To, #iq{type = set, payload = Request} = IQ_Rec) -> User = exmpp_jid:node_as_list(From), LServer = exmpp_jid:prep_domain_as_list(From), + LServerB = exmpp_jid:prep_domain(From), case ?IS_MY_HOST(LServer) of true -> - set_vcard(User, LServer, Request), + set_vcard(User, LServer, LServerB, Request), exmpp_iq:result(IQ_Rec); false -> exmpp_iq:error(IQ_Rec, 'not-allowed') end. -%% @spec (User::string(), Host::string()) -> {vcard, xmlel()} | novcard +%% @spec (User::binary(), Host::binary()) -> {vcard, xmlel()} | novcard get_vcard(User, Host) -> US = {User, Host}, case gen_storage:dirty_read(Host, {vcard, US}) of @@ -253,7 +254,7 @@ get_vcard(User, Host) -> end. -set_vcard(User, LServer, VCARD) -> +set_vcard(User, LServer, LServerB, VCARD) -> FN = exmpp_xml:get_path(VCARD, [{element, 'FN'}, cdata_as_list]), Family = exmpp_xml:get_path(VCARD, @@ -301,14 +302,14 @@ set_vcard(User, LServer, VCARD) -> US = {LUser, LServer}, - VcardToStore = case gen_storage:table_info(LServer, vcard, backend) of + VcardToStore = case gen_storage:table_info(LServerB, vcard, backend) of mnesia -> VCARD; odbc -> lists:flatten(exmpp_xml:document_to_list(VCARD)) end, F = fun() -> - gen_storage:write(LServer, #vcard{user_host = US, vcard = VcardToStore}), - gen_storage:write(LServer, + gen_storage:write(LServerB, #vcard{user_host = US, vcard = VcardToStore}), + gen_storage:write(LServerB, #vcard_search{user_host=US, username = User, lusername = LUser, fn = FN, lfn = LFN, @@ -324,8 +325,8 @@ set_vcard(User, LServer, VCARD) -> orgunit = OrgUnit, lorgunit = LOrgUnit }) end, - gen_storage:transaction(LServer, vcard, F), LServerB = list_to_binary(LServer), + gen_storage:transaction(LServerB, vcard, F), ejabberd_hooks:run(vcard_set, LServerB, [list_to_binary(LUser), LServerB, VCARD]) catch _ -> @@ -402,9 +403,8 @@ do_route(ServerHost, From, To, Packet) -> Result = #xmlel{ ns = ?NS_SEARCH, name = 'query', - children = [ - #xmlel{ - ns = ?NS_DATA_FORMS, + children = + [#xmlel{ns = ?NS_DATA_FORMS, name = 'x', attrs = [?XMLATTR('type', <<"result">>)], @@ -729,10 +729,10 @@ remove_user(User, Server) when is_binary(User), is_binary(Server) -> LServer = binary_to_list(exmpp_stringprep:nameprep(Server)), US = {LUser, LServer}, F = fun() -> - gen_storage:delete(LServer, {vcard, US}), - gen_storage:delete(LServer, {vcard_search, US}) + gen_storage:delete(Server, {vcard, US}), + gen_storage:delete(Server, {vcard_search, US}) end, - gen_storage:transaction(LServer, vcard, F). + gen_storage:transaction(Server, vcard, F). %%% @@ -892,6 +892,7 @@ get_user_photo(User, Host) -> user_queue_parse_query(US, Query) -> {User, Server} = US, + ?INFO_MSG("Query vcard: ~p", [Query]), %+++ case lists:keysearch("removevcard", 1, Query) of {value, _} -> case remove_user(list_to_binary(User), list_to_binary(Server)) of diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 3487ad1fc..7368194a3 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -172,7 +172,7 @@ start_link(Host, Opts) -> init([Host, Opts]) -> HostB = list_to_binary(Host), State = parse_options(Host, Opts), - IQDisc = gen_mod:get_opt(iqdisc, Opts, parallel), + IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), gen_iq_handler:add_iq_handler(ejabberd_local, HostB, ?NS_VCARD, ?MODULE, process_local_iq, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, HostB, ?NS_VCARD, @@ -439,9 +439,8 @@ route(State, From, To, Packet) -> Result = #xmlel{ ns = ?NS_SEARCH, name = 'query', - children = [ - #xmlel{ - ns = ?NS_DATA_FORMS, + children = + [#xmlel{ns = ?NS_DATA_FORMS, name = 'x', attrs = [?XMLATTR('type', <<"result">>)], diff --git a/src/mod_vcard_odbc.erl b/src/mod_vcard_odbc.erl index bb0ad5ca8..7682646dd 100644 --- a/src/mod_vcard_odbc.erl +++ b/src/mod_vcard_odbc.erl @@ -464,12 +464,6 @@ record_to_item(LServer, {Username, FN, Family, Given, Middle, search(LServer, Data) -> MatchSpec = make_matchspec(LServer, Data), - AllowReturnAll = gen_mod:get_module_opt(LServer, ?MODULE, - allow_return_all, false), - if - (MatchSpec == "") and (not AllowReturnAll) -> - []; - true -> Limit = case gen_mod:get_module_opt(LServer, ?MODULE, matches, ?JUD_MATCHES) of infinity -> @@ -491,7 +485,6 @@ search(LServer, Data) -> Error -> ?ERROR_MSG("~p", [Error]), [] - end end. @@ -500,12 +493,7 @@ make_matchspec(LServer, Data) -> filter_fields(Data, ["host = '", Host, "'"], LServer). filter_fields([], Match, _LServer) -> - case Match of - "" -> - ""; - _ -> - [" where ", Match] - end; + [" where ", Match]; filter_fields([{SVar, [Val]} | Ds], Match, LServer) when is_list(Val) and (Val /= "") -> LVal = exmpp_stringprep:to_lower(Val), @@ -539,12 +527,7 @@ make_val(Match, Field, Val) -> SVal = ejabberd_odbc:escape(Val), [Field, " = '", SVal, "'"] end, - case Match of - "" -> - Condition; - _ -> - [Match, " and ", Condition] - end. + [Match, " and ", Condition]. diff --git a/src/web/ejabberd_http_bind.erl b/src/web/ejabberd_http_bind.erl index a9bdbdd39..52e38d76d 100644 --- a/src/web/ejabberd_http_bind.erl +++ b/src/web/ejabberd_http_bind.erl @@ -59,7 +59,7 @@ rid = none, key, socket, - output = "", + output = [], input = queue:new(), waiting_input = false, shaper_state, @@ -1157,7 +1157,7 @@ send_outpacket(#http_bind{pid = FsmRef}, OutPacket) -> case SEls of [{xmlstreamelement, #xmlel{name = 'features', - declared_ns = [{undefined, 'stream'}], + declared_ns = [{undefined, "stream"}], attrs = StreamAttribs, children = StreamEls}} | % {xmlelement, diff --git a/src/web/ejabberd_http_poll.erl b/src/web/ejabberd_http_poll.erl index f18774b2e..1033cbc3b 100644 --- a/src/web/ejabberd_http_poll.erl +++ b/src/web/ejabberd_http_poll.erl @@ -73,9 +73,7 @@ -define(CT, {"Content-Type", "text/xml; charset=utf-8"}). -define(BAD_REQUEST, [?CT, {"Set-Cookie", "ID=-3:0; expires=-1"}]). --define(PARSER_OPTIONS, [ - {names_as_atom, true} -]). +-define(PARSER_OPTIONS, [{names_as_atom, true}]). %%%---------------------------------------------------------------------- %%% API diff --git a/src/web/ejabberd_web_admin.erl b/src/web/ejabberd_web_admin.erl index 60c19e58d..cfbdbe746 100644 --- a/src/web/ejabberd_web_admin.erl +++ b/src/web/ejabberd_web_admin.erl @@ -1001,8 +1001,8 @@ process_admin(Host, {value, {_, String}} -> case parse_access_rule(String) of {ok, Rs} -> - ejabberd_config:add_global_option( - {access, Name, Host}, Rs), + ejabberd_config:add_global_option + ({access, Name, Host}, Rs), ok; _ -> error @@ -1732,10 +1732,17 @@ user_info(User, Server, Query, Lang) -> FIP = case ejabberd_sm:get_user_info( UserB, ServerB, R) of offline -> + NodePidS = "", ""; Info when is_list(Info) -> Node = proplists:get_value(node, Info), + NodeS = atom_to_list(Node), Conn = proplists:get_value(conn, Info), + Priority = proplists:get_value(priority, Info), + Creation = proplists:get_value(creation, Info), + Pid = proplists:get_value(pid, Info), + PidS = pid_to_list(Pid), + NodePidS = NodeS ++ "/pid/" ++ PidS, {IP, Port} = proplists:get_value(ip, Info), ConnS = case Conn of c2s -> "plain"; @@ -1746,14 +1753,16 @@ user_info(User, Server, Query, Lang) -> http_poll -> "http-poll" end, " (" ++ + " #" ++ integer_to_list(Priority) ++ " " ++ ConnS ++ "://" ++ inet_parse:ntoa(IP) ++ ":" ++ - integer_to_list(Port) - ++ "#" ++ atom_to_list(Node) - ++ ")" + integer_to_list(Port) ++ + "#" ++ NodeS ++ + " " ++ Creation ++ + ") " end, - ?LI([?C(binary_to_list(R) ++ FIP)]) + ?LI([?C(binary_to_list(R) ++ FIP), ?AC("/admin/node/" ++ NodePidS ++ "/", "View Process")]) end, lists:sort(Resources)))] end, Password = ejabberd_auth:get_password_s(User, Server), @@ -2149,6 +2158,7 @@ get_node(global, Node, [], Query, Lang) -> [?XE('ul', [?LI([?ACT(Base ++ "db/", "Database")]), ?LI([?ACT(Base ++ "backup/", "Backup")]), + ?LI([?ACT(Base ++ "pid/", "Erlang Processes")]), ?LI([?ACT(Base ++ "ports/", "Listened Ports")]), ?LI([?ACT(Base ++ "stats/", "Statistics")]), ?LI([?ACT(Base ++ "update/", "Update")]) @@ -2326,6 +2336,71 @@ get_node(global, Node, ["backup"], Query, Lang) -> ]) ])])]; +get_node(global, Node, ["pid"], _Query, Lang) -> + NodeS = atom_to_list(Node), + Processes = rpc:call(Node, erlang, processes, []), + ProcessesNumber = length(Processes), + ProcessesList = lists:map( + fun(P) -> + PS = pid_to_list(P), + NodePidS = NodeS ++ "/pid/" ++ PS, + ?AC("/admin/node/" ++ NodePidS ++ "/", PS) + end, + Processes), + [?XC('h1', io_lib:format(?T("Erlang Processes at node ~p"), [Node])), + ?XAE('table', [], + [?XE('tbody', + [?XE('tr', [?XCT('td', "Number of processes:"), + ?XAC('td', [?XMLATTR('class', <<"alignright">>)], + pretty_string_int(ProcessesNumber))]) + ]) + ]), + ?XAE('p', [], + [?CT("Processes: ")] ++ ProcessesList + )]; + +get_node(global, Node, ["pid", PidS], _Query, Lang) -> + NodeS = atom_to_list(Node), + ProcessInfo = rpc:call(Node, erlang, process_info, [list_to_pid(PidS)]), + ProcessInfoS = io_lib:format("~p", [ProcessInfo]), + ProcLinkList = case re:run(ProcessInfoS, "<[0-9]+\\.[0-9]+\\.[0-9]+>", + [global, {capture, all, list}]) of + {match, PidsRareList} -> + lists:map( + fun([PS]) -> + NodePidS = NodeS ++ "/pid/" ++ PS, + ?AC("/admin/node/" ++ NodePidS ++ "/", PS) + end, + PidsRareList); + _ -> + [] + end, + PortLinkList = + case proplists:get_value(links, ProcessInfo) of + Links when is_list(Links) -> + lists:foldl( + fun(Link, LinkRes) when is_port(Link) -> + PortInfo = rpc:call(Node, erlang, port_info, [Link]), + PortInfoString = io_lib:format("~p", [PortInfo]), + LinkRes ++ [{erlang:port_to_list(Link), PortInfoString}]; + (_Link, LinkRes) -> LinkRes + end, + [], + Links); + _ -> + [] + end, + [?XC('h1', io_lib:format(?T("Erlang Process ~s at node ~p"), [PidS, Node])), + ?XC('h3', ?T("Process Information:")), + ?XAE('pre', [], [?C(ProcessInfoS)]), + ?XC('h3', ?T("Related Processes:")), + ?XAE('p', [], ProcLinkList), + ?XC('h3', ?T("Linked Ports:")), + ?XE('ul', + [ ?XE('li', [ ?C(PortName), ?BR, ?C(PortDescr) ]) + || {PortName, PortDescr} <- PortLinkList]) + ]; + get_node(global, Node, ["ports"], Query, Lang) -> Ports = rpc:call(Node, ejabberd_config, get_local_option, [listen]), Res = case catch node_ports_parse_query(Node, Ports, Query) of @@ -2964,6 +3039,7 @@ make_node_menu(global, Node, Lang) -> NodeBase = get_base_path(global, Node), NodeFixed = [{"db/", "Database"}, {"backup/", "Backup"}, + {"pid/", "Erlang Processes"}, {"ports/", "Listened Ports"}, {"stats/", "Statistics"}, {"update/", "Update"}] |