]> granicus.if.org Git - ejabberd/commitdiff
*** empty log message ***
authorAlexey Shchepin <alexey@process-one.net>
Thu, 2 Jan 2003 21:01:12 +0000 (21:01 +0000)
committerAlexey Shchepin <alexey@process-one.net>
Thu, 2 Jan 2003 21:01:12 +0000 (21:01 +0000)
SVN Revision: 25

src/ejabberd_c2s.erl
src/ejabberd_local.erl
src/ejabberd_router.erl
src/jlib.erl
src/mod_disco.erl
src/mod_register.erl
src/mod_vcard.erl [new file with mode: 0644]
src/namespaces.hrl [new file with mode: 0644]
src/xml.erl

index 170cfcec8e4350e0e42f8b1afac91f7a36fd4671..a6189035641ec645e96326dbfdb9369dc986ad37 100644 (file)
@@ -24,6 +24,7 @@
         terminate/3]).
 
 -include("ejabberd.hrl").
+-include("namespaces.hrl").
 
 -define(SETS, gb_sets).
 
@@ -288,6 +289,18 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
                                StateData
                        end,
                {false, Attrs, NewSt};
+           "iq" ->
+               IQ = jlib:iq_query_info(Packet),
+               case IQ of
+                   {iq, ID, Type, ?NS_VCARD, SubEl} ->
+                       ResIQ = mod_vcard:process_sm_iq(From, To, IQ),
+                       ejabberd_router:route(To,
+                                             From,
+                                             jlib:iq_to_xml(ResIQ)),
+                       {false, Attrs, StateData};
+                   _ ->
+                       {true, Attrs, StateData}
+               end;
            _ ->
                {true, Attrs, StateData}
        end,
