Permalink
Browse files

first commit

  • Loading branch information...
0 parents commit 0ee69cf2e7ac27c425af22963e3c1159467d93f8 Boris Okner committed Jul 1, 2011
5 Emakefile
@@ -0,0 +1,5 @@
+%% --
+%%
+%% --
+
+{'/Users/bokner/projects/xmpp_component/trunk/*', [debug_info, {outdir, "/Users/bokner/projects/xmpp_component/trunk/ebin"}, {i, "/Users/bokner/projects/xmpp_component/trunk/include/."}]}.
48 README
@@ -0,0 +1,48 @@
+What is this:
+This is a XMPP component implementation.
+The external component connects to Jabber/XMPP server using XEP-0114 protocol. The code contains a gen_component behavior for handling routed packets in a structured fashion.
+
+test_component.erl contains minimal component code. Please refer to xep0114:test/0 function for usage example.
+
+Prerequisites:
+EXMPP library has to be installed.
+In order for component to be able to connect to the server, product-specific configuration has to be done on a server side.
+If you're using ejabberd, below is a fragment of ejabberd.cfg (release 2.0.5) that corresponds to test/0 mentioned above:
+
+% This fragment has to be added to a service list inside <listen> element; adjust host names acording to your domain names.
+
+<start of fragment>
+
+{7047, ejabberd_service,
+ [{hosts, ["test1.zephyr.local"],
+ [{password, "secret"}]}]},
+
+{9049, ejabberd_service,
+ [{hosts, ["test2.zephyr.local"],
+ [{password, "secret"}]}]},
+
+<end of fragment>
+
+Please refer to ejabberd installation guide for service configuration details.
+
+
+To run the test:
+
+1. Adjust host names according to your domain names both in the fragment below and in test:test_gen_component/0;
+2. Fire Erlang shell in a directory where files are and recompile:
+
+1>make:all([load]).
+
+3. From Erlang shell:
+
+2>test:test_gen_component().
+
+The output should show handshake messages. From now on you should be able to see services through conventional Jabber client
+using Service Discovery. It was tested with Adium and Psi. You will also see incoming packets as the client sends them to services.
+
+License and disclaimers:
+The code is free software and is licensed under GNU General Public License.
+Please refer to source code headers for details.
+
+Contact:
+Boris Okner at boris.okner@gmail.com
9 ebin/weazard.app
@@ -0,0 +1,9 @@
+{application, weazard,
+[{description,"Weazard XMPP component"},
+{vsn,"0.1"},
+{modules,[weazard, gen_component, 'xep-0106', weather_alerts,
+ xml, xml_stream, sha
+]},
+{registered,[]},
+{applications,[kernel, stdlib]},
+{mod,{weazard_app,["test1.zephyr.local", "zephyr.local", 7047, "secret"]}}]}.
349 gen_component.erl
@@ -0,0 +1,349 @@
+%%% File : gen_component.erl
+%%% Author : Boris Okner <b.okner@rogers.com>
+%%% Description : XMPP component behavior
+%%% Created : 27 Jun 2009 by Boris Okner <b.okner@rogers.com>
+%%% This code is based on xmpp_component.erl from Epeios 1.0.0,
+%%% created by Mickael Remond <mremond@process-one.net>
+%%%
+%%% 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(gen_component).
+
+-export([behaviour_info/1]).
+-export([start_component/6, stop_component/1]).
+-export([send_packet/2, print_packet/1, feed_component/2]).
+
+
+%% FSM states:
+-export([wait_open_stream/2,
+ wait_handshake/2,
+ connected/2]).
+
+-export([init/1,
+ handle_event/3,
+ handle_sync_event/4,
+ code_change/4,
+ handle_info/3,
+ terminate/3]).
+
+-export([receiver/3]).
+
+-behaviour(gen_fsm).
+
+% Return a list of required functions and their arity
+behaviour_info(callbacks) ->
+ [
+ {init, 2},
+ {on_connect, 1},
+ {terminate, 1},
+ {handle_iq, 4},
+ {handle_message, 4},
+ {handle_presence, 4},
+ {send_packet, 1},
+ {disco_info, 2},
+ {disco_items, 2},
+ {handle_feed, 2}
+ ];
+behaviour_info(_Other) -> undefined.
+
+% State
+-record(state, {name, secret, host, port, socket, module, module_state, parser}).
+-ifdef(DBGFSM).
+-define(FSMOPTS, [{debug, [trace]}]).
+-else.
+-define(FSMOPTS, []).
+-endif.
+
+-define(PARSER_OPTIONS,
+ [
+ {names_as_atom, true},
+ {check_nss, xmpp},
+ {check_elems, xmpp},
+ {check_attrs, xmpp},
+ {emit_endtag, false},
+ {root_depth, 0},
+ {max_size, infinity}]).
+
+% Interface
+start_component(ComponentName, Server, Port, Secret, Module, Args) ->
+ gen_fsm:start_link({local, list_to_atom(ComponentName)},
+ ?MODULE,
+ [ComponentName, Server, Port, Secret, Module, Args],
+ [?FSMOPTS]).
+
+stop_component(ComponentName) ->
+ % We need to make sure we send "unavailable" presence before connection is shut down.
+ gen_fsm:sync_send_all_state_event(list_to_atom(ComponentName), unavailable),
+ gen_fsm:send_all_state_event(list_to_atom(ComponentName), stop).
+
+% Helpers
+
+send_packet(ComponentName, XmlString) ->
+ send_to_server(ComponentName, {packet, XmlString}).
+
+% Feed from underlying service
+feed_component(ComponentName, Feed) ->
+ send_to_server(ComponentName, {feed, Feed}).
+
+% Incoming packet handling
+receive_packet(Packet, Module, State) ->
+ print_packet(Packet),
+
+ To = exmpp_stanza:get_recipient(Packet),
+ From = exmpp_stanza:get_sender(Packet),
+ Result =
+ case exmpp_iq:is_iq(Packet) of
+ true ->
+ Module:handle_iq(exmpp_iq:xmlel_to_iq(Packet), From, To, State);
+ false ->
+ case exmpp_message:is_message(Packet) of
+ true ->
+ Module:handle_message(Packet, From, To, State);
+ false ->
+ case exmpp_presence:is_presence(Packet) of
+ true ->
+ Module:handle_presence(Packet,
+ From,
+ To, State);
+ false ->
+ throw({error, {unknownPacketType, Packet}})
+ end
+ end
+ end,
+ case Result of
+ ok ->
+ State;
+ {ok, NewState} ->
+ NewState;
+ Other ->
+ throw({unexpected_return, Other})
+ end.
+
+
+print_packet(undefined) ->
+ io:format("empty packet received");
+
+print_packet(Packet) ->
+ io:format("Incoming: ~p~n", [exmpp_xml:document_to_list(Packet)]).
+
+
+
+%% Send the message via the server we are connected to
+send_to_server(ComponentName, Event) ->
+ %io:format("Sending via server: ~p~n", [Event]),
+ gen_fsm:send_event(list_to_atom(ComponentName), Event).
+
+init([ComponentName, Server, Port, Secret, Module, Args]) ->
+ Socket = connect(Server, Port),
+ Parser = exmpp_xml:start_parser(),
+ Pid = start_receiver(Socket, Parser),
+ gen_tcp:controlling_process(Socket, Pid),
+ ok = stream_open(Socket, ComponentName, Server),
+ {ok, ModuleState} = Module:init(ComponentName, Args),
+ {ok, wait_open_stream, #state{name=ComponentName,
+ secret=Secret,
+ host=Server,
+ port=Port,
+ socket=Socket,
+ module=Module,
+ module_state = ModuleState,
+ parser = Parser}}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% state_name(Event, State) -> {next_state, NextStateName, NextState}|
+%% {next_state, NextStateName,
+%% NextState, Timeout} |
+%% {stop, Reason, NewState}
+%% Description:There should be one instance of this function for each possible
+%% state name. Whenever a gen_fsm receives an event sent using
+%% gen_fsm:send_event/2, the instance of this function with the same name as
+%% the current state name StateName is called to handle the event. It is also
+%% called if a timeout occurs.
+%%--------------------------------------------------------------------
+wait_open_stream({xmlstreamstart, stream, Attrs} = Event, State) ->
+ io:format("EV: ~p~n", [Event]),
+ {value, StreamID} = xml:get_attr("id", Attrs),
+ handshake(State#state.socket, StreamID, State#state.secret),
+ {next_state, wait_handshake, State};
+wait_open_stream(Event, State) ->
+ io:format("EV: ~p~n", [Event]),
+ {next_state, wait_open_stream, State}.
+
+wait_handshake({xmlstreamelement,{xmlel, 'jabber:component:accept', [], handshake, [],[]}}, #state{name = ComponentName} = State) ->
+ io:format("Component : ~p started.~n", [ComponentName]),
+ Module = State#state.module,
+ {ok, ModuleState} = Module:on_connect(State#state.module_state),
+ {next_state, connected, State#state{module_state = ModuleState}};
+wait_handshake(Event, State) ->
+ io:format("EV: ~p~n",[Event]),
+ {next_state, wait_handshake, State}.
+
+connected({packet, XMLString}, State) ->
+ gen_tcp:send(State#state.socket, XMLString),
+ {next_state, connected, State};
+connected({xmlstreamelement, Packet}, State) ->
+ Module = State#state.module,
+ ModuleState = receive_packet(Packet, Module, State#state.module_state),
+ {next_state, connected, State#state{module_state = ModuleState}};
+connected({feed, Feed}, State) ->
+ Module = State#state.module,
+ {ok, ModuleState} = Module:handle_feed(Feed, State#state.module_state),
+ {next_state, connected, State#state{module_state = ModuleState}};
+
+connected(Event, State) ->
+ io:format("connected: ~p~n",[Event]),
+ {next_state, connected, State}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_event(Event, StateName, State) -> {next_state, NextStateName,
+%% NextState} |
+%% {next_state, NextStateName,
+%% NextState, Timeout} |
+%% {stop, Reason, NewState}
+%% Description: Whenever a gen_fsm receives an event sent using
+%% gen_fsm:send_all_state_event/2, this function is called to handle
+%% the event.
+%%--------------------------------------------------------------------
+handle_event(stop, _StateName, State) ->
+ {stop, normal, State};
+
+handle_event(_Event, StateName, State) ->
+ {next_state, StateName, State}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_sync_event(Event, From, StateName,
+%% State) -> {next_state, NextStateName, NextState} |
+%% {next_state, NextStateName, NextState,
+%% Timeout} |
+%% {reply, Reply, NextStateName, NextState}|
+%% {reply, Reply, NextStateName, NextState,
+%% Timeout} |
+%% {stop, Reason, NewState} |
+%% {stop, Reason, Reply, NewState}
+%% Description: Whenever a gen_fsm receives an event sent using
+%% gen_fsm:sync_send_all_state_event/2,3, this function is called to handle
+%% the event.
+%%--------------------------------------------------------------------
+handle_sync_event(get_component_name, _From, StateName, State) ->
+ {reply, State#state.name, StateName, State};
+
+handle_sync_event(unavailable, _From, StateName, #state{module = Module, module_state = ModuleState} = State) ->
+ Module:terminate(ModuleState),
+ {reply, ok, StateName, State};
+
+handle_sync_event(_Event, _From, StateName, State) ->
+ Reply = ok,
+ {reply, Reply, StateName, State}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_info(Info,StateName,State)-> {next_state, NextStateName, NextState}|
+%% {next_state, NextStateName, NextState,
+%% Timeout} |
+%% {stop, Reason, NewState}
+%% Description: This function is called by a gen_fsm when it receives any
+%% other message than a synchronous or asynchronous event
+%% (or a system message).
+%%--------------------------------------------------------------------
+handle_info(_Info, StateName, State) ->
+ {next_state, StateName, State}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, StateName, State) -> void()
+%% Description:This function is called by a gen_fsm when it is about
+%% to terminate. It should be the opposite of Module:init/1 and do any
+%% necessary cleaning up. When it returns, the gen_fsm terminates with
+%% Reason. The return value is ignored.
+%%--------------------------------------------------------------------
+terminate(_Reason, _StateName, #state{socket = Socket, parser = _Parser, module = _Module}) ->
+
+ %exmpp_xml:stop_parser(Parser),
+ gen_tcp:close(Socket),
+
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% code_change(OldVsn, StateName, State, Extra) -> {ok, StateName, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, StateName, State, _Extra) ->
+ {ok, StateName, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+%% Connect to the Jabber / XMPP server using the component protocol.
+connect(Server, Port) ->
+
+ Socket = case gen_tcp:connect(Server, Port, [binary,{active, false},
+ {packet, 0},
+ {reuseaddr, true} ], 10000) of
+ {ok, Sock} ->
+ Sock;
+ {error, econnrefused = Reason} ->
+ io:format("Error: server ~s:~p refused the connection.~n~n",
+ [Server, Port]),
+ exit(Reason);
+ {error, Reason} ->
+ io:format("Connection error: [~p]~n~n", [Reason]),
+ exit(Reason)
+ end,
+ Socket.
+
+stream_open(Socket, ComponentName, _Server) ->
+ Packet = ["<stream:stream xmlns='jabber:component:accept'"
+ " xmlns:stream='http://etherx.jabber.org/streams'"
+ " to='", ComponentName, "'>"],
+ gen_tcp:send(Socket, Packet).
+
+handshake(Socket, StreamID, Secret) ->
+ io:format("Handshake: ~p, ~p~n", [StreamID, Secret]),
+ Handshake = sha:sha(StreamID ++ Secret),
+ Packet =["<handshake>", Handshake, "</handshake>"],
+ gen_tcp:send(Socket, Packet).
+
+
+%% Parsing and reception process
+start_receiver(Socket, Parser) ->
+ XMLStreamState = xml_stream:new(self(), Parser),
+ spawn_link(?MODULE, receiver, [Socket, XMLStreamState, Parser]).
+
+
+receiver(Socket, XMLStreamState, Parser) ->
+ process_flag(trap_exit, true),
+ receiver_loop(Socket, XMLStreamState, Parser).
+receiver_loop(Socket, XMLStreamState, Parser) ->
+ case gen_tcp:recv(Socket, 0) of
+ {ok, Data} ->
+ NewXMLStreamState = xml_stream:parse(XMLStreamState, Data),
+ receiver_loop(Socket, NewXMLStreamState, Parser);
+ {error, Reason} ->
+ io:format("Receiver loop: error: ~p~n",[Reason]),
+ catch(xml_stream:close(XMLStreamState)),
+ exit({error, Reason});
+%% Trap exit signal:
+ Other ->
+ io:format("Receiver loop: received: ~p~n",[Other]),
+ catch(xml_stream:close(XMLStreamState)),
+ exit({error, Other})
+ end.
0 gen_component_new
No changes.
535 gen_component_new.erl
@@ -0,0 +1,535 @@
+%% Copyright ProcessOne 2006-2009. All Rights Reserved.
+%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+
+%% @author Ery Lee<ery.lee@gmail.com>
+
+%% @doc
+%% The module <strong>{@module}</strong> implements xep-0114 component.
+%%
+%% <p>
+%% This module is intended to be used directly by client developers.
+%% </p>
+%%
+
+-module(gen_component_new).
+-behaviour(gen_fsm).
+
+%% XMPP Component API:
+-export([start/0, start_link/0, start_debug/0, stop/1]).
+
+-export([auth/3,
+ connect/3,
+ handshake/1,
+ send_packet/2,
+ set_controlling_process/2]).
+
+%% gen_fsm callbacks
+-export([init/1,
+ code_change/4,
+ handle_info/3,
+ handle_event/3,
+ handle_sync_event/4,
+ terminate/3]).
+
+%% States
+-export([setup/3,
+ wait_for_stream/2, wait_for_stream/3,
+ stream_opened/2, stream_opened/3,
+ stream_error/2, stream_error/3,
+ stream_closed/2, stream_closed/3,
+ wait_for_handshake_result/2,
+ session_established/2, session_established/3
+ ]).
+
+-include("exmpp.hrl").
+-include("exmpp_client.hrl").
+
+-record(state, {
+ domain,
+ auth_method,
+ client_pid,
+ connection = exmpp_tcp,
+ connection_ref,
+ stream_ref,
+ stream_id = false,
+ stream_error,
+ receiver_ref,
+ from_pid %% Use by gen_fsm to handle postponed replies
+ }).
+
+%% This timeout should match the connect timeout
+-define(TIMEOUT, 5000).
+
+%%====================================================================
+%% API
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: start_link() -> ok,Pid} | ignore | {error,Error}
+%% Description:Creates a gen_fsm process which calls Module:init/1 to
+%% initialize. To ensure a synchronized start-up procedure, this function
+%% does not return until Module:init/1 has returned.
+%%--------------------------------------------------------------------
+%% Start the Component (used to get a reference):
+start() ->
+ case gen_fsm:start(?MODULE, [self()], []) of
+ {ok, PID} -> PID;
+ {error, Reason} -> erlang:error({error, Reason})
+ end.
+%% Start the Component (used to get a reference):
+start_link() ->
+ case gen_fsm:start_link(?MODULE, [self()], []) of
+ {ok, PID} -> PID;
+ {error, Reason} -> erlang:error({error, Reason})
+ end.
+
+%% Start the Component in debug mode
+%% (trace events)
+start_debug() ->
+ case gen_fsm:start(?MODULE, [self()], [{debug,[trace]}]) of
+ {ok, PID} -> PID;
+ {error, Reason} -> erlang:error({error, Reason})
+ end.
+
+%% Close Component and disconnect
+stop(Component) ->
+ catch gen_fsm:sync_send_all_state_event(Component, stop),
+ ok.
+
+%% Set authentication mode to basic (password)
+auth(Component, Domain, Password)
+ when is_pid(Component),
+ is_list(Domain),
+ is_list(Password) ->
+ gen_fsm:sync_send_event(Component, {set_auth, Domain, Password}).
+
+%% Initiate standard TCP XMPP server connection
+%% If the domain is not passed we expect to find it in the authentication
+%% method. It should thus be set before.
+%% Returns StreamId (String)
+connect(Component, Server, Port)
+ when is_pid(Component),
+ is_list(Server),
+ is_integer(Port) ->
+ case gen_fsm:sync_send_event(Component, {connect_tcp, Server, Port},
+ ?TIMEOUT) of
+ Error when is_tuple(Error) -> erlang:throw(Error);
+ StreamId -> StreamId
+ end.
+
+%% Handshake
+%% Returns ok
+handshake(Component) when is_pid(Component) ->
+ case gen_fsm:sync_send_event(Component, {handshake}) of
+ ok -> ok;
+ Error when is_tuple(Error) -> erlang:throw(Error)
+ end.
+
+%% Send any exmpp formatted packet
+send_packet(Component, Packet) when is_pid(Component) ->
+ case gen_fsm:sync_send_event(Component, {send_packet, Packet}) of
+ Error when is_tuple(Error) -> erlang:throw(Error);
+ Id -> Id
+ end.
+
+set_controlling_process(Component,Client) when is_pid(Component), is_pid(Client) ->
+ case gen_fsm:sync_send_all_state_event(Component, {set_controlling_process, Client}) of
+ Error when is_tuple(Error) -> erlang:throw(Error);
+ Id -> Id
+ end.
+
+%%====================================================================
+%% gen_fsm callbacks
+%%====================================================================
+init([Pid]) ->
+ inets:start(),
+ exmpp_stringprep:start(),
+ {A1,A2,A3} = now(),
+ random:seed(A1, A2, A3),
+ {ok, setup, #state{client_pid=Pid}}.
+
+handle_event(tcp_closed, _StateName, State) ->
+ {stop, tcp_closed, State};
+
+handle_event(_Event, StateName, State) ->
+ {next_state, StateName, State}.
+
+handle_sync_event(stop, _From, _StateName, State) ->
+ Reply = ok,
+ {stop, normal, Reply, State};
+handle_sync_event({set_controlling_process,Client}, _From, StateName, State) ->
+ Reply = ok,
+ {reply,Reply,StateName,State#state{client_pid=Client}};
+handle_sync_event(_Event, _From, StateName, State) ->
+ Reply = ok,
+ {reply, Reply, StateName, State}.
+
+handle_info(_Info, StateName, State) ->
+ {next_state, StateName, State}.
+
+
+terminate(Reason, _StateName, #state{connection_ref = undefined,
+ stream_ref = undefined,
+ from_pid=From}) ->
+ reply(Reason, From),
+ ok;
+terminate(Reason, _StateName, #state{connection_ref = undefined,
+ stream_ref = StreamRef,
+ from_pid=From}) ->
+ exmpp_xmlstream:stop(StreamRef),
+ exmpp_xml:stop_parser(exmpp_xmlstream:get_parser(StreamRef)),
+ reply(Reason, From),
+ ok;
+terminate(Reason, _StateName, #state{connection_ref = ConnRef,
+ connection = Module,
+ stream_ref = undefined,
+ from_pid=From}) ->
+ Module:close(ConnRef),
+ reply(Reason, From),
+ ok;
+terminate(Reason, _StateName, #state{connection_ref = ConnRef,
+ connection = Module,
+ stream_ref = StreamRef,
+ receiver_ref = ReceiverRef,
+ from_pid=From}) ->
+ exmpp_xmlstream:stop(StreamRef),
+ exmpp_xml:stop_parser(exmpp_xmlstream:get_parser(StreamRef)),
+ Module:close(ConnRef, ReceiverRef),
+ reply(Reason, From),
+ ok.
+
+%% Send gen_fsm reply if needed
+reply(_Reply, undefined) ->
+ ok;
+reply(Reply, {P, _} = From) when is_pid(P) ->
+ gen_fsm:reply(From, Reply);
+reply(_, _) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% code_change(OldVsn, StateName, State, Extra) -> {ok, StateName, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, StateName, State, _Extra) ->
+ {ok, StateName, State}.
+
+%%====================================================================
+%% States
+%%====================================================================
+%% ---------------------------
+%% Setup state: Configuration
+
+%% Define JID and authentication method
+setup({set_auth, Domain, Password}, _From, State) ->
+ {reply, ok, setup, State#state{auth_method ={Domain, Password}}};
+setup({connect_tcp, Host, Port}, From, State) ->
+ case State#state.auth_method of
+ undefined ->
+ {reply, {connect_error,
+ authentication_or_domain_undefined}, setup, State};
+ _Other ->
+ connect(exmpp_tcp, {Host, Port}, From, State)
+ end.
+
+%% ---------------------------
+%% Stream negociation:
+
+%% Standard opening stream:
+-define(stream,
+ #xmlstreamstart{element=#xmlel{
+ ns='http://etherx.jabber.org/streams',
+ name=stream}}).
+%% Standard stream error:
+-define(streamerror,
+ #xmlstreamelement{element=#xmlel{
+ ns='http://etherx.jabber.org/streams',
+ name=error,
+ children=[#xmlel{name=Reason} | _MoreReasons]}}).
+
+%% Special stream error: disconnected
+-define(streamdisconnected,
+ #xmlstreamelement{element=#xmlel{
+ ns='http://etherx.jabber.org/streams',
+ name=error,
+ children=[#xmlcdata{cdata= <<"Disconnected">> }]}}).
+
+%% Standard end of stream:
+-define(streamend,
+ #xmlstreamend{endtag=#xmlendtag{
+ ns='http://etherx.jabber.org/streams',
+ name=stream}}).
+
+%% We cannot receive API call in this state
+wait_for_stream(_Event, _From, State) ->
+ {reply, {error, busy_connecting_to_server}, wait_for_stream, State}.
+%% TODO: Check that we receive a client stream. Need change in the
+%% parsing library.
+wait_for_stream(Start = ?stream, State = #state{connection = _Module,
+ connection_ref = _ConnRef,
+ auth_method = _Auth,
+ from_pid = From}) ->
+ %% Get StreamID
+ StreamId = exmpp_xml:get_attribute_as_list(Start#xmlstreamstart.element, id, ""),
+ gen_fsm:reply(From, StreamId),
+ {next_state, stream_opened, State#state{from_pid=undefined,
+ stream_id = StreamId}}.
+
+%% ---------------------------
+%% Between stream opening and Component opening
+
+%% Supported user commands at this stage:
+%% handshake and register
+stream_opened({handshake}, _From,State=#state{auth_method=undefined}) ->
+ {reply, {error, auth_method_undefined}, stream_opened, State};
+stream_opened({handshake}, From, State=#state{connection = Module,
+ connection_ref = ConnRef,
+ stream_id = StreamId, auth_method = {_Domain, Password}}) ->
+ %% Retrieve supported authentication methods:
+ %% TODO: Do different thing if we use basic or SASL auth
+ %% For now, we consider everything is legacy (basic)
+ Digest = exmpp_client_legacy_auth:hex(exmpp_client_legacy_auth:digest(StreamId, Password)),
+ Handshake = #xmlel{name=handshake, children=#xmlcdata{cdata = Digest}},
+ Module:send(ConnRef, Handshake),
+ {next_state, wait_for_handshake_result, State#state{from_pid=From}};
+
+%% We can define update handshake informations after we are connected to
+%% the XMPP server:
+%% Define JID and authentication method
+stream_opened({set_auth, Domain, Password}, _From, State) ->
+ {reply, ok, stream_opened, State#state{auth_method= {Domain, Password}}};
+stream_opened({presence, _Status, _Show}, _From, State) ->
+ {reply, {error, not_session_established}, setup, State};
+%% We allow to send packet here to give control to the developer on all packet
+%% send to the server. The developer can implements his own login management
+%% code.
+%% If the packet is an iq set or get:
+%% We check that there is a valid id and return it to match the reply
+stream_opened({send_packet, Packet}, _From,
+ State = #state{connection = Module,
+ connection_ref = ConnRef}) ->
+ Id = send_packet(Packet, Module, ConnRef),
+ {reply, Id, stream_opened, State}.
+
+%% Process incoming
+%% Dispatch incoming messages
+stream_opened(#xmlstreamelement{element=#xmlel{name=message, attrs=Attrs}=MessageElement}, State = #state{connection = _Module, connection_ref = _ConnRef}) ->
+ process_message(State#state.client_pid, Attrs, MessageElement),
+ {next_state, stream_opened, State};
+%% Dispach IQs from server
+stream_opened(#xmlstreamelement{element=#xmlel{name=iq, attrs=Attrs}=IQElement}, State) ->
+ process_iq(State#state.client_pid, Attrs, IQElement),
+ {next_state, stream_opened, State};
+%% Handle stream error: We keep the process alive to be able
+%% return errors
+stream_opened(?streamerror, State) ->
+ {next_state, stream_error, State#state{stream_error=Reason}};
+%% Handle end of stream
+stream_opened(?streamend, State) ->
+ {next_state, stream_closed, State}.
+
+stream_error(_Signal, _From, State) ->
+ {reply, {stream_error, State#state.stream_error}, stream_error, State}.
+stream_error(?streamend, State) ->
+ {next_state, stream_closed, State};
+stream_error(_Signal, State) ->
+ {next_state, stream_error, State}.
+
+stream_closed(_Signal, _From, State = #state{stream_error = undefined}) ->
+ {reply, {stream_closed, undefined}, stream_closed, State};
+stream_closed(_Signal, _From, State) ->
+ {reply, {stream_error, State#state.stream_error}, stream_closed, State}.
+stream_closed(_Signal, State) ->
+ {next_state, stream_closed, State}.
+
+wait_for_handshake_result(#xmlstreamelement{element=#xmlel{name=handshake}} , State=#state{from_pid = From}) ->
+ case From of
+ undefined -> ok;
+ From -> gen_fsm:reply(From, ok)
+ end,
+ {next_state, session_established, State};
+
+%% Reason comes from streamerror macro
+wait_for_handshake_result(?streamerror, State) ->
+ {stop, {error, Reason}, State}.
+
+%% ---
+%% Send packets
+%% If the packet is an iq set or get:
+%% We check that there is a valid id and return it to match the reply
+session_established({send_packet, Packet}, _From,
+ State = #state{connection = Module,
+ connection_ref = ConnRef}) ->
+ Id = send_packet(Packet, Module, ConnRef),
+ {reply, Id, session_established, State}.
+
+%% ---
+%% Receive packets
+%% When logged in we dispatch the event we receive
+%% Dispatch incoming presence packets
+session_established(#xmlstreamelement{element=#xmlel{name=presence, attrs=Attrs}=PresenceElement},
+ State = #state{connection = _Module, connection_ref = _ConnRef}) ->
+ process_presence(State#state.client_pid, Attrs, PresenceElement),
+ {next_state, session_established, State};
+%% Dispatch incoming messages
+session_established(#xmlstreamelement{element=#xmlel{name=message, attrs=Attrs}=MessageElement}, State = #state{connection = _Module, connection_ref = _ConnRef}) ->
+ process_message(State#state.client_pid, Attrs, MessageElement),
+ {next_state, session_established, State};
+%% Dispach IQs from server
+session_established(#xmlstreamelement{element=#xmlel{name=iq, attrs=Attrs}=IQElement}, State) ->
+ process_iq(State#state.client_pid, Attrs, IQElement),
+ {next_state, session_established, State};
+%% Process unexpected packet
+session_established(_Packet, State) ->
+ %% log it or do something better
+ io:format("!!!ALERT!!! Unknown packet:~p~p~n", [_Packet, State]),
+ {next_state, session_established, State}.
+
+%% TODO:
+%% Handle disconnections
+%% Connection replaced.
+
+%%--------------------------------------------------------------------
+%% Internal functions
+%%--------------------------------------------------------------------
+
+%% Connect to server
+connect(Module, Params, From, State=#state{auth_method = {Domain, _P}}) ->
+ connect(Module, Params, Domain, From, State).
+connect(Module, Params, Domain, From, #state{client_pid=_ClientPid} = State) ->
+ try start_parser() of
+ StreamRef ->
+ try Module:connect(self(), StreamRef, Params) of
+ {ConnRef, ReceiverRef} ->
+ %% basic (legacy) authent: we do not use version
+ %% 1.0 in stream:
+ ok = Module:send(ConnRef,
+ exmpp_stream:opening(Domain,
+ ?NS_COMPONENT_ACCEPT,
+ {0,0})),
+ %% TODO: Add timeout on wait_for_stream to return
+ %% meaningfull error.
+ {next_state, wait_for_stream,
+ State#state{domain = Domain,
+ connection = Module,
+ connection_ref = ConnRef,
+ stream_ref = StreamRef,
+ receiver_ref = ReceiverRef,
+ from_pid = From}}
+ catch
+ Error ->
+ exmpp_xmlstream:stop(StreamRef),
+ %% We do not stop here, because the developer
+ %% might want to start a connection using another
+ %% transport
+ {reply, Error, setup,
+ State#state{stream_ref = undefined,
+ from_pid = From}}
+ end
+ catch
+ Error ->
+ {reply, Error, setup, State}
+ end.
+
+%% Define parser options
+%% No compatibility mode: We use all the nice optimisation of exmpp:
+-define(PARSER_OPTIONS,
+ [
+ {names_as_atom, true},
+ {check_nss, xmpp},
+ {check_elems, xmpp},
+ {check_attrs, xmpp},
+ {emit_endtag, false},
+ {root_depth, 0},
+ {max_size, infinity}]).
+
+%% Start parser and return stream reference
+start_parser() ->
+ exmpp_xmlstream:start({gen_fsm, self()},
+ exmpp_xml:start_parser(?PARSER_OPTIONS),
+ [{xmlstreamstart,new}]).
+
+%% Packet processing functions
+process_presence(ClientPid, Attrs, Packet) ->
+ Type = get_attribute_value(Attrs, type, "available"),
+ Who = get_attribute_value(Attrs, from, ""),
+ Id = get_attribute_value(Attrs, id, ""),
+ ClientPid ! #received_packet{packet_type = presence,
+ type_attr = Type,
+ from = Who,
+ id = Id,
+ raw_packet = Packet}.
+
+process_message(ClientPid, Attrs, Packet) ->
+ Type = get_attribute_value(Attrs, type, "normal"),
+ Who = get_attribute_value(Attrs, from, ""),
+ Id = get_attribute_value(Attrs, id, ""),
+ ClientPid ! #received_packet{packet_type = message,
+ type_attr = Type,
+ from = Who,
+ id = Id,
+ raw_packet = Packet}.
+
+process_iq(ClientPid, Attrs, Packet) ->
+ Type = get_attribute_value(Attrs, type, ""),
+ Who = get_attribute_value(Attrs, from, ""),
+ Id = get_attribute_value(Attrs, id, ""),
+ ClientPid ! #received_packet{packet_type = iq,
+ type_attr = Type,
+ from = Who,
+ id = Id,
+ raw_packet = Packet}.
+
+%% Add a packet ID is needed:
+%% Check that the attribute list has defined an ID.
+%% If no ID has been defined, add a packet id to the list of attributes
+%% This function uses {@link random:uniform/1}. It's up to the caller to
+%% seed the generator.
+check_id(Attrs) ->
+ case exmpp_xml:get_attribute_from_list_as_binary(Attrs, id, <<>>) of
+ <<>> ->
+ Id = exmpp_utils:random_id("Component"),
+ {exmpp_xml:set_attribute_in_list(Attrs, id, Id), Id};
+ Id -> {Attrs, Id}
+ end.
+
+%% Try getting a given atribute from a list of xmlattr records
+%% Return default value if attribute is not found
+get_attribute_value(Attrs, Attr, Default) ->
+ exmpp_xml:get_attribute_from_list_as_list(Attrs, Attr, Default).
+
+%% Internal operations
+%% send_packet: actually format and send the packet:
+send_packet(#xmlel{name=iq, attrs=Attrs}=IQElement, Module, ConnRef) ->
+ Type = exmpp_xml:get_attribute_from_list_as_binary(Attrs, type, undefined),
+ case Type of
+ <<"error">> ->
+ {Attrs2, PacketId} = check_id(Attrs),
+ Module:send(ConnRef, IQElement#xmlel{attrs=Attrs2}),
+ PacketId;
+ <<"result">> ->
+ {Attrs2, PacketId} = check_id(Attrs),
+ Module:send(ConnRef, IQElement#xmlel{attrs=Attrs2}),
+ PacketId;
+ <<"set">> ->
+ {Attrs2, PacketId} = check_id(Attrs),
+ Module:send(ConnRef, IQElement#xmlel{attrs=Attrs2}),
+ PacketId;
+ <<"get">> ->
+ {Attrs2, PacketId} = check_id(Attrs),
+ Module:send(ConnRef, IQElement#xmlel{attrs=Attrs2}),
+ PacketId
+ end;
+send_packet(#xmlel{attrs=Attrs}=Element, Module, ConnRef) ->
+ {Attrs2, Id} = check_id(Attrs),
+ Module:send(ConnRef, Element#xmlel{attrs=Attrs2}),
+ Id.
41 include/.svn/all-wcprops
@@ -0,0 +1,41 @@
+K 25
+svn:wc:ra_dav:version-url
+V 40
+/xmpp_component/!svn/ver/6/trunk/include
+END
+exmpp_nss.hrl
+K 25
+svn:wc:ra_dav:version-url
+V 54
+/xmpp_component/!svn/ver/6/trunk/include/exmpp_nss.hrl
+END
+exmpp_xmpp.hrl
+K 25
+svn:wc:ra_dav:version-url
+V 55
+/xmpp_component/!svn/ver/6/trunk/include/exmpp_xmpp.hrl
+END
+jlib.hrl
+K 25
+svn:wc:ra_dav:version-url
+V 49
+/xmpp_component/!svn/ver/6/trunk/include/jlib.hrl
+END
+exmpp_client.hrl
+K 25
+svn:wc:ra_dav:version-url
+V 57
+/xmpp_component/!svn/ver/6/trunk/include/exmpp_client.hrl
+END
+exmpp.hrl
+K 25
+svn:wc:ra_dav:version-url
+V 50
+/xmpp_component/!svn/ver/6/trunk/include/exmpp.hrl
+END
+exmpp_xml.hrl
+K 25
+svn:wc:ra_dav:version-url
+V 54
+/xmpp_component/!svn/ver/6/trunk/include/exmpp_xml.hrl
+END
239 include/.svn/entries
@@ -0,0 +1,239 @@
+9
+
+dir
+6
+https://tagsahead.svn.beanstalkapp.com/xmpp_component/trunk/include
+https://tagsahead.svn.beanstalkapp.com/xmpp_component
+
+
+
+2009-06-29T17:49:36.322982Z
+6
+teamhand
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+66fc955e-542c-4072-9450-743a066e6300
+
+
+
+
+
+
+0
+
+exmpp_nss.hrl
+file
+
+
+
+
+2009-06-21T22:38:38.000000Z
+2a4adf841d4204042081afcb72290e3f
+2009-06-29T17:49:36.322982Z
+6
+teamhand
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+24067
+
+exmpp_xmpp.hrl
+file
+
+
+
+
+2009-06-21T22:38:38.000000Z
+2ec04887222360f968eecdc4acdf7bc8
+2009-06-29T17:49:36.322982Z
+6
+teamhand
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2106
+
+jlib.hrl
+file
+
+
+
+
+2009-06-21T22:38:38.000000Z
+e5785936ff824fb278a50035091ccbd5
+2009-06-29T17:49:36.322982Z
+6
+teamhand
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13108
+
+exmpp_client.hrl
+file
+
+
+
+
+2009-06-21T22:38:38.000000Z
+ae2ec1705fbdb33cf0658097eea569f4
+2009-06-29T17:49:36.322982Z
+6
+teamhand
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1127
+
+exmpp.hrl
+file
+
+
+
+
+2009-06-21T22:38:38.000000Z
+3f67aa877a01d9ec8a8ea1e15517703c
+2009-06-29T17:49:36.322982Z
+6
+teamhand
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1280
+
+exmpp_xml.hrl
+file
+
+
+
+
+2009-06-21T22:38:38.000000Z
+42532a713b6637da89c266141b9da7de
+2009-06-29T17:49:36.322982Z
+6
+teamhand
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3505
+
1 include/.svn/format
@@ -0,0 +1 @@
+9
40 include/.svn/text-base/exmpp.hrl.svn-base
@@ -0,0 +1,40 @@
+%% Copyright ProcessOne 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+
+% Namespace and prefix macros.
+-include("exmpp_nss.hrl").
+
+% Records to represent XML nodes.
+-include("exmpp_xml.hrl").
+
+% Records to represent XMPP/Jabber specific structures.
+-include("exmpp_xmpp.hrl").
+
+% --------------------------------------------------------------------
+% Records to represent events.
+% --------------------------------------------------------------------
+
+% Stream start.
+-record(xmlstreamstart, {
+ element % #xmlel
+}).
+
+% Depth 1 element, inside a stream.
+-record(xmlstreamelement, {
+ element % #xmlel
+}).
+
+% Stream end.
+-record(xmlstreamend, {
+ endtag % xmlnsendelement
+}).
26 include/.svn/text-base/exmpp_client.hrl.svn-base
@@ -0,0 +1,26 @@
+%% Copyright ProcessOne 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+
+
+%% This record is used to pass received packets back to client.
+%% The record is defined to make it easy to use pattern matching on
+%% the most used data received.
+-record(received_packet,
+ {
+ packet_type, % message, iq, presence
+ type_attr, % depend on packet. Example: set, get, subscribe, etc
+ from, % JID
+ id, % Packet ID
+ queryns, % IQ only: Namespace of the query
+ raw_packet % raw exmpp record
+ }).
540 include/.svn/text-base/exmpp_nss.hrl.svn-base
@@ -0,0 +1,540 @@
+%% Copyright ProcessOne 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+
+% --------------------------------------------------------------------
+% Namespace and prefix macros.
+% --------------------------------------------------------------------
+
+% Defined by XML.
+-define(NS_XML, 'http://www.w3.org/XML/1998/namespace').
+-define(NS_XML_s, "http://www.w3.org/XML/1998/namespace").
+-define(NS_XML_pfx, "xml").
+
+% Defined by XMPP Core (RFC 3920).
+-define(NS_XMPP, 'http://etherx.jabber.org/streams').
+-define(NS_XMPP_pfx, "stream").
+-define(NS_STREAM_ERRORS, 'urn:ietf:params:xml:ns:xmpp-streams').
+-define(NS_TLS, 'urn:ietf:params:xml:ns:xmpp-tls').
+-define(NS_SASL, 'urn:ietf:params:xml:ns:xmpp-sasl').
+-define(NS_BIND, 'urn:ietf:params:xml:ns:xmpp-bind').
+-define(NS_STANZA_ERRORS, 'urn:ietf:params:xml:ns:xmpp-stanzas').
+
+% Defined by XMPP-IM (RFC 3921).
+-define(NS_JABBER_CLIENT, 'jabber:client').
+-define(NS_JABBER_SERVER, 'jabber:server').
+-define(NS_SESSION, 'urn:ietf:params:xml:ns:xmpp-session').
+-define(NS_ROSTER, 'jabber:iq:roster').
+
+% Defined by End-to-End Signing and Object Encryption for XMPP (RFC 3923).
+-define(NS_E2E, 'urn:ietf:params:xml:ns:xmpp-e2e').
+
+% Defined by XEP-0003: Proxy Accept Socket Service (PASS).
+-define(NS_PASS, 'jabber:iq:pass').
+-define(NS_PASS_s, "jabber:iq:pass").
+
+% Defined by XEP-0004: Data Forms.
+-define(NS_DATA_FORMS, 'jabber:x:data').
+-define(NS_DATA_FORMS_s, "jabber:x:data").
+
+% Defined by XEP-0009: Jabber-RPC.
+-define(NS_RPC, 'jabber:iq:rpc').
+-define(NS_RPC_s, "jabber:iq:rpc").
+
+% Defined by XEP-0011: Jabber Browsing.
+-define(NS_BROWSE, 'jabber:iq:browse').
+-define(NS_BROWSE_s, "jabber:iq:browse").
+
+% Defined by XEP-0012: Last Activity.
+-define(NS_LAST_ACTIVITY, 'jabber:iq:last').
+-define(NS_LAST_ACTIVITY_s, "jabber:iq:last").
+
+% Defined by XEP-0013: Flexible Offline Message Retrieval.
+-define(NS_OFFLINE, 'http://jabber.org/protocol/offline').
+-define(NS_OFFLINE_s, "http://jabber.org/protocol/offline").
+
+% Defined by XEP-0016: Privacy Lists.
+-define(NS_PRIVACY, 'jabber:iq:privacy').
+-define(NS_PRIVACY_s, "jabber:iq:privacy").
+
+% Defined by XEP-0020: Feature Negotiation.
+-define(NS_FEATURE_NEG, 'http://jabber.org/protocol/feature-neg').
+-define(NS_FEATURE_NEG_s, "http://jabber.org/protocol/feature-neg").
+
+% Defined by XEP-0022: Message Events.
+-define(NS_MESSAGE_EVENT, 'jabber:x:event').
+-define(NS_MESSAGE_EVENT_s, "jabber:x:event").
+
+% Defined by XEP-0023: Message Expiration.
+-define(NS_MESSAGE_EXPIRE, 'jabber:x:expire').
+-define(NS_MESSAGE_EXPIRE_s, "jabber:x:expire").
+
+% Defined by XEP-0027: Current Jabber OpenPGP Usage.
+-define(NS_PGP_ENCRYPTED, 'jabber:x:encrypted').
+-define(NS_PGP_SIGNED, 'jabber:x:signed').
+-define(NS_PGP_ENCRYPTED_s, "jabber:x:encrypted").
+-define(NS_PGP_SIGNED_s, "jabber:x:signed").
+
+% Defined by XEP-0030: Service Discovery.
+-define(NS_DISCO_INFO, 'http://jabber.org/protocol/disco#info').
+-define(NS_DISCO_ITEMS, 'http://jabber.org/protocol/disco#items').
+-define(NS_DISCO_INFO_s, "http://jabber.org/protocol/disco#info").
+-define(NS_DISCO_ITEMS_s, "http://jabber.org/protocol/disco#items").
+
+% Defined by XEP-0033: Extended Stanza Addressing.
+-define(NS_ADDRESS, 'http://jabber.org/protocol/address').
+-define(NS_ADDRESS_s, "http://jabber.org/protocol/address").
+
+% Defined by XEP-0039: Statistics Gathering.
+-define(NS_STATS, 'http://jabber.org/protocol/stats').
+-define(NS_STATS_s, "http://jabber.org/protocol/stats").
+
+% Defined by XEP-0045: Multi-User Chat.
+-define(NS_MUC, 'http://jabber.org/protocol/muc').
+-define(NS_MUC_ADMIN, 'http://jabber.org/protocol/muc#admin').
+-define(NS_MUC_OWNER, 'http://jabber.org/protocol/muc#owner').
+-define(NS_MUC_UNIQUE, 'http://jabber.org/protocol/muc#unique').
+-define(NS_MUC_USER, 'http://jabber.org/protocol/muc#user').
+-define(NS_MUC_s, "http://jabber.org/protocol/muc").
+-define(NS_MUC_ADMIN_s, "http://jabber.org/protocol/muc#admin").
+-define(NS_MUC_OWNER_s, "http://jabber.org/protocol/muc#owner").
+-define(NS_MUC_UNIQUE_s, "http://jabber.org/protocol/muc#unique").
+-define(NS_MUC_USER_s, "http://jabber.org/protocol/muc#user").
+
+% Defined by XEP-0047: In-Band Bytestreams.
+-define(NS_IBB, 'http://jabber.org/protocol/ibb').
+
+% Defined by XEP-0048: Bookmarks.
+-define(NS_BOOKMARKS, 'storage:bookmarks').
+-define(NS_BOOKMARKS_s, "storage:bookmarks").
+
+% Defined by XEP-0049: Private XML Storage.
+-define(NS_PRIVATE, 'jabber:iq:private').
+-define(NS_PRIVATE_s, "jabber:iq:private").
+
+% Defined by XEP-0050: Ad-Hoc Commands.
+-define(NS_ADHOC, 'http://jabber.org/protocol/commands').
+-define(NS_ADHOC_s, "http://jabber.org/protocol/commands").
+-define(NS_ADHOC_b, <<"http://jabber.org/protocol/commands">>).
+
+% Defined by XEP-0054: vcard-temp.
+-define(NS_VCARD, 'vcard-temp').
+-define(NS_VCARD_s, "vcard-temp").
+
+% Defined by XEP-0055: Jabber Search.
+-define(NS_SEARCH, 'jabber:iq:search').
+-define(NS_SEARCH_s, "jabber:iq:search").
+
+% Defined by XEP-0059: Result Set Management.
+-define(NS_RSM, 'http://jabber.org/protocol/rsm').
+-define(NS_RSM_s, "http://jabber.org/protocol/rsm").
+
+% Defined by XEP-0060: Publish-Subscribe.
+-define(NS_PUBSUB,
+ 'http://jabber.org/protocol/pubsub').
+-define(NS_PUBSUB_ERRORS,
+ 'http://jabber.org/protocol/pubsub#errors').
+-define(NS_PUBSUB_EVENT,
+ 'http://jabber.org/protocol/pubsub#event').
+-define(NS_PUBSUB_OWNER,
+ 'http://jabber.org/protocol/pubsub#owner').
+-define(NS_PUBSUB_SUBSCRIBE_AUTH,
+ 'http://jabber.org/protocol/pubsub#subscribe_authorization').
+-define(NS_PUBSUB_SUBSCRIBE_OPTIONS,
+ 'http://jabber.org/protocol/pubsub#subscribe_options').
+-define(NS_PUBSUB_NODE_CONFIG,
+ 'http://jabber.org/protocol/pubsub#node_config').
+-define(NS_PUBSUB_META_DATA,
+ 'http://jabber.org/protocol/pubsub#meta-data').
+-define(NS_PUBSUB_PUBLISH_OPTIONS,
+ 'http://jabber.org/protocol/pubsub#publish-options').
+-define(NS_PUBSUB_s,
+ "http://jabber.org/protocol/pubsub").
+-define(NS_PUBSUB_ERRORS_s,
+ "http://jabber.org/protocol/pubsub#errors").
+-define(NS_PUBSUB_EVENT_s,
+ "http://jabber.org/protocol/pubsub#event").
+-define(NS_PUBSUB_OWNER_s,
+ "http://jabber.org/protocol/pubsub#owner").
+-define(NS_PUBSUB_SUBSCRIBE_AUTH_s,
+ "http://jabber.org/protocol/pubsub#subscribe_authorization").
+-define(NS_PUBSUB_SUBSCRIBE_OPTIONS_s,
+ "http://jabber.org/protocol/pubsub#subscribe_options").
+-define(NS_PUBSUB_NODE_CONFIG_s,
+ "http://jabber.org/protocol/pubsub#node_config").
+-define(NS_PUBSUB_META_DATA_s,
+ "http://jabber.org/protocol/pubsub#meta-data").
+-define(NS_PUBSUB_PUBLISH_OPTIONS_s,
+ "http://jabber.org/protocol/pubsub#publish-options").
+
+% Defined by XEP-0065: SOCKS5 Bytestreams.
+-define(NS_BYTESTREAMS, 'http://jabber.org/protocol/bytestreams'.
+-define(NS_BYTESTREAMS_s, "http://jabber.org/protocol/bytestreams".
+
+% Defined by XEP-0066: Out of Band Data.
+-define(NS_OOBD_IQ, 'jabber:iq:oob').
+-define(NS_OOBD_X, 'jabber:x:oob').
+-define(NS_OOBD_IQ_s, "jabber:iq:oob").
+-define(NS_OOBD_X_s, "jabber:x:oob").
+
+% Defined by XEP-0070: Verifying HTTP Requests via XMPP.
+-define(NS_HTTP_AUTH, 'http://jabber.org/protocol/http-auth').
+-define(NS_HTTP_AUTH_s, "http://jabber.org/protocol/http-auth").
+
+% Defined by XEP-0071: XHTML-IM.
+-define(NS_XHTML_IM, 'http://jabber.org/protocol/xhtml-im').
+-define(NS_XHTML_IM_s, "http://jabber.org/protocol/xhtml-im").
+
+% Defined by XEP-0072: SOAP Over XMPP.
+-define(NS_SOAP_FAULT, 'http://jabber.org/protocol/soap#fault').
+-define(NS_SOAP_FAULT_s, "http://jabber.org/protocol/soap#fault").
+
+% Defined by XEP-0077: In-Band Registration.
+-define(NS_INBAND_REGISTER, 'jabber:iq:register').
+-define(NS_INBAND_REGISTER_FEAT, 'http://jabber.org/features/iq-register').
+-define(NS_INBAND_REGISTER_s, "jabber:iq:register").
+-define(NS_INBAND_REGISTER_FEAT_s, "http://jabber.org/features/iq-register").
+
+% Defined by XEP-0078: Non-SASL Authentication.
+-define(NS_LEGACY_AUTH, 'jabber:iq:auth').
+-define(NS_LEGACY_AUTH_FEAT, 'http://jabber.org/features/iq-aut').
+-define(NS_LEGACY_AUTH_s, "jabber:iq:auth").
+-define(NS_LEGACY_AUTH_FEAT_s, "http://jabber.org/features/iq-aut").
+
+% Defined by XEP-0079: Advanced Message Processing.
+-define(NS_AMP, 'http://jabber.org/protocol/amp').
+-define(NS_AMP_ERRORS, 'http://jabber.org/protocol/amp#error').
+-define(NS_AMP_FEAT, 'http://jabber.org/features/amp').
+-define(NS_AMP_s, "http://jabber.org/protocol/amp").
+-define(NS_AMP_ERRORS_s, "http://jabber.org/protocol/amp#error").
+-define(NS_AMP_FEAT_s, "http://jabber.org/features/amp").
+
+% Defined by XEP-0080: User Location.
+-define(NS_GEOLOC, 'http://jabber.org/protocol/geoloc').
+-define(NS_GEOLOC_s, "http://jabber.org/protocol/geoloc").
+
+% Defined by XEP-0083: Nested Roster Groups.
+-define(NS_ROSTER_DELIMITER, 'roster:delimiter').
+-define(NS_ROSTER_DELIMITER_s, "roster:delimiter").
+
+% Defined by XEP-0084: User Avatar.
+-define(NS_USER_AVATAR, 'urn:xmpp:avatar:metadata').
+-define(NS_USER_AVATAR_s, "urn:xmpp:avatar:metadata").
+
+% Defined by XEP-0085: Chat State Notifications
+-define(NS_CHATSTATES, 'http://jabber.org/protocol/chatstates').
+-define(NS_CHATSTATES_s, "http://jabber.org/protocol/chatstates").
+
+% Defined by XEP-0090: Entity Time.
+-define(NS_TIME_OLD, 'jabber:iq:time').
+-define(NS_TIME_OLD_s, "jabber:iq:time").
+
+% Defined by XEP-0091: Delayed Delivery.
+-define(NS_DELAY_OLD, 'jabber:x:delay').
+-define(NS_DELAY_OLD_s, "jabber:x:delay").
+
+% Defined by XEP-0092: Software Version.
+-define(NS_SOFT_VERSION, 'jabber:iq:version').
+-define(NS_SOFT_VERSION_s, "jabber:iq:version").
+
+% Defined by XEP-0093: Roster Item Exchange.
+-define(NS_ROSTER_EXCHANGE_OLD, 'jabber:x:roster').
+-define(NS_ROSTER_EXCHANGE_OLD_s, "jabber:x:roster").
+
+% Defined by XEP-0095: Stream Initiation.
+-define(NS_SI, 'http://jabber.org/protocol/si').
+-define(NS_SI_s, "http://jabber.org/protocol/si").
+
+% Defined by XEP-0096: File Transfer.
+-define(NS_FILE_TRANSFERT,
+ 'http://jabber.org/protocol/si/profile/file-transfer').
+-define(NS_FILE_TRANSFERT_s,
+ "http://jabber.org/protocol/si/profile/file-transfer").
+
+% Defined by XEP-0100: Gateway Interaction.
+-define(NS_GATEWAY, 'jabber:iq:gateway').
+-define(NS_GATEWAY_s, "jabber:iq:gateway").
+
+% Defined by XEP-0107: User Mood.
+-define(NS_USER_MOOD, 'http://jabber.org/protocol/mood').
+-define(NS_USER_MOOD_s, "http://jabber.org/protocol/mood").
+
+% Defined by XEP-0108: User Activity.
+-define(NS_USER_ACTIVITY, 'http://jabber.org/protocol/activity').
+-define(NS_USER_ACTIVITY_s, "http://jabber.org/protocol/activity").
+
+% Defined by XEP-0114: Jabber Component Protocol.
+-define(NS_COMPONENT_ACCEPT, 'jabber:component:accept').
+-define(NS_COMPONENT_CONNECT, 'jabber:component:connect').
+-define(NS_COMPONENT_ACCEPT_s, "jabber:component:accept").
+-define(NS_COMPONENT_CONNECT_s, "jabber:component:connect").
+
+% Defined by XEP-0115: Entity Capabilities.
+-define(NS_CAPS, 'http://jabber.org/protocol/caps').
+-define(NS_CAPS_s, "http://jabber.org/protocol/caps").
+
+% Defined by XEP-0118: User Tune.
+-define(NS_USER_TUNE, 'http://jabber.org/protocol/tune').
+-define(NS_USER_TUNE_s, "http://jabber.org/protocol/tune").
+
+% Defined by XEP-0122: Data Forms Validation.
+-define(NS_DATA_FORMS_VALIDATE,
+ 'http://jabber.org/protocol/xdata-validate').
+-define(NS_DATA_FORMS_VALIDATE_s,
+ "http://jabber.org/protocol/xdata-validate").
+
+% Defined by XEP-0124: Bidirectional-streams Over Synchronous HTTP.
+-define(NS_BOSH, 'http://jabber.org/protocol/httpbind').
+-define(NS_BOSH_s, "http://jabber.org/protocol/httpbind").
+
+% Defined by XEP-0130: Waiting Lists.
+-define(NS_WAITING_LIST, 'http://jabber.org/protocol/waitinglist').
+-define(NS_WAITING_LIST_s, "http://jabber.org/protocol/waitinglist").
+
+% Defined by XEP-0131: Stanza Headers and Internet Metadata (SHIM).
+-define(NS_SHIM, 'http://jabber.org/protocol/shim').
+-define(NS_SHIM_s, "http://jabber.org/protocol/shim").
+
+% Defined by XEP-0136: Message Archiving.
+-define(NS_ARCHIVING, 'urn:xmpp:archive').
+-define(NS_ARCHIVING_s, "urn:xmpp:archive").
+
+% Defined by XEP-0137: Publishing Stream Initiation Requests.
+-define(NS_SI_PUB, 'http://jabber.org/protocol/sipub').
+-define(NS_SI_PUB_s, "http://jabber.org/protocol/sipub").
+
+% Defined by XEP-0138: Stream Compression.
+-define(NS_COMPRESS, 'http://jabber.org/protocol/compress').
+-define(NS_COMPRESS_FEAT, 'http://jabber.org/features/compress').
+-define(NS_COMPRESS_s, "http://jabber.org/protocol/compress").
+-define(NS_COMPRESS_FEAT_s, "http://jabber.org/features/compress").
+
+% Defined by XEP-0141: Data Forms Layout.
+-define(NS_DATA_FORMS_LAYOUT,
+ 'http://jabber.org/protocol/xdata-layout').
+-define(NS_DATA_FORMS_LAYOUT_s,
+ "http://jabber.org/protocol/xdata-layout").
+
+% Defined by XEP-0144: Roster Item Exchange.
+-define(NS_ROSTER_EXCHANGE, 'http://jabber.org/protocol/rosterx').
+-define(NS_ROSTER_EXCHANGE_s, "http://jabber.org/protocol/rosterx").
+
+% Defined by XEP-0145: Annotations.
+-define(NS_ROSTER_NOTES, 'storage:rosternotes').
+-define(NS_ROSTER_NOTES_s, "storage:rosternotes").
+
+% Defined by XEP-0153: vCard-Based Avatars.
+-define(NS_VCARD_UPDATE, 'vcard-temp:x:update').
+-define(NS_VCARD_UPDATE_s, "vcard-temp:x:update").
+
+% Defined by XEP-0154: User Profile.
+-define(NS_USER_PROFILE, 'urn:xmpp:tmp:profile').
+-define(NS_USER_PROFILE_s, "urn:xmpp:tmp:profile").
+
+% Defined by XEP-0158: Robot Challenges.
+-define(NS_ROBOT_CHALLENGE, 'urn:xmpp:tmp:challenge').
+-define(NS_ROBOT_CHALLENGE_s, "urn:xmpp:tmp:challenge").
+
+% Defined by XEP-0161: Abuse Reporting.
+-define(NS_ABUSE_REPORTING, 'urn:xmpp:tmp:abuse').
+-define(NS_ABUSE_REPORTING_s, "urn:xmpp:tmp:abuse").
+
+% Defined by XEP-0166: Jingle.
+-define(NS_JINGLE, 'urn:xmpp:tmp:jingle').
+-define(NS_JINGLE_ERRORS, 'urn:xmpp:tmp:jingle:errors').
+-define(NS_JINGLE_s, "urn:xmpp:tmp:jingle").
+-define(NS_JINGLE_ERRORS_s, "urn:xmpp:tmp:jingle:errors").
+
+% Defined by XEP-0167: Jingle RTP Sessions.
+-define(NS_JINGLE_RPT, 'urn:xmpp:tmp:jingle:apps:rtp').
+-define(NS_JINGLE_RPT_INFO, 'urn:xmpp:tmp:jingle:apps:rtp:info').
+-define(NS_JINGLE_RPT_s, "urn:xmpp:tmp:jingle:apps:rtp").
+-define(NS_JINGLE_RPT_INFO_s, "urn:xmpp:tmp:jingle:apps:rtp:info").
+
+% Defined by XEP-0168: Resource Application Priority.
+-define(NS_RAP,
+ 'http://www.xmpp.org/extensions/xep-0168.html#ns').
+-define(NS_RAP_ROUTE,
+ 'http://www.xmpp.org/extensions/xep-0168.html#ns-route').
+-define(NS_RAP_s,
+ "http://www.xmpp.org/extensions/xep-0168.html#ns").
+-define(NS_RAP_ROUTE_s,
+ "http://www.xmpp.org/extensions/xep-0168.html#ns-route").
+
+% Defined by XEP-0171: Language Translation.
+-define(NS_LANG_TRANS, 'urn:xmpp:langtrans').
+-define(NS_LANG_TRANS_ITEMS, 'urn:xmpp:langtrans#items').
+-define(NS_LANG_TRANS_s, "urn:xmpp:langtrans").
+-define(NS_LANG_TRANS_ITEMS_s, "urn:xmpp:langtrans#items").
+
+% Defined by XEP-0172: User Nickname.
+-define(NS_USER_NICKNAME, 'http://jabber.org/protocol/nick').
+-define(NS_USER_NICKNAME_s, "http://jabber.org/protocol/nick").
+
+% Defined by XEP-0176: Jingle ICE-UDP Transport Method.
+-define(NS_JINGLE_ICE_UDP, 'urn:xmpp:tmp:jingle:transports:ice-udp').
+-define(NS_JINGLE_ICE_UDP_s, "urn:xmpp:tmp:jingle:transports:ice-udp").
+
+% Defined by XEP-0177: Jingle Raw UDP Transport Method.
+-define(NS_JINGLE_RAW_UDP,
+ 'urn:xmpp:tmp:jingle:transports:raw-udp').
+-define(NS_JINGLE_RAW_UDP_INFO,
+ 'urn:xmpp:tmp:jingle:transports:raw-udp:info').
+-define(NS_JINGLE_RAW_UDP_s,
+ "urn:xmpp:tmp:jingle:transports:raw-udp").
+-define(NS_JINGLE_RAW_UDP_INFO_s,
+ "urn:xmpp:tmp:jingle:transports:raw-udp:info").
+
+% Defined by XEP-0181: Jingle DTMF.
+-define(NS_JINGLE_DTMF, 'urn:xmpp:tmp:jingle:dtmf').
+-define(NS_JINGLE_DTMF_s, "urn:xmpp:tmp:jingle:dtmf").
+
+% Defined by XEP-0184: Message Receipts.
+-define(NS_RECEIPTS, 'urn:xmpp:receipts').
+-define(NS_RECEIPTS_s, "urn:xmpp:receipts").
+
+% Defined by XEP-0186: Invisible Command.
+-define(NS_INVISIBLE_COMMAND, 'urn:xmpp:tmp:invisible').
+-define(NS_INVISIBLE_COMMAND_s, "urn:xmpp:tmp:invisible").
+
+% Defined by XEP-0189: Public Key Publishing.
+-define(NS_PUBKEY, 'urn:xmpp:tmp:pubkey').
+-define(NS_PUBKEY_s, "urn:xmpp:tmp:pubkey").
+
+% Defined by XEP-0191: Simple Communications Blocking.
+-define(NS_BLOCKING, 'urn:xmpp:blocking').
+-define(NS_BLOCKING_ERRORS, 'urn:xmpp:blocking:errors').
+-define(NS_BLOCKING_s, "urn:xmpp:blocking").
+-define(NS_BLOCKING_ERRORS_s, "urn:xmpp:blocking:errors").
+
+% Defined by XEP-0194: User Chatting.
+-define(NS_USER_CHATTING,
+ 'http://www.xmpp.org/extensions/xep-0194.html#ns').
+-define(NS_USER_CHATTING_s,
+ "http://www.xmpp.org/extensions/xep-0194.html#ns").
+
+% Defined by XEP-0195: User Browsing.
+-define(NS_USER_BROWSING,
+ 'http://www.xmpp.org/extensions/xep-0195.html#ns').
+-define(NS_USER_BROWSING_s,
+ "http://www.xmpp.org/extensions/xep-0195.html#ns").
+
+% Defined by XEP-0196: User Gaming.
+-define(NS_USER_GAMING,
+ 'http://www.xmpp.org/extensions/xep-0196.html#ns').
+-define(NS_USER_GAMING_s,
+ "http://www.xmpp.org/extensions/xep-0196.html#ns").
+
+% Defined by XEP-0197: User Viewing.
+-define(NS_USER_VIEWING,
+ 'http://www.xmpp.org/extensions/xep-0197.html#ns').
+-define(NS_USER_VIEWING_s,
+ "http://www.xmpp.org/extensions/xep-0197.html#ns").
+
+% Defined by XEP-0198: Stanza Acknowledgements.
+-define(NS_STANZA_ACK,
+ 'http://www.xmpp.org/extensions/xep-0198.html#ns').
+-define(NS_STANZA_ACK_s,
+ "http://www.xmpp.org/extensions/xep-0198.html#ns").
+
+% Defined by XEP-0199: XMPP Ping.
+-define(NS_PING, 'urn:xmpp:ping').
+-define(NS_PING_s, "urn:xmpp:ping").
+
+% Defined by XEP-0202: Entity Time.
+-define(NS_TIME, 'urn:xmpp:time').
+-define(NS_TIME_s, "urn:xmpp:time").
+
+% Defined by XEP-0203: Delayed Delivery.
+-define(NS_DELAY, 'urn:xmpp:delay').
+-define(NS_DELAY_s, "urn:xmpp:delay").
+
+% Defined by XEP-0206: XMPP Over BOSH.
+-define(NS_XBOSH, 'urn:xmpp:xbosh').
+-define(NS_XBOSH_s, "urn:xmpp:xbosh").
+-define(NS_XBOSH_pfx, "xmpp").
+
+% Defined by XEP-0208: Bootstrapping Implementation of Jingle.
+-define(NS_JINGLE_BOOTSTRAPING,
+ 'http://www.xmpp.org/extensions/xep-0208.html#ns').
+-define(NS_JINGLE_BOOTSTRAPING_s,
+ "http://www.xmpp.org/extensions/xep-0208.html#ns").
+
+% Defined by XEP-0209: Metacontacts.
+-define(NS_METACONTACTS, 'storage:metacontacts').
+-define(NS_METACONTACTS_s, "storage:metacontacts").
+
+% Defined by XEP-0215: External Service Discovery.
+-define(NS_EXTERNAL_DISCO,
+ 'http://www.xmpp.org/extensions/xep-0215.html#ns').
+-define(NS_EXTERNAL_DISCO_s,
+ "http://www.xmpp.org/extensions/xep-0215.html#ns").
+
+% Defined by XEP-0220: Server Dialback.
+-define(NS_DIALBACK, 'jabber:server:dialback').
+-define(NS_DIALBACK_FEAT, 'urn:xmpp:features:dialback').
+-define(NS_DIALBACK_pfx, "db").
+-define(NS_DIALBACK_s, "jabber:server:dialback").
+-define(NS_DIALBACK_FEAT_s, "urn:xmpp:features:dialback").
+
+% Defined by XEP-0221: Data Forms Media Element.
+-define(NS_DATA_FORMS_MEDIA, 'urn:xmpp:tmp:media-element').
+-define(NS_DATA_FORMS_MEDIA_s, "urn:xmpp:tmp:media-element").
+
+% Defined by XEP-0224: Attention.
+-define(NS_ATTENTION,
+ 'http://www.xmpp.org/extensions/xep-0224.html#ns').
+-define(NS_ATTENTION_s,
+ "http://www.xmpp.org/extensions/xep-0224.html#ns").
+
+% Defined by XEP-0225: Component Connections.
+-define(NS_COMPONENT_CONNECTION, 'urn:xmpp:tmp:component').
+-define(NS_COMPONENT_CONNECTION_s, "urn:xmpp:tmp:component").
+
+% Defined by XEP-0227: Portable Import/Export Format for XMPP-IM Servers.
+-define(NS_SERVER_IMPORT_EXPORT,
+ 'http://www.xmpp.org/extensions/xep-0227.html#ns').
+-define(NS_SERVER_IMPORT_EXPORT_s,
+ "http://www.xmpp.org/extensions/xep-0227.html#ns").
+
+% Defined by XEP-0231: Data Element.
+-define(NS_DATA, 'urn:xmpp:tmp:data-element').
+-define(NS_DATA_s, "urn:xmpp:tmp:data-element").
+
+% Defined by XEP-0233: Use of Domain-Based Service Names in XMPP SASL
+% Negotiation.
+-define(NS_DOMAIN_BASED_NAME, 'urn:xmpp:tmp:domain-based-name').
+-define(NS_DOMAIN_BASED_NAME_s, "urn:xmpp:tmp:domain-based-name").
+
+% Defined by XEP-0234: Jingle File Transfer.
+-define(NS_JINGLE_FILE_TRANSFERT, 'urn:xmpp:tmp:jingle:apps:file-transfer').
+-define(NS_JINGLE_FILE_TRANSFERT_s, "urn:xmpp:tmp:jingle:apps:file-transfer").
+
+% Defined by XEP-0235: Authorization Tokens.
+-define(NS_AUTH_TOKEN, 'urn:xmpp:tmp:auth-token').
+-define(NS_AUTH_TOKEN_s, "urn:xmpp:tmp:auth-token").
+
+% Defined by XEP-0237: Roster Sequencing.
+-define(NS_ROSTER_SEQ, 'urn:xmpp:tmp:roster-sequencing').
+-define(NS_ROSTER_SEQ_s, "urn:xmpp:tmp:roster-sequencing").
+
+% Defined by XEP-0244: IO Data.
+-define(NS_IO_DATA, 'urn:xmpp:tmp:io-data').
+-define(NS_IO_DATA_s, "urn:xmpp:tmp:io-data").
+
+% Defined by XEP-0247: Jingle XML Streams.
+-define(NS_JINGLE_XML_STREAM, 'urn:xmpp:tmp:jingle:apps:xmlstream').
+-define(NS_JINGLE_XML_STREAM_s, "urn:xmpp:tmp:jingle:apps:xmlstream").
+
+% Defined by XHTML 1.0.
+-define(NS_XHTML, 'http://www.w3.org/1999/xhtml').
+-define(NS_XHTML_s, "http://www.w3.org/1999/xhtml").
111 include/.svn/text-base/exmpp_xml.hrl.svn-base
@@ -0,0 +1,111 @@
+%% Copyright ProcessOne 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+
+% --------------------------------------------------------------------
+% Type definition.
+% --------------------------------------------------------------------
+
+% NS, element's name and attribute's name.
+-type(xmlname() :: atom() | string()).
+
+% Structures used by XML serialization functions.
+-type(xmldefaultns() :: xmlname() | [xmlname()]).
+-type(xmldefaultnss() :: [xmldefaultns()]).
+-type(xmlprefixednss() :: [{xmlname(), string()}]).
+
+% Path description (to be used in exmpp_xml:get_path/2).
+-type(xmlpathcomponent() ::
+ {element, xmlname()} |
+ {element, xmlname(), xmlname()} |
+ {attribute, xmlname()} |
+ {attribute, xmlname(), xmlname()} |
+ cdata |
+ cdata_as_list).
+-type(xmlpath() :: [xmlpathcomponent()]).
+
+% --------------------------------------------------------------------
+% Records to represent XML nodes.
+% --------------------------------------------------------------------
+
+% Note: The records defined here are documented in exmpp_xml.
+
+% Character data.
+-record(xmlcdata, {
+ cdata = <<>> :: binary()
+}).
+-type(xmlcdata() :: #xmlcdata{}).
+
+% Attributes.
+-record(xmlattr, {
+ ns = undefined :: xmlname() | undefined,
+ name :: xmlname(),
+ value :: binary()
+}).
+-type(xmlattr() :: #xmlattr{}).
+
+% Old attribute isn't represented by a record.
+-type(xmlattr_old() :: {xmlname(), string()}).
+
+% Elements.
+-record(xmlel, {
+ ns = undefined :: xmlname() | undefined,
+ declared_ns = [] :: [{xmlname(), string() | none}],
+ name :: xmlname(),
+ attrs = [] :: [xmlattr()],
+ children = [] :: [#xmlel{} | xmlcdata()] | undefined
+}).
+-type(xmlel() :: #xmlel{}).
+
+% XML end tag.
+% To use when 'children' is undefined in xmlel or xmlelement.
+-record(xmlendtag, {
+ ns = undefined :: xmlname() | undefined,
+ name :: xmlname()
+}).
+-type(xmlendtag() :: #xmlendtag{}).
+
+% Old record for xmlel.
+-record(xmlelement, {
+ name :: xmlname(),
+ attrs = [] :: [xmlattr_old()],
+ children = [] :: [#xmlelement{} | xmlcdata()] | undefined
+}).
+-type(xmlel_old() :: #xmlelement{}).
+
+% Processing Instruction.
+-record(xmlpi, {
+ target :: binary(),
+ value :: binary()
+}).
+-type(xmlpi() :: #xmlpi{}).
+
+-type(xmlattr_any() :: xmlattr() | xmlattr_old()).
+-type(xmlel_any() :: xmlel() | xmlel_old()).
+-type(xmlnode() :: xmlel() | xmlel_old() | xmlcdata()).
+
+% --------------------------------------------------------------------
+% Macros to help creation of XML nodes.
+% --------------------------------------------------------------------
+
+-define(XMLEL1(Name),
+ exmpp_xml:element(Name)).
+-define(XMLEL2(NS, Name),
+ exmpp_xml:element(NS, Name)).
+-define(XMLEL4(NS, Name, Attrs, Children),
+ exmpp_xml:element(NS, Name, Attrs, Children)).
+
+-define(XMLATTR(Name, Value),
+ exmpp_xml:attribute(Name, Value)).
+
+-define(XMLCDATA(CData),
+ exmpp_xml:cdata(CData)).
63 include/.svn/text-base/exmpp_xmpp.hrl.svn-base
@@ -0,0 +1,63 @@
+%% Copyright ProcessOne 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+
+% --------------------------------------------------------------------
+% Records to represent XMPP/Jabber specific structures.
+% --------------------------------------------------------------------
+
+% IQ stanza.
+-record(iq, {
+ kind :: request | response,
+ type :: get | set | result | error,
+ id :: binary() | undefined,
+ ns :: xmlname() | undefined,
+ payload :: #xmlel{} | undefined,
+ error :: #xmlel{} | undefined,
+ lang :: binary() | undefined,
+ iq_ns :: xmlname() | undefined
+}).
+
+% --------------------------------------------------------------------
+% Macros for common tests.
+% --------------------------------------------------------------------
+
+% Guard expression to test a stanza as defined by XMPP-IM.
+-define(IS_IM_STANZA(El), (
+ El#xmlel.ns == ?NS_JABBER_CLIENT orelse
+ El#xmlel.ns == ?NS_JABBER_SERVER orelse
+ El#xmlel.ns == ?NS_COMPONENT_ACCEPT orelse
+ El#xmlel.ns == ?NS_COMPONENT_CONNECT
+)).
+
+% Guard expression to test a message.
+-define(IS_MESSAGE(El), (
+ ?IS_IM_STANZA(El) andalso El#xmlel.name == 'message'
+)).
+
+% Guard expression to test a presence.
+-define(IS_PRESENCE(El), (
+ ?IS_IM_STANZA(El) andalso El#xmlel.name == 'presence'
+)).
+
+% Guard expression to test an IQ.
+-define(IS_IQ(El), (
+ ?IS_IM_STANZA(El) andalso El#xmlel.name == 'iq'
+)).
+-define(IS_IQ_RECORD(IQ), (
+ is_record(IQ, iq)
+)).
+
+% Guard expression to test a JID.
+-define(IS_JID(Jid), (
+ element(1, Jid) =:= 'jid' andalso tuple_size(Jid) =:= 5
+)).
308 include/.svn/text-base/jlib.hrl.svn-base
@@ -0,0 +1,308 @@
+%%%----------------------------------------------------------------------
+%%%
+%%% ejabberd, Copyright (C) 2002-2009 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
+%%%
+%%%----------------------------------------------------------------------
+
+-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_AUTH, "jabber:iq:auth").
+-define(NS_AUTH_ERROR, "jabber:iq:auth:error").
+-define(NS_REGISTER, "jabber:iq:register").
+-define(NS_SEARCH, "jabber:iq:search").
+-define(NS_ROSTER, "jabber:iq:roster").
+-define(NS_PRIVACY, "jabber:iq:privacy").
+-define(NS_PRIVATE, "jabber:iq:private").
+-define(NS_VERSION, "jabber:iq:version").
+-define(NS_TIME, "jabber:iq:time").
+-define(NS_LAST, "jabber:iq:last").
+-define(NS_XDATA, "jabber:x:data").
+-define(NS_IQDATA, "jabber:iq:data").
+-define(NS_DELAY, "jabber:x:delay").
+-define(NS_EXPIRE, "jabber:x:expire").
+-define(NS_EVENT, "jabber:x:event").
+-define(NS_XCONFERENCE, "jabber:x:conference").
+-define(NS_STATS, "http://jabber.org/protocol/stats").
+-define(NS_MUC, "http://jabber.org/protocol/muc").
+-define(NS_MUC_USER, "http://jabber.org/protocol/muc#user").
+-define(NS_MUC_ADMIN, "http://jabber.org/protocol/muc#admin").
+-define(NS_MUC_OWNER, "http://jabber.org/protocol/muc#owner").
+-define(NS_PUBSUB, "http://jabber.org/protocol/pubsub").
+-define(NS_PUBSUB_EVENT, "http://jabber.org/protocol/pubsub#event").
+-define(NS_PUBSUB_OWNER, "http://jabber.org/protocol/pubsub#owner").
+-define(NS_PUBSUB_NMI, "http://jabber.org/protocol/pubsub#node-meta-info").
+-define(NS_PUBSUB_ERRORS,"http://jabber.org/protocol/pubsub#errors").
+-define(NS_PUBSUB_NODE_CONFIG, "http://jabber.org/protocol/pubsub#node_config").
+-define(NS_PUBSUB_SUB_AUTH, "http://jabber.org/protocol/pubsub#subscribe_authorization").
+-define(NS_COMMANDS, "http://jabber.org/protocol/commands").
+-define(NS_BYTESTREAMS, "http://jabber.org/protocol/bytestreams").
+-define(NS_ADMIN, "http://jabber.org/protocol/admin").
+
+-define(NS_EJABBERD_CONFIG, "ejabberd:config").
+
+-define(NS_STREAM, "http://etherx.jabber.org/streams").
+
+-define(NS_STANZAS, "urn:ietf:params:xml:ns:xmpp-stanzas").
+-define(NS_STREAMS, "urn:ietf:params:xml:ns:xmpp-streams").
+
+-define(NS_TLS, "urn:ietf:params:xml:ns:xmpp-tls").
+-define(NS_SASL, "urn:ietf:params:xml:ns:xmpp-sasl").
+-define(NS_SESSION, "urn:ietf:params:xml:ns:xmpp-session").
+-define(NS_BIND, "urn:ietf:params:xml:ns:xmpp-bind").
+
+-define(NS_FEATURE_IQAUTH, "http://jabber.org/features/iq-auth").
+-define(NS_FEATURE_IQREGISTER, "http://jabber.org/features/iq-register").
+-define(NS_FEATURE_COMPRESS, "http://jabber.org/features/compress").
+
+-define(NS_COMPRESS, "http://jabber.org/protocol/compress").
+
+-define(NS_CAPS, "http://jabber.org/protocol/caps").
+
+% TODO: remove "code" attribute (currently it used for backward-compatibility)
+-define(STANZA_ERROR(Code, Type, Condition),
+ {xmlelement, "error",
+ [{"code", Code}, {"type", Type}],
+ [{xmlelement, Condition, [{"xmlns", ?NS_STANZAS}], []}]}).
+
+-define(ERR_BAD_REQUEST,
+ ?STANZA_ERROR("400", "modify", "bad-request")).
+-define(ERR_CONFLICT,
+ ?STANZA_ERROR("409", "cancel", "conflict")).
+-define(ERR_FEATURE_NOT_IMPLEMENTED,
+ ?STANZA_ERROR("501", "cancel", "feature-not-implemented")).
+-define(ERR_FORBIDDEN,
+ ?STANZA_ERROR("403", "auth", "forbidden")).
+-define(ERR_GONE,
+ ?STANZA_ERROR("302", "modify", "gone")).
+-define(ERR_INTERNAL_SERVER_ERROR,
+ ?STANZA_ERROR("500", "wait", "internal-server-error")).
+-define(ERR_ITEM_NOT_FOUND,
+ ?STANZA_ERROR("404", "cancel", "item-not-found")).
+-define(ERR_JID_MALFORMED,
+ ?STANZA_ERROR("400", "modify", "jid-malformed")).
+-define(ERR_NOT_ACCEPTABLE,
+ ?STANZA_ERROR("406", "modify", "not-acceptable")).
+-define(ERR_NOT_ALLOWED,
+ ?STANZA_ERROR("405", "cancel", "not-allowed")).
+-define(ERR_NOT_AUTHORIZED,
+ ?STANZA_ERROR("401", "auth", "not-authorized")).
+-define(ERR_PAYMENT_REQUIRED,
+ ?STANZA_ERROR("402", "auth", "payment-required")).
+-define(ERR_RECIPIENT_UNAVAILABLE,
+ ?STANZA_ERROR("404", "wait", "recipient-unavailable")).
+-define(ERR_REDIRECT,
+ ?STANZA_ERROR("302", "modify", "redirect")).
+-define(ERR_REGISTRATION_REQUIRED,
+ ?STANZA_ERROR("407", "auth", "registration-required")).
+-define(ERR_REMOTE_SERVER_NOT_FOUND,
+ ?STANZA_ERROR("404", "cancel", "remote-server-not-found")).
+-define(ERR_REMOTE_SERVER_TIMEOUT,
+ ?STANZA_ERROR("504", "wait", "remote-server-timeout")).
+-define(ERR_RESOURCE_CONSTRAINT,
+ ?STANZA_ERROR("500", "wait", "resource-constraint")).
+-define(ERR_SERVICE_UNAVAILABLE,
+ ?STANZA_ERROR("503", "cancel", "service-unavailable")).
+-define(ERR_SUBSCRIPTION_REQUIRED,
+ ?STANZA_ERROR("407", "auth", "subscription-required")).
+-define(ERR_UNEXPECTED_REQUEST,
+ ?STANZA_ERROR("400", "wait", "unexpected-request")).
+%-define(ERR_,
+% ?STANZA_ERROR("", "", "")).
+
+-define(STANZA_ERRORT(Code, Type, Condition, Lang, Text),
+ {xmlelement, "error",
+ [{"code", Code}, {"type", Type}],
+ [{xmlelement, Condition, [{"xmlns", ?NS_STANZAS}], []},
+ {xmlelement, "text", [{"xmlns", ?NS_STANZAS}],
+ [{xmlcdata, translate:translate(Lang, Text)}]}]}).
+
+-define(ERRT_BAD_REQUEST(Lang, Text),
+ ?STANZA_ERRORT("400", "modify", "bad-request", Lang, Text)).
+-define(ERRT_CONFLICT(Lang, Text),
+ ?STANZA_ERRORT("409", "cancel", "conflict", Lang, Text)).
+-define(ERRT_FEATURE_NOT_IMPLEMENTED(Lang, Text),
+ ?STANZA_ERRORT("501", "cancel", "feature-not-implemented", Lang, Text)).
+-define(ERRT_FORBIDDEN(Lang, Text),
+ ?STANZA_ERRORT("403", "auth", "forbidden", Lang, Text)).
+-define(ERRT_GONE(Lang, Text),
+ ?STANZA_ERRORT("302", "modify", "gone", Lang, Text)).
+-define(ERRT_INTERNAL_SERVER_ERROR(Lang, Text),
+ ?STANZA_ERRORT("500", "wait", "internal-server-error", Lang, Text)).
+-define(ERRT_ITEM_NOT_FOUND(Lang, Text),
+ ?STANZA_ERRORT("404", "cancel", "item-not-found", Lang, Text)).
+-define(ERRT_JID_MALFORMED(Lang, Text),
+ ?STANZA_ERRORT("400", "modify", "jid-malformed", Lang, Text)).
+-define(ERRT_NOT_ACCEPTABLE(Lang, Text),
+ ?STANZA_ERRORT("406", "modify", "not-acceptable", Lang, Text)).
+-define(ERRT_NOT_ALLOWED(Lang, Text),
+ ?STANZA_ERRORT("405", "cancel", "not-allowed", Lang, Text)).
+-define(ERRT_NOT_AUTHORIZED(Lang, Text),
+ ?STANZA_ERRORT("401", "auth", "not-authorized", Lang, Text)).
+-define(ERRT_PAYMENT_REQUIRED(Lang, Text),
+ ?STANZA_ERRORT("402", "auth", "payment-required", Lang, Text)).
+-define(ERRT_RECIPIENT_UNAVAILABLE(Lang, Text),
+ ?STANZA_ERRORT("404", "wait", "recipient-unavailable", Lang, Text)).
+-define(ERRT_REDIRECT(Lang, Text),
+ ?STANZA_ERRORT("302", "modify", "redirect", Lang, Text)).
+-define(ERRT_REGISTRATION_REQUIRED(Lang, Text),
+ ?STANZA_ERRORT("407", "auth", "registration-required", Lang, Text)).
+-define(ERRT_REMOTE_SERVER_NOT_FOUND(Lang, Text),
+ ?STANZA_ERRORT("404", "cancel", "remote-server-not-found", Lang, Text)).
+-define(ERRT_REMOTE_SERVER_TIMEOUT(Lang, Text),
+ ?STANZA_ERRORT("504", "wait", "remote-server-timeout", Lang, Text)).
+-define(ERRT_RESOURCE_CONSTRAINT(Lang, Text),
+ ?STANZA_ERRORT("500", "wait", "resource-constraint", Lang, Text)).
+-define(ERRT_SERVICE_UNAVAILABLE(Lang, Text),
+ ?STANZA_ERRORT("503", "cancel", "service-unavailable", Lang, Text)).
+-define(ERRT_SUBSCRIPTION_REQUIRED(Lang, Text),
+ ?STANZA_ERRORT("407", "auth", "subscription-required", Lang, Text)).
+-define(ERRT_UNEXPECTED_REQUEST(Lang, Text),
+ ?STANZA_ERRORT("400", "wait", "unexpected-request", Lang, Text)).
+
+% Auth stanza errors
+-define(ERR_AUTH_NO_RESOURCE_PROVIDED(Lang),
+ ?ERRT_NOT_ACCEPTABLE(Lang, "No resource provided")).
+-define(ERR_AUTH_BAD_RESOURCE_FORMAT(Lang),
+ ?ERRT_NOT_ACCEPTABLE(Lang, "Illegal resource format")).
+-define(ERR_AUTH_RESOURCE_CONFLICT(Lang),
+ ?ERRT_CONFLICT(Lang, "Resource conflict")).
+
+
+-define(STREAM_ERROR(Condition),
+ {xmlelement, "stream:error",
+ [],
+ [{xmlelement, Condition, [{"xmlns", ?NS_STREAMS}], []}]}).
+
+-define(SERR_BAD_FORMAT,
+ ?STREAM_ERROR("bad-format")).
+-define(SERR_BAD_NAMESPACE_PREFIX,
+ ?STREAM_ERROR("bad-namespace-prefix")).
+-define(SERR_CONFLICT,
+ ?STREAM_ERROR("conflict")).
+-define(SERR_CONNECTION_TIMEOUT,
+ ?STREAM_ERROR("connection-timeout")).
+-define(SERR_HOST_GONE,
+ ?STREAM_ERROR("host-gone")).
+-define(SERR_HOST_UNKNOWN,
+ ?STREAM_ERROR("host-unknown")).
+-define(SERR_IMPROPER_ADDRESSING,
+ ?STREAM_ERROR("improper-addressing")).
+-define(SERR_INTERNAL_SERVER_ERROR,
+ ?STREAM_ERROR("internal-server-error")).
+-define(SERR_INVALID_FROM,
+ ?STREAM_ERROR("invalid-from")).
+-define(SERR_INVALID_ID,
+ ?STREAM_ERROR("invalid-id")).
+-define(SERR_INVALID_NAMESPACE,
+ ?STREAM_ERROR("invalid-namespace")).
+-define(SERR_INVALID_XML,
+ ?STREAM_ERROR("invalid-xml")).
+-define(SERR_NOT_AUTHORIZED,
+ ?STREAM_ERROR("not-authorized")).
+-define(SERR_POLICY_VIOLATION,
+ ?STREAM_ERROR("policy-violation")).
+-define(SERR_REMOTE_CONNECTION_FAILED,
+ ?STREAM_ERROR("remote-connection-failed")).
+-define(SERR_RESOURSE_CONSTRAINT,
+ ?STREAM_ERROR("resource-constraint")).
+-define(SERR_RESTRICTED_XML,
+ ?STREAM_ERROR("restricted-xml")).
+% TODO: include hostname or IP
+-define(SERR_SEE_OTHER_HOST,
+ ?STREAM_ERROR("see-other-host")).
+-define(SERR_SYSTEM_SHUTDOWN,
+ ?STREAM_ERROR("system-shutdown")).
+-define(SERR_UNSUPPORTED_ENCODING,
+ ?STREAM_ERROR("unsupported-encoding")).
+-define(SERR_UNSUPPORTED_STANZA_TYPE,
+ ?STREAM_ERROR("unsupported-stanza-type")).
+-define(SERR_UNSUPPORTED_VERSION,
+ ?STREAM_ERROR("unsupported-version")).
+-define(SERR_XML_NOT_WELL_FORMED,
+ ?STREAM_ERROR("xml-not-well-formed")).
+%-define(SERR_,
+% ?STREAM_ERROR("")).
+
+-define(STREAM_ERRORT(Condition, Lang, Text),
+ {xmlelement, "stream:error",
+ [],
+ [{xmlelement, Condition, [{"xmlns", ?NS_STREAMS}], []},
+ {xmlelement, "text", [{"xml:lang", Lang}, {"xmlns", ?NS_STREAMS}],
+ [{xmlcdata, translate:translate(Lang, Text)}]}]}).
+
+-define(SERRT_BAD_FORMAT(Lang, Text),
+ ?STREAM_ERRORT("bad-format", Lang, Text)).
+-define(SERRT_BAD_NAMESPACE_PREFIX(Lang, Text),
+ ?STREAM_ERRORT("bad-namespace-prefix", Lang, Text)).
+-define(SERRT_CONFLICT(Lang, Text),
+ ?STREAM_ERRORT("conflict", Lang, Text)).
+-define(SERRT_CONNECTION_TIMEOUT(Lang, Text),
+ ?STREAM_ERRORT("connection-timeout", Lang, Text)).
+-define(SERRT_HOST_GONE(Lang, Text),
+ ?STREAM_ERRORT("host-gone", Lang, Text)).
+-define(SERRT_HOST_UNKNOWN(Lang, Text),
+ ?STREAM_ERRORT("host-unknown", Lang, Text)).
+-define(SERRT_IMPROPER_ADDRESSING(Lang, Text),
+ ?STREAM_ERRORT("improper-addressing", Lang, Text)).
+-define(SERRT_INTERNAL_SERVER_ERROR(Lang, Text),
+ ?STREAM_ERRORT("internal-server-error", Lang, Text)).
+-define(SERRT_INVALID_FROM(Lang, Text),
+ ?STREAM_ERRORT("invalid-from", Lang, Text)).
+-define(SERRT_INVALID_ID(Lang, Text),
+ ?STREAM_ERRORT("invalid-id", Lang, Text)).
+-define(SERRT_INVALID_NAMESPACE(Lang, Text),
+ ?STREAM_ERRORT("invalid-namespace", Lang, Text)).
+-define(SERRT_INVALID_XML(Lang, Text),
+ ?STREAM_ERRORT("invalid-xml", Lang, Text)).
+-define(SERRT_NOT_AUTHORIZED(Lang, Text),
+ ?STREAM_ERRORT("not-authorized", Lang, Text)).
+-define(SERRT_POLICY_VIOLATION(Lang, Text),
+ ?STREAM_ERRORT("policy-violation", Lang, Text)).
+-define(SERRT_REMOTE_CONNECTION_FAILED(Lang, Text),
+ ?STREAM_ERRORT("remote-connection-failed", Lang, Text)).
+-define(SERRT_RESOURSE_CONSTRAINT(Lang, Text),
+ ?STREAM_ERRORT("resource-constraint", Lang, Text)).
+-define(SERRT_RESTRICTED_XML(Lang, Text),
+ ?STREAM_ERRORT("restricted-xml", Lang, Text)).
+% TODO: include hostname or IP
+-define(SERRT_SEE_OTHER_HOST(Lang, Text),
+ ?STREAM_ERRORT("see-other-host", Lang, Text)).
+-define(SERRT_SYSTEM_SHUTDOWN(Lang, Text),
+ ?STREAM_ERRORT("system-shutdown", Lang, Text)).
+-define(SERRT_UNSUPPORTED_ENCODING(Lang, Text),
+ ?STREAM_ERRORT("unsupported-encoding", Lang, Text)).
+-define(SERRT_UNSUPPORTED_STANZA_TYPE(Lang, Text),
+ ?STREAM_ERRORT("unsupported-stanza-type", Lang, Text)).
+-define(SERRT_UNSUPPORTED_VERSION(Lang, Text),
+ ?STREAM_ERRORT("unsupported-version", Lang, Text)).
+-define(SERRT_XML_NOT_WELL_FORMED(Lang, Text),
+ ?STREAM_ERRORT("xml-not-well-formed", Lang, Text)).
+%-define(SERRT_(Lang, Text),
+% ?STREAM_ERRORT("", Lang, Text)).
+
+
+-record(jid, {user, server, resource,
+ luser, lserver, prep_resource}).
+
+-record(iq, {id = "",
+ type,
+ xmlns = "",
+ lang = "",
+ sub_el}).
+
40 include/exmpp.hrl
@@ -0,0 +1,40 @@
+%% Copyright ProcessOne 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+
+% Namespace and prefix macros.
+-include("exmpp_nss.hrl").
+
+% Records to represent XML nodes.
+-include("exmpp_xml.hrl").
+
+% Records to represent XMPP/Jabber specific structures.
+-include("exmpp_xmpp.hrl").
+
+% --------------------------------------------------------------------
+% Records to represent events.
+% --------------------------------------------------------------------
+
+% Stream start.
+-record(xmlstreamstart, {
+ element % #xmlel
+}).
+
+% Depth 1 element, inside a stream.
+-record(xmlstreamelement, {
+ element % #xmlel
+}).
+
+% Stream end.
+-record(xmlstreamend, {
+ endtag % xmlnsendelement
+}).
26 include/exmpp_client.hrl
@@ -0,0 +1,26 @@
+%% Copyright ProcessOne 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+
+
+%% This record is used to pass received packets back to client.
+%% The record is defined to make it easy to use pattern matching on
+%% the most used data received.
+-record(received_packet,
+ {
+ packet_type, % message, iq, presence
+ type_attr, % depend on packet. Example: set, get, subscribe, etc
+ from, % JID
+ id, % Packet ID
+ queryns, % IQ only: Namespace of the query
+ raw_packet % raw exmpp record
+ }).
540 include/exmpp_nss.hrl
@@ -0,0 +1,540 @@
+%% Copyright ProcessOne 2006-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+
+% --------------------------------------------------------------------
+% Namespace and prefix macros.
+% --------------------------------------------------------------------
+
+% Defined by XML.
+-define(NS_XML, 'http://www.w3.org/XML/1998/namespace').
+-define(NS_XML_s, "http://www.w3.org/XML/1998/namespace").
+-define(NS_XML_pfx, "xml").
+
+% Defined by XMPP Core (RFC 3920).
+-define(NS_XMPP, 'http://etherx.jabber.org/streams').
+-define(NS_XMPP_pfx, "stream").
+-define(NS_STREAM_ERRORS, 'urn:ietf:params:xml:ns:xmpp-streams').
+-define(NS_TLS, 'urn:ietf:params:xml:ns:xmpp-tls').
+-define(NS_SASL, 'urn:ietf:params:xml:ns:xmpp-sasl').
+-define(NS_BIND, 'urn:ietf:params:xml:ns:xmpp-bind').
+-define(NS_STANZA_ERRORS, 'urn:ietf:params:xml:ns:xmpp-stanzas').
+
+% Defined by XMPP-IM (RFC 3921).
+-define(NS_JABBER_CLIENT, 'jabber:client').
+-define(NS_JABBER_SERVER, 'jabber:server').
+-define(NS_SESSION, 'urn:ietf:params:xml:ns:xmpp-session').
+-define(NS_ROSTER, 'jabber:iq:roster').
+
+% Defined by End-to-End Signing and Object Encryption for XMPP (RFC 3923).
+-define(NS_E2E, 'urn:ietf:params:xml:ns:xmpp-e2e').
+
+% Defined by XEP-0003: Proxy Accept Socket Service (PASS).
+-define(NS_PASS, 'jabber:iq:pass').
+-define(NS_PASS_s, "jabber:iq:pass").
+
+% Defined by XEP-0004: Data Forms.
+-define(NS_DATA_FORMS, 'jabber:x:data').
+-define(NS_DATA_FORMS_s, "jabber:x:data").
+
+% Defined by XEP-0009: Jabber-RPC.
+-define(NS_RPC, 'jabber:iq:rpc').
+-define(NS_RPC_s, "jabber:iq:rpc").
+
+% Defined by XEP-0011: Jabber Browsing.
+-define(NS_BROWSE, 'jabber:iq:browse').
+-define(NS_BROWSE_s, "jabber:iq:browse").
+
+% Defined by XEP-0012: Last Activity.
+-define(NS_LAST_ACTIVITY, 'jabber:iq:last').
+-define(NS_LAST_ACTIVITY_s, "jabber:iq:last").
+
+% Defined by XEP-0013: Flexible Offline Message Retrieval.
+-define(NS_OFFLINE, 'http://jabber.org/protocol/offline').
+-define(NS_OFFLINE_s, "http://jabber.org/protocol/offline").