@@ -315,6 +328,14 @@ terminate(Reason, StateName, StateData) ->
            ejabberd_sm:close_session(StateData#state.user,
                                      StateData#state.resource)
     end,
+    From = {StateData#state.user,
+           StateData#state.server,
+           StateData#state.resource},
+    Packet = {xmlelement, "presence", [{"type", "unavailable"}], []},
+    ejabberd_sm:unset_presence(StateData#state.user,
+                              StateData#state.resource),
+    presence_broadcast(From, StateData#state.pres_a, Packet),
+    presence_broadcast(From, StateData#state.pres_i, Packet),
     StateData#state.sender ! close,
     ok.
 
@@ -463,7 +484,7 @@ presence_update(From, Packet, StateData) ->
        "unsubscribed" ->
            StateData;
        _ ->
-           update_priority(jlib:get_subtag(Packet, "priority"), StateData),
+           update_priority(xml:get_subtag(Packet, "priority"), StateData),
            FromUnavail = (StateData#state.pres_last == undefined) or
                StateData#state.pres_invis,
            ?DEBUG("from unavail = ~p~n", [FromUnavail]),
index c42a8a019f181cf96d5b3f949e91ac31dacbf7d7..0bb2181eacf4f538dd5be64183a561da18a3a392 100644 (file)
@@ -23,6 +23,7 @@ start() ->
     mod_register:start(),
     mod_roster:start(),
     mod_disco:start(),
+    mod_vcard:start(),
     ok.
 
 init() ->
index e28eeb7416f708da9ee58562face0c2ef5c4455e..b58bbdb9ab58dcf77fac77ce89e4c55158bba47f 100644 (file)
@@ -10,7 +10,8 @@
 -author('alexey@sevcom.net').
 -vsn('$Revision$ ').
 
--export([route/3, register_route/1, register_local_route/1]).
+-export([route/3, register_route/1, register_local_route/1,
+        dirty_get_all_routes/0]).
 
 -export([start/0, init/0]).
 
@@ -90,7 +91,7 @@ do_route(From, To, Packet) ->
                    [] ->
                        case mnesia:read({route, DstDomain}) of
                            [] ->
-                               error;
+                               false;
                            [R] ->
                                {ok, R#route.node, R#route.pid}
                        end;
@@ -99,7 +100,7 @@ do_route(From, To, Packet) ->
                end
        end,
     case mnesia:transaction(F) of
-       {atomic, error} ->
+       {atomic, false} ->
            ejabberd_s2s ! {route, From, To, Packet};
        {atomic, {ok, Node, Pid}} ->
            case node() of
@@ -125,3 +126,9 @@ register_route(Domain) ->
 register_local_route(Domain) ->
     ejabberd_router ! {register_local_route, Domain, self()}.
 
+
+dirty_get_all_routes() ->
+    lists:delete(?MYNAME,
+                lists:umerge(lists:sort(mnesia:dirty_all_keys(route)),
+                             lists:sort(mnesia:dirty_all_keys(local_route)))).
+
index 974117fded1c1c6136cf0319a0e8f761a29328e6..6cafb9598a722d149cb8f122019c5c89383d6ed9 100644 (file)
@@ -25,8 +25,7 @@
         get_iq_namespace/1,
         iq_query_info/1,
         is_iq_request_type/1,
-        iq_to_xml/1,
-        get_subtag/2]).
+        iq_to_xml/1]).
 
 
 %send_iq(From, To, ID, SubTags) ->
@@ -249,17 +248,3 @@ iq_to_xml({iq, ID, Type, _, SubEl}) ->
     end.
 
 
-get_subtag({xmlelement, _, _, Els}, Name) ->
-    get_subtag1(Els, Name).
-
-get_subtag1([El | Els], Name) ->
-    case El of
-       {xmlelement, Name, _, _} ->
-           El;
-       _ ->
-           get_subtag1(Els, Name)
-    end;
-get_subtag1([], _) ->
-    false.
-
-
index 16512ddf5e20003d9ea4e43393f648c0e2b6472b..b49ef1be8d9c34369b38493e0474f8a7fc3cd427 100644 (file)
@@ -2,7 +2,7 @@
 %%% File    : mod_disco.erl
 %%% Author  : Alexey Shchepin <alexey@sevcom.net>
 %%% Purpose : 
-%%% Created :  1 Jan 2003 by Alexey Shchepin <alex@alex.sevcom.net>
+%%% Created :  1 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
 %%% Id      : $Id$
 %%%----------------------------------------------------------------------
 
@@ -18,9 +18,7 @@
         register_feature/1]).
 
 -include("ejabberd.hrl").
-
--define(NS_DISCO_ITEMS, "http://jabber.org/protocol/disco#items").
--define(NS_DISCO_INFO, "http://jabber.org/protocol/disco#info").
+-include("namespaces.hrl").
 
 -define(EMPTY_INFO_RESULT,
        {iq, ID, result, XMLNS, [{xmlelement, "query",
@@ -56,7 +54,9 @@ process_local_iq_items(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
        get ->
            case xml:get_tag_attr_s("node", SubEl) of
                "" ->
-                   Domains = [],
+                   Domains =
+                       lists:map(fun domain_to_xml/1,
+                                 ejabberd_router:dirty_get_all_routes()),
                    {iq, ID, result, XMLNS,
                     [{xmlelement,
                       "query",
@@ -124,6 +124,9 @@ process_local_iq_info(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
 feature_to_xml({Feature}) ->
     {xmlelement, "feature", [{"var", Feature}], []}.
 
+domain_to_xml(Domain) ->
+    {xmlelement, "item", [{"jid", Domain}], []}.
+
 
 get_online_users() ->
     case catch ejabberd_sm:dirty_get_sessions_list() of
index b9d5be87fdfbc44765614d6928b14335a3d16118..457ca31fcb3a294810a7b306c24f80e4bc2ddea8 100644 (file)
@@ -25,9 +25,9 @@ init() ->
 process_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
     case Type of
        set ->
-           UTag = jlib:get_subtag(SubEl, "username"),
-           PTag = jlib:get_subtag(SubEl, "password"),
-           RTag = jlib:get_subtag(SubEl, "remove"),
+           UTag = xml:get_subtag(SubEl, "username"),
+           PTag = xml:get_subtag(SubEl, "password"),
+           RTag = xml:get_subtag(SubEl, "remove"),
            if
                (UTag /= false) and (RTag /= false) ->
                    {iq, ID, error, XMLNS,
diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl
new file mode 100644 (file)
index 0000000..bdef5db
--- /dev/null
@@ -0,0 +1,239 @@
+%%%----------------------------------------------------------------------
+%%% File    : mod_vcard.erl
+%%% Author  : Alexey Shchepin <alexey@sevcom.net>
+%%% Purpose : 
+%%% Created :  2 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
+%%% Id      : $Id$
+%%%----------------------------------------------------------------------
+
+-module(mod_vcard).
+-author('alexey@sevcom.net').
+-vsn('$Revision$ ').
+
+-export([start/0, init/0,
+        process_local_iq/3,
+        process_sm_iq/3]).
+
+-include("ejabberd.hrl").
+-include("namespaces.hrl").
+
+
+-record(vcard_search, {user, fn, family, given, middle, nickname,
+                      bday, ctry, locality, email,
+                      orgname, orgunit}).
+-record(vcard, {user, vcard}).
+
+
+start() ->
+    mnesia:create_table(vcard, [{disc_only_copies, [node()]},
+                               {attributes, record_info(fields, vcard)}]),
+    mnesia:create_table(vcard_search,
+                       [{disc_copies, [node()]},
+                        {attributes, record_info(fields, vcard_search)}]),
+    %mnesia:add_table_index(vcard_search, fn),
+    %mnesia:add_table_index(vcard_search, n),
+    %mnesia:add_table_index(vcard_search, nickname),
+    %mnesia:add_table_index(vcard_search, bday),
+    %mnesia:add_table_index(vcard_search, ctry),
+    %mnesia:add_table_index(vcard_search, locality),
+    %mnesia:add_table_index(vcard_search, email),
+    %mnesia:add_table_index(vcard_search, orgname),
+    %mnesia:add_table_index(vcard_search, orgunit),
+
+
+    ejabberd_local:register_iq_handler(?NS_VCARD,
+                                      ?MODULE, process_local_iq),
+    ejabberd_sm:register_iq_handler(?NS_VCARD,
+                                   ?MODULE, process_sm_iq),
+    spawn(?MODULE, init, []).
+
+init() ->
+    ejabberd_router:register_local_route("ejud." ++ ?MYNAME),
+    loop().
+
+loop() ->
+    receive
+       {route, From, To, Packet} ->
+           do_route(From, To, Packet),
+           loop();
+       _ ->
+           loop()
+    end.
+
+
+process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
+    case Type of
+       set ->
+           {User, Server, _} = From,
+           LUser = jlib:tolower(User),
+           LServer = jlib:tolower(Server),
+           case ?MYNAME of
+               LServer ->
+                   set_vcard(LUser, SubEl),
+                   {iq, ID, result, XMLNS, []};
+               _ ->
+                   {iq, ID, error, XMLNS,
+                    [SubEl, {xmlelement, "error",
+                             [{"code", "405"}],
+                             [{xmlcdata, "Not Allowed"}]}]}
+           end;
+       get ->
+           {iq, ID, result, XMLNS,
+            [{xmlelement, "vCard",
+              [{"xmlns", ?NS_VCARD}],
+              [{xmlelement, "FN", [],
+                [{xmlcdata, "ejabberd"}]},
+               {xmlelement, "URL", [],
+                [{xmlcdata,
+                  "http://www.jabber.ru/projects/ejabberd/"}]},
+               {xmlelement, "DESC", [],
+                [{xmlcdata, "Erlang Jabber Server\n"
+                  "Copyright (c) 2002, 2003 Alexey Shchepin"}]},
+               {xmlelement, "BDAY", [],
+                [{xmlcdata, "20021116"}]}
+              ]}]}
+    end.
+
+
+process_sm_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
+    case Type of
+       set ->
+           {iq, ID, error, XMLNS, [SubEl, {xmlelement, "error",
+                                           [{"code", "405"}],
+                                           [{xmlcdata, "Not Allowed"}]}]};
+       get ->
+           {User, _, _} = To,
+           LUser = jlib:tolower(User),
+           F = fun() ->
+                       mnesia:read({vcard, LUser})
+               end,
+           Els = case mnesia:transaction(F) of
+                     {atomic, Rs} ->
+                         lists:map(fun(R) ->
+                                           R#vcard.vcard
+                                   end, Rs);
+                     {aborted, Reason} ->
+                         []
+                 end,
+           {iq, ID, result, XMLNS, Els}
+    end.
+
+
+set_vcard(LUser, VCARD) ->
+    FN       = xml:get_path_s(VCARD, [{elem, "FN"},                     cdata]),
+    Family   = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "FAMILY"},    cdata]),
+    Given    = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "GIVEN"},     cdata]),
+    Middle   = xml:get_path_s(VCARD, [{elem, "N"}, {elem, "MIDDLE"},    cdata]),
+    Nickname = xml:get_path_s(VCARD, [{elem, "NICKNAME"},               cdata]),
+    BDay     = xml:get_path_s(VCARD, [{elem, "BDAY"},                   cdata]),
+    %ctry     = xml:get_path_s(VCARD, [{elem, "CTRY"}, cdata]),
+    %locality = xml:get_path_s(VCARD, [{elem, "FN"}, cdata]),
+    EMail    = xml:get_path_s(VCARD, [{elem, "EMAIL"},                  cdata]),
+    OrgName  = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGNAME"}, cdata]),
+    OrgUnit  = xml:get_path_s(VCARD, [{elem, "ORG"}, {elem, "ORGUNIT"}, cdata]),
+    F = fun() ->
+               mnesia:write(#vcard{user = LUser, vcard = VCARD}),
+               mnesia:write(#vcard_search{user = LUser,
+                                          fn = FN,
+                                          family = Family,
+                                          given = Given,
+                                          middle = Middle,
+                                          nickname = Nickname,
+                                          bday = BDay,
+                                          %ctry = CTRY,
+                                          %locality = Locality,
+                                          email = EMail,
+                                          orgname = OrgName,
+                                          orgunit = OrgUnit
+                                         })
+       end,
+    mnesia:transaction(F).
+
+-define(FORM,
+       [{xmlelement, "instructions", [],
+         [{xmlcdata, "You need a x:data capable client to search"}]},
+        {xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}],
+         [{xmlelement, "title", [], [{xmlcdata, "Users Search"}]},
+          {xmlelement, "instructions", [],
+           [{xmlcdata, "Fill in fields to search "
+             "for any matching Jabber User"}]},
+          {xmlelement, "field", [{"type", "text-single"},
+                                 {"label", "Full Name"},
+                                 {"var", "fn"}], []}
+         ]}]).
+
+
+
+
+do_route(From, To, Packet) ->
+    {User, Server, Resource} = To,
+    if
+       (User /= "") or (Resource /= "") ->
+           Err = jlib:make_error_reply(Packet, "503", "Service Unavailable"),
+           ejabberd_router ! {route, To, From, Err};
+       true ->
+           IQ = jlib:iq_query_info(Packet),
+           case IQ of
+               {iq, ID, Type, ?NS_SEARCH, SubEl} ->
+                   case Type of
+                       set ->
+                           % TODO
+                           Err = jlib:make_error_reply(
+                                   Packet, "501", "Not Implemented"),
+                           ejabberd_router:route(To, From, Err);
+                       get ->
+                           ResIQ = {iq, ID, result, ?NS_SEARCH,
+                                    [{xmlelement,
+                                      "query",
+                                      [{"xmlns", ?NS_SEARCH}],
+                                      ?FORM
+                                     }]},
+                           ejabberd_router:route(To,
+                                                 From,
+                                                 jlib:iq_to_xml(ResIQ))
+                   end;
+               {iq, ID, Type, ?NS_DISCO_INFO, SubEl} ->
+                   case Type of
+                       set ->
+                           Err = jlib:make_error_reply(
+                                   Packet, "405", "Not Allowed"),
+                           ejabberd_router:route(To, From, Err);
+                       get ->
+                           ResIQ = {iq, ID, result, ?NS_DISCO_INFO,
+                                    [{xmlelement,
+                                      "query",
+                                      [{"xmlns", ?NS_DISCO_INFO}],
+                                      [{xmlelement, "identity",
+                                        [{"category", "directory"},
+                                         {"type", "user"},
+                                         {"name", "EJUD"}], []},
+                                       {xmlelement, "feature",
+                                        [{"var", ?NS_SEARCH}], []}
+                                      ]
+                                     }]},
+                           ejabberd_router:route(To,
+                                                 From,
+                                                 jlib:iq_to_xml(ResIQ))
+                   end;
+               {iq, ID, Type, ?NS_DISCO_ITEMS, SubEl} ->
+                   case Type of
+                       set ->
+                           Err = jlib:make_error_reply(
+                                   Packet, "405", "Not Allowed"),
+                           ejabberd_router:route(To, From, Err);
+                       get ->
+                           ResIQ = {iq, ID, result, ?NS_DISCO_INFO,
+                                    [{xmlelement,
+                                      "query",
+                                      [{"xmlns", ?NS_DISCO_INFO}], []}]},
+                           ejabberd_router:route(To,
+                                                 From,
+                                                 jlib:iq_to_xml(ResIQ))
+                   end;
+               _ ->
+                   Err = jlib:make_error_reply(Packet,
+                                               "503", "Service Unavailable"),
+                   ejabberd_router:route(To, From, Err)
+           end
+    end.
+
diff --git a/src/namespaces.hrl b/src/namespaces.hrl
new file mode 100644 (file)
index 0000000..15b3353
--- /dev/null
@@ -0,0 +1,14 @@
+%%%----------------------------------------------------------------------
+%%% File    : namespaces.hrl
+%%% Author  : Alexey Shchepin <alexey@sevcom.net>
+%%% Purpose : 
+%%% Created :  2 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
+%%%----------------------------------------------------------------------
+
+-define(NS_DISCO_ITEMS, "http://jabber.org/protocol/disco#items").
+-define(NS_DISCO_INFO, "http://jabber.org/protocol/disco#info").
+-define(NS_VCARD, "vcard-temp").
+-define(NS_SEARCH, "jabber:iq:search").
+-define(NS_XDATA, "jabber:x:data").
+
+
index 171607361c9e9d00a860f12124a65a74c4890469..00b7087d52ba4485f72b63eb2af8ff4f944766a8 100644 (file)
@@ -13,7 +13,9 @@
 -export([element_to_string/1, crypt/1, remove_cdata/1,
         get_cdata/1, get_tag_cdata/1,
         get_attr/2, get_attr_s/2,
-        get_tag_attr/2, get_tag_attr_s/2]).
+        get_tag_attr/2, get_tag_attr_s/2,
+        get_subtag/2,
+        get_path_s/2]).
 
 element_to_string(El) ->
     case El of
@@ -100,3 +102,32 @@ get_tag_attr(AttrName, {xmlelement, Name, Attrs, Els}) ->
 get_tag_attr_s(AttrName, {xmlelement, Name, Attrs, Els}) ->
     get_attr_s(AttrName, Attrs).
 
+
+get_subtag({xmlelement, _, _, Els}, Name) ->
+    get_subtag1(Els, Name).
+
+get_subtag1([El | Els], Name) ->
+    case El of
+       {xmlelement, Name, _, _} ->
+           El;
+       _ ->
+           get_subtag1(Els, Name)
+    end;
+get_subtag1([], _) ->
+    false.
+
+
+get_path_s(El, []) ->
+    El;
+get_path_s(El, [{elem, Name} | Path]) ->
+    case get_subtag(El, Name) of
+       false ->
+           "";
+       SubEl ->
+           get_path_s(SubEl, Path)
+    end;
+get_path_s(El, [{attr, Name}]) ->
+    get_tag_attr_s(Name, El);
+get_path_s(El, [cdata]) ->
+    get_tag_cdata(El).
+