Compare commits

...

1280 Commits

Author SHA1 Message Date
Badlop 8cd0894ad5 Update version numbers of the related: exmpp, ejabberd 2, and Erlang 2011-03-11 10:55:34 +01:00
Badlop 33feca74ec Document that ODBC tables are created by ejabberd itself (EJAB-1421) 2011-03-10 20:29:07 +01:00
Badlop 102dabdefc Only attempt to migrate an old ODBC table if it still exists 2011-03-10 20:29:04 +01:00
Christophe Romain 38bf3bfc1c fix PEP broadcasting (thanks to Karim Gemayel)(EJAB-1411) 2011-03-10 12:24:56 +01:00
Pablo Polvorin afec527f5f Include client namespace in CAPs queries (EJAB-1411)
When constructing an IQ record, if no namespace is specified
for the IQ,  exmpp treat that literally as "no namespace" and
so put xmlns="" (it do not interpret it as "no change" and let
the parent namespace apply).
So it is neccesarly to especify the jabber:client namespace.

See EXMPP-53.
2011-03-09 16:30:16 -03:00
Badlop 8a135262db Fix bashism and remove duplicate unused option (EJAB-1404) 2011-03-09 16:26:09 +01:00
Pablo Polvorin 3b2af5dfc5 Fix internal-server-error error response (EJAB-1414).
Ejabberd was trying to send a tuple instead of the full error stanza.
2011-03-09 10:30:54 -03:00
Badlop 4caf2c8674 If the port number isn't listener, then specify the protocol (EJAB-1418) 2011-03-03 11:36:35 +01:00
Badlop 6cc950d76f captcha_host must have the port number to get protocol (EJAB-1418) 2011-03-03 00:05:06 +01:00
Badlop bf8e09038e ejabberdctl needs space between INET_DIST_INTERFACE (thanks to Dale Chase)(EJAB-1416) 2011-02-28 18:42:04 +01:00
Badlop 9a55ced505 Fix to show correctly the command that is unknown 2011-02-23 16:51:40 +01:00
Badlop eaa17dab90 Revert "Mention in release notes that Pubsub/PEP isn't ready for alpha-testing (EJAB-1393)"
This reverts commit 76b0300505.
2011-02-23 12:06:32 +01:00
Badlop 62a4e20ae7 Tweak pg2_backport.erl to work with Erlang older than R13A (EJAB-1349) 2011-02-22 23:44:22 +01:00
Badlop e0bda563e6 Add support for '@online@' Shared Roster Group (thanks to Martin Langhoff)(EJAB-1391)
New version of the @online@ patch originally by Collabora.
Notes:
- the presence push is mediated via the group rather than
  per user - this may reduce memory footprint... _if_ ejabberd
  has some smart optimisation in that codepath
- it assumes that any group with membership @online@ _displays_
  online as well -- this is a simplification and breaks the
  decoupling that ejabberd has in this regard.
2011-02-21 22:32:57 +01:00
Badlop 61e4fde247 Forward old messages to newly spawned extauth process (thanks to Mika Seppänen)(EJAB-1385) 2011-02-21 16:19:45 +01:00
Christophe Romain 7f899ee179 fix broadcast issue (EJAB-1411) 2011-02-21 15:12:31 +01:00
Christophe Romain 75a85beb80 Merge branch 'master' of git+ssh://gitorious.process-one.net/ejabberd/mainline 2011-02-21 14:45:44 +01:00
Christophe Romain 0b7bb342cf fix API issue for subscribe/unsubscribe (EJAB-1410) 2011-02-21 14:45:05 +01:00
Badlop 8f9bf47d78 New route_iq/5 accepting Timeout (thanks to Edwin Fine)(EJAB-1398)
Also new register_iq_response_handler/5
2011-02-21 13:46:59 +01:00
Badlop 76b0300505 Mention in release notes that Pubsub/PEP isn't ready for alpha-testing (EJAB-1393) 2011-02-21 12:55:40 +01:00
Christophe Romain 15749a2193 server must generate itemid if not given at publish time (EJAB-1409) 2011-02-21 12:08:58 +01:00
Badlop 60d83f937d New DIST_USE_INTERFACE to restrict IP where erlang connections are listened (EJAB-1404) 2011-02-16 23:53:40 +01:00
Badlop 7060791e4e New Indonesian translation (thanks to Irfan Mahfudz Guntur)(EJAB-1407) 2011-02-16 13:46:48 +01:00
Christophe Romain 72395ba497 fix empty pubsub payload check 2011-02-14 16:48:54 +01:00
Christophe Romain 4a2005f7cc update copyright up to 2011 2011-02-14 13:47:22 +01:00
Badlop 90c711162b Provide HTTPS URL in CAPTCHA form when listener has 'tls' option (EJAB-1406) 2011-02-14 13:01:46 +01:00
Badlop 7111ecc1b7 Fix typo in French translation 2011-02-11 20:21:24 +01:00
Badlop e1cc8a90fa Escape output from ctlexec() to erl script (thanks to Dan Scott)(EJAB-1399) 2011-02-09 16:34:48 +01:00
Christophe Romain 96d1400792 typo fix 2011-02-09 16:32:11 +01:00
Christophe Romain 975e7f47ee fix previous commit issues 2011-02-09 14:27:40 +01:00
Christophe Romain 2f681b05f3 refactor pubsub broadcast to allow large optimization 2011-02-08 19:08:38 +01:00
Badlop a3dba06baf Remove erroneous comment (EJAB-645) 2011-02-03 17:27:04 +01:00
Badlop 16a97ab903 Handle Tigase's unexpected version=1.0 when ejabberd doesn't announce it (EJAB-1379) 2011-01-31 19:50:56 +01:00
Badlop d8f339bceb Add to example config file access_from comment 2011-01-28 17:16:36 +01:00
Badlop 798d7bce1b Fix unused variable when code was copied from mod_pubsub.erl 2011-01-27 16:42:27 +01:00
Badlop a98193ea6e Merge exmpp jlib.erl into ejabberd jlib.erl (EJAB-1377) 2011-01-27 16:30:55 +01:00
Pablo Polvorin 70a2200888 Fix initial presence after roster subscription approval (EJAB-1384)
Send initial presence after the roster subscription workflow
is complete.
2011-01-27 11:05:16 -03:00
Badlop 3391c9cad7 mod_pres_counter prevents subscription flood (thanks to Ahmed Omar and Alexey Shchepin)(EJAB-1388) 2011-01-19 23:44:53 +01:00
Badlop d5cfdc7f1f Fix delayed response of a timeout call was reused for next login (EJAB-1385) 2011-01-19 19:27:52 +01:00
Badlop caf64c035f Subsecond timestamp granularity in offline messages (EJAB-1376) 2011-01-18 23:25:41 +01:00
Badlop 089a00fc3f Clarify more the expected content of welcome_message mod_register option 2011-01-17 23:42:51 +01:00
Badlop bec67378aa Fix compilation bug in BOSH 2011-01-17 17:31:28 +01:00
Badlop 9bb4f124ad Update NODE and HOST with the definitive values from ejabberdctl or command line 2011-01-17 17:28:12 +01:00
Christophe Romain 722fdd6bc7 check_start must grep processes for nodename last 2011-01-17 16:55:00 +01:00
Christophe Romain d34dab4822 improve check_start, avoid false process match with grep 2011-01-17 16:52:20 +01:00
Badlop ad357c2f59 Clarify error message when BOSH query is sent to non-running module 2011-01-14 15:48:22 +01:00
Badlop 2d0d46e296 Option to reject S2S connection if untrusted certificate (EJAB-464) 2011-01-11 16:38:33 +01:00
Badlop d523901ddc Include From attribute in the stream header of outgoing S2S connections 2011-01-11 16:38:32 +01:00
Badlop 41fc44e55f When TLS is required in s2s, add subelement to stream:features starttls 2011-01-11 16:38:30 +01:00
Badlop befb4fc7ea Add option to require encryption in S2S connections (EJAB-495) 2011-01-11 16:38:28 +01:00
Pablo Polvorin 54557cb867 Send correct from/to attributes in s2s dialback response (EJAB-1363).
We were sending swapped from/to attributes when replying to db:verify requests.
Some servers don't mind about this, but others like prosody checks this and
rejects the verification, the s2s connection in that case couldn't be established.
2011-01-10 17:46:07 -03:00
Badlop 2d3efdf983 Fix old unresolved merge conflicts in pg.sql
Please note that ejabberd takes care to create the tables in your
ODBC database if needed. The file pg.sql is provided for reference
purposes only, as it isn't needed when preparing the database.
2011-01-09 18:51:24 +01:00
Badlop 159529d539 Add start time information in ejabberd log
One way to print that information is to configure in ejabberd.cfg
  {loglevel, {4, [{ejabberd_app, debug}]}}.
2011-01-05 18:38:01 +01:00
Badlop e3d875d09f Several bugfixes in Caps (thanks to Karim Gemayel)
- fix bug with caps 2.0: ERRORs were logged in some cases
- enhance record definitions
- turn string() data into binary() ones
- remove mod_caps:node_to_binary/2, mod_caps:features_to_binary/1 and mod_caps:binary_to_features/1.

Tested with Psi+ (caps 1.0) and OneTeam (caps 2.0), and they now don't produce ERROR REPORTs.
2010-12-30 20:32:01 +01:00
Badlop ea84f802e5 Keep the order of stanzas when BOSH sends several (EJAB-1374) 2010-12-30 13:49:26 +01:00
Badlop 20c4919eda Revert buggy previous commit (thanks to W. Andrew Loe III), and add better fix 2010-12-30 13:49:07 +01:00
Badlop 9cbf08700d Provide stacktrace in log report when a transaction fails 2010-12-30 13:47:15 +01:00
Badlop ff455f1a42 Don't delete the whole table, as other module instances may already have started rooms. 2010-12-30 13:44:53 +01:00
Evgeniy Khramtsov a4728d14d5 Change c2s state before offline messages resending 2010-12-28 21:12:33 +09:00
Christophe Romain f2925d8efc new caps processing and related fixes in ejabberd_c2s.erl and miscellaneous fixes in mod_pubsub.erl (Thanks to Karim Gemayel)(EJAB-620) 2010-12-24 16:21:28 +01:00
Badlop 4b0a7fe307 Only call mod_roster when the user is in a local vhost, fixing EJAB-869 2010-12-23 21:05:21 +01:00
Badlop 980d9c37ea Fix bug introduced with an old commit (EJAB-72) 2010-12-23 19:19:00 +01:00
Alexey Shchepin a40e9c2626 Remove version=1.0 from stream opening when TLS is not available (thanks to Karim Gemayel) 2010-12-23 16:28:35 +02:00
Badlop 897141c9e1 Delete obsolete modules, because now the standard ones use gen_storage 2010-12-23 14:19:59 +01:00
Badlop d20b6dccb3 Remove log line that was intended only for debugging during development 2010-12-23 13:30:41 +01:00
Badlop fe909a45e9 Allow auth modules to provide SASL errors; default is "not-authorized".
See
http://tools.ietf.org/html/draft-saintandre-rfc3920bis-09#section-7.4
2010-12-23 13:27:24 +01:00
Alexey Shchepin bb4a87806f Make jlib:ip_to_list safe to use 2010-12-23 13:17:14 +01:00
Badlop 7ca1c0387c Clean muc_online_room when mod_muc starts (EJAB-1365) 2010-12-23 02:16:00 +01:00
Badlop 8c4e4e5f91 Bugfix in starting persistent rooms when mod_muc odbc (EJAB-1365) 2010-12-23 02:15:58 +01:00
Badlop 93787bee73 Bugfix mod_muc odbc couldn't register nickname (EJAB-1364) 2010-12-23 02:15:56 +01:00
Badlop d3efcf8682 Document the types of some state elements 2010-12-23 02:15:53 +01:00
Badlop 268e80ece7 Document in mod_muc.erl the gen_storage table schema (EJAB-1368) 2010-12-23 02:15:43 +01:00
Badlop a33c389b9b Add support in WebAdmin to register vhosts, and a page to restart or remove it 2010-12-23 02:15:40 +01:00
Badlop 9ce44cd0a7 New ejabberd commands to list, register and remove vhosts 2010-12-23 02:15:38 +01:00
Badlop be8e1bfc35 Fix register of vhost (EJAB-1346) 2010-12-23 02:15:35 +01:00
Badlop 7b2b9412ad Add some variable type hints 2010-12-23 02:15:33 +01:00
Badlop 75f2e775ab Update auth modules to support stopping 2010-12-23 02:15:09 +01:00
Badlop 0859667a8c Fix Type definition 2010-12-21 01:04:52 +01:00
Badlop 563344d219 Remove call to function no longer existent 2010-12-21 01:03:00 +01:00
Evgeniy Khramtsov a13c9185f7 Make sure 'closed' event is correctly processed on every state 2010-12-17 17:27:52 +09:00
W. Andrew Loe III 1eeff9b0df Export make_sid so we can use it in pre-binding. 2010-12-15 16:58:09 +01:00
W. Andrew Loe III 942c6e4dd0 Ignore OS X libraries. 2010-12-15 16:47:46 +01:00
Badlop 8b7d529519 Add release notes for ejabberd 2.1.6 2010-12-15 16:25:41 +01:00
Badlop a47caa8c54 Fix warning about unused variables 2010-12-13 20:59:36 +01:00
Badlop aee3e30232 Fix some exmpp attribute type 2010-12-11 23:16:17 +01:00
Badlop 1bbb41682a Mention in the Guide that mod_muc supports the backend option 2010-12-09 23:58:43 +01:00
Badlop d448b6c955 Fix some errors when porting from mod_pubsub.erl (thanks to Karim Gemayel) 2010-12-07 19:36:34 +01:00
Badlop 74f86bef6a Support for X-Forwarded-For HTTP header (EJAB-1356) 2010-12-07 16:51:20 +01:00
Christophe Romain ce0219c569 update pubsub_odbc patch 2010-12-07 15:22:54 +01:00
Christophe Romain 53cc032251 add node attribute to pubsub subscribe event (EJAB-1361) 2010-12-07 13:53:58 +01:00
Badlop a8bf889e79 Fix detection of mod_last at server start (EJAB-641) 2010-12-03 17:25:10 +01:00
Badlop 4e2bd18c7f Update example extauth script with tryregister, removeuser and removeuser3 (EJAB-641) 2010-12-03 17:23:55 +01:00
Badlop 27872c6022 Support PostgreSQL 9.0 (EJAB-1359)(thanks to Stephen Gibberd and Konstantin Nikiforov) 2010-12-03 12:43:27 +01:00
Badlop c6e0cff144 Fix use of exmpp 2010-12-02 20:14:54 +01:00
Pablo Polvorin a8ef64ab45 Fix cyrsasl_digest RFC-2831 2.1.2.1 (EJAB-476)
Fix sasl digest bug when username|password|resource strings had
all characters <= U+00FF and at least one character >= U+0080.

Warnning:
Note that by fixing the bug, we may be broking compatibility with clients
that "implements" it.
See comments on https://support.process-one.net/browse/EJAB-476
2010-12-02 12:56:21 -03:00
Christophe Romain 9afaec40f5 fix pubsub cross domain eventing (EJAB-1340) 2010-12-02 14:05:19 +01:00
Evgeniy Khramtsov 8520b76483 Increase maximum restart strategy of the ODBC supervisor. Do not brutally kill ODBC processes on supervisor shutdown to avoid polution of the mnesia table 2010-12-01 14:25:58 +09:00
Badlop b8f04aae6f When the Password attribute is missing in PIEFXIS file, don't check account auth. 2010-12-01 00:55:29 +01:00
Pablo Polvorin c9db1f691c Merge branch 'master' of git+ssh://git@gitorious.process-one.net/ejabberd/mainline 2010-11-29 16:56:32 -03:00
Pablo Polvorin ef572c815f Port to latest exmpp changes (attribute names as binary()).
All atributes are now binary() instead of atoms.
2010-11-29 16:44:31 -03:00
Christopher tofu Zorn dad3297c9c expose find_connection for routing in other modules (if needed) 2010-11-29 20:06:02 +01:00
Christopher tofu Zorn 312574cbc5 add the ability to send raw xml packets over http bind 2010-11-29 20:06:00 +01:00
Badlop 008a0a29cd Fix characters not allowed in username. Don't include that in translatable string.
List mentioned in:
http://xmpp.org/rfcs/rfc3920.html#nodeprep-prohibited
2010-11-29 19:39:01 +01:00
Badlop f9e2466867 Support negative part-hour TZ values (thanks to Alexander Zhukov)(EJAB-1301) 2010-11-29 14:35:57 +01:00
Alexey Shchepin 26550efd91 Don't loop when there is nothing after a stream start 2010-11-26 17:11:56 +01:00
Andreas Köhler 7be6e33ea4 Correct domain_certfile tlsopts modifications for s2s connections (EJAB-1086)
* In ejabberd_s2s_out:wait_for_feature_request/2, the domain to use for
  looking up domain_certfile options is #state.myname and not
  #state.server

* If s2s_certfile is not specified, connect should still be part of the
  tls options used by ejabberd_s2s_out

* Add #state.server to ejabberd_s2s_in processes and store the to
  attribute in :wait_for_stream/2. Then use that server in
  :wait_for_feature_request/2 to change the tls options like in
  ejabberd_s2s_out.

Fixes EJAB-1086.
2010-11-26 00:13:36 +01:00
Badlop 7aa48e265a Send Unavailable Presence stanza when an occupant is kicked or banned (EJAB-1350) 2010-11-22 21:16:34 +01:00
Badlop 2ef06678c0 Port SSLVER detection from 2.1.x, needed for ?PG2 (EJAB-1349) 2010-11-22 16:20:40 +01:00
Badlop 2aa56cd86e Use pg2 from R14B in systems with older versions (EJAB-1349)
pg2_backport.erl is a copy of pg2.erl from Erlang/OTP R14B.
That module is used in ejabberd installations where an OTP
previous to R14 is installed.
2010-11-22 16:02:36 +01:00
Badlop 33116be0ae Disapprove the use of R14A and R14B due to the rwlock bug. 2010-11-19 15:36:48 +01:00
Badlop d94f6b45bf Remove forgotten mentions of obsolete and undocumented mod_..._odbc 2010-11-19 11:31:01 +01:00
Christophe Romain 81f4e71efa add missing modrosterodbc newcommand 2010-11-19 10:35:00 +01:00
Evgeniy Khramtsov 5a3fe4e348 Document mod_shared_roster_ldap (thanks to Marcin Owsiany) 2010-11-18 17:02:21 +09:00
Badlop c2dface515 Fix http-bind supervisor to support multiple vhosts (EJAB-1321) 2010-11-17 20:30:37 +01:00
Andreas Köhler 690c56ca6d Fix R12B5 compatibility in ejabberd_http_bind.erl (EJAB-1343)
erlang:max/2 and :min/2 are new functions
2010-11-17 13:03:59 +01:00
Andreas Köhler aaa69a8c36 Use LFrom and LTo consistently in ejabberd_s2s_in:stream_established/2 (EJAB-1342) 2010-11-17 12:56:18 +01:00
Evgeniy Khramtsov ec0e0ef8a6 Do not start mod_proxy65 if it is unable to bind an address (EJAB-1336) 2010-11-17 18:13:55 +09:00
Evgeniy Khramtsov 0b8a761a61 Use MEDIUMTEXT type for vcard avatars in MySQL schema (EJAB-1252) 2010-11-17 17:42:04 +09:00
Evgeniy Khramtsov 0ccbd7e3f2 Do not print full error message when LDAP timeout occurs (EJAB-1324) 2010-11-17 17:15:28 +09:00
Evgeniy Khramtsov 549f1029a6 Set SSL_MODE_RELEASE_BUFFERS mode when available (EJAB-1351) 2010-11-17 13:55:35 +09:00
Badlop da7e53fe3c Temporary workaround for starting stored rooms 2010-11-16 02:13:58 +01:00
Badlop 3e9de2ec79 Provide new, not old, affiliation in kick/ban presence with codes 321 and 301 2010-11-16 01:19:34 +01:00
Badlop d146ef873d Fix typos in the example configuration file 2010-11-12 22:01:09 +01:00
Andreas Köhler d8d20d5b88 Before binding tcp ports, checks the socket type and listener options
(EJAB-1334)

If the callback module has a socket type of independent and needs to
create the listener itself, do not pre-bind the port. The same holds if
there are errors in the listener configuration.
2010-11-10 23:45:27 +01:00
Andreas Köhler 1ab92d1159 Bind listener ports early and start accepting connections later
(EJAB-1334)

It may happen that auth or rdbms client tcp connections bind a local
socket to a port number required by a configered listener. The ejabberd
applications fails to start up and needs to be restarted.

In plain C you would bind(2) the listener port and listen(2) later on.
gen_tcp:listen/2 does not allow to separate these two steps though, so
another way is not to accept connections while start up. OTOH, the
kernel will syn/ack incoming connections and receive data, leaving them
in a buffer for the ejabberd to read from. If this is unwanted, a load
balancer would need to receive data from the ejabberd server before
adding the node to its pool.

This patch binds tcp ports while initializing the ejabberd_listener
process, storing ListenSockets in an ets table. start_listeners/0 will
reuse these ports later on.
2010-11-10 23:45:24 +01:00
Badlop abf069da9e Rollback some Specs that break Dialyzer (thanks to Karim Gemayel)(EJAB-1345) 2010-11-10 21:27:53 +01:00
ppolvorin f4f949bd72 Fix anonymous user cleanup (EJAB-883)
anonymous users table and vcards were not correctly cleaned up
after the user disconnect.
2010-11-10 13:27:47 -03:00
Andreas Köhler f4507a088a In mod_last*:get_last_iq/4, check for user resources first to return 0 seconds if there is one
Fixes problem 2 of EJAB-1158.
2010-11-10 15:41:10 +01:00
Andreas Köhler 6b46b8f794 Refactor mod_last to use the same core get_last/2 functionality, but keep api stable
The local function get_last/4 has been renamed to get_last_iq/4, since
it converts the result of get_last/2 (typically {ok, TimeStamp, Status})
to an iq packet.
2010-11-10 15:41:09 +01:00
Andreas Köhler 7d93cad452 Before forwarding last activity requests to a user, check that the user's presence is visible for From
According to XEP-0012, 4. Online User Query, "if the requesting entity
is not authorized to view the user's presence information (normally via
a presence subscription as defined in XMPP IM), the user's server MUST
NOT deliver the IQ-get to an available resource but instead MUST return
a <forbidden/> error in response to the last activity request."

So check for a subscription of from of the jid and bare jid and whether
outgoing presences to From are allowed.

Fixes problem 3 of EJAB-1158.
2010-11-10 15:41:08 +01:00
Andreas Köhler 860d8525ee Remove dead code for NS_VCARD iq packets from ejabberd_c2s
For EJAB-1045, the special NS_VCARD block for handling incoming vcard
iqs on behalf of clients has already been restricted to cases where the
user or resource part of the recipient is empty. But then the packets
should not have been routed to the c2s process anyway. This patch
completely removes it.
2010-11-10 15:41:07 +01:00
Andreas Köhler 351635d0aa Use ejabberd_c2s:privacy_check_packet/5 for all those hook folded runs in the c2s module 2010-11-10 15:41:06 +01:00
Andreas Köhler 614f13714c Use c2s state data as user and server in ejabberd_c2s:is_privacy_allow
is_privacy_allow is only used in ejabberd_c2s:handle_info/3 to determine
for a few presence types whether the packet is allowed to be forwarded
to the user's client. This only makes sense if To#jid.user and
To#jid.server match StateData#state.user and StateData#state.server.

Also, add the atom in as parameter to a new argument Dir of
is_privacy_allow and extract from that function
privacy_check_packet(StateData, From, To, Packet, Dir) which runs the
privavcy check without converting allow/deny to true/false.
2010-11-10 15:41:05 +01:00
Andreas Köhler 642b18edcb Correct error responses of forbidden offline last activity queries
According to XEP-0012 Last Activity, the server must return iq errors
with forbidden instead of not-allowed.

Fixes problem 1 of EJAB-1158.
2010-11-10 15:41:03 +01:00
Christophe Romain 03239c662e populate pubsub#roster_groups_allowed in node configuration options (thanks to Karim Gemayel)(EJAB-1344) 2010-11-10 15:14:16 +01:00
Christophe Romain fbb84c8256 fix bad plugin order issue injected in previous patch (EJAB-1286) 2010-11-09 14:36:04 +01:00
Andreas Köhler e710ac51eb Correct privacy check direction in mod_last (EJAB-1339)
The change for EJAB-1271 to change the direction of the privacy check
from out to in violates the idea that the check should imitate a
subscription state check of from. Rather correct the order of the From
and To parameters.
2010-11-09 13:57:01 +01:00
Andreas Köhler 6ce29e7ecb Change max restart strategy of ejabberd_odbc_sup to handle some SQL timeouts. 2010-11-08 18:42:37 +01:00
Badlop e84d853bc3 Improve the IQ error stanzas to provide an explanation (EJAB-1262) 2010-11-08 12:01:14 +01:00
Christophe Romain 5e0f2b8560 avoid node_call to break transaction (thanks to Karim Gemayel)(EJAB-1286) 2010-11-08 11:18:33 +01:00
Andreas Köhler 01b6cd3aba Re-raise exceptions caught in gen_mod:start_module/3 (EJAB-1335)
Modules configured by the administrator normally should not be treated
as optional, so a exception (error, exit, throw) to start them should not
be caught and logged only.

This patch re-raises a caught exception instead of ignoring the
exception and inserting the module's opts on success. That way
gen_mod:get_module_opt/4 should work while calling Module:start/2.
2010-11-07 00:47:53 +01:00
Badlop 2ebfd4090a Fix register 2010-11-06 21:53:18 +01:00
Evgeniy Khramtsov e4a1eb4370 Take care of xml:lang attribute in unauthenticated stanzas as well 2010-11-06 21:53:16 +01:00
Evgeniy Khramtsov e3afec9465 Disable LRU caching algorithm for LDAP shared rosters 2010-11-06 21:53:14 +01:00
Evgeniy Khramtsov 29fbe6d8e1 Do not store long language tag to avoid possible DoS/flood attacks 2010-11-06 21:53:13 +01:00
Evgeniy Khramtsov 5c3611fe32 LDAP shared roster support (thanks to Realloc and Marcin Owsiany) 2010-11-06 21:53:11 +01:00
Badlop 4a1d8c2cd2 New ip_access option restricts which IPs can register (thanks to Alexey Shchepin)(EJAB-915) 2010-11-05 19:33:20 +01:00
Badlop b9c6f6e627 Disable mod_register_web in default config because by default captcha is disabled 2010-11-05 19:33:10 +01:00
Badlop d456578b3c Added mod_register_web: web page for account registration (EJAB-471) 2010-11-05 18:21:59 +01:00
Badlop 659d546897 Fix warnings detected by Dialyzer 2010-11-04 01:00:18 +01:00
Jonas Ådahl bacecae3dd Fixes a leak of ejabberd_receiver processes.
When a (non-frontend) socket module without any custom receiver fails to
start, the newly created ejabberd_receiver process needs to be properly
closed.
2010-11-03 17:10:46 +01:00
Badlop 5168f68946 Don't add Pid to Captcha record when it's requested by c2s instead of muc 2010-11-03 14:05:27 +01:00
Badlop 9a32615122 Handle incoherence of argument type in calls to remove_user 2010-11-03 13:24:40 +01:00
Badlop 48dcc5180a Additional fixes for previous captcha commits related to exmpp 2010-11-03 12:44:11 +01:00
Badlop 32868e534e Include a Required xml element in the captcha field 2010-11-03 12:44:04 +01:00
Evgeniy Khramtsov 773c54f912 Add top-level instructions for x:data incompatible clients 2010-11-03 12:44:03 +01:00
Badlop 82e8048a8a Changes in registration form to workaround client problems (EJAB-1262)
Changes included:
* Remove var in fixed field because Gajim and Tkabber display it to user
* Add workaround for Psi's overlap fields
* Add var=url attribute, required by Psi to display the field
* Provide the image URL as a copy-able form field
2010-11-03 12:44:02 +01:00
Badlop 633b467a22 Workaround for Psi's wrong Type in form submission 2010-11-03 12:44:01 +01:00
Badlop b0ae3d14aa Add CAPTCHA example configurations to cfg (EJAB-1262)(EJAB-1326) 2010-11-03 12:44:00 +01:00
Evgeniy Khramtsov 2d8bfb1a15 Provide image url in registration form when captcha is enabled 2010-11-03 12:43:59 +01:00
Evgeniy Khramtsov 30366dbe98 Add password entropy check (EJAB-1326) 2010-11-03 12:43:58 +01:00
Evgeniy Khramtsov 55bd17d6f5 Rename option captcha to captcha_protected for consistency 2010-11-03 12:43:57 +01:00
Badlop f310292da4 CAPTCHA IBR support (EJAB-1262)(thanks to Evgeniy Khramtsov) 2010-11-03 12:43:55 +01:00
Badlop 81546f3270 Fix crash in ejabberd_c2s when blacklist hook returned true (thanks to Jonas Ådahl)
Cause of the crash jlib:ip_to_list/1 only supports IP tuples using the
form {N1,N2,N3,N4} which is not the case when IPv6 is enabled.
2010-11-02 14:04:10 +01:00
Badlop 91dee14ad6 Fix errors in EDoc comments 2010-10-28 18:23:02 +02:00
Badlop 231d44ffa3 Handle binary data from SockMod:recv in ejabberd_http:recv_data/3 (thanks to Andreas Köhler)(EJAB-1331) 2010-10-27 21:21:15 +02:00
Andreas Köhler 70c247d357 Ignore Length argument to tls:recv/[23] (EJAB-1327)
The Length argument cannot be used for gen_tcp:recv/3, because the
compressed size does not equal the desired uncompressed one.
2010-10-26 19:33:56 +02:00
Andreas Köhler 1579bf2d18 Re-use the TLSSock argument in tls:send/2 (EJAB-1327) 2010-10-26 19:33:53 +02:00
Badlop d9ac399c74 Improve example of outoging_s2s_options 2010-10-22 23:16:52 +02:00
Christophe Romain 378b8a60c6 add function specification, convert string() to binary(), fix pubsub.hrl (thanks to Karim Gemayel) 2010-10-19 17:08:59 +02:00
Peter Lemenkov 70cdcfcae1 Change directory before any operation to one readable by INSTALLUSER (EJAB-1322)
This is required in order to suppress error messages like
"File operation error: eacces" when ejabberd was started from directory,
which is not readable by INSTALLUSER (/root, for example). See rhbz #564686:

https://bugzilla.redhat.com/564686

Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2010-10-19 01:16:15 +02:00
Badlop a473935782 Fix bug in mod_pubsub in_subscription return value 2010-10-19 00:28:24 +02:00
Badlop 16f0873488 Fix bug when routing error stanza 2010-10-16 22:51:51 +02:00
Badlop 17b4aaa1f7 When privacy list denies local user's outgoing stanza, try to return error (EJAB-1320)
See:
http://xmpp.org/extensions/xep-0016.html#example-51
Example 51. Error: contact is blocked
2010-10-16 22:51:50 +02:00
Badlop eddbad2c76 Check privacy of outgoing Message stanzas (EJAB-1320) 2010-10-16 22:51:48 +02:00
Badlop 2e932dd85c Add support to ejabberd_ctl to handle anonymous command arguments 2010-10-16 00:48:03 +02:00
Badlop 3bc7127743 Rename aclocal.m4 to acinclude.m4 (thanks to Andreas Köhler)
Also fixed minor typos, added the compiled aclocal.m4 to gitignore,
and documented how to build the script 'configure'.

Related documentation:
http://www.gnu.org/software/hello/manual/automake/Local-Macros.html#Local-Macros
http://www.gnu.org/software/hello/manual/automake/Invoking-aclocal.html#Invoking-aclocal
2010-10-15 16:24:17 +02:00
Badlop d6a69dbca5 Fix errors detected by Dialyzer 2010-10-15 13:11:14 +02:00
Badlop 864b0ec149 Document ejabberd_loglevel using EDoc (EJAB-225) 2010-10-15 13:10:56 +02:00
Badlop abdbb347eb Rename ejabberd_loglevel:get/0 to get_default, and add a more general get (EJAB-225)
API change: ejabberd_loglevel:get/0 renamed to ejabberd_loglevel:get_default/0
2010-10-15 13:10:53 +02:00
Andreas Köhler 651ee5eb19 Fix unused variable warning in ejabberd_loglevel 2010-10-15 13:10:43 +02:00
Andreas Köhler e1f5fb798c Add set_custom/2, clear_custom/0 and clear_custom/1 to ejabberd_loglevel 2010-10-15 13:10:42 +02:00
Andreas Köhler 14349890e3 Document new loglevel configuration form. 2010-10-15 13:10:41 +02:00
Andreas Köhler 81555d8def Add support for changing the loglevels for given modules (EJAB-225)
ejabberd_loglevel:set/1 now understands more input formats:

set(Param) -> {module, ejabberd_logger}
    Param = Level | {Level, CustomLevels}
    CustomLevels = [CustomLevel]
    CustomLevel = {Module, Level}
    Module = atom()
    Level = integer() | atom()

set(Level) is equivalent to set({Level, []}), so it clears all module
level customizations. log_src/2 adds additional function heads for those
_msg function and module combinations that need non-default behavior,
i.e. add or filter logging.

ejabberd_loglevel:get/0 only returns the default log level. To retrieve
the complete setting use ejabberd_logger:get/0 instead.
2010-10-15 13:10:40 +02:00
Andreas Köhler cc76869da5 Use warning_msg event type for warning log level. 2010-10-15 13:10:39 +02:00
Andreas Köhler 6523258b53 Add warning message and report handlers to ejabberd_logger_h.erl. 2010-10-15 13:10:38 +02:00
Andreas Köhler 1cbe821145 Improve ejabberd_logger code generation
Split the monolithic function ejabberd_loglevel:ejabberd_logger_src/1
into separate functions returning deep lists.

log_src/2 now returns the code for any of *_msg/4. Its parameters are
the current loglevel (integer()) and a loglevel specification
(#loglevel{}), with added information in #loglevel:

- function: The api function enabled by this level, may be no_log
- event_type: The type of the event sent to the error_logger
- msg_prefix: One character used in the message (one of "DIWEC")

If the current loglevel is too low for logging, the api function is
optimized at compile time.
2010-10-15 13:10:36 +02:00
Andreas Köhler 61d8bf9440 Use records for encoding static loglevel information. 2010-10-15 13:10:34 +02:00
Badlop d1f5fb4aa9 Speed up ejabberd_s2s:is_service/2, allow_host/2 (thanks to Andreas Köhler)(EJAB-1319)
Iterating through the list of possible parent domains of a given domain
and comparing with the list of hosts or routes is almost always faster
than doing it the other way around. It naturally returns the shortest or
longest parent domain satisfying a predicate, whereas the possibly long
list compared with would need to be sorted by length first.
2010-10-14 21:14:46 +02:00
Badlop 0960637aa4 Include a gitignore file in the ejabberd git repository (EJAB-1312) 2010-10-14 19:49:33 +02:00
Christophe Romain a73d451576 make http-bind restartable (thanks to Andreas Köhler)(EJAB-1318) 2010-10-13 10:55:35 +02:00
Pablo Polvorin ce9ce8293b Merge branch 'master' of git+ssh://git@gitorious.process-one.net/ejabberd/mainline 2010-10-12 10:57:07 -03:00
Badlop 82a8dc7b3a Cosmetic code changes to support emacs indentation 2010-10-07 17:38:18 +02:00
Badlop 404b9a4a11 Minor fix in http_bind detected by Dialyzer 2010-10-07 00:16:24 +02:00
Badlop f4f2f46f50 Dirty fixes for Dialyzer warnings in mod_privacy 2010-10-07 00:14:28 +02:00
Badlop 6c74c67069 Fix Captcha library and MUC use for exmpp 2010-10-06 13:05:21 +02:00
Badlop 645ddcb749 Fix unused variables 2010-10-05 15:48:11 +02:00
Evgeniy Khramtsov 8647ca5f0b use one_queue IQ discipline by default 2010-10-05 21:32:47 +10:00
Christophe Romain ee861e650d fix dializer warnings (thanks to Karim Gemayel) 2010-10-04 17:41:59 +02:00
Badlop 349c44fcc0 Fix Edoc errors (thanks to Karim Gemayel) 2010-09-30 13:44:16 +02:00
Christophe Romain 78b8307a1f fix dializer warnings (thanks to Karim Gemayel) 2010-09-30 12:06:40 +02:00
Christophe Romain 7c580bbeed Merge branch 'master' of git+ssh://gitorious.process-one.net/ejabberd/mainline 2010-09-29 11:48:40 +02:00
Christophe Romain 6b7d73dcd5 fix dializer errors, improve documentation (thanks to Karim Gemayel)(EJAB-1260) 2010-09-29 11:48:19 +02:00
Badlop c57f726ecb Fix some Dialyzer warnings 2010-09-28 16:06:37 +02:00
Badlop 56b66ab64f Dialyzer fixes. Ensure all_table_hosts/1 returns only a list of binaries 2010-09-28 16:06:35 +02:00
Badlop 403690a498 Only install the guide.html files when it was compiled (EJAB-1311) 2010-09-28 16:06:32 +02:00
Christophe Romain f7dc4df784 Allow use with binary() Host from exmpp (thanks to Karim Gemayel) 2010-09-28 10:06:16 +02:00
Badlop 819dbdbf59 Move the extract_translations code to the tools dir (EJAB-1311) 2010-09-27 13:39:15 +02:00
Badlop 2293bd6855 Move the extauth example script to the tools dir (EJAB-1311) 2010-09-27 13:35:33 +02:00
Badlop caf07d09bf Remove files about obsolete transports (EJAB-1311) 2010-09-27 13:35:08 +02:00
Badlop b2d67df8d0 Remove Marshall T. Rose examples, superseded by supported examples (EJAB-1311) 2010-09-27 13:34:43 +02:00
Badlop 73c992c5af Delete compiled files from git; they are included in source package (EJAB-1311) 2010-09-27 13:31:50 +02:00
Badlop a46f02a136 Fix typo in type 2010-09-22 00:14:47 +02:00
Badlop 62b3b31b8d Allow webadmins to change roster of user (EJAB-72) 2010-09-21 17:05:50 +02:00
Evgeniy Khramtsov d4480c1361 fixes default value for cache_life_time 2010-09-21 04:32:42 +10:00
Christophe Romain 2e75faefae improve type specification 2010-09-20 16:54:37 +02:00
Badlop 9bde1dc9af Add missing needdb, use bare jid to get roster; now group and subs blocking works again (thanks to Andreas Köhler) 2010-09-17 21:06:30 +02:00
Andreas Köhler afac34de88 Discard unmatched INFO messages in ejabberd services.
This patch will stop services terminating with function clause messages,
but doesn't affect the message queue at all.
2010-09-17 19:28:35 +02:00
Christophe Romain 1cbfdce457 remove garbage configuration 2010-09-16 14:52:30 +02:00
Badlop cb953f949f Fix problems reported by Dialyzer 2010-09-15 20:04:35 +02:00
Christophe Romain 52deb16676 apply modification for the exmpp #jid{} record update 2010-09-15 12:16:03 +02:00
Badlop 89a98be605 Display priority, login time, pid and pid info in webadmin (EJAB-1300) 2010-09-13 17:49:55 +02:00
Badlop 813022aec1 Support timezone West of UTC (thanks to Edwin Fine)(EJAB-1301) 2010-09-13 12:07:35 +02:00
Pablo Polvorin 0d5f20cae1 Include roster pack patch from Geoff
Patch was already applied to 2.x branch, but not yet ported to master.
2010-09-10 15:32:19 -03:00
Christophe Romain 4b5b98b465 clean nodeid/nidx variables names (thanks to Karim)(EJAB-1000) 2010-09-10 19:45:28 +02:00
Evgeniy Khramtsov 556892aebf cache lifetime should be converted in microseconds 2010-09-08 02:37:01 +10:00
Evgeniy Khramtsov 7a3aa8f97d Implemented dirty (non-atomic) functions; added copyright notice 2010-08-31 18:07:24 +10:00
Evgeniy Khramtsov 1bd43bbd2d implemented backend-independed key-value cacheing table; applied to mod_caps.erl first 2010-08-30 14:32:48 +10:00
Pablo Polvorin 77d5eabd00 Update rosteritem table definition for mysql (gen_storage)
Previous definition do not work with gen_storage.
gen_storage creates the table when they don't exists, but if
they exists it simple uses that definition.

Note that the column values also had changed in gen_storage,
so instead of "B" for a bidirectional subscription, it must be
"both".  Keep this in mind when loading data into the DB
2010-08-27 14:17:04 -03:00
Badlop 9050aa1de0 Support exmpp's jid record, and require next exmpp release (EXMPP-41) 2010-08-27 15:36:29 +02:00
Evgeniy Khramtsov 445691bab1 fixes ampersand escaping (EJAB-1258) 2010-08-19 20:37:28 +10:00
Andreas Köhler d6722e353f Fix mod_offline:remove_old_messages/1. 2010-08-18 13:22:38 +02:00
Andreas Köhler b2d96d0753 Fix gen_storage:matchrules_transform_conditions/2 for =/=, and, andalso, or and orelse. 2010-08-18 13:22:37 +02:00
Andreas Köhler 7f1759ab0a Fix a ?DEBUG call in ejabberd_auth. 2010-08-18 13:22:34 +02:00
Badlop 3cb128963c Fix ejabberd_auth:get_vh_registered_users/2 (thanks to Andreas Köhler) 2010-08-18 13:22:30 +02:00
Badlop 555a3113a1 Fix EDoc error 2010-08-16 12:02:45 +02:00
Badlop dffb9cdaf9 Fix Dialyzer reports 2010-08-13 17:41:05 +02:00
Badlop 6e65f0694e New API to update host config on the fly (thanks to Juan Pablo Carlino)
Adds ejabberd_hosts:update_host_conf/2 to update a host with a new
configuration on the fly. Typically this is useful to enable / disable
specific modules for a given host without restarting the whole app.
Also fixes a problem with mod_disco, after config refreshing to include
global services if there are not locally available.
2010-08-11 23:31:30 +02:00
Evgeniy Khramtsov bee01cfd1e fixes typo for table copy 2010-08-10 19:44:45 +10:00
Badlop da866ed326 When user joins non-anonymous room, warn also in presence stanza (EJAB-310) 2010-08-07 21:26:22 +02:00
Badlop b0b98e8c63 Update the 'configure' script 2010-08-07 19:54:04 +02:00
Evgeniy Khramtsov 83e17a7c65 Make MD2 autodetected (EJAB-1285) 2010-08-07 22:28:48 +10:00
Badlop 771da0e1d6 Preliminary release notes for 3.0.0 2010-08-06 13:32:29 +02:00
Badlop 75d8d8a43e Fix minor typo in log message 2010-08-06 11:08:19 +02:00
Badlop 80610e62f8 Require the latest exmpp version released 2010-08-06 00:54:25 +02:00
Badlop fa9b8d63f9 Ensure the default virtual host "localhost" is defined and is the first 2010-08-05 22:19:41 +02:00
Badlop d4316558de When an obsolete ODBC module is starting, switch to the normal one 2010-08-05 00:49:58 +02:00
Christophe Romain 690857e0d4 enforce disco features results (thanks to Karim)(EJAB-1033, EJAB-1228, EJAB-1238) 2010-08-04 18:30:22 +02:00
Badlop 73705a3b2e Explain better what's the problem with the option clusterid 2010-08-04 14:03:33 +02:00
Evgeniy Khramtsov 7510a54f81 Loading ASN.1 driver explicitly to avoid races in LDAP (EJAB-1284) 2010-08-04 19:25:18 +10:00
Badlop 8235c9eea1 Change record() to tuple() so Dialyzer can run 2010-08-02 23:47:11 +02:00
Badlop 8cd32f9706 Change syntax of type declarations so Dialyzer accepts them 2010-08-02 23:45:51 +02:00
Badlop b28b9686fe Copy latest release notes from the 2.1.x branch 2010-08-02 17:53:30 +02:00
Badlop 72b9d8b250 Remove unused and useless SVN keywords 2010-08-02 16:03:05 +02:00
Badlop 6abfea6d8d Minor cosmetic change in clusterid description 2010-08-02 15:48:35 +02:00
Badlop d599aba9ca Fix example GSSAPI config 2010-07-31 01:09:47 +02:00
Badlop 02f19c0c1d Only start GSSAPI support when configured, and when esasl is found 2010-07-31 01:08:11 +02:00
Badlop 3181685158 Support parallel extauth script (thanks to Jesse Thompson)(EJAB-1280) 2010-07-30 20:34:01 +02:00
Badlop f93c6c2b35 Copy translations from 2.1.x branch, and update 2010-07-30 16:50:03 +02:00
Badlop a134626849 Fix some English strings 2010-07-30 16:49:31 +02:00
Badlop 31198d6c63 Fix regexp call 2010-07-30 16:49:04 +02:00
Badlop 92dc45ad76 Don't call modules that were obsoleted by GS 2010-07-30 13:22:03 +02:00
Badlop 8a5b08e3f0 New access option in mod_roster to disable changes (EJAB-72) 2010-07-30 13:21:58 +02:00
Badlop 1a368436b4 Use the term 'room' instead of 'chatroom' and 'conference' 2010-07-30 00:06:19 +02:00
Badlop 59a19ca87a Don't offer SASL auth before doing TLS if TLS is required (thanks to Etan Reisner)
Originally reported in
http://yo.jabber.ru/bugzilla/show_bug.cgi?id=251

Implements:
http://tools.ietf.org/html/rfc3920#section-6.2
If Use of TLS (Section 5) needs to be
established before a particular authentication mechanism may be used, the
receiving entity MUST NOT provide that mechanism in the list of available SASL
authentication mechanisms prior to TLS negotiation.
2010-07-29 23:14:03 +02:00
Badlop e653598cd0 Allow mod_caps and shared_roster to start, they don't really need to use GS 2010-07-29 20:35:30 +02:00
Badlop 891c9610e9 Remove support to migrate mod_muc from ejabberd 0.7.5 or older 2010-07-29 20:24:46 +02:00
Badlop 9265c23e1a Don't say v1.2, because that number is never increased and is confusing 2010-07-28 20:00:47 +02:00
Badlop 11130806f9 Return Registered element when account exists (thanks to PioneerMike) 2010-07-28 19:48:06 +02:00
Badlop 0d065dd021 Fix Edoc comments 2010-07-23 13:36:35 +02:00
Badlop f5dc8d2f78 Document GSSAPI (EJAB-831) 2010-07-23 01:23:39 +02:00
Badlop 07e459d577 Various fixes (EJAB-831) 2010-07-23 01:23:37 +02:00
Badlop aa791ad0c4 Support SASL GSSAPI authentication (thanks to Mikael Magnusson)(EJAB-831) 2010-07-23 01:23:35 +02:00
Badlop 17fc992ba9 Recompile the guide and configure 2010-07-23 00:30:52 +02:00
Badlop 115392ff2d Add MH and GS specific options to ejabberd.cfg.example 2010-07-23 00:30:45 +02:00
Badlop b1545d1d7d Document GS in the Guide, undocument the mod_*_odbc 2010-07-23 00:30:43 +02:00
Badlop 9e2d614b41 Update ejabberd version from 3.0.0-prealpha to 3.0.0-alpha-x 2010-07-23 00:30:41 +02:00
Badlop 917c5edfe5 Mark as obsolete the modules that use odbc instead of GS 2010-07-23 00:30:37 +02:00
Badlop 1285bd52c9 Fix ejabberd_odbc code 2010-07-23 00:30:33 +02:00
Badlop 597c1c87d4 Fix ejabberd modules 2010-07-23 00:30:32 +02:00
Badlop 58bed2cbff Fix core files 2010-07-23 00:30:31 +02:00
Badlop 13fad04d14 Fix GS 2010-07-23 00:30:29 +02:00
Badlop eb2ad7e699 Patch modules for GS (thanks to Stephan Maka) 2010-07-23 00:29:40 +02:00
Badlop 511f73812d Patch core for GS (thanks to Stephan Maka) 2010-07-23 00:29:36 +02:00
Badlop a7d9fa7301 New files for GS (thanks to Stephan Maka) 2010-07-23 00:29:34 +02:00
Badlop bb77c39553 Patch ODBC modules for MH (thanks to Alexey Shchepin and Geoff Cant) 2010-07-23 00:29:32 +02:00
Badlop a1a6bd79ac Patch mnesia modules for MH (thanks to Alexey Shchepin and Geoff Cant) 2010-07-23 00:29:30 +02:00
Badlop cdb379a22c Patch core for MH (thanks to Alexey Shchepin and Geoff Cant) 2010-07-23 00:29:28 +02:00
Badlop 9336356efd New files for MH (thanks to Alexey Shchepin and Geoff Cant)
Thanks to:
Alexey Shchepin for planning and developing MH in late 2007
Geoff Cant for improving during 2008 and 2009
Christophe Romain and Badlop for merging into master in 2010
2010-07-23 00:29:26 +02:00
Badlop 8e9888c411 When logging s2s out connection attempt or success, log if TLS is used 2010-07-23 00:27:26 +02:00
Badlop 027418aba5 The command Update now returns meaningful message and exit-status (EJAB-1237) 2010-07-22 16:38:04 +02:00
Christophe Romain f36da63a3a Allow roster change from external component (TECH-1001) 2010-07-22 11:06:51 +02:00
Christophe Romain 5bc9860f5d add ejabberdctl ability to check epmd names (TECH-1121) 2010-07-20 14:05:18 +02:00
Badlop c237570bc2 Describe what a user gets when he hits the registration_timeout limit 2010-07-19 12:13:00 +02:00
Badlop 0dcbe10a22 Only compile etop_tr.erl when running: make debugtools=true 2010-07-19 12:12:30 +02:00
Badlop 581f011b28 Fix warning about unused variable 2010-07-19 12:11:10 +02:00
Christophe Romain fb2c74c4aa add missing hrl 2010-07-16 18:55:58 +02:00
Christophe Romain 8dbd6007ed Add etop command to ejabberdctl 2010-07-16 16:24:55 +02:00
Evgeniy Khramtsov c9faa5bde7 correct handling of SQL boolean types (EJAB-1275) 2010-07-14 21:57:32 +10:00
Christophe Romain de6675a433 Added catches to reset_stream calls to avoid errors during a race condition (thanks to Aleksey Shchepin) 2010-07-13 22:13:38 +02:00
Christophe Romain 81d364a97a Make chat room destroy and create being sync_dirty to limit mnesia overload. (thanks to Mickael Remond) 2010-07-13 22:09:48 +02:00
Christophe Romain 02b7ba50fe Try forcing usage of cache for all MySQL sessions, and add correct timeout on odbc driver query. (thanks to Mickael Remond) 2010-07-13 22:08:16 +02:00
Christophe Romain e64d69350f Add rate limit command to ejabberd_listener. You can now limit the max number of TCP connects per second on a given port. (thanks to Mickael Remond) 2010-07-13 22:07:43 +02:00
Badlop 2b48732de4 Fix my flock change from last friday 2010-07-12 18:53:28 +02:00
Badlop 29e626bf80 Remove ejabberd_debug because p1_prof provides similar and better features 2010-07-12 16:03:47 +02:00
Badlop 2e13a56ca9 Only compile and install p1_prof when: make debugtools=true 2010-07-12 16:03:44 +02:00
Badlop 976baccceb Raise requirement to Erlang/OTP R12B-5 (EJAB-953) 2010-07-12 15:21:31 +02:00
Badlop f8412d7c5d When using OTP R14, use public_key library instead of old ssl (EJAB-953) 2010-07-12 13:58:10 +02:00
Badlop 5a8d99232c Mention missing modules in the overview table 2010-07-11 12:21:57 +02:00
Badlop fe70217703 Some systems delete the lock dir; in such case don't use flock at all 2010-07-09 22:40:32 +02:00
Evgeniy Khramtsov 20f6e4714e Added functions to collect statistics about queues, memory, reductions etc. Several cleanups 2010-07-10 01:37:28 +10:00
Evgeniy Khramtsov b76eba62ea New ejabberd profiler 2010-07-05 13:46:49 +10:00
Badlop 5b6351577a Fix print of command result that contains ~ (thanks to Tsukasa Hamano) 2010-07-03 00:45:46 +02:00
Badlop 894f0abdfa Prevent Dialyzer warnings about case inside macro 2010-07-02 23:40:51 +02:00
Badlop c89944fe12 Don't handle useless case of Affiliation none 2010-07-02 23:40:51 +02:00
Badlop fe1a4908b5 Move deeply nested cases to functions, and fix affiliation changes. 2010-07-02 23:40:51 +02:00
Evgeniy Khramtsov d60ef4c212 Use ets insead of asking supervisor in ejabberd_odbc_sup:get_pids/1 (Thanks to Alexey Shchepin) 2010-07-03 00:35:34 +10:00
Badlop 5161a9d4e8 Show some more room options in the log file 2010-07-02 15:21:05 +02:00
Badlop eb0dc4f4ca Document the mod_muc option captcha_protected 2010-07-02 13:09:11 +02:00
Badlop 6b9a523dc9 Recompile the Guide and Configure 2010-07-01 17:08:17 +02:00
Badlop 3e97054390 Requirement of OpenSSL increased from 0.9.6 to 0.9.8 2010-07-01 17:06:25 +02:00
Badlop 69d10702ee Fix typo in --enable-transient_supervisors 2010-07-01 17:05:24 +02:00
Christophe Romain 455107ff5f fix some dialyzer warnings on pubsub (EJAB-1260) 2010-07-01 11:19:48 +02:00
Badlop 5ca3f221cc Fix privacy check when serving local Last (thanks to Brian Acton)(EJAB-1271) 2010-06-29 11:59:16 +02:00
Badlop 7ffe06c77f Fix binary Host argument 2010-06-28 13:54:43 +02:00
Badlop bdea5d3598 Fix problem when FIREWALL_WINDOW options for erl kernel were used 2010-06-28 13:18:48 +02:00
Badlop a07eb3e023 Fix missing closing right parenthesis in define 2010-06-28 12:23:18 +02:00
Badlop c3ef12debb Inform client that SSL session caching is disabled (thanks to Pawel Chmielowski) 2010-06-25 18:33:59 +02:00
Badlop 739412119e Don't ask for client certificate when using tls (EJAB-1267) 2010-06-25 18:33:56 +02:00
Badlop 90d9ed1ee4 OpenSSL is required, not optional 2010-06-25 16:59:15 +02:00
Badlop 7d96d831c1 Fix Edoc typo 2010-06-25 00:03:38 +02:00
Badlop b2eb9bc512 Fix some binary variables 2010-06-24 00:22:26 +02:00
Badlop 71fc696f81 When account is deleted, delete also member of stored shared rosters. 2010-06-24 00:04:02 +02:00
Evgeniy Khramtsov 234280ddc7 now admins are able to see private rooms in disco (EJAB-1269) 2010-06-23 17:51:05 +10:00
Badlop 7a76cabe26 Varied fixes in mod_muc_room 2010-06-22 00:11:41 +02:00
Badlop a610d8b699 Several fixes about binary in mod_muc_room 2010-06-22 00:11:41 +02:00
Badlop 98a78b7955 Several fixes about binary in mod_muc 2010-06-22 00:11:41 +02:00
Badlop 493d3bc7aa Fix language string 2010-06-22 00:11:41 +02:00
Badlop ac6ae9e8dd Fix xmlcdata binary content 2010-06-22 00:11:41 +02:00
Badlop a6c0a3d59b Fix exmpp parser options 2010-06-22 00:11:41 +02:00
Badlop 0b5bcaf74a Remove some unused cases clauses 2010-06-22 00:11:41 +02:00
Badlop 3ee28ef7cc Throw a meaningful error when the URL can't be parsed 2010-06-22 00:11:41 +02:00
Badlop 3f68689367 Handle when username in shared roster members is undefined 2010-06-22 00:11:41 +02:00
Badlop 6fc578f2ee Use string instead of binary for body content 2010-06-22 00:11:41 +02:00
Badlop cd4c730b9c Fix pattern match 2010-06-22 00:11:41 +02:00
Evgeniy Khramtsov b0b66be747 Added md2/1 support 2010-06-22 02:57:58 +10:00
Evgeniy Khramtsov e04a690303 New OpenSSL functions wrapper: sha224/1, sha256/1, sha384/1, sha512/1 2010-06-22 02:34:27 +10:00
Badlop bc44a3584f Fix detection of push roster item unsubscribed 2010-06-18 21:24:52 +02:00
Badlop 5e986442a2 Remove duplicate function from mod_roster 2010-06-18 21:24:52 +02:00
Badlop 19ad0eb238 Fid mod_roster_odbc binary arguments 2010-06-18 21:24:52 +02:00
Badlop fe4944e031 Provide iq instead of xmlel in roster webadmin changes 2010-06-18 21:24:51 +02:00
Badlop a51df8db6e Fix build of blank JID 2010-06-18 21:24:51 +02:00
Badlop b605295f9d Fix call to exmpp_stanza:error 2010-06-18 21:24:51 +02:00
Badlop dd69d47543 Fix xmlcdata binary content 2010-06-18 21:24:51 +02:00
Badlop 3b7449fb92 Fix result IQ vcard stanza 2010-06-18 21:24:51 +02:00
Badlop 0514ccb047 Remove function clause that is never called 2010-06-18 21:24:51 +02:00
Badlop cab6ee9d86 Fix some exmpp calls 2010-06-18 21:24:51 +02:00
Badlop 63032e1397 Fix xmlcdata type 2010-06-18 21:24:51 +02:00
Badlop 8cef084bd2 New mod_echo option client_version for the educational example 2010-06-18 21:24:51 +02:00
Badlop 6942d0bcc3 Remove in mod_caps handle of unused md5 hash 2010-06-18 21:24:51 +02:00
Badlop 979c2b5a74 Fix binary arguments 2010-06-18 21:24:51 +02:00
Badlop a62a9b6460 Remove unused function, and unused os:type return 2010-06-18 21:24:51 +02:00
Badlop 67da88f0bd Improve ejabberd's broadcast stanzas to satisfy #xmlel type 2010-06-18 21:24:51 +02:00
Badlop 4fd7ec27f5 OTP doc says the Command in the open_port spawn tuple must be string() 2010-06-18 21:24:51 +02:00
Badlop 19a8b79342 Improve handle of inet:gethostbyname return 2010-06-18 21:24:51 +02:00
Badlop be111b6749 More remove support for XEP-0018 (EJAB-810) 2010-06-18 21:24:51 +02:00
Badlop b6711e407e Remove support for the rejected XEP-0018 Invisible Presence (EJAB-810) 2010-06-17 22:43:15 +02:00
Badlop 3bcc60066e Throw error when tls has no_certfile, instead of returning error tuple 2010-06-17 22:39:01 +02:00
Badlop 8d783bae15 Fix roster webadmin display 2010-06-17 15:55:33 +02:00
Badlop e0bdbcf063 Fix exmpp bug in mod_pubsub_odbc 2010-06-17 15:55:06 +02:00
Badlop f32332cdfc Rebuilt the configure script with: autoconf 2010-06-16 16:06:44 +02:00
Peter Lemenkov 399bb31e13 Pass correct version to autoreconf
It seems that AC_INIT macro is wrongly initialized. See this link
for explanation of a particular AC_INIT variables:

http://www.gnu.org/software/autoconf/manual/html_node/Initializing-configure.html

Briefly, AC_INIT macro should be populated with the following data:

AC_INIT (package, version, [bug-report], [tarname], [url])

Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2010-06-16 16:06:16 +02:00
Peter Lemenkov eae5d1b764 Install COPYING file along with other docs
It's a generally good idea to provide file with licensing terms.

Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2010-06-16 16:06:14 +02:00
Peter Lemenkov 1459cb8a56 Install dev.html, and guide.pdf if it exists
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2010-06-16 16:06:11 +02:00
Christophe Romain 53638d094a remove outdated and useless file, use ejabberdctl.template instead 2010-06-16 12:20:46 +02:00
Badlop 8d3fd94d7d Log error when HTTP request has ambiguous Host header (EJAB-1261) 2010-06-16 11:45:13 +02:00
Badlop e27dda3ff1 Fix for Erlang R12, that doesn't support: true andalso ok 2010-06-15 23:01:13 +02:00
Jerome Sautret 1142cdad1b Discard queued requests that are too old (the caller has already got a timeout).
(cherry picked from commit 0e5b930b22)
2010-06-11 16:38:19 +02:00
Christophe Romain 2028698336 Fix bad pattern matching on undefined resource 2010-06-10 18:26:21 +02:00
Badlop 5d1d797330 Explain that 2 LDAP connections are established per vhost 2010-06-10 15:03:30 +02:00
Christophe Romain a67539075f prevent pubsub filtering too much packets 2010-06-10 14:25:46 +02:00
Badlop 75053cf40d Fix to push new contacts to connected users 2010-06-10 13:45:46 +02:00
Badlop cbf06b4785 Fix to not send roster contact from oneself 2010-06-10 13:14:09 +02:00
Badlop cc7ecfb39e Support anonymous accounts in Shared Roster @all@ directive (EJAB-1264)
With this change, logged anonymous accounts are considered to be registered.
2010-06-10 12:22:27 +02:00
Badlop 04943ca469 Fix bug creating anonymous mnesia table 2010-06-10 12:17:31 +02:00
Badlop 89f99c4251 Fix Dialyzer errors in ejabberd_ctl 2010-06-10 00:52:51 +02:00
Badlop 1a6c162371 Fix Dialyzer errors in auth modules 2010-06-10 00:52:38 +02:00
Evgeniy Khramtsov ead2655a62 fixes some badmatches and calls to undefined functions (part of EJAB-1260) 2010-06-09 15:56:33 +10:00
Badlop 526912756b Fix warnings about unused variables 2010-06-08 21:29:53 +02:00
Badlop aa176917fa Fix typo in previous pubsub commit 2010-06-08 21:29:39 +02:00
Badlop be25c5ada7 Fix export to SQL 2010-06-08 21:16:41 +02:00
Badlop d2dee01f7c Don't delete offline messages in mnesia when exporting to PIEFXIS 2010-06-08 18:56:10 +02:00
Badlop b9e79aac6c Fix IQ records 2010-06-08 18:56:09 +02:00
Badlop 2e9f3d3308 Fix call to mod_offline 2010-06-08 18:56:08 +02:00
Badlop 39e18e3738 Fix JID conversion, useful for mod_offline update from 2.1.x to 3.0 2010-06-08 18:56:07 +02:00
Christophe Romain baef586581 fix unexported function calls 2010-06-08 15:57:36 +02:00
Badlop db17504c82 Don't hide the erlang node when using ejabberdctl debug 2010-06-07 22:40:11 +02:00
Badlop 85e59c14d2 New argument --erlargs to pass arguments to erl 2010-06-07 22:40:10 +02:00
Badlop d48b4f2438 Fix typo in update_list command (EJAB-1237) 2010-06-07 15:58:26 +02:00
Badlop 6925f388e7 Fix previous commit (EJAB-1257) 2010-06-07 13:48:20 +02:00
Badlop bc1b4163a2 New optional BOSH connection attribute process-delay (EJAB-1257) 2010-06-07 13:45:05 +02:00
Badlop 4e459b9466 Fix call to the proper API function 2010-06-03 12:29:44 +02:00
Badlop e3e888b8de Fix crash because JID is a 3-tuple 2010-06-03 12:19:52 +02:00
Badlop b1dfb4b5f2 Clarify in the Guide that mssql configuration is similar to odbc 2010-06-02 17:34:40 +02:00
Christophe Romain 2f372261d3 sync last changes in pubsub_odbc patch 2010-06-02 16:47:03 +02:00
Evgeniy Khramtsov 2187bccc38 consistent hashing support. WARNING: update exmpp before running this 2010-06-03 00:01:36 +10:00
Christophe Romain 6c0c30c032 final fix on created node notification (EJAB-1225) 2010-06-02 14:38:04 +02:00
Christophe Romain 166e742b3c can not use unexpected-request with 'cancel' type 2010-05-28 16:27:04 +02:00
Christophe Romain 76447a8810 fix error code when unsubscribing from a non-existent node (needs exmpp from e8f1096) (EJAB-1227) 2010-05-28 14:25:06 +02:00
Christophe Romain 0232f5958f send created node notifications (EJAB-1225) 2010-05-28 13:27:28 +02:00
Christophe Romain e042fdb111 fix cached_item issue with PEP 2010-05-28 13:17:36 +02:00
Christophe Romain 01855b4e32 make last_item_cache feature cluster aware (EJAB-1234) 2010-05-28 11:32:51 +02:00
Badlop 9275a0020e Handle error response from auth modules (thanks to Eric Liang) 2010-05-28 01:36:27 +02:00
Badlop fbc8466c3c Makefile with optional ejabberd_debug.erl compilation (EJAB-1242)
Only compile and install ejabberd_debug.erl when running:
 make ejabberd_debug=true
2010-05-28 00:48:29 +02:00
Badlop bd69e3ad6c Remove useless loop and clean prepare_response (thanks to Christopher tofu Zorn)
1. Remove the silly loop that isnt needed,
   this speeds up all requests by 100 milliseconds.

2. Clean up prepare response function and add two new functions to
   handle out going payloads based of whether its a new session or not.
2010-05-28 00:40:07 +02:00
Badlop 3b963c4f18 Add created_at column also to PostgreSQL schema (thanks to Mathias Ertl)(EJAB-1240) 2010-05-26 16:13:55 +02:00
Badlop 72b2209c3e Mix the commands update_all/0 and update_module/1 into update/1 (EJAB-1237) 2010-05-25 20:02:29 +02:00
Badlop 75c5803431 New ejabberd commands to update modified modules (EJAB-1237) 2010-05-24 13:56:52 +02:00
Badlop d03eacd160 Only log when script errors are found 2010-05-24 13:54:25 +02:00
Christopher tofu Zorn c13df5645e typo on exported function 2010-05-20 20:45:57 +02:00
Christopher tofu Zorn a76d3d46fc expose more functions so developers can implement prebinding methods 2010-05-20 20:32:56 +02:00
Badlop e5535c80da Document mod_multicast, and add module disabled to default config 2010-05-20 00:08:43 +02:00
Badlop 41484213fd Use multicast in C2S presence broadcast (EJAB-267) 2010-05-20 00:03:05 +02:00
Badlop a4cf03dbf0 Use multicast in MUC groupchat messages (EJAB-266) 2010-05-20 00:03:04 +02:00
Badlop 8935da5b5c Service for XEP-0033: Extended Stanza Addressing (EJAB-265) 2010-05-20 00:03:02 +02:00
Badlop 9c12790011 New ejabberd router for multicast packets (EJAB-329) 2010-05-20 00:03:00 +02:00
Christophe Romain bc963e7855 fix EJAB-1233 on pubsub_odbc patch 2010-05-19 11:03:20 +02:00
Christophe Romain 877a864ba3 remove useless binding 2010-05-19 10:43:07 +02:00
Christophe Romain 033bec01e3 prevent orphaned pubsub node (EJAB-1233) 2010-05-19 10:42:49 +02:00
Christophe Romain 5f89f481e4 fix hometree<->flat change 2010-05-18 17:29:09 +02:00
Christophe Romain 95057c1182 finish port to exmpp calls on jid transformation 2010-05-18 15:20:41 +02:00
Christophe Romain f6e4d95c6f PubSub: node_flat becomes default plugin (thanks to Karim Gemayel)(EJAB-1077) 2010-05-17 22:09:01 +02:00
Christophe Romain 4409c49494 fix create_node_permission using binary() instead of string() 2010-05-17 12:52:43 +02:00
Badlop f32b394a96 Fix English typos 2010-05-17 11:56:51 +02:00
Christophe Romain c09df6cf93 fix pubsub->pubsub_odbc patch 2010-05-17 11:11:33 +02:00
Christophe Romain 497911fc5d accept pubsub publish using normal message 2010-05-17 10:31:53 +02:00
Christophe Romain 46ac8f97eb Add pubsub#type node config (EJAB-1083) 2010-05-12 14:51:38 +02:00
Christophe Romain 0964724b2a sync pubsub_odbc with latest code 2010-05-12 13:54:21 +02:00
Christophe Romain ccc684b095 Enforce pubsub#show_values subscription option (EJAB-1096)(thanks to Karim Gemayel) 2010-05-12 13:46:34 +02:00
Christophe Romain 2f075b7b77 Add pubsub#notify_sub node option (EJAB-1230)(thanks to Karim Gemayel) 2010-05-12 12:01:54 +02:00
Christophe Romain e1dd9ed875 fix unsubscribing with SubID (thanks to Karim Gemayel) 2010-05-12 11:47:43 +02:00
Badlop e7d70933ac Show HTTP auth username and IP address in logs, not the password (EJAB-1231) 2010-05-12 10:28:01 +02:00
Badlop 611a9c0136 Fix EDoc errors 2010-05-11 13:15:33 +02:00
Badlop 834ca8a08d Show vCard size in WebAdmin, allow to delete it, allow to view the vCard 2010-05-11 01:22:20 +02:00
Badlop 34bc4da8d8 Fix vcard removal 2010-05-11 01:22:18 +02:00
Badlop 3727e2426d Catch error when auth crashes 2010-05-11 01:22:17 +02:00
Badlop 7aa5e8f435 Don't show HTTP request in logs, because reveals password (EJAB-1231) 2010-05-10 23:23:38 +02:00
Badlop 6129065cfa Show parsing error in debug log message 2010-05-10 22:45:24 +02:00
Badlop 86eebc21b4 More fixes in BOSH, it seems to work now 2010-05-10 22:44:55 +02:00
Badlop 56f5a7846f Fix binary conversion when removing user in mod_pubsub 2010-05-10 17:01:20 +02:00
Badlop bb4dae26da Optionally cache extauth users in mnesia (EJAB-641) 2010-05-10 16:43:39 +02:00
Badlop 2afce7822f Use a standard method to get a random seed (EJAB-1229) 2010-05-10 15:39:20 +02:00
Badlop e249a21f83 Fix warning 2010-05-10 15:10:24 +02:00
Badlop 2331e23f49 New option pam_userinfotype to provide username or JID (EJAB-652) 2010-05-10 15:08:21 +02:00
Badlop 110819525f Partially revert "Fix more HTTP-Bind", add proper fix: c2s works again, BOSH not yet 2010-05-10 13:56:58 +02:00
Evgeniy Khramtsov 3f6579ffbc new option ldap_tls_verify is added (EJAB-1229) 2010-05-10 19:57:40 +10:00
Evgeniy Khramtsov 92ec42565e full support for XEP-0115 v1.5 (EJAB-1223) (EJAB-1189) 2010-05-10 16:00:30 +10:00
Christopher tofu Zorn f84a1c88cf Change max inactivity from 30 to 120 seconds 2010-05-06 20:55:08 +02:00
Christopher tofu Zorn a1205f347f Use dirty_delete when removing the session.
There is no need for a transaction and has less overhead
2010-05-06 20:55:03 +02:00
Badlop 674ee7f5f6 Fix more HTTP-Bind; now works with exmpp bosh_client, but not others yet. 2010-05-05 19:59:57 +02:00
Badlop 4d1dfe8914 Indicate explicitly what nodes are handled by mod_configure 2010-05-04 11:40:35 +02:00
Christophe Romain dc4d72cf77 Let PubSub check the namespace of the published root payload element 2010-05-03 14:35:49 +02:00
Badlop 57ffba34c2 New page Miscelanea Options 2010-05-03 13:59:18 +02:00
Christophe Romain 2f97ef8b81 Enforce pubsub#presence_based_delivery (EJAB-1221) (thanks to Karim Gemayel)
this commit also sync pubsub_odbc back to latest pubsub
2010-04-29 12:54:35 +02:00
Emilio Bustos 4548f2faf0 Fixed Bugs handling Service Discovery to contacts (EJAB-1207) 2010-04-29 00:38:25 -03:00
Badlop f01dd3e942 Fix Edoc comment 2010-04-28 20:15:15 +02:00
Badlop 53a5b602dc New Access rule webadmin_view for read-only (thanks to Oleg Palij)(EJAB-213) 2010-04-27 23:27:24 +02:00
Christophe Romain b49dd8b8c4 fix node path format, must be binary() 2010-04-27 19:08:56 +02:00
Badlop 4c147c5f29 Don't store blocked messages in offline queue (thanks to Brian Acton)(EJAB-1224) 2010-04-27 13:29:05 +02:00
Badlop 9820880cd5 Automatic vcard avatar addition in presence (thanks to Igor Goryachev)(EJAB-208) 2010-04-27 12:33:38 +02:00
Badlop 8713465df1 No need to handle IQ requests other than Get and Set 2010-04-22 20:15:45 +02:00
Badlop cb9b97411b Rename mod_muc_log option spam_prevention to link_nofollow (EJAB-1141) 2010-04-21 18:58:03 +02:00
Badlop 069ad5332d Update WebAdmin logo to ejabberd 3. 2010-04-21 15:50:01 +02:00
Badlop 1d7daab4e8 Don't send error stanza as reply to error stanza (EJAB-930) 2010-04-20 20:31:17 +02:00
Badlop 6cdfec1284 Fix support for registration from C2S connections 2010-04-19 16:08:01 +02:00
Badlop ab77bb5466 Recompile the Guide 2010-04-19 15:20:45 +02:00
Evgeniy Khramtsov c8f5585f3b added notes about LDAP password change 2010-04-19 23:10:22 +10:00
Evgeniy Khramtsov e117ce1b7b allow inband password change (EJAB-199) 2010-04-19 21:05:19 +10:00
Badlop b0d5ac0b33 Minor fixes in listeners options list 2010-04-19 11:57:16 +02:00
Evgeniy Khramtsov 5bb22101e2 LDAP extensible match support (EJAB-722) 2010-04-19 14:14:26 +10:00
Badlop f70ebd6983 Allow definition of local address for outgoing s2s (EJAB-418) 2010-04-15 01:04:40 +02:00
Badlop 5cb10cf9fa Fix outgoing s2s 2010-04-14 21:08:24 +02:00
Badlop 3259c1c2ea Update some HTTP-Bind to work with exmpp; but doesn't work yet. 2010-04-14 16:50:32 +02:00
Badlop 58a4b594db Update calls of old xml_stream and xml, to exmpp. 2010-04-14 16:45:37 +02:00
Badlop 7471d49b5a Fix roster display in WebAdmin 2010-04-14 16:42:29 +02:00
Badlop 67cced15b9 Fix calls to register_feature 2010-04-14 01:08:22 +02:00
Badlop 7fffae5b1a Rename some JEP references to XEP 2010-04-14 01:00:14 +02:00
Badlop bda56552eb Fix management of disco_features and disco_extra_domains 2010-04-14 00:57:56 +02:00
Badlop d2104ba4e1 Reduce verbosity of log when captcha_cmd is checked but not configured. 2010-04-12 13:33:13 +02:00
Pablo Polvorin 3581b137e1 Remove warning for undefined print_state/1 function for p1_fsm processes.
Include a identity function as implementation of print_state/1.
2010-04-09 14:18:44 -03:00
Christophe Romain 44abf1ff28 fix subscriptions, subscribe, and configure options (thanks to Karim Gemayel) 2010-04-08 13:58:47 +02:00
Badlop 7814527e0d Bugfix for starting with a clean caps table (thanks to Karim Gemayel) 2010-04-07 12:50:47 +02:00
Badlop 57d5bc693c Add xml default content type (thanks to Aaron Winborn)(EJAB-14214) 2010-04-06 23:04:28 +02:00
Emilio Bustos b85b63018d Move SQL queries from vcard_odbc to odbc_queries. 2010-03-31 16:33:18 -03:00
Pablo Polvorin fd990cf4d8 Allow customizing the StateData in p1_fsm before error reporting.
A new callback is introduced on the p1_fsm behaviour:

print_error/1

If the module implements this function, it will be invoked
in case of process crash with the current state data *before*
printing the error in the log. The function must return the
desired State to print.

It is used in ejabberd_c2s to prune the presence sets that
can be large. Instead, the state is changed to include only
the # of elements on each set.

Change inspired in comming changes to gen_server on OTP, and
http://github.com/erlyvideo/erlyvideo/commit/b01d15abc3189226dbf824db19db22da35fa33a0#diff-0
2010-03-30 16:44:39 -03:00
Badlop da50d95873 Refactor code to reduce calls to get_affiliation and get_role (thanks to Steam)(EJAB-1038) 2010-03-29 20:49:22 +02:00
Christophe Romain 2f899ba76f purge_offline and get/set affiliation bugfix 2010-03-22 20:27:13 +01:00
Evgeniy Khramtsov d11a715eda - pass jid into feature_check_packet hook;
- bounce messages when closing c2s session;
- implemented treap:to_list/1 and treap:from_list/1
2010-03-17 23:47:13 +09:00
Mickael Remond 6d9094ceca Move HTTP session timeout log from warning level to info. Timeout can be generated when user close the browser for example. 2010-03-14 10:30:01 +01:00
Christophe Romain d50fc6728e improve remove_user (EJAB-1172) 2010-03-11 16:07:56 +01:00
Peter Lemenkov c316bfae25 More compliance with LSB
The init-script shall return 4 in case then user doesn't have sufficient privileges for action.
See http://refspecs.freestandards.org/LSB_3.2.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html

Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2010-03-08 22:41:14 +01:00
Christophe Romain 37a23e69d7 allows PEP to send to bare jid on s2s 2010-03-08 15:35:19 +01:00
Badlop 13412129ec Document mod_sic (EJAB-1205) 2010-03-08 13:59:06 +01:00
Badlop 94257c3e4b Implement XEP-0279: Server IP Check (thanks to Karim Gemayel)(EJAB-1205) 2010-03-08 13:58:53 +01:00
Badlop 4dc48da638 Replace concat_binary supported until R14 with list_to_binary supported since R9 2010-03-08 12:53:37 +01:00
Badlop 002104c62e Catch errors when exporting to PIEFXIS file (EJAB-1178) 2010-03-08 11:16:33 +01:00
Badlop 3844883321 Recompile the Guide 2010-03-08 11:16:05 +01:00
Evgeniy Khramtsov fb64d79379 ldap_dn_filter option is documented; now fetching only needed attributes in LDAP search requests (EJAB-1204) 2010-03-08 16:51:24 +09:00
Evgeniy Khramtsov 9d2fd3e52c now using "%u" pattern as default for ldap_uids (EJAB-1203) 2010-03-08 14:08:22 +09:00
Christophe Romain 7d497615a1 add extended stanza addressing 'replyto' on PEP (EJAB-1198) (thanks karim) 2010-03-05 18:33:12 +01:00
Christophe Romain fe40651b0d add pubsub#purge_offline (EJAB-1186) (thanks karim) 2010-03-05 16:09:06 +01:00
Christophe Romain 3c36cd64e3 fix pubsub#title option (EJAB-1190) (thanks karim) 2010-03-05 15:45:31 +01:00
Christophe Romain 7d97830ad7 mod_caps optimizations (thanks evgeniy) 2010-03-05 15:38:44 +01:00
Denis Kurochkin a1fe809197 MSSQL support was broken (EJAB-1201) 2010-03-05 14:46:17 +01:00
Christophe Romain 236423d058 fix: subscribe, unsubscribe, last published item (thanks karim) 2010-03-05 13:50:51 +01:00
Evgeniy Khramtsov c8c7169465 improved s2s connections clean up (EJAB-1202) 2010-03-04 12:43:43 +09:00
Badlop 64f8cf8a9e Clarify in Displayed Groups label that it expects IDs. 2010-03-01 11:44:02 +01:00
Badlop c99de764bc Add quotes in documentation of some erl arguments (thanks to Vincent Courcelle)(EJAB-1191) 2010-02-25 00:06:13 +01:00
Badlop c9463e3308 Fix resending authorization problem 2010-02-24 13:14:53 +01:00
Badlop 87beae3298 Run user_receive_packet also when sending offline messages to client (thanks to Brian Acton)(EJAB-1193) 2010-02-22 22:56:57 +01:00
Badlop 3e6acdfb4a Fix typos in example config comments (thanks to Florian Zumbiehl)(EJAB-1192) 2010-02-22 13:40:19 +01:00
Badlop ebc82f2968 Use alternative of file:read_line/1 to not require R13B02 2010-02-20 19:31:57 +01:00
Evgeniy Khramtsov 9890cc89b6 get rid of queue:filter/2 to keep compatibility with older Erlang versions 2010-02-20 20:14:34 +09:00
Evgeniy Khramtsov 62ad40b1e4 now using mnesia:async_dirty when cleaning table from failed node 2010-02-19 16:41:13 +09:00
Badlop ca1ac76108 Reduce verbosity of HTTP Binding log messages (thanks to Alexey Shchepin) 2010-02-19 00:08:04 +01:00
Badlop ceb377621e Recompile guide.html 2010-02-18 22:25:36 +01:00
ekhramtsov d70e92d781 improved explanation of "max_fsm_queue" option; included this option in ejabberd.cfg.example 2010-02-18 15:42:59 +09:00
ekhramtsov c0a0bae91e option "access_from" is now documented (EJAB-1187) 2010-02-18 15:00:40 +09:00
ekhramtsov e7c93ae68d new option "hostname" is added (thanks to Stefan Hepp) (EJAB-838) 2010-02-17 23:58:53 +09:00
Badlop 55986739c9 Update namespaces to match exmpp_nss.hrl (thanks to Karim Gemayel)(EJAB-1179)
This requires a recent exmpp from Git. Once released, it'll require exmpp 0.9.3
2010-02-16 17:33:53 +01:00
Badlop 8539a7d7ea Close also legacy sessions that were half connected (thanks to Evgeniy Khramtsov)(EJAB-1165) 2010-02-16 12:44:43 +01:00
Badlop 23d008cd79 Remove references to the old SVN repository. 2010-02-16 12:00:05 +01:00
Badlop 5a82e3ac70 Rewrite mnesia counter functions to use dirty_update_counter (EJAB-1177)
(thanks to Juan Pablo Carlino and Alexey Shchepin)
2010-02-15 23:38:08 +01:00
Badlop 4117a5e856 New command to set master Mnesia node 2010-02-15 23:25:02 +01:00
Badlop 6cf078ae83 Shared roster gets contact nickname from vcard, when available (EJAB-114) 2010-02-15 22:47:38 +01:00
Badlop 27be3b400e Cross-domain HTTP-Bind support (thanks to Jack Moffitt)(EJAB-1168) 2010-02-15 22:39:32 +01:00
Badlop fa4ebab036 Fix cluster race condition in route read (thanks to Alexey Shchepin) 2010-02-15 18:37:42 +01:00
Badlop df2878739c Improve TTY code to work on more operating systems (thanks to Jan Koum) 2010-02-12 22:11:22 +01:00
Badlop cab98b3fd5 Added support for Jot in ctl and TTY in debug (thanks to Jan Koum) 2010-02-12 20:52:31 +01:00
Badlop 60ffcd78f1 Minor fixes in the new ejabberdctl flock code 2010-02-12 20:25:20 +01:00
Martin Langhoff 6557136426 ejabberdctl: support concurrent connections with bound conn names
If flock is available, ejabberdctl will use it to grab one
of a bound number of connection names. This allows concurrent
connections while using a bound number of atoms.

Using PID, timestamps or random strings for transient connection IDs
(which would avoid the need for flock) uses an unbound number of atoms.
This can effectively DoS servers, as these connection names are
not garbage collected.
2010-02-12 20:24:58 +01:00
Badlop 50b0ef4db9 Replace mention of ejabberd SVN with Git. 2010-02-11 13:24:39 +01:00
Badlop 18074abfdd Remove unnecessary section about Snow Leopard with Erlang R13B 2010-02-11 13:23:41 +01:00
Badlop d429ba812c Fix bashism in 'ejabberdctl started' 2010-02-11 11:04:15 +01:00
Badlop 0d09816c39 Allow a request_handler to serve a file in root of HTTP 2010-02-10 20:17:37 +01:00
Badlop 4caf4da9a6 Add Edoc comment about run_fold/4 function 2010-02-08 21:27:10 +01:00
Badlop 961640bd2c Fix to get shared roster displayed when user logins 2010-02-08 21:14:40 +01:00
Badlop 5d92dce21d Update spec of node_hometree get_states (thanks to Magnus Henoch) 2010-02-08 17:54:11 +01:00
Badlop 50f5356c89 Another migration of regexp call to re (EJAB-921) 2010-02-08 13:42:05 +01:00
Badlop 3156cdf10e Fix character in README file, in master, too. 2010-02-08 12:38:52 +01:00
Badlop 7a5ec47b58 Copied release notes from previous 2.1.* releases
SVN Revision: 2962
2010-02-05 13:34:09 +01:00
Pablo Polvorin b22e8b706a Add new debuging hook to the http receiving process.
The new hook is called http_request_debug, and receive the  LocalPath and Request as parameter.

SVN Revision: 2961
2010-02-05 13:34:09 +01:00
Pablo Polvorin 0ddf0d10a5 Hibernate http-bind process after handling a request.
When using BOSH, this reduces memory consuption of the http-bind process, with negligible CPU impact.

SVN Revision: 2960
2010-02-05 13:34:09 +01:00
Pablo Polvorin 0ed8ae5975 Bug Fix: The value of max # of erlang process specified in ejabberdctl.cfg was not used.
It was called PROCESSES in the .cfg file,  and ERL_PROCESSES in the script.  The latter is the correct,  to be coherent with ERL_MAX_PORTS and ERL_MAX_ETS_TABLES.

SVN Revision: 2959
2010-02-05 13:34:09 +01:00
Evgeniy Khramtsov 1283a59465 Added new acl for mod_register: access_from. This acl is applied if existing account tries to register a new account (either via s2s or c2s). The default action is to deny such operations.
SVN Revision: 2958
2010-02-03 12:20:04 +00:00
Evgeniy Khramtsov ad1aec6cd1 avoid resending <stream:error> stanzas on terminate (EJAB-1180)
SVN Revision: 2957
2010-02-03 12:10:08 +00:00
Evgeniy Khramtsov 7d7177a6af changed Reason to shutdown when stopping destroyed MUC room
SVN Revision: 2956
2010-02-03 11:50:37 +00:00
Badlop f5e6c9a2a3 Fix bug handling Reason in gen_fsm:terminate
SVN Revision: 2951
2010-02-02 11:15:44 +00:00
Evgeniy Khramtsov 7cd5a04087 improved SQL reconnect behaviour
SVN Revision: 2948
2010-01-31 11:48:21 +00:00
Christophe Romain bfff7d721d remove useless empty dir
SVN Revision: 2946
2010-01-28 16:04:58 +00:00
Evgeniy Khramtsov aaff63da58 regenerated guide.html
SVN Revision: 2944
2010-01-28 15:37:02 +00:00
Evgeniy Khramtsov 95a3cc88cd fixes badly formed define
SVN Revision: 2943
2010-01-28 15:34:00 +00:00
Evgeniy Khramtsov 70c1a3f60b ejabberd_c2s option "max_fsm_queue" is now documented
SVN Revision: 2942
2010-01-28 14:01:31 +00:00
Evgeniy Khramtsov c24af4ca63 new ejabberd_c2s option support: max_fsm_queue
SVN Revision: 2940
2010-01-28 13:46:44 +00:00
Evgeniy Khramtsov e31b2582b6 now using p1_fsm behaviour in c2s FSM (EJAB-1173)
SVN Revision: 2937
2010-01-28 13:11:14 +00:00
Badlop 479e5cb107 Fix disco of bare JID
SVN Revision: 2935
2010-01-27 18:54:03 +00:00
Badlop 887a65aa18 exmpp in pubsub doc and retrocompatibility comments (thanks to Karim Gemayel)
SVN Revision: 2934
2010-01-27 18:53:56 +00:00
Badlop e4a6d20328 exmpp fixes in captcha (thanks to Karim Gemayel)
SVN Revision: 2933
2010-01-27 18:53:47 +00:00
Badlop f5e1479afe exmpp fixes in receiver (thanks to Karim Gemayel)
SVN Revision: 2932
2010-01-27 18:53:43 +00:00
Badlop a10493976e exmpp fixes in mod_muc (thanks to Karim Gemayel)
SVN Revision: 2931
2010-01-27 18:53:38 +00:00
Badlop 4caac4a322 exmpp fixes in c2s, piefxis and mod_vcard_ldap (thanks to Karim Gemayel)
SVN Revision: 2930
2010-01-27 18:53:33 +00:00
Badlop e98df7acb1 exmpp fixes in http_bind (thanks to Karim Gemayel)
SVN Revision: 2929
2010-01-27 18:53:27 +00:00
Mickaël Rémond f20d2bb2ff Fix typo in doc
SVN Revision: 2927
2010-01-26 13:14:19 +00:00
Badlop a5e4f34dbb Fix documentation installation, no need for executable permission (thanks to Peter)(EJAB-1170)
SVN Revision: 2923
2010-01-25 18:27:24 +00:00
Badlop 1c9760f6d2 Fix typo in EJABBERD_BIN_PATH (thanks to Martin Langhoff)(EJAB-891)
SVN Revision: 2922
2010-01-25 18:24:59 +00:00
Badlop 2b1ea7d85b Ignore in SVN also epam binary, and Makefile of pam and odbc subdirectories.
SVN Revision: 2921
2010-01-22 18:55:39 +00:00
Badlop 1677603e59 Ignore in SVN the file stun/Makefile
SVN Revision: 2920
2010-01-22 14:22:50 +00:00
Badlop a95286d511 Recompile the configure script and the Guide.
SVN Revision: 2919
2010-01-22 11:30:31 +00:00
Badlop 6e18e292f3 Degrade trunk to prealpha, and show a warning in configure script.
SVN Revision: 2918
2010-01-22 11:27:32 +00:00
Badlop 114dd4d9e7 Support in ejabberdctl help command names with old - characters.
SVN Revision: 2917
2010-01-20 10:32:56 +00:00
Badlop 0495112aab Close sessions that were half connected (thanks to Alexey Shchepin)(EJAB-1165)
SVN Revision: 2912
2010-01-17 19:29:35 +00:00
Badlop f3483529a7 Fix some moved URLs in the Guide
SVN Revision: 2910
2010-01-16 14:35:23 +00:00
Badlop ffc4f3dc48 Document the option route_subdomains in the Guide (EJAB-1164)
SVN Revision: 2909
2010-01-16 14:35:19 +00:00
Badlop a9fba750fa Improve functions calls when closing client connection.
SVN Revision: 2905
2010-01-15 12:02:15 +00:00
Christophe Romain 13220d44f4 improve delete_subscriptions code
SVN Revision: 2903
2010-01-14 12:56:40 +00:00
Christophe Romain 0c9e0168d5 fix binary conversion of ServerHost in presence/2
SVN Revision: 2901
2010-01-13 14:53:05 +00:00
Christophe Romain db4fe25274 add send_loop robustness
SVN Revision: 2900
2010-01-13 10:25:06 +00:00
Badlop e948aafeca If big offline message queue, show only subset on WebAdmin (EJAB-1095)
SVN Revision: 2898
2010-01-13 00:00:34 +00:00
Badlop 4639c0faf0 Fix explanation of access_max_user_messages.
SVN Revision: 2897
2010-01-13 00:00:11 +00:00
Badlop 82cd0adb79 Check for Effective GID EGID in ejabberdctl (thanks to Rustam Aliyev)(EJAB-1160)
SVN Revision: 2894
2010-01-12 18:13:30 +00:00
Badlop 1bcd481fdc Update year of ProcessOne copyright from 2009 to 2010 (EJAB-1159)
SVN Revision: 2892
2010-01-12 16:15:16 +00:00
Badlop 768ea20a3a Require exmpp 0.9.2
SVN Revision: 2890
2010-01-12 15:55:31 +00:00
Christophe Romain bb1ab19997 avoid calling gen_server on internal events (EJAB-1156)
SVN Revision: 2887
2010-01-12 15:14:57 +00:00
Christophe Romain dd159242e3 allow unsubscribe with 'all' SubId, as mod_pubsub already does
SVN Revision: 2885
2010-01-12 14:42:23 +00:00
Christophe Romain f8886ee36c fix NodeName issue from r2880 (thanks to Karim Gemayel)
SVN Revision: 2883
2010-01-12 13:30:49 +00:00
Christophe Romain 67af2908f9 fix headers (EJAB-1091), (EJAB-1092), (EJAB-1093) (thanks to Karim Gemayel)
SVN Revision: 2881
2010-01-12 12:34:02 +00:00
Badlop 9df6e1fe0a Support in user list page of WebAdmin when mod_offline is disabled (EJAB-377)
SVN Revision: 2878
2010-01-12 12:06:43 +00:00
Badlop a658348ac1 Show and throw error when captcha_cmd is required but not configured.
SVN Revision: 2875
2010-01-11 22:22:04 +00:00
Badlop 75ca3d8975 Minor case code simplification.
SVN Revision: 2873
2010-01-09 18:39:17 +00:00
Mickaël Rémond b431a9099e jlib:make_jid/3 does not exist anymore. I think I replaced it correctly by exmpp_jid:make/3
SVN Revision: 2872
2010-01-09 16:44:33 +00:00
Mickaël Rémond 7ed6614ad4 Added a comment to improve code as suggested by Dialyzer.
SVN Revision: 2871
2010-01-09 16:38:07 +00:00
Mickaël Rémond 4fba4db32f Match Erlang typing documentation, to remove dialyzer warning. Code was working fine however.
SVN Revision: 2870
2010-01-09 16:31:45 +00:00
Mickaël Rémond a0554183c5 Attempt to fix dialyzer warning: adhoc.erl:51: Guard test XData::'false' | #xmlel{ns::'jabber:x:data',declared_ns::[{_,_}],attrs::[{_,_,_,_}],children::'undefined' | [{_,_} | {_,_,_,_,_,_}]} =:= 'true' can never succeed
SVN Revision: 2869
2010-01-09 16:18:59 +00:00
Mickaël Rémond b1ad7ad0ba Fix typo in comment.
SVN Revision: 2868
2010-01-09 15:19:48 +00:00
Mickaël Rémond 0537eea929 Small refactoring
SVN Revision: 2867
2010-01-09 15:15:46 +00:00
Badlop cfc9089e51 An AccessCommand with Access 'all', don't require auth to execute it.
SVN Revision: 2866
2010-01-09 00:48:03 +00:00
Badlop bb926f8f87 Remove doc/api directory because its content is now in doc/devdoc.
SVN Revision: 2864
2010-01-07 20:13:03 +00:00
Badlop c2f242b4a6 Fix so script runs correctly when invoked by root (EJAB-1152)
SVN Revision: 2863
2010-01-05 20:31:19 +00:00
Badlop 3f1c8f98ed Show the last activity time in the user page.
SVN Revision: 2861
2010-01-04 20:39:01 +00:00
Badlop 7a3ce2e81a Command to stop ejabberd informing users, with grace period, and kindly (EJAB-1112)
SVN Revision: 2860
2010-01-04 20:35:47 +00:00
Badlop 8c0cc95a55 When ejabberd stops, send stream close to clients (thanks to Alexey Shchepin)(EJAB-1112)
SVN Revision: 2859
2010-01-04 20:32:44 +00:00
Badlop 38dfef923c Improve parsing of ejabberd_sm:get_user_info result.
SVN Revision: 2858
2010-01-04 19:03:36 +00:00
Christophe Romain 89bceb959a add explicit comment on last published items configuration (EJAB-1130)
SVN Revision: 2856
2010-01-04 11:50:08 +00:00
Badlop 8deb2b57af Improve log message when showing lines of config file.
SVN Revision: 2851
2009-12-30 01:39:02 +00:00
Badlop 60915a7f21 Kick occupants with reason when room is stopped due to MUC shutdown (EJAB-1149)
SVN Revision: 2849
2009-12-30 01:29:02 +00:00
Badlop 69869f0446 Fix warning about unused variable
SVN Revision: 2847
2009-12-29 23:13:15 +00:00
Badlop 1eb2b1f047 If problem in config file starting ejabberd: display config lines and stop node (EJAB-1148)
SVN Revision: 2845
2009-12-29 22:49:16 +00:00
Badlop a89b400c04 Add +export_all to EFLAGS if: make debug=true (thanks to Marcin Owsiany)(EJAB-1134)
SVN Revision: 2843
2009-12-29 19:15:59 +00:00
Badlop 6f3aeead07 Support also SASL PLAIN auth messages described in RFC4616 (EJAB-1132)
SVN Revision: 2841
2009-12-29 18:45:02 +00:00
Badlop 3da20486c1 Disable code of recent commit because some clients can't handle it (EJAB-1058)
SVN Revision: 2840
2009-12-29 18:44:48 +00:00
Badlop d911cd1124 Write in room log when a room is created, destroyed, started, stopped (EJAB-1144)
SVN Revision: 2837
2009-12-29 14:44:12 +00:00
Badlop a7bd529dac Send features after negotiating binding and session (EJAB-1058)
SVN Revision: 2835
2009-12-28 20:10:18 +00:00
Badlop 857c87499a Fix bug of unbound variable Attrs in the previous commit.
SVN Revision: 2833
2009-12-28 18:47:14 +00:00
Badlop 381dff1afc Provide more detailed log message when s2s stream start fails.
SVN Revision: 2832
2009-12-28 15:31:18 +00:00
Badlop 378a6b2ff2 Better use install_fallback when importing a Mnesia backup file.
SVN Revision: 2830
2009-12-28 12:44:07 +00:00
Badlop 5b782ad5a1 Support for arguments in ejabberdctl that are empty strings.
SVN Revision: 2828
2009-12-28 11:46:22 +00:00
Badlop 93ed18c2e2 Add explanation about global Access precendence over vhost Access (EJAB-803)
SVN Revision: 2826
2009-12-23 16:09:47 +00:00
Badlop 95e96cc346 Fix error message when register is forbidden by ACL (EJAB-803)
SVN Revision: 2825
2009-12-23 16:09:33 +00:00
Badlop 0e2cd7a8d0 Clarify that 'tls' option is still useful in ejabberd_http for HTTPS.
SVN Revision: 2820
2009-12-23 09:05:02 +00:00
Badlop 332b474a9e Remove the old note about LDAP lack of encryption.
SVN Revision: 2818
2009-12-21 16:11:18 +00:00
Badlop 7434234c27 pep_mapping not working due to Node type mismatch (EJAB-1135)
SVN Revision: 2816
2009-12-21 15:20:27 +00:00
Badlop 848e72bcab Fix EDoc comment
SVN Revision: 2813
2009-12-21 14:31:10 +00:00
Badlop eb26edf5f5 Fix get_group_opt to return Default value in case of Mnesia error.
SVN Revision: 2812
2009-12-19 00:19:26 +00:00
Badlop 440299656f Print command's reply and newline only when there's something to print.
SVN Revision: 2807
2009-12-11 20:08:06 +00:00
Badlop 4ac69edfe7 Added to ejabberdctl an experimental variable EJABBERD_BYPASS_WARNINGS
SVN Revision: 2805
2009-12-11 19:43:57 +00:00
Badlop 9ccdcfc849 Add support for serving a Unique Room Name (thanks to Pablo Polvorin)(EJAB-1121)
SVN Revision: 2803
2009-12-11 12:32:40 +00:00
Badlop 514d5aab14 Show Last Activity menu item in Webadmin only if vhost has mod_last (EJAB-1031)
SVN Revision: 2801
2009-12-09 17:48:03 +00:00
Badlop 2a09bdad13 Call in WebAdmin the proper mod_last backend module (EJAB-1031)
SVN Revision: 2800
2009-12-09 17:47:50 +00:00
Badlop dfa966a576 Fix erl -setcookie argument in cluster setup (thanks to Jan Koum)
SVN Revision: 2797
2009-12-09 10:09:57 +00:00
Pablo Polvorin 573ff2564b Remove usage of #jid record introduced in 2787.
Replace explicit references to #jid with exmpp_jid API calls.

SVN Revision: 2794
2009-12-08 18:59:00 +00:00
Badlop 929022bc0f Apply a forgotten part of the original patch (EJAB-1119)
SVN Revision: 2793
2009-12-08 17:33:30 +00:00
Badlop 21a36819b0 Fix memory and port leak when TLS is enabled in HTTP (thanks to Brian Cully)(EJAB-1119)
SVN Revision: 2791
2009-12-07 17:34:52 +00:00
Badlop efd99f5b28 Add notices about MIT license and copyright to escobar_hiliter.erl
SVN Revision: 2788
2009-12-07 15:50:08 +00:00
Christophe Romain 913684e5a5 prevent sending duplicated last items if several resources online (EJAB-1116)
SVN Revision: 2787
2009-12-06 23:21:03 +00:00
Badlop 40e06b55c0 Typo in mod_pubsub_odbc breaks Service Discovery and more (EJAB-1115)
SVN Revision: 2785
2009-12-04 18:36:07 +00:00
Badlop 182f4b008b Call ejabberd_router:route/3 instead of sending a message (EJAB-1114)
SVN Revision: 2783
2009-12-04 16:32:20 +00:00
Badlop c3df4f3eb0 Small relax the limitation in the mod_pubsub_odbc host option.
SVN Revision: 2780
2009-12-04 16:07:43 +00:00
Badlop 2c1b8b0930 Merge from 2.1.x 2498: added mod_pubsub_odbc documentation
SVN Revision: 2779
2009-12-03 22:58:49 +00:00
Badlop 3cca748bd5 Explain limitation in the mod_pubsub_odbc host option.
SVN Revision: 2778
2009-12-03 22:58:30 +00:00
Badlop 2a05ca5f2b Use os:getenv to get HOME; if variable is undefined use default values.
SVN Revision: 2772
2009-12-03 15:58:19 +00:00
Badlop 3173d9167f Forward IQ vCard queries of room occupants to bare JID, not full (EJAB-1045)
SVN Revision: 2770
2009-12-01 20:02:16 +00:00
Badlop f7b5afec51 Don't handle internally an IQ vCard if destination is full JID (EJAB-1045)
SVN Revision: 2769
2009-12-01 20:02:00 +00:00
Badlop bc355eebaa Fix call to get_module_proc with binary.
SVN Revision: 2765
2009-11-30 13:08:37 +00:00
Badlop 78f9586839 Fix call to hook management in mod_caps start/stop
SVN Revision: 2764
2009-11-30 12:55:35 +00:00
Badlop 040892d1a2 Remove all references to unused library: expat (EJAB-1111)
SVN Revision: 2763
2009-11-30 12:32:14 +00:00
Badlop 71cd4917d8 Move get_group_name outside the loop (thanks to mikekaganski)
SVN Revision: 2761
2009-11-26 14:45:39 +00:00
Badlop b989297725 Fix problem of authentication when using plain from SVN r2575 (EJAB-936)
SVN Revision: 2759
2009-11-24 21:40:50 +00:00
Badlop cf6d842d45 Fix warning
SVN Revision: 2758
2009-11-24 15:22:06 +00:00
Badlop 733e84a4a8 Fix exmpp_stanza:get_sender return value.
SVN Revision: 2757
2009-11-24 11:56:26 +00:00
Badlop 9ac9a84ca7 Fix explanation of option content_types. Reorder options.
SVN Revision: 2756
2009-11-23 20:28:53 +00:00
Badlop 4f369d048d Generate main XML file also when exporting only a vhost (EJAB-1098)
SVN Revision: 2754
2009-11-23 18:35:11 +00:00
Badlop c1a7e30f12 Show informative webpage when browsing the HTTP-Poll page (EJAB-1106)
SVN Revision: 2752
2009-11-23 15:22:45 +00:00
Badlop 4dcfde7737 Change captcha.sh to not depend on bash (thanks to Konstantin Khomoutov)(EJAB-1105)
SVN Revision: 2750
2009-11-23 12:43:56 +00:00
Badlop 0838514c27 Option to define custom HTTP headers in mod_http_fileserver (EJAB-612)
SVN Revision: 2748
2009-11-23 12:13:26 +00:00
Badlop 29f3ef4716 Explain that the example captcha.sh requires Bash because uses RANDOM feature.
SVN Revision: 2746
2009-11-17 15:49:54 +00:00
Badlop a8e5437271 Include IP address, time and module in IBR admin message (thanks to Tsukasa Hamano)
SVN Revision: 2743
2009-11-17 11:14:00 +00:00
Badlop a363d988a7 The default value of option ldap_filter is: undefined.
SVN Revision: 2742
2009-11-13 20:17:54 +00:00
Badlop e1968b6b52 Copied Release Notes from 2.1.0 tag
SVN Revision: 2740
2009-11-13 20:07:03 +00:00
Evgeniy Khramtsov 99a6f12026 fixes allow_host/2 on subdomains. added hook s2s_allow_host: the hook should return deny or allow
SVN Revision: 2739
2009-11-13 16:22:54 +00:00
Badlop eca650efac Fix bug that forgot listener options when using R12 or older.
SVN Revision: 2736
2009-11-06 18:33:37 +00:00
Christophe Romain bde4b7b057 minor bug fixes related to the use/conversion of/to exmpp (thanks to Karim Gemayel)
SVN Revision: 2733
2009-11-06 14:36:41 +00:00
Christophe Romain a1e9b55ead minor bug fixes related to the use/conversion of/to exmpp (thanks to Karim Gemayel)
SVN Revision: 2732
2009-11-06 14:34:23 +00:00
Christophe Romain 1c4cc57e3f fix root node deletion match
SVN Revision: 2730
2009-11-05 17:36:54 +00:00
Badlop 26cd3a78d2 Fix ProcessOne name in comments.
SVN Revision: 2728
2009-11-04 20:19:38 +00:00
Badlop 3ed3c94a15 Extend explanation of ldap_encrypt tls (thanks to Konstantin Khomoutov)
SVN Revision: 2727
2009-11-04 20:18:23 +00:00
Badlop ff338a0a62 Fix disco on root node, add commands to disco (thanks to Brian Cully)(EJAB-1094)
SVN Revision: 2726
2009-11-04 20:17:08 +00:00
Badlop 5138a9709e Send authorization messages outside of get-pending transaction (thanks to Brian Cully)(EJAB-1090)
SVN Revision: 2725
2009-11-04 20:16:05 +00:00
Badlop ae93cf2c28 Send authorization messages outside of get-pending transaction (thanks to Brian Cully)(EJAB-1090)
SVN Revision: 2720
2009-11-04 17:40:39 +00:00
Badlop 1c2d639179 Fix small typo (thanks to MiCHi)
SVN Revision: 2716
2009-10-29 12:41:51 +00:00
Christophe Romain 2078f9ae95 typo fix on mod_pubsub and improve ejabberd_sm:get_session_pid api
SVN Revision: 2715
2009-10-27 14:40:01 +00:00
Christophe Romain 1fea1e3f4e minor bugfix, thanks to brian Cully (EJAB-1089)
SVN Revision: 2714
2009-10-27 14:30:00 +00:00
Christophe Romain b2bd51d3e3 fix disco bugs, thanks to Brian Cully (EJAB-1088)
SVN Revision: 2712
2009-10-27 14:24:33 +00:00
Badlop 80a7f5123d Update ejabberd-p1 logo
SVN Revision: 2709
2009-10-26 18:30:53 +00:00
Badlop 8746175f1d Better detection of ejabberd modules. Support down to Graphviz 2.8. Fix APP colours.
SVN Revision: 2708
2009-10-26 18:30:38 +00:00
Badlop 236d8fa254 Update overview.edoc
SVN Revision: 2706
2009-10-23 15:14:39 +00:00
Badlop 3872907f38 Fix EDoc errors
SVN Revision: 2705
2009-10-23 15:14:25 +00:00
Badlop 98f79f0c47 Add devdoc support to Makefiles
SVN Revision: 2704
2009-10-23 15:14:08 +00:00
Badlop 795992fb30 Update stylesheet
SVN Revision: 2703
2009-10-23 15:13:48 +00:00
Badlop 96504ffd88 Add images for ejabberd devdoc.
SVN Revision: 2702
2009-10-23 15:13:28 +00:00
Badlop 5e7b217d6c Add funrelg: draw a function relation graph from source code using Graphviz.
SVN Revision: 2701
2009-10-23 15:13:11 +00:00
Badlop f07513c74b Add escobar_run, a small frontend to call escobar_hilite.
SVN Revision: 2700
2009-10-23 15:12:48 +00:00
Badlop 22fffb32ca Customize escobar_hilite.erl for ejabberd purposes.
SVN Revision: 2699
2009-10-23 15:12:32 +00:00
Badlop abcb3f22a8 Add escobar_hilite.erl and escobar.css.
SVN Revision: 2698
2009-10-23 15:12:16 +00:00
Badlop f7a5689c45 Move overview.edoc to src/ dir.
SVN Revision: 2697
2009-10-23 15:12:01 +00:00
Badlop bebc5a137a Rename directory doc/api to doc/devdoc
SVN Revision: 2696
2009-10-23 15:11:43 +00:00
Badlop 5625f7d984 Fix mistake that disallowed s2s_out connections when using Erlang R12 or older.
SVN Revision: 2695
2009-10-22 14:44:00 +00:00
Badlop c889491e2f The road-to-exmpp branch now becomes trunk.
SVN Revision: 2693
2009-10-21 12:58:55 +00:00
Christophe Romain cd09381efd update pubsub patch
SVN Revision: 2691
2009-10-21 08:31:51 +00:00
Pablo Polvorin 306cff729c Merge with trunk #2687 (EJAB-667) (untested)
SVN Revision: 2690
2009-10-20 22:09:43 +00:00
Badlop 4083267cc9 Mention the change in nodename slash separation in release notes.
SVN Revision: 2689
2009-10-20 15:39:57 +00:00
Badlop 12573ed8d2 Body tag not properly closed in HTTP-Bind (thanks to Janusz Dziemidowicz)(EJAB-1075)
SVN Revision: 2686
2009-10-20 09:56:51 +00:00
Badlop 6b4651fad6 In default config, only local accounts can create rooms and pubsub nodes.
SVN Revision: 2684
2009-10-19 17:05:13 +00:00
Badlop 0095f4fbf9 Provide send_timeout_close option in TCP only in R13B or higher (EJAB-926)
SVN Revision: 2682
2009-10-19 14:53:39 +00:00
Badlop 372658d299 Merged from trunk SVN r2671:
Support gen_tcp send timeout: Close the connection if the other end has disconnected ungracefully or cannot keep up with the rate at which we are sending data (EJAB-926)

SVN Revision: 2681
2009-10-19 14:53:21 +00:00
Badlop 227514c20c Support ejabberd_listener option 'backlog' to increase TCP backlog (thanks to Janusz Dziemidowicz)(EJAB-1063)
SVN Revision: 2679
2009-10-19 13:24:13 +00:00
Badlop 9a6c869cb8 Fix word Sensible with Sensitive (thanks to Marcin Owsiany)(EJAB-1071)
SVN Revision: 2676
2009-10-19 10:50:00 +00:00
Badlop dce7b1430b Start mnesia as a permanent application (thanks to Brian Cully)(EJAB-1068)
SVN Revision: 2674
2009-10-19 10:42:19 +00:00
Badlop 162fbc2ef8 Small fix in RSM decoding (thanks to Alexander Tsvyashchenko)(EJAB-1066)
SVN Revision: 2670
2009-10-15 22:46:50 +00:00
Badlop 13b8940606 Fixed more gcc signedness warnings
SVN Revision: 2669
2009-10-13 22:31:06 +00:00
Badlop f1b9f1fb63 Fix EDoc compilation errors.
SVN Revision: 2667
2009-10-13 21:36:32 +00:00
Christophe Romain 861cc87272 prevent remove_user from blocking gen_server, and allow plugin to change broadcasted payload on publish
SVN Revision: 2665
2009-10-13 16:42:13 +00:00
Badlop e5fb89731c If s2s fails due to namespace mismatch, show differences to help debugging the problem.
SVN Revision: 2663
2009-10-12 22:51:53 +00:00
Christophe Romain 2565a670b1 fix get_item issue on authorize access model (thanks to brian cully) (EJAB-1060)
SVN Revision: 2661
2009-10-12 15:25:00 +00:00
Badlop 74cd5ffb02 Autodetect compilation parameters for Mac OS X Snow Leopard (EJAB-1056)
SVN Revision: 2659
2009-10-12 12:59:07 +00:00
Christophe Romain c3303ce364 return invalid-options on badly formed subscription options
SVN Revision: 2657
2009-10-12 10:23:51 +00:00
Christophe Romain 2042ab090d Default pubsub messages to headline if nothing is configured (thanks to Brian Cully) (EJAB-1061)
SVN Revision: 2655
2009-10-12 09:06:37 +00:00
Badlop 13a231f6fa Add debug message on command execution
Merged from trunk@2650.

SVN Revision: 2653
2009-10-09 12:01:43 +00:00
Badlop 503defac73 Fix regression for authorize node subscription (thanks to Brian Cully)(EJAB-1060)
SVN Revision: 2652
2009-10-09 12:01:30 +00:00
Badlop 2d41c81890 Document new option max_fsm_queue.
SVN Revision: 2649
2009-10-08 14:34:32 +00:00
Badlop 036095f37d New option added: max_fsm_queue. Removed hardcoded FSMLIMITS. (thanks to Evgeniy Khramtsov)
Merged from trunk@2645

SVN Revision: 2647
2009-10-08 11:33:32 +00:00
Badlop a2bb22a0e7 Use queue to reduced quadratic time effort on selective receive (thanks to Alexey Shchepin)
Merged from trunk@2644

SVN Revision: 2646
2009-10-08 11:33:18 +00:00
Christophe Romain 65926460b2 allow max_items_node use on pep
SVN Revision: 2643
2009-10-06 15:22:02 +00:00
Badlop f4e35033e7 Improve stream error stanza when receives invalid handshake from component.
SVN Revision: 2641
2009-10-06 10:05:10 +00:00
Badlop 75793f7cf4 New CAPTCHA script since previous one has been broken (thanks to Evgeniy Khramtsov)(merged from trunk@2631)
SVN Revision: 2639
2009-10-02 15:04:16 +00:00
Mickaël Rémond e36c530732 Describe how to compile ejabberd on Mac OS X Snow Leopard with Erlang R13B-2
SVN Revision: 2637
2009-09-27 14:31:52 +00:00
Christophe Romain 53edf861e0 do not create hometree base when hometree not configured as plugin
SVN Revision: 2635
2009-09-25 13:14:59 +00:00
Christophe Romain 24afead423 fix EJAB-1054 (thanks to Evgeniy Khramtsov)
SVN Revision: 2633
2009-09-25 12:48:10 +00:00
Christophe Romain 2f5211ab74 improve waiting caps clean (EJAB-1054)
SVN Revision: 2629
2009-09-24 19:52:46 +00:00
Christophe Romain b168cd7cf2 fix EJAB-1044 and EJAB-1055
SVN Revision: 2628
2009-09-24 19:47:01 +00:00
Badlop 667fc07ec6 Recomppile guide.
SVN Revision: 2624
2009-09-24 13:36:48 +00:00
Christophe Romain e5a26b388f rename pep_sendlast_offline option to ignore_pep_from_offline (EJAB-1047)
SVN Revision: 2623
2009-09-23 22:00:53 +00:00
Christophe Romain 479b04a6a3 fix Makefile.win32 for including stun (thanks to neustradamus)
SVN Revision: 2620
2009-09-23 21:12:44 +00:00
Badlop b12b18d59f Fix wrong XEP number to XEP-0227
SVN Revision: 2618
2009-09-23 17:27:09 +00:00
Christophe Romain b3955fca3a fix EJAB-1048 and EJAB-819, thanks to badlop
SVN Revision: 2616
2009-09-23 16:32:06 +00:00
Badlop bac5c30380 Replace several mentions of Jabber to XMPP (thanks to Nicolas Vérité)
SVN Revision: 2614
2009-09-23 15:29:34 +00:00
Mickaël Rémond 4ce2890af0 Replaced Jabber references in config file with XMPP, official name of the protocol
SVN Revision: 2612
2009-09-23 12:37:58 +00:00
Badlop 169a0471b9 Document more ejabberd commands in the Guide (EJAB-1041)
SVN Revision: 2609
2009-09-21 10:14:06 +00:00
Christophe Romain 6bdf4aa960 improve configure parsing in iq_pubsub (sync with ejabberd 2.1.0)
SVN Revision: 2605
2009-09-20 08:14:24 +00:00
Christophe Romain 36676f0719 fix missing member affiliation on odbc plugin
SVN Revision: 2604
2009-09-18 13:44:12 +00:00
Christophe Romain bb1fca058d Return terminal binding condition on max stanza size limit (thanks to Aleksey)
SVN Revision: 2602
2009-09-18 13:33:12 +00:00
Jérôme Sautret b4c161e04a Merge r2592 and r2593 from trunk:
Fix pubsub tables constraints in MySQL schema creation script.
Add a "created_at" column to some tables in the MySQL schema to store
a timestamp (thanks to Pedro Melo, EJAB-376).

SVN Revision: 2594
2009-09-10 16:59:58 +00:00
Christophe Romain 376741c9a1 fix delete item to allow owner being able to remove all publisher items, and also fix EJAB-1036
SVN Revision: 2591
2009-09-09 21:49:23 +00:00
Badlop 04e86829e3 Change some error messages.
SVN Revision: 2588
2009-09-07 14:31:34 +00:00
Christophe Romain 75dbcd5c68 fix minor timestamp shift between item creation and modification
SVN Revision: 2586
2009-09-04 23:34:05 +00:00
Pablo Polvorin 283aa52b31 Port #2583 from trunk
Use the local (target) domain for firing the s2s_receive_packet hook.  

It was using the external server domain (LFrom) instead of the local domain (LTo).  
This might have impact on mod_caps in s2s scenarios, needs further attention.

SVN Revision: 2584
2009-09-04 21:33:30 +00:00
Badlop 29b2da42f5 Replace calls from 'regexp' to the OTP R12 new module 're' (EJAB-921)
SVN Revision: 2582
2009-09-02 14:26:01 +00:00
Badlop 330a4c9452 Small fix exmpp related code
SVN Revision: 2581
2009-09-02 14:25:42 +00:00
Christophe Romain fa23b83dbb improve previous patch
SVN Revision: 2579
2009-09-01 13:23:19 +00:00
Badlop 81f4644622 Fix missing tag when configuring subscription option (thanks to Clochix)
SVN Revision: 2577
2009-09-01 08:19:14 +00:00
Badlop 095cd6ce9b BOSH module optimization and clean-up (thanks to Aleksey Shchepin and Mickaël Rémond)(EJAB-936)
Unfortunately, http-bind doesn't work in this branch,
neither in this commit or before it.

SVN Revision: 2575
2009-08-31 18:40:25 +00:00
Badlop f5eb9e3c9f Support zlib compression after STARTTLS (thanks to Aleksey Shchepin)(EJAB-499)
Unfortunately, zlib compression doesn't work in this branch,
neither in this commit or before it.

SVN Revision: 2572
2009-08-31 16:30:19 +00:00
Badlop 98f93104a7 Rename erlang log file sasl.log to erlang.log (EJAB-783)
SVN Revision: 2568
2009-08-31 11:03:35 +00:00
Christophe Romain 3940a6bab3 secure calls to ets:lookup
SVN Revision: 2564
2009-08-28 16:28:22 +00:00
Christophe Romain de78508f45 fix send last item issue
SVN Revision: 2561
2009-08-28 00:09:21 +00:00
Christophe Romain fab29f4cf0 port all recent fixes from trunk related to odbc subscriptions
SVN Revision: 2559
2009-08-27 23:09:20 +00:00
Christophe Romain adfca08e43 remove INFO_MSG call inside sql_query_internal
SVN Revision: 2557
2009-08-27 22:30:57 +00:00
Christophe Romain 35e8b95928 added pubsub odbc tables creation
SVN Revision: 2550
2009-08-27 09:49:37 +00:00
Christophe Romain f5091aa1ae pubsub now is sync with last trunk
SVN Revision: 2546
2009-08-27 08:48:21 +00:00
Christophe Romain bb08207569 fix node_public portage
SVN Revision: 2545
2009-08-27 08:34:16 +00:00
Christophe Romain 71e0d7d8e2 port commit from r2527 to odbc plugin
SVN Revision: 2544
2009-08-27 08:26:22 +00:00
Christophe Romain 3b27670d4d update win32 makefile
SVN Revision: 2542
2009-08-27 07:55:45 +00:00
Pablo Polvorin 944dd1cc7f Port pubsub odbc backend to exmpp.
Warning: A work in progress, isn't working yet!

SVN Revision: 2541
2009-08-26 20:27:57 +00:00
Evgeniy Khramtsov ba3a45452e check if a room is not persistent before starting a new one with the same name (EJAB-1026)
SVN Revision: 2540
2009-08-26 04:18:42 +00:00
Pablo Polvorin f7c5a4a15b backport trunk commit r2530
SVN Revision: 2538
2009-08-25 20:33:01 +00:00
Pablo Polvorin 4d5bfe2ee8 Fix pubsub_publish_item_ hook call parameter and jid conversion on node_hometree.
published messages are delivered to subscribers (flat nodes).

SVN Revision: 2537
2009-08-25 20:03:28 +00:00
Pablo Polvorin a1a6469ed0 Updated to trunk r2532, fix subscription managment (by owner)
SVN Revision: 2536
2009-08-25 19:54:44 +00:00
Pablo Polvorin fcf66c2e75 Fix affiliation managment
Node owner can add/remove affiliations

SVN Revision: 2535
2009-08-25 17:42:25 +00:00
Pablo Polvorin b4f0bb65c6 Fix disco#items on pubsub nodes
SVN Revision: 2534
2009-08-25 17:23:43 +00:00
Pablo Polvorin 938a4007b3 Initial port of pubsub changes(up to r2444) to exmpp branch.
pubsub odbc isn't ported yet.  
Not tested (only basic node creation and configuration), should still have losts of bugs to discover.

SVN Revision: 2533
2009-08-25 17:14:30 +00:00
Badlop 6470e6cc25 Write PID file, path is configurable in ejabberdctl.cfg (EJAB-1023)
SVN Revision: 2527
2009-08-24 21:21:39 +00:00
Badlop 9769a17866 Document that the admin can install ejabberd.init script (EJAB-755)
SVN Revision: 2525
2009-08-24 19:59:44 +00:00
Badlop 19355e947e Prepare ejabberd.init when installing ejabberd.
SVN Revision: 2524
2009-08-24 19:59:30 +00:00
Badlop d9a8c89b5a Added preliminary template file for ejabberd.init (thanks to Christophe Romain)
SVN Revision: 2523
2009-08-24 19:59:17 +00:00
Evgeniy Khramtsov 6688b4ea78 do not include MAPPED-ADDRESS in new style responses since it is not required by the RFC
SVN Revision: 2515
2009-08-21 06:07:55 +00:00
Badlop d05565c6e0 Show example config to disable account create/delete, and allow password change.
SVN Revision: 2513
2009-08-20 21:45:15 +00:00
Badlop ec26a28cd2 Merge 2427 from trunk: return timeout in requests if DB connection can't be established
SVN Revision: 2511
2009-08-20 17:37:37 +00:00
Badlop 05755b9b09 Merge some old English fixes from trunk SVN.
SVN Revision: 2505
2009-08-19 17:59:49 +00:00
Badlop 007cafa7cd Fix EDoc errors.
SVN Revision: 2495
2009-08-17 17:17:34 +00:00
Badlop a9ce2fc38a Display room service messages in distintive blue colour.
SVN Revision: 2492
2009-08-15 22:03:14 +00:00
Badlop 0175932d86 Update Ingoing s2s connections inner state to hold domain name (thanks to Juan Pablo Carlino)(EJAB-972)
SVN Revision: 2490
2009-08-15 21:39:41 +00:00
Badlop 26cdea53c7 Don't allow room config to enable password protection with empty password (EJAB-1011)
SVN Revision: 2488
2009-08-15 20:11:24 +00:00
Badlop e585b07d76 If room config violates service policy, return not-acceptable instead of bad-request.
SVN Revision: 2487
2009-08-15 20:11:10 +00:00
Badlop 6eb5b544b4 Remove workarounds that supported R11 or older (EJAB-446)(EJAB-628)(EJAB-997)
SVN Revision: 2486
2009-08-15 20:10:49 +00:00
Evgeniy Khramtsov 9c0495b563 removed unnecessary gen_server call
SVN Revision: 2477
2009-08-13 10:02:04 +00:00
Badlop 2c25db28c4 Describe the options syntax, not only the name (EJAB-998)
SVN Revision: 2473
2009-08-12 14:18:47 +00:00
Badlop 14464ab6cc Add support in WebAdmin for the new listener network protocol
SVN Revision: 2464
2009-08-11 18:24:12 +00:00
Badlop a4b2d032f9 Add stun directory to compilation process
SVN Revision: 2463
2009-08-11 18:23:54 +00:00
Badlop 3078c28d1a Document STUN server (thanks to Evgeniy Khramtsov), and minor doc enhancements.
* Add stun listener to example config file, disabled.
* Improve enumeration of listeners options

SVN Revision: 2460
2009-08-11 13:22:39 +00:00
Evgeniy Khramtsov cf90c8176e updated top supervisor for STUN support
SVN Revision: 2459
2009-08-11 13:17:46 +00:00
Evgeniy Khramtsov 0a8bcf6530 restore missing stun directory
SVN Revision: 2458
2009-08-11 12:54:40 +00:00
Evgeniy Khramtsov bf0dbeb8b3 STUN support backport
SVN Revision: 2457
2009-08-11 12:53:46 +00:00
Badlop b453ee5e1f Update URLs of IETF and XMPP protocol documents
SVN Revision: 2456
2009-08-11 11:49:54 +00:00
Badlop 2e8fe6a1ab Add ejabberd command to get the current loglevel (EJAB-1004)
SVN Revision: 2449
2009-08-07 14:56:12 +00:00
Badlop e0be566491 ejabberdctl commands use _ instead of -. For backwards compatibility - is still supported.
SVN Revision: 2448
2009-08-07 14:55:08 +00:00
Badlop 936b2d4188 Merge 2426 from trunk: add get/0 API function that returns current log level (EJAB-1004).
SVN Revision: 2436
2009-08-06 22:01:01 +00:00
Badlop 9a204593e1 Merge 2425 from trunk: fix keepalive query, broken by r2092.
SVN Revision: 2435
2009-08-06 21:57:53 +00:00
Badlop 6aa4bb9f08 Merge 2422, 2423: cosmetic change, fix shell function syntax (EJAB-1003), use variable for Erlang shell.
SVN Revision: 2434
2009-08-06 21:54:10 +00:00
Badlop 562e63a3b0 Fix argument passing
SVN Revision: 2433
2009-08-06 21:15:15 +00:00
Badlop 663e29af89 Document options for Roster Versioning (EJAB-964)
SVN Revision: 2432
2009-08-06 21:07:23 +00:00
Badlop 4f6b67b190 Move functions from roster_versioning to mod_roster (EJAB-964)
SVN Revision: 2431
2009-08-06 21:07:18 +00:00
Pablo Polvorin 1b85310f1a Support for roster versioning (EJAB-964)
Introduces two options for mod_roster and mod_roster_odbc:
- {versioning, true | false}   Enable or disable roster versioning on ejabberd.
- {store_current_id, true | false}   If true, the current roster version is stored on DB (internal or odbc). Otherwise it is calculated on the fly each time.

Performance:
Setting store_current_id to true should help in reducing the load for both ejabberd and the DB.

Details: 
If store_current_id is false,  the roster version is a hash of the entire roster. If store_current_id is true, the roster version is a hash, but of the current time
(this has to do with transactional semantics; we need to perform both the roster update and the version update on the same transaction, but we don't   
have the entire roster when we are changing a single item on DB. Loading it there requires significant changes to be introduced, so I opted for this simpler approach).

In either case, there is no difference for the clients, the roster version ID is opaque.

IMPORTANT:
mod_shared_roster is not compatible with the option 'store_current_id'.  Shared roster and roster versioning can be both enabled, but store_current_id MUST be set to false.

SVN Revision: 2428
2009-08-06 15:45:13 +00:00
Badlop 6aa3706bec Support XEP-0227 Portable Import/Export (EJAB-993)
SVN Revision: 2421
2009-08-05 18:23:54 +00:00
Pablo Polvorin 92ad67a814 Fix problems when deleting a roster item.
The deleted item was left on the user roster, and unsubscribe presence stanza wasn't sent to the unsubscribed user.

SVN Revision: 2420
2009-08-05 17:39:47 +00:00
Badlop 14399e3d57 Support XEP-0199 Ping (thanks to Brian Cully and Evgeniy Khramtsov)(EJAB-974)
SVN Revision: 2419
2009-08-03 19:33:42 +00:00
Badlop a321ab3653 Document the new option s2s_dns_options, expressed in seconds (EJAB-994)
SVN Revision: 2418
2009-08-03 15:04:52 +00:00
Evgeniy Khramtsov ce3fa18fb6 fixes incorrect substitution of an LDAP pattern
SVN Revision: 2415
2009-07-31 06:43:17 +00:00
Badlop 4064e933fe ejabberd 3.0.0 will require Erlang/OTP R12B-4 or higher, or R13B or higher (EJAB-997)
SVN Revision: 2410
2009-07-30 18:29:46 +00:00
Badlop f5868a0952 Delete expat_erl, stringprep, xml and xml_stream; replaced by exmpp (EJAB-991)
SVN Revision: 2409
2009-07-30 17:57:56 +00:00
Evgeniy Khramtsov 35c1c3774c do not crash on unmatched request
SVN Revision: 2407
2009-07-30 13:10:01 +00:00
Geoff Cant 628b03f3c0 EJAB-994: Implements DNS timeouts and retries.
SVN Revision: 2405
2009-07-30 12:35:18 +00:00
Evgeniy Khramtsov c6f3fbb82c treap.erl backport
SVN Revision: 2400
2009-07-29 03:43:58 +00:00
Geoff Cant 504cc7b7dd EJAB-940: Implements reliable ODBC transaction nesting.
SVN Revision: 2396
2009-07-28 13:43:00 +00:00
Badlop e6205e8f26 Fix error when nick registration stanza doesn't contain Value.
SVN Revision: 2395
2009-07-27 09:37:24 +00:00
Badlop 620a50223c New command to dump a table to text file.
SVN Revision: 2391
2009-07-23 15:23:26 +00:00
Badlop 646adbf186 Add support to delete content and delete table.
SVN Revision: 2390
2009-07-23 15:23:21 +00:00
Badlop 73f2fc76d9 Log an error if HTTP request does not include Host header (EJAB-966)
SVN Revision: 2387
2009-07-23 14:51:16 +00:00
Evgeniy Khramtsov 553969f0fd delete/2 now does not crash when there is nothing to delete. fold/1 added
SVN Revision: 2385
2009-07-22 06:52:47 +00:00
Mickaël Rémond ee142c5fe1 Fix typo from EJAB-988
SVN Revision: 2381
2009-07-21 19:18:22 +00:00
Badlop 97dfcb9fb0 HTML room logs: fix formatting of spaces; log config when disabling logging; display occupants (EJAB-986)
SVN Revision: 2379
2009-07-21 18:35:20 +00:00
Badlop 97ee31e751 Allow content types to be configured in ejabberd.cfg (EJAB-975)(thanks to Brian Cully)
SVN Revision: 2377
2009-07-21 17:32:29 +00:00
Badlop 338af10aaf moved some log reports from error to debug level (thanks to Evgeniy Khramtsov)
SVN Revision: 2374
2009-07-20 09:21:42 +00:00
Badlop 020a3e6d6b Revert workaround of EJAB-611 because it seems no longer required (EJAB-709)
SVN Revision: 2371
2009-07-17 21:47:26 +00:00
Badlop 5e05ad03bb Support XEP-0157: Contact Addresses for XMPP Services (EJAB-235)
SVN Revision: 2369
2009-07-17 20:47:40 +00:00
Badlop 8d988d1bd2 Store account number in internal auth of (EJAB-981)(thanks to Juan Pablo Carlino)
SVN Revision: 2366
2009-07-17 19:06:42 +00:00
Badlop f3db058fef If a command is already defined: log as Debug, not as Warning.
SVN Revision: 2363
2009-07-16 20:18:36 +00:00
Badlop b49a15efeb If directory /sbin is created, set permissions 755, not 750.
SVN Revision: 2359
2009-07-07 08:27:58 +00:00
Badlop be5b35e999 Temporary Debug and Ctl nodes must get nodename similar to destination.
SVN Revision: 2357
2009-07-06 14:11:35 +00:00
Badlop 30697ca0a1 Add -hidden flag when calling Debug or Ctl
SVN Revision: 2356
2009-07-06 14:11:31 +00:00
Badlop 0e19ca68b4 Support XEP-0085 Chat State Notifications (EJAB-961)
SVN Revision: 2351
2009-06-30 19:33:09 +00:00
Badlop f82131af15 Include original timestamp on delayed presences (thanks to Mickael Remond)(EJAB-234)
SVN Revision: 2349
2009-06-30 17:51:37 +00:00
Badlop 16ca8d178d Add XEP82 Date Time, update XEP202 Entity Time and XEP203 Delayed Delivery (EJAB-234)
SVN Revision: 2347
2009-06-30 16:55:26 +00:00
Badlop cdac156f2e Add announcement of offline feature to service discovery (EJAB-234)
SVN Revision: 2346
2009-06-30 16:54:46 +00:00
Badlop ba335346f2 Don't use lists:keyfind/3 bcause it was introduced only in recent R13A.
SVN Revision: 2342
2009-06-25 18:05:34 +00:00
Badlop 82b3790f85 Improve explanation about SSL for port 5223 and its option 'tls'.
SVN Revision: 2340
2009-06-25 18:03:29 +00:00
Badlop 52c0fd8f09 Add note about PAM configuration for pam_winbind (thanks to Jon Bendtsen)
SVN Revision: 2338
2009-06-25 17:09:06 +00:00
Badlop e37b26e068 Improvements in the WebAdmin browsing menus.
SVN Revision: 2336
2009-06-25 17:04:03 +00:00
Badlop 6ac4157fc1 Add Vim folding
SVN Revision: 2335
2009-06-23 21:13:04 +00:00
Badlop b9cbb7a72b Detect auth errors and report in log file. Support auth when domain not provided.
SVN Revision: 2331
2009-06-22 23:14:18 +00:00
Badlop 0aca6920a7 ejabbed 3.0.0 requires exmpp 0.9.1 or higher.
SVN Revision: 2328
2009-06-17 09:07:02 +00:00
Badlop a6e8e10a3d Erlang/OTP R13B can be used, but its support is still experimental.
SVN Revision: 2327
2009-06-17 09:06:57 +00:00
Badlop bfbc69e8f9 Update version number to 3.0.0-alpha
SVN Revision: 2326
2009-06-17 09:06:52 +00:00
Badlop 13c76c12f8 Workaround to compile with exmpp
SVN Revision: 2324
2009-06-16 18:28:06 +00:00
Badlop 08ebf50480 Add permanent section about mod_http_fileserver to the Guide. Example config.
SVN Revision: 2323
2009-06-16 18:28:01 +00:00
Badlop a6b5e6360b Add unit test script for http-bind service (thanks to Stefan Strigler)
SVN Revision: 2322
2009-06-16 18:27:55 +00:00
Badlop b49f8a81a8 Add forgotten copyright and license notices.
SVN Revision: 2321
2009-06-16 18:27:51 +00:00
Badlop ab5b66facc Easier debugging (EJAB-936)(thanks to Michael Remond)
SVN Revision: 2320
2009-06-16 18:27:45 +00:00
Badlop 35c6ea68cc Code clean-up (EJAB-936)(thanks to Michael Remond)
SVN Revision: 2319
2009-06-16 18:27:40 +00:00
Badlop b74cb8828b Started code clean-up (EJAB-936)(thanks to Michael Remond)
SVN Revision: 2318
2009-06-16 18:27:35 +00:00
Badlop a1b84c6fa3 Replaced sha1 to hexadecimal transformation with sha:sha/1 call (thanks to Alexey Shchepin)
SVN Revision: 2317
2009-06-16 18:27:31 +00:00
Badlop 3e3d01063d Replace TYPE/1 with is_TYPE/1 (EJAB-922)
SVN Revision: 2316
2009-06-16 18:27:27 +00:00
Badlop c19cc61c48 Simplified code.(thanks to Michael Remond)
SVN Revision: 2315
2009-06-16 18:27:24 +00:00
Badlop 5854edafdd Properly warn user and admin when mod_http_bind is not started.(thanks to Michael Remond)
SVN Revision: 2314
2009-06-16 18:27:18 +00:00
Badlop 2c33e72eea Do not clear input when dispatching a get when we have nothing to output. (thanks to Geoff Cant)
SVN Revision: 2313
2009-06-16 18:27:14 +00:00
Badlop 24ab5026c9 Changed the place where database is created(thanks to Michael Remond)
SVN Revision: 2312
2009-06-16 18:27:10 +00:00
Badlop c74ef80f79 Fix remote-stream-error stanzas
SVN Revision: 2311
2009-06-16 18:27:05 +00:00
Badlop eeb11046d5 New option max_inactivity to configure maximum inactivity period (EJAB-512)
SVN Revision: 2310
2009-06-16 18:27:01 +00:00
Badlop 66f3f0f3de Fix warning of unused Host variable
SVN Revision: 2309
2009-06-16 18:26:57 +00:00
Badlop a1bce24461 Include condition in http-bind terminate body when service stops (EJAB-792)
SVN Revision: 2308
2009-06-16 18:26:53 +00:00
Badlop 1c2d0afd95 Fix unknown rid error (thanks to Jerome Sautret)
SVN Revision: 2307
2009-06-16 18:26:48 +00:00
Badlop 6e52ca3f4e Implement packets reordering to avoid race conditions (EJAB-724).(thanks to Michael Remond)
SVN Revision: 2306
2009-06-16 18:26:44 +00:00
Badlop 1d1f72fdc2 Updated IP retrieving (thanks to Alexey Shchepin)
SVN Revision: 2305
2009-06-16 18:26:40 +00:00
Badlop d25bd8c1c6 Improve ip fetching patch (thanks to Christohpe Romain)
SVN Revision: 2304
2009-06-16 18:26:36 +00:00
Badlop 3e0827deea Retrieve correct IP from http connection (thanks to Christohpe Romain)
SVN Revision: 2303
2009-06-16 18:26:31 +00:00
Badlop 481c7ea4e6 Fix syntax error. (thanks to Jerome Sautret)
SVN Revision: 2302
2009-06-16 18:26:27 +00:00
Badlop 646477be08 Removed HTTP bind session count. Removed the 'sponsored bind session' text. (thanks to Michael Remond)
Details:
Removed the HTTP bind session count because it leaks information on the size of the platform.
Removed the text 'sponsored by Mabber' because it is confusing, as people could think a third-party service using HTTP bind is sponsored by Mabber.

SVN Revision: 2301
2009-06-16 18:26:23 +00:00
Badlop 3e2c626696 Do not display error message when starting several hosts (EJAB-571) (thanks to Christohpe Romain)
SVN Revision: 2300
2009-06-16 18:26:19 +00:00
Badlop 38ce8b494e Provide explanation in error message when module is already started for another vhost
SVN Revision: 2299
2009-06-16 18:26:15 +00:00
Badlop 292e2f6b69 Removed small warning
SVN Revision: 2298
2009-06-16 18:26:11 +00:00
Badlop 94c3a384b1 Bugfixes (thanks to Alexey Shchepin)
SVN Revision: 2297
2009-06-16 18:26:07 +00:00
Badlop 5f07b4bf9b Removed receive_loop (thanks to Alexey Shchepin)
SVN Revision: 2296
2009-06-16 18:26:02 +00:00
Badlop 68754c4b5d Remove Erlang module attribute 'vsn' because it does not provide any worth feature, and it difficults hot code update (EJAB-440)
SVN Revision: 2295
2009-06-16 18:25:59 +00:00
Badlop ff4ccc1d85 Bugfix when table does not exist (thanks to Justin Kirby)
SVN Revision: 2294
2009-06-16 18:25:54 +00:00
Badlop d84a2f8215 Migration code for people using previous version of the HTTP binding module (EJAB-390)
SVN Revision: 2293
2009-06-16 18:25:51 +00:00
Badlop 86738e965f Do not overwrite the stanza namespace (thanks to Anastasia Gornostaeva)
SVN Revision: 2292
2009-06-16 18:25:46 +00:00
Badlop 818f28d85f Support for c2s ACL access, max_stanza and shaper on http_poll connections (EJAB-243, EJAB-415, EJAB-416)(thanks to Michael Remond)
SVN Revision: 2291
2009-06-16 18:25:42 +00:00
Badlop 5f7356c16c The Erlang/OTP function httpd_util:to_lower/1 is deprecated, and it is recommended to use string:to_lower/1 instead.
SVN Revision: 2290
2009-06-16 18:25:38 +00:00
Badlop b0b708ddea Use DEBUG instead of INFO_MSG to keep log files small. Fix parse errors for grepping 'stream:error' (thanks to Stefan Strigler)
SVN Revision: 2289
2009-06-16 18:25:34 +00:00
Badlop 4adf23b4e9 Forgot keyword 'catch' when doing list_to_float on bosh version attribute for initial request (thanks to Stefan Strigler)
SVN Revision: 2288
2009-06-16 18:25:30 +00:00
Badlop 2f29e761c2 Fixes for pausing sessions; did not parse 'pause' attribute to int (thanks to Stefan Strigler)
SVN Revision: 2287
2009-06-16 18:25:26 +00:00
Badlop 8aede81188 Support pausing sessions (thanks to Stefan Strigler) (thanks to Stefan Strigler)
SVN Revision: 2286
2009-06-16 18:25:22 +00:00
Badlop c151da684d Comment-header: talk about xmpp over bosh rather than http binding (thanks to Stefan Strigler)
SVN Revision: 2285
2009-06-16 18:25:18 +00:00
Badlop bf4e927142 Removed debugging stuff. Removed error condition (thanks to Stefan Strigler)
SVN Revision: 2284
2009-06-16 18:25:14 +00:00
Badlop 7cb0b1a911 Code cleanup. Code reorganization. Store version of bosh session. Use bosh version for error conditions (thanks to Stefan Strigler)
SVN Revision: 2283
2009-06-16 18:25:10 +00:00
Badlop 6cbae7025c Store version as float (thanks to Stefan Strigler)
SVN Revision: 2282
2009-06-16 18:25:06 +00:00
Badlop 202bece16d Save bosh version with session (thanks to Stefan Strigler)
SVN Revision: 2281
2009-06-16 18:25:02 +00:00
Badlop f07df01185 Code rearranged (thanks to Stefan Strigler)
SVN Revision: 2280
2009-06-16 18:24:58 +00:00
Badlop 702978fa4b Make use of macros for namespaces. Some code cleanup. (thanks to Stefan Strigler)
SVN Revision: 2279
2009-06-16 18:24:54 +00:00
Badlop b79473b2f5 Fix for 'terminate' in request, send empty body instead of error (thanks to Stefan Strigler)
SVN Revision: 2278
2009-06-16 18:24:50 +00:00
Badlop 80b59441d5 Disabled debugging (thanks to Stefan Strigler)
SVN Revision: 2277
2009-06-16 18:24:46 +00:00
Badlop f422ec457a Some code cleanup (thanks to Stefan Strigler)
SVN Revision: 2276
2009-06-16 18:24:42 +00:00
Badlop 5048b6bdaf Bosh compliance: honor xmpp:version (thanks to Stefan Strigler)
SVN Revision: 2275
2009-06-16 18:24:38 +00:00
Badlop 01dc4611b9 Restore ejabberd directory structure (src/web) for integration as patch (thanks to Christohpe Romain)
SVN Revision: 2274
2009-06-16 18:24:34 +00:00
Badlop 5495516c30 We do not send a 'version' attribute at the stream header for now (thanks to Stefan Strigler)
SVN Revision: 2273
2009-06-16 18:24:30 +00:00
Badlop 2f8112b108 Prepare_response: fixed a dbg message. Changed http header (thanks to Stefan Strigler)
SVN Revision: 2272
2009-06-16 18:24:26 +00:00
Badlop 229c24e1f2 Implements sockname and peername for compatibility (thanks to Christohpe Romain)
SVN Revision: 2271
2009-06-16 18:24:22 +00:00
Badlop 832d59803a Reverted to r76 as 97 is completely broken and should not have been checked in at all (thanks to Stefan Strigler)
SVN Revision: 2270
2009-06-16 18:24:18 +00:00
Badlop 197639a34b Minor changes (thanks to Stefan Strigler)
SVN Revision: 2269
2009-06-16 18:24:14 +00:00
Badlop bb229a3a0c Disabled debug (thanks to Stefan Strigler)
SVN Revision: 2268
2009-06-16 18:24:09 +00:00
Badlop eca818be5a Deal with return values from starting/terminating supervisor (thanks to Stefan Strigler)
SVN Revision: 2267
2009-06-16 18:24:05 +00:00
Badlop 33896adf9d Disabled debug (thanks to Stefan Strigler)
SVN Revision: 2266
2009-06-16 18:24:01 +00:00
Badlop f5223b1643 Removed my own supervisor (thanks to Stefan Strigler)
SVN Revision: 2265
2009-06-16 18:23:57 +00:00
Badlop ecc2bbd752 Renamed some vars for (thanks to Stefan Strigler)
SVN Revision: 2264
2009-06-16 18:23:53 +00:00
Badlop d019405d51 Start supervisor here (thanks to Stefan Strigler)
SVN Revision: 2263
2009-06-16 18:23:49 +00:00
Badlop 7d62dff7e5 Make use of new api for plugable http based services (thanks to Stefan Strigler)
SVN Revision: 2262
2009-06-16 18:23:45 +00:00
Badlop dd8e4c620b Initial commit of HTTP-Bind source code (thanks to Stefan Striegler)
SVN Revision: 2261
2009-06-16 18:23:40 +00:00
Badlop 77a62670d3 Add permanent section about mod_http_fileserver to the Guide. Example config.
SVN Revision: 2197
2009-06-16 13:53:25 +00:00
Badlop 8e8b78a4c3 Add forgotten copyright and license notices.
SVN Revision: 2196
2009-06-16 13:53:18 +00:00
Badlop 249ee4b318 New option directory_indices, and improve logging (thanks to Brian Cully)(EJAB-932)
SVN Revision: 2195
2009-06-16 13:53:13 +00:00
Badlop 226bcd1360 Fix capitalization of HTTP headers (thanks to Brian Cully)(EJAB-892)
SVN Revision: 2194
2009-06-16 13:53:07 +00:00
Badlop 4956ed11f4 Converted to gen_server behaviour (EJAB-561). Use the general reopen_log_hook instead of ejabberdctl command.
SVN Revision: 2193
2009-06-16 13:53:02 +00:00
Badlop b44a3c7650 Fix ip source to comply with new ip storage into ejabberd_http (thanks to Christophe Romain)
SVN Revision: 2192
2009-06-16 13:52:57 +00:00
Badlop fa83147926 Use httpd_util:to_lower when not compiling with Erlang R12 (EJAB-628)
SVN Revision: 2191
2009-06-16 13:52:52 +00:00
Badlop 14afea1a20 Added JavaScript content type
SVN Revision: 2190
2009-06-16 13:52:47 +00:00
Badlop 4fdc4a2e06 Include Last-Modified HTTP header in responses to allow caching (EJAB-546) in mod_http_fileserver and mod_muc_log_http.
SVN Revision: 2189
2009-06-16 13:52:42 +00:00
Badlop 0864e8a24f Fix error creating ETS table if enabled in several vhosts (EJAB-551). Unregister the command when stopping the module.
SVN Revision: 2188
2009-06-16 13:52:37 +00:00
Badlop 6af85aea18 Remove Erlang module attribute 'vsn' because it doesn't provide any worth feature, and it difficults hot code update (EJAB-440)
SVN Revision: 2187
2009-06-16 13:52:32 +00:00
Badlop 0d4155b902 The Erlang/OTP function httpd_util:to_lower/1 is deprecated, and it's recommended to use string:to_lower/1 instead.
SVN Revision: 2186
2009-06-16 13:52:28 +00:00
Badlop 91193bf928 Small change in accesslog file format; fix bug when accesslog conf parameter wasn't present in the conf file (thanks to Jerome Sautret)
SVN Revision: 2185
2009-06-16 13:52:17 +00:00
Badlop b57248e822 Added accesslog parameter to record requests log in a file similar to Apache (thanks to Jerome Sautret)
SVN Revision: 2184
2009-06-16 13:52:12 +00:00
Badlop 487b80b9b0 Initial commit of mod_http_fileserver (thanks to Massimiliano Mirra)
SVN Revision: 2183
2009-06-16 13:52:07 +00:00
Badlop 818a70bdd7 Do not include mod_irc, it can be found in ejabberd-modules SVN. Iconv not required. (EJAB-954)
SVN Revision: 2167
2009-06-16 11:27:33 +00:00
Mickaël Rémond 940f5be35e Fix syntax error in config file
SVN Revision: 2166
2009-06-16 00:49:09 +00:00
Badlop 88fd7b226a Add option to restrict max offline messages by Access and ACL (EJAB-951)
New option for mod_offline: access_max_user_messages.
The old option user_max_messages is no longer supported.

SVN Revision: 2163
2009-06-15 17:44:04 +00:00
Badlop 2f6cea2be3 Fix warning about a case already covered.
SVN Revision: 2161
2009-06-15 17:27:11 +00:00
Badlop b4a1b4c8fb Replace TYPE/1 with is_TYPE/1 (EJAB-922)
SVN Revision: 2160
2009-06-15 17:27:06 +00:00
Badlop 2f3963417f Prevent process crash if the IP and port of a connection is unknown.
SVN Revision: 2156
2009-06-11 18:57:03 +00:00
Badlop 8de03275c3 When client is closed, include the Reason in the stream trailer stanza.
SVN Revision: 2154
2009-06-09 12:10:24 +00:00
Badlop 60f52b2cd8 Add forgotten copyright and license notices. Fix blackspaces.
SVN Revision: 2152
2009-06-09 10:56:49 +00:00
Badlop dd101c99e5 Malformed CAPTCHA response may crash a room. This is now fixed. (thanks to Evgeniy Khramtsov)
SVN Revision: 2150
2009-06-09 09:39:07 +00:00
Badlop a45e6da3d0 Remove support of deprecated Disco Publish XEP-0030 (EJAB-904)
SVN Revision: 2141
2009-06-02 18:09:01 +00:00
Badlop 2b6f45e4c1 Update some calls from jlib:make_jid to exmpp_jid:make
SVN Revision: 2139
2009-06-01 23:44:55 +00:00
Badlop 332de67fe2 Fix some calls to exmpp
SVN Revision: 2138
2009-06-01 21:04:16 +00:00
Badlop ff3fd02115 Fix Access check: the rule can be defined in a vhost or global.
SVN Revision: 2137
2009-06-01 21:04:11 +00:00
Karim Gemayel 437c9d07f5 API renaming : bare_jid_to_binary -> bare_to_binary
SVN Revision: 2135
2009-06-01 17:00:44 +00:00
Karim Gemayel 9abe47f350 API renaming : jid_to_binary -> to_binary
SVN Revision: 2134
2009-06-01 16:59:08 +00:00
Karim Gemayel 7a884ced32 API renaming : bare_jid_to_list -> bare_to_list
SVN Revision: 2133
2009-06-01 16:54:33 +00:00
Karim Gemayel 0ace8bda8c API renaming : prepd_jid_to_list -> prep_to_list
SVN Revision: 2132
2009-06-01 16:53:48 +00:00
Karim Gemayel 15bc238297 API renaming : jid_to_list -> to_list
SVN Revision: 2131
2009-06-01 16:52:14 +00:00
Karim Gemayel 1b94c7a8b3 API renaming : compare_bare_jids -> bare_compare
SVN Revision: 2130
2009-06-01 16:50:36 +00:00
Karim Gemayel c31f99937f API renaming : compare_jids -> compare
SVN Revision: 2129
2009-06-01 16:49:00 +00:00
Karim Gemayel 4258b99b2b API renaming : lresource_as_list -> prep_resource_as_list
SVN Revision: 2128
2009-06-01 16:43:15 +00:00
Karim Gemayel 29c0e17ca2 API renaming : lresource -> prep_resource
SVN Revision: 2127
2009-06-01 16:42:07 +00:00
Karim Gemayel d51d9e9fff API renaming : lnode_as_list -> prep_node_as_list
SVN Revision: 2126
2009-06-01 16:40:51 +00:00
Karim Gemayel d5f2c41f26 API renaming : lnode -> prep_node
SVN Revision: 2125
2009-06-01 16:39:36 +00:00
Karim Gemayel 7eb395b87d API renaming : ldomain_as_list -> prep_domain_as_list
SVN Revision: 2124
2009-06-01 16:38:28 +00:00
Karim Gemayel 19d7d79229 API renaming : ldomain -> prep_domain
SVN Revision: 2123
2009-06-01 16:37:15 +00:00
Karim Gemayel 526dc54173 API renaming : parse_jid -> parse
SVN Revision: 2122
2009-06-01 16:35:55 +00:00
Karim Gemayel a136192db2 API renaming : bare_jid_to_jid -> full
SVN Revision: 2121
2009-06-01 16:34:38 +00:00
Karim Gemayel 5dbc4f9954 API renaming : jid_to_bare_jid > bare
SVN Revision: 2120
2009-06-01 16:30:15 +00:00
Karim Gemayel 447d3818f5 API renaming : make_jid -> make
SVN Revision: 2119
2009-06-01 16:26:00 +00:00
Christophe Romain 7c45f8f053 fix nodetree virtual to allow node subscription
SVN Revision: 2117
2009-05-29 00:44:07 +00:00
Christophe Romain 497d4d26bb make flat the default node plugin
SVN Revision: 2116
2009-05-29 00:27:26 +00:00
Christophe Romain db6a8c2e05 fix ets table name change
SVN Revision: 2115
2009-05-29 00:13:21 +00:00
Christophe Romain a16230c9ca pubsub: added configuration option in guide.tex, added last item cache, use default node type if given type is not configured, make node_flat the default node plugin. caps: improve cache handling
SVN Revision: 2114
2009-05-28 23:21:50 +00:00
Badlop 0bbbf468f0 Fix crashes when browsing some WebAdmin pages (EJAB-821)
SVN Revision: 2111
2009-05-27 17:29:58 +00:00
Badlop 9bcba6c8b8 Update CSS of WebAdmin menu
SVN Revision: 2110
2009-05-27 17:29:50 +00:00
Badlop a1fe76fb5b Support to select what modules to update. Split large function in smaller ones.
SVN Revision: 2109
2009-05-27 17:29:43 +00:00
Pablo Polvorin dc613df3b1 Do not indent the resulting html. Indentation in exmpp is buggy, and there isn't a real adventage on indenting the generated html
SVN Revision: 2106
2009-05-27 15:02:44 +00:00
Christophe Romain 45a8a0fb53 make get_items able to sort items in publish order (EJAB-824)
SVN Revision: 2105
2009-05-26 22:50:11 +00:00
Christophe Romain aa210166c4 improve get_entity_* to work regardless of nodetree (EJAB-937)
SVN Revision: 2104
2009-05-26 21:50:13 +00:00
Badlop 43a3fef7bb Document how to setup CAPTCHA. Install example captcha.sh (EJAB-895)
SVN Revision: 2103
2009-05-26 17:20:50 +00:00
Badlop 55bebb0f62 Implement XEP-158 CAPTCHA Forms, support in mod_muc, sample script (thanks to Evgeniy Khramtsov)(EJAB-895)
SVN Revision: 2102
2009-05-26 17:20:09 +00:00
Badlop 18ae44f930 Support LDAPS with TLS (EJAB-109)(thanks to Thomas Baden, Andy Harb, Sergei Golovan, Anton Podavalov)
SVN Revision: 2099
2009-05-25 17:16:54 +00:00
Badlop dc3899dfd9 Decrease proxy65 buffer sizes to 8192 bytes.
The original size of 65535 confused clients with tight
shapers (thanks to Evgeniy Khramtsov)

SVN Revision: 2097
2009-05-25 11:19:28 +00:00
Mickaël Rémond b6b4b0cdf9 * trunk/src/odbc/ejabberd_odbc.erl: Fix typo (EJABS-859) (EJAB-940) (CR-EJAB-10)
* branches/road-to-exmpp/src/odbc/ejabberd_odbc.erl: Likewise.

SVN Revision: 2095
2009-05-21 16:43:33 +00:00
Mickaël Rémond 8be73967fd * src/odbc/ejabberd_odbc.erl: Support for nested transactions (EJABS-859) (EJAB-940) (CR-EJAB-10)
SVN Revision: 2094
2009-05-21 16:28:49 +00:00
Christophe Romain 2e26b6bf8b PubSub: improve get_entity_* API
SVN Revision: 2091
2009-05-19 22:29:28 +00:00
Badlop b473862da6 Added API function to get current S2S connections with information
get_info_s2s_connections(Type) returns a list of incoming (or outgoing)
S2S connections with information for each one including IP address,
port number, TLS options... (thanks to Juan Pablo Carlino)

SVN Revision: 2089
2009-05-19 09:39:13 +00:00
Badlop 0a9581a375 LDAP bind attempts: log warnings and increase timeout after reject.
Merged from trunk SVN r2086:
Log warnings on unsuccessful LDAP bind attempts.
Increase timeout before the next LDAP bind attempt up to
five seconds if the last bind attempt was rejected by the
LDAP server ("soft" error) (thanks to Konstantin Khomoutov)

SVN Revision: 2087
2009-05-18 11:41:53 +00:00
Badlop 5bd67495ed Document how to convert Mnesia node name
SVN Revision: 2085
2009-05-15 22:57:40 +00:00
Badlop 23509c1688 New command to convert mnesia nodename, copied from OTP and Debian
SVN Revision: 2084
2009-05-15 22:56:55 +00:00
Badlop a63f548528 Allow to define additional Erlang options in ejabberdctl.cfg (thanks to Sergei Golovan)
SVN Revision: 2083
2009-05-15 22:56:13 +00:00
Badlop ee8ed2828a The --node argument overwrites the value of ejabberdctl.cfg
SVN Revision: 2082
2009-05-15 22:55:29 +00:00
Badlop 35daf5df78 No longer edit ChangeLog, will be auto generated for ejabberd releases.
Added new call 'make changelog' which generates a ChangeLog file by
prepending to the old file obtained from SVN the new lines obtained
from SVN Log and formatted with svn2cl.
ChangeLog will be generated and included in ejabberd releases.

SVN Revision: 2076
2009-05-14 21:12:12 +00:00
Mickaël Rémond 3ca2d4dab3 * src/ejabberd_debug.erl: Handled fprof based profiling (EJABS-872).
* src/ejabberd_app.erl: Likewise.

SVN Revision: 2075
2009-05-13 12:36:37 +00:00
Christophe Romain c12b1870b7 Fix bad transaction returncode in unsubscribe presence handler
SVN Revision: 2074
2009-05-12 21:00:05 +00:00
Christophe Romain fd36726357 Prevent race condition when calling get_caps while note_caps has not been handled yet (EJAB-934)
SVN Revision: 2072
2009-05-11 17:27:55 +00:00
Christophe Romain 8dc1bb0659 handle Example 90 of XEP-0060 (EJAB-909), and make use of nodeAttr
SVN Revision: 2069
2009-05-08 01:28:17 +00:00
Christophe Romain 38413dc236 Allow to get subscriptions on a given node (EJAB-712), and presence based fixes
SVN Revision: 2067
2009-05-08 00:02:08 +00:00
Badlop ef94ad36cd Merge 2063 from trunk.
* src/ejabberd_app.erl: Better support for profiling.
* src/ejabberd.erl: Likewise
* src/ejabberd_ctl.erl: Likewise
* src/ejabberd_debug.erl: Likewise

SVN Revision: 2064
2009-05-07 22:56:23 +00:00
Christophe Romain e40e4298ca several pubsub fixes and improvements. also fixes EJAB-913 and EJAB-871
SVN Revision: 2061
2009-05-07 00:54:44 +00:00
Badlop 1d3947c0da Replace TYPE/1 with is_TYPE/1 (EJAB-922)
SVN Revision: 2057
2009-05-06 16:54:43 +00:00
Badlop 69349925a3 * src/Makefile.in: Prevent Erlang R13B compilation warning:
behaviour X undefined (EJAB-920)

SVN Revision: 2056
2009-05-06 15:15:09 +00:00
Badlop 921c7ede0d * src/ejabberd_loglevel.erl: Use dynamic_compile instead of
ram_file_io_server. Support definition of loglevels with integer
or atom. (thanks to Geoff Cant)(EJAB-919)
* src/dynamic_compile.erl: Added erlang module that converts
string to binary loadable code by Mats Cronqvist, Chris Newcombe,
and Jacob Vorreuter.
* src/ram_file_io_server.erl: Remove file not longer useful.
* src/ejabberd.app: Likewise

SVN Revision: 2054
2009-05-06 14:51:51 +00:00
Badlop e202ec009e * src/mod_muc/mod_muc_room.erl: Fix badarg return (EJAB-899)
SVN Revision: 2053
2009-05-03 11:26:18 +00:00
Christophe Romain ced30acb20 backport pubsub/pep/caps optimizations from trunk
SVN Revision: 2052
2009-04-30 23:17:38 +00:00
Badlop 3debaf99d8 * src/ejabberd_hooks.erl: Support distributed hooks (EJAB-829)
SVN Revision: 2047
2009-04-28 14:57:16 +00:00
Badlop 2908e5da19 Merge 1969 and 1970 from trunk.
* src/ejabberd_hooks.erl: anonymous functions support.

SVN Revision: 2046
2009-04-28 14:46:12 +00:00
Badlop 5afe7cfafb * src/translate.erl: Support additional files (EJAB-925)
* contrib/extract_translations/extract_translations.erl: Likewise
* contrib/extract_translations/prepare-translation.sh: Likewise

SVN Revision: 2044
2009-04-27 20:55:35 +00:00
Badlop d7829a76ce * src/win32_dns.erl: Fix problem parsing some win32 dns (EJAB-927)
SVN Revision: 2043
2009-04-27 20:36:19 +00:00
Badlop ec779c001c * src/cyrsasl_digest.erl: Fix auth verification (EJAB-863)
SVN Revision: 2042
2009-04-27 20:24:21 +00:00
Badlop 028509c3a9 * src/jlib.erl: Fix recursive call to speedup base64
decoding (thanks to Jeffrey Rogiers)(EJAB-333)

SVN Revision: 2041
2009-04-27 19:17:17 +00:00
Christophe Romain fd5e312ed9 minor cosmetic fix
SVN Revision: 2040
2009-04-24 21:34:59 +00:00
Christophe Romain 6710d66a58 fix minor pubsub init glitch, and allow ejabberd_odbc to execute bloc of queries without transaction
SVN Revision: 2039
2009-04-24 10:32:41 +00:00
Christophe Romain 1d44abfc8a improve send last published items spawning
SVN Revision: 2037
2009-04-22 23:01:51 +00:00
Badlop 0141779b9c * src/ejabberd.cfg.example: Fix English typos. Fix line length:
max 80 characters per line. Remove trailing blankspaces. Added
markers for Vim fold, you may want to add to $HOME/.vimrc this
line: set modeline
* src/ejabberdctl.cfg.example: Likewise

SVN Revision: 2035
2009-04-22 13:45:57 +00:00
Badlop 92b1e9d9ac * src/mod_muc/mod_muc.erl: Limit number of characters in Room ID,
Name and Description (EJAB-899)
* src/mod_muc/mod_muc_room.erl: Likewise
* doc/guide.tex: Likewise
* doc/guide.html: Likewise

SVN Revision: 2034
2009-04-22 12:05:10 +00:00
Badlop 43b59911e2 * src/cyrsasl.erl: Change API of check_password: pass a function
to generate the digest (thanks to Graham Whitted)(EJAB-863)
* src/cyrsasl_anonymous.erl: Likewise
* src/cyrsasl_digest.erl: Likewise
* src/cyrsasl_plain.erl: Likewise
* src/ejabberd_auth.erl: Likewise
* src/ejabberd_auth_anonymous.erl: Likewise
* src/ejabberd_auth_external.erl: Likewise
* src/ejabberd_auth_internal.erl: Likewise
* src/ejabberd_auth_ldap.erl: Likewise
* src/ejabberd_auth_odbc.erl: Likewise
* src/ejabberd_auth_pam.erl: Likewise
* src/ejabberd_c2s.erl: Likewise

SVN Revision: 2033
2009-04-22 11:44:03 +00:00
Badlop 240e37c387 * src/ejabberd_c2s.erl: Fix for SASL Anonymous connections not
stored or purged (thanks to Andy Skelton)(EJAB-912)

SVN Revision: 2032
2009-04-22 11:02:03 +00:00
Badlop 39f71ab2ab * src/mod_shared_roster.erl: Support in API to add 'all' as member
of a group (thanks to Martin Langhoff)(EJAB-916)

SVN Revision: 2031
2009-04-22 10:40:11 +00:00
Christophe Romain 6e37389145 fix missing greetings
SVN Revision: 2026
2009-04-17 20:43:12 +00:00
Badlop 554a9a72f1 * doc/guide.tex: Document new ejabberdctl option. New section that
documents AccessCommands. (EJAB-910)
* doc/guide.html: Likewise

SVN Revision: 2025
2009-04-17 13:53:20 +00:00
Badlop fd967d6976 * src/ejabberd_ctl.erl: New option to require auth in ejabberdctl
and restrict what commands and arguments can execute (EJAB-910)
* src/ejabberd_config.erl: Likewise

SVN Revision: 2024
2009-04-17 13:48:59 +00:00
Badlop b451f07801 * src/ejabberd_commands.erl: API to restrict who can execute what
commands and arguments (EJAB-910)

SVN Revision: 2023
2009-04-17 13:43:15 +00:00
Badlop 5ca560d0bd * src/mod_caps.erl: Fix unbound variable
SVN Revision: 2022
2009-04-17 13:40:57 +00:00
Badlop 13fcbd6413 * doc/guide.tex: Explain that the recommended Erlang/OTP version
is R12B-5, and R13 is not supported yet.
* doc/guide.html: Likewise
* README: Likewise

SVN Revision: 2021
2009-04-14 18:31:29 +00:00
Badlop 8782597c1a * src/mod_muc/mod_muc_log.erl: Linkify also xmpp:..., as it was
done previously (thanks to Konstantin Khomoutov)(EJAB-850)

SVN Revision: 2020
2009-04-14 18:25:58 +00:00
Christophe Romain ab4750ec1e after check, last commit was useless
SVN Revision: 2019
2009-04-14 12:46:55 +00:00
Christophe Romain b519fdd3cb back to original caps patch which may be safer
SVN Revision: 2018
2009-04-14 10:13:05 +00:00
Christophe Romain 08cbaf8ccf Better handling of presence hook and caps clean
SVN Revision: 2015
2009-04-10 13:21:37 +00:00
Badlop 6b2a838e24 * src/msgs/pl.po: Fix some translations (thanks to Andrzej Smyk)
SVN Revision: 2011
2009-04-09 11:18:06 +00:00
Badlop 854b448536 * src/mod_pubsub/mod_pubsub.erl: Announce PubSub features in the
server JID only if PEP is enabled (EJAB-905)

SVN Revision: 2010
2009-04-08 19:30:24 +00:00
Badlop 2195e433dc * src/mod_muc/mod_muc.erl: English fixes (thanks to Glenn Sieb)
* src/mod_muc/mod_muc_log.erl: Likewise
* src/mod_muc/mod_muc_room.erl: Likewise
* src/mod_register.erl: Likewise
* src/web/ejabberd_web_admin.erl: Likewise

SVN Revision: 2009
2009-04-08 19:04:13 +00:00
Badlop d13be09524 * src/mod_pubsub/mod_pubsub.erl: Quickfix compilation errors.
SVN Revision: 2008
2009-04-08 18:58:11 +00:00
Badlop e34d6e3678 * src/mod_irc/mod_irc_connection.erl: Fix compilation warnings.
SVN Revision: 2006
2009-04-08 18:52:52 +00:00
Badlop 79247dad41 * doc/release_notes_2.0.5.txt: Added file for new release
SVN Revision: 2002
2009-04-01 10:37:18 +00:00
Badlop 61691ac47d Merge 1998 from trunk.
* src/ejabberd_sm.erl: Partially retract SVN r1976
EJAB-300 (EJAB-890). Check default privacy list when account, not
a specific session, receives a presence subscription
stanza (EJAB-300).
* src/ejabberd_c2s.erl: Likewise

SVN Revision: 1999
2009-03-24 18:02:13 +00:00
Christophe Romain 3e756f5d1c implement roster acces model (EJAB-780)
SVN Revision: 1997
2009-03-20 00:08:38 +00:00
Christophe Romain 026c4a2711 Allow more environment variable overrides in ejabberdctl (EJAB-891)
SVN Revision: 1996
2009-03-19 21:30:10 +00:00
Badlop cd3556f195 Fix mistake when calling win32_dns.
SVN Revision: 1990
2009-03-11 18:36:27 +00:00
Badlop d0a6ae7855 * doc/release_notes_2.0.4.txt: Added file for new release
SVN Revision: 1987
2009-03-10 16:25:20 +00:00
Badlop b245d68568 * src/tls/tls_drv.c: Fix encryption problem for ejabberd_http
after timeout (thanks to Alexey Shchepin)(EJAB-880)

SVN Revision: 1986
2009-03-10 15:21:36 +00:00
Christophe Romain 2c4effe6ce typo fix on roster access_model
SVN Revision: 1985
2009-03-10 12:09:31 +00:00
Christophe Romain 5ed381fc58 Fix PEP with other domains and s2s (EJAB-825)
SVN Revision: 1982
2009-03-10 11:13:46 +00:00
Badlop 4c08e65fab * src/tls/tls_drv.c: Fix to support OpenSSL older than
0.9.8f (EJAB-877)(thanks to Jonathan Schleifer)
* doc/guide.tex: It is again supported OpenSSL older than 0.9.8f
* doc/guide.html: Likewise

SVN Revision: 1979
2009-03-09 19:17:53 +00:00
Badlop 4dde341c9d Merge 1925 from trunk.
* src/mod_proxy65/mod_proxy65_service.erl: if an ip option is not
defined, the module takes an IP address of a local
hostname (thanks to Evgeniy Khramtsov)

SVN Revision: 1978
2009-03-09 14:44:46 +00:00
Badlop ed3cae6f11 * src/Makefile.in: In SunOS, use different C flags (thanks to
Thomas)(EJAB-438)
* src/ejabberd_zlib/Makefile.in: Likewise
* src/mod_irc/Makefile.in: Likewise
* src/stringprep/Makefile.in: Likewise
* src/tls/Makefile.in: Likewise

SVN Revision: 1977
2009-03-07 09:52:26 +00:00
Badlop 56c33e994d * src/ejabberd_c2s.erl: Enforce privacy rules also for
subscription requests (EJAB-300)
* src/ejabberd_sm.erl: Likewise

SVN Revision: 1976
2009-03-07 08:59:26 +00:00
Badlop d6820f2c2d * src/mod_privacy.erl: Temporary workaround to inconsistency
* src/mod_privacy_odbc.erl: Likewise

SVN Revision: 1975
2009-03-07 08:53:34 +00:00
Badlop cf4b7b36ee Merge 1856 from trunk.
* src/eldap/eldap.erl: moves waiting for response queries to
pending queue on an LDAP connection failure (thanks to Evgeniy
Khramtsov)

SVN Revision: 1974
2009-03-06 11:50:23 +00:00
Badlop d23ebd354b Merge 1855 from trunk.
* src/eldap/eldap.erl: implemented queue for pending
queries (thanks to Evgeniy Khramtsov)

SVN Revision: 1973
2009-03-06 11:42:56 +00:00
Badlop 66c60c4e6d Merge 1851 from trunk.
* src/eldap/eldap.erl: Close a connection on tcp_error (thanks to
Evgeniy Khramtsov)

SVN Revision: 1972
2009-03-06 11:39:12 +00:00
Badlop 19b803bb03 * src/ejabberd_app.erl: In a Windows machine, explicitly add the
nameservers, as it seems Erlang does not do itself (EJAB-860)
* src/win32_dns.erl: Get name servers from Windows registy (thanks
to Geoff Cant)

SVN Revision: 1968
2009-03-05 20:03:18 +00:00
Badlop 982f61774d * doc/guide.tex: Require OpenSSL 0.9.8f or higher (EJAB-877)
* doc/guide.html: Likewise

SVN Revision: 1967
2009-03-05 19:48:24 +00:00
Badlop 7982492f50 * src/ejabberd_auth.erl: If anonymous auth is enabled, when
checking if the account already exists in other auth methods, take
into account if the auth method failed (EJAB-882)
* src/ejabberd_auth_anonymous.erl: Likewise
* src/ejabberd_auth_external.erl: Likewise
* src/ejabberd_auth_internal.erl: Likewise
* src/ejabberd_auth_ldap.erl: Likewise
* src/ejabberd_auth_odbc.erl: Likewise
* src/ejabberd_auth_pam.erl: Likewise

SVN Revision: 1966
2009-03-04 18:34:02 +00:00
Badlop 7af7afc30e * src/mod_caps.erl: Fix two small compilation errors
SVN Revision: 1965
2009-03-04 09:55:20 +00:00
Christophe Romain ab2dc5877f Allow node creation without configure item
SVN Revision: 1964
2009-03-04 01:14:13 +00:00
Christophe Romain 592c98fd7a update pubsub version
SVN Revision: 1961
2009-03-04 01:04:51 +00:00
Christophe Romain facf17e689 Add roster subscriptions handling and make PEP events sent to all resources
SVN Revision: 1958
2009-03-03 23:26:07 +00:00
Badlop 1db9642e4c Merge 1916 from trunk.
* src/ejabberd_listener.erl: Fix report message of 'undef' error

SVN Revision: 1955
2009-03-03 19:48:20 +00:00
Badlop 4df4527e77 Merge 1907 from trunk.
* src/ejabberd_listener.erl: Fix a minor compilation warning and
add EDoc comment

SVN Revision: 1954
2009-03-03 19:46:08 +00:00
Badlop dbf0bb209d Merge 1891 from trunk.
* src/ejabberd_listener.erl: When stopping a listener, don't stop
the listener supervisor (EJAB-874)

SVN Revision: 1953
2009-03-03 19:43:55 +00:00
Badlop 9a7c6b8be1 Merge 1884 from trunk.
* src/ejabberd_listener.erl: More error detections

SVN Revision: 1952
2009-03-03 19:40:55 +00:00
Badlop 36fc43c364 Merge 1883 from trunk.
* src/ejabberd_listener.erl: More error detections

SVN Revision: 1951
2009-03-03 19:39:36 +00:00
Badlop f80758f0de Merge 1882 from trunk.
* src/ejabberd_config.erl: Check certfiles are readable on server
start and listener start (EJAB-753)
* src/ejabberd_listener.erl: Likewise

SVN Revision: 1950
2009-03-03 19:38:13 +00:00
Badlop 25ef60a2c1 Merge 1875 from trunk.
* src/ejabberd_listener.erl: Report error at startup if a listener
module isn't available or is not an ejabberd listener (EJAB-868)

SVN Revision: 1949
2009-03-03 19:35:32 +00:00
Badlop 5bfdb71b4c Merge 1881 from trunk.
* src/mod_privacy.erl: Privacy List: deny presence-out all + send
presence to: presence is sent (EJAB-255)
* src/ejabberd_c2s.erl: Likewise

SVN Revision: 1948
2009-03-03 19:32:48 +00:00
Badlop 890b1c4f60 Merge 1834 from trunk.
* src/mod_privacy.erl: Only run roster_get_jid_info if privacy
list has subscription or group (thanks to George Hazan)(EJAB-851).
Sort items in privacy list by order before storing (EJAB-848)
* src/mod_privacy.hrl: Likewise
* src/mod_privacy_odbc.erl: Likewise

SVN Revision: 1947
2009-03-03 19:26:24 +00:00
Badlop 4046ecc99e Merge 1880 from trunk.
* src/mod_muc/mod_muc_room.erl: Owner of a password protected room
must provide the password, like other participants (EJAB-867)

SVN Revision: 1946
2009-03-03 19:07:24 +00:00
Badlop fe297e1dea Merge 1879 from trunk.
* src/mod_muc/mod_muc_log.erl: Prevent XSS in MUC logs by
linkifying only a few known protocols (EJAB-850)

SVN Revision: 1945
2009-03-03 19:03:56 +00:00
Badlop f0c0b2230a Merge 1878 from trunk.
* src/mod_muc/mod_muc.erl: Export function to create MUC
room (thanks to Eric Cestari) (EJAB-729)

SVN Revision: 1944
2009-03-03 19:01:24 +00:00
Badlop 23ec55975e Merge 1877 from trunk.
* src/mod_roster.erl: When account is deleted, cancel presence
subscription for all roster items (EJAB-790)
* src/mod_roster_odbc.erl: Likewise

SVN Revision: 1943
2009-03-03 18:57:47 +00:00
Badlop 54da31e805 Merge 1874 from trunk.
* src/mod_shared_roster.erl: Fix bug: a pending subscription
request, and later the requester added to the roster due to a
shared roster group, that request could neither be accepted or
rejected (thanks to Brian Cully)(EJAB-869)

SVN Revision: 1942
2009-03-03 18:53:28 +00:00
Badlop b0f29b20db Merge 1876 from trunk.
* src/web/ejabberd_http_poll.erl: Allow configuration of session
timeout, using new global option http_poll_timeout (EJAB-135)
* doc/guide.tex: Document new option
* doc/guide.html: Likewise

SVN Revision: 1941
2009-03-03 18:49:02 +00:00
Badlop c13ed8c625 Merge 1872 from trunk.
* src/ejabberd_system_monitor.erl: Allow parametrizable watchdog
threshold: option watchdog_large_heap or chatting with the
watchdog bot (EJAB-545)
* src/ejabberd_config.erl: Likewise
* doc/guide.tex: Likewise
* doc/guide.html: Likewise

SVN Revision: 1940
2009-03-03 18:45:26 +00:00
Badlop 79463d7f7d Merge 1873 from trunk.
* src/web/ejabberd_web_admin.erl: Show big integers with comma
separators for easy reading

SVN Revision: 1939
2009-03-03 18:29:53 +00:00
Badlop 77ff657351 Merge 1859 from trunk.
* src/web/ejabberd_web_admin.erl: Calls to the hook
webadmin_menu_node provide the node as first argument, and calls
to webadmin_menu_hostnode provide both the host and the node. Fix
call to make_menu_items, because webadmin_menu_node was called in
cases where webadmin_menu_hostnode should be called. Align to
right some table elements.

SVN Revision: 1938
2009-03-03 18:24:42 +00:00
Badlop 85412f0a41 Merge from trunk: 1835, 1836, 1842, 1843, 1854, 1858, 1860, 1861, and 1862.
* doc/Makefile: In Clean do not remove html. In new Distclean,
remove also html.

* doc/Makefile: When cleaning, remove contributed_modules.tex

* src/Makefile.in: Fix arguments to Install program

* doc/guide.tex: Provide only an example of language option
* doc/guide.html: Likewise

* doc/guide.tex: mod_muc can run in several nodes of cluster
* doc/guide.html: Likewise

* doc/api/process-one.css: Add some style to HTML elements

* src/ejabberd_listener.erl: Fix EDoc errors
* src/web/ejabberd_web_admin.erl: Likewise

* src/ejabberd_hooks.erl: Explanation in EDoc of some functions

* doc/guide.tex: Explain that account creation is only supported
by internal and odbc authentication methods
* doc/guide.html: Likewise

* src/Makefile.in: The path to the installed copy of ejabberd
Guide is set in the environment variable
EJABBERD_DOC_PATH (EJAB-837).
* src/web/ejabberd_web_admin.erl: Likewise
* src/ejabberdctl.template: Likewise
* doc/guide.tex: Likewise
* doc/guide.html: Likewise

SVN Revision: 1937
2009-03-03 18:11:23 +00:00
Pablo Polvorin 54a6992ae0 Serialize s2s stanzas to iolist() rather than list()
SVN Revision: 1936
2009-03-02 15:48:01 +00:00
Pablo Polvorin 2c35514537 Correct include declaration (thanks to badlop). Bug was introduced in r1863
SVN Revision: 1935
2009-03-02 13:27:35 +00:00
Pablo Polvorin 7fea7b30b2 Elements and namespace for (XEP-0039) aren't know by exmpp ("http://jabber.org/protocol/stats" is represented as a list())
SVN Revision: 1934
2009-03-01 20:48:43 +00:00
Pablo Polvorin f0d55c9a3f Fix bug when clients connect using legacy ssl
(ejabberd_receiver:process_data/2 was called before initializing  the xmlstream).

SVN Revision: 1933
2009-03-01 20:18:42 +00:00
Pablo Polvorin 3336d66fc4 Host argument for ejabberd_hooks's functions must be in binary() format.
SVN Revision: 1932
2009-03-01 19:03:35 +00:00
Badlop 19d27258d9 * src/mod_pubsub/node_default.erl: Fix that non-subscriber could
fetch items from Authorize node (thanks to Brian Cully)(EJAB-873)

SVN Revision: 1930
2009-02-27 23:56:46 +00:00
Pablo Polvorin 58e4b98d61 Fix small bug introduced in revision 1924.
SVN Revision: 1929
2009-02-27 21:09:44 +00:00
Badlop c73e87e9c8 Merge fix from trunk r1910
* src/web/ejabberd_http.erl: Added a workaround for inet:peername
returning 'ebadf'

SVN Revision: 1928
2009-02-27 16:19:19 +00:00
Badlop 6482c11f92 * src/tls/tls_drv.c: S2S connection with STARTTLS fails to Gtalk
and recent Openfire (thanks to Philipp Hancke)(EJAB-877)

SVN Revision: 1926
2009-02-27 15:42:27 +00:00
Christophe Romain f4a952032a cosmetic changes
SVN Revision: 1924
2009-02-27 03:19:53 +00:00
Badlop dd5a7bcd54 * doc/guide.tex: No mention to the release date in ejabberd Guide
or release notes. The date of an ejabberd release is determined by
the date of the corresponding release announcement.

SVN Revision: 1922
2009-02-26 23:10:28 +00:00
Badlop 34f6de0c84 * src/mod_pubsub/mod_pubsub.erl: Fix incorrect implementation of
Pubsub payload requirements (thanks to Andy Skelton)(EJAB-823)

SVN Revision: 1921
2009-02-25 21:17:14 +00:00
Pablo Polvorin 2678342c4a mod_muc/mod_muc_log.erl: The logging code expect nicknames to be in list() format.
SVN Revision: 1920
2009-02-24 20:50:28 +00:00
Pablo Polvorin 0f53fea903 src/mod_echo.erl: Fix call to exmpp_xml:get_cdata_as_list/1.
SVN Revision: 1919
2009-02-24 20:25:57 +00:00
Pablo Polvorin 9b1e5928bd Remove unused var
SVN Revision: 1918
2009-02-24 20:07:32 +00:00
Pablo Polvorin 31ef821e46 Exmpp related fixed to the external components service.
SVN Revision: 1917
2009-02-24 18:52:37 +00:00
Pablo Polvorin 3119badb2b Removed a couple of expensive function calls used as arguments for
?DEBUG macros. All arguments used in the ?DEBUG macro are strictly 
evaluated (even if the loglevel is higher). 
The same is true for all log macros defined in ejabberd.hrl.  
We might need to use lazy evaluation for the arguments, when they 
are expensive to generate (wrap the arguments lists in a fun).

SVN Revision: 1915
2009-02-24 03:04:58 +00:00
Pablo Polvorin acae6e20de * Use exmpp_jid:to_binary/1 when possible.
* ejabberd_odbc:escape/1 now can escape binaries too. This 
avoid the need to convert a binary value to list() just to 
sql-escape it. The escaped value returned is allways a list() 
(ejabberd's odbc drivers only works on lists())

SVN Revision: 1914
2009-02-23 19:45:55 +00:00
Christophe Romain 7a17baccac Do not call mod_caps:clear_caps as it breaks PubSub/PEP (EJAB-854)
SVN Revision: 1913
2009-02-23 15:58:21 +00:00
Pablo Polvorin 4956259124 src/mod_roster.erl: Bugfix in remove_user/2, values already in binary() format.
SVN Revision: 1909
2009-02-21 18:07:37 +00:00
Badlop a5f70e15a2 * src/ejabberd_auth.erl: Password is undefined when using digest
SVN Revision: 1908
2009-02-21 14:41:29 +00:00
Pablo Polvorin 2df100213b mod_configure: Fix bug in form generation
SVN Revision: 1893
2009-02-20 16:34:56 +00:00
Pablo Polvorin e989d41d50 "remove_user" hook actualized to expect binary arguments.
Fix webadmin code that performs addition / removal  of users.

SVN Revision: 1892
2009-02-20 15:30:16 +00:00
Christophe Romain edc0a9ac87 fix nodetree plugin resolver, and backport last changes from trunk
SVN Revision: 1890
2009-02-19 11:29:01 +00:00
Pablo Polvorin 5334a2d965 Bugfix: mod_announce.erl:get_title/2 now accepts node argument in binary() or list() format.
SVN Revision: 1887
2009-02-18 18:14:06 +00:00
Pablo Polvorin 7c10f3422a src/web/ejabberd_web_admin.erl, src/web/ejabberd_web_admin.hrl:
Many exmpp related fixes. Fix a bug when displaying users lists, 
if we can't access the 'offline_msg' mnesia table (using mod_offline_odbc).
This fix should be temporal, we should find a better way to manage this
situation.

src/web/ejabberd_http.erl: Language must be in binary() format.

src/translate.erl: Remove a debug call to io:format/2.

src/ejabberd_sm.erl, src/mod_configure.erl, src/mod_disco.erl:
ejabberd_sm:get_user_resources/2 returns resources as binary().

src/ejabberd_sm.erl: Bugfix in get_user_info/3.

SVN Revision: 1886
2009-02-18 18:03:11 +00:00
Pablo Polvorin ea62092d6e src/ejabberd_auth.erl: Fix: for legacy authentication, the Digest parameters could be 'undefined'.
src/mod_muc/mod_muc_room.erl: Typo.
src/ejabberd_c2s.erl: Remove comment for an already done TODO.

SVN Revision: 1885
2009-02-18 13:48:06 +00:00
Christophe Romain e977d099e2 prevent from calling get_vh_registered_users/2 when not available
SVN Revision: 1871
2009-02-13 15:01:55 +00:00
Jean-Sébastien Pédron bf82bac328 o Document the type of the argument(s) and the returned type of every
functions.
o  Add guardians expression to exported functions to ensure at an early
stage that we were given the right arguments.
o  Fix table conversion to exmpp; many fields were left as string(),
preventing matching from working correctly.
o  In user_roster_item_parse_query/4, fix a bug where the same variable
was used for two distinct purpose.
o  In user_roster_item_parse_query/4, fix a bad usage of
exmpp_jid:jid_to_list/1.

PR:		EJABP-1

SVN Revision: 1867
2009-02-06 13:43:40 +00:00
Jean-Sébastien Pédron 25bd2bc7fe Document the short JID type.
PR:		EJABP-1

SVN Revision: 1866
2009-02-06 13:35:40 +00:00
Jean-Sébastien Pédron 93b26d947c Add documentation stub for some types. This will be filled later.
PR:		EJABP-1

SVN Revision: 1865
2009-02-06 13:34:12 +00:00
Jean-Sébastien Pédron 8290026940 o Document the type of the argument(s) and the returned type of every
functions.
o  Add guardians expression to many functions of ejabberd_auth and
ejabberd_auth_anonymous to ensure at an early stage that we were given
the right arguments. Other modules are not changed because they are only
used by ejabberd_auth which already does the check.

PR:		EJABP-1

SVN Revision: 1863
2009-02-05 11:13:01 +00:00
Jean-Sébastien Pédron 4badd3b6ac Disable "TODO:" interpretation in eDoc because usually, the following
text isn't in eDoc format.

PR:		EJABP-1

SVN Revision: 1857
2009-01-30 15:50:13 +00:00
Jean-Sébastien Pédron 69a2194efe exmpp_server_sasl:next_step/1 returns the mechanism as list() again, so
the call to binary_to_list/1 isn't necessary anymore.

PR:		EJABP-1

SVN Revision: 1853
2009-01-23 14:06:48 +00:00
Jean-Sébastien Pédron b5c8b99272 Document every functions to clarify the types to give and returned.
PR:		EJABP-1

SVN Revision: 1852
2009-01-23 10:10:33 +00:00
Badlop 35926b96b4 * src/odbc/mysql.sql: Fix complain about comment syntax
* src/odbc/pg.sql: Likewise

SVN Revision: 1850
2009-01-23 00:10:00 +00:00
Pablo Polvorin d1cf37bbec Small fixes
SVN Revision: 1849
2009-01-22 22:19:03 +00:00
Jean-Sébastien Pédron 4c61d254cc Add edoc-info & erlang.png to svn:ignore.
PR:		EJABP-1

SVN Revision: 1848
2009-01-22 15:56:37 +00:00
Jean-Sébastien Pédron 9c68810c77 Ignore files generated by eDoc.
PR:		EJABP-1

SVN Revision: 1847
2009-01-22 15:55:48 +00:00
Jean-Sébastien Pédron 4417608b27 Document every functions to clarify the types to give and returned.
PR:		EJABP-1

SVN Revision: 1846
2009-01-22 15:54:03 +00:00
Jean-Sébastien Pédron a105dcb060 In get_vh_session_list/1, remove a bad list_to_binary/1; now that
exmpp_stringprep return the correct type, it was used on a binary().

PR:		EJABP-1

SVN Revision: 1845
2009-01-22 15:52:30 +00:00
Jean-Sébastien Pédron 0cf0992f78 Fix some eDoc @spec directives.
PR:		EJABP-1

SVN Revision: 1844
2009-01-22 15:50:43 +00:00
Jean-Sébastien Pédron 842ebfcca0 A lot of bug fixes regarding attribute values type:
o  Fix some bugs by getting attributes as list() instead of binary().
o  Instead creating #xmlattr directly, use the new ?XMLATTR macro; it'll
take care of the anything-to-binary() conversion.
o  Fix a bug where recipient and sender were used as binary() instead of
list(), which is required by the rest of the S2S code.
o  Fix a bug where binary_to_list/1 was called on a list().

Now concerning JIDs :
o  Now that #jid{} isn't part of the API of Exmppp anymore, replace
remaining direct usages by calls to exmpp_jid.
o  Replace exmpp_jid:make_bare_jid() by exmpp_jid:make_jid().
o  Replace exmpp_jid:*_to_jid/1 by exmpp_jid:parse_jid/1.

PR:		EJABP-1

SVN Revision: 1841
2009-01-21 13:34:26 +00:00
Jean-Sébastien Pédron 376ee2ed90 o In process_iq_get/3 and process_iq_set/3, use binary() version of
LUser and LServer.
o  In convert_to_exmpp2/2, user and server are stored as binary().

PR:		EJABP-1

SVN Revision: 1840
2009-01-21 13:31:14 +00:00
Jean-Sébastien Pédron 2f1397c50e Use string() version of UserName and UserHost.
PR:		EJABP-1

SVN Revision: 1839
2009-01-21 13:30:18 +00:00
Jean-Sébastien Pédron cdbb000638 Return invalid-mechanism when a mechanism isn't supported instead of
no-mechanism, which wasn't standard-compliant.

PR:		EJABP-1

SVN Revision: 1838
2009-01-21 13:07:55 +00:00
Jean-Sébastien Pédron 8a413018c2 In match_acl/3, use string() version of User/Server/Resource to match an
ACL.

PR:		EJABP-1

SVN Revision: 1837
2009-01-21 12:44:36 +00:00
Pablo Polvorin 03f2de75f5 Typo (prolists -> proplists).
SVN Revision: 1833
2009-01-19 17:45:11 +00:00
Jean-Sébastien Pédron 38c0f3cdc8 Replace remaining calls to deprecated API:
o  In src/cyrsasl_digest.erl, replace hijacked usage of
xml:get_attr_s/2 by proper calls to proplists:get_value/3.
o  Still in src/cyrsasl_digest.erl, replace a call to
stringprep:tolower/1 by exmpp_stringprep:to_lower/1.
o  In src/ejabberd_service.erl, replace a call to xml:crypt/1 by
exmpp_xml:escape_using_entities/1.

PR:		EJABP-1

SVN Revision: 1832
2009-01-19 15:58:16 +00:00
Jean-Sébastien Pédron 4d95ac08dd Remove empty svn:mergeinfo properties so it won't get in the way during
future merges.

The server and the repository are Subversion 1.4.x: they are unable to
understand this property.

Subversion 1.5.x clients usually won't commit it on purpose when the
server and/or the repository are 1.4.x. But they will copy it when doing
WC-to-WC copy because they do not communicate with the server at this
time.

SVN Revision: 1831
2009-01-19 15:42:25 +00:00
Jean-Sébastien Pédron fc77b48344 Merge from trunk (r1804 to r1829).
The merge party is over, you may now double-check that everything is in
place.

PR:		EJABP-1

SVN Revision: 1830
2009-01-19 15:27:07 +00:00
Jean-Sébastien Pédron ff500d8297 Merge from trunk (r1787 to r1804).
Included are fixes to src/mod_configure.erl and src/mod_caps.erl.

Note: this merge doesn't include the following revisions because it was
made by previous commits:
r1766, r1768, r1781, r1783, r1794, r1797, r1799, r1802.

Warning: Ejabberd may be broken until the merge is completly finished.

PR:		EJABP-1

SVN Revision: 1829
2009-01-19 14:47:33 +00:00
Pablo Polvorin e2ee44617c translate.erl: Bugfix, ?MYLANG macro returns a list().
SVN Revision: 1828
2009-01-19 13:44:43 +00:00
Jean-Sébastien Pédron 25009ff9f4 Merge from trunk (r1764 to r1787).
Warning: Ejabberd may be broken until the merge is completly finished.

PR:		EJABP-1

SVN Revision: 1827
2009-01-19 11:59:40 +00:00
Jean-Sébastien Pédron bc51bd0dbd Merge from trunk (r1752 to r1764).
Warning: Ejabberd may be broken until the merge is completly finished.

PR:		EJABP-1

SVN Revision: 1826
2009-01-19 11:16:44 +00:00
Jean-Sébastien Pédron 8a27b5446d Fix accesses to the new #jid opaque type.
PR:		EJABP-1

SVN Revision: 1825
2009-01-19 10:14:55 +00:00
Jean-Sébastien Pédron 2cc2039ad8 Merge from trunk (r1734 to r1752).
Note: this merge doesn't include the following revisions because it was
made by previous commits:
r1737, r1740, r1745, r1747, r1748.

Additionnaly, any deprecated content was removed from jlib.hrl. This
leaves only the new RSM records.

Warning: Ejabberd may be broken until the merge is completly finished.

PR:		EJABP-1

SVN Revision: 1824
2009-01-19 10:14:04 +00:00
Pablo Polvorin 04f6a2be37 Store host and room name as binary(). Use jid_to_binary() instead of jid_to_list().
SVN Revision: 1821
2009-01-15 19:41:06 +00:00
Pablo Polvorin 2538001b08 Store registered nicknames, rooms and domains as binary().
Use document_to_iolist/1 and iolist_size/1 instead of document_to_list/1.

SVN Revision: 1820
2009-01-15 15:21:54 +00:00
Pablo Polvorin e8f630b93a mod_pubsub: initial update to new hooks API (using binaries). mod_pubsub is still unusable with exmpp.
SVN Revision: 1809
2009-01-12 18:17:05 +00:00
Pablo Polvorin 49210e3099 Apply commit 1212 (caps handling fix), was incorrectly overwritten on 1770.
SVN Revision: 1807
2009-01-12 18:15:44 +00:00
Pablo Polvorin 96c0ff44f9 Fix typo
SVN Revision: 1806
2009-01-12 15:51:22 +00:00
Christophe Romain 56bccce713 fix previous fix misplacing (EJAB-840)
SVN Revision: 1803
2009-01-11 06:24:42 +00:00
Christophe Romain 89be1c2ede fix owners cache and fix unsubscribe permissions (EJAB-840)
SVN Revision: 1800
2009-01-11 02:05:41 +00:00
Pablo Polvorin c77f7e727b Update gen_iq_handler API, require the 'Host' argument to be in binary() format.
Fix bug in vcard user search, odbc backend.

SVN Revision: 1796
2009-01-10 16:10:12 +00:00
Christophe Romain 36080fb682 fix unsubscription of full jid subscribed node (EJAB-839)
SVN Revision: 1795
2009-01-10 13:40:38 +00:00
Pablo Polvorin 98f51dc91f Adapt to new exmpp API where get_id/1, get_lang/1, get_initiating_entity/1, get_receiving_entity/1 and get_type/1 returns binary().
SVN Revision: 1791
2009-01-09 19:18:46 +00:00
Christophe Romain d2524b20d5 minor pubsub fixes
SVN Revision: 1782
2009-01-08 18:44:11 +00:00
Christophe Romain 068c93e562 fix EJAB-701 and EJAB-836
SVN Revision: 1781
2009-01-08 17:27:47 +00:00
Pablo Polvorin e0e58711bb XML attributes as binary(). Change Node argument to binary in the following hooks:
disco_local_items, disco_local_features, disco_local_identity, disco_sm_items and 
disco_sm_identity.

SVN Revision: 1780
2009-01-08 14:54:00 +00:00
Pablo Polvorin 2cbd61f268 Fix typo in mod_roster
SVN Revision: 1773
2009-01-05 15:41:53 +00:00
Pablo Polvorin 4827db4f56 Big #jid to binary() conversion.
Internal tables (ejabberd_router, ejabberd_sm, ejabberd_hooks, mod_last, mod_roster) use binary() as storage.
Basic test using the ODBC backend.

SVN Revision: 1770
2009-01-03 15:15:38 +00:00
Christophe Romain 1a44fe29b4 PubSub: Added access-whitelist and member-affiliation features (EJAB-780)
SVN Revision: 1769
2009-01-03 00:58:18 +00:00
Christophe Romain e032a8c54f PubSub cleanup, EJAB-827 fix, EJAB-701 partial fix
SVN Revision: 1767
2009-01-03 00:29:36 +00:00
Christophe Romain 214ef31053 Improve handling of PEP sent to external contacts (EJAB-825)
SVN Revision: 1751
2008-12-23 13:58:38 +00:00
Christophe Romain 978adbbd94 Fix send_last_published_item issue when running on clustered table (EJAB-793)
SVN Revision: 1741
2008-12-20 00:01:26 +00:00
Christophe Romain e6535dcc67 Check option of the nodetree instead of checking configuration
SVN Revision: 1738
2008-12-18 13:46:30 +00:00
Pablo Polvorin d3ddf10839 mod_muc_room.erl: Fix bug in MUC invite.
SVN Revision: 1736
2008-12-17 16:24:15 +00:00
Jean-Sébastien Pédron 69805f36fa Merge from trunk (r1730 to r1734).
PR:		EJABP-1

SVN Revision: 1735
2008-12-17 13:52:44 +00:00
Jean-Sébastien Pédron 6a3436b1c4 Merge from trunk (r1709 to r1730).
Ejabberd should be usable again.

PR:		EJABP-1

SVN Revision: 1731
2008-12-16 13:16:56 +00:00
Jean-Sébastien Pédron 62f9f6e6c5 Convert to exmpp the parts in mod_pubsub recently merged from trunk.
Warning: Ejabberd is unusable because the rest of trunk hasn't been
merged yet!

PR:		EJABP-1

SVN Revision: 1730
2008-12-16 10:31:08 +00:00
Christophe Romain 96aaba738b fix get_item_name deadlock on transaction
SVN Revision: 1729
2008-12-15 19:58:53 +00:00
Jean-Sébastien Pédron f83fc51960 Replace stringprep by exmpp_stringprep.
PR:		EJABP-1

SVN Revision: 1726
2008-12-10 14:44:08 +00:00
Christophe Romain e1575e3177 fix typo bug injected in r1712
SVN Revision: 1725
2008-12-09 22:42:34 +00:00
Christophe Romain 3d28a7837d minor bugfix
SVN Revision: 1723
2008-12-09 22:09:30 +00:00
Christophe Romain 44b4c29d08 lattest pubsub merge added in Changelog
SVN Revision: 1721
2008-12-09 00:35:27 +00:00
Christophe Romain 9f2fda6060 merge to lattest trunk r1716
SVN Revision: 1720
2008-12-09 00:32:36 +00:00
Jean-Sébastien Pédron 3bfb2b5cc1 Merge from trunk (r1692 to r1709).
PR:		EJABP-1

SVN Revision: 1710
2008-12-08 12:02:27 +00:00
Jean-Sébastien Pédron 82b97b9639 Finish the conversion of mod_pubsub to Exmpp.
PR:		EJABP-1

SVN Revision: 1709
2008-12-08 11:21:32 +00:00
Jean-Sébastien Pédron d01c24bd23 Fix acl:match_rule/3 call. It takes a #jid record, not a short JID.
PR:		EJABP-1

SVN Revision: 1708
2008-12-08 11:20:21 +00:00
Jean-Sébastien Pédron 163d185776 First pass of Exmpp conversion for mod_pubsub.
CAUTION:
o  Several modules aren't converted yet.
o  Existent Mnesia tables written to disc are not updated.
o  There must be bugs, mostly because of the mix between #jid record
and short JIDs.
PR:		EJABP-1

SVN Revision: 1705
2008-12-05 15:13:09 +00:00
Jean-Sébastien Pédron 6305ddca18 Add the module and function names to the error message, when a module
crash.

SVN Revision: 1704
2008-12-05 15:08:03 +00:00
Jean-Sébastien Pédron b82b66fdf0 Update Exmpp XML parser options.
SVN Revision: 1703
2008-12-05 15:06:49 +00:00
Jean-Sébastien Pédron b425093813 Convert mod_proxy65 to exmpp.
SVN Revision: 1701
2008-12-03 14:34:43 +00:00
Jean-Sébastien Pédron f30d2b9f1c Fix two warnings about unused variables.
PR:		EJABP-1

SVN Revision: 1696
2008-12-01 15:54:57 +00:00
Jean-Sébastien Pédron 9e96043255 Merge from trunk (r1649 to r1692).
PR:		EJABP-1

SVN Revision: 1695
2008-12-01 15:53:30 +00:00
Jean-Sébastien Pédron bd300e870c Convert mod_muc to Exmpp.
PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1692
2008-12-01 15:01:27 +00:00
Jean-Sébastien Pédron e06f533f6b Start the exmpp application.
PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1691
2008-12-01 15:00:36 +00:00
Jean-Sébastien Pédron 7088ba88a9 o In store_last_info/4, fix a bug where the status was not converted to
list before calling ejabberd_odbc:escape/1.
o  In get_last_info/2, fix a bug where the status was returned as a list
instead of a binary.

SVN Revision: 1690
2008-12-01 12:16:41 +00:00
Jean-Sébastien Pédron 0313adaec6 Convert to exmpp.
PR:		EJABP-1

SVN Revision: 1663
2008-10-20 10:34:00 +00:00
Jean-Sébastien Pédron 50b1e4c36f Convert to exmpp.
The admin web interface is working but HTTP polling seems broken in the
trunk.

PR:		EJABP-1

SVN Revision: 1654
2008-10-13 15:36:43 +00:00
Jean-Sébastien Pédron a94caf218f Remove all deprecated functions from jlib.
This was accidentally committed with the merge.

PR:		EJABP-1

SVN Revision: 1651
2008-10-13 11:43:33 +00:00
Jean-Sébastien Pédron ab2b70f189 Merge from trunk (r1613 to 1649).
PR:		EJABP-1

SVN Revision: 1650
2008-10-13 10:11:19 +00:00
Jean-Sébastien Pédron 3190c0ed6c Convert to exmpp.
PR:		EJABP-1

SVN Revision: 1649
2008-10-13 09:39:58 +00:00
Jean-Sébastien Pédron 461a5eb315 Convert to exmpp.
PR:		EJABP-1

SVN Revision: 1648
2008-10-13 09:39:18 +00:00
Jean-Sébastien Pédron 01ef834b82 Remove the deprecated list of converted modules.
PR:		EJABP-1

SVN Revision: 1647
2008-10-13 09:38:34 +00:00
Jean-Sébastien Pédron 0211c8145d Replace jlib:nameprep/1 by exmpp_stringprep:nameprep/1.
PR:		EJABP-1

SVN Revision: 1646
2008-10-13 09:37:48 +00:00
Jean-Sébastien Pédron 4a9892fa15 Replace jlib:nameprep/1 by exmpp_stringprep:nameprep/1 and change the
error handling.

PR:		EJABP-1

SVN Revision: 1628
2008-10-10 15:24:47 +00:00
Jean-Sébastien Pédron 71bfefa788 Convert to exmpp.
PR:		EJABP-1

SVN Revision: 1627
2008-10-10 15:23:58 +00:00
Jean-Sébastien Pédron 071c858055 Don't start stringprep_sup.
PR:		EJABP-1

SVN Revision: 1626
2008-10-10 14:58:35 +00:00
Jean-Sébastien Pédron 0244963935 Replace jlib:nameprep/1 by exmpp_stringprep:nameprep/1 and change the
error handling.

PR:		EJABP-1

SVN Revision: 1625
2008-10-10 14:57:44 +00:00
Jean-Sébastien Pédron 3adb238b31 Fix a bug where the wrong module was called (jlib instead of exmpp_jid).
PR:		EJABP-1

SVN Revision: 1624
2008-10-10 14:41:26 +00:00
Jean-Sébastien Pédron e3100110f0 Replace jlib:nameprep/1 by exmpp_stringprep:nameprep/1 and change the
error handling.

PR:		EJABP-1

SVN Revision: 1623
2008-10-10 14:40:04 +00:00
Jean-Sébastien Pédron 5224a796cc Replace jlib:iq_to_xml/1 by exmpp_iq:iq_to_xmlel/1.
PR:		EJABP-1

SVN Revision: 1622
2008-10-10 14:38:52 +00:00
Jean-Sébastien Pédron 285b3858dd Replace jlib:*prep/1 by exmpp_stringprep:*prep/1 and change the error
handling.

PR:		EJABP-1

SVN Revision: 1621
2008-10-10 14:37:26 +00:00
Jean-Sébastien Pédron 53bea055aa Remove a remaining jlib:jid_remove_resource/1 call.
PR:		EJABP-1

SVN Revision: 1620
2008-10-10 14:36:25 +00:00
Jean-Sébastien Pédron 129b0e99cf Replace jlib:nodeprep/1 by exmpp_stringprep:nodeprep/1 and change the
error handling.

PR:		EJABP-1

SVN Revision: 1619
2008-10-10 14:35:17 +00:00
Jean-Sébastien Pédron c0e4af9ac0 Replace jlib:nameprep/1 by exmpp_stringprep:nameprep/1 and change the
error handling.

PR:		EJABP-1

SVN Revision: 1618
2008-10-10 14:33:16 +00:00
Jean-Sébastien Pédron ccd94bb734 Fix a buf where a tuple was passed to exmpp_jid:jid_to_list/1 instead of
a #jid. Now we use exmpp_jid:jid_to_list/3.

PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1617
2008-10-10 08:16:29 +00:00
Jean-Sébastien Pédron e1b3bd611d Fix a bug where legacy authentication informations were not search among
the query children but among the IQ children.

PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1616
2008-10-10 08:14:08 +00:00
Jean-Sébastien Pédron 6ab7e339bd Fix handling of unauthenticated stanzas which are not request IQ.
PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1615
2008-10-09 11:54:42 +00:00
Jean-Sébastien Pédron 67a87af459 Merge from trunk (r1563 to r1613).
PR:		EJABP-1

SVN Revision: 1614
2008-10-08 12:02:30 +00:00
Jean-Sébastien Pédron aaecdc4b8a Convert to exmpp.
PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1611
2008-10-07 12:20:09 +00:00
Jean-Sébastien Pédron 78466384c4 Convert to exmpp.
PR:		EJABP-1

SVN Revision: 1610
2008-10-07 09:55:38 +00:00
Jean-Sébastien Pédron ca7a0813b4 Fix a bug where an error stanza was not created correctly, leading to
ejabberd_c2s crash.

PR:		EJABP-1

SVN Revision: 1609
2008-10-07 09:54:53 +00:00
Jean-Sébastien Pédron bc0d8613ab Fix status handling by always using binaries: until now, we were mixing
lists and binaries in a non-working way.

PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1608
2008-10-06 15:16:09 +00:00
Jean-Sébastien Pédron 0434c1424a The Mnesia table wasn't updated when converting from an old schema.
PR:		EJABP-1

SVN Revision: 1607
2008-10-06 15:14:01 +00:00
Jean-Sébastien Pédron 3f8a303286 Convert to exmpp.
PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1606
2008-10-06 15:01:36 +00:00
Jean-Sébastien Pédron 5ceffdd5a7 Fix a confusion between #jid and tuples.
PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1604
2008-10-06 15:00:34 +00:00
Jean-Sébastien Pédron 01da93bf70 mod_privacy & friends may return an empty list.
PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1603
2008-10-06 14:58:45 +00:00
Jean-Sébastien Pédron 028a3c2ded Fix a bug where we were matching on #iq.type instead of #iq.kind,
resulting in bad-request sent to the client.

PR:		EJABP-1

SVN Revision: 1602
2008-10-06 14:56:36 +00:00
Jean-Sébastien Pédron 1698b8ec04 o In start/2 and stop/1, the IQ registration must use a namespace as
atom, not list.
o  The functions process_local_iq/3, process_sm_iq/3 and get_last/3
receive an #iq, not an #xmlel.
o  In store_last_info/4 and remove_user/2, add try/catch block around
exmpp_stringprep:*prep/1 uses.

SVN Revision: 1594
2008-10-02 14:59:48 +00:00
Jean-Sébastien Pédron 9e018532c8 o In #jid, when the node isn't specified, it defaults to the atom
"undefined", not an empty binary.
o  Fix a bug where we expected an #xmlelement to have only one #xmlcdata
child.

SVN Revision: 1593
2008-10-02 13:52:39 +00:00
Jean-Sébastien Pédron 24cb7cb039 exmpp_xml:get_element_by_name/2 is deprecated; use
exmpp_xml:get_element/2 instead.

SVN Revision: 1592
2008-10-02 13:34:52 +00:00
Jean-Sébastien Pédron 7c28aba6a1 Fix a bug where a JID represented as a tuple was used in a function
expecting a #jid.

PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1591
2008-10-02 13:17:49 +00:00
Jean-Sébastien Pédron 2309f9b8bc Fix multiple bugs in ODBC mods.
PR:		EJABP-1
Submitted by:	Pablo Polvorin <pablo.polvorin@process-one.net>

SVN Revision: 1589
2008-10-01 09:41:57 +00:00
Jean-Sébastien Pédron ddcb94649d Fill exmpp_xml known list with the nss/names/attrs used by this module.
SVN Revision: 1585
2008-09-29 13:19:11 +00:00
Jean-Sébastien Pédron 5f7e16eac3 Add the {autoload_known, true} flag to the XML parser options. This
allows modules to extend the known nss/names/attrs with their own data.

SVN Revision: 1584
2008-09-29 13:17:21 +00:00
Jean-Sébastien Pédron da034b3090 Fix a bug in #xmlel construction: children must be a list.
SVN Revision: 1583
2008-09-29 11:30:25 +00:00
Jean-Sébastien Pédron 12d515a8fe Convert to exmpp (not tested yet).
SVN Revision: 1582
2008-09-29 11:29:09 +00:00
Jean-Sébastien Pédron f5f3c85112 Remove compatibility code (not tested yet).
SVN Revision: 1581
2008-09-29 10:38:04 +00:00
Jean-Sébastien Pédron d8153b702a o Add try/catch block around exmpp_stringprep:*prep/1 uses.
o  Add table conversion.
o  In get_last/3, do not convert status to binary because it's already
one.

SVN Revision: 1580
2008-09-29 10:34:06 +00:00
Jean-Sébastien Pédron 9a4f5bb2d9 When the status is not specified in a presence stanza, default to an
empty binary, not an empty string; this is what mod_last expects.

SVN Revision: 1579
2008-09-29 10:31:24 +00:00
Jean-Sébastien Pédron 7624284070 Remove compatilibity code.
SVN Revision: 1578
2008-09-29 09:42:46 +00:00
Jean-Sébastien Pédron c32cbd90e8 Fix a bug in parse_xdata_submit/1 and parse_xdata_fields/2 where
exmpp_xml:get_attribute_from_list/3 was called with only 2 arguments;
this code has not been updated when exmpp_xml's API changed...

SVN Revision: 1577
2008-09-29 09:42:05 +00:00
Jean-Sébastien Pédron c068d20588 In mod_offline:
o  Remove any compatibility code: the core of Ejabberd expects new
structures.
o  Add table conversion.
o  Add try/catch block around exmpp_stringprep:*prep/1 uses.

To permit the complete removal of the compatibility code, jlib had to be
changed too: the timestamp_to_xml/1 function now returns an #xmlel.

SVN Revision: 1575
2008-09-25 10:46:00 +00:00
Jean-Sébastien Pédron c74ab439ef Convert to exmpp.
SVN Revision: 1574
2008-09-23 13:11:05 +00:00
Jean-Sébastien Pédron 44c77364ce Fix a typo in the exmpp_stringprep module name.
SVN Revision: 1573
2008-09-23 13:10:33 +00:00
Jean-Sébastien Pédron 0dbbf53fbe o Fix a misuse of exmpp_stanza:error/2: the namespace argument (the
first one) was missing.
o  Fix a bug in process_privacy_iq/4 where the #iq record was not
converted back to an #xmlel before calling ejabberd_router:route/3.

SVN Revision: 1572
2008-09-23 13:09:32 +00:00
Jean-Sébastien Pédron 052d006c88 Fix a typo in the exmpp_stringprep module name.
SVN Revision: 1571
2008-09-23 13:06:45 +00:00
Jean-Sébastien Pédron 0e91ea9e5f o Fix a bug in process_sm_iq/3 where a badmatch exception was raised
when the user didn't have a vCard.
o  Fix a bug in remove_user/2 where the exmpp_jid module was use instead
of exmpp_stringprep.

SVN Revision: 1570
2008-09-23 13:05:43 +00:00
Jean-Sébastien Pédron 5803c51633 Convert to exmpp.
SVN Revision: 1568
2008-09-22 11:18:08 +00:00
Jean-Sébastien Pédron 35a7342416 o Remove unappropriate comments in get_sm_features/5.
o  Use the '_s' variants of NS_* macros instead of a call to
atom_to_list/1 in do_route/4.
o  A call to the stringprep module was left in filter_fields/3.

SVN Revision: 1567
2008-09-22 11:17:23 +00:00
Jean-Sébastien Pédron e9d7ac68da o Fix a bug in get_in_pending_subscriptions() where the type of the
presence stanza was lost.
o  Reorganize a few lines in user_roster() to match mod_roster_odbc.

SVN Revision: 1566
2008-09-18 14:55:43 +00:00
Jean-Sébastien Pédron 56a0c8ed1d Convert to exmpp.
SVN Revision: 1565
2008-09-18 14:55:03 +00:00
Jean-Sébastien Pédron 4eaa8e19c9 Merge from trunk (r1457 to r1563).
SVN Revision: 1564
2008-09-16 14:39:57 +00:00
Jean-Sébastien Pédron 414948d822 VCard are now stored as #xmlel. Mnesia tables are converted during
startup.

SVN Revision: 1553
2008-08-27 12:39:49 +00:00
Jean-Sébastien Pédron 02e6bf8759 handle_cast({disco_response, ...}, ...) now receives an #iq record:
update the code to handle this.

SVN Revision: 1552
2008-08-27 09:46:25 +00:00
Jean-Sébastien Pédron 8baed08641 Remove a debugging io:format/2.
SVN Revision: 1551
2008-08-27 09:45:01 +00:00
Jean-Sébastien Pédron 4e39f4cab1 o Remove compatibility code. Use the atom 'undefined' in JIDs (normal
and short).
o  Add try/catch blocks where Exmpp can raise exceptions.
o  Remove some unused code.
o  Convert on-disk Mnesia database: JIDs, extra XML elements and
askmessage are concerned.
o  By default, 'askmessage' is now an empty binary instead of an empty
string, for consistency's sake.
o  Fix some bugs.

SVN Revision: 1547
2008-08-26 13:59:04 +00:00
Jean-Sébastien Pédron 9f0d79da9a o Use the new functions from jlib.
o  Remove the compatibility code. It's becoming confusing to handle every
case every where. Also, in JIDs (normal and short), the atom "undefined'
is expected, not the empty string anymore!

SVN Revision: 1546
2008-08-26 13:38:49 +00:00
Jean-Sébastien Pédron 80fcd2eb56 Remove commented-out code and use proper variable names.
SVN Revision: 1545
2008-08-26 13:00:35 +00:00
Jean-Sébastien Pédron 5aead42964 Use the new short_prepd_jid/1 function from jlib.
SVN Revision: 1544
2008-08-26 12:58:13 +00:00
Jean-Sébastien Pédron ab75683bc9 short_jid/1 and short_bare_jid/1 now produce a short JID from the
user-provided JID parts. To obtain a short JID from the STRINGPREP'd
parts, use the new short_prepd_jid/1 and short_prepd_bare_jid/1
functions.

SVN Revision: 1543
2008-08-26 12:56:45 +00:00
Jean-Sébastien Pédron d8c3aae412 Convert to the new #iq record from Exmpp.
SVN Revision: 1524
2008-08-14 13:36:11 +00:00
Jean-Sébastien Pédron 5e78c53572 Remove the compatibility layer and always call modules with the new #iq
record from Exmpp.

SVN Revision: 1523
2008-08-14 13:34:30 +00:00
Jean-Sébastien Pédron 44d3e844a3 Accept 'undefined' as a language and treat it as the empty string.
SVN Revision: 1522
2008-08-14 13:32:31 +00:00
Jean-Sébastien Pédron 85c2097ece Update to use the new names used in exmpp_jid.
SVN Revision: 1515
2008-08-06 13:51:42 +00:00
Jean-Sébastien Pédron cb20c9b0d7 Update to use the new exmpp_xml:get_attribute/{3,4} API.
SVN Revision: 1514
2008-08-06 13:46:23 +00:00
Jean-Sébastien Pédron d9a493561b Convert to exmpp.
SVN Revision: 1513
2008-08-06 13:44:58 +00:00
Jean-Sébastien Pédron 70956ece12 Convert to exmpp.
SVN Revision: 1492
2008-07-25 14:26:59 +00:00
Jean-Sébastien Pédron adaf392156 o Finish conversion to exmpp for mod_caps.
o  In ejabberd_loca, IQ response handler are now always called with
arguments in the new format.

SVN Revision: 1469
2008-07-22 14:51:19 +00:00
Jean-Sébastien Pédron 37b99639d4 Convert to exmpp.
SVN Revision: 1468
2008-07-22 14:03:11 +00:00
Jean-Sébastien Pédron a8ab6c1568 Add support for #xmlel to parse_xdata_submit/1 and friends. This fixes
the user search in mod_vcard.

SVN Revision: 1466
2008-07-21 15:54:47 +00:00
Jean-Sébastien Pédron 4a1e45070e One call to jlib:jid_to_string/1 was remaining.
SVN Revision: 1465
2008-07-21 15:53:58 +00:00
Jean-Sébastien Pédron b33ac47228 Convert to exmpp.
SVN Revision: 1464
2008-07-21 15:30:32 +00:00
Jean-Sébastien Pédron 6e91399922 Convert to exmpp.
SVN Revision: 1463
2008-07-21 15:29:52 +00:00
Jean-Sébastien Pédron 75a8be230b Prepare gen_iq_handler to pass arguments in the new format to a built-in
list of modules known to support them. Other modules will still receive
arguments in the old format.

SVN Revision: 1462
2008-07-21 15:28:44 +00:00
Jean-Sébastien Pédron 07b1210b50 Merge revisions from 1444 to revision 1457 from trunk.
SVN Revision: 1458
2008-07-17 15:33:50 +00:00
Jean-Sébastien Pédron 532e8ee228 Start conversion to exmpp. For now, only direct calls from ejabberd_c2s
are done. Calls through gen_iq_handler aren't.

SVN Revision: 1457
2008-07-17 15:26:48 +00:00
Jean-Sébastien Pédron 574dbbfd08 Merge revisions from 1434 to revision 1444 from trunk.
SVN Revision: 1445
2008-07-15 08:45:05 +00:00
Jean-Sébastien Pédron 332fb55e3a MFC:
Merge revisions from 1362 to revision 1434 from trunk.

SVN Revision: 1435
2008-07-11 12:48:27 +00:00
Jean-Sébastien Pédron 5610d00b4d Convert to exmpp. Note that this module hasn't been tested yet!
SVN Revision: 1434
2008-07-11 12:41:48 +00:00
Jean-Sébastien Pédron 8bfccb42a9 Exmpp now takes care of stanza serialization and compatible namespaces.
SVN Revision: 1433
2008-07-11 12:40:49 +00:00
Jean-Sébastien Pédron 7ca5bebab3 Convert to exmpp.
SVN Revision: 1422
2008-07-09 09:16:03 +00:00
Jean-Sébastien Pédron d5aa4be7e5 Convert #xmlelement returned by the 'c2s_stream_features' hook to
#xmlel.

SVN Revision: 1421
2008-07-09 09:14:19 +00:00
Jean-Sébastien Pédron 1a687a4f1a SASL errors are now atoms, not strings anymore.
SVN Revision: 1420
2008-07-08 15:43:52 +00:00
Jean-Sébastien Pédron 13b78b1ad2 Routing is now done with #xmlel. A warning is printed if those modules
have to route an old #xmlelement.

SVN Revision: 1406
2008-07-01 15:51:34 +00:00
Jean-Sébastien Pédron 48cf5cb84a Do not use the #iq record anymore internally. However it's still created
and passed to other modules.

SVN Revision: 1405
2008-07-01 14:25:02 +00:00
Jean-Sébastien Pédron 5317dd64d7 Change warning message.
SVN Revision: 1404
2008-07-01 14:20:20 +00:00
Jean-Sébastien Pédron a25609f66b Accept new #xmlel in functions that create #iq. A warning is printed
when these functions are called with an old #xmlelement.

SVN Revision: 1403
2008-07-01 14:19:36 +00:00
Jean-Sébastien Pédron d6e6432a46 Convert to exmpp.
SVN Revision: 1402
2008-07-01 13:34:51 +00:00
Jean-Sébastien Pédron 094fa47f9f Convert gen_iq_handler to exmpp.
SVN Revision: 1401
2008-07-01 10:21:35 +00:00
Jean-Sébastien Pédron 6f7cf2e58b Use a function to convert to old structures instead of duplicating code
inside the module.

SVN Revision: 1400
2008-07-01 10:20:01 +00:00
Jean-Sébastien Pédron b08ae07347 acl doesn't require conversion anymore.
SVN Revision: 1399
2008-07-01 09:46:57 +00:00
Jean-Sébastien Pédron ffbf8d5faa Convert acl to exmpp.
SVN Revision: 1398
2008-07-01 09:41:32 +00:00
Jean-Sébastien Pédron f55274c7fb o Use jlib:short_bare_jid/1.
o  Rewrite is_auth_packet/1 to use new formats.
o  Don't convert <presence/> before calling ejabberd_sm:set_presence/7.
o  Don't convert broadcast children, because it's an internal special
element.

SVN Revision: 1397
2008-07-01 09:17:48 +00:00
Jean-Sébastien Pédron b9074097da Forgot to convert a <presence/> from the new to the old record.
SVN Revision: 1396
2008-07-01 09:13:49 +00:00
Jean-Sébastien Pédron 83a33726ce Add function short_bare_jid/1.
SVN Revision: 1395
2008-07-01 09:12:59 +00:00
Jean-Sébastien Pédron 8c33e12616 Use the new clause of exmpp_stanza:reply_with_error/2, exmpp_iq:error/2,
exmpp_iq:error_without_original/2 and the new exmpp_jid:make_bare_jid/1.

SVN Revision: 1394
2008-07-01 08:01:06 +00:00
Jean-Sébastien Pédron 87218e1447 Convert to exmpp.
SVN Revision: 1393
2008-07-01 07:49:57 +00:00
Jean-Sébastien Pédron 06965000a5 Before doing any routing, the router print a warning if old structures
are used. Then it converts the structures to the old format and route
them. The router doesn't care about the structures format but the
conversion is necesary for code called from this module.

In C2S and S2S, no conversion is done before calling
ejabberd_router:route/3.

SVN Revision: 1392
2008-06-30 16:55:03 +00:00
Jean-Sébastien Pédron cc033b3b98 o Use the new functions from jlib.
o  Use the new exmpp_xml:node_to_list/3.

SVN Revision: 1391
2008-06-30 15:51:23 +00:00
Jean-Sébastien Pédron 290040ad9d o Add function to convert to and from old ejabberd #jid record.
o  Move function short_jid/1 from ejabberd_c2s.

SVN Revision: 1390
2008-06-30 15:49:58 +00:00
Jean-Sébastien Pédron 264e72830b Convert to exmpp.
SVN Revision: 1389
2008-06-30 14:04:31 +00:00
Jean-Sébastien Pédron d05c2ee8a1 Use -include_lib instead of -include to include exmpp.hrl. This is a
better solution than specifying the path (with -I) on erlc(1) command
line.

SVN Revision: 1388
2008-06-30 12:13:15 +00:00
Jean-Sébastien Pédron b32aba27c1 o Use the new exmpp namespace macro names.
o  Update send_element/2 to use exmpp new to_list functions.

SVN Revision: 1384
2008-06-27 13:46:08 +00:00
Jean-Sébastien Pédron 22e79490ff Convert to exmpp.
SVN Revision: 1383
2008-06-26 15:48:19 +00:00
Jean-Sébastien Pédron 1a311a30b5 o Use a macro in ?DEFAULT_NS instead of the namespace atom directly.
o  Comment DBGFSM our again.
o  Remove macro ERR_SERVICE_UNAVAILABLE.
o  In wait_for_auth and is_auth_packet, an empty resource is returned as
'undefined', not the empty string in the {auth, ...} tuple.
o  In handle_sync_event, remove a debugging printf.
o  In handle_info({route, ...}), use macro IS_PRESENCE & friends instead
of direct matching with NS_JABBER_CLIENT and name. This way, the S2S
doesn't have to change the namespace of all its incoming stanzas to
NS_JABBER_CLIENT.
o  In send_element, for stanzas under the NS_JABBER_SERVER namespace, lie
to exmpp_xml by telling it that this namespace is the default one.

SVN Revision: 1382
2008-06-26 15:47:21 +00:00
Jean-Sébastien Pédron 999f3233bb Fix short JID comparison in get_subscribed_and_online; it was using
'undefined' instead of empty strings.

SVN Revision: 1381
2008-06-25 13:27:03 +00:00
Jean-Sébastien Pédron 07651d712f Finish ejabberd_c2s conversion with the functions related to offline
stanzas.

SVN Revision: 1380
2008-06-25 12:37:45 +00:00
Jean-Sébastien Pédron 6f931ce4fd Convert all presence-related functions.
SVN Revision: 1378
2008-06-24 16:12:56 +00:00
Jean-Sébastien Pédron e93e846e16 o Use the new exmpp_stream:opening_reply/3 function in wait_for_stream/2.
o  The function terminate/3 is converted to exmpp.

SVN Revision: 1377
2008-06-24 09:44:56 +00:00
Jean-Sébastien Pédron 4e2e68a3fb The handle_info clause that treats routing order is now converted.
In-memory sets and dict still use the short JID form with empty strings
for unspecified fields. Users are able to connect to ejabberd but some
features don't seem to work proprerly.

SVN Revision: 1376
2008-06-24 08:55:24 +00:00
Jean-Sébastien Pédron e95df7999f Convert JID to the expected form outside of the C2S (empty fields must
be set to the empty string). This fixes the broken routing.

SVN Revision: 1375
2008-06-23 11:47:10 +00:00
Jean-Sébastien Pédron 2a43998444 o Change the usage of #state.lang somewhat.
o  Fix value of DefaultLang: it doesn't contain the whole serialized
attribute.
o  Use exmpp_jid:make_bare_jid/2 more.

I started to work on the second half of the module and discovered
several annoying things:
o  JID are represented in two forms: the #jid record and the
{N, D, R} tuple.
o  Sometimes, #xmlelement may contain non-#xml* tuples in their
children. This is the case for some <presence/> stanzas. Their
children are used to pass random data.
I'm less and less convicted that ejabberd_c2s can be fully converted
without starting to work on other modules.

SVN Revision: 1370
2008-06-20 14:54:59 +00:00
Jean-Sébastien Pédron 06eea52ad8 Update the svn:ignore property.
SVN Revision: 1369
2008-06-20 12:56:39 +00:00
Jean-Sébastien Pédron 389b5e6448 First bunch of modifications to use exmpp. All FSM state function are
updated. But other functions are not for now.

Users are able to connect to ejabberd but some features may not work.

SVN Revision: 1368
2008-06-20 12:52:29 +00:00
Jean-Sébastien Pédron a19f280fcc Enable the new #xmlel record.
SVN Revision: 1367
2008-06-20 12:50:20 +00:00
Jean-Sébastien Pédron e4646a6788 Add exmpp detection.
SVN Revision: 1366
2008-06-20 12:49:39 +00:00
Jean-Sébastien Pédron 58bfea2ad1 Replace the use of xml_stream by exmpp_xmlstream. exmpp_xml is
configured to produce old #xmlelement records. exmpp_xmlstream is
configured to send old xmlstreamstart tuple.

Users are able to connect to ejabberd. 

Next step: ejabberd_c2s.

SVN Revision: 1365
2008-06-19 10:23:52 +00:00
Jean-Sébastien Pédron ad4a1c2a59 Create a branch "road-to-exmpp". This is a development branch that
will receive all the changes to make ejabberd use the new "exmpp"
application.

SVN Revision: 1362
2008-06-19 08:48:45 +00:00
338 changed files with 59365 additions and 61622 deletions
+38
View File
@@ -0,0 +1,38 @@
#
# You can add personal rules in your file .git/info/exclude
*.swp
*~
/doc/*.aux
/doc/*.haux
/doc/*.html
/doc/*.htoc
/doc/*.idx
/doc/*.ilg
/doc/*.ind
/doc/*.log
/doc/*.out
/doc/*.pdf
/doc/*.toc
/doc/contributed_modules.tex
/doc/version.tex
/src/*.beam
/src/*.so
/src/*.so.dSYM
/src/*/*.beam
/src/*/Makefile
/src/Makefile
/src/XmppAddr.asn1db
/src/XmppAddr.erl
/src/XmppAddr.hrl
/src/aclocal.m4
/src/autom4te.cache
/src/config.log
/src/config.status
/src/configure
/src/ejabberd.init
/src/ejabberdctl.example
/src/eldap/ELDAPv3.asn1db
/src/eldap/ELDAPv3.erl
/src/eldap/ELDAPv3.hrl
/src/eldap/eldap_filter_yecc.erl
/src/epam
+12 -9
View File
@@ -8,20 +8,17 @@ Quickstart guide
To compile ejabberd you need:
- GNU Make
- GCC
- Libexpat 1.95 or higher
- Erlang/OTP R10B-9 or higher. The recommended version is R12B-5.
Support for R13 is experimental.
- OpenSSL 0.9.6 or higher, for STARTTLS, SASL and SSL
encryption. Optional, highly recommended.
- Erlang/OTP R12B-5 or higher. Recommended: R12B-5, R13B04 and R14B01.
Avoid R14A and R14B.
- exmpp 0.9.6 or higher
- OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption.
- Zlib 1.2.3 or higher, for Stream Compression support
(XEP-0138). Optional.
- Erlang mysql library. Optional. MySQL authentication/storage.
- Erlang pgsql library. Optional. PostgreSQL authentication/storage.
- PAM library. Optional. For Pluggable Authentication Modules (PAM).
- GNU Iconv 1.8 or higher, for the IRC Transport
(mod_irc). Optional. Not needed on systems with GNU Libc.
- ImageMagicks Convert program. Optional. For CAPTCHA challenges.
- exmpp 0.9.1 or higher. Optional. For import/export XEP-0227 files.
- ESASL library. Optional. For SASL GSSAPI authentication.
- ImageMagick's Convert program. Optional. For CAPTCHA challenges.
1. Compile and install on *nix systems
@@ -30,6 +27,12 @@ To compile ejabberd, go to the directory src/ and execute the commands:
./configure
make
If you get an error like:
./configure: No such file or directory
the solution is to first execute:
aclocal
autoconf
To install ejabberd, run this command with system administrator rights
(root user):
+2 -3
View File
@@ -1,5 +1,3 @@
# $Id$
SHELL = /bin/bash
CONTRIBUTED_MODULES = ""
@@ -16,7 +14,7 @@ release:
@echo "* Do not forget to update the version number in src/ejabberd.app!"
@echo "* Do not forget to update the features in introduction.tex (including \new{} and \improved{} tags)."
@echo "Press any key to continue"
@read foo
##@read foo
@echo "% ejabberd version (automatically generated)." > version.tex
@echo "\newcommand{\version}{"`sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../src/ejabberd.app`"}" >> version.tex
@echo -n "% Contributed modules (automatically generated)." > contributed_modules.tex
@@ -37,6 +35,7 @@ clean:
rm -f *.out
rm -f *.pdf
rm -f *.toc
rm -f version.tex
[ ! -f contributed_modules.tex ] || rm contributed_modules.tex
distclean: clean
-10
View File
@@ -1,10 +0,0 @@
@author Mickael Remond <mickael.remond@process-one.net>
[http://www.process-one.net/]
@copyright 2007 ProcessOne
@version {@vsn}, {@date} {@time}
@title ejabberd Development API Documentation
@doc
== Introduction ==
TODO: Insert content from Jerome documentation.
-410
View File
@@ -1,410 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<TITLE>Ejabberd 2.1.0 Developers Guide
</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<META name="GENERATOR" content="hevea 1.10">
<STYLE type="text/css">
.li-itemize{margin:1ex 0ex;}
.li-enumerate{margin:1ex 0ex;}
.dd-description{margin:0ex 0ex 1ex 4ex;}
.dt-description{margin:0ex;}
.toc{list-style:none;}
.thefootnotes{text-align:left;margin:0ex;}
.dt-thefootnotes{margin:0em;}
.dd-thefootnotes{margin:0em 0em 0em 2em;}
.footnoterule{margin:1em auto 1em 0px;width:50%;}
.caption{padding-left:2ex; padding-right:2ex; margin-left:auto; margin-right:auto}
.title{margin:2ex auto;text-align:center}
.center{text-align:center;margin-left:auto;margin-right:auto;}
.flushleft{text-align:left;margin-left:0ex;margin-right:auto;}
.flushright{text-align:right;margin-left:auto;margin-right:0ex;}
DIV TABLE{margin-left:inherit;margin-right:inherit;}
PRE{text-align:left;margin-left:0ex;margin-right:auto;}
BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;}
TD P{margin:0px;}
.boxed{border:1px solid black}
.textboxed{border:1px solid black}
.vbar{border:none;width:2px;background-color:black;}
.hbar{border:none;height:2px;width:100%;background-color:black;}
.hfill{border:none;height:1px;width:200%;background-color:black;}
.vdisplay{border-collapse:separate;border-spacing:2px;width:auto; empty-cells:show; border:2px solid red;}
.vdcell{white-space:nowrap;padding:0px;width:auto; border:2px solid green;}
.display{border-collapse:separate;border-spacing:2px;width:auto; border:none;}
.dcell{white-space:nowrap;padding:0px;width:auto; border:none;}
.dcenter{margin:0ex auto;}
.vdcenter{border:solid #FF8000 2px; margin:0ex auto;}
.minipage{text-align:left; margin-left:0em; margin-right:auto;}
.marginpar{border:solid thin black; width:20%; text-align:left;}
.marginparleft{float:left; margin-left:0ex; margin-right:1ex;}
.marginparright{float:right; margin-left:1ex; margin-right:0ex;}
.theorem{text-align:left;margin:1ex auto 1ex 0ex;}
.part{margin:2ex auto;text-align:center}
</STYLE>
</HEAD>
<BODY >
<!--HEVEA command line is: /usr/bin/hevea -fix -pedantic dev.tex -->
<!--CUT DEF section 1 --><P><A NAME="titlepage"></A>
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.1.0 Developers Guide</H1><H3 CLASS="titlerest">Alexey Shchepin<BR>
<A HREF="mailto:alexey@sevcom.net"><TT>mailto:alexey@sevcom.net</TT></A><BR>
<A HREF="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT></A></H3></TD></TR>
</TABLE><DIV CLASS="center">
<IMG SRC="logo.png" ALT="logo.png">
</DIV><BLOCKQUOTE CLASS="quotation"><I>I can thoroughly recommend ejabberd for ease of setup &#X2013;
Kevin Smith, Current maintainer of the Psi project</I></BLOCKQUOTE><!--TOC section Contents-->
<H2 CLASS="section"><!--SEC ANCHOR -->Contents</H2><!--SEC END --><UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc1">1&#XA0;&#XA0;Key Features</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc2">2&#XA0;&#XA0;Additional Features</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc3">3&#XA0;&#XA0;How it Works</A>
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc4">3.1&#XA0;&#XA0;Router</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc5">3.2&#XA0;&#XA0;Local Router</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc6">3.3&#XA0;&#XA0;Session Manager</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc7">3.4&#XA0;&#XA0;S2S Manager</A>
</LI></UL>
</LI><LI CLASS="li-toc"><A HREF="#htoc8">4&#XA0;&#XA0;Authentication</A>
<UL CLASS="toc">
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc9">4.0.1&#XA0;&#XA0;External</A>
</LI></UL>
</UL>
</LI><LI CLASS="li-toc"><A HREF="#htoc10">5&#XA0;&#XA0;XML Representation</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc11">6&#XA0;&#XA0;Module <TT>xml</TT></A>
</LI><LI CLASS="li-toc"><A HREF="#htoc12">7&#XA0;&#XA0;Module <TT>xml_stream</TT></A>
</LI><LI CLASS="li-toc"><A HREF="#htoc13">8&#XA0;&#XA0;Modules</A>
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc14">8.1&#XA0;&#XA0;Module gen_iq_handler</A>
</LI><LI CLASS="li-toc"><A HREF="#htoc15">8.2&#XA0;&#XA0;Services</A>
</LI></UL>
</LI></UL><P>Introduction
<A NAME="intro"></A></P><P><TT>ejabberd</TT> is a free and open source instant messaging server written in <A HREF="http://www.erlang.org/">Erlang/OTP</A>.</P><P><TT>ejabberd</TT> is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication.</P><P><TT>ejabberd</TT> is designed to be a rock-solid and feature rich XMPP server.</P><P><TT>ejabberd</TT> is suitable for small deployments, whether they need to be scalable or not, as well as extremely big deployments.</P><!--TOC section Key Features-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc1">1</A>&#XA0;&#XA0;Key Features</H2><!--SEC END --><P>
<A NAME="keyfeatures"></A>
</P><P><TT>ejabberd</TT> is:
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
Cross-platform: <TT>ejabberd</TT> runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.</LI><LI CLASS="li-itemize">Distributed: You can run <TT>ejabberd</TT> on a cluster of machines and all of them will serve the same Jabber domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.</LI><LI CLASS="li-itemize">Fault-tolerant: You can deploy an <TT>ejabberd</TT> cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced &#X2018;on the fly&#X2019;.</LI><LI CLASS="li-itemize">Administrator Friendly: <TT>ejabberd</TT> is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Comprehensive documentation.
</LI><LI CLASS="li-itemize">Straightforward installers for Linux, Mac OS X, and Windows. </LI><LI CLASS="li-itemize">Web Administration.
</LI><LI CLASS="li-itemize">Shared Roster Groups.
</LI><LI CLASS="li-itemize">Command line administration tool. </LI><LI CLASS="li-itemize">Can integrate with existing authentication mechanisms.
</LI><LI CLASS="li-itemize">Capability to send announce messages.
</LI></UL></LI><LI CLASS="li-itemize">Internationalized: <TT>ejabberd</TT> leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Translated to 25 languages. </LI><LI CLASS="li-itemize">Support for <A HREF="http://www.ietf.org/rfc/rfc3490.txt">IDNA</A>.
</LI></UL></LI><LI CLASS="li-itemize">Open Standards: <TT>ejabberd</TT> is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
<UL CLASS="itemize"><LI CLASS="li-itemize">
Fully XMPP compliant.
</LI><LI CLASS="li-itemize">XML-based protocol.
</LI><LI CLASS="li-itemize"><A HREF="http://www.ejabberd.im/protocols">Many protocols supported</A>.
</LI></UL></LI></UL><!--TOC section Additional Features-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc2">2</A>&#XA0;&#XA0;Additional Features</H2><!--SEC END --><P>
<A NAME="addfeatures"></A>
</P><P>Moreover, <TT>ejabberd</TT> comes with a wide range of other state-of-the-art features:
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
Modular
<UL CLASS="itemize"><LI CLASS="li-itemize">
Load only the modules you want.
</LI><LI CLASS="li-itemize">Extend <TT>ejabberd</TT> with your own custom modules.
</LI></UL>
</LI><LI CLASS="li-itemize">Security
<UL CLASS="itemize"><LI CLASS="li-itemize">
SASL and STARTTLS for c2s and s2s connections.
</LI><LI CLASS="li-itemize">STARTTLS and Dialback s2s connections.
</LI><LI CLASS="li-itemize">Web Admin accessible via HTTPS secure access.
</LI></UL>
</LI><LI CLASS="li-itemize">Databases
<UL CLASS="itemize"><LI CLASS="li-itemize">
Internal database for fast deployment (Mnesia).
</LI><LI CLASS="li-itemize">Native MySQL support.
</LI><LI CLASS="li-itemize">Native PostgreSQL support.
</LI><LI CLASS="li-itemize">ODBC data storage support.
</LI><LI CLASS="li-itemize">Microsoft SQL Server support. </LI></UL>
</LI><LI CLASS="li-itemize">Authentication
<UL CLASS="itemize"><LI CLASS="li-itemize">
Internal Authentication.
</LI><LI CLASS="li-itemize">PAM, LDAP and ODBC. </LI><LI CLASS="li-itemize">External Authentication script.
</LI></UL>
</LI><LI CLASS="li-itemize">Others
<UL CLASS="itemize"><LI CLASS="li-itemize">
Support for virtual hosting.
</LI><LI CLASS="li-itemize">Compressing XML streams with Stream Compression (<A HREF="http://www.xmpp.org/extensions/xep-0138.html">XEP-0138</A>).
</LI><LI CLASS="li-itemize">Statistics via Statistics Gathering (<A HREF="http://www.xmpp.org/extensions/xep-0039.html">XEP-0039</A>).
</LI><LI CLASS="li-itemize">IPv6 support both for c2s and s2s connections.
</LI><LI CLASS="li-itemize"><A HREF="http://www.xmpp.org/extensions/xep-0045.html">Multi-User Chat</A> module with support for clustering and HTML logging. </LI><LI CLASS="li-itemize">Users Directory based on users vCards.
</LI><LI CLASS="li-itemize"><A HREF="http://www.xmpp.org/extensions/xep-0060.html">Publish-Subscribe</A> component with support for <A HREF="http://www.xmpp.org/extensions/xep-0163.html">Personal Eventing via Pubsub</A>.
</LI><LI CLASS="li-itemize">Support for web clients: <A HREF="http://www.xmpp.org/extensions/xep-0025.html">HTTP Polling</A> and <A HREF="http://www.xmpp.org/extensions/xep-0206.html">HTTP Binding (BOSH)</A> services.
</LI><LI CLASS="li-itemize">IRC transport.
</LI><LI CLASS="li-itemize">Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
</LI></UL>
</LI></UL><!--TOC section How it Works-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc3">3</A>&#XA0;&#XA0;How it Works</H2><!--SEC END --><P>
<A NAME="howitworks"></A></P><P>A XMPP domain is served by one or more <TT>ejabberd</TT> nodes. These nodes can
be run on different machines that are connected via a network. They all must
have the ability to connect to port 4369 of all another nodes, and must have
the same magic cookie (see Erlang/OTP documentation, in other words the file
<TT>~ejabberd/.erlang.cookie</TT> must be the same on all nodes). This is
needed because all nodes exchange information about connected users, S2S
connections, registered services, etc&#X2026;</P><P>Each <TT>ejabberd</TT> node have following modules:
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
router;
</LI><LI CLASS="li-itemize">local router.
</LI><LI CLASS="li-itemize">session manager;
</LI><LI CLASS="li-itemize">S2S manager;
</LI></UL><!--TOC subsection Router-->
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc4">3.1</A>&#XA0;&#XA0;Router</H3><!--SEC END --><P>This module is the main router of XMPP packets on each node. It routes
them based on their destinations domains. It has two tables: local and global
routes. First, domain of packet destination searched in local table, and if it
found, then the packet is routed to appropriate process. If no, then it
searches in global table, and is routed to the appropriate <TT>ejabberd</TT> node or
process. If it does not exists in either tables, then it sent to the S2S
manager.</P><!--TOC subsection Local Router-->
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc5">3.2</A>&#XA0;&#XA0;Local Router</H3><!--SEC END --><P>This module routes packets which have a destination domain equal to this server
name. If destination JID has a non-empty user part, then it routed to the
session manager, else it is processed depending on it&#X2019;s content.</P><!--TOC subsection Session Manager-->
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc6">3.3</A>&#XA0;&#XA0;Session Manager</H3><!--SEC END --><P>This module routes packets to local users. It searches for what user resource
packet must be sended via presence table. If this resource is connected to
this node, it is routed to C2S process, if it connected via another node, then
the packet is sent to session manager on that node.</P><!--TOC subsection S2S Manager-->
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc7">3.4</A>&#XA0;&#XA0;S2S Manager</H3><!--SEC END --><P>This module routes packets to other XMPP servers. First, it checks if an
open S2S connection from the domain of the packet source to the domain of
packet destination already exists. If it is open on another node, then it
routes the packet to S2S manager on that node, if it is open on this node, then
it is routed to the process that serves this connection, and if a connection
does not exist, then it is opened and registered.</P><!--TOC section Authentication-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc8">4</A>&#XA0;&#XA0;Authentication</H2><!--SEC END --><!--TOC subsubsection External-->
<H4 CLASS="subsubsection"><!--SEC ANCHOR --><A NAME="htoc9">4.0.1</A>&#XA0;&#XA0;External</H4><!--SEC END --><P>
<A NAME="externalauth"></A>
</P><P>The external authentication script follows
<A HREF="http://www.erlang.org/doc/tutorial/c_portdriver.html">the erlang port driver API</A>.</P><P>That script is supposed to do theses actions, in an infinite loop:
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
read from stdin: AABBBBBBBBB.....
<UL CLASS="itemize"><LI CLASS="li-itemize">
A: 2 bytes of length data (a short in network byte order)
</LI><LI CLASS="li-itemize">B: a string of length found in A that contains operation in plain text
operation are as follows:
<UL CLASS="itemize"><LI CLASS="li-itemize">
auth:User:Server:Password (check if a username/password pair is correct)
</LI><LI CLASS="li-itemize">isuser:User:Server (check if it&#X2019;s a valid user)
</LI><LI CLASS="li-itemize">setpass:User:Server:Password (set user&#X2019;s password)
</LI></UL>
</LI></UL>
</LI><LI CLASS="li-itemize">write to stdout: AABB
<UL CLASS="itemize"><LI CLASS="li-itemize">
A: the number 2 (coded as a short, which is bytes length of following result)
</LI><LI CLASS="li-itemize">B: the result code (coded as a short), should be 1 for success/valid, or 0 for failure/invalid
</LI></UL>
</LI></UL><P>Example python script
</P><PRE CLASS="verbatim">#!/usr/bin/python
import sys
from struct import *
def from_ejabberd():
input_length = sys.stdin.read(2)
(size,) = unpack('&gt;h', input_length)
return sys.stdin.read(size).split(':')
def to_ejabberd(bool):
answer = 0
if bool:
answer = 1
token = pack('&gt;hh', 2, answer)
sys.stdout.write(token)
sys.stdout.flush()
def auth(username, server, password):
return True
def isuser(username, server):
return True
def setpass(username, server, password):
return True
while True:
data = from_ejabberd()
success = False
if data[0] == "auth":
success = auth(data[1], data[2], data[3])
elif data[0] == "isuser":
success = isuser(data[1], data[2])
elif data[0] == "setpass":
success = setpass(data[1], data[2], data[3])
to_ejabberd(success)
</PRE><!--TOC section XML Representation-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc10">5</A>&#XA0;&#XA0;XML Representation</H2><!--SEC END --><P>
<A NAME="xmlrepr"></A></P><P>Each XML stanza is represented as the following tuple:
</P><PRE CLASS="verbatim">XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
Name = string()
Attrs = [Attr]
Attr = {Key, Val}
Key = string()
Val = string()
ElementOrCDATA = XMLElement | CDATA
CDATA = {xmlcdata, string()}
</PRE><P>E.&#XA0;g. this stanza:
</P><PRE CLASS="verbatim">&lt;message to='test@conference.example.org' type='groupchat'&gt;
&lt;body&gt;test&lt;/body&gt;
&lt;/message&gt;
</PRE><P>is represented as the following structure:
</P><PRE CLASS="verbatim">{xmlelement, "message",
[{"to", "test@conference.example.org"},
{"type", "groupchat"}],
[{xmlelement, "body",
[],
[{xmlcdata, "test"}]}]}}
</PRE><!--TOC section Module <TT>xml</TT>-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc11">6</A>&#XA0;&#XA0;Module <TT>xml</TT></H2><!--SEC END --><P>
<A NAME="xmlmod"></A></P><DL CLASS="description"><DT CLASS="dt-description">
</DT><DD CLASS="dd-description"><CODE>element_to_string(El) -&gt; string()</CODE>
<PRE CLASS="verbatim">El = XMLElement
</PRE>Returns string representation of XML stanza <TT>El</TT>.</DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description"><CODE>crypt(S) -&gt; string()</CODE>
<PRE CLASS="verbatim">S = string()
</PRE>Returns string which correspond to <TT>S</TT> with encoded XML special
characters.</DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description"><CODE>remove_cdata(ECList) -&gt; EList</CODE>
<PRE CLASS="verbatim">ECList = [ElementOrCDATA]
EList = [XMLElement]
</PRE><TT>EList</TT> is a list of all non-CDATA elements of ECList.</DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description"><CODE>get_path_s(El, Path) -&gt; Res</CODE>
<PRE CLASS="verbatim">El = XMLElement
Path = [PathItem]
PathItem = PathElem | PathAttr | PathCDATA
PathElem = {elem, Name}
PathAttr = {attr, Name}
PathCDATA = cdata
Name = string()
Res = string() | XMLElement
</PRE>If <TT>Path</TT> is empty, then returns <TT>El</TT>. Else sequentially
consider elements of <TT>Path</TT>. Each element is one of:
<DL CLASS="description"><DT CLASS="dt-description">
</DT><DD CLASS="dd-description"><CODE>{elem, Name}</CODE> <TT>Name</TT> is name of subelement of
<TT>El</TT>, if such element exists, then this element considered in
following steps, else returns empty string.
</DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description"><CODE>{attr, Name}</CODE> If <TT>El</TT> have attribute <TT>Name</TT>, then
returns value of this attribute, else returns empty string.
</DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description"><CODE>cdata</CODE> Returns CDATA of <TT>El</TT>.
</DD></DL></DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description">TODO:
<PRE CLASS="verbatim"> get_cdata/1, get_tag_cdata/1
get_attr/2, get_attr_s/2
get_tag_attr/2, get_tag_attr_s/2
get_subtag/2
</PRE></DD></DL><!--TOC section Module <TT>xml_stream</TT>-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc12">7</A>&#XA0;&#XA0;Module <TT>xml_stream</TT></H2><!--SEC END --><P>
<A NAME="xmlstreammod"></A></P><DL CLASS="description"><DT CLASS="dt-description">
</DT><DD CLASS="dd-description"><CODE>parse_element(Str) -&gt; XMLElement | {error, Err}</CODE>
<PRE CLASS="verbatim">Str = string()
Err = term()
</PRE>Parses <TT>Str</TT> using XML parser, returns either parsed element or error
tuple.
</DD></DL><!--TOC section Modules-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc13">8</A>&#XA0;&#XA0;Modules</H2><!--SEC END --><P>
<A NAME="emods"></A></P><!--TOC subsection Module gen_iq_handler-->
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc14">8.1</A>&#XA0;&#XA0;Module gen_iq_handler</H3><!--SEC END --><P>
<A NAME="geniqhandl"></A></P><P>The module <CODE>gen_iq_handler</CODE> allows to easily write handlers for IQ packets
of particular XML namespaces that addressed to server or to users bare JIDs.</P><P>In this module the following functions are defined:
</P><DL CLASS="description"><DT CLASS="dt-description">
</DT><DD CLASS="dd-description"><CODE>add_iq_handler(Component, Host, NS, Module, Function, Type)</CODE>
<PRE CLASS="verbatim">Component = Module = Function = atom()
Host = NS = string()
Type = no_queue | one_queue | parallel
</PRE>Registers function <CODE>Module:Function</CODE> as handler for IQ packets on
virtual host <CODE>Host</CODE> that contain child of namespace <CODE>NS</CODE> in
<CODE>Component</CODE>. Queueing discipline is <CODE>Type</CODE>. There are at least
two components defined:
<DL CLASS="description"><DT CLASS="dt-description">
</DT><DD CLASS="dd-description"><CODE>ejabberd_local</CODE> Handles packets that addressed to server JID;
</DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description"><CODE>ejabberd_sm</CODE> Handles packets that addressed to users bare JIDs.
</DD></DL>
</DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description"><CODE>remove_iq_handler(Component, Host, NS)</CODE>
<PRE CLASS="verbatim">Component = atom()
Host = NS = string()
</PRE>Removes IQ handler on virtual host <CODE>Host</CODE> for namespace <CODE>NS</CODE> from
<CODE>Component</CODE>.
</DD></DL><P>Handler function must have the following type:
</P><DL CLASS="description"><DT CLASS="dt-description">
</DT><DD CLASS="dd-description"><CODE>Module:Function(From, To, IQ)</CODE>
<PRE CLASS="verbatim">From = To = jid()
</PRE></DD></DL><PRE CLASS="verbatim">-module(mod_cputime).
-behaviour(gen_mod).
-export([start/2,
stop/1,
process_local_iq/3]).
-include("ejabberd.hrl").
-include("jlib.hrl").
-define(NS_CPUTIME, "ejabberd:cputime").
start(Host, Opts) -&gt;
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_CPUTIME,
?MODULE, process_local_iq, IQDisc).
stop(Host) -&gt;
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_CPUTIME).
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -&gt;
case Type of
set -&gt;
{iq, ID, error, XMLNS,
[SubEl, ?ERR_NOT_ALLOWED]};
get -&gt;
CPUTime = element(1, erlang:statistics(runtime))/1000,
SCPUTime = lists:flatten(io_lib:format("~.3f", CPUTime)),
{iq, ID, result, XMLNS,
[{xmlelement, "query",
[{"xmlns", ?NS_CPUTIME}],
[{xmlelement, "cputime", [], [{xmlcdata, SCPUTime}]}]}]}
end.
</PRE><!--TOC subsection Services-->
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc15">8.2</A>&#XA0;&#XA0;Services</H3><!--SEC END --><P>
<A NAME="services"></A></P><PRE CLASS="verbatim">-module(mod_echo).
-behaviour(gen_mod).
-export([start/2, init/1, stop/1]).
-include("ejabberd.hrl").
-include("jlib.hrl").
start(Host, Opts) -&gt;
MyHost = gen_mod:get_opt(host, Opts, "echo." ++ Host),
register(gen_mod:get_module_proc(Host, ?PROCNAME),
spawn(?MODULE, init, [MyHost])).
init(Host) -&gt;
ejabberd_router:register_local_route(Host),
loop(Host).
loop(Host) -&gt;
receive
{route, From, To, Packet} -&gt;
ejabberd_router:route(To, From, Packet),
loop(Host);
stop -&gt;
ejabberd_router:unregister_route(Host),
ok;
_ -&gt;
loop(Host)
end.
stop(Host) -&gt;
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
Proc ! stop,
{wait, Proc}.
</PRE><!--CUT END -->
<!--HTMLFOOT-->
<!--ENDHTML-->
<!--FOOTER-->
<HR SIZE=2><BLOCKQUOTE CLASS="quote"><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
</EM><A HREF="http://hevea.inria.fr/index.html"><EM>H</EM><EM><FONT SIZE=2><sup>E</sup></FONT></EM><EM>V</EM><EM><FONT SIZE=2><sup>E</sup></FONT></EM><EM>A</EM></A><EM>.</EM></BLOCKQUOTE></BODY>
</HTML>
+3 -4
View File
@@ -37,24 +37,20 @@
\newcommand{\modecho}{\module{mod\_echo}}
\newcommand{\modirc}{\module{mod\_irc}}
\newcommand{\modlast}{\module{mod\_last}}
\newcommand{\modlastodbc}{\module{mod\_last\_odbc}}
\newcommand{\modmuc}{\module{mod\_muc}}
\newcommand{\modmuclog}{\module{mod\_muc\_log}}
\newcommand{\modoffline}{\module{mod\_offline}}
\newcommand{\modofflineodbc}{\module{mod\_offline\_odbc}}
\newcommand{\modprivacy}{\module{mod\_privacy}}
\newcommand{\modprivate}{\module{mod\_private}}
\newcommand{\modpubsub}{\module{mod\_pubsub}}
\newcommand{\modregister}{\module{mod\_register}}
\newcommand{\modroster}{\module{mod\_roster}}
\newcommand{\modrosterodbc}{\module{mod\_roster\_odbc}}
\newcommand{\modservicelog}{\module{mod\_service\_log}}
\newcommand{\modsharedroster}{\module{mod\_shared\_roster}}
\newcommand{\modstats}{\module{mod\_stats}}
\newcommand{\modtime}{\module{mod\_time}}
\newcommand{\modvcard}{\module{mod\_vcard}}
\newcommand{\modvcardldap}{\module{mod\_vcard\_ldap}}
\newcommand{\modvcardodbc}{\module{mod\_vcard\_odbc}}
\newcommand{\modversion}{\module{mod\_version}}
%% Title page
@@ -176,6 +172,9 @@ That script is supposed to do theses actions, in an infinite loop:
\item auth:User:Server:Password (check if a username/password pair is correct)
\item isuser:User:Server (check if it's a valid user)
\item setpass:User:Server:Password (set user's password)
\item tryregister:User:Server:Password (try to register an account)
\item removeuser:User:Server (remove this account)
\item removeuser3:User:Server:Password (remove this account if the password is correct)
\end{itemize}
\end{itemize}
\item write to stdout: AABB
+1 -1
View File
@@ -15,4 +15,4 @@ clean:
docs:
erl -noshell -run edoc_run application \
"'$(APPNAME)'" '"$(SRCDIR)"' '[{dir,"$(DOCDIR)"},{packages, false},{todo,true},{private,true},{def,{vsn,"$(VSN)"}},{stylesheet,"process-one.css"},{overview,"$(DOCDIR)/overview.edoc"}]' -s init stop
"'$(APPNAME)'" '"$(SRCDIR)"' '[{dir,"$(DOCDIR)"},{packages, false},{todo,false},{private,true},{def,{vsn,"$(VSN)"}},{stylesheet,"process-one.css"},{overview,"$(DOCDIR)/overview.edoc"}]' -s init stop
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

+19
View File
@@ -0,0 +1,19 @@
.comment {color: brown}
.export {color: darkorchid}
.import {color: darkorchid}
.string {color: maroon}
.builtin {color: dodgerblue}
.guard {color: mediumturquoise}
.function {color: blue}
.variable {color: green}
.macro {color: mediumpurple}
.record {color: orangered}
.call {color: purple}
.attribute {color: firebrick}
.error{color: red}
.l {
font-style: normal;
font-weight: normal;
text-decoration: none;
color: gray;
}
+356
View File
@@ -0,0 +1,356 @@
%%%-------------------------------------------------------------------
%%% File : escobar_hiliter.erl
%%% Author : Mats Cronqvist <mats.cronqvist@gmail.com>
%%% Description :
%%%
%%% Created : 6 Jun 2005 by Mats Cronqvist <mats.cronqvist@gmail.com>
%%%
%%%
%%% Escobar, Copyright (c) 2005-2009 Mats Cronqvist
%%%
%%% MIT License:
%%%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy
%%% of this software and associated documentation files (the "Software"), to deal
%%% in the Software without restriction, including without limitation the rights
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
%%% copies of the Software, and to permit persons to whom the Software is
%%% furnished to do so, subject to the following conditions:
%%%
%%% The above copyright notice and this permission notice shall be included in
%%% all copies or substantial portions of the Software.
%%%
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
%%% THE SOFTWARE.
%%%
%%%-------------------------------------------------------------------
-module(escobar_hilite).
-export([file/1,tree/1,string/1,out/2]).
-define(LOG(T),escobar:log(process_info(self()),T)).
-import(erl_syntax,
[get_ann/1,add_ann/2,subtrees/1,update_tree/2,type/1,get_pos/1,
application/2,application_arguments/1,application_operator/1,
arity_qualifier_argument/1,arity_qualifier_body/1,
atom_name/1,atom_value/1,
attribute/2,attribute_name/1,attribute_arguments/1,
clause/3,clause_patterns/1,clause_guard/1,clause_body/1,
comment/2,comment_text/1,comment_padding/1,
function/2,function_name/1,function_clauses/1,function_arity/1,
integer_literal/1,
list/1,list_elements/1,
macro/2,macro_name/1,macro_arguments/1,
module_qualifier_body/1, module_qualifier_argument/1,
string_value/1,string_literal/1,
variable_literal/1,variable_name/1,
record_access/3, record_access_argument/1,
record_access_field/1,record_access_type/1,
record_expr/3, record_expr_argument/1,
record_expr_fields/1, record_expr_type/1,
record_index_expr/2, record_index_expr_field/1,
record_index_expr_type/1,
form_list/1,
get_precomments/1,get_postcomments/1,has_comments/1,
copy_comments/2,remove_comments/1]).
-import(prettypr,
[above/2,follow/2,beside/2,empty/0,
null_text/1,break/1,floating/3,text/1,floating/1]).
-import(lists,[flatten/1,duplicate/2,keysearch/3,member/2,usort/1,reverse/1]).
-import(filename,[join/1,basename/1]).
out(File,HtmlString) ->
{ok,FD}=file:open(File,[write]),
try
io:fwrite(FD,"<html>",[]),
io:fwrite(FD,"<link rel=\"stylesheet\" type=\"text/css\"",[]),
io:fwrite(FD,"href=\"escobar.css\"></link><body><pre>",[]),
io:fwrite(FD,"~s",[HtmlString]),
io:fwrite(FD,"</pre></body></html>",[])
after
file:close(FD)
end.
string(Str) ->
tree(form_list(scan_and_parse(Str,1,[]))).
scan_and_parse([],_Line,Forms) -> reverse(Forms);
scan_and_parse(Text,Line,Forms) ->
{done,{ok,Toks,NLine},Cont} = erl_scan:tokens([],Text,Line),
{ok,Form} = erl_parse:parse_form(Toks),
scan_and_parse(Cont,NLine,[Form|Forms]).
file(FileName) ->
case filelib:is_regular(FileName) of
true ->
case filename:extension(FileName) of
".beam"-> tree(get_tree_beam(FileName));
".erl" -> tree(get_comm_tree_erl(FileName));
".hrl" -> tree(get_comm_tree_erl(FileName));
X -> erlang:error({unknown_extension,X})
end;
false->
erlang:error({no_file,FileName})
end.
get_comm_tree_erl(Filename) ->
Comms = erl_comment_scan:file(Filename),
Forms = get_forms_erl(Filename),
erl_recomment:recomment_forms(Forms,Comms).
get_tree_beam(Filename) ->
case beam_lib:chunks(Filename,["Abst"]) of
{ok,{_,[{"Abst",AChunk}]}} ->
{_,Forms} = binary_to_term(AChunk),
form_list(Forms);
_ ->
erlang:error({no_debuginfo,Filename})
end.
get_forms_erl(Filename) ->
{ok,Fs} = epp_dodger:parse_file(Filename,[{no_fail, true}]),
Fs.
%%% # tree
%%% turn a syntax tree into html by annotating and pretty-printing
%%% with a hook function
tree(Tree) ->
pout(ann(type(Tree),Tree)).
%%lists:foldl(fun(Form,Acc) -> [pout(ann(Form))|Acc] end, [], Tree).
pout(Form) ->
erl_prettypr:format(Form,[{hook,fun tag/3},{paper,90},{ribbon,650}]).
%%% ## formatting
%%% ### 'tag' - the format hook function
tag(Node,Ctxt,Cont) ->
Tags = get_ann(Node),
case member(has_comment,Tags) of
true ->
PreC = get_precomments(Node),
PostC = get_postcomments(Node),
Nod = remove_comments(Node),
Doc0 = tagit(Tags--[has_comment],Cont(Nod,Ctxt)),
postcomment(precomment(Doc0,PreC),PostC);
false ->
Doc0 = Cont(Node,Ctxt),
tagit(Tags,Doc0)
end.
tagit([],Doc0) ->
Doc0;
tagit(["binary"],{beside,_,{beside,Doc,_}}) ->
beside(floating(text("&lt;&lt;")),beside(Doc,floating(text("&gt;&gt;"))));
tagit([Tag],Doc0) ->
beside(null_text(Tag),beside(Doc0,null_text(etag(Tag)))).
etag("<"++Tag) -> "</"++hd(string:tokens(Tag," "))++">".
%%%### comment stuff
precomment(Doc,PreC) ->
above(floating(break(stack(PreC)), -1, -1), Doc).
postcomment(Doc,PostC) ->
beside(Doc, floating(break(stack(PostC)), 1, 0)).
stack([]) -> empty();
stack([Comm|Comms]) ->
Doc = maybe_pad(stack_comment_lines(comment_text(Comm)),Comm),
case Comms of
[] -> Doc;
_ -> above(Doc, stack(Comms))
end.
maybe_pad(Doc,Comm) ->
case comment_padding(Comm) of
I when is_integer(I), 0 < I -> beside(text(duplicate(I,$ )), Doc);
_ -> Doc
end.
%%% stolen with pride from erl_prettypr
%%% Stack lines of text above each other and prefix each string in
%%% the list with a single `%' character.
stack_comment_lines([S | Ss]) ->
D = tagit([dehtml('span', [{class,comment}])],text("%"++debracket(S))),
case Ss of
[] -> D;
_ -> above(D, stack_comment_lines(Ss))
end;
stack_comment_lines([]) ->
empty().
%%% annotate nodes that should be hilited
%%% the annotation is put on the subtree that should be marked up
%%% the annotation is;
%%% has_comments|Markup
%%% if a node already has an annotation the new one is dropped, except
%%% if either the new or the old one is has_comments
ann(binary,Tree) ->
new_tree(Tree,add_anno("binary",Tree));
ann(application,Tree) ->
Op = application_operator(Tree),
Args = application_arguments(Tree),
new_tree(Tree,application(add_anno(mu(application,Tree),Op),Args));
ann(attribute,Tree) ->
Name = attribute_name(Tree),
case atom_value(Name) of
export ->
AQs = list_elements(hd(attribute_arguments(Tree))),
Args = [list([add_anno(mu(export,Tree),AQ) || AQ <- AQs])];
import ->
[ImportMod,ImportFAs] = attribute_arguments(Tree),
AQs = list_elements(ImportFAs),
Args = [ImportMod,list([add_anno(mu(import,Tree),AQ) || AQ <- AQs])];
define ->
[Macro|Rest] = attribute_arguments(Tree),
case type(Macro) of
application ->
Op = application_operator(Macro),
As = application_arguments(Macro),
Args = [application(add_anno(mu(macro,Tree),Op),As)|Rest];
_ ->
Args = [add_anno(mu(macro,Tree),Macro)|Rest]
end;
record ->
[Rec|Rest] = attribute_arguments(Tree),
Args = [add_anno(mu(record,Tree),Rec)|Rest];
_ ->
Args = attribute_arguments(Tree)
end,
new_tree(Tree,attribute(add_anno(mu(attribute,Tree),Name),Args));
ann(record_access,Tree) ->
Arg = record_access_argument(Tree),
Type = record_access_type(Tree),
Field = record_access_field(Tree),
new_tree(Tree,record_access(Arg,add_anno(mu(record,Tree),Type),Field));
ann(record_expr,Tree) ->
Arg = record_expr_argument(Tree),
Type = record_expr_type(Tree),
Fields = record_expr_fields(Tree),
new_tree(Tree,record_expr(Arg,add_anno(mu(record,Tree),Type),Fields));
ann(record_index_expr,Tree) ->
Type = record_index_expr_type(Tree),
Field = record_index_expr_field(Tree),
new_tree(Tree,record_index_expr(add_anno(mu(record,Tree),Type),Field));
ann(function,Tree) ->
Name = function_name(Tree),
Clauses = function_clauses(Tree),
new_tree(Tree,function(add_anno(mu(function,Tree),Name),Clauses));
ann(macro,Tree) ->
Name = macro_name(Tree),
Args = macro_arguments(Tree),
new_tree(Tree,macro(add_anno(mu(macro,Tree),Name), Args));
ann(string,OTree) ->
Tree = erl_syntax:string(debracket(string_value(OTree))),
new_tree(OTree,add_anno(mu(string,OTree),Tree));
ann(variable,Tree) ->
new_tree(Tree,add_anno(mu(variable,Tree),Tree));
ann(text,Tree) ->
new_tree(Tree,add_anno(mu(error,Tree),Tree));
ann(comment,OTree) ->
Pad = comment_padding(OTree),
Text = [debracket(S) || S <- comment_text(OTree)],
Tree = comment(Pad,Text),
new_tree(OTree,add_anno(mu(comment,OTree),Tree));
ann(_Typ,Tree) ->
new_tree(Tree,Tree).
new_tree(OTree,NTree) ->
Tree =
case has_comments(OTree) of
true -> add_ann(has_comment,copy_comments(OTree,NTree));
false -> NTree
end,
SubTrees = subtrees(Tree),
case [[ann(type(SubT),SubT) || SubT<-Group] || Group<-SubTrees] of
[] -> Tree;
NSubtrees -> update_tree(Tree,NSubtrees)
end.
debracket([]) -> [];
debracket([$>|Str]) -> "&gt;"++debracket(Str);
debracket([$<|Str]) -> "&lt;"++debracket(Str);
debracket([C|Str]) -> [C|debracket(Str)].
add_anno(nil,Tree) -> Tree;
add_anno(Ann,Tree) ->
case get_ann(Tree) of
[] -> add_ann(Ann,Tree);
[has_comment] -> add_ann(Ann,Tree);
_OAnn -> Tree
end.
%%%### the markups
mu(application,Node) ->
Op = application_operator(Node),
Ar = length(application_arguments(Node)),
case type(Op) of
%% variable ->
%% dehtml('span', [{class,variable}]);
atom ->
case is_guard_or_builtin(atom_value(Op),Ar) of
guard -> dehtml('span', [{class,guard}]);
builtin->dehtml('span', [{class,builtin}]);
neither->dehtml('span', [{class,call}])
end;
module_qualifier ->
Mod = module_qualifier_argument(Op),
Fun = module_qualifier_body(Op),
case {type(Mod),type(Fun)} of
{atom,atom} ->
case atom_value(Mod) of
erlang -> dehtml('span', [{class,builtin}]);
_ -> dehtml('span', [{class,call}])
end;
_ ->
nil
end;
_ ->
nil
end;
mu(function = Class, {tree, function, _, {function, _, [{tree, clause, _, {clause, Vars, _, _}} | _]}}) ->
dehtml('span', [{class,Class}, {arity,length(Vars)}]);
mu(Class,_Node) ->
dehtml('span', [{class,Class}]).
dehtml(Tag,Atts) ->
flatten([$<,str(Tag),$ ,[[str(A),"=\"",str(V),"\" "]||{A,V}<-Atts],$>]).
str(I) when is_integer(I) -> integer_to_list(I);
str(A) when is_atom(A) -> atom_to_list(A);
str(L) when is_list(L) -> L.
is_guard_or_builtin(atom,1) ->guard;
is_guard_or_builtin(binary,1) ->guard;
is_guard_or_builtin(constant,1) ->guard;
is_guard_or_builtin(float,1) ->guard;
is_guard_or_builtin(function,1) ->guard;
is_guard_or_builtin(function,2) ->guard;
is_guard_or_builtin(integer,1) ->guard;
is_guard_or_builtin(list,1) ->guard;
is_guard_or_builtin(number,1) ->guard;
is_guard_or_builtin(pid,1) ->guard;
is_guard_or_builtin(port,1) ->guard;
is_guard_or_builtin(reference,1) ->guard;
is_guard_or_builtin(tuple,1) ->guard;
is_guard_or_builtin(record,2) ->guard;
is_guard_or_builtin(record,3) ->guard;
is_guard_or_builtin(F,A) ->
case erlang:function_exported(erlang,F,A) orelse
erlang:is_builtin(erlang,F,A) of
true -> builtin;
false-> neither
end.
+54
View File
@@ -0,0 +1,54 @@
%%%-------------------------------------------------------------------
%%% File : escobar_run.erl
%%% Author : Badlop <badlop@process-one.net>
%%% Purpose : Frontend to run Escobar
%%% Created : 16 Apr 2008 by Badlop <badlop@process-one.net>
%%%-------------------------------------------------------------------
-module(escobar_run).
%%% Download ejabberd_hilite.erl from http://code.google.com/p/erl-escobar/
%%% Example calls:
%%% escobar_run:file("escobar_run.erl", "../ejascobar/").
%%% escobar_run:dir(".", "../ejascobar/").
%%% escobar_run:dir(".", "../doc/api/").
%%% find ./ -type f -name '*.html' -exec sed -i 's/class="function" >\([a-z0-9]*\)</class="function" id="\1">\1</;' {} \;
-export([file/2, file/1, dir/1]).
file([F, OutDir]) ->
file(F, OutDir).
file(F, OutDir) ->
String = escobar_hilite:file(F),
FB = filename:basename(F),
FilenameHTML = filename:join(OutDir, FB ++ ".html"),
escobar_hilite:out(FilenameHTML, String).
dir([SrcDir, OutDir]) ->
SrcDirAbs = filename:absname(SrcDir),
OutDirAbs = filename:absname(OutDir),
Files = get_files([SrcDirAbs]),
lists:foreach(
fun(F) ->
case filename:extension(F) of
".erl" ->
file(F, OutDirAbs);
".hrl" ->
file(F, OutDirAbs);
_ ->
ok
end
end,
Files).
get_files([]) ->
[];
get_files([FHead | FTail]) ->
case catch file:list_dir(FHead) of
{ok, Files} ->
FilesHead = [filename:join(FHead, FilesN) || FilesN <- Files],
get_files(FilesHead ++ FTail);
{error, enotdir} ->
[FHead] ++ get_files(FTail)
end.
Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

+522
View File
@@ -0,0 +1,522 @@
%%%----------------------------------------------------------------------
%%% File : funrelg.erl
%%% Author : Badlop <badlop@process-one.net>
%%% Purpose : Function Relation Graph
%%% Created : 3 Apr 2007 by Badlop <badlop@process-one.net>
%%%
%%%
%%% 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
%%%
%%%----------------------------------------------------------------------
-module(funrelg).
-author('badlop@process-one.net').
-export([dir/1, file/1, g/0, g/1, gc/0, gc/1, d/0]).
-record(mfa, {mod, func, arity}).
-record(arcs, {id, from, to, occ}).
%% The functions that are not in export and don't call anybody are not drawn
%% The calls to this module that use Mod:Func are drawn as external calls
%%-----------------------------
%% Module handlers
%%-----------------------------
dir([SrcDir, OutDir]) ->
SrcDirAbs = filename:absname(SrcDir),
OutDirAbs = filename:absname(OutDir),
Files = get_files([SrcDirAbs]),
lists:foreach(
fun(F) ->
file(F, OutDirAbs)
end,
Files).
file([SrcDir, OutDir]) ->
SrcFilAbs = filename:absname(SrcDir),
OutDirAbs = filename:absname(OutDir),
file(SrcFilAbs, OutDirAbs).
file(SrcFile, OutDir) ->
case {filename:extension(SrcFile), filename:basename(SrcFile)} of
%% The file must by *.erl, and the first character must be a-z
{".erl", [FirstChar | _]} when (FirstChar >= 97) and (FirstChar =< 122) ->
make_file(SrcFile, OutDir),
d();
_ ->
ok
end.
get_files([]) ->
[];
get_files([FHead | FTail]) ->
case catch file:list_dir(FHead) of
{ok, Files} ->
FilesHead = [filename:join(FHead, FilesN) || FilesN <- Files],
get_files(FilesHead ++ FTail);
{error, enotdir} ->
[FHead] ++ get_files(FTail)
end.
make_file(File, OutDir) ->
FB = filename:basename(File),
FileDot = filename:join(OutDir, FB ++ ".dot"),
Text = gc(File),
{ok,FO}=file:open(FileDot,[write]),
try
io:fwrite(FO,"~s",[Text])
after
file:close(FO)
end,
FileSvg = filename:join(OutDir, filename:basename(File, ".erl") ++ ".svg"),
case os:cmd("dot -Tsvg " ++ FileDot ++ " -o " ++ FileSvg) of
"" -> ok;
ShellResult ->
io:format("Trying to run 'dot', we got this result:~n ~s~n"
"Remember that you need to have Graphviz 'dot' installed.~n", [ShellResult])
end,
ok.
%%====================================================================
%% Internal functions
%%====================================================================
g() ->
g("a.erl").
g(Filename) ->
gc(Filename),
halt().
gc() ->
gc("a.erl").
gc(Filename) ->
{ok, File} = epp_dodger:parse_file(Filename),
ets:new(arcs, [set, public, named_table, {keypos, 2}]),
ets:new(mfa_conversion, [set, public, named_table, {keypos, 1}]),
ets:new(counters, [set, public, named_table]),
ets:insert(counters, {arcs_id, 0}),
ModuleName = get_module_name(File),
Exports = lists:usort(get_exports(File)),
Functions = get_functions(File),
FunctionsParsed = lists:usort(parse_functions(Functions)), % side effects: stores on ets
Privates = FunctionsParsed -- Exports,
%%Externals = get_externals(),
MFAs = get_func_calls(),
AppModules1 = os:cmd("ls -1 ../doc/devdoc/*.html | tr \".\" \" \" | tr \"/\" \" \" | awk '{print $3}'"),
AppModules = [list_to_atom(Str) || Str <- string:tokens(AppModules1, [10])],
ExternalTypes1 = [mfa_to_externaltype(MFA, ModuleName, AppModules, FunctionsParsed) || MFA <- MFAs],
ExternalTypes = lists:usort(ExternalTypes1),
AppExternals = [Function || {Type, Function} <- ExternalTypes, Type == app],
ExmppExternals = [Function || {Type, Function} <- ExternalTypes, Type == exmpp],
OTPExternals = [Function || {Type, Function} <- ExternalTypes, Type == other],
textize(ModuleName, Exports, Privates, AppExternals, ExmppExternals, OTPExternals).
get_arcs_id() ->
ets:update_counter(counters, arcs_id, 1).
insert_arc_normal(FromFunc, FromArity, ToFunc, ToArity) ->
From = #mfa{mod = -1, func = FromFunc, arity = FromArity},
To = #mfa{mod = -1, func = ToFunc, arity = ToArity},
insert_arc(From, To).
insert_arc_external(FromFunc, FromArity, ToMod, ToFunc, ToArity) ->
From = #mfa{mod = -1, func = FromFunc, arity = FromArity},
To = #mfa{mod = ToMod, func = ToFunc, arity = ToArity},
insert_arc(From, To).
insert_arc(From, To) ->
Match = #arcs{
from = From,
to = To,
id='$1',
_='_'},
Select = [{Match, [], ['$1']}],
Ids = ets:select(arcs, Select),
case Ids of
[] ->
ets:insert(arcs,
#arcs{
id = get_arcs_id(),
from = From,
to = To,
occ = 1
}
);
[Id] ->
[Arc] = ets:lookup(arcs, Id),
Arc2 = Arc#arcs{occ = Arc#arcs.occ+1},
ets:insert(arcs, Arc2)
end.
read_arc(Id) ->
ets:lookup(arcs, Id).
d() ->
ets:delete(arcs),
ets:delete(mfa_conversion),
ets:delete(counters).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Get
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
get_module_name(File) ->
Attributes = get_elements(attribute, File),
get_attribute(module, Attributes).
get_exports(File) ->
Attributes = get_elements(attribute, File),
Exports = get_attribute(export, Attributes),
parse_export(Exports).
get_functions(File) ->
get_elements(function, File).
get_elements(Type, L) -> get_elements(Type, L, []).
get_elements(_, [], Res) -> Res;
get_elements(Type, [{tree, Type, _, A} | L], Res) ->
get_elements(Type, L, Res++[A]);
get_elements(Type, [_ | L], Res) ->
get_elements(Type, L, Res).
get_attribute(_, []) -> [];
get_attribute(Name, [{attribute, {tree, atom, _, Name}, [Al]} | As]) ->
case Name of
module ->
{tree, atom, _, Mn} = Al,
Mn;
export ->
{tree, list, _, {list, Exports, _}} = Al,
Exports++get_attribute(Name, As);
_ -> ok
end;
get_attribute(Name, [_ | As]) ->
get_attribute(Name, As).
parse_export(Ex) ->
lists:foldl(
fun(Aq, Res) ->
{tree, arity_qualifier, _, {arity_qualifier, Atom, Inte}} = Aq,
{tree, atom, _, An} = Atom,
{tree, integer, _, In} = Inte,
Res++[{An, In}]
end,
[],
Ex).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Parse
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
parse_functions(Functions) ->
lists:map(
fun(E) ->
{function, {_, _, _, Fn}, Clauses} = E,
Arity = get_function_arity(Clauses),
parse_clauses(Fn, Clauses),
{Fn, Arity}
end,
Functions).
parse_clauses(Fn, Clauses) ->
lists:foreach(
fun(E) ->
{tree, clause, L, C} = E,
{attr, _Ln, _, _} = L,
{clause, Parameters, _, Contents} = C,
Fa = length(Parameters),
parse_contents({Fn, Fa}, Contents)
end,
Clauses).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% OLD
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
parse_contents(F, Contents) ->
{_, Res} = lists:foldl(
fun(C, {Fu, R}) ->
{Fu, R++parse_content(F, C)}
end,
{F, []},
Contents),
Res.
parse_content(F, {tree, application, L, A}) ->
{attr, _Ln, _, _} = L,
parse_application(F, A);
parse_content(F, {tree, list, _, {list, [L], Ls}}) ->
RL = parse_content(F, L),
RL++parse_content(F, Ls);
parse_content(F, {tree, tuple, _, T}) ->
parse_contents(F, T);
parse_content(F, {tree, match_expr, _, M}) ->
{match_expr, _, Value} = M,
parse_content(F, Value);
parse_content(F, {tree, try_expr, _, T}) ->
{try_expr, As, Bs, Cs, Ds} = T,
RAs = parse_contents(F, As),
RBs = parse_contents(F, Bs),
RDs = parse_contents(F, Ds),
RAs++RBs++RDs++parse_contents(F, Cs);
parse_content(F, {tree, block_expr, _, Ts}) ->
parse_contents(F, Ts);
parse_content(F, {tree, catch_expr, _, C}) ->
parse_content(F, C);
parse_content(F, {tree, case_expr, _, C}) ->
{case_expr, Case, Cases} = C,
R2 = parse_content(F, Case),
R2++parse_contents(F, Cases);
parse_content(F, {tree, if_expr, _, Cases}) ->
parse_contents(F, Cases);
parse_content(F, {tree, disjunction, _, Cases}) ->
parse_contents(F, Cases);
parse_content(F, {tree, conjunction, _, Cases}) ->
parse_contents(F, Cases);
parse_content(F, {tree, list_comp, _, L}) ->
{list_comp, A, Bs} = L,
RA = parse_content(F, A),
RA++parse_contents(F, Bs);
parse_content(F, {tree, generator, _, G}) ->
{generator, _, Gen} = G,
parse_content(F, Gen);
parse_content(F, {tree, clause, _, C}) ->
{clause, Clause, When, Second} = C,
R2 = parse_contents(F, Clause),
R3 = parse_content(F, When),
R2++R3++parse_contents(F, Second);
parse_content(F, {tree, fun_expr, _, E}) ->
parse_contents(F, E);
parse_content(F, {tree, record_expr, _, E}) ->
{record_expr, _, _, Records} = E,
parse_contents(F, Records);
parse_content(F, {tree, record_field, _, R}) ->
{record_field, F1, F2} = R,
R2 = parse_content(F, F1),
R2++parse_content(F, F2);
parse_content(F, {tree, receive_expr, _, E}) ->
{receive_expr, E1, _, _} = E,
parse_contents(F, E1);
parse_content(F, {tree, infix_expr, _, I}) ->
{infix_expr, _Operator, T1, T2} = I,
R = parse_content(F, T1),
R++parse_content(F, T2);
parse_content(_F, {tree, prefix_expr, _, _P}) ->
[];
parse_content(_F, {tree, class_qualifier, _, _}) -> [];
parse_content(_F, {tree, implicit_fun, _, _}) -> [];
parse_content(_F, {tree, record_access, _, _}) -> [];
parse_content(_F, {tree, record_index_expr, _, _}) -> [];
parse_content(_F, {tree, macro, _, _}) -> [];
parse_content(_F, {tree, binary, _, _}) -> [];
parse_content(_F, {tree, binary_generator, _, _}) -> [];
parse_content(_F, {tree, binary_comp, _, _}) -> [];
parse_content(_F, {integer, _, _I}) -> [];
parse_content(_F, {float, _, _I}) -> [];
parse_content(_F, {string, _, _S}) -> [];
parse_content(_F, {char, _, _S}) -> [];
parse_content(_F, {atom, _, _A}) -> [];
parse_content(_F, {var, _, _V}) -> [];
parse_content(_F, {nil, _}) -> [];
parse_content(_F, none) -> [];
parse_content(_F, C) -> io:format("Unknown content: ~p~n", [C]), [].
parse_application({Fn, Fa}, {application, {atom, _, Name}, Valores}) ->
Arity = length(Valores),
insert_arc_normal(Fn, Fa, Name, Arity),
Ra = [{arc_normal, Fn, Name}],
Ra++parse_contents({Fn, Fa}, Valores);
parse_application({Fn, Fa}, {application, {tree, module_qualifier, _, M}, Tree2}) ->
case M of
{module_qualifier, {_, _, Tf1}, {_, _, Tf2}} ->
ToArity = length(Tree2),
insert_arc_external(Fn, Fa, Tf1, Tf2, ToArity),
parse_contents({Fn, Fa}, Tree2);
_Other ->
%%io:format("Unknown application module_qualifier: ~p~n", [M]),
parse_contents({Fn, Fa}, Tree2)
end;
parse_application({Fn, Fa}, {application, {tree, record_access, _, _}, Tree2}) ->
parse_contents({Fn, Fa}, Tree2);
parse_application({Fn, Fa}, {application, {var, _, _}, Tree2}) ->
parse_contents({Fn, Fa}, Tree2);
parse_application({Fn, Fa}, {application, Other, Tree2}) ->
io:format("Unknown application tree: ~p~n", [Other]),
parse_contents({Fn, Fa}, Tree2).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Textize
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
textize(ModuleName, Exports, Privates, AppExternals, ExmppExternals, OTPExternals) ->
ExportsS = textize_exports(Exports),
PrivatesS = textize_exports(Privates),
AppExternalsS = textize_externals(AppExternals),
ExmppExternalsS = textize_externals(ExmppExternals),
OTPExternalsS = textize_externals(OTPExternals),
Arcs = textize_arcs(),
io_lib:format(
"digraph ~p {~n"++
" label = \"Module ~p\";~n"++
" labelloc = \"t\";~n"++
" fontname = Helvetica;~n"++
" rankdir = LR;~n"++
" ratio = fill;~n"++
%%" node [shape = box, style = filled, color = olivedrab1, fontsize=40];~s~n"++
%%" node [shape = parallelogram, style = filled, color = rosybrown1, fontsize=40];~s~n"++
%%" node [shape = ellipse, style = filled, color = slategray1, peripheries=3, fontsize=40];~n"++
" node [shape = box, color=darkgreen, fillcolor=Honeydew, style=filled, href=\"PRI~p.html#\\N\"];~s~n"++
" node [shape = box, color=darkgreen, fillcolor=PaleGreen, style=filled, href=\"EXP~p.html#\\N\"];~s~n"++
" node [shape = box, color=darkgreen, fillcolor=Aquamarine, style=filled, href=\"APP\\N\"];~s~n"++
" node [shape = box, color=darkblue, fillcolor=LightSkyBlue,style=filled, href=\"EXM\\N\"];~s~n"++
" node [shape = box, color=darkred, fillcolor=PeachPuff, style=filled, href=\"OTP\\N\"];~s~n"++
" node [shape = box];~n"++
"~s"++
"}~n",
[ModuleName, ModuleName,
ModuleName, PrivatesS,
ModuleName, ExportsS,
AppExternalsS,
ExmppExternalsS,
OTPExternalsS,
Arcs]).
textize_exports(Exports) ->
lists:foldl(
fun({Func, Arity}, R) ->
string:concat(R, io_lib:format(" \"~p/~p\";", [Func, Arity]))
end,
"",
Exports).
textize_externals(Externals) ->
lists:foldl(
fun({Mod, Func, Arity}, R) ->
string:concat(R, io_lib:format(" \"~p:~p/~p\";", [Mod, Func, Arity]));
({Func, Arity}, R) ->
string:concat(R, io_lib:format(" \"~p/~p\";", [Func, Arity]))
end,
"",
Externals).
textize_arcs() ->
Id = ets:first(arcs),
textize_arcs(Id, []).
textize_arcs('$end_of_table', Res) -> Res;
textize_arcs(Id, Res) ->
[Arc] = read_arc(Id),
From = mfa_prepare(Arc#arcs.from),
To = mfa_prepare(Arc#arcs.to),
Edge_attrs = check_loop(From, To)++check_occu(Arc#arcs.occ)++check_external(Arc#arcs.to),
Res2 = io_lib:format(" ~s -> ~s~s;~n", [From, To, Edge_attrs]),
Id_next = ets:next(arcs, Id),
textize_arcs(Id_next, string:concat(Res2, Res)).
get_func_calls() ->
Id = ets:first(arcs),
get_func_calls(Id, []).
get_func_calls('$end_of_table', Res) -> Res;
get_func_calls(Id, Res) ->
[Arc] = read_arc(Id),
MFA = Arc#arcs.to,
Call = MFA,
Id_next = ets:next(arcs, Id),
get_func_calls(Id_next, [Call | Res]).
mfa_prepare(MFAinitial) ->
MFA = try_mfa_conversion(MFAinitial),
Mod = case MFA#mfa.mod of
-1 -> "\"";
M -> io_lib:format("\"~p:", [M])
end,
Func = io_lib:format("~p", [MFA#mfa.func]),
Arity = case MFA#mfa.arity of
-1 -> "\"";
A -> io_lib:format("/~p\"", [A])
end,
string:concat(Mod, string:concat(Func, Arity)).
%% noexternal | app | exmpp | other
mfa_to_externaltype(MFA, ModuleName, AppModules, Functions) ->
case MFA of
{mfa, -1, Fu, Ar} ->
case {is_internal, lists:member({Fu, Ar}, Functions)} of
{is_internal, true} ->
{noexternal, {Fu, Ar}};
{is_internal, false} ->
store_mfa_conversion(MFA, {mfa, -1, Fu, Ar}),
{other, {Fu, Ar}}
end;
{mfa, Mo, Fu, Ar} when Mo == ModuleName ->
store_mfa_conversion(MFA, {mfa, -1, Fu, Ar}),
{noexternal, {Fu, Ar}};
{mfa, Mo, Fu, Ar} ->
Type = case {is_app, lists:member(Mo, AppModules)} of
{is_app, true} -> app;
{is_app, false} ->
case string:str(atom_to_list(Mo), "exmpp") of
0 -> other;
N when is_integer(N) -> exmpp
end
end,
{Type, {Mo, Fu, Ar}}
end.
get_function_arity([{tree, clause, _, {clause, Vars, _, _}} | _]) ->
length(Vars);
get_function_arity(E) ->
io:format("Unknown function arity: ~p~n", [E]).
store_mfa_conversion(MFA1, MFA2) ->
ets:insert(mfa_conversion, {MFA1, MFA2}).
try_mfa_conversion(MFA) ->
case ets:lookup(mfa_conversion, MFA) of
[{MFA,MFA2}] ->
MFA2;
[] ->
MFA
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Utils
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%check_loop(I, I) -> " [color = sandybrown]";
check_loop(I, I) -> "";
check_loop(_, _) -> "".
check_occu(1) -> "";
check_occu(Occ) -> io_lib:format(" [label=\"~p\"]", [Occ]).
check_external(To) ->
case To#mfa.mod of
-1 -> " [style = bold]";
_ -> ""
end.
@@ -1,3 +1,25 @@
div.navbar table tr td a[target="_parent"] {
background: transparent url("ejabberd-devdoc.png") no-repeat;
display: block;
font-size: 0%;
top: 0;
left: 0;
padding: 0;
margin: 0;
width: 192px;
height: 42px;
}
div.navbar table tr td a img {
border: 0;
padding: 0 0 0 10;
float: right;
}
p i {
display: none;
}
html, body {
font-family: Verdana, sans-serif;
color: #000;
@@ -5,19 +27,20 @@ html, body {
}
h1 {
font-size: 20px;
color: #4a5389;
border-bottom: solid 1px #000;
}
h2 {
font-size: 24px;
font-size: 18px;
text-align: right;
color: #4a5389;
border-bottom: 1px solid #000;
}
h3 {
font-size: 18px;
font-size: 16px;
color: #900;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

-132
View File
@@ -1,132 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<TITLE>Ejabberd 2.1.0 Feature Sheet
</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<META name="GENERATOR" content="hevea 1.10">
<STYLE type="text/css">
.li-itemize{margin:1ex 0ex;}
.li-enumerate{margin:1ex 0ex;}
.dd-description{margin:0ex 0ex 1ex 4ex;}
.dt-description{margin:0ex;}
.toc{list-style:none;}
.thefootnotes{text-align:left;margin:0ex;}
.dt-thefootnotes{margin:0em;}
.dd-thefootnotes{margin:0em 0em 0em 2em;}
.footnoterule{margin:1em auto 1em 0px;width:50%;}
.caption{padding-left:2ex; padding-right:2ex; margin-left:auto; margin-right:auto}
.title{margin:2ex auto;text-align:center}
.center{text-align:center;margin-left:auto;margin-right:auto;}
.flushleft{text-align:left;margin-left:0ex;margin-right:auto;}
.flushright{text-align:right;margin-left:auto;margin-right:0ex;}
DIV TABLE{margin-left:inherit;margin-right:inherit;}
PRE{text-align:left;margin-left:0ex;margin-right:auto;}
BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;}
TD P{margin:0px;}
.boxed{border:1px solid black}
.textboxed{border:1px solid black}
.vbar{border:none;width:2px;background-color:black;}
.hbar{border:none;height:2px;width:100%;background-color:black;}
.hfill{border:none;height:1px;width:200%;background-color:black;}
.vdisplay{border-collapse:separate;border-spacing:2px;width:auto; empty-cells:show; border:2px solid red;}
.vdcell{white-space:nowrap;padding:0px;width:auto; border:2px solid green;}
.display{border-collapse:separate;border-spacing:2px;width:auto; border:none;}
.dcell{white-space:nowrap;padding:0px;width:auto; border:none;}
.dcenter{margin:0ex auto;}
.vdcenter{border:solid #FF8000 2px; margin:0ex auto;}
.minipage{text-align:left; margin-left:0em; margin-right:auto;}
.marginpar{border:solid thin black; width:20%; text-align:left;}
.marginparleft{float:left; margin-left:0ex; margin-right:1ex;}
.marginparright{float:right; margin-left:1ex; margin-right:0ex;}
.theorem{text-align:left;margin:1ex auto 1ex 0ex;}
.part{margin:2ex auto;text-align:center}
SPAN{width:20%; float:right; text-align:left; margin-left:auto;}
</STYLE>
</HEAD>
<BODY >
<!--HEVEA command line is: /usr/bin/hevea -fix -pedantic features.tex -->
<!--CUT DEF section 1 --><P><A NAME="titlepage"></A>
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.1.0 Feature Sheet</H1><H3 CLASS="titlerest">Sander Devrieze<BR>
<A HREF="mailto:s.devrieze@pandora.be"><TT>mailto:s.devrieze@pandora.be</TT></A><BR>
<A HREF="xmpp:sander@devrieze.dyndns.org"><TT>xmpp:sander@devrieze.dyndns.org</TT></A></H3></TD></TR>
</TABLE><DIV CLASS="center">
<IMG SRC="logo.png" ALT="logo.png">
</DIV><BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>I can thoroughly recommend ejabberd for ease of setup &#X2013;
Kevin Smith, Current maintainer of the Psi project</I></FONT></BLOCKQUOTE><P>Introduction
<A NAME="intro"></A></P><BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. &#X2014;
Joeri</I></FONT></BLOCKQUOTE><P><TT>ejabberd</TT> is a <B><FONT SIZE=4><FONT COLOR="#001376">free and open source</FONT></FONT></B> instant messaging server written in <A HREF="http://www.erlang.org/">Erlang/OTP</A>.</P><P><TT>ejabberd</TT> is <B><FONT SIZE=4><FONT COLOR="#001376">cross-platform</FONT></FONT></B>, distributed, fault-tolerant, and based on open standards to achieve real-time communication.</P><P><TT>ejabberd</TT> is designed to be a <B><FONT SIZE=4><FONT COLOR="#001376">rock-solid and feature rich</FONT></FONT></B> XMPP server.</P><P><TT>ejabberd</TT> is suitable for small deployments, whether they need to be <B><FONT SIZE=4><FONT COLOR="#001376">scalable</FONT></FONT></B> or not, as well as extremely big deployments.</P><!--TOC section Key Features-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc1"></A>Key Features</H2><!--SEC END --><P>
<A NAME="keyfeatures"></A>
</P><BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>Erlang seems to be tailor-made for writing stable, robust servers. &#X2014;
Peter Saint-Andr&#XE9;, Executive Director of the Jabber Software Foundation</I></FONT></BLOCKQUOTE><P><TT>ejabberd</TT> is:
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
<B><FONT SIZE=4><FONT COLOR="#001376">Cross-platform:</FONT></FONT></B> <TT>ejabberd</TT> runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.</LI><LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Distributed:</FONT></FONT></B> You can run <TT>ejabberd</TT> on a cluster of machines and all of them will serve the same Jabber domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.</LI><LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Fault-tolerant:</FONT></FONT></B> You can deploy an <TT>ejabberd</TT> cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced &#X2018;on the fly&#X2019;.</LI><LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Administrator Friendly:</FONT></FONT></B> <TT>ejabberd</TT> is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Comprehensive documentation.
</LI><LI CLASS="li-itemize">Straightforward installers for Linux, Mac OS X, and Windows. </LI><LI CLASS="li-itemize">Web Administration.
</LI><LI CLASS="li-itemize">Shared Roster Groups.
</LI><LI CLASS="li-itemize">Command line administration tool. </LI><LI CLASS="li-itemize">Can integrate with existing authentication mechanisms.
</LI><LI CLASS="li-itemize">Capability to send announce messages.
</LI></UL></LI><LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Internationalized:</FONT></FONT></B> <TT>ejabberd</TT> leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Translated to 25 languages. </LI><LI CLASS="li-itemize">Support for <A HREF="http://www.ietf.org/rfc/rfc3490.txt">IDNA</A>.
</LI></UL></LI><LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Open Standards:</FONT></FONT></B> <TT>ejabberd</TT> is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
<UL CLASS="itemize"><LI CLASS="li-itemize">
Fully XMPP compliant.
</LI><LI CLASS="li-itemize">XML-based protocol.
</LI><LI CLASS="li-itemize"><A HREF="http://www.ejabberd.im/protocols">Many protocols supported</A>.
</LI></UL></LI></UL><!--TOC section Additional Features-->
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc2"></A>Additional Features</H2><!--SEC END --><P>
<A NAME="addfeatures"></A>
</P><BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>ejabberd is making inroads to solving the "buggy incomplete server" problem &#X2014;
Justin Karneges, Founder of the Psi and the Delta projects</I></FONT></BLOCKQUOTE><P>Moreover, <TT>ejabberd</TT> comes with a wide range of other state-of-the-art features:
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
Modular
<UL CLASS="itemize"><LI CLASS="li-itemize">
Load only the modules you want.
</LI><LI CLASS="li-itemize">Extend <TT>ejabberd</TT> with your own custom modules.
</LI></UL>
</LI><LI CLASS="li-itemize">Security
<UL CLASS="itemize"><LI CLASS="li-itemize">
SASL and STARTTLS for c2s and s2s connections.
</LI><LI CLASS="li-itemize">STARTTLS and Dialback s2s connections.
</LI><LI CLASS="li-itemize">Web Admin accessible via HTTPS secure access.
</LI></UL>
</LI><LI CLASS="li-itemize">Databases
<UL CLASS="itemize"><LI CLASS="li-itemize">
Internal database for fast deployment (Mnesia).
</LI><LI CLASS="li-itemize">Native MySQL support.
</LI><LI CLASS="li-itemize">Native PostgreSQL support.
</LI><LI CLASS="li-itemize">ODBC data storage support.
</LI><LI CLASS="li-itemize">Microsoft SQL Server support. </LI></UL>
</LI><LI CLASS="li-itemize">Authentication
<UL CLASS="itemize"><LI CLASS="li-itemize">
Internal Authentication.
</LI><LI CLASS="li-itemize">PAM, LDAP and ODBC. </LI><LI CLASS="li-itemize">External Authentication script.
</LI></UL>
</LI><LI CLASS="li-itemize">Others
<UL CLASS="itemize"><LI CLASS="li-itemize">
Support for virtual hosting.
</LI><LI CLASS="li-itemize">Compressing XML streams with Stream Compression (<A HREF="http://www.xmpp.org/extensions/xep-0138.html">XEP-0138</A>).
</LI><LI CLASS="li-itemize">Statistics via Statistics Gathering (<A HREF="http://www.xmpp.org/extensions/xep-0039.html">XEP-0039</A>).
</LI><LI CLASS="li-itemize">IPv6 support both for c2s and s2s connections.
</LI><LI CLASS="li-itemize"><A HREF="http://www.xmpp.org/extensions/xep-0045.html">Multi-User Chat</A> module with support for clustering and HTML logging. </LI><LI CLASS="li-itemize">Users Directory based on users vCards.
</LI><LI CLASS="li-itemize"><A HREF="http://www.xmpp.org/extensions/xep-0060.html">Publish-Subscribe</A> component with support for <A HREF="http://www.xmpp.org/extensions/xep-0163.html">Personal Eventing via Pubsub</A>.
</LI><LI CLASS="li-itemize">Support for web clients: <A HREF="http://www.xmpp.org/extensions/xep-0025.html">HTTP Polling</A> and <A HREF="http://www.xmpp.org/extensions/xep-0206.html">HTTP Binding (BOSH)</A> services.
</LI><LI CLASS="li-itemize">IRC transport.
</LI><LI CLASS="li-itemize">Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
</LI></UL>
</LI></UL><!--CUT END -->
<!--HTMLFOOT-->
<!--ENDHTML-->
<!--FOOTER-->
<HR SIZE=2><BLOCKQUOTE CLASS="quote"><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
</EM><A HREF="http://hevea.inria.fr/index.html"><EM>H</EM><EM><FONT SIZE=2><sup>E</sup></FONT></EM><EM>V</EM><EM><FONT SIZE=2><sup>E</sup></FONT></EM><EM>A</EM></A><EM>.</EM></BLOCKQUOTE></BODY>
</HTML>
-3977
View File
File diff suppressed because it is too large Load Diff
+1048 -366
View File
File diff suppressed because it is too large Load Diff
+1 -2
View File
@@ -68,7 +68,7 @@ Peter Saint-Andr\'e, Executive Director of the Jabber Software Foundation}
\item \marking{Internationalized:} \ejabberd{} leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
\begin{itemize}
\item Translated to 25 languages. %%\improved{}
\item Translated to 24 languages. %%\improved{}
\item Support for \footahref{http://www.ietf.org/rfc/rfc3490.txt}{IDNA}.
\end{itemize}
@@ -127,7 +127,6 @@ Moreover, \ejabberd{} comes with a wide range of other state-of-the-art features
\item Users Directory based on users vCards.
\item \txepref{0060}{Publish-Subscribe} component with support for \txepref{0163}{Personal Eventing via Pubsub}.
\item Support for web clients: \txepref{0025}{HTTP Polling} and \txepref{0206}{HTTP Binding (BOSH)} services.
\item IRC transport.
\item Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
\end{itemize}
\end{itemize}
Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

+17 -5
View File
@@ -135,6 +135,8 @@
- Implicit item deletion is not notified when deleting node
- Make PubSub x-data configuration form handles list value
- Make default node name convention XEP-compatible, document usage of hierarchy
- Node names are used verbatim, without separating by slash, unless a
node plugin uses its own separator
- Send authorization update event (XEP-0060, 8.6)
- Support of collection node subscription options
- Support ODBC storage. Experimental, needs more testing.
@@ -207,14 +209,24 @@
Upgrading From ejabberd 2.0.x:
- The database schemas didn't change since ejabberd 1.1.4.
Anyway, it is recommended to backup the Mnesia spool directory and
- The database schemas have three changes since ejabberd 2.0.x.
Check the database creation SQL files and update your database.
1) New table roster_version to support roster versioning.
2) Six new tables for optional pubsub ODBC storage.
3) Some tables in the MySQL database have a new created_at column.
- As usual, it is recommended to backup the Mnesia spool directory and
your SQL database (if used) before upgrading ejabberd.
- The plugin of mod_pubsub "default" is renamed to "flat". You need
to edit the ejabberd configuration file and replace those names.
- Between ejabberd 2.0.0 and 2.0.5, mod_pubsub used "default" as the
default node plugin. But in 2.1.0 this is renamed to "hometree".
You have to edit your ejabberd config file and replace those names.
If you used ejabberd 2.0.5 or older, the database will be updated
automatically. But if you were using ejabberd from SVN, you must
manually run ejabberdctl with the command: rename_default_nodeplugin.
Running this command on already updated database does nothing.
- The listener options 'ip' and inet6' are not documented anymore
- The listener options 'ip' and 'inet6' are not documented anymore
but they are supported and you can continue using them.
There is a new syntax to define IP address and IP version.
As usual, check the ejabberd Guide for more information.
+47
View File
@@ -0,0 +1,47 @@
Release Notes
ejabberd 2.1.1
ejabberd 2.1.1 is the first bugfix release in ejabberd 2.1.x branch.
ejabberd 2.1.1 includes several important bugfixes.
More details of those fixes can be retrieved from:
http://redir.process-one.net/ejabberd-2.1.1
The new code can be downloaded from ejabberd download page:
http://www.process-one.net/en/ejabberd/
The changes are:
* Core
- Call ejabberd_router:route/3 instead of sending a message
- Can't connect if starttls_required and zlib are set
- Routes vCard request to the occupant full JID, but should to bare JID
- S2S: fix allow_host/2 on subdomains. added hook s2s_allow_host
* MUC
- Support converting one-to-one chat to MUC
- Add support for serving a Unique Room Name
* Publish Subscribe
- Receive same last published PEP items at reconnect if several resources online
- Typo in mod_pubsub_odbc breaks Service Discovery and more
* Web
- Fix memory and port leak when TLS is enabled in HTTP
- WebAdmin doesn't report correct last activity with postgresql backend
- Option to define custom HTTP headers in mod_http_fileserver
- Show informative webpage when browsing the HTTP-Poll page
* Other
- Change captcha.sh to not depend on bash
- Generate main XML file also when exporting only a vhost
- Fix last newline in ejabberdctl result
- Guide: fix -setcookie, mod_pubsub_odbc host, content_types
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
+51
View File
@@ -0,0 +1,51 @@
Release Notes
ejabberd 2.1.2
ejabberd 2.1.2 is the second bugfix release in ejabberd 2.1.x branch.
ejabberd 2.1.2 includes several bugfixes.
More details of those fixes can be retrieved from:
http://redir.process-one.net/ejabberd-2.1.2
The new code can be downloaded from ejabberd download page:
http://www.process-one.net/en/ejabberd/
The major changes are:
* Core
- Close sessions that were half connected
- Fix SASL PLAIN authentication message for RFC4616 compliance
- Fix support for old Erlang/OTP R10 and R11
- Return proper error (not 'conflict') when register is forbidden by ACL
- When ejabberd stops, send stream close to clients
* ejabberdctl
- Check for EGID in ejabberdctl command
- Command to stop ejabberd informing users, with grace period
- If there's a problem in config file, display config lines and stop node
* MUC
- Kick occupants with reason when room is stopped due to MUC shutdown
- Write in room log when a room is created, destroyed, started, stopped
* PubSub and PEP
- Don't call gen_server on internal event (improves performance and scalability)
- Fix duplicate SHIM header in Pubsub message
- Notification messages of Pubsub node config change contained a SHIM header
- SubID SHIM header missing in Pubsub message with multiple
subscriptions on the same node
- PEP: last published item not sent from unavailable users when the
subscription is implicit (XEP-0115)
- pep_mapping not working due to Node type mismatch
* WebAdmin
- If big offline message queue, show only subset on WebAdmin
- Support in user list page of WebAdmin when mod_offline is disabled
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
+91
View File
@@ -0,0 +1,91 @@
Release Notes
ejabberd 2.1.3
ejabberd 2.1.3 is the third release in ejabberd 2.1.x branch.
ejabberd 2.1.3 includes many bugfixes, and some improvements.
More details of those fixes can be retrieved from:
http://redir.process-one.net/ejabberd-2.1.3
The new code can be downloaded from ejabberd download page:
http://www.process-one.net/en/ejabberd/
This is the full list of changes:
* Client connections
- Avoid 'invalid' value in iq record
- Avoid resending stream:error stanzas on terminate (EJAB-1180)
- Close also legacy sessions that were half connected (EJAB-1165)
- iq_query_info/1 now returns 'invalid' if XMLNS is invalid
- New ejabberd_c2s option support: max_fsm_queue
- Rewrite mnesia counter functions to use dirty_update_counter (EJAB-1177)
- Run user_receive_packet also when sending offline messages (EJAB-1193)
- Use p1_fsm behaviour in c2s FSM (EJAB-1173)
* Clustering
- Fix cluster race condition in route read
- New command to set master Mnesia node
- Use mnesia:async_dirty when cleaning table from failed node
* Documentation
- Add quotes in documentation of some erl arguments (EJAB-1191)
- Add option access_from (EJAB-1187)
- Add option max_fsm_queue (EJAB-1185)
- Fix documentation installation, no need for executable permission (EJAB-1170)
- Fix typo in EJABBERD_BIN_PATH (EJAB-891)
- Fix typos in example config comments (EJAB-1192)
* ejabberdctl
- Support concurrent connections with bound connection names
- Add support for Jot in ctl and TTY in debug
- Support help command names with old - characters
- Fix to really use the variable ERL_PROCESSES
* Erlang compatibility
- Don't call queue:filter/2 to keep compatibility with older Erlang versions
- Use alternative of file:read_line/1 to not require R13B02
* HTTP
- Add new debugging hook to the http receiving process
- Allow a request_handler to serve a file in root of HTTP
* HTTP-Bind (BOSH)
- Cross-domain HTTP-Bind support (EJAB-1168)
- Hibernate http-bind process after handling a request
- Reduce verbosity of HTTP Binding log messages
* LDAP
- Document ldap_dn_filter, fetch only needed attributes in search (EJAB-1204)
- Use "%u" pattern as default for ldap_uids (EJAB-1203)
* Localization
- Fix German translation (EJAB-1195)
- Fix Russian translation
* ODBC
- Fix MSSQL support, which was broken (EJAB-1201)
- Improved SQL reconnect behaviour
* Pubsub, PEP and Caps
- Add extended stanza addressing 'replyto' on PEP (EJAB-1198)
- Add pubsub#purge_offline (EJAB-1186)
- Fix pubsub#title option (EJAB-1190)
- Fix remove_user for node subscriptions (EJAB-1172)
- Optimizations in mod_caps
* Other
- mod_register: Add new acl access_from, default is to deny
- mod_sic: new module for the experimental XEP-0279 Server IP Check (EJAB-1205)
- PIEFXIS: Catch errors when exporting to PIEFXIS file (EJAB-1178)
- Proxy65: new option "hostname" (EJAB-838)
- Roster: Fix resending authorization problem
- Shared Roster Groups: get contacts nickname from vcard (EJAB-114)
- S2S: Improved s2s connections clean up (EJAB-1202)
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
+80
View File
@@ -0,0 +1,80 @@
Release Notes
ejabberd 2.1.4
ejabberd 2.1.4 is the fourth release in ejabberd 2.1.x branch,
and includes many small bugfixes and improvements.
Read more details about the changes in:
http://redir.process-one.net/ejabberd-2.1.4
Download the source code and installers from:
http://www.process-one.net/en/ejabberd/
This is the full list of changes:
* Authentication
- Extauth: Optionally cache extauth users in mnesia (EJAB-641)
- LDAP: Allow inband password change (EJAB-199)
- LDAP: Extensible match support (EJAB-722)
- LDAP: New option ldap_tls_verify is added (EJAB-1229)
- PAM: New option pam_userinfotype to provide username or JID (EJAB-652)
* HTTP
- Add xml default content type
- Don't show HTTP request in logs, because reveals password (EJAB-1231)
- Move HTTP session timeout log from warning level to info
- New Access rule webadmin_view for read-only
* HTTP-Bind (BOSH)
- Change max inactivity from 30 to 120 seconds
- Export functions to facilitate prebinding methods
- Use dirty_delete when removing the session
- Remove an unneeded delay of 100 milliseconds
* Pubsub, PEP and Caps
- Enforce pubsub#presence_based_delivery (EJAB-1221)
- Enforce pubsub#show_values subscription option (EJAB-1096)
- Fix error code when unsubscribing from a non-existent node
- Fix to send node notifications (EJAB-1225)
- Full support for XEP-0115 v1.5 (EJAB-1223)(EJAB-1189)
- Make last_item_cache feature to be cluster aware
- Prevent orphaned pubsub node (EJAB-1233)
- Send created node notifications
* Other
- Bounce messages when closing c2s session
- Bugfixes when handling Service Discovery to contacts (EJAB-1207)
- Compilation of ejabberd_debug.erl is now optional
- Don't send error stanza as reply to error stanza (EJAB-930)
- Don't store blocked messages in offline queue
- Reduce verbosity of log when captcha_cmd is checked but not configured
- Use a standard method to get a random seed (EJAB-1229)
- Commands: new update_list and update to update modified modules (EJAB-1237)
- Localization: Updated most translations
- MUC: Refactor code to reduce calls to get_affiliation and get_role
- ODBC: Add created_at column also to PostgreSQL schema
- Vcard: Automatic vcard avatar addition in presence
Upgrading From previous ejabberd releases:
- If you use PostgreSQL, maybe you want to add the column created_at
to several tables. This is only a suggestion; ejabberd doesn't use
that column. Add it to your existing database executing those SQL
statements:
ALTER TABLE users ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
ALTER TABLE rosterusers ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
ALTER TABLE spool ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
ALTER TABLE vcard ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
ALTER TABLE privacy_list ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
ALTER TABLE privacy_storage ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now();
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
+70
View File
@@ -0,0 +1,70 @@
Release Notes
ejabberd 2.1.5
ejabberd 2.1.5 is the fifth release in ejabberd 2.1.x branch,
and includes several minor bugfixes and a few improvements.
Read more details about the changes in:
http://redir.process-one.net/ejabberd-2.1.5
Download the source code and installers from:
http://www.process-one.net/en/ejabberd/
This is the full list of changes:
* Authentication
- Extauth: Support parallel script running (EJAB-1280)
- mod_register: Return Registered element when account exists
* ejabberdctl
- Fix print of command result that contains ~
- Fix problem when FIREWALL_WINDOW options for erl kernel were used
- Fix typo in update_list command (EJAB-1237)
- Some systems delete the lock dir; in such case don't use flock at all
- The command Update now returns meaningful message and exit-status (EJAB-1237)
* HTTP-Bind (BOSH)
- Don't say v1.2 in the Bind HTTP page
- New optional BOSH connection attribute process-delay (EJAB-1257)
* MUC
- Document the mod_muc option captcha_protected
- Now admins are able to see private rooms in disco (EJAB-1269)
- Show some more room options in the log file
* ODBC
- Correct handling of SQL boolean types (EJAB-1275)
- Discard too old queued requests (the caller has already got a timeout)
- Fixes wrong SQL escaping when --enable-full-xml is set
- Use ets insead of asking supervisor in ejabberd_odbc_sup:get_pids/1
* Pubsub, PEP and Caps
- Enforce disco features results (EJAB-1033, EJAB-1228, EJAB-1238)
- Support all the hash functions required by Caps XEP-0115
* Requirements
- Fixed support for Erlang R12; which doesn't support: true andalso ok
- Support OTP R14A by using public_key library instead of old ssl (EJAB-953)
- Requirement of OpenSSL increased from 0.9.6 to 0.9.8
- OpenSSL is now required, not optional
* Other
- Don't ask for client certificate when using tls (EJAB-1267)
- Fix typo in --enable-transient_supervisors
- Fix privacy check when serving local Last (EJAB-1271)
- Inform client that SSL session caching is disabled
- New configure option: --enable-nif
- Use driver allocator in C files for reflecting memory in erlang:memory(system)
- Debug: New p1_prof compiled with: make debugtools=true
- Debug: Added functions to collect stats about queues, memory, reductions etc
- HTTP: Log error if request has ambiguous Host header (EJAB-1261)
- Logs: When logging s2s out connection attempt or success, log if TLS is used
- Shared Rosters: When account is deleted, delete also member of stored rosters
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
+67
View File
@@ -0,0 +1,67 @@
Release Notes
ejabberd 2.1.6
ejabberd 2.1.6 is the sixth release in ejabberd 2.1.x branch,
and includes a lot of bugfixes and improvements.
Read more details about the changes in:
http://redir.process-one.net/ejabberd-2.1.6
Download the source code and installers from:
http://www.process-one.net/en/ejabberd/
Some of the changes are:
* Account register
- mod_register: New ip_access option restricts which IPs can register (EJAB-915)
- mod_register: Default configuration allows registrations only from localhost
- mod_register: New password_strength for entropy check (EJAB-1326)
- mod_register: New captcha_protected option to require CAPTCHA (EJAB-1262)
- mod_register_web: New module, with CAPTCHA support (EJAB-471)
* BOSH
- Don't loop when there is nothing after a stream start (EJAB-1358)
- Fix http-bind supervisor to support multiple vhosts (EJAB-1321)
- Support to restart http-bind (EJAB-1318)
- Support for X-Forwarded-For HTTP header (EJAB-1356)
* Erlang/OTP compatibility
- R11: Fix detection of Erlang R11 and older (EJAB-1287)
- R12B5: Fix compatibility in ejabberd_http_bind.erl (EJAB-1343)
- R14A: Make xml.c correctly compile (EJAB-1288)
- R14A, R14B: Disapprove the use of R14A and R14B due to the rwlock bug
- R14B: Use pg2 from this version in systems with older ones (EJAB-1349)
* Listeners
- Bind listener ports early and start accepting connections later
- Fix a leak of ejabberd_receiver processes
- Speed up ejabberd_s2s:is_service/2, allow_host/2 (EJAB-1319)
- S2S: New option to require encryption (EJAB-495)
- S2S: New option to reject connection if untrusted certificate (EJAB-464)
- S2S: Include From attribute in the stream header of outgoing S2S connections
- S2S: Fix domain_certfile tlsopts modifications for S2S connections (EJAB-1086)
* Pubsub/PEP/Caps
- Fix pubsub cross domain eventing (EJAB-1340)
- Use one_queue IQ discipline by default
- Implement lifetime for broken hashes
- New CAPS processing
* ODBC
- Increase maximum restart strategy to handle some SQL timeouts
- Support PostgreSQL 9.0 (EJAB-1359)
- Use MEDIUMTEXT type for vcard avatars in MySQL schema (EJAB-1252)
* Miscellanea:
- mod_shared_roster_ldap: New Shared Roster Groups using LDAP information
- mod_privacy: Fix to allow block by group and subscription again
- Support timezone West of UTC (EJAB-1301)
- Support to change loglevel per module at runtime (EJAB-225)
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
+104
View File
@@ -0,0 +1,104 @@
******************************************************************************
* These are the preliminary release notes of ejabberd 3.0.0.
*
* The download page for preliminary releases is:
* http://download.process-one.net/ejabberd/
*
* WARNING!!! PRELIMINARY DATABASE SCHEMA !!!
* The database schema may change before ejabberd 3.0.0 is released,
* and no migration code will be developed for this preliminary schema.
* The only supported migrations are
* from any ejabberd 0.9.0 ... 2.1.x to the final 3.0.0.
* Don't use this preliminary ejabberd release for a production server.
* You can test this release with a blank database or with a copy of your
* production database, but don't let your users connect to this copy
* because their changes may get lost when you upgrade to the final 3.0.0.
******************************************************************************
Release Notes
ejabberd 3.0.0
ejabberd 3.0.0 is the first release in the brand new 3.x.x branch,
and includes several minor bugfixes and a few improvements.
Read more details about the changes in:
http://redir.process-one.net/ejabberd-3.0.0
Download the source code and installers from:
http://www.process-one.net/en/ejabberd/
ejabberd 3.0.0 includes three major changes:
* exmpp is now extensively used in ejabberd for parsing stanzas, and many more.
* gen_storage (abbreviated GS) provides a database abstraction layer,
which supports storage in Mnesia and in ODBC databases.
Several ejabberd modules use GS, like mod_roster and ejabberd_auth_storage.
The schema of the tables stored by those modules have changed.
ejabberd automatically creates mnesia and ODBC tables,
and migrates them from a previous ejabberd version.
* Massive Hosting (abbreviated MH) is preliminary implemented in ejabberd,
but it is still incomplete, untested and undocumented.
This is a more detailed list of changes since ejabberd 2.1.x releases:
* Requirements
- Erlang/OTP R12B-5 or higher is required
- exmpp 0.9.6 or higher is required, not optional
- ESASL library is optional, for SASL GSSAPI authentication
- Libexpat not required by ejabberd, it uses exmpp now (EJAB-1111)
- GNU Iconv not required, because mod_irc isn't included anymore (EJAB-954)
- Only database migration from ejabberd 0.9.0 up to 2.1.x is supported
- ejabberd modules developed for previous releases need to be upgraded to exmpp
* Configuration
- New option clusterid
- New option that can't be used yet: static_modules
- ejabberd_auth_storage: new option auth_storage
- mod_muc_log: option spam_prevention is now link_nofollow (EJAB-1141)
- mod_roster: new access option (EJAB-72)
- S2S: allow definition of local address for outgoing connections (EJAB-418)
* Database
- New gen_storage that provides a database storage abstraction layer (EJAB-1102)
- mod_*_odbc are obsolete, use the normal ones with the option {backend, odbc}
- New ejabberd_auth_storage that supports internal and odbc databases
* XEP support
- Removed support for the deprecated XEP-0018 Invisible Presence (EJAB-810)
- mod_multicast: service for XEP-0033: Extended Stanza Addressing (EJAB-265)
- New ejabberd router for multicast packets (XEP-0033) (EJAB-329)
- ejabberd_c2s uses XEP-0033 if mod_multicast is enabled (EJAB-267)
- mod_muc uses XEP-0033 if mod_multicast is enabled (EJAB-266)
* Pubsub/PEP/Caps
- Allow distinguish between leafs and items (EJAB-1027)
- Enforce disco features results (EJAB-1033, EJAB-1228, EJAB-1238)
- Enforce pubsub#presence_based_delivery (EJAB-1221)
- Improve get_caps while still waiting for initial presence (EJAB-934)
- Make nodetree_tree implicitly create parent node if required (EJAB-944)
- Only use binary() instead of string() in Host and ServerHost (EJAB-1244)
- Rename NodeId (pubsub_node.id) bindings to Nidx (EJAB-1000)
- node_flat becomes default; it has the code instead of hometree (EJAB-1077)
- pubsub#notify_sub node option (EJAB-1230)
- pubsub#type node config and payload namespace (EJAB-1083)
* Miscellanea
- Bugfix handling Service Discovery to contacts (EJAB-1207)
- Bugfix: external contacts were offline after unavailable presence (EJAB-943)
- Don't offer SASL auth before doing TLS if TLS is required
- Experimental support for GSSAPI auth, requires esasl library (EJAB-831)
- Use binaries instead of lists where possible (EJAB-17)
- Windows ejabberdctl.cmd only handles up to 4 arguments (EJAB-1216)
- ejabberdctl: when starting, check it isn't already running
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
-2
View File
@@ -1,2 +0,0 @@
% ejabberd version (automatically generated).
\newcommand{\version}{2.1.0}
-75
View File
@@ -1,75 +0,0 @@
#!/bin/sh
#
# PROVIDE: ejabberd
# REQUIRE: DAEMON
# KEYWORD: shutdown
#
HOME=/usr/pkg/jabber D=/usr/pkg/jabber/ejabberd export HOME
name="ejabberd"
rcvar=$name
if [ -r /etc/rc.conf ]
then
. /etc/rc.conf
else
eval ${rcvar}=YES
fi
# $flags from environment overrides ${rcvar}_flags
if [ -n "${flags}" ]
then
eval ${rcvar}_flags="${flags}"
fi
checkyesno()
{
eval _value=\$${1}
case $_value in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0 ;;
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1 ;;
*)
echo "\$${1} is not set properly."
return 1
;;
esac
}
cmd=${1:-start}
case ${cmd} in
force*)
cmd=${cmd#force}
eval ${rcvar}=YES
;;
esac
if checkyesno ${rcvar}
then
else
exit 0
fi
case ${cmd} in
start)
if [ -x $D/src ]; then
echo "Starting ${name}."
cd $D/src
ERL_MAX_PORTS=32000 export ERL_MAX_PORTS
ulimit -n $ERL_MAX_PORTS
su jabber -c "/usr/pkg/bin/erl -sname ejabberd -s ejabberd -heart -detached -sasl sasl_error_logger '{file, \"ejabberd-sasl.log\"}' &" \
1>/dev/null 2>&1
fi
;;
stop)
echo "rpc:call('ejabberd@`hostname -s`', init, stop, [])." | \
su jabber -c "/usr/pkg/bin/erl -sname ejabberdstop"
;;
restart)
echo "rpc:call('ejabberd@`hostname -s`', init, restart, [])." | \
su jabber -c "/usr/pkg/bin/erl -sname ejabberdrestart"
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
-81
View File
@@ -1,81 +0,0 @@
#!/bin/sh
echo '1. fetch, compile, and install erlang'
if [ ! pkg_info erlang 1>/dev/null 2>&1 ]; then
cd /usr/pkgsrc/lang/erlang
make fetch-list|sh
make
make install
fi
if pkg_info erlang | grep -q erlang-9.1nb1; then
else
echo "erlang-9.1nb1 not installed" 1>&2
exit 1
fi
echo '2. install crypt_drv.so'
if [ ! -d /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib ] ; then
mkdir -p /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
fi
if [ ! -f /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib/crypto_drv.so ]; then
cp work/otp*/lib/crypto/priv/*/*/crypto_drv.so \
/usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
fi
echo '3. compile and install elibcrypto.so'
if [ ! -f /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib/elibcrypto.so ]; then
cd /usr/pkgsrc/lang/erlang/work/otp_src_R9B-1/lib/crypto/c_src
ld -r -u CRYPTO_set_mem_functions -u MD5 -u MD5_Init -u MD5_Update \
-u MD5_Final -u SHA1 -u SHA1_Init -u SHA1_Update -u SHA1_Final \
-u des_set_key -u des_ncbc_encrypt -u des_ede3_cbc_encrypt \
-L/usr/lib -lcrypto -o ../priv/obj/i386--netbsdelf/elibcrypto.o
cc -shared \
-L/usr/pkgsrc/lang/erlang/work/otp_src_R9B-1/lib/erl_interface/obj/i386--netbsdelf \
-o ../priv/obj/i386--netbsdelf/elibcrypto.so \
../priv/obj/i386--netbsdelf/elibcrypto.o -L/usr/lib -lcrypto
cp ../priv/obj/i386--netbsdelf/elibcrypto.so \
/usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
fi
echo '4. compile and install ssl_esock'
if [ ! -f /usr/pkg/lib/erlang/lib/ssl-2.3.5/priv/bin/ssl_esock ]; then
cd /usr/pkg/lib/erlang/lib/ssl-2.3.5/priv/obj/
make
fi
echo '5. initial ejabberd configuration'
cd /usr/pkg/jabber/ejabberd/src
./configure
echo '6. edit ejabberd Makefiles'
for M in Makefile mod_*/Makefile; do
if [ ! -f $M.orig ]; then
mv $M $M.orig
sed -e s%/usr/local%/usr/pkg%g < $M.orig > $M
fi
done
echo '7. compile ejabberd'
gmake
for A in mod_irc mod_muc mod_pubsub; do
(cd $A; gmake)
done
echo ''
echo 'now edit ejabberd.cfg'
echo ''
echo 'to start ejabberd: erl -sname ejabberd -s ejabberd'
-66
View File
@@ -1,66 +0,0 @@
% jabber.dbc.mtview.ca.us
override_acls.
{acl, admin, {user, "mrose", "jabber.dbc.mtview.ca.us"}}.
{access, announce, [{allow, admin},
{deny, all}]}.
{access, c2s, [{deny, blocked},
{allow, all}]}.
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
{access, configure, [{allow, admin},
{deny, all}]}.
{access, disco_admin, [{allow, admin},
{deny, all}]}.
{access, muc_admin, [{allow, admin},
{deny, all}]}.
{access, register, [{deny, all}]}.
{access, s2s_shaper, [{fast, all}]}.
{auth_method, internal}.
{host, "jabber.dbc.mtview.ca.us"}.
{outgoing_s2s_port, 5269}.
{shaper, normal, {maxrate, 1000}}.
{shaper, fast, {maxrate, 50000}}.
{welcome_message, none}.
{listen, [{5222, ejabberd_c2s,
[{access, c2s},
{shaper, c2s_shaper}]},
{5223, ejabberd_c2s,
[{access, c2s},
{shaper, c2s_shaper},
{ssl, [{certfile, "/etc/openssl/certs/ejabberd.pem"}]}]},
{5269, ejabberd_s2s_in,
[{shaper, s2s_shaper}]}]}.
{modules, [
{mod_register, []},
{mod_roster, []},
{mod_privacy, []},
{mod_configure, []},
{mod_disco, []},
{mod_stats, []},
{mod_vcard, []},
{mod_offline, []},
{mod_echo, [{host, "echo.jabber.dbc.mtview.ca.us"}]},
{mod_private, []},
% {mod_irc, []},
{mod_muc, []},
{mod_pubsub, []},
{mod_time, []},
{mod_last, []},
{mod_version, []}
]}.
% Local Variables:
% mode: erlang
% End:
@@ -1,77 +0,0 @@
<!-- aim-transport.xml -->
<jabber>
<!--
You need to add elogger and rlogger entries when using ejabberd.
In this case the transport will do the logging.
-->
<log id='elogger'>
<host/>
<logtype/>
<format>%d: [%t] (%h): %s</format>
<file>/var/log/jabber/aim-transport-error.log</file>
</log>
<log id='rlogger'>
<host/>
<logtype>record</logtype>
<format>%d %h %s</format>
<file>/var/log/jabber/aim-transport-record.log</file>
</log>
<!--
ejabberd do not provide XDB services.
xdb_file.so is loaded in to handle all XDB requests.
-->
<xdb id="xdb">
<host/>
<load>
<xdb_file>/usr/local/lib/jabber/libjabberdxdbfile.so</xdb_file> <!-- This file is part of jabberd-1.4.x. -->
</load>
<xdb_file xmlns="jabber:config:xdb_file">
<spool><jabberd:cmdline flag='s'>/var/spool/jabber</jabberd:cmdline></spool>
</xdb_file>
</xdb>
<!--
Make sure that all host names here are resolveable via DNS if you
want the transport to be available to the public.
-->
<service id='aim.SERVER.COM'>
<!-- aim-transport configuration. -->
<aimtrans xmlns='jabber:config:aimtrans'>
<vCard>
<FN>AIM/ICQ Transport</FN>
<DESC>This is the AIM/ICQ Transport.</DESC>
<MAIL>EMAIL@ADDRESS.COM</MAIL>
<URL>http://aim-transport.jabberstudio.org/</URL>
</vCard>
<charset>cp1252</charset>
</aimtrans>
<!-- aim-transport module. -->
<load>
<aim_transport>/usr/local/lib/jabber/aim-transport.so</aim_transport>
</load>
</service>
<!--
The settings below have to match the settings you made
in your ejabberd.cfg configuration file.
-->
<service id="icq-linker">
<uplink/>
<connect>
<ip>127.0.0.1</ip>
<port>5233</port>
<secret>SECRET</secret>
</connect>
</service>
<pidfile>/var/run/jabber/aim-transport.pid</pidfile>
</jabber>
-136
View File
@@ -1,136 +0,0 @@
<!-- ile.xml -->
<config>
<jabber>
<server>127.0.0.1</server>
<port>5238</port>
<secret>SECRET</secret>
<service>ile.SERVER.COM</service>
<connectsleep>7</connectsleep> <!-- seconds to wait if we get disconnected -->
<language>en</language>
<vCard>
<FN>I Love Email</FN>
<DESC>With this service you can receive email notifications.
Security warning: Be careful when using this. Your password will travel in clear from your client to your jabber server if you don't use SSL and it will probably travel in clear from the jabber server to your email server. Use with care. This shouldn't be an issue in your Intranet, but it is if you use an ILE installed in a foreign jabber server.</DESC>
<MAIL>EMAIL@ADDRESS.COM</MAIL>
<URL>http://ile.jabberstudio.org/</URL>
</vCard>
</jabber>
<debug>
<file>/var/log/jabber/ile.log</file>
<level>1</level> <!-- man Net::Jabber::Debug -->
</debug>
<mail>
<checkinterval>10</checkinterval> <!-- in minutes -->
<timeout>20</timeout> <!-- timeout for IMAP/POP connection, in seconds -->
</mail>
<files>
<users>/var/spool/jabber/ile.SERVER.COM/users.db</users>
<passwords>/var/spool/jabber/ile.SERVER.COM/passwords.db</passwords>
<hosts>/var/spool/jabber/ile.SERVER.COM/hosts.db</hosts>
<types>/var/spool/jabber/ile.SERVER.COM/types.db</types>
<notifyxa>/var/spool/jabber/ile.SERVER.COM/notifyxa.db</notifyxa>
<notifydnd>/var/spool/jabber/ile.SERVER.COM/notifydnd.db</notifydnd>
<urls>/var/spool/jabber/ile.SERVER.COM/urls.db</urls>
</files>
<form>
<en>
<instructions>Please fill in the fields,according to your email account settings and notification preferences</instructions>
<title>ILE: Email notification service</title>
<email_options>Email account settings</email_options>
<user>Username</user>
<pass>Password</pass>
<host>Hostname</host>
<type>Type</type>
<newmail>You have received NUM email messages since last time I checked, which was CHECKINTERVAL minutes ago.</newmail>
<errorcheck>There was an error while trying to check mail for ACCOUNT.</errorcheck>
<notify_options>Notification Options</notify_options>
<notifyxa>Notify even when Xtended Away (XA)</notifyxa>
<notifydnd>Notify even when Do Not Disturb (DND)</notifydnd>
<webmail_url>Webmail URL</webmail_url>
<webmail_login>Login to ACCOUNT</webmail_login>
<iledesc>ILE: an email notifier component: http://ile.jabberstudio.org</iledesc>
</en>
<es>
<instructions>Por favor, rellene los campos del formulario.</instructions>
<title>ILE: Servicio de notificación de correo</title>
<email_options>Configuración de la cuenta de correo</email_options>
<user>Usuario</user>
<pass>Clave</pass>
<host>Host</host>
<type>Tipo</type>
<newmail>Ha recibido NUM email(s) desde la última comprobación que fue hace CHECKINTERVAL minutos</newmail>
<errorcheck>Ha habido un error en la comprobación del correo para la cuenta ACCOUNT.</errorcheck>
<notify_options>Opciones de notificación</notify_options>
<notifyxa>Notificar incluso si muy ausente (XA)</notifyxa>
<notifydnd>Notificar incluso si no molestar (DND)</notifydnd>
<webmail_url>Webmail URL</webmail_url>
<webmail_login>Leer correo de ACCOUNT</webmail_login>
<iledesc>ILE: un notificador de nuevo email - http://ile.jabberstudio.org</iledesc>
</es>
<ca>
<instructions>Ompli els camps del formulari.</instructions>
<title>ILE: Servei de notificació de nou email</title>
<email_options>Dades del compte de mail</email_options>
<user>Usuari</user>
<pass>Clau</pass>
<host>Host</host>
<type>Tipus</type>
<newmail>Ha rebut NUM email(s) des de la última comprobació que va ser fa CHECKINTERVAL minuts.</newmail>
<errorcheck>S'ha produit un error en la comprobació del correu per al compte ACCOUNT.</errorcheck>
<notify_options>Opcions de notificació</notify_options>
<notifyxa>Notificar si molt absent (XA)</notifyxa>
<notifydnd>Notificar si no molestar (DND)</notifydnd>
<webmail_url>Webmail URL</webmail_url>
<webmail_login>Llegir correu de ACCOUNT</webmail_login>
<iledesc>ILE: un notificador de nou email - http://ile.jabberstudio.org</iledesc>
</ca>
<ro>
<!-- Contributed by Adrian Rappa -->
<instructions>Va rog completati urmatoarele campuri</instructions>
<title>I Love Email: new email notification service</title>
<email_options>Email account settings</email_options>
<user>Nume utilizator</user>
<pass>Parola</pass>
<host>Nume gazda</host>
<type>Tip</type>
<newmail>Ati primit NUM mesaj(e) de la ultima verificare, care a fost acum CHECKINTERVAL minute.</newmail>
<errorcheck>A fost eroare in timp ce incercam sa verific posta pentru ACCOUNT.</errorcheck>
<notify_options>Notification Options</notify_options>
<notifyxa>Notify even when Xtended Away (XA)</notifyxa>
<notifydnd>Notify even when Do Not Disturb (DND)</notifydnd>
<webmail_url>Webmail URL</webmail_url>
<webmail_login>Login to ACCOUNT</webmail_login>
<iledesc>ILE: an email notifier component: http://ile.jabberstudio.org</iledesc>
</ro>
<nl>
<!-- Contributed by Sander Devrieze -->
<instructions>Vul volgende velden in.</instructions>
<title>ILE: Dienst voor e-mailnotificaties</title>
<email_options>Instellingen van e-mailaccount</email_options>
<user>Gebruikersnaam</user>
<pass>Wachtwoord</pass>
<host>Inkomende mailserver</host>
<type>Type verbinding</type>
<newmail>U hebt NUM berichten ontvangen sinds CHECKINTERVAL minuten geleden.</newmail>
<errorcheck>Fout tijdens controle op nieuwe e-mails bij ACCOUNT. ILE zal deze account niet meer opnieuw controleren tot u uw registratiegegevens wijzigt of opnieuw aanmeldt.</errorcheck>
<notify_options>Notificatie-instellingen</notify_options>
<notifyxa>Notificeer ook in de status Niet Beschikbaar (XA)</notifyxa>
<notifydnd>Notificeer ook in de status Niet Storen (DND)</notifydnd>
<webmail_url>URL van webmail</webmail_url>
<webmail_login>Aanmelden op ACCOUNT</webmail_login>
<iledesc>ILE: een dienst om e-mailnotificaties te ontvangen: http://ile.jabberstudio.org</iledesc>
</nl>
</form>
</config>
@@ -1,149 +0,0 @@
<jggtrans>
<service jid="gg.SERVER.COM"/>
<!-- This connects the jabber-gg-transport process to ejabberd. -->
<connect id="gglinker">
<ip>127.0.0.1</ip>
<port>5237</port>
<secret>SECRET</secret>
</connect>
<register>
<!-- This tag contains the message displayed to users at registration time.
You can use <p/> and/or <br/> to break lines. Multiple spaces and newlines
are converted to just one, so formatting of config file doesn't really matter. -->
<instructions>
Fill in your GG number (after "username")
and password to register on the transport.
<p/>To change your information in the GaduGadu directory you need to fill in the other fields.
<p/>To remove registration you need to leave the form blank.
</instructions>
</register>
<search>
<!-- This tag contains the message displayed to users at search time. -->
<instructions>
To search people:<br/>
First fill in surname or family name, nickname, city, birthyear or range of birthyears (eg. 1950-1960)
and gender (you may fill in more fields at once).<br/>
or<br/>
Fill in phone number<br/>
or<br/>
Fill in the GG number of the person you are searching.
</instructions>
</search>
<gateway>
<!-- This is message, that may be displayed to user when adding gg contact. -->
<desc>Please fill in the GaduGadu number of the person you want to add.</desc>
<!-- And this is the prompt for GG number. -->
<prompt>GG Nummer</prompt>
</gateway>
<vCard>
<FN>Gadu-Gadu Transport</FN>
<DESC>This is the Gadu-Gadu Transport.</DESC>
<EMAIL>EMAIL@ADDRESS.COM</EMAIL>
<URL>http://www.jabberstudio.org/projects/jabber-gg-transport/</URL>
</vCard>
<!-- Default user locale (language).
Empty means system locale setting,
no (or commented-out) <default_locale> tag means no translations. -->
<!-- <default_locale>pl_PL</default_locale> -->
<!-- Logger configuration.
You may configure one logger of type "syslog" and/or one of type "file".
You may also not configure logging at all. -->
<log type="syslog" facility="local0"/>
<log type="file">/var/log/jabber/jabber-gg-transport.log</log>
<!-- Uncomment this, if you want proxy to be used for Gadu-Gadu connection. -->
<!--
<proxy>
<ip>127.0.0.1</ip>
<port>8080</port>
</proxy>
-->
<!-- You can change these values according to your needs. -->
<conn_timeout>60</conn_timeout>
<ping_interval>10</ping_interval>
<!-- Gadu-Gadu server doesn't seem to answer pings anymore :-(
So let's give it 10 year :-) -->
<pong_timeout>315360000</pong_timeout>
<!-- This time after disconnection from Gadu-Gadu server the transport
will try to connect again. -->
<reconnect>300</reconnect>
<!-- How long to wait before restart, after jabber server connection is broken
negative value means, that jggtrans should terminate. -->
<restart_timeout>60</restart_timeout>
<!-- Delay between the unavailable presence is received from user and loggin out
from Gadu-Gadu - for nice <presence type="invisible"/> support. -->
<disconnect_delay>5</disconnect_delay>
<!-- list of Gadu-Gadu servers to use.
<hub/> means "use GG hub to find server"
<server/> tag should contain server address and may contain "port"
attribute with port number. When TLS is available (supported by libgadu)
it will be used unless "tls" attribute is set to "no". Please notice,
that not all servers will accept TLS connections.
Servers (including hub) are tried in order as they appear in <servers/>
element.
A reasonable default server list is hardcoded in jggtrans.
-->
<!--
<servers>
<hub/>
<server port="443">217.17.41.90</server>
<server tls="no">217.17.41.85</server>
<server tls="no">217.17.41.88</server>
</servers>
-->
<!-- Spool directory. This is the place, where user info will be stored. -->
<!-- Be careful about permissions - users' Gadu-Gadu passwords are stored there. -->
<spool>/var/spool/jabber/gg.SERVER.COM/</spool>
<!-- Where to store pid file. This tag is optional. -->
<pidfile>/var/run/jabber/jabber-gg-transport.pid</pidfile>
<!-- jid allowed to do some administrative task (eg. discovering online users).
May be used multiple times. -->
<admin>GG_TRANSPORT_ADMIN@SERVER.COM</admin>
<!-- ACL gives detailed access control to the transport. -->
<acl>
<!-- Example entries: -->
<allow who="admin@SERVER.COM" what="iq/query?xmlns=http://jabber.org/protocol/stats"/>
<!-- will allow statistics gathering to admin@SERVER.COM -->
<deny who="*" what="iq/query?xmlns=http://jabber.org/protocol/stats"/>
<!-- will deny statistics gathering for anybody else -->
<!-- <allow who="*@SERVER.COM"/> -->
<!-- will allow anything else to users from "SERVER.COM" -->
<!-- <deny what="iq/query?xmlns=jabber:x:register"/> -->
<!-- will deny registration for all other users -->
<!-- <allow what="presence"/> -->
<!-- allow presence from anybody -->
<!-- <allow what="iq"/> -->
<!-- allow iq from anybody -->
<!-- <allow what="message"/> -->
<!-- allow message from anybody -->
<!-- <deny/> -->
<!-- will deny anything else -->
</acl>
</jggtrans>
-128
View File
@@ -1,128 +0,0 @@
<!-- jit.xml -->
<jabber>
<!--
You need to add elogger and rlogger entries here when using ejabberd.
In this case the transport will do the logging.
-->
<log id='elogger'>
<host/>
<logtype/>
<file>/var/log/jabber/jit-error</file> <!-- WPJabber logs with date. -->
</log>
<log id='rlogger'>
<host/>
<logtype>record</logtype>
<file>/var/log/jabber/jit-record</file> <!-- WPJabber logs with date. -->
</log>
<!--
ejabberd do not provide XDB services.
xdb_file-jit.so (the renamed xdb_file.so from WPJabber) is
loaded in to handle all XDB requests.
Read also the documentation in xdb_file/README from the JIT package.
-->
<xdb id="xdb">
<host/>
<load>
<xdb_file>/usr/local/lib/jabber/xdb_file.so</xdb_file> <!-- The xdb_file.so from WPJabber/JIT. -->
</load>
<xdb_file xmlns="jabber:config:xdb_file">
<spool><jabberd:cmdline flag='s'>/var/spool/jabber</jabberd:cmdline></spool>
</xdb_file>
</xdb>
<!--
Make sure that all host names here are resolveable via DNS if you
want the transport to be available to the public.
-->
<service id="icq.SERVER.COM">
<!--
Replace SERVER.COM with the same as above to enable sms.
-->
<host>sms.icq.SERVER.COM</host>
<!-- JIT configuration. -->
<icqtrans xmlns="jabber:config:icqtrans">
<sms>
<host>sms.icq.SERVER.COM</host>
<!-- Status of virtual "sms-contacts". -->
<show>away</show>
<status/>
</sms>
<instructions>Fill in your UIN and password.</instructions>
<search>Search ICQ users.</search>
<vCard>
<FN>ICQ Transport (JIT)</FN>
<DESC>This is the Jabber ICQ Transport.</DESC>
<MAIL>EMAIL@ADDRESS.COM</MAIL>
<URL>http://jit.jabberstudio.org/</URL>
</vCard>
<!-- Hashtable for users. -->
<prime>3907</prime>
<!-- Send messages from ICQ as chat to Jabber clients. -->
<chat/>
<!-- Enable this for ICQ web presence. -->
<web/>
<!--
If you don't want jabber:x:data forms
in reg and search uncomment this tag
(Not recomended).
-->
<no_xdata/>
<!--
This tag is necessary when using ejabberd.
In this way JIT will have its own contact list.
-->
<own_roster/>
<!--
When present, this tag will tell JIT not to try to
get the user's roster (which will take a bit of time
to fail in scenarios described above).
-->
<no_jabber_roster/>
<!-- File with stats. -->
<user_count_file>/var/spool/jabber/jit-count</user_count_file>
<!--
Interval beetween checking sessions: ping, messages, acks.
-->
<session_check>5</session_check>
<!-- Reconnect retries. -->
<reconnects>5</reconnects>
<!--
Time in sec when session can be inactive, 0=disabled.
-->
<session_timeout>18000</session_timeout>
<charset>windows-1252</charset>
<server>
<host port="5190">login.icq.com</host>
</server>
</icqtrans>
<!-- JIT module. -->
<load>
<icqtrans>/usr/local/lib/jabber/jit.so</icqtrans>
</load>
</service>
<!--
The settings below have to match the settings you made
in your ejabberd.cfg configuration file.
-->
<service id="icq-linker">
<host>SERVER.COM</host>
<uplink/>
<connect>
<ip>127.0.0.1</ip>
<port>5234</port>
<secret>SECRET</secret>
</connect>
</service>
<pidfile>/var/run/jabber/jit.pid</pidfile>
</jabber>
@@ -1,118 +0,0 @@
<!-- msn-transport.xml -->
<jabber>
<!--
You need to add elogger and rlogger entries here when using ejabberd.
In this case the transport will do the logging.
-->
<log id='elogger'>
<host/>
<logtype/>
<format>%d: [%t] (%h): %s</format>
<file>/var/log/jabber/msn-transport-error.log</file>
</log>
<log id='rlogger'>
<host/>
<logtype>record</logtype>
<format>%d %h %s</format>
<file>/var/log/jabber/msn-transport-record.log</file>
</log>
<!--
ejabberd do not provide XDB services.
xdb_file.so is loaded in to handle all XDB requests.
-->
<xdb id="xdb">
<host/>
<load>
<xdb_file>/usr/local/lib/jabber/libjabberdxdbfile.so</xdb_file>
</load>
<xdb_file xmlns="jabber:config:xdb_file">
<spool><jabberd:cmdline flag='s'>/var/spool/jabber</jabberd:cmdline></spool>
</xdb_file>
</xdb>
<!--
Make sure that all host names here are resolveable via DNS if you
want the transport to be available to the public.
-->
<service id="msn.SERVER.COM">
<!-- msn-transport configuration. -->
<msntrans xmlns="jabber:config:msntrans">
<instructions>Fill in your MSN account and password (eg: user1@hotmail.com). A nickname is optional.</instructions>
<vCard>
<FN>MSN Transport</FN>
<DESC>This is the MSN Transport.</DESC>
<EMAIL>EMAIL@ADDRESS.COM</EMAIL>
<URL>http://msn-transport.jabberstudio.org/</URL>
</vCard>
<!--
Conference support allows you to create groupchat rooms on the
msn-transport and invite MSN users to join.
-->
<conference id="conference.msn.SERVER.COM">
<!--
This will make MSN transport invite you to a special groupchat
room when more then one user joins a normal one-on-one session.
Joining this room will make MSN transport "switch" the session
into groupchat mode. If you ignore it, MSN transport will
continue to send the messages as one-on-one chats.
-->
<invite>More than one user entered this chat session. Enter this room to switch to groupchat modus.</invite>
<notice>
<join> is available</join>
<leave> has leaved the room</leave>
</notice>
</conference>
<!-- Enable Hotmail inbox notification. -->
<headlines/>
<!--
Enable fancy friendly names
If the user enters a nickname upon registration, and the user has
a status message, their MSN friendly name will be "nickname - status message".
If the user does not enter a nickname on registration, but they do have
a status message, their friendly name will just be their status message.
If the user did enter a nickname on registration, but they have a blank status message,
then their friendly name will just be the registered nickname.
If the user did not enter a nickname on registration, and they have a blank status message,
their nickname will just be the username portion of their JID.
If the above chosen friendly name is too long, then it will be truncated and "..." placed
at the end. MSN only supports friendly names of 128 characters, so this is unavoidable.
If this is disabled, then the registered nick is always sent as the MSN friendly name,
or if that is blank, the username portion of their JID is sent instead.
-->
<fancy_friendly/>
</msntrans>
<!-- msn-transport module. -->
<load>
<msntrans>/usr/local/lib/jabber/msn-transport.so</msntrans>
</load>
</service>
<!--
The settings below have to match the settings you made
in your ejabberd.cfg configuration file.
-->
<service id="msn-linker">
<uplink/>
<connect>
<ip>127.0.0.1</ip>
<port>5235</port>
<secret>SECRET</secret>
</connect>
</service>
<pidfile>/var/run/jabber/msn-transport.pid</pidfile>
</jabber>
@@ -1,86 +0,0 @@
<!-- yahoo-transport-2.xml -->
<jabber>
<!--
You need to add the elogger entry here when using ejabberd.
In this case the transport will do the logging.
-->
<log id='elogger'>
<host/>
<logtype/>
<format>%d: [%t] (%h): %s</format>
<file>/var/log/jabber/yahoo-transport-2-error.log</file>
<stderr/>
</log>
<!--
ejabberd do not provide XDB services.
xdb_file.so is loaded in to handle all XDB requests.
-->
<xdb id="xdb">
<host/>
<load>
<xdb_file>/usr/local/lib/jabber/libjabberdxdbfile.so</xdb_file>
</load>
<xdb_file xmlns="jabber:config:xdb_file">
<spool><jabberd:cmdline flag='s'>/var/spool/jabber</jabberd:cmdline></spool>
</xdb_file>
</xdb>
<!--
Make sure that all host names here are resolveable via DNS if you
want the transport to be available to the public.
-->
<service id="yahoo.SERVER.COM">
<!-- yahoo-transport-2 configuration. -->
<config xmlns="jabber:config:yahoo">
<vCard>
<NAME>Yahoo! Transport</NAME>
<FN>vCard not implemented in current version</FN>
<DESC>This is the Yahoo! transport.</DESC>
<MAIL>EMAIL@ADDRESS.COM</MAIL>
<URL>http://yahoo-transport-2.jabberstudio.org/</URL>
</vCard>
<instructions>Fill in your YAHOO! Messenger username and password to register on this transport.</instructions>
<server>scs.msg.yahoo.com</server>
<port>5050</port>
<!--
The character map. This provides character set translation from UTF-8
to the indicated character map. See the man page for 'iconv' for available
character maps on your platform. CP1252 is the standard Windows character
set.
-->
<charmap>CP1252</charmap>
<!--
When this element exists, the transport will send new mail notifications as
well as a count of unread messages when the user initially logs in.
-->
<newmail/>
</config>
<!-- yahoo-transport-2 module. -->
<load>
<yahoo_transport>/usr/local/lib/jabber/yahoo-transport-2.so</yahoo_transport>
</load>
</service>
<!--
The settings below have to match the settings you made
in your ejabberd.cfg configuration file.
-->
<service id="yahoo-linker">
<uplink/>
<connect>
<ip>127.0.0.1</ip>
<port>5236</port>
<secret>SECRET</secret>
</connect>
</service>
<pidfile>/var/run/jabber/yahoo-transport-2.pid</pidfile>
</jabber>
@@ -1,45 +0,0 @@
#!/bin/sh
#########################################################
#
# aim-transport -- script to start aim-transport.
#
#########################################################
DAEMON=/usr/local/sbin/jabberd-aim-transport
CONF=/etc/jabber/aim-transport.xml
NAME=jabberd-aim-transport
HOME=/etc/jabber/
USER=ejabberd
#########################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
debug)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in debugging mode."
$DAEMON -D -H $HOME -c $CONF &
;;
start)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME."
$DAEMON -H $HOME -c $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|restart}"
exit 1
esac
@@ -1,43 +0,0 @@
#!/bin/sh
#########################################################
#
# ile -- script to start ILE.
#
#########################################################
DAEMON=/usr/local/sbin/ile.pl
NAME=ile.pl
CONF=/etc/jabber/ile.xml
USER=ejabberd
#########################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
debug)
echo "Not implemented yet. Starting in normal mode"
$0 start
;;
start)
test -f $DAEMON || exit 0
echo "Starting $NAME."
$DAEMON $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|status|restart}"
exit 1
esac
@@ -1,47 +0,0 @@
#!/bin/sh
#########################################################
#
# jabber-gg-transport -- script to start jabber-gg-transport.
#
#########################################################
DAEMON=/usr/local/sbin/jggtrans
CONF=/etc/jabber/jabber-gg-transport.xml
NAME=jggtrans
HOME=/etc/jabber/
USER=ejabberd
#########################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
debug)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in debugging mode."
$DAEMON -D -H $HOME -c $CONF &
;;
start)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME."
$DAEMON $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
rm /var/run/jabber/jabber-gg-transport.pid
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|restart}"
exit 1
esac
@@ -1,45 +0,0 @@
#!/bin/sh
#########################################################
#
# jit -- script to start JIT.
#
#########################################################
DAEMON=/usr/local/sbin/wpjabber-jit
CONF=/etc/jabber/jit.xml
NAME=wpjabber-jit
HOME=/etc/jabber/
USER=ejabberd
#########################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
debug)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in debugging mode."
$DAEMON -D -H $HOME -c $CONF &
;;
start)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME."
$DAEMON -H $HOME -c $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|restart}"
exit 1
esac
@@ -1,50 +0,0 @@
#!/bin/sh
#########################################################
#
# msn-transport -- script to start MSN Transport.
#
#########################################################
DAEMON=/usr/local/sbin/jabberd-msn-transport
CONF=/etc/jabber/msn-transport.xml
NAME=jabberd-msn-transport
HOME=/etc/jabber/
USER=ejabberd
#########################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
strace)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in strace mode."
strace -o /opt/ejabberd/var/log/jabber/strace.log $DAEMON -H $HOME -c $CONF &
;;
debug)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in debugging mode."
$DAEMON -D -H $HOME -c $CONF &
;;
start)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME."
$DAEMON -H $HOME -c $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|restart}"
exit 1
esac
@@ -1,45 +0,0 @@
#!/bin/sh
##############################################################
#
# yahoo-transport-2 -- script to start Yahoo-transport-2.
#
#############################################################
DAEMON=/usr/local/sbin/jabberd-yahoo-transport-2
CONF=/etc/jabber/yahoo-transport-2.xml
NAME=jabberd-yahoo-transport-2
HOME=/etc/jabber/
USER=ejabberd
#############################################################
if [ "`/usr/bin/whoami`" != "$USER" ]; then
echo "You need to be" $USER "user to run this script."
exit 1
fi
case "$1" in
debug)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME in debugging mode."
$DAEMON -D -H $HOME -c $CONF &
;;
start)
test -f $DAEMON -a -f $CONF || exit 0
echo "Starting $NAME."
$DAEMON -H $HOME -c $CONF &
;;
stop)
echo "Stopping $NAME."
killall $NAME &
;;
restart|reload)
$0 stop
sleep 3
$0 start
;;
*)
echo "Usage: $0 {debug|start|stop|restart}"
exit 1
esac
+122 -28
View File
@@ -1,15 +1,11 @@
# $Id$
CC = @CC@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
EXPAT_CFLAGS = @EXPAT_CFLAGS@
ERLANG_CFLAGS= @ERLANG_CFLAGS@
EXPAT_LIBS = @EXPAT_LIBS@
ERLANG_LIBS = @ERLANG_LIBS@
ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj
@@ -30,15 +26,16 @@ else
INIT_USER=$(INSTALLUSER)
endif
EFLAGS += @ERLANG_SSL39@ -pa .
EFLAGS += @ERLANG_SSLVER@ -pa .
# make debug=true to compile Erlang module with debug informations.
ifdef debug
EFLAGS+=+debug_info
EFLAGS+=+debug_info +export_all
endif
ifdef ejabberd_debug
EFLAGS+=-Dejabberd_debug
DEBUGTOOLS = p1_prof.erl etop_tr.erl
ifdef debugtools
SOURCES+=$(DEBUGTOOLS)
endif
ifeq (@hipe@, true)
@@ -57,6 +54,11 @@ ifeq (@transient_supervisors@, false)
EFLAGS+=-DNO_TRANSIENT_SUPERVISORS
endif
ifeq (@md2@, true)
EFLAGS+=-DHAVE_MD2
ERLANG_CFLAGS += -DHAVE_MD2
endif
INSTALL_EPAM=
ifeq (@pam@, pam)
INSTALL_EPAM=install -m 750 $(O_USER) epam $(PBINDIR)
@@ -65,11 +67,12 @@ endif
prefix = @prefix@
exec_prefix = @exec_prefix@
SUBDIRS = @mod_irc@ @mod_pubsub@ @mod_muc@ @mod_proxy65@ @eldap@ @pam@ @web@ stringprep stun @tls@ @odbc@ @ejabberd_zlib@
ERLSHLIBS = expat_erl.so
SUBDIRS = stun @mod_pubsub@ @mod_muc@ @mod_proxy65@ @eldap@ @pam@ @web@ @tls@ @odbc@ @ejabberd_zlib@
ERLSHLIBS =
ERLBEHAVS = cyrsasl.erl gen_mod.erl p1_fsm.erl
SOURCES_ALL = $(wildcard *.erl)
SOURCES = $(filter-out $(ERLBEHAVS),$(SOURCES_ALL))
SOURCES_MISC = $(ERLBEHAVS) $(DEBUGTOOLS)
SOURCES += $(filter-out $(SOURCES_MISC),$(SOURCES_ALL))
ERLBEHAVBEAMS = $(ERLBEHAVS:.erl=.beam)
BEAMS = $(SOURCES:.erl=.beam)
@@ -110,6 +113,9 @@ MSGSDIR = $(PRIVDIR)/msgs
# /var/lib/ejabberd/
SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd
# /var/lock/ejabberdctl
CTLLOCKDIR = $(DESTDIR)@localstatedir@/lock/ejabberdctl
# /var/lib/ejabberd/.erlang.cookie
COOKIEFILE = $(SPOOLDIR)/.erlang.cookie
@@ -138,7 +144,7 @@ all-recursive: $(ERLBEHAVBEAMS)
all-recursive install-recursive uninstall-recursive \
clean-recursive distclean-recursive \
clean-recursive distclean-recursive devdoc-recursive \
mostlyclean-recursive maintainer-clean-recursive:
@subdirs="$(SUBDIRS)"; for subdir in $$subdirs; do \
target=`echo $@|sed 's,-recursive,,'`; \
@@ -154,15 +160,13 @@ mostlyclean-recursive maintainer-clean-recursive:
$(ERLSHLIBS): %.so: %.c
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) \
$(subst ../,,$(subst .so,.c,$@)) \
$(EXPAT_LIBS) \
$(EXPAT_CFLAGS) \
$(ERLANG_LIBS) \
$(ERLANG_CFLAGS) \
-o $@ \
$(DYNAMIC_LIB_CFLAGS)
translations:
../contrib/extract_translations/prepare-translation.sh -updateall
../tools/extract_translations/prepare-translation.sh -updateall
install: all
#
@@ -232,6 +236,11 @@ install: all
chmod -R 750 $(SPOOLDIR)
[ ! -f $(COOKIEFILE) ] || { $(CHOWN_COMMAND) @INSTALLUSER@ $(COOKIEFILE) >$(CHOWN_OUTPUT) ; chmod 400 $(COOKIEFILE) ; }
#
# ejabberdctl lock directory
install -d -m 750 $(O_USER) $(CTLLOCKDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(CTLLOCKDIR) >$(CHOWN_OUTPUT)
chmod -R 750 $(CTLLOCKDIR)
#
# Log directory
install -d -m 750 $(O_USER) $(LOGDIR)
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(LOGDIR) >$(CHOWN_OUTPUT)
@@ -239,9 +248,16 @@ install: all
#
# Documentation
install -d $(DOCDIR)
install ../doc/guide.html $(DOCDIR)
install ../doc/*.png $(DOCDIR)
install ../doc/*.txt $(DOCDIR)
[ -f ../doc/guide.html ] \
&& install -m 644 ../doc/dev.html $(DOCDIR) \
&& install -m 644 ../doc/guide.html $(DOCDIR) \
&& install -m 644 ../doc/*.png $(DOCDIR) \
|| echo "No ../doc/guide.html was built"
install -m 644 ../doc/*.txt $(DOCDIR)
[ -f ../doc/guide.pdf ] \
&& install -m 644 ../doc/guide.pdf $(DOCDIR) \
|| echo "No ../doc/guide.pdf was built"
install -m 644 ../COPYING $(DOCDIR)
uninstall: uninstall-binary
@@ -265,9 +281,10 @@ uninstall-all: uninstall-binary
rm -rf $(ETCDIR)
rm -rf $(EJABBERDDIR)
rm -rf $(SPOOLDIR)
rm -rf $(CTLLOCKDIR)
rm -rf $(LOGDIR)
clean: clean-recursive clean-local
clean: clean-recursive clean-local clean-devdoc
clean-local:
rm -f *.beam $(ERLSHLIBS) epam ejabberdctl.example
@@ -277,7 +294,6 @@ distclean: distclean-recursive clean-local
rm -f config.status
rm -f config.log
rm -f Makefile
[ ! -f ../ChangeLog ] || rm -f ../ChangeLog
TAGS:
etags *.erl
@@ -287,11 +303,89 @@ Makefile: Makefile.in
dialyzer: $(BEAMS)
@dialyzer -c .
LASTSVNREVCHANGELOG = 2075
changelog:
svn up -r $(LASTSVNREVCHANGELOG) ../ChangeLog
mv ../ChangeLog ../ChangeLog.old
svn2cl -r BASE:$(LASTSVNREVCHANGELOG) -o ../ChangeLog --group-by-day \
--separate-daylogs --break-before-msg --reparagraph ..
cat ../ChangeLog.old >> ../ChangeLog
rm ../ChangeLog.old
## Devdoc definitions
SRCDIR=.
DDTDIR=.
DEVDOCDIR=../doc/devdoc
DEVDOC_ERLS = $(wildcard ../doc/devdoc/*.erl)
DEVDOC_BEAMS = $(DEVDOC_ERLS:.erl=.beam)
APPNAME = ejabberd
VSN = $(shell sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ./ejabberd.app)
.PHONY = all
HTMLS = $(SOURCES:%.erl=../doc/devdoc/%.html)
ERLHTMLS = $(SOURCES:%.erl=../doc/devdoc/%.erl.html)
SVGS = $(SOURCES:%.erl=../doc/devdoc/%.svg)
EDOCINDEX = $(DEVDOCDIR)/index.html
## Devdoc rules
devdoc: compile-devdoc devdoc-root devdoc-recursive
$(devdoc-customize)
$(devdoc-move)
devdoc-root: $(EDOCINDEX) $(HTMLS) $(ERLHTMLS) $(SVGS)
define devdoc-customize
find $(DDTDIR) -type f -name '*.erl.html' -exec sed -i 's/<span class="attribute" >module<\/span>(\([A-Za-z0-9_]*\))/<span class="attribute" >module<\/span>(<a href="\1.html">\1<\/a>)/g;' {} \;
find $(DDTDIR) -type f -name '*.erl.html' -exec sed -i 's/arity="\([0-9]*\)" >\([A-Za-z0-9_]*\)</><a class="function" id="\2-\1" href="EDOCFILENAME#\2-\1">\2<\/a></g;' {} \;
find $(DDTDIR) -type f -name '*.erl.html' -exec sed -i 's/class="export" >\([A-Za-z0-9_]*\)\/\([0-9]*\)</class="export" ><a href="#\1-\2">\1\/\2<\/a></g;' {} \;
for fn in *.erl.html; do \
sed -i 's/EDOCFILENAME/'$${fn%.erl.html}.html'/g;' $${fn} ; \
sed = $${fn} | sed 'N;s/\n/ /;s/^\([0-9_]*\)/<a href="#\1" name="\1" class="l">\1<\/a>/' >$${fn}.tmp ; \
mv $${fn}.tmp $${fn} ; \
sed -i 's/<a href="#1" name="1" class="l">1<\/a> <html><link rel="stylesheet" type="text\/css"href="escobar.css"><\/link><body><pre><span class="comment" >/<html><link rel="stylesheet" type="text\/css" href="escobar.css"><\/link><body><pre><span class="comment" ><a href="#1" name="1" class="l">1<\/a> /g;' $${fn} ; \
done
-mv *.erl.html $(DEVDOCDIR)
find $(DDTDIR) -type f -name '*.html' -exec sed -i 's/<a href="overview-summary.html" target="overviewFrame">/<a href="index.html" target="_parent">/g;' {} \;
find $(DDTDIR) -type f -name '*.html' -exec sed -i 's/align=\"right\" border=\"0\" alt=\"erlang logo\"/alt=\"erlang logo\"><\/a><a href=\"http:\/\/www.ejabberd.im\/\"><img src=\"ejabberd-im.png\" alt=\"ejabberd Community\"><\/a><a href=\"http:\/\/www.process-one.net\/en\/ejabberd\/\"><img src=\"ejabberd-p1.png\" alt=\"ejabberd home\"><\/a><a href=\"http:\/\/www.process-one.net\/\"><img src=\"process-one.png\" alt=\"ProcessOne\"/g;' {} \;
find $(DDTDIR) -type f -name '*.html' -exec sed -i 's/^<h1>Module \([A-Za-z0-9_]*\)<\/h1>/<h1>Module \1 [<a href="\1.erl.html">erl<\/a> <a href="\1.svg">svg<\/a>]<\/h1>/g;' {} \;
find $(DDTDIR) -type f -name '*.html' -exec sed -i 's/class="function"><a name="\([A-Za-z0-9_]*\)-\([0-9_]*\)">/class="function"><a name="\1-\2" href="ESCOFILENAME#\1-\2">/g;' {} \;
-for fn in *.html; do sed -i 's/ESCOFILENAME/'$${fn%.html}.erl.html'/g;' $${fn} ; done
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="EXP\([A-Za-z0-9_]*\).html#\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="\1.html#\2-\3"/g;' {} \;
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="PRI\([A-Za-z0-9_]*\).html#\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="\1.html#\2-\3"/g;' {} \;
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="APP\([A-Za-z0-9_]*\):\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="\1.html#\2-\3"/g;' {} \;
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="EXM\([A-Za-z0-9_]*\):\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="http:\/\/www.process-one.net\/docs\/exmpp\/devdoc\/trunk\/\1.html#\2-\3"/g;' {} \;
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="OTP\([A-Za-z0-9_]*\):\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="http:\/\/www.erlang.org\/doc\/man\/\1.html#\2-\3"/g;' {} \;
find $(DDTDIR) -type f -name '*.svg' -exec sed -i 's/xlink:href="OTP\([A-Za-z0-9_]*\)\/\([0-9_]*\)"/xlink:href="http:\/\/www.erlang.org\/doc\/man\/erlang.html#\1-\2"/g;' {} \;
endef
define devdoc-move
-rm *.dot
-mv *.html $(DEVDOCDIR)
-mv *.svg $(DEVDOCDIR)
endef
compile-devdoc: $(DEVDOC_BEAMS)
[ ! -f funrelg.beam ] || mv funrelg.beam $(DEVDOCDIR)
[ ! -f escobar_hilite.beam ] || mv escobar_hilite.beam $(DEVDOCDIR)
[ ! -f escobar_run.beam ] || mv escobar_run.beam $(DEVDOCDIR)
$(EDOCINDEX):
@ERL@ -noshell -run edoc_run application "'$(APPNAME)'" '"$(SRCDIR)"' \
'[{dir,"$(DDTDIR)"},{packages,false},{todo,true},{private,true},{def,{vsn,"$(VSN)"}},{stylesheet,"process-one.css"},{overview,"overview.edoc"}]' -s init stop
sed -i 's/<title>The ejabberd application<\/title>/<title>ejabberd devdoc<\/title><link rel="shortcut icon" href="favicon.ico" type="image\/x-icon"\/>/g;' $(DDTDIR)/index.html
mv edoc-info $(DEVDOCDIR)
mv *.png $(DEVDOCDIR)
cp *.html $(DEVDOCDIR)
@ERL@ -noshell -pa $(DEVDOCDIR) -run escobar_run dir $(SRCDIR) $(SRCDIR) -s init stop
@ERL@ -noshell -pa $(DEVDOCDIR) -run funrelg dir $(SRCDIR) $(SRCDIR) -s init stop
$(devdoc-customize)
$(devdoc-move)
$(DEVDOCDIR)/%.erl.html: %.erl
@ERL@ -noshell -pa $(DEVDOCDIR) -run escobar_run file $< $(SRCDIR) -s init stop
$(DEVDOCDIR)/%.html: %.erl
@ERL@ -noshell -run edoc_run file $< \
'[{dir,"$(DDTDIR)"},{packages,false},{todo,true},{private,true},{def,{vsn,"$(VSN)"}},{stylesheet,"process-one.css"},{overview,"overview.edoc"}]' -s init stop
$(DEVDOCDIR)/%.svg: %.erl
@ERL@ -noshell -pa $(DEVDOCDIR) -run funrelg file $< $(SRCDIR) -s init stop
clean-devdoc:
rm -f $(DEVDOCDIR)/edoc-info
rm -f $(DEVDOCDIR)/erlang.png
rm -f $(DEVDOCDIR)/*.beam
rm -f $(DEVDOCDIR)/*.dot
rm -f $(DEVDOCDIR)/*.html
rm -f $(DEVDOCDIR)/*.svg
+5 -14
View File
@@ -52,9 +52,6 @@ release : build release_clean
mkdir $(SRC_DIR)\eldap
copy eldap\eldap.* $(SRC_DIR)\eldap
copy eldap\ELDAPv3.asn $(SRC_DIR)\eldap
mkdir $(SRC_DIR)\mod_irc
copy mod_irc\*.erl $(SRC_DIR)\mod_irc
copy mod_irc\*.c $(SRC_DIR)\mod_irc
mkdir $(SRC_DIR)\mod_muc
copy mod_muc\*.erl $(SRC_DIR)\mod_muc
mkdir $(SRC_DIR)\mod_pubsub
@@ -85,17 +82,15 @@ release : build release_clean
copy ..\doc\*.html $(DOC_DIR)
copy ..\doc\*.png $(DOC_DIR)
SOURCE = expat_erl.c
OBJECT = expat_erl.o
DLL = expat_erl.dll
SOURCE =
OBJECT =
DLL =
build : $(DLL) compile-beam all-recursive
all-recursive :
cd eldap
nmake -nologo -f Makefile.win32
cd ..\mod_irc
nmake -nologo -f Makefile.win32
cd ..\mod_muc
nmake -nologo -f Makefile.win32
cd ..\mod_pubsub
@@ -127,8 +122,6 @@ CLEAN : clean-recursive clean-local
clean-local :
-@erase $(OBJECT)
-@erase $(DLL)
-@erase expat_erl.exp
-@erase expat_erl.lib
-@erase *.beam
-@erase XmppAddr.asn1db
-@erase XmppAddr.erl
@@ -137,8 +130,6 @@ clean-local :
clean-recursive :
cd eldap
nmake -nologo -f Makefile.win32 clean
cd ..\mod_irc
nmake -nologo -f Makefile.win32 clean
cd ..\mod_muc
nmake -nologo -f Makefile.win32 clean
cd ..\mod_pubsub
@@ -164,10 +155,10 @@ distclean : release_clean clean
-@erase Makefile.inc
CC=cl.exe
CC_FLAGS=-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT $(EXPAT_FLAG) -MD -Ox -I"$(ERLANG_DIR)\usr\include" -I"$(EI_DIR)\include" -I"$(EXPAT_DIR)\source\lib"
CC_FLAGS=-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT -MD -Ox -I"$(ERLANG_DIR)\usr\include" -I"$(EI_DIR)\include"
LD=link.exe
LD_FLAGS=-release -nologo -incremental:no -dll "$(EI_DIR)\lib\ei_md.lib" "$(EI_DIR)\lib\erl_interface_md.lib" "$(EXPAT_LIB)" MSVCRT.LIB kernel32.lib advapi32.lib gdi32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib
LD_FLAGS=-release -nologo -incremental:no -dll "$(EI_DIR)\lib\ei_md.lib" "$(EI_DIR)\lib\erl_interface_md.lib" MSVCRT.LIB kernel32.lib advapi32.lib gdi32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib
$(DLL) : $(OBJECT)
$(LD) $(LD_FLAGS) -out:$(DLL) $(OBJECT)
+24 -138
View File
@@ -1,38 +1,4 @@
AC_DEFUN(AM_WITH_EXPAT,
[ AC_ARG_WITH(expat,
[AC_HELP_STRING([--with-expat=PREFIX], [prefix where EXPAT is installed])])
EXPAT_CFLAGS=
EXPAT_LIBS=
if test x"$with_expat" != x; then
EXPAT_CFLAGS="-I$with_expat/include"
EXPAT_LIBS="-L$with_expat/lib"
fi
AC_CHECK_LIB(expat, XML_ParserCreate,
[ EXPAT_LIBS="$EXPAT_LIBS -lexpat"
expat_found=yes ],
[ expat_found=no ],
"$EXPAT_LIBS")
if test $expat_found = no; then
AC_MSG_ERROR([Could not find development files of Expat library])
fi
expat_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $EXPAT_CFLAGS"
expat_save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $EXPAT_CFLAGS"
AC_CHECK_HEADERS(expat.h, , expat_found=no)
if test $expat_found = no; then
AC_MSG_ERROR([Could not find expat.h])
fi
CFLAGS="$expat_save_CFLAGS"
CPPFLAGS="$expat_save_CPPFLAGS"
AC_SUBST(EXPAT_CFLAGS)
AC_SUBST(EXPAT_LIBS)
])
AC_DEFUN(AM_WITH_ZLIB,
AC_DEFUN([AM_WITH_ZLIB],
[ AC_ARG_WITH(zlib,
[AC_HELP_STRING([--with-zlib=PREFIX], [prefix where zlib is installed])])
@@ -68,7 +34,7 @@ if test x"$ejabberd_zlib" != x; then
fi
])
AC_DEFUN(AM_WITH_PAM,
AC_DEFUN([AM_WITH_PAM],
[ AC_ARG_WITH(pam,
[AC_HELP_STRING([--with-pam=PREFIX], [prefix where PAM is installed])])
if test x"$pam" != x; then
@@ -103,7 +69,7 @@ if test x"$pam" != x; then
fi
])
AC_DEFUN(AM_WITH_ERLANG,
AC_DEFUN([AM_WITH_ERLANG],
[ AC_ARG_WITH(erlang,
[AC_HELP_STRING([--with-erlang=PREFIX], [path to erlc and erl])])
@@ -121,20 +87,27 @@ AC_DEFUN(AM_WITH_ERLANG,
-author('alexey@sevcom.net').
-export([[start/0]]).
-include_lib("ssl/include/ssl_pkix.hrl").
start() ->
EIDirS = code:lib_dir("erl_interface") ++ "\n",
EILibS = libpath("erl_interface") ++ "\n",
EXMPPDir = code:lib_dir("exmpp"),
case EXMPPDir of
{error, bad_name} -> exit("exmpp not found");
_ -> ok
end,
EXMPPDirS = EXMPPDir ++ "\n",
RootDirS = code:root_dir() ++ "\n",
file:write_file("conftest.out", list_to_binary(EIDirS ++ EILibS ++ ssldef() ++ RootDirS)),
file:write_file("conftest.out", list_to_binary(EIDirS ++ EILibS ++ ssldef() ++ EXMPPDirS ++ RootDirS)),
halt().
-[ifdef]('id-pkix').
ssldef() -> "-DSSL39\n".
-else.
ssldef() -> "\n".
-endif.
ssldef() ->
OTP = (catch erlang:system_info(otp_release)),
if
OTP >= "R14" -> "-DSSL40\n";
OTP >= "R12" -> "-DSSL39\n";
true -> "\n"
end.
%% return physical architecture based on OS/Processor
archname() ->
@@ -184,7 +157,9 @@ _EOF
# Second line
ERLANG_EI_LIB=`cat conftest.out | head -n 2 | tail -n 1`
# Third line
ERLANG_SSL39=`cat conftest.out | head -n 3 | tail -n 1`
ERLANG_SSLVER=`cat conftest.out | head -n 3 | tail -n 1`
# Fourth line
ERLANG_EXMPP=`cat conftest.out | head -n 4 | tail -n 1`
# End line
ERLANG_DIR=`cat conftest.out | tail -n 1`
@@ -193,12 +168,13 @@ _EOF
AC_SUBST(ERLANG_CFLAGS)
AC_SUBST(ERLANG_LIBS)
AC_SUBST(ERLANG_SSL39)
AC_SUBST(ERLANG_SSLVER)
AC_SUBST(ERLANG_EXMPP)
AC_SUBST(ERLC)
AC_SUBST(ERL)
])
AC_DEFUN(AC_MOD_ENABLE,
AC_DEFUN([AC_MOD_ENABLE],
[
$1=
make_$1=
@@ -217,98 +193,8 @@ AC_SUBST(make_$1)
])
dnl From Bruno Haible.
AC_DEFUN([AM_ICONV],
[
dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
dnl those with the standalone portable GNU libiconv installed).
AC_ARG_WITH([libiconv-prefix],
[AC_HELP_STRING([--with-libiconv-prefix=PREFIX], [prefix where libiconv is installed])], [
for dir in `echo "$withval" | tr : ' '`; do
if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi
if test -d $dir/include; then CFLAGS="$CFLAGS -I$dir/include"; fi
if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi
done
])
AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
am_cv_func_iconv="no, consider installing GNU libiconv"
am_cv_lib_iconv=no
AC_TRY_LINK([#include <stdlib.h>
#include <iconv.h>],
[iconv_t cd = iconv_open("","");
iconv(cd,NULL,NULL,NULL,NULL);
iconv_close(cd);],
am_cv_func_iconv=yes)
if test "$am_cv_func_iconv" != yes; then
am_save_LIBS="$LIBS"
LIBS="$LIBS -liconv"
AC_TRY_LINK([#include <stdlib.h>
#include <iconv.h>],
[iconv_t cd = iconv_open("","");
iconv(cd,NULL,NULL,NULL,NULL);
iconv_close(cd);],
am_cv_lib_iconv=yes
am_cv_func_iconv=yes)
LIBS="$am_save_LIBS"
fi
dnl trying /usr/local
if test "$am_cv_func_iconv" != yes; then
am_save_LIBS="$LIBS"
am_save_CFLAGS="$CFLAGS"
am_save_LDFLAGS="$LDFLAGS"
LIBS="$LIBS -liconv"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
CFLAGS="$CFLAGS -I/usr/local/include"
AC_TRY_LINK([#include <stdlib.h>
#include <iconv.h>],
[iconv_t cd = iconv_open("","");
iconv(cd,NULL,NULL,NULL,NULL);
iconv_close(cd);],
am_cv_lib_iconv=yes
am_cv_func_iconv=yes
CPPFLAGS="$CPPFLAGS -I/usr/local/include",
LDFLAGS="$am_save_LDFLAGS"
CFLAGS="$am_save_CFLAGS")
LIBS="$am_save_LIBS"
fi
])
if test "$am_cv_func_iconv" = yes; then
AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
AC_MSG_CHECKING([for iconv declaration])
AC_CACHE_VAL(am_cv_proto_iconv, [
AC_TRY_COMPILE([
#include <stdlib.h>
#include <iconv.h>
extern
#ifdef __cplusplus
"C"
#endif
#if defined(__STDC__) || defined(__cplusplus)
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
#else
size_t iconv();
#endif
], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
AC_MSG_RESULT([$]{ac_t:-
}[$]am_cv_proto_iconv)
AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
[Define as const if the declaration of iconv() needs const.])
fi
LIBICONV=
if test "$am_cv_lib_iconv" = yes; then
LIBICONV="-liconv"
fi
AC_SUBST(LIBICONV)
])
dnl <openssl>
AC_DEFUN(AM_WITH_OPENSSL,
AC_DEFUN([AM_WITH_OPENSSL],
[ AC_ARG_WITH(openssl,
[AC_HELP_STRING([--with-openssl=PREFIX], [prefix where OPENSSL is installed])])
unset SSL_LIBS;
+119 -21
View File
@@ -5,7 +5,7 @@
%%% Created : 18 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -32,13 +32,45 @@
add/3,
add_list/3,
match_rule/3,
for_host/1,
% for debugging only
match_acl/3]).
-include("ejabberd.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
%% @type aclspec() = all | JID_Exact | JID_Regexp | JID_Glob | Shared_Group
%% JID_Exact = {user, U} | {user, U, S} | {server, S} | {resource, R}
%% U = string()
%% S = string()
%% R = string()
%% JID_Regexp = {user_regexp, UR} | {user_regexp, UR, S} | {server_regexp, SR} | {resource_regexp, RR} | {node_regexp, UR, SR}
%% UR = string()
%% SR = string()
%% RR = string()
%% JID_Glob = {user_glob, UG} | {user_glob, UG, S} | {server_glob, SG} | {resource_glob, RG} | {node_glob, UG, SG}
%% UG = string()
%% SG = string()
%% RG = string()
%% Shared_Group = {shared_group, G} | {shared_group, G, H}
%% G = string()
%% H = string().
%% @type acl() = {acl, ACLName, ACLSpec}
%% ACLName = atom()
%% ACLSpec = aclspec().
%% Record in its Ejabberd-configuration-file variant.
%% @type storedacl() = {acl, {ACLName, Host}, ACLSpec}
%% ACLName = atom()
%% Host = global | string()
%% ACLSpec = aclspec().
%% Record in its Mnesia-table-record variant.
-record(acl, {aclname, aclspec}).
%% @spec () -> ok
start() ->
mnesia:create_table(acl,
[{disc_copies, [node()]},
@@ -47,9 +79,20 @@ start() ->
mnesia:add_table_copy(acl, node(), ram_copies),
ok.
%% @spec (Host, ACLName, ACLSpec) -> storedacl()
%% Host = global | string()
%% ACLName = atom()
%% ACLSpec = aclspec()
to_record(Host, ACLName, ACLSpec) ->
#acl{aclname = {ACLName, Host}, aclspec = normalize_spec(ACLSpec)}.
%% @spec (Host, ACLName, ACLSpec) -> {atomic, ok} | {aborted, Reason}
%% Host = global | string()
%% ACLName = atom()
%% ACLSpec = all | none | aclspec()
%% Reason = term()
add(Host, ACLName, ACLSpec) ->
F = fun() ->
mnesia:write(#acl{aclname = {ACLName, Host},
@@ -57,6 +100,11 @@ add(Host, ACLName, ACLSpec) ->
end,
mnesia:transaction(F).
%% @spec (Host, ACLs, Clear) -> ok | false
%% Host = global | string()
%% ACLs = [acl()]
%% Clear = bool()
add_list(Host, ACLs, Clear) ->
F = fun() ->
if
@@ -86,8 +134,17 @@ add_list(Host, ACLs, Clear) ->
false
end.
normalize(A) ->
jlib:nodeprep(A).
%% @spec (String) -> Prepd_String
%% String = string()
%% Prepd_String = string()
normalize(String) ->
exmpp_stringprep:nodeprep(String).
%% @spec (ACLSpec) -> Normalized_ACLSpec
%% ACLSpec = all | none | aclspec()
%% Normalized_ACLSpec = aclspec()
normalize_spec({A, B}) ->
{A, normalize(B)};
normalize_spec({A, B, C}) ->
@@ -99,6 +156,12 @@ normalize_spec(none) ->
%% @spec (Host, Rule, JID) -> Access
%% Host = global | string()
%% Rule = all | none | atom()
%% JID = exmpp_jid:jid()
%% Access = allow | deny | atom()
match_rule(global, Rule, JID) ->
case Rule of
all -> allow;
@@ -143,23 +206,37 @@ match_rule(Host, Rule, JID) ->
end
end.
%% @spec (ACLs, JID, Host) -> Access
%% ACLs = [{Access, ACLName}]
%% Access = deny | atom()
%% ACLName = atom()
%% JID = exmpp_jid:jid()
%% Host = string()
match_acls([], _, _Host) ->
deny;
match_acls([{Access, ACL} | ACLs], JID, Host) ->
case match_acl(ACL, JID, Host) of
match_acls([{Access, ACLName} | ACLs], JID, Host) ->
case match_acl(ACLName, JID, Host) of
true ->
Access;
_ ->
match_acls(ACLs, JID, Host)
end.
match_acl(ACL, JID, Host) ->
case ACL of
%% @spec (ACLName, JID, Host) -> bool()
%% ACLName = all | none | atom()
%% JID = exmpp_jid:jid()
%% Host = string()
match_acl(ACLName, JID, Host) ->
case ACLName of
all -> true;
none -> false;
_ ->
{User, Server, Resource} = jlib:jid_tolower(JID),
lists:any(fun(#acl{aclspec = Spec}) ->
User = exmpp_jid:prep_node_as_list(JID),
Server = exmpp_jid:prep_domain_as_list(JID),
Resource = exmpp_jid:prep_resource_as_list(JID),
lists:any(fun(#acl{aclname=Name, aclspec = Spec}) ->
case Spec of
all ->
true;
@@ -168,17 +245,21 @@ match_acl(ACL, JID, Host) ->
andalso
((Host == Server) orelse
((Host == global) andalso
lists:member(Server, ?MYHOSTS)));
?IS_MY_HOST(Server)));
{user, U, S} ->
(U == User) andalso (S == Server);
{server, S} ->
S == Server;
{resource, R} ->
R == Resource;
{user_regexp, UR} when is_tuple(Name),
element(2, Name) =:= global ->
?IS_MY_HOST(Server)
andalso is_regexp_match(User, UR);
{user_regexp, UR} ->
((Host == Server) orelse
((Host == global) andalso
lists:member(Server, ?MYHOSTS)))
?IS_MY_HOST(Server)))
andalso is_regexp_match(User, UR);
{shared_group, G} ->
mod_shared_roster:is_user_in_group({User, Server}, G, Host);
@@ -197,7 +278,7 @@ match_acl(ACL, JID, Host) ->
{user_glob, UR} ->
((Host == Server) orelse
((Host == global) andalso
lists:member(Server, ?MYHOSTS)))
?IS_MY_HOST(Server)))
andalso
is_glob_match(User, UR);
{user_glob, UR, S} ->
@@ -218,24 +299,41 @@ match_acl(ACL, JID, Host) ->
false
end
end,
ets:lookup(acl, {ACL, global}) ++
ets:lookup(acl, {ACL, Host}))
ets:lookup(acl, {ACLName, global}) ++
ets:lookup(acl, {ACLName, Host}))
end.
%% @spec (String, RegExp) -> bool()
%% String = string() | undefined
%% RegExp = string()
is_regexp_match(undefined, _RegExp) ->
false;
is_regexp_match(String, RegExp) ->
case regexp:first_match(String, RegExp) of
try re:run(String, RegExp, [{capture, none}]) of
nomatch ->
false;
{match, _, _} ->
true;
{error, ErrDesc} ->
match ->
true
catch
_:ErrDesc ->
?ERROR_MSG(
"Wrong regexp ~p in ACL: ~p",
[RegExp, lists:flatten(regexp:format_error(ErrDesc))]),
"Wrong regexp ~p in ACL:~n~p",
[RegExp, ErrDesc]),
false
end.
%% @spec (String, Glob) -> bool()
%% String = string() | undefined
%% Glob = string()
is_glob_match(String, Glob) ->
is_regexp_match(String, regexp:sh_to_awk(Glob)).
is_regexp_match(String, xmerl_regexp:sh_to_awk(Glob)).
for_host(Host) ->
mnesia:select(acl,
ets:fun2ms(fun (#acl{aclname = {_ACLName, H}})
when H =:= Host ->
object()
end)).
+47 -43
View File
@@ -1,11 +1,11 @@
%%%----------------------------------------------------------------------
%%% File : adhoc.erl
%%% Author : Magnus Henoch <henoch@dtek.chalmers.se>
%%% Purpose : Provide helper functions for ad-hoc commands (JEP-0050)
%%% Purpose : Provide helper functions for ad-hoc commands (XEP-0050)
%%% Created : 31 Oct 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -31,47 +31,52 @@
produce_response/2,
produce_response/1]).
-include_lib("exmpp/include/exmpp.hrl").
-include("ejabberd.hrl").
-include("jlib.hrl").
-include("adhoc.hrl").
%% Parse an ad-hoc request. Return either an adhoc_request record or
%% an {error, ErrorType} tuple.
parse_request(#iq{type = set, lang = Lang, sub_el = SubEl, xmlns = ?NS_COMMANDS}) ->
?DEBUG("entering parse_request...", []),
Node = xml:get_tag_attr_s("node", SubEl),
SessionID = xml:get_tag_attr_s("sessionid", SubEl),
Action = xml:get_tag_attr_s("action", SubEl),
XData = find_xdata_el(SubEl),
{xmlelement, _, _, AllEls} = SubEl,
if XData ->
Others = lists:delete(XData, AllEls);
true ->
Others = AllEls
end,
parse_request(#iq{type = Type, ns = NS, payload = SubEl, lang = Lang}) ->
try
case {Type, NS} of
{set, ?NS_ADHOC} ->
?DEBUG("entering parse_request...", []),
Node = exmpp_xml:get_attribute_as_list(SubEl, <<"node">>, ""),
SessionID = exmpp_xml:get_attribute_as_list(SubEl, <<"sessionid">>, ""),
Action = exmpp_xml:get_attribute_as_list(SubEl, <<"action">>, ""),
XData = find_xdata_el(SubEl),
AllEls = exmpp_xml:get_child_elements(SubEl),
Others = case XData of
false ->
AllEls;
_ ->
lists:delete(XData, AllEls)
end,
#adhoc_request{lang = Lang,
node = Node,
sessionid = SessionID,
action = Action,
xdata = XData,
others = Others};
parse_request(_) ->
{error, ?ERR_BAD_REQUEST}.
#adhoc_request{lang = Lang,
node = Node,
sessionid = SessionID,
action = Action,
xdata = XData,
others = Others};
_ ->
{error, 'bad-request'}
end
catch
_ ->
{error, 'bad-request'}
end.
%% Borrowed from mod_vcard.erl
find_xdata_el({xmlelement, _Name, _Attrs, SubEls}) ->
find_xdata_el(#xmlel{children = SubEls}) ->
find_xdata_el1(SubEls).
find_xdata_el1([]) ->
false;
find_xdata_el1([{xmlelement, Name, Attrs, SubEls} | Els]) ->
case xml:get_attr_s("xmlns", Attrs) of
?NS_XDATA ->
{xmlelement, Name, Attrs, SubEls};
_ ->
find_xdata_el1(Els)
end;
find_xdata_el1([#xmlel{ns = ?NS_DATA_FORMS} = El | _Els]) ->
El;
find_xdata_el1([_ | Els]) ->
find_xdata_el1(Els).
@@ -109,20 +114,19 @@ produce_response(#adhoc_response{lang = _Lang,
"" ->
ActionsElAttrs = [];
_ ->
ActionsElAttrs = [{"execute", DefaultAction}]
ActionsElAttrs = [?XMLATTR(<<"execute">>, DefaultAction)]
end,
ActionsEls = [{xmlelement, "actions",
ActionsElAttrs,
[{xmlelement, Action, [], []} || Action <- Actions]}]
ActionsEls = [#xmlel{ns = ?NS_ADHOC, name = 'actions', attrs =
ActionsElAttrs, children =
[#xmlel{ns = ?NS_ADHOC, name = Action} || Action <- Actions]}]
end,
NotesEls = lists:map(fun({Type, Text}) ->
{xmlelement, "note",
[{"type", Type}],
[{xmlcdata, Text}]}
#xmlel{ns = ?NS_ADHOC, name = 'note', attrs =
[?XMLATTR(<<"type">>, Type)],
children = [#xmlcdata{cdata = list_to_binary(Text)}]}
end, Notes),
{xmlelement, "command",
[{"xmlns", ?NS_COMMANDS},
{"sessionid", SessionID},
{"node", Node},
{"status", atom_to_list(Status)}],
#xmlel{ns = ?NS_ADHOC, name = 'command', attrs =
[?XMLATTR(<<"sessionid">>, SessionID),
?XMLATTR(<<"node">>, Node),
?XMLATTR(<<"status">>, Status)], children =
ActionsEls ++ NotesEls ++ Elements}.
+1 -1
View File
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
+604
View File
@@ -0,0 +1,604 @@
%%%-------------------------------------------------------------------
%%% File : cache_tab.erl
%%% Author : Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%% Description : Caching key-value table
%%%
%%% Created : 29 Aug 2010 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License
%%% along with this program; if not, write to the Free Software
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
%%% 02111-1307 USA
%%%
%%%-------------------------------------------------------------------
-module(cache_tab).
-define(GEN_SERVER, gen_server).
-behaviour(?GEN_SERVER).
%% API
-export([start_link/4, new/2, delete/1, delete/3, lookup/3,
insert/4, info/2, tab2list/1, setopts/2,
dirty_lookup/3, dirty_insert/4, dirty_delete/3,
all/0, test/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-record(state, {tab = treap:empty(),
name,
size = 0,
owner,
max_size,
life_time,
warn,
hits = 0,
miss = 0,
procs_num,
cache_missed,
lru,
shrink_size}).
-define(PROCNAME, ?MODULE).
-define(CALL_TIMEOUT, 60000).
%% Defaults
-define(MAX_SIZE, 1000).
-define(WARN, true).
-define(CACHE_MISSED, true).
-define(LRU, true).
-define(LIFETIME, 600). %% 10 minutes
%%====================================================================
%% API
%%====================================================================
start_link(Proc, Tab, Opts, Owner) ->
?GEN_SERVER:start_link({local, Proc}, ?MODULE,
[Tab, Opts, get_proc_num(), Owner], []).
new(Tab, Opts) ->
Res = lists:flatmap(
fun(Proc) ->
Spec = {{Tab, Proc},
{?MODULE, start_link,
[Proc, Tab, Opts, self()]},
permanent,
brutal_kill,
worker,
[?MODULE]},
case supervisor:start_child(cache_tab_sup, Spec) of
{ok, _Pid} ->
[ok];
R ->
[R]
end
end, get_all_procs(Tab)),
case lists:filter(fun(ok) -> false; (_) -> true end, Res) of
[] ->
ok;
Err ->
{error, Err}
end.
delete(Tab) ->
lists:foreach(
fun(Proc) ->
supervisor:terminate_child(cache_tab_sup, {Tab, Proc}),
supervisor:delete_child(cache_tab_sup, {Tab, Proc})
end, get_all_procs(Tab)).
delete(Tab, Key, F) ->
?GEN_SERVER:call(
get_proc_by_hash(Tab, Key), {delete, Key, F}, ?CALL_TIMEOUT).
dirty_delete(Tab, Key, F) ->
F(),
?GEN_SERVER:call(
get_proc_by_hash(Tab, Key), {cache_delete, Key}, ?CALL_TIMEOUT).
lookup(Tab, Key, F) ->
?GEN_SERVER:call(
get_proc_by_hash(Tab, Key), {lookup, Key, F}, ?CALL_TIMEOUT).
dirty_lookup(Tab, Key, F) ->
Proc = get_proc_by_hash(Tab, Key),
case ?GEN_SERVER:call(Proc, {cache_lookup, Key}, ?CALL_TIMEOUT) of
{ok, '$cached_mismatch'} ->
error;
{ok, Val} ->
{ok, Val};
_ ->
{Result, NewVal} = case F() of
{ok, Val} ->
{{ok, Val}, Val};
_ ->
{error, '$cached_mismatch'}
end,
?GEN_SERVER:call(
Proc, {cache_insert, Key, NewVal}, ?CALL_TIMEOUT),
Result
end.
insert(Tab, Key, Val, F) ->
?GEN_SERVER:call(
get_proc_by_hash(Tab, Key), {insert, Key, Val, F}, ?CALL_TIMEOUT).
dirty_insert(Tab, Key, Val, F) ->
F(),
?GEN_SERVER:call(
get_proc_by_hash(Tab, Key), {cache_insert, Key, Val}, ?CALL_TIMEOUT).
info(Tab, Info) ->
case lists:map(
fun(Proc) ->
?GEN_SERVER:call(Proc, {info, Info}, ?CALL_TIMEOUT)
end, get_all_procs(Tab)) of
Res when Info == size ->
{ok, lists:sum(Res)};
Res when Info == all ->
{ok, Res};
Res when Info == ratio ->
{H, M} = lists:foldl(
fun({Hits, Miss}, {HitsAcc, MissAcc}) ->
{HitsAcc + Hits, MissAcc + Miss}
end, {0, 0}, Res),
{ok, [{hits, H}, {miss, M}]};
_ ->
{error, badarg}
end.
setopts(Tab, Opts) ->
lists:foreach(
fun(Proc) ->
?GEN_SERVER:call(Proc, {setopts, Opts}, ?CALL_TIMEOUT)
end, get_all_procs(Tab)).
tab2list(Tab) ->
lists:flatmap(
fun(Proc) ->
?GEN_SERVER:call(Proc, tab2list, ?CALL_TIMEOUT)
end, get_all_procs(Tab)).
all() ->
lists:usort(
[Tab || {{Tab, _}, _, _, _} <- supervisor:which_children(cache_tab_sup)]).
%%====================================================================
%% gen_server callbacks
%%====================================================================
init([Tab, Opts, N, Pid]) ->
State = #state{procs_num = N,
owner = Pid,
name = Tab},
{ok, do_setopts(State, Opts)}.
handle_call({lookup, Key, F}, _From, #state{tab = T} = State) ->
CleanPrio = clean_priority(State#state.life_time),
case treap:lookup(Key, T) of
{ok, Prio, Val} when (State#state.lru == true) or (Prio =< CleanPrio) ->
Hits = State#state.hits,
NewState = treap_update(Key, Val, State#state{hits = Hits + 1}),
case Val of
'$cached_mismatch' ->
{reply, error, NewState};
_ ->
{reply, {ok, Val}, NewState}
end;
_ ->
case catch F() of
{ok, Val} ->
Miss = State#state.miss,
NewState = treap_insert(Key, Val, State),
{reply, {ok, Val}, NewState#state{miss = Miss + 1}};
{'EXIT', Reason} ->
print_error(lookup, [Key], Reason, State),
{reply, error, State};
_ ->
Miss = State#state.miss,
NewState = State#state{miss = Miss + 1},
if State#state.cache_missed ->
{reply, error,
treap_insert(Key, '$cached_mismatch', NewState)};
true ->
{reply, error, NewState}
end
end
end;
handle_call({cache_lookup, Key}, _From, #state{tab = T} = State) ->
CleanPrio = clean_priority(State#state.life_time),
case treap:lookup(Key, T) of
{ok, Prio, Val} when (State#state.lru == true) or (Prio =< CleanPrio) ->
Hits = State#state.hits,
NewState = treap_update(Key, Val, State#state{hits = Hits + 1}),
{reply, {ok, Val}, NewState};
_ ->
Miss = State#state.miss,
NewState = State#state{miss = Miss + 1},
{reply, error, NewState}
end;
handle_call({insert, Key, Val, F}, _From, #state{tab = T} = State) ->
case treap:lookup(Key, T) of
{ok, _Prio, Val} ->
{reply, ok, treap_update(Key, Val, State)};
_ ->
case catch F() of
{'EXIT', Reason} ->
print_error(insert, [Key, Val], Reason, State),
{reply, ok, State};
_ ->
{reply, ok, treap_insert(Key, Val, State)}
end
end;
handle_call({cache_insert, _, '$cached_mismatch'}, _From,
#state{cache_missed = false} = State) ->
{reply, ok, State};
handle_call({cache_insert, Key, Val}, _From, State) ->
{reply, ok, treap_insert(Key, Val, State)};
handle_call({delete, Key, F}, _From, State) ->
NewState = treap_delete(Key, State),
case catch F() of
{'EXIT', Reason} ->
print_error(delete, [Key], Reason, State);
_ ->
ok
end,
{reply, ok, NewState};
handle_call({cache_delete, Key}, _From, State) ->
NewState = treap_delete(Key, State),
{reply, ok, NewState};
handle_call({info, Info}, _From, State) ->
Res = case Info of
size ->
State#state.size;
ratio ->
{State#state.hits, State#state.miss};
all ->
[{max_size, State#state.max_size},
{life_time, State#state.life_time},
{shrink_size, State#state.shrink_size},
{size, State#state.size},
{owner, State#state.owner},
{hits, State#state.hits},
{miss, State#state.miss},
{cache_missed, State#state.cache_missed},
{lru, State#state.lru},
{warn, State#state.warn}];
_ ->
badarg
end,
{reply, Res, State};
handle_call(tab2list, _From, #state{tab = T} = State) ->
Res = treap:fold(
fun({Key, _, Val}, Acc) ->
[{Key, Val}|Acc]
end, [], T),
{reply, Res, State};
handle_call({setopts, Opts}, _From, State) ->
{reply, ok, do_setopts(State, Opts)};
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
do_setopts(#state{procs_num = N} = State, Opts) ->
MaxSize = case {proplists:get_value(max_size, Opts),
State#state.max_size} of
{MS, _} when is_integer(MS), MS > 0 ->
round(MS/N);
{unlimited, _} ->
unlimited;
{_, undefined} ->
round(?MAX_SIZE/N);
{_, MS} ->
MS
end,
LifeTime = case {proplists:get_value(life_time, Opts),
State#state.life_time} of
{LT, _} when is_integer(LT), LT > 0 ->
LT*1000*1000;
{unlimited, _} ->
unlimited;
{_, undefined} ->
?LIFETIME*1000*1000;
{_, LT} ->
LT
end,
ShrinkSize = case {proplists:get_value(shrink_size, Opts),
State#state.shrink_size} of
{SS, _} when is_integer(SS), SS > 0 ->
round(SS/N);
_ when is_integer(MaxSize) ->
round(MaxSize/2);
_ ->
unlimited
end,
Warn = case {proplists:get_value(warn, Opts),
State#state.warn} of
{true, _} ->
true;
{false, _} ->
false;
{_, undefined} ->
?WARN;
{_, W} ->
W
end,
CacheMissed = case proplists:get_value(
cache_missed, Opts, State#state.cache_missed) of
false ->
false;
true ->
true;
_ ->
?CACHE_MISSED
end,
LRU = case proplists:get_value(
lru, Opts, State#state.lru) of
false ->
false;
true ->
true;
_ ->
?LRU
end,
State#state{max_size = MaxSize,
warn = Warn,
life_time = LifeTime,
cache_missed = CacheMissed,
lru = LRU,
shrink_size = ShrinkSize}.
get_proc_num() ->
erlang:system_info(logical_processors).
get_proc_by_hash(Tab, Term) ->
N = erlang:phash2(Term, get_proc_num()) + 1,
get_proc(Tab, N).
get_proc(Tab, N) ->
list_to_atom(atom_to_list(?PROCNAME) ++ "_" ++
atom_to_list(Tab) ++ "_" ++ integer_to_list(N)).
get_all_procs(Tab) ->
[get_proc(Tab, N) || N <- lists:seq(1, get_proc_num())].
now_priority() ->
{MSec, Sec, USec} = now(),
-((MSec*1000000 + Sec)*1000000 + USec).
clean_priority(LifeTime) ->
if is_integer(LifeTime) ->
now_priority() + LifeTime;
true ->
unlimited
end.
treap_update(Key, Val, #state{tab = T, lru = LRU} = State) ->
if LRU ->
Priority = now_priority(),
NewT = treap:insert(Key, Priority, Val, T),
State#state{tab = NewT};
true ->
State
end.
treap_insert(Key, Val, State) ->
State1 = clean_treap(State),
#state{size = Size} = State2 = shrink_treap(State1),
T = State2#state.tab,
case treap:lookup(Key, T) of
{ok, _, Val} ->
treap_update(Key, Val, State2);
{ok, _, _} ->
NewT = treap:insert(Key, now_priority(), Val, T),
State2#state{tab = NewT};
_ ->
NewT = treap:insert(Key, now_priority(), Val, T),
State2#state{tab = NewT, size = Size+1}
end.
treap_delete(Key, #state{tab = T, size = Size} = State) ->
case treap:lookup(Key, T) of
{ok, _, _} ->
NewT = treap:delete(Key, T),
clean_treap(State#state{tab = NewT, size = Size-1});
_ ->
State
end.
clean_treap(#state{tab = T, size = Size, life_time = LifeTime} = State) ->
if is_integer(LifeTime) ->
Priority = now_priority(),
{Cleaned, NewT} = clean_treap(T, Priority + LifeTime, 0),
State#state{size = Size - Cleaned, tab = NewT};
true ->
State
end.
clean_treap(Treap, CleanPriority, N) ->
case treap:is_empty(Treap) of
true ->
{N, Treap};
false ->
{_Key, Priority, _Value} = treap:get_root(Treap),
if Priority > CleanPriority ->
clean_treap(treap:delete_root(Treap), CleanPriority, N+1);
true ->
{N, Treap}
end
end.
shrink_treap(#state{tab = T,
max_size = MaxSize,
shrink_size = ShrinkSize,
warn = Warn,
size = Size} = State) when Size >= MaxSize ->
if Warn ->
?WARNING_MSG("shrinking table:~n"
"** Table: ~p~n"
"** Processes Number: ~p~n"
"** Max Size: ~p items~n"
"** Shrink Size: ~p items~n"
"** Life Time: ~p microseconds~n"
"** Hits/Miss: ~p/~p~n"
"** Owner: ~p~n"
"** Cache Missed: ~p~n"
"** Instruction: you have to tune cacheing options"
" if this message repeats too frequently",
[State#state.name, State#state.procs_num,
MaxSize, ShrinkSize, State#state.life_time,
State#state.hits, State#state.miss,
State#state.owner, State#state.cache_missed]);
true ->
ok
end,
{Shrinked, NewT} = shrink_treap(T, ShrinkSize, 0),
State#state{tab = NewT, size = Size - Shrinked};
shrink_treap(State) ->
State.
shrink_treap(T, ShrinkSize, ShrinkSize) ->
{ShrinkSize, T};
shrink_treap(T, ShrinkSize, N) ->
case treap:is_empty(T) of
true ->
{N, T};
false ->
shrink_treap(treap:delete_root(T), ShrinkSize, N+1)
end.
print_error(Operation, Args, Reason, State) ->
?ERROR_MSG("callback failed:~n"
"** Tab: ~p~n"
"** Owner: ~p~n"
"** Operation: ~p~n"
"** Args: ~p~n"
"** Reason: ~p",
[State#state.name, State#state.owner,
Operation, Args, Reason]).
%%--------------------------------------------------------------------
%%% Tests
%%--------------------------------------------------------------------
-define(lookup, dirty_lookup).
-define(delete, dirty_delete).
-define(insert, dirty_insert).
%%-define(lookup, lookup).
%%-define(delete, delete).
%%-define(insert, insert).
test() ->
LifeTime = 2,
ok = new(test_tbl, [{life_time, LifeTime}, {max_size, unlimited}]),
check([]),
ok = ?insert(test_tbl, "key", "value", fun() -> ok end),
check([{"key", "value"}]),
{ok, "value"} = ?lookup(test_tbl, "key", fun() -> error end),
check([{"key", "value"}]),
io:format("** waiting for ~p seconds to check if LRU works fine...~n",
[LifeTime+1]),
timer:sleep(timer:seconds(LifeTime+1)),
ok = ?insert(test_tbl, "key1", "value1", fun() -> ok end),
check([{"key1", "value1"}]),
ok = ?delete(test_tbl, "key1", fun() -> ok end),
{ok, "value"} = ?lookup(test_tbl, "key", fun() -> {ok, "value"} end),
check([{"key", "value"}]),
ok = ?delete(test_tbl, "key", fun() -> ok end),
check([]),
%% io:format("** testing buggy callbacks...~n"),
%% delete(test_tbl, "key", fun() -> erlang:error(badarg) end),
%% insert(test_tbl, "key", "val", fun() -> erlang:error(badarg) end),
%% lookup(test_tbl, "key", fun() -> erlang:error(badarg) end),
check([]),
delete(test_tbl),
test1().
test1() ->
MaxSize = 10,
ok = new(test_tbl, [{max_size, MaxSize}, {shrink_size, 1}, {warn, false}]),
lists:foreach(
fun(N) ->
ok = ?insert(test_tbl, N, N, fun() -> ok end)
end, lists:seq(1, MaxSize*get_proc_num())),
{ok, MaxSize} = info(test_tbl, size),
delete(test_tbl),
test2().
test2() ->
LifeTime = 2,
ok = new(test_tbl, [{life_time, LifeTime},
{max_size, unlimited},
{lru, false}]),
check([]),
ok = ?insert(test_tbl, "key", "value", fun() -> ok end),
{ok, "value"} = ?lookup(test_tbl, "key", fun() -> error end),
check([{"key", "value"}]),
io:format("** waiting for ~p seconds to check if non-LRU works fine...~n",
[LifeTime+1]),
timer:sleep(timer:seconds(LifeTime+1)),
error = ?lookup(test_tbl, "key", fun() -> error end),
check([{"key", '$cached_mismatch'}]),
ok = ?insert(test_tbl, "key", "value1", fun() -> ok end),
check([{"key", "value1"}]),
delete(test_tbl),
io:format("** testing speed, this may take a while...~n"),
test3(1000),
test3(10000),
test3(100000),
test3(1000000).
test3(Iter) ->
ok = new(test_tbl, [{max_size, unlimited}, {life_time, unlimited}]),
L = lists:seq(1, Iter),
T1 = now(),
lists:foreach(
fun(N) ->
ok = ?insert(test_tbl, N, N, fun() -> ok end)
end, L),
io:format("** average insert (size = ~p): ~p usec~n",
[Iter, round(timer:now_diff(now(), T1)/Iter)]),
T2 = now(),
lists:foreach(
fun(N) ->
{ok, N} = ?lookup(test_tbl, N, fun() -> ok end)
end, L),
io:format("** average lookup (size = ~p): ~p usec~n",
[Iter, round(timer:now_diff(now(), T2)/Iter)]),
{ok, Iter} = info(test_tbl, size),
delete(test_tbl).
check(List) ->
Size = length(List),
{ok, Size} = info(test_tbl, size),
List = tab2list(test_tbl).
@@ -1,11 +1,12 @@
%%%-------------------------------------------------------------------
%%% File : stringprep_sup.erl
%%% Author : Mickael Remond <mremond@process-one.net>
%%% Description : Supervisor for the Stringprep worker.
%%% Created : 29 Jun 2007 by Mickael Remond <mremond@process-one.net>
%%% File : cache_tab_sup.erl
%%% Author : Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%% Description : Cache tables supervisor
%%%
%%% Created : 30 Aug 2010 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -23,8 +24,7 @@
%%% 02111-1307 USA
%%%
%%%-------------------------------------------------------------------
-module(stringprep_sup).
-module(cache_tab_sup).
-behaviour(supervisor).
@@ -39,30 +39,15 @@
%%====================================================================
%% API functions
%%====================================================================
%%--------------------------------------------------------------------
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
%% Description: Starts the supervisor
%%--------------------------------------------------------------------
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
%%====================================================================
%% Supervisor callbacks
%%====================================================================
%%--------------------------------------------------------------------
%% Func: init(Args) -> {ok, {SupFlags, [ChildSpec]}} |
%% ignore |
%% {error, Reason}
%% Description: Whenever a supervisor is started using
%% supervisor:start_link/[2,3], this function is called by the new process
%% to find out about restart strategy, maximum restart frequency and child
%% specifications.
%%--------------------------------------------------------------------
init([]) ->
StringPrep = {stringprep,
{stringprep, start_link, []},
permanent,
brutal_kill,
worker,
[stringprep]},
{ok,{{one_for_all,10,1}, [StringPrep]}}.
{ok, {{one_for_one,10,1}, []}}.
%%====================================================================
%% Internal functions
%%====================================================================
-6215
View File
File diff suppressed because it is too large Load Diff
+14 -9
View File
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.53)
AC_INIT(ejabberd.erl, version, [ejabberd@process-one.net], [ejabberd])
AC_INIT(ejabberd, m4_esyscmd([grep -o -E "\{vsn,.\".*\"\}" ejabberd.app | cut -d \" -f 2 | tr -d '\n']), [ejabberd@process-one.net], [ejabberd])
# Checks for programs.
AC_PROG_CC
@@ -14,10 +14,6 @@ fi
#locating erlang
AM_WITH_ERLANG
#locating iconv
AM_ICONV
#locating libexpat
AM_WITH_EXPAT
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@@ -32,7 +28,6 @@ AC_PREFIX_DEFAULT(/)
AC_FUNC_MALLOC
AC_HEADER_STDC
AC_MOD_ENABLE(mod_irc, yes)
AC_MOD_ENABLE(mod_muc, yes)
AC_MOD_ENABLE(mod_proxy65, yes)
AC_MOD_ENABLE(mod_pubsub, yes)
@@ -81,7 +76,7 @@ AC_ARG_ENABLE(transient_supervisors,
[case "${enableval}" in
yes) transient_supervisors=true ;;
no) transient_supervisors=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-full-xml) ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-transient_supervisors) ;;
esac],[transient_supervisors=true])
AC_SUBST(transient_supervisors)
@@ -95,14 +90,12 @@ esac],[full_xml=false])
AC_SUBST(full_xml)
AC_CONFIG_FILES([Makefile
$make_mod_irc
$make_mod_muc
$make_mod_pubsub
$make_mod_proxy65
$make_eldap
$make_pam
$make_web
stringprep/Makefile
stun/Makefile
$make_tls
$make_odbc
@@ -139,6 +132,9 @@ if test "$ENABLEUSER" != ""; then
AC_SUBST([INSTALLUSER], [$ENABLEUSER])
fi
AC_CHECK_HEADER(openssl/md2.h, md2=true, md2=false)
AC_SUBST(md2)
AC_CANONICAL_SYSTEM
#AC_DEFINE_UNQUOTED(CPU_VENDOR_OS, "$target")
#AC_SUBST(target_os)
@@ -167,3 +163,12 @@ LD_SHARED="$LD_SHARED $CBIT"
echo "CBIT is set to '$CBIT'"
AC_OUTPUT
echo
echo "********************** WARNING ! ************************"
echo "* ejabberd master is NOT ready for real usage yet, *"
echo "* because it is still in heavy development. *"
echo "* Don't use ejabberd master, it is still alpha code! *"
echo "* Please use ejabberd 2.1.x branch instead. *"
echo "*********************************************************"
echo
+5 -21
View File
@@ -1,11 +1,11 @@
%%%----------------------------------------------------------------------
%%% File : configure.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Purpose :
%%% Purpose :
%%% Created : 27 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -42,33 +42,24 @@ start() ->
end,
case Static of
true ->
ExpatLib = "EXPAT_LIB = $(EXPAT_DIR)\\StaticLibs\\libexpatMT.lib\n",
ExpatFlag = "EXPAT_FLAG = -DXML_STATIC\n",
IconvDir = "ICONV_DIR = c:\\sdk\\GnuWin32\n",
IconvLib = "ICONV_LIB = $(ICONV_DIR)\\lib\\libiconv.lib\n",
ZlibDir = "ZLIB_DIR = c:\\sdk\\GnuWin32\n",
ZlibLib = "ZLIB_LIB = $(ZLIB_DIR)\\lib\\zlib.lib\n";
false ->
ExpatLib = "EXPAT_LIB = $(EXPAT_DIR)\\Libs\\libexpat.lib\n",
ExpatFlag = "",
IconvDir = "ICONV_DIR = c:\\sdk\\GnuWin32\n",
IconvLib = "ICONV_LIB = $(ICONV_DIR)\\lib\\libiconv.lib\n",
ZlibDir = "ZLIB_DIR = c:\\sdk\\GnuWin32\n",
ZlibLib = "ZLIB_LIB = $(ZLIB_DIR)\\lib\\zlib.lib\n"
end,
EVersion = "ERLANG_VERSION = " ++ erlang:system_info(version) ++ "\n",
EIDirS = "EI_DIR = " ++ code:lib_dir("erl_interface") ++ "\n",
EIDirS = "EI_DIR = " ++ code:lib_dir(erl_interface) ++ "\n",
RootDirS = "ERLANG_DIR = " ++ code:root_dir() ++ "\n",
%% Load the ejabberd application description so that ?VERSION can read the vsn key
application:load(ejabberd),
Version = "EJABBERD_VERSION = " ++ ?VERSION ++ "\n",
ExpatDir = "EXPAT_DIR = c:\\sdk\\Expat-2.0.0\n",
OpenSSLDir = "OPENSSL_DIR = c:\\sdk\\OpenSSL\n",
DBType = "DBTYPE = generic\n", %% 'generic' or 'mssql'
SSLDir = "SSLDIR = " ++ code:lib_dir("ssl") ++ "\n",
StdLibDir = "STDLIBDIR = " ++ code:lib_dir("stdlib") ++ "\n",
SSLDir = "SSLDIR = " ++ code:lib_dir(ssl) ++ "\n",
StdLibDir = "STDLIBDIR = " ++ code:lib_dir(stdlib) ++ "\n",
file:write_file("Makefile.inc",
list_to_binary(EVersion ++
@@ -79,13 +70,6 @@ start() ->
StdLibDir ++
OpenSSLDir ++
DBType ++
ExpatDir ++
ExpatLib ++
ExpatFlag ++
IconvDir ++
IconvLib ++
ZlibDir ++
ZlibLib)),
halt().
+157 -51
View File
@@ -5,7 +5,7 @@
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -30,22 +30,46 @@
-export([start/0,
register_mechanism/3,
listmech/1,
server_new/7,
server_new/8,
server_start/3,
server_step/2]).
-include("cyrsasl.hrl").
-include("ejabberd.hrl").
%% @type saslmechanism() = {sasl_mechanism, Mechanism, Module, Require_Plain}
%% Mechanism = string()
%% Module = atom()
%% Require_Plain = bool().
%% Registry entry of a supported SASL mechanism.
-record(sasl_mechanism, {mechanism, module, require_plain_password}).
-record(sasl_state, {service, myname, realm,
get_password, check_password, check_password_digest,
mech_mod, mech_state}).
%% @type saslstate() = {sasl_state, Service, Myname, Realm, GetPassword, CheckPassword, CheckPasswordDigest, Mech_Mod, Mech_State}
%% Service = string()
%% Myname = string()
%% Realm = string()
%% GetPassword = function()
%% CheckPassword = function()
%% CheckPasswordDigest = any()
%% Mech_Mod = atom()
%% Mech_State = term().
%% State of this process.
-record(sasl_state, {service, myname,
mech_mod, mech_state, params}).
-export([behaviour_info/1]).
%% @hidden
behaviour_info(callbacks) ->
[{mech_new, 4}, {mech_step, 2}];
[{mech_new, 1}, {mech_step, 2}];
behaviour_info(_Other) ->
undefined.
%% @spec () -> ok
start() ->
ets:new(sasl_mechanism, [named_table,
public,
@@ -53,49 +77,81 @@ start() ->
cyrsasl_plain:start([]),
cyrsasl_digest:start([]),
cyrsasl_anonymous:start([]),
maybe_try_start_gssapi(),
ok.
maybe_try_start_gssapi() ->
case os:getenv("KRB5_KTNAME") of
false ->
ok;
_String ->
try_start_gssapi()
end.
try_start_gssapi() ->
case code:load_file(esasl) of
{module, _Module} ->
cyrsasl_gssapi:start([]);
{error, What} ->
?ERROR_MSG("Support for GSSAPI not started because esasl.beam was not found: ~p", [What])
end.
%% @spec (Mechanism, Module, Require_Plain) -> true
%% Mechanism = string()
%% Module = atom()
%% Require_Plain = bool()
register_mechanism(Mechanism, Module, RequirePlainPassword) ->
ets:insert(sasl_mechanism,
#sasl_mechanism{mechanism = Mechanism,
module = Module,
require_plain_password = RequirePlainPassword}).
%%% TODO: use callbacks
%%-include("ejabberd.hrl").
%%-include("jlib.hrl").
%%check_authzid(_State, Props) ->
%% AuthzId = xml:get_attr_s(authzid, Props),
%% case jlib:string_to_jid(AuthzId) of
%% error ->
%% {error, "invalid-authzid"};
%% JID ->
%% LUser = jlib:nodeprep(xml:get_attr_s(username, Props)),
%% {U, S, R} = jlib:jid_tolower(JID),
%% case R of
%% "" ->
%% {error, "invalid-authzid"};
%% _ ->
%% case {LUser, ?MYNAME} of
%% {U, S} ->
%% ok;
%% _ ->
%% {error, "invalid-authzid"}
%% end
%% end
%% end.
% TODO use callbacks
%-include("ejabberd.hrl").
%-include("jlib.hrl").
%check_authzid(_State, Props) ->
% AuthzId = xml:get_attr_s(authzid, Props),
% case jlib:string_to_jid(AuthzId) of
% error ->
% {error, "invalid-authzid"};
% JID ->
% LUser = jlib:nodeprep(xml:get_attr_s(username, Props)),
% {U, S, R} = jlib:short_prepd_jid(JID),
% case R of
% "" ->
% {error, "invalid-authzid"};
% _ ->
% case {LUser, ?MYNAME} of
% {U, S} ->
% ok;
% _ ->
% {error, "invalid-authzid"}
% end
% end
% end.
%% @spec (State, Props) -> ok | {error, 'not-authorized'}
%% State = saslstate()
%% Props = [{Key, Value}]
%% Key = atom()
%% Value = string()
check_credentials(_State, Props) ->
User = xml:get_attr_s(username, Props),
case jlib:nodeprep(User) of
error ->
{error, "not-authorized"};
"" ->
{error, "not-authorized"};
_LUser ->
ok
case proplists:get_value(username, Props) of
undefined ->
{error, 'not-authorized'};
User ->
case exmpp_stringprep:is_node(User) of
false -> {error, 'not-authorized'};
true -> ok
end
end.
%% @spec (Host) -> [Mechanism]
%% Host = string()
%% Mechanism = string()
listmech(Host) ->
RequirePlainPassword = ejabberd_auth:plain_password_required(Host),
@@ -112,35 +168,78 @@ listmech(Host) ->
['$1']}]),
filter_anonymous(Host, Mechs).
%% @spec (Service, ServerFQDN, UserRealm, SecFlags, GetPassword, CheckPassword, CheckPasswordDigest, Socket) -> saslstate()
%% Service = string()
%% ServerFQDN = string()
%% UserRealm = string()
%% SecFlags = [term()]
%% GetPassword = function()
%% CheckPassword = function()
server_new(Service, ServerFQDN, UserRealm, _SecFlags,
GetPassword, CheckPassword, CheckPasswordDigest) ->
GetPassword, CheckPassword, CheckPasswordDigest, Socket) ->
Params = #sasl_params{
host = ServerFQDN,
realm = UserRealm,
get_password = GetPassword,
check_password = CheckPassword,
check_password_digest= CheckPasswordDigest,
socket = Socket
},
#sasl_state{service = Service,
myname = ServerFQDN,
realm = UserRealm,
get_password = GetPassword,
check_password = CheckPassword,
check_password_digest= CheckPasswordDigest}.
params = Params}.
%% @spec (State, Mech, ClientIn) -> Ok | Continue | Error
%% State = saslstate()
%% Mech = string()
%% ClientIn = string()
%% Ok = {ok, Props}
%% Props = [Prop]
%% Prop = [{Key, Value}]
%% Key = atom()
%% Value = string()
%% Continue = {continue, ServerOut, New_State}
%% ServerOut = string()
%% New_State = saslstate()
%% Error = {error, Reason} | {error, Username, Reason}
%% Reason = term()
%% Username = string()
server_start(State, Mech, ClientIn) ->
case lists:member(Mech, listmech(State#sasl_state.myname)) of
true ->
case ets:lookup(sasl_mechanism, Mech) of
[#sasl_mechanism{module = Module}] ->
{ok, MechState} = Module:mech_new(
State#sasl_state.myname,
State#sasl_state.get_password,
State#sasl_state.check_password,
State#sasl_state.check_password_digest),
{ok, MechState} =
Module:mech_new(State#sasl_state.params),
server_step(State#sasl_state{mech_mod = Module,
mech_state = MechState},
ClientIn);
_ ->
{error, "no-mechanism"}
{error, 'invalid-mechanism'}
end;
false ->
{error, "no-mechanism"}
{error, 'invalid-mechanism'}
end.
%% @spec (State, ClientIn) -> Ok | Continue | Error
%% State = saslstate()
%% ClientIn = string()
%% Ok = {ok, Props}
%% Props = [Prop]
%% Prop = [{Key, Value}]
%% Key = atom()
%% Value = string()
%% Continue = {continue, ServerOut, New_State}
%% ServerOut = string()
%% New_State = saslstate()
%% Error = {error, Reason} | {error, Username, Reason}
%% Reason = term()
%% Username = string()
server_step(State, ClientIn) ->
Module = State#sasl_state.mech_mod,
MechState = State#sasl_state.mech_state,
@@ -161,8 +260,15 @@ server_step(State, ClientIn) ->
{error, Error}
end.
%% Remove the anonymous mechanism from the list if not enabled for the given
%% host
%% @spec (Host, Mechs) -> [Filtered_Mechs]
%% Host = string()
%% Mechs = [Mech]
%% Mech = string()
%% Filtered_Mechs = [Mech]
%%
%% @doc Remove the anonymous mechanism from the list if not enabled for
%% the given host.
filter_anonymous(Host, Mechs) ->
case ejabberd_auth_anonymous:is_sasl_anonymous_enabled(Host) of
true -> Mechs;
+15
View File
@@ -0,0 +1,15 @@
%% @type saslparams() = {sasl_params, Host, Realm, GetPassword, CheckPassword, CheckPasswordDigest}
%% Host = string()
%% Realm = string()
%% GetPassword = function()
%% CheckPassword = function()
%% CheckPasswordDigest = any().
%% Parameters for SASL.
-record(sasl_params, {
host,
realm,
get_password,
check_password,
check_password_digest,
socket}).
+24 -4
View File
@@ -6,7 +6,7 @@
%%% Created : 23 Aug 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -27,22 +27,42 @@
-module(cyrsasl_anonymous).
-export([start/1, stop/0, mech_new/4, mech_step/2]).
-export([start/1, stop/0, mech_new/1, mech_step/2]).
-include("cyrsasl.hrl").
-behaviour(cyrsasl).
%% @type mechstate() = {state, Server}
%% Server = string().
-record(state, {server}).
%% @spec (Opts) -> true
%% Opts = term()
start(_Opts) ->
cyrsasl:register_mechanism("ANONYMOUS", ?MODULE, false),
ok.
%% @spec () -> ok
stop() ->
ok.
mech_new(Host, _GetPassword, _CheckPassword, _CheckPasswordDigest) ->
mech_new(#sasl_params{host=Host}) ->
{ok, #state{server = Host}}.
%% @spec (State, ClientIn) -> Ok | Error
%% State = mechstate()
%% ClientIn = string()
%% Ok = {ok, Props}
%% Props = [Prop]
%% Prop = {username, Username} | {auth_module, AuthModule}
%% Username = string()
%% AuthModule = ejabberd_auth_anonymous
%% Error = {error, 'not-authorized'}
mech_step(State, _ClientIn) ->
%% We generate a random username:
User = lists:concat([randoms:get_string() | tuple_to_list(now())]),
@@ -50,7 +70,7 @@ mech_step(State, _ClientIn) ->
%% Checks that the username is available
case ejabberd_auth:is_user_exists(User, Server) of
true -> {error, "not-authorized"};
true -> {error, 'not-authorized'};
false -> {ok, [{username, User},
{auth_module, ejabberd_auth_anonymous}]}
end.
+166 -21
View File
@@ -5,7 +5,7 @@
%%% Created : 11 Mar 2003 by Alexey Shchepin <alexey@sevcom.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -29,29 +29,60 @@
-export([start/1,
stop/0,
mech_new/4,
mech_new/1,
mech_step/2]).
-include("ejabberd.hrl").
-include("cyrsasl.hrl").
-behaviour(cyrsasl).
%% @type mechstate() = {state, Step, Nonce, Username, AuthzId, GetPassword, CheckPassword, AuthModule, Host}
%% Step = 1 | 3 | 5
%% Nonce = string()
%% Username = string()
%% AuthzId = string()
%% GetPassword = function()
%% AuthModule = atom()
%% Host = string().
-record(state, {step, nonce, username, authzid, get_password, check_password, auth_module,
host}).
%% @spec (Opts) -> true
%% Opts = term()
start(_Opts) ->
cyrsasl:register_mechanism("DIGEST-MD5", ?MODULE, true).
%% @spec () -> ok
stop() ->
ok.
mech_new(Host, GetPassword, _CheckPassword, CheckPasswordDigest) ->
mech_new(#sasl_params{host=Host, get_password=GetPassword,
check_password_digest=CheckPasswordDigest}) ->
{ok, #state{step = 1,
nonce = randoms:get_string(),
host = Host,
get_password = GetPassword,
check_password = CheckPasswordDigest}}.
%% @spec (State, ClientIn) -> Ok | Continue | Error
%% State = mechstate()
%% ClientIn = string()
%% Ok = {ok, Props}
%% Props = [Prop]
%% Prop = {username, Username} | {authzid, AuthzId} | {auth_module, AuthModule}
%% Username = string()
%% AuthzId = string()
%% AuthModule = atom()
%% Continue = {continue, ServerOut, New_State}
%% ServerOut = string()
%% New_State = mechstate()
%% Error = {error, Reason} | {error, Reason, Username}
%% Reason = term()
mech_step(#state{step = 1, nonce = Nonce} = State, _) ->
{continue,
"nonce=\"" ++ Nonce ++
@@ -60,23 +91,23 @@ mech_step(#state{step = 1, nonce = Nonce} = State, _) ->
mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
case parse(ClientIn) of
bad ->
{error, "bad-protocol"};
{error, 'bad-protocol'};
KeyVals ->
DigestURI = xml:get_attr_s("digest-uri", KeyVals),
UserName = xml:get_attr_s("username", KeyVals),
DigestURI = proplists:get_value("digest-uri", KeyVals, ""),
UserName = proplists:get_value("username", KeyVals, ""),
case is_digesturi_valid(DigestURI, State#state.host) of
false ->
?DEBUG("User login not authorized because digest-uri "
"seems invalid: ~p", [DigestURI]),
{error, "not-authorized", UserName};
{error, 'not-authorized', UserName};
true ->
AuthzId = xml:get_attr_s("authzid", KeyVals),
AuthzId = proplists:get_value("authzid", KeyVals, ""),
case (State#state.get_password)(UserName) of
{false, _} ->
{error, "not-authorized", UserName};
{error, 'not-authorized', UserName};
{Passwd, AuthModule} ->
case (State#state.check_password)(UserName, "",
xml:get_attr_s("response", KeyVals),
proplists:get_value("response", KeyVals, ""),
fun(PW) -> response(KeyVals, UserName, PW, Nonce, AuthzId,
"AUTHENTICATE") end) of
{true, _} ->
@@ -90,9 +121,9 @@ mech_step(#state{step = 3, nonce = Nonce} = State, ClientIn) ->
username = UserName,
authzid = AuthzId}};
false ->
{error, "not-authorized", UserName};
{error, 'not-authorized', UserName};
{false, _} ->
{error, "not-authorized", UserName}
{error, 'not-authorized', UserName}
end
end
end
@@ -105,11 +136,18 @@ mech_step(#state{step = 5,
{auth_module, AuthModule}]};
mech_step(A, B) ->
?DEBUG("SASL DIGEST: A ~p B ~p", [A,B]),
{error, "bad-protocol"}.
{error, 'bad-protocol'}.
%% @spec (S) -> [{Key, Value}] | bad
%% S = string()
%% Key = string()
%% Value = string()
parse(S) ->
parse1(S, "", []).
%% @hidden
parse1([$= | Cs], S, Ts) ->
parse2(Cs, lists:reverse(S), "", Ts);
parse1([$, | Cs], [], Ts) ->
@@ -123,6 +161,8 @@ parse1([], [], T) ->
parse1([], _S, _T) ->
bad.
%% @hidden
parse2([$\" | Cs], Key, Val, Ts) ->
parse3(Cs, Key, Val, Ts);
parse2([C | Cs], Key, Val, Ts) ->
@@ -130,6 +170,8 @@ parse2([C | Cs], Key, Val, Ts) ->
parse2([], _, _, _) ->
bad.
%% @hidden
parse3([$\" | Cs], Key, Val, Ts) ->
parse4(Cs, Key, Val, Ts);
parse3([$\\, C | Cs], Key, Val, Ts) ->
@@ -139,6 +181,8 @@ parse3([C | Cs], Key, Val, Ts) ->
parse3([], _, _, _) ->
bad.
%% @hidden
parse4([$, | Cs], Key, Val, Ts) ->
parse1(Cs, "", [{Key, lists:reverse(Val)} | Ts]);
parse4([$\s | Cs], Key, Val, Ts) ->
@@ -149,6 +193,10 @@ parse4([], Key, Val, Ts) ->
parse1([], "", [{Key, lists:reverse(Val)} | Ts]).
%% @spec (DigestURICase, JabberHost) -> bool()
%% DigestURICase = string()
%% JabberHost = string()
%%
%% @doc Check if the digest-uri is valid.
%% RFC-2831 allows to provide the IP address in Host,
%% however ejabberd doesn't allow that.
@@ -156,8 +204,9 @@ parse4([], Key, Val, Ts) ->
%% is provided by several hosts (being one of them server3.example.org),
%% then digest-uri can be like xmpp/server3.example.org/jabber.example.org
%% In that case, ejabberd only checks the service name, not the host.
is_digesturi_valid(DigestURICase, JabberHost) ->
DigestURI = stringprep:tolower(DigestURICase),
DigestURI = exmpp_stringprep:to_lower(DigestURICase),
case catch string:tokens(DigestURI, "/") of
["xmpp", Host] when Host == JabberHost ->
true;
@@ -170,14 +219,20 @@ is_digesturi_valid(DigestURICase, JabberHost) ->
%% @hidden
digit_to_xchar(D) when (D >= 0) and (D < 10) ->
D + 48;
digit_to_xchar(D) ->
D + 87.
%% @hidden
hex(S) ->
hex(S, []).
%% @hidden
hex([], Res) ->
lists:reverse(Res);
hex([N | Ns], Res) ->
@@ -185,20 +240,35 @@ hex([N | Ns], Res) ->
digit_to_xchar(N div 16) | Res]).
%% @spec (KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) -> string()
%% KeyVals = [{Key, Value}]
%% Key = string()
%% Value = string()
%% User = string()
%% Passwd = string()
%% Nonce = string()
%% AuthzId = nil() | string()
%% A2Prefix = string()
response(KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) ->
Realm = xml:get_attr_s("realm", KeyVals),
CNonce = xml:get_attr_s("cnonce", KeyVals),
DigestURI = xml:get_attr_s("digest-uri", KeyVals),
NC = xml:get_attr_s("nc", KeyVals),
QOP = xml:get_attr_s("qop", KeyVals),
Realm = proplists:get_value("realm", KeyVals, ""),
CNonce = proplists:get_value("cnonce", KeyVals, ""),
DigestURI = proplists:get_value("digest-uri", KeyVals, ""),
NC = proplists:get_value("nc", KeyVals, ""),
QOP = proplists:get_value("qop", KeyVals, ""),
%% handle non-fully latin-1 strings as specified
%% on RFC 2831 Section 2.1.2.1 (EJAB-476)
SUser = sanitize(User),
SPasswd = sanitize(Passwd),
SRealm = sanitize(Realm),
A1 = case AuthzId of
"" ->
binary_to_list(
crypto:md5(User ++ ":" ++ Realm ++ ":" ++ Passwd)) ++
crypto:md5(SUser ++ ":" ++ SRealm ++ ":" ++ SPasswd)) ++
":" ++ Nonce ++ ":" ++ CNonce;
_ ->
binary_to_list(
crypto:md5(User ++ ":" ++ Realm ++ ":" ++ Passwd)) ++
crypto:md5(SUser ++ ":" ++ SRealm ++ ":" ++ SPasswd)) ++
":" ++ Nonce ++ ":" ++ CNonce ++ ":" ++ AuthzId
end,
A2 = case QOP of
@@ -214,4 +284,79 @@ response(KeyVals, User, Passwd, Nonce, AuthzId, A2Prefix) ->
hex(binary_to_list(crypto:md5(T))).
sanitize(V) ->
L = from_utf8(V),
case lists:all(fun is_latin1/1, L) of
true -> L;
false -> V
end.
%%%% copied from xmerl_ucs:from_utf8/1 and xmerl_ucs:is_latin1/1 , to not
%%%% require xmerl as a dependency only for this.
from_utf8(Bin) when is_binary(Bin) -> from_utf8(binary_to_list(Bin));
from_utf8(List) ->
case expand_utf8(List) of
{Result,0} -> Result;
{_Res,_NumBadChar} ->
exit({ucs,{bad_utf8_character_code}})
end.
%% expand_utf8([Byte]) -> {[UnicodeChar],NumberOfBadBytes}
%% Expand UTF8 byte sequences to ISO 10646/Unicode
%% charactes. Any illegal bytes are removed and the number of
%% bad bytes are returned.
%%
%% Reference:
%% RFC 3629: "UTF-8, a transformation format of ISO 10646".
expand_utf8(Str) ->
expand_utf8_1(Str, [], 0).
expand_utf8_1([C|Cs], Acc, Bad) when C < 16#80 ->
%% Plain Ascii character.
expand_utf8_1(Cs, [C|Acc], Bad);
expand_utf8_1([C1,C2|Cs], Acc, Bad) when C1 band 16#E0 =:= 16#C0,
C2 band 16#C0 =:= 16#80 ->
case ((C1 band 16#1F) bsl 6) bor (C2 band 16#3F) of
C when 16#80 =< C ->
expand_utf8_1(Cs, [C|Acc], Bad);
_ ->
%% Bad range.
expand_utf8_1(Cs, Acc, Bad+1)
end;
expand_utf8_1([C1,C2,C3|Cs], Acc, Bad) when C1 band 16#F0 =:= 16#E0,
C2 band 16#C0 =:= 16#80,
C3 band 16#C0 =:= 16#80 ->
case ((((C1 band 16#0F) bsl 6) bor (C2 band 16#3F)) bsl 6) bor
(C3 band 16#3F) of
C when 16#800 =< C ->
expand_utf8_1(Cs, [C|Acc], Bad);
_ ->
%% Bad range.
expand_utf8_1(Cs, Acc, Bad+1)
end;
expand_utf8_1([C1,C2,C3,C4|Cs], Acc, Bad) when C1 band 16#F8 =:= 16#F0,
C2 band 16#C0 =:= 16#80,
C3 band 16#C0 =:= 16#80,
C4 band 16#C0 =:= 16#80 ->
case ((((((C1 band 16#0F) bsl 6) bor (C2 band 16#3F)) bsl 6) bor
(C3 band 16#3F)) bsl 6) bor (C4 band 16#3F) of
C when 16#10000 =< C ->
expand_utf8_1(Cs, [C|Acc], Bad);
_ ->
%% Bad range.
expand_utf8_1(Cs, Acc, Bad+1)
end;
expand_utf8_1([_|Cs], Acc, Bad) ->
%% Ignore bad character.
expand_utf8_1(Cs, Acc, Bad+1);
expand_utf8_1([], Acc, Bad) -> {lists:reverse(Acc),Bad}.
%%% Test for legitimate Latin-1 code
is_latin1(Ch) when is_integer(Ch), Ch >= 0, Ch =< 255 -> true;
is_latin1(_) -> false.
+164
View File
@@ -0,0 +1,164 @@
%%%----------------------------------------------------------------------
%%% File : cyrsasl_gssapi.erl
%%% Author : Mikael Magnusson <mikma@users.sourceforge.net>
%%% Purpose : GSSAPI SASL mechanism
%%% Created : 1 June 2007 by Mikael Magnusson <mikma@users.sourceforge.net>
%%%----------------------------------------------------------------------
%%%
%%% Copyright (C) 2007-2009 Mikael Magnusson <mikma@users.sourceforge.net>
%%%
%%% Permission is hereby granted, free of charge, to any person
%%% obtaining a copy of this software and associated documentation
%%% files (the "Software"), to deal in the Software without
%%% restriction, including without limitation the rights to use, copy,
%%% modify, merge, publish, distribute, sublicense, and/or sell copies
%%% of the Software, and to permit persons to whom the Software is
%%% furnished to do so, subject to the following conditions:
%%%
%%% The above copyright notice and this permission notice shall be
%%% included in all copies or substantial portions of the Software.
%%%
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
%%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
%%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
%%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
%%% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
%%% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
%%% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
%%% SOFTWARE.
%%%
%%%
%%% configuration options:
%%% {sasl_realm, "<Kerberos realm>"}.
%%%
%%% environment variables:
%%% KRB5_KTNAME
%%%
-module(cyrsasl_gssapi).
-author('mikma@users.sourceforge.net').
-export([start/1,
stop/0,
mech_new/1,
mech_step/2]).
-include("ejabberd.hrl").
-include("cyrsasl.hrl").
-behaviour(cyrsasl).
-define(SERVER, ?MODULE).
-define(SERVICE, "xmpp").
-record(state, {sasl,
needsmore=true,
step=0,
host,
realm,
authid,
authzid,
authrealm,
error}).
start(_Opts) ->
ChildSpec =
{?SERVER,
{esasl, start_link, [{local, ?SERVER}]},
transient,
1000,
worker,
[esasl]},
case supervisor:start_child(ejabberd_sup, ChildSpec) of
{ok, _Pid} ->
cyrsasl:register_mechanism("GSSAPI", ?MODULE, false);
{error, Error} = E ->
?ERROR_MSG("esasl failed: ~p", [Error]),
E
end.
stop() ->
catch esasl:stop(?SERVER),
supervisor:terminate_child(ejabberd_sup, ?SERVER),
supervisor:delete_child(ejabberd_sup, ?SERVER).
mech_new(#sasl_params{host=Host, realm=Realm, socket=Socket}) ->
case ejabberd_socket:gethostname(Socket) of
{ok, FQDN} ->
?DEBUG("mech_new ~p ~p ~p~n", [Host, Realm, FQDN]),
case esasl:server_start(?SERVER, "GSSAPI", ?SERVICE, FQDN) of
{ok, Sasl} ->
{ok, #state{sasl=Sasl,host=Host,realm=Realm}};
{error, {gsasl_error, Error}} ->
{ok, Str} = esasl:str_error(?SERVER, Error),
?DEBUG("esasl error: ~p", [Str]),
{ok, #state{needsmore=error,error="internal-server-error"}};
{error, Error} ->
?DEBUG("esasl error: ~p", [Error]),
{ok, #state{needsmore=error,error="internal-server-error"}}
end;
{error, Error} ->
?DEBUG("gethostname error: ~p", [Error]),
{ok, #state{needsmore=error,error="internal-server-error"}}
end.
mech_step(State, ClientIn) when is_list(ClientIn) ->
catch do_step(State, ClientIn).
do_step(#state{needsmore=error,error=Error}=_State, _) ->
{error, Error};
do_step(#state{needsmore=false}=State, _) ->
check_user(State);
do_step(#state{needsmore=true,sasl=Sasl,step=Step}=State, ClientIn) ->
?DEBUG("mech_step~n", []),
case esasl:step(Sasl, list_to_binary(ClientIn)) of
{ok, RspAuth} ->
?DEBUG("ok~n", []),
{ok, Display_name} = esasl:property_get(Sasl, gssapi_display_name),
{ok, Authzid} = esasl:property_get(Sasl, authzid),
{Authid, [$@ | Auth_realm]} =
lists:splitwith(fun(E)->E =/= $@ end, Display_name),
State1 = State#state{authid=Authid,
authzid=Authzid,
authrealm=Auth_realm},
handle_step_ok(State1, binary_to_list(RspAuth));
{needsmore, RspAuth} ->
?DEBUG("needsmore~n", []),
if (Step > 0) and (ClientIn =:= []) and (RspAuth =:= <<>>) ->
{error, "not-authorized"};
true ->
{continue, binary_to_list(RspAuth),
State#state{step=Step+1}}
end;
{error, _} ->
{error, "not-authorized"}
end.
handle_step_ok(State, []) ->
check_user(State);
handle_step_ok(#state{step=Step}=State, RspAuth) ->
?DEBUG("continue~n", []),
{continue, RspAuth, State#state{needsmore=false,step=Step+1}}.
check_user(#state{authid=Authid,authzid=Authzid,
authrealm=Auth_realm,host=Host,realm=Realm}) ->
if Realm =/= Auth_realm ->
?DEBUG("bad realm ~p (expected ~p)~n",[Auth_realm, Realm]),
throw({error, "not-authorized"});
true ->
ok
end,
case ejabberd_auth:is_user_exists(Authid, Host) of
false ->
?DEBUG("bad user ~p~n",[Authid]),
throw({error, "not-authorized"});
true ->
ok
end,
?DEBUG("GSSAPI authenticated ~p ~p~n", [Authid, Authzid]),
{ok, [{username, Authid}, {authzid, Authzid}]}.
+60 -7
View File
@@ -5,7 +5,7 @@
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -27,40 +27,86 @@
-module(cyrsasl_plain).
-author('alexey@process-one.net').
-export([start/1, stop/0, mech_new/4, mech_step/2, parse/1]).
-export([start/1, stop/0, mech_new/1, mech_step/2, parse/1]).
-include("cyrsasl.hrl").
-behaviour(cyrsasl).
%% @type mechstate() = {state, CheckPassword}
%% CheckPassword = function().
-record(state, {check_password}).
%% @spec (Opts) -> true
%% Opts = term()
start(_Opts) ->
cyrsasl:register_mechanism("PLAIN", ?MODULE, false),
ok.
%% @spec () -> ok
stop() ->
ok.
mech_new(_Host, _GetPassword, CheckPassword, _CheckPasswordDigest) ->
mech_new(#sasl_params{check_password = CheckPassword}) ->
{ok, #state{check_password = CheckPassword}}.
%% @spec (State, ClientIn) -> Ok | Error
%% State = mechstate()
%% ClientIn = string()
%% Ok = {ok, Props}
%% Props = [Prop]
%% Prop = {username, Username} | {authzid, AuthzId} | {auth_module, AuthModule}
%% Username = string()
%% AuthzId = string()
%% AuthModule = atom()
%% Error = {error, Reason} | {error, Reason, Username}
%% Reason = term()
mech_step(State, ClientIn) ->
case parse(ClientIn) of
case prepare(ClientIn) of
[AuthzId, User, Password] ->
case (State#state.check_password)(User, Password) of
{true, AuthModule} ->
{ok, [{username, User}, {authzid, AuthzId},
{auth_module, AuthModule}]};
{false, ReasonAuthFail} when is_list(ReasonAuthFail) ->
{error, ReasonAuthFail, User};
_ ->
{error, "not-authorized", User}
{error, 'not-authorized', User}
end;
_ ->
{error, "bad-protocol"}
{error, 'bad-protocol'}
end.
prepare(ClientIn) ->
case parse(ClientIn) of
[[], UserMaybeDomain, Password] ->
case parse_domain(UserMaybeDomain) of
%% <NUL>login@domain<NUL>pwd
[User, _Domain] ->
[UserMaybeDomain, User, Password];
%% <NUL>login<NUL>pwd
[User] ->
["", User, Password]
end;
%% login@domain<NUL>login<NUL>pwd
[AuthzId, User, Password] ->
[AuthzId, User, Password];
_ ->
error
end.
%% @hidden
parse(S) ->
parse1(S, "", []).
%% @hidden
parse1([0 | Cs], S, T) ->
parse1(Cs, "", [lists:reverse(S) | T]);
parse1([C | Cs], S, T) ->
@@ -71,5 +117,12 @@ parse1([], S, T) ->
lists:reverse([lists:reverse(S) | T]).
parse_domain(S) ->
parse_domain1(S, "", []).
parse_domain1([$@ | Cs], S, T) ->
parse_domain1(Cs, "", [lists:reverse(S) | T]);
parse_domain1([C | Cs], S, T) ->
parse_domain1(Cs, [C | S], T);
parse_domain1([], S, T) ->
lists:reverse([lists:reverse(S) | T]).
+5 -16
View File
@@ -1,8 +1,6 @@
%% $Id$
{application, ejabberd,
[{description, "ejabberd"},
{vsn, "2.1.0"},
{vsn, "3.0.0-alpha-x"},
{modules, [acl,
adhoc,
configure,
@@ -15,10 +13,9 @@
ejabberd_auth_anonymous,
ejabberd_auth,
ejabberd_auth_external,
ejabberd_auth_internal,
ejabberd_auth_ldap,
ejabberd_auth_odbc,
ejabberd_auth_pam,
ejabberd_auth_storage,
ejabberd,
ejabberd_c2s,
ejabberd_c2s_config,
@@ -37,6 +34,7 @@
ejabberd_rdbms,
ejabberd_receiver,
ejabberd_router,
ejabberd_router_multicast,
ejabberd_s2s,
ejabberd_s2s_in,
ejabberd_s2s_out,
@@ -61,7 +59,6 @@
gen_mod,
gen_pubsub_node,
gen_pubsub_nodetree,
iconv,
idna,
jd2ejd,
jlib,
@@ -74,19 +71,13 @@
mod_echo,
mod_http_bind,
mod_http_fileserver,
mod_irc,
mod_irc_connection,
mod_last,
mod_last_odbc,
mod_muc,
mod_muc_log,
mod_muc_room,
mod_offline,
mod_offline_odbc,
mod_privacy,
mod_privacy_odbc,
mod_private,
mod_private_odbc,
mod_proxy65,
mod_proxy65_lib,
mod_proxy65_service,
@@ -95,14 +86,12 @@
mod_pubsub,
mod_register,
mod_roster,
mod_roster_odbc,
mod_service_log,
mod_shared_roster,
mod_stats,
mod_time,
mod_vcard,
mod_vcard_ldap,
mod_vcard_odbc,
mod_version,
node_buddy,
node_club,
@@ -115,6 +104,7 @@
nodetree_virtual,
p1_fsm,
p1_mnesia,
p1_prof,
randoms,
sha,
shaper,
@@ -123,13 +113,13 @@
tls,
translate,
xml,
xml_stream,
'XmppAddr'
]},
{registered, [ejabberd,
ejabberd_sup,
ejabberd_auth,
ejabberd_router,
ejabberd_router_multicast,
ejabberd_sm,
ejabberd_s2s,
ejabberd_local,
@@ -142,7 +132,6 @@
ejabberd_mod_roster,
ejabberd_mod_echo,
ejabberd_mod_pubsub,
ejabberd_mod_irc,
ejabberd_mod_muc,
ejabberd_offline,
random_generator
+159 -83
View File
@@ -5,7 +5,7 @@
%%% The parameters used in this configuration file are explained in more detail
%%% in the ejabberd Installation and Operation Guide.
%%% Please consult the Guide in case of doubts, it is included in
%%% Please consult the Guide in case of doubts, it is included with
%%% your copy of ejabberd, and is also available online at
%%% http://www.process-one.net/en/ejabberd/docs/
@@ -26,11 +26,11 @@
%%% [http_poll, web_admin, tls]
%%%
%%% - A keyword of ejabberd is a word in lowercase.
%%% The strings are enclosed in "" and can have spaces, dots...
%%% Strings are enclosed in "" and can contain spaces, dots, ...
%%% {language, "en"}.
%%% {ldap_rootdn, "dc=example,dc=com"}.
%%%
%%% - This term includes a tuple, a keyword, a list and two strings:
%%% - This term includes a tuple, a keyword, a list, and two strings:
%%% {hosts, ["jabber.example.net", "im.example.com"]}.
%%%
@@ -74,26 +74,36 @@
%%
%% watchdog_admins: Only useful for developers: if an ejabberd process
%% consumes a lot of memory, send live notifications to these XMPP
%% consumes a lot of memory, send live notifications to these XMPP
%% accounts.
%%
%%{watchdog_admins, ["bob@example.com"]}.
%%%. =====================
%%%' CLUSTER CONFIGURATION
%% clusterid: the integer id of the cluster of nodes this node will
%% belong to.
{clusterid, 1}.
%%%. ================
%%%' SERVED HOSTNAMES
%%
%% hosts: Domains served by ejabberd.
%% You can define one or several, for example:
%% {hosts, ["example.net", "example.com", "example.org"]}.
%% {hosts, ["localhost", "example.net", "example.com", "example.org"]}.
%%
%% Additional hosts will be discovered from the 'hosts' database table
%% configured for the first host.
{hosts, ["localhost"]}.
%%
%% route_subdomains: Delegate subdomains to other XMPP server.
%% route_subdomains: Delegate subdomains to other XMPP servers.
%% For example, if this ejabberd serves example.org and you want
%% to allow communication with a XMPP server called im.example.org.
%% to allow communication with an XMPP server called im.example.org.
%%
%%{route_subdomains, s2s}.
@@ -102,8 +112,8 @@
%%%' LISTENING PORTS
%%
%% listen: Which ports will ejabberd listen, which service handles it
%% and what options to start it with.
%% listen: The ports ejabberd will listen on, which service each is handled
%% by and what options to start it with.
%%
{listen,
[
@@ -111,8 +121,8 @@
{5222, ejabberd_c2s, [
%%
%% If TLS is compiled and you installed a SSL
%% certificate, put the correct path to the
%% If TLS is compiled in and you installed a SSL
%% certificate, specify the full path to the
%% file and uncomment this line:
%%
%%{certfile, "/path/to/ssl.pem"}, starttls,
@@ -123,7 +133,7 @@
]},
%%
%% To enable the old SSL connection method in port 5223:
%% To enable the old SSL connection method on port 5223:
%%
%%{5223, ejabberd_c2s, [
%% {access, c2s},
@@ -138,7 +148,7 @@
]},
%%
%% ejabberd_service: Interact with external components (transports...)
%% ejabberd_service: Interact with external components (transports, ...)
%%
%%{8888, ejabberd_service, [
%% {access, all},
@@ -162,6 +172,7 @@
captcha,
http_bind,
http_poll,
%%register,
web_admin
]}
@@ -169,10 +180,10 @@
%%
%% s2s_use_starttls: Enable STARTTLS + Dialback for S2S connections.
%% Allowed values are: true or false.
%% Allowed values are: false optional required required_trusted
%% You must specify a certificate file.
%%
%%{s2s_use_starttls, true}.
%%{s2s_use_starttls, optional}.
%%
%% s2s_certfile: Specify a certificate file.
@@ -212,11 +223,19 @@
%%
%% auth_method: Method used to authenticate the users.
%% The default method is the internal.
%% The default method is the internal Mnesia database storage.
%% If you want to use a different method,
%% comment this line and enable the correct ones.
%% comment those lines and enable the desired lines later.
%%
{auth_method, internal}.
{auth_method, storage}.
{auth_storage, mnesia}.
%%
%% Authentication using ODBC
%% Remember to setup a database in the next section.
%%
%%{auth_method, storage}.
%%{auth_storage, odbc}.
%%
%% Authentication using external script
@@ -225,12 +244,6 @@
%%{auth_method, external}.
%%{extauth_program, "/path/to/authentication/script"}.
%%
%% Authentication using ODBC
%% Remember to setup a database in the next section.
%%
%%{auth_method, odbc}.
%%
%% Authentication using PAM
%%
@@ -249,14 +262,14 @@
%%{ldap_encrypt, none}.
%%{ldap_encrypt, tls}.
%%
%% Port connect to LDAP servers:
%% Port to connect to on LDAP servers:
%%{ldap_port, 389}.
%%{ldap_port, 636}.
%%
%% LDAP manager:
%%{ldap_rootdn, "dc=example,dc=com"}.
%%
%% Password to LDAP manager:
%% Password of LDAP manager:
%%{ldap_password, "******"}.
%%
%% Search base of LDAP directory:
@@ -286,28 +299,38 @@
%%%. ==============
%%%' DATABASE SETUP
%% ejabberd uses by default the internal Mnesia database,
%% so you can avoid this section.
%% ejabberd by default uses the internal Mnesia database,
%% so you do not necessarily need this section.
%% This section provides configuration examples in case
%% you want to use other database backends.
%% Please consult the ejabberd Guide for details about database creation.
%% Please consult the ejabberd Guide for details on database creation.
%% Template host ODBC configuration.
%% The host specified here will be used by default for all discovered vhosts.
%% The actual ODBC server configuration must be provided in a host_config directive.
{odbc_server, {host, "localhost"}}.
{host_config, "localhost",
[
%%
%% MySQL server:
%%
%%{odbc_server, {mysql, "server", "database", "username", "password"}}.
%%{odbc_server, {mysql, "server", "database", "username", "password"}}
%%
%% If you want to specify the port:
%%{odbc_server, {mysql, "server", 1234, "database", "username", "password"}}.
%%{odbc_server, {mysql, "server", 1234, "database", "username", "password"}}
%%
%% PostgreSQL server:
%%
%%{odbc_server, {pgsql, "server", "database", "username", "password"}}.
%%{odbc_server, {pgsql, "server", "database", "username", "password"}}
%%
%% If you want to specify the port:
%%{odbc_server, {pgsql, "server", 1234, "database", "username", "password"}}.
%%{odbc_server, {pgsql, "server", 1234, "database", "username", "password"}}
%%
]
}.
%% If you use PostgreSQL, have a large database, and need a
%% faster but inexact replacement for "select count(*) from users"
%%
@@ -324,8 +347,8 @@
%%{odbc_pool_size, 10}.
%%
%% Interval to make a dummy SQL request to keep alive the connections
%% to the database. Specify in seconds: for example 28800 means 8 hours
%% Interval to make a dummy SQL request to keep the connections to the
%% database alive. Specify in seconds: for example 28800 means 8 hours
%%
%%{odbc_keepalive_interval, undefined}.
@@ -334,22 +357,28 @@
%%%' TRAFFIC SHAPERS
%%
%% The "normal" shaper limits traffic speed to 1.000 B/s
%% The "normal" shaper limits traffic speed to 1000 B/s
%%
{shaper, normal, {maxrate, 1000}}.
%%
%% The "fast" shaper limits traffic speed to 50.000 B/s
%% The "fast" shaper limits traffic speed to 50000 B/s
%%
{shaper, fast, {maxrate, 50000}}.
%%
%% This option specifies the maximum number of elements in the queue
%% of the FSM. Refer to the documentation for details.
%%
{max_fsm_queue, 1000}.
%%%. ====================
%%%' ACCESS CONTROL LISTS
%%
%% The 'admin' ACL grants administrative privileges to XMPP accounts.
%% You can put as many accounts as you want.
%% You can put here as many accounts as you want.
%%
%%{acl, admin, {user, "aleksey", "localhost"}}.
%%{acl, admin, {user, "ermine", "example.org"}}.
@@ -390,7 +419,7 @@
{access, max_user_sessions, [{10, all}]}.
%% Maximum number of offline messages that users can have:
{access, max_user_offline_messages, [{5000, admin}, {100, all}]}.
{access, max_user_offline_messages, [{5000, admin}, {100, all}]}.
%% This rule allows access only for local users:
{access, local, [{allow, local}]}.
@@ -399,41 +428,41 @@
{access, c2s, [{deny, blocked},
{allow, all}]}.
%% For C2S connections, all users except admins use "normal" shaper
%% For C2S connections, all users except admins use the "normal" shaper
{access, c2s_shaper, [{none, admin},
{normal, all}]}.
%% All S2S connections use "fast" shaper
%% All S2S connections use the "fast" shaper
{access, s2s_shaper, [{fast, all}]}.
%% Only admins can send announcement messages:
{access, announce, [{allow, admin}]}.
%% Only admins can use configuration interface:
%% Only admins can use the configuration interface:
{access, configure, [{allow, admin}]}.
%% Admins of this server are also admins of MUC service:
%% Admins of this server are also admins of the MUC service:
{access, muc_admin, [{allow, admin}]}.
%% Only accounts of the local ejabberd server can create rooms:
{access, muc_create, [{allow, local}]}.
%% All users are allowed to use MUC service:
%% All users are allowed to use the MUC service:
{access, muc, [{allow, all}]}.
%% Only accounts in the local ejabberd server can create Pubsub nodes:
%% Only accounts on the local ejabberd server can create Pubsub nodes:
{access, pubsub_createnode, [{allow, local}]}.
%% In-band registration allows registration of any possible username.
%% To disable in-band registration, replace 'allow' with 'deny'.
{access, register, [{allow, all}]}.
%% By default frequency of account registrations from the same IP
%% is limited to 1 account every 10 minutes. To disable put: infinity
%% By default the frequency of account registrations from the same IP
%% is limited to 1 account every 10 minutes. To disable, specify: infinity
%%{registration_timeout, 600}.
%%
%% Define specific Access rules in a virtual host.
%% Define specific Access Rules in a virtual host.
%%
%%{host_config, "localhost",
%% [
@@ -443,6 +472,19 @@
%%}.
%%%. =======
%%%' CAPTCHA
%%
%% Full path to a script that generates the image.
%%
%%{captcha_cmd, "/lib/ejabberd/priv/bin/captcha.sh"}.
%% Host for the URL and port where ejabberd listens for CAPTCHA requests.
%%
%%{captcha_host, "example.org:5280"}.
%%%. ================
%%%' DEFAULT LANGUAGE
@@ -459,61 +501,61 @@
%%}.
%%%. =======
%%%' CAPTCHA
%%%. ================
%%%' INSTANCE MODULES
%%
%% Full path to a script that generates the image.
%% Modules to start for every virtual host.
%%
%%{captcha_cmd, "/lib/ejabberd/priv/bin/captcha.sh"}.
%%
%% Host part of the URL sent to the user.
%%
%%{captcha_host, "example.org:5280"}.
%%%. =======
%%%' MODULES
%%
%% Modules enabled in all ejabberd virtual hosts.
%% Note: One copy of each module will be started for each host.
%%
{modules,
[
{mod_adhoc, []},
{mod_announce, [{access, announce}]}, % recommends mod_adhoc
{mod_caps, []},
{mod_caps, []}, % 1 proc/host
{mod_configure,[]}, % requires mod_adhoc
{mod_disco, []},
%%{mod_echo, [{host, "echo.localhost"}]},
{mod_irc, []},
{mod_http_bind, []},
%%{mod_http_fileserver, [
%% {docroot, "/var/www"},
%% {docroot, "/var/www"},
%% {accesslog, "/var/log/ejabberd/access.log"}
%% ]},
{mod_last, []},
{mod_muc, [
%%{host, "conference.@HOST@"},
{access, muc},
{access_create, muc_create},
{access_persistent, muc_create},
{access_admin, muc_admin}
]},
{mod_muc, [ % 1 proc/host
{host, "conference.@HOST@"},
{access, muc},
{access_create, muc_create},
{access_persistent, muc_create},
{access_admin, muc_admin}
]},
%%{mod_muc_log,[]},
%%{mod_multicast,[]},
{mod_offline, [{access_max_user_messages, max_user_offline_messages}]},
{mod_ping, []},
%%{mod_pres_counter,[{count, 5}, {interval, 60}]},
{mod_privacy, []},
{mod_private, []},
%%{mod_proxy65,[]},
{mod_pubsub, [
{access_createnode, pubsub_createnode},
{ignore_pep_from_offline, true},
{last_item_cache, false},
{plugins, ["flat", "hometree", "pep"]} % pep requires mod_caps
]},
%%{mod_pubsub, [ % 1 proc/host
%% {access_createnode, pubsub_createnode},
%% {ignore_pep_from_offline, true}, % reduces resource comsumption, but XEP incompliant
%% %%{ignore_pep_from_offline, false}, % XEP compliant, but increases resource comsumption
%% {last_item_cache, false},
%% {plugins, ["flat", "pep"]} % pep requires mod_caps
%% ]},
{mod_register, [
%%
%% Protect In-Band account registrations with CAPTCHA.
%%
%%{captcha_protected, true},
%%
%% Set the minimum informational entropy for passwords.
%%
%%{password_strength, 32},
%%
%% After successful registration, the user receives
%% a message with this subject and body.
@@ -527,17 +569,53 @@
%%
%%{registration_watchers, ["admin1@example.org"]},
%%
%% Only clients in the server machine can register accounts
%%
{ip_access, [{allow, "127.0.0.0/8"},
{deny, "0.0.0.0/0"}]},
%%
%% Local c2s or remote s2s users cannot register accounts
%%
%%{access_from, deny},
{access, register}
]},
%%{mod_register_web, [
%%
%% When a user registers, send a notification to
%% these XMPP accounts.
%%
%%{registration_watchers, ["admin1@example.org"]}
%% ]},
{mod_roster, []},
%%{mod_service_log,[]},
{mod_shared_roster,[]},
{mod_stats, []},
{mod_time, []},
{mod_vcard, []},
{mod_vcard, []}, % 1 proc/host
{mod_version, []}
]}.
%%%.
%%%' STATIC MODULES
%%
%% Modules to start for the global virtual host ("localhost").
%%
%% The functionality of these modules will be enabled in all ejabberd
%% virtual hosts without consuming more resources.
%%
{static_modules,
[
]}.
%%%.
%%%' HOST SPECIFIC MODULES
%%
%% Enable modules with custom options in a specific virtual host
%%
@@ -553,8 +631,6 @@
%%%.
%%%'
%%% $Id$
%%% Local Variables:
%%% mode: erlang
%%% End:
+36 -3
View File
@@ -5,7 +5,7 @@
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -28,8 +28,14 @@
-author('alexey@process-one.net').
-export([start/0, stop/0,
get_pid_file/0,
get_so_path/0, get_bin_path/0]).
get_so_path/0,
get_bin_path/0,
get_pid_file/0,
is_my_host/1,
normalize_host/1
]).
-include("ejabberd.hrl").
start() ->
%%ejabberd_cover:start(),
@@ -65,6 +71,33 @@ get_bin_path() ->
Path
end.
is_my_host([$* | _]) ->
false;
is_my_host(Host) ->
case ejabberd_config:get_local_option({Host, host}) of
undefined ->
WCHost = re:replace(Host, "^[^.]*\.", "*.", [{return, list}]),
case ejabberd_config:get_local_option({WCHost, host}) of
undefined ->
false;
_ ->
true
end;
_ ->
true
end.
normalize_host(global) ->
global;
normalize_host(Host) ->
WCHost = re:replace(Host, "^[^.]*\.", "*.", [{return, list}]),
case ejabberd_config:get_local_option({WCHost, host}) of
undefined ->
Host;
_ ->
WCHost
end.
%% @spec () -> false | string()
get_pid_file() ->
case os:getenv("EJABBERD_PID_PATH") of
+5 -3
View File
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -23,7 +23,8 @@
%% If the ejabberd application description isn't loaded, returns atom: undefined
-define(VERSION, element(2, application:get_key(ejabberd,vsn))).
-define(MYHOSTS, ejabberd_config:get_global_option(hosts)).
-define(IS_MY_HOST(Host), ejabberd:is_my_host(Host)).
-define(MYHOSTS, ejabberd_config:get_global_option(hosts)). %% Deprecated
-define(MYNAME, hd(ejabberd_config:get_global_option(hosts))).
-define(MYLANG, ejabberd_config:get_global_option(language)).
@@ -35,6 +36,8 @@
-define(S2STIMEOUT, 600000).
-define(PRIVACY_SUPPORT, true).
%%-define(DBGFSM, true).
%% ---------------------------------
@@ -58,4 +61,3 @@
-define(CRITICAL_MSG(Format, Args),
ejabberd_logger:critical_msg(?MODULE,?LINE,Format, Args)).
+137 -9
View File
@@ -5,7 +5,7 @@
%%% Created : 7 May 2006 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -30,14 +30,21 @@
-export([start/0, stop/0,
%% Server
status/0, reopen_log/0,
stop_kindly/2, send_service_message_all_mucs/2,
%% Erlang
update_list/0, update/1,
%% Accounts
register/3, unregister/2,
registered_users/1,
%% For debugging gen_storage
get_last_info/0,
get_last_info/2,
%% Migration jabberd1.4
import_file/1, import_dir/1,
%% Purge DB
delete_expired_messages/0, delete_old_messages/1,
%% Mnesia
set_master/1,
backup_mnesia/1, restore_mnesia/1,
dump_mnesia/1, dump_table/2, load_mnesia/1,
install_fallback_mnesia/1,
@@ -79,6 +86,11 @@ commands() ->
desc = "Reopen the log files",
module = ?MODULE, function = reopen_log,
args = [], result = {res, rescode}},
#ejabberd_commands{name = stop_kindly, tags = [server],
desc = "Inform users and rooms, wait, and stop the server",
module = ?MODULE, function = stop_kindly,
args = [{delay, integer}, {announcement, string}],
result = {res, rescode}},
#ejabberd_commands{name = get_loglevel, tags = [logs, server],
desc = "Get the current loglevel",
module = ejabberd_loglevel, function = get,
@@ -88,6 +100,17 @@ commands() ->
{leveldesc, string}
]}}},
#ejabberd_commands{name = update_list, tags = [server],
desc = "List modified modules that can be updated",
module = ?MODULE, function = update_list,
args = [],
result = {modules, {list, {module, string}}}},
#ejabberd_commands{name = update, tags = [server],
desc = "Update the given module, or use the keyword: all",
module = ?MODULE, function = update,
args = [{module, string}],
result = {res, restuple}},
#ejabberd_commands{name = register, tags = [accounts],
desc = "Register a user",
module = ?MODULE, function = register,
@@ -104,6 +127,21 @@ commands() ->
args = [{host, string}],
result = {users, {list, {username, string}}}},
#ejabberd_commands{name = gli, tags = [accounts],
desc = "Get information about last access of an account",
module = ?MODULE, function = get_last_info,
args = [],
result = {lastinfo, {tuple, [{timestamp, integer},
{status, string}
]}}},
#ejabberd_commands{name = get_last_info, tags = [accounts],
desc = "Get information about last access of an account",
module = ?MODULE, function = get_last_info,
args = [{user, string}, {host, string}],
result = {lastinfo, {tuple, [{timestamp, integer},
{status, string}
]}}},
#ejabberd_commands{name = import_file, tags = [mnesia],
desc = "Import user data from jabberd14 spool file",
module = ?MODULE, function = import_file,
@@ -135,12 +173,13 @@ commands() ->
desc = "Delete offline messages older than DAYS",
module = ?MODULE, function = delete_old_messages,
args = [{days, integer}], result = {res, rescode}},
#ejabberd_commands{name = rename_default_nodeplugin, tags = [mnesia],
desc = "Update PubSub table from ejabberd trunk SVN to 2.1.0",
module = mod_pubsub, function = rename_default_nodeplugin,
args = [], result = {res, rescode}},
#ejabberd_commands{name = set_master, tags = [mnesia],
desc = "Set master node of the clustered Mnesia tables",
longdesc = "If you provide as nodename \"self\", this "
"node will be set as its own master.",
module = ?MODULE, function = set_master,
args = [{nodename, string}], result = {res, restuple}},
#ejabberd_commands{name = mnesia_change_nodename, tags = [mnesia],
desc = "Change the erlang node name in a backup file",
module = ?MODULE, function = mnesia_change_nodename,
@@ -215,6 +254,75 @@ get_sasl_error_logger_type () ->
_ -> all
end.
%%%
%%% Stop Kindly
%%%
stop_kindly(DelaySeconds, AnnouncementText) ->
Subject = io_lib:format("Server stop in ~p seconds!", [DelaySeconds]),
WaitingDesc = io_lib:format("Waiting ~p seconds", [DelaySeconds]),
Steps = [{"Stopping ejabberd port listeners",
ejabberd_listener, stop_listeners, []},
{"Sending announcement to connected users",
mod_announce, send_announcement_to_all,
[?MYNAME, Subject, AnnouncementText]},
{"Sending service message to MUC rooms",
ejabberd_admin, send_service_message_all_mucs,
[Subject, AnnouncementText]},
{WaitingDesc, timer, sleep, [DelaySeconds * 1000]},
{"Stopping ejabberd", application, stop, [ejabberd]},
{"Stopping Mnesia", mnesia, stop, []},
{"Stopping Erlang node", init, stop, []}
],
NumberLast = length(Steps),
TimestampStart = calendar:datetime_to_gregorian_seconds({date(), time()}),
lists:foldl(
fun({Desc, Mod, Func, Args}, NumberThis) ->
SecondsDiff =
calendar:datetime_to_gregorian_seconds({date(), time()})
- TimestampStart,
io:format("[~p/~p ~ps] ~s... ",
[NumberThis, NumberLast, SecondsDiff, Desc]),
Result = apply(Mod, Func, Args),
io:format("~p~n", [Result]),
NumberThis+1
end,
1,
Steps),
ok.
send_service_message_all_mucs(Subject, AnnouncementText) ->
Message = io_lib:format("~s~n~s", [Subject, AnnouncementText]),
lists:foreach(
fun(ServerHost) ->
MUCHost = gen_mod:get_module_opt_host(
ServerHost, mod_muc, "conference.@HOST@"),
MUCHostB = list_to_binary(MUCHost),
mod_muc:broadcast_service_message(MUCHostB, Message)
end,
?MYHOSTS).
%%%
%%% ejabberd_update
%%%
update_list() ->
{ok, _Dir, UpdatedBeams, _Script, _LowLevelScript, _Check} =
ejabberd_update:update_info(),
[atom_to_list(Beam) || Beam <- UpdatedBeams].
update("all") ->
[update_module(ModStr) || ModStr <- update_list()];
update(ModStr) ->
update_module(ModStr).
update_module(ModuleNameString) ->
ModuleName = list_to_atom(ModuleNameString),
case ejabberd_update:update([ModuleName]) of
{ok, Res} -> {ok, io_lib:format("Updated: ~p", [Res])};
{error, Reason} -> {error, Reason}
end.
%%%
%%% Account management
%%%
@@ -222,7 +330,7 @@ get_sasl_error_logger_type () ->
register(User, Host, Password) ->
case ejabberd_auth:try_register(User, Host, Password) of
{atomic, ok} ->
{ok, io_lib:format("User ~s@~s succesfully registered", [User, Host])};
{ok, io_lib:format("User ~s@~s successfully registered", [User, Host])};
{atomic, exists} ->
String = io_lib:format("User ~s@~s already registered at node ~p",
[User, Host, node()]),
@@ -242,6 +350,12 @@ registered_users(Host) ->
SUsers = lists:sort(Users),
lists:map(fun({U, _S}) -> U end, SUsers).
get_last_info() -> get_last_info("badlop", "localhost").
get_last_info(User, Server) ->
case mod_last:get_last_info(User, Server) of
{ok, TimeStamp, Status} -> {TimeStamp, Status};
not_found -> {"never", ""}
end.
%%%
%%% Migration management
@@ -273,11 +387,11 @@ import_dir(Path) ->
%%%
delete_expired_messages() ->
{atomic, ok} = mod_offline:remove_expired_messages(),
mod_offline:remove_expired_messages(),
ok.
delete_old_messages(Days) ->
{atomic, _} = mod_offline:remove_old_messages(Days),
mod_offline:remove_old_messages(Days),
ok.
@@ -285,6 +399,20 @@ delete_old_messages(Days) ->
%%% Mnesia management
%%%
set_master("self") ->
set_master(node());
set_master(NodeString) when is_list(NodeString) ->
set_master(list_to_atom(NodeString));
set_master(Node) when is_atom(Node) ->
case mnesia:set_master_nodes([Node]) of
ok ->
{ok, ""};
{error, Reason} ->
String = io_lib:format("Can't set master node ~p at node ~p:~n~p",
[Node, node(), Reason]),
{error, String}
end.
backup_mnesia(Path) ->
case mnesia:backup(Path) of
ok ->
+35 -16
View File
@@ -5,7 +5,7 @@
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -42,10 +42,10 @@ start(normal, _Args) ->
ejabberd_loglevel:set(4),
write_pid_file(),
application:start(sasl),
application:start(exmpp),
randoms:start(),
db_init(),
sha:start(),
stringprep_sup:start_link(),
start(),
translate:start(),
acl:start(),
@@ -56,6 +56,8 @@ start(normal, _Args) ->
ejabberd_config:start(),
ejabberd_check:config(),
connect_nodes(),
%% Loading ASN.1 driver explicitly to avoid races in LDAP
catch asn1rt:load_driver(),
Sup = ejabberd_sup:start_link(),
ejabberd_rdbms:start(),
ejabberd_auth:start(),
@@ -64,7 +66,10 @@ start(normal, _Args) ->
%ejabberd_debug:eprof_start(),
%ejabberd_debug:fprof_start(),
maybe_add_nameservers(),
print_start_debug_info(),
start_modules(),
ejabberd_cluster:announce(),
ejabberd_node_groups:start(),
ejabberd_listener:start_listeners(),
?INFO_MSG("ejabberd ~s is started in the node ~p", [?VERSION, node()]),
Sup;
@@ -77,13 +82,15 @@ start(_, _) ->
prep_stop(State) ->
stop_modules(),
ejabberd_admin:stop(),
broadcast_c2s_shutdown(),
timer:sleep(5000),
State.
%% All the processes were killed when this function is called
stop(_State) ->
?INFO_MSG("ejabberd ~s is stopped in the node ~p", [?VERSION, node()]),
delete_pid_file(),
ejabberd_debug:stop(),
%%ejabberd_debug:stop(),
ok.
@@ -101,19 +108,7 @@ init() ->
LogPath = get_log_path(),
error_logger:add_report_handler(ejabberd_logger_h, LogPath),
erl_ddll:load_driver(ejabberd:get_so_path(), tls_drv),
case erl_ddll:load_driver(ejabberd:get_so_path(), expat_erl) of
ok -> ok;
{error, already_loaded} -> ok
end,
Port = open_port({spawn, expat_erl}, [binary]),
loop(Port).
loop(Port) ->
receive
_ ->
loop(Port)
end.
ok.
db_init() ->
case mnesia:system_info(extra_db_nodes) of
@@ -127,6 +122,15 @@ db_init() ->
%% Start all the modules in all the hosts
start_modules() ->
case ejabberd_config:get_local_option({static_modules, global}) of
undefined ->
ok;
StaticModules ->
lists:foreach(
fun({Module, Args}) ->
gen_mod:start_module(global, Module, Args)
end, StaticModules)
end,
lists:foreach(
fun(Host) ->
case ejabberd_config:get_local_option({modules, Host}) of
@@ -198,6 +202,13 @@ add_windows_nameservers() ->
lists:foreach(fun(IPT) -> inet_db:add_ns(IPT) end, IPTs).
broadcast_c2s_shutdown() ->
Children = supervisor:which_children(ejabberd_c2s_sup),
lists:foreach(
fun({_, C2SPid, _, _}) ->
C2SPid ! system_shutdown
end, Children).
%%%
%%% PID file
%%%
@@ -227,3 +238,11 @@ delete_pid_file() ->
PidFilename ->
file:delete(PidFilename)
end.
print_start_debug_info() ->
?DEBUG("Inet DB RC:~n~p", [inet_db:get_rc()]),
?DEBUG("Mnesia database:~n~p", [mnesia:system_info(all)]),
?DEBUG("Mnesia tables:~n~p",
[ [{Table, mnesia:table_info(Table, all)} ||
Table <- lists:sort(mnesia:system_info(tables))] ]),
ok.
+263 -93
View File
@@ -5,7 +5,7 @@
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -49,86 +49,149 @@
is_user_exists_in_other_modules/3,
remove_user/2,
remove_user/3,
plain_password_required/1
plain_password_required/1,
entropy/1
]).
-export([start/1
,start_module/2
,stop_module/2
,start_modules/2
,start_method/2
,stop_method/2
,start_methods/2
]).
-export([auth_modules/1]).
-include("ejabberd.hrl").
%% @type authmodule() = ejabberd_auth_anonymous | ejabberd_auth_external |
%% ejabberd_auth_ldap | ejabberd_auth_pam |
%% ejabberd_auth_storage | atom().
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
start() ->
lists:foreach(
fun(Host) ->
lists:foreach(
fun(M) ->
M:start(Host)
end, auth_modules(Host))
end, ?MYHOSTS).
plain_password_required(Server) ->
%% @spec () -> term()
start() ->
?DEBUG("About to start auth modules. Hosts: ~p", [?MYHOSTS]),
lists:foreach(fun start/1, ?MYHOSTS).
start(Host) ->
start_modules(Host, auth_modules(Host)).
start_modules(Host, Modules) when is_list(Modules) ->
lists:foreach(fun (M) -> start_module(Host, M) end, Modules).
start_module(Host, Module) when is_atom(Module) ->
Module:start(Host).
stop_module(Host, Module) when is_atom(Module) ->
Module:stop(Host).
start_methods(Host, Methods) when is_list(Methods) ->
lists:foreach(fun (M) -> start_method(Host, M) end, Methods).
start_method(Host, Method) when is_atom(Method) ->
start_module(Host, module_name(Method)).
stop_method(Host, Method) when is_atom(Method) ->
stop_module(Host, module_name(Method)).
%% @spec (Server) -> bool()
%% Server = string()
plain_password_required(Server) when is_list(Server) ->
lists:any(
fun(M) ->
M:plain_password_required()
end, auth_modules(Server)).
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Check if the user and password can login in server.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% true | false
check_password(User, Server, Password) ->
check_password(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
case check_password_with_authmodule(User, Server, Password) of
{true, _AuthModule} -> true;
false -> false
{false, _Reason} -> false
end.
%% @spec (User, Server, Password, Digest, DigestGen) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% Digest = string()
%% DigestGen = function()
%% @doc Check if the user and password can login in server.
%% @spec (User::string(), Server::string(), Password::string(),
%% Digest::string(), DigestGen::function()) ->
%% true | false
check_password(User, Server, Password, Digest, DigestGen) ->
check_password(User, Server, Password, Digest, DigestGen)
when is_list(User), is_list(Server), is_list(Password),
is_list(Digest), is_function(DigestGen) ->
case check_password_with_authmodule(User, Server, Password,
Digest, DigestGen) of
{true, _AuthModule} -> true;
false -> false
{false, _Reason} -> false
end.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% {true, AuthModule} | {false, Reason::string()}
%% where
%% AuthModule = ejabberd_auth_anonymous | ejabberd_auth_external
%% | ejabberd_auth_ldap | ejabberd_auth_pam | ejabberd_auth_storage
%% @doc Check if the user and password can login in server.
%% The user can login if at least an authentication method accepts the user
%% and the password.
%% The first authentication method that accepts the credentials is returned.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% {true, AuthModule} | false
%% where
%% AuthModule = ejabberd_auth_anonymous | ejabberd_auth_external
%% | ejabberd_auth_internal | ejabberd_auth_ldap
%% | ejabberd_auth_odbc | ejabberd_auth_pam
check_password_with_authmodule(User, Server, Password) ->
check_password_loop(auth_modules(Server), [User, Server, Password]).
check_password_with_authmodule(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
check_password_loop(auth_modules(Server), [User, Server, Password], "").
check_password_with_authmodule(User, Server, Password, Digest, DigestGen) ->
%% @spec (User, Server, Password, Digest, DigestGen) -> {true, AuthModule} | false
%% User = string()
%% Server = string()
%% Password = string() | undefined
%% Digest = string() | undefined
%% DigestGen = function()
%% AuthModule = authmodule()
%% @doc Check the password is valid and also return the authentication module that accepts it.
%% The password is 'undefined' if the client
%% authenticates using the digest method as defined in
%% XEP-0078: Non-SASL Authentication
check_password_with_authmodule(User, Server, Password, Digest, DigestGen)
when is_list(User), is_list(Server), (is_list(Password) orelse Password == 'undefined'),
is_function(DigestGen), (is_list(Digest) orelse Digest == 'undefined')->
check_password_loop(auth_modules(Server), [User, Server, Password,
Digest, DigestGen]).
Digest, DigestGen], "").
check_password_loop([], _Args) ->
false;
check_password_loop([AuthModule | AuthModules], Args) ->
check_password_loop([], _Args, LastReason) ->
{false, LastReason};
check_password_loop([AuthModule | AuthModules], Args, PreviousReason) ->
case apply(AuthModule, check_password, Args) of
true ->
{true, AuthModule};
{false, Reason} when Reason /= "" ->
check_password_loop(AuthModules, Args, Reason);
{false, ""} ->
check_password_loop(AuthModules, Args, PreviousReason);
false ->
check_password_loop(AuthModules, Args)
check_password_loop(AuthModules, Args, PreviousReason)
end.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% ok | {error, ErrorType}
%% where ErrorType = empty_password | not_allowed | invalid_jid
%% @spec (User, Server, Password) -> ok | {error, ErrorType}
%% User = string()
%% Server = string()
%% Password = string()
%% ErrorType = empty_password | not_allowed | invalid_jid
set_password(_User, _Server, "") ->
%% We do not allow empty password
{error, empty_password};
set_password(User, Server, Password) ->
set_password(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
lists:foldl(
fun(M, {error, _}) ->
M:set_password(User, Server, Password);
@@ -137,49 +200,71 @@ set_password(User, Server, Password) ->
end, {error, not_allowed}, auth_modules(Server)).
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string() | nil()
try_register(_User, _Server, "") ->
%% We do not allow empty password
{error, not_allowed};
try_register(User, Server, Password) ->
case is_user_exists(User,Server) of
{error, not_allowed};
try_register(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
case is_user_exists(User, Server) of
true ->
{atomic, exists};
false ->
case lists:member(jlib:nameprep(Server), ?MYHOSTS) of
case ?IS_MY_HOST(exmpp_stringprep:nameprep(Server)) of
true ->
Res = lists:foldl(
fun(_M, {atomic, ok} = Res) ->
Res;
(M, _) ->
M:try_register(User, Server, Password)
end, {error, not_allowed}, auth_modules(Server)),
case Res of
{atomic, ok} ->
ejabberd_hooks:run(register_user, Server,
[User, Server]),
{atomic, ok};
_ -> Res
end;
fun (_M, {atomic, ok} = Res) ->
Res;
(M, _) ->
M:try_register(User, Server, Password)
end, {error, not_allowed}, auth_modules(Server)),
trigger_register_hooks(Res, User, Server);
false ->
{error, not_allowed}
end
end.
%% Registered users list do not include anonymous users logged
trigger_register_hooks({atomic, ok} = Res, User, Server) ->
ejabberd_hooks:run(register_user, list_to_binary(Server),
[User, Server]),
Res;
trigger_register_hooks(Res, _User, _Server) ->
Res.
%% @spec () -> [{LUser, LServer}]
%% LUser = string()
%% LServer = string()
%% @doc Registered users list do not include anonymous users logged.
dirty_get_registered_users() ->
lists:flatmap(
fun(M) ->
M:dirty_get_registered_users()
end, auth_modules()).
%% Registered users list do not include anonymous users logged
get_vh_registered_users(Server) ->
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
%% @doc Registered users list do not include anonymous users logged.
get_vh_registered_users(Server) when is_list(Server) ->
lists:flatmap(
fun(M) ->
M:get_vh_registered_users(Server)
end, auth_modules(Server)).
get_vh_registered_users(Server, Opts) ->
%% @spec (Server, Opts) -> [{LUser, LServer}]
%% Server = string()
%% Opts = [{Opt, Val}]
%% Opt = atom()
%% Val = term()
%% LUser = string()
%% LServer = string()
get_vh_registered_users(Server, Opts) when is_list(Server) ->
lists:flatmap(
fun(M) ->
case erlang:function_exported(
@@ -191,7 +276,11 @@ get_vh_registered_users(Server, Opts) ->
end
end, auth_modules(Server)).
get_vh_registered_users_number(Server) ->
%% @spec (Server) -> Users_Number
%% Server = string()
%% Users_Number = integer()
get_vh_registered_users_number(Server) when is_list(Server) ->
lists:sum(
lists:map(
fun(M) ->
@@ -204,7 +293,14 @@ get_vh_registered_users_number(Server) ->
end
end, auth_modules(Server))).
get_vh_registered_users_number(Server, Opts) ->
%% @spec (Server, Opts) -> Users_Number
%% Server = string()
%% Opts = [{Opt, Val}]
%% Opt = atom()
%% Val = term()
%% Users_Number = integer()
get_vh_registered_users_number(Server, Opts) when is_list(Server) ->
lists:sum(
lists:map(
fun(M) ->
@@ -217,9 +313,13 @@ get_vh_registered_users_number(Server, Opts) ->
end
end, auth_modules(Server))).
%% @spec (User, Server) -> Password | false
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Get the password of the user.
%% @spec (User::string(), Server::string()) -> Password::string()
get_password(User, Server) ->
get_password(User, Server) when is_list(User), is_list(Server) ->
lists:foldl(
fun(M, false) ->
M:get_password(User, Server);
@@ -227,7 +327,13 @@ get_password(User, Server) ->
Password
end, false, auth_modules(Server)).
get_password_s(User, Server) ->
%% @spec (User, Server) -> Password | nil()
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Get the password of the user.
get_password_s(User, Server) when is_list(User), is_list(Server) ->
case get_password(User, Server) of
false ->
"";
@@ -235,10 +341,15 @@ get_password_s(User, Server) ->
Password
end.
%% @spec (User, Server) -> {Password, AuthModule} | {false, none}
%% User = string()
%% Server = string()
%% Password = string()
%% AuthModule = authmodule()
%% @doc Get the password of the user and the auth module.
%% @spec (User::string(), Server::string()) ->
%% {Password::string(), AuthModule::atom()} | {false, none}
get_password_with_authmodule(User, Server) ->
get_password_with_authmodule(User, Server)
when is_list(User), is_list(Server) ->
lists:foldl(
fun(M, {false, _}) ->
{M:get_password(User, Server), M};
@@ -246,18 +357,36 @@ get_password_with_authmodule(User, Server) ->
{Password, AuthModule}
end, {false, none}, auth_modules(Server)).
%% Returns true if the user exists in the DB or if an anonymous user is logged
%% under the given name
is_user_exists(User, Server) ->
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
%% @doc Returns true if the user exists in the DB or if an anonymous
%% user is logged under the given name.
is_user_exists(User, Server) when is_list(User), is_list(Server) ->
lists:any(
fun(M) ->
M:is_user_exists(User, Server)
case M:is_user_exists(User, Server) of
{error, Error} ->
?ERROR_MSG("The authentication module ~p returned an "
"error~nwhen checking user ~p in server ~p~n"
"Error message: ~p",
[M, User, Server, Error]),
false;
Else ->
Else
end
end, auth_modules(Server)).
%% Check if the user exists in all authentications module except the module
%% passed as parameter
%% @spec (Module::atom(), User, Server) -> true | false | maybe
is_user_exists_in_other_modules(Module, User, Server) ->
%% @spec (Module, User, Server) -> true | false | maybe
%% Module = authmodule()
%% User = string()
%% Server = string()
%% @doc Check if the user exists in all authentications module except
%% the module passed as parameter.
is_user_exists_in_other_modules(Module, User, Server)
when is_list(User), is_list(Server) ->
is_user_exists_in_other_modules_loop(
auth_modules(Server)--[Module],
User, Server).
@@ -278,25 +407,33 @@ is_user_exists_in_other_modules_loop([AuthModule|AuthModules], User, Server) ->
%% @spec (User, Server) -> ok | error | {error, not_allowed}
%% User = string()
%% Server = string()
%% @doc Remove user.
%% Note: it may return ok even if there was some problem removing the user.
remove_user(User, Server) ->
%% TODO: Fix me: It always return ok even if there was some problem removing the user.
%% dialyzer warning
%% ejabberd_auth.erl:388: The variable _ can never match since previous clauses completely covered the type 'ok'
remove_user(User, Server) when is_list(User), is_list(Server) ->
R = lists:foreach(
fun(M) ->
M:remove_user(User, Server)
end, auth_modules(Server)),
case R of
ok -> ejabberd_hooks:run(remove_user, jlib:nameprep(Server), [User, Server]);
_ -> none
end,
fun(M) ->
M:remove_user(User, Server)
end, auth_modules(Server)),
ejabberd_hooks:run(remove_user, list_to_binary(exmpp_stringprep:nameprep(Server)),
[list_to_binary(User), list_to_binary(Server)]),
R.
%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request | error
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Try to remove user if the provided password is correct.
%% The removal is attempted in each auth method provided:
%% when one returns 'ok' the loop stops;
%% if no method returns 'ok' then it returns the error message indicated by the last method attempted.
remove_user(User, Server, Password) ->
remove_user(User, Server, Password)
when is_list(User), is_list(Server), is_list(Password) ->
R = lists:foldl(
fun(_M, ok = Res) ->
Res;
@@ -304,17 +441,44 @@ remove_user(User, Server, Password) ->
M:remove_user(User, Server, Password)
end, error, auth_modules(Server)),
case R of
ok -> ejabberd_hooks:run(remove_user, jlib:nameprep(Server), [User, Server]);
ok -> ejabberd_hooks:run(remove_user, list_to_binary(exmpp_stringprep:nameprep(Server)),
[list_to_binary(User), list_to_binary(Server)]);
_ -> none
end,
R.
%% @spec (IOList) -> non_negative_float()
%% @doc Calculate informational entropy.
entropy(IOList) ->
case binary_to_list(iolist_to_binary(IOList)) of
"" ->
0.0;
S ->
Set = lists:foldl(
fun(C, [Digit, Printable, LowLetter, HiLetter, Other]) ->
if C >= $a, C =< $z ->
[Digit, Printable, 26, HiLetter, Other];
C >= $0, C =< $9 ->
[9, Printable, LowLetter, HiLetter, Other];
C >= $A, C =< $Z ->
[Digit, Printable, LowLetter, 26, Other];
C >= 16#21, C =< 16#7e ->
[Digit, 33, LowLetter, HiLetter, Other];
true ->
[Digit, Printable, LowLetter, HiLetter, 128]
end
end, [0, 0, 0, 0, 0], S),
length(S) * math:log(lists:sum(Set))/math:log(2)
end.
%%%----------------------------------------------------------------------
%%% Internal functions
%%%----------------------------------------------------------------------
%% Return the lists of all the auth modules actually used in the
%% configuration
%% @spec () -> [authmodule()]
%% @doc Return the lists of all the auth modules actually used in the
%% configuration.
auth_modules() ->
lists:usort(
lists:flatmap(
@@ -322,13 +486,19 @@ auth_modules() ->
auth_modules(Server)
end, ?MYHOSTS)).
%% Return the list of authenticated modules for a given host
auth_modules(Server) ->
LServer = jlib:nameprep(Server),
Method = ejabberd_config:get_local_option({auth_method, LServer}),
%% @spec (Server) -> [authmodule()]
%% Server = string()
%% @doc Return the list of authenticated modules for a given host.
auth_modules(Server) when is_list(Server) ->
LServer = exmpp_stringprep:nameprep(Server),
Method = ejabberd_config:get_local_option({auth_method, ejabberd:normalize_host(LServer)}),
Methods = if
Method == undefined -> [];
is_list(Method) -> Method;
is_atom(Method) -> [Method]
end,
[list_to_atom("ejabberd_auth_" ++ atom_to_list(M)) || M <- Methods].
[module_name(M) || M <- Methods].
module_name(Method) when is_atom(Method) ->
list_to_atom("ejabberd_auth_" ++ atom_to_list(Method)).
+175 -57
View File
@@ -5,7 +5,7 @@
%%% Created : 17 Feb 2006 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -28,6 +28,7 @@
-author('mickael.remond@process-one.net').
-export([start/1,
stop/1,
allow_anonymous/1,
is_sasl_anonymous_enabled/1,
is_login_anonymous_enabled/1,
@@ -53,33 +54,56 @@
remove_user/3,
plain_password_required/0]).
-include_lib("exmpp/include/exmpp.hrl").
-include("ejabberd.hrl").
-include("jlib.hrl").
-record(anonymous, {us, sid}).
%% Create the anonymous table if at least one virtual host has anonymous features enabled
%% Register to login / logout events
start(Host) ->
%% @spec (Host) -> ok
%% Host = string()
%% @doc Create the anonymous table if at least one virtual host has
%% anonymous features enabled.
%% Register to login / logout events.
start(Host) when is_list(Host) ->
HostB = list_to_binary(Host),
%% TODO: Check cluster mode
update_tables(),
mnesia:create_table(anonymous, [{ram_copies, [node()]},
{type, bag},
{attributes, record_info(fields, anonymous)}]),
{type, bag}, {local_content, true},
{attributes, record_info(fields, anonymous)}]),
mnesia:add_table_copy(anonymous, node(), ram_copies),
%% The hooks are needed to add / remove users from the anonymous tables
ejabberd_hooks:add(sm_register_connection_hook, Host,
ejabberd_hooks:add(sm_register_connection_hook, HostB,
?MODULE, register_connection, 100),
ejabberd_hooks:add(sm_remove_connection_hook, Host,
ejabberd_hooks:add(sm_remove_connection_hook, HostB,
?MODULE, unregister_connection, 100),
ok.
%% Return true if anonymous is allowed for host or false otherwise
allow_anonymous(Host) ->
stop(Host) when is_list(Host) ->
HostB = list_to_binary(Host),
ejabberd_hooks:delete(sm_register_connection_hook, HostB,
?MODULE, register_connection, 100),
ejabberd_hooks:delete(sm_remove_connection_hook, HostB,
?MODULE, unregister_connection, 100),
ok.
%% @spec (Host) -> bool()
%% Host = string()
%% @doc Return true if anonymous is allowed for host or false otherwise.
allow_anonymous(Host) when is_list(Host) ->
lists:member(?MODULE, ejabberd_auth:auth_modules(Host)).
%% Return true if anonymous mode is enabled and if anonymous protocol is SASL
%% anonymous protocol can be: sasl_anon|login_anon|both
is_sasl_anonymous_enabled(Host) ->
%% @spec (Host) -> bool()
%% Host = string()
%% @doc Return true if anonymous mode is enabled and if anonymous
%% protocol is SASL anonymous.
%% protocol can be: sasl_anon|login_anon|both
is_sasl_anonymous_enabled(Host) when is_list(Host) ->
case allow_anonymous(Host) of
false -> false;
false -> false;
true ->
case anonymous_protocol(Host) of
sasl_anon -> true;
@@ -88,23 +112,29 @@ is_sasl_anonymous_enabled(Host) ->
end
end.
%% Return true if anonymous login is enabled on the server
%% @spec (Host) -> bool()
%% Host = string()
%% @doc Return true if anonymous login is enabled on the server.
%% anonymous login can be use using standard authentication method (i.e. with
%% clients that do not support anonymous login)
is_login_anonymous_enabled(Host) ->
is_login_anonymous_enabled(Host) when is_list(Host) ->
case allow_anonymous(Host) of
false -> false;
true ->
case anonymous_protocol(Host) of
login_anon -> true;
both -> true;
both -> true;
_Other -> false
end
end.
%% Return the anonymous protocol to use: sasl_anon|login_anon|both
%% @spec (Host) -> sasl_anon | login_anon | both
%% Host = string()
%% @doc Return the anonymous protocol to use: sasl_anon|login_anon|both.
%% defaults to login_anon
anonymous_protocol(Host) ->
anonymous_protocol(Host) when is_list(Host) ->
case ejabberd_config:get_local_option({anonymous_protocol, Host}) of
sasl_anon -> sasl_anon;
login_anon -> login_anon;
@@ -112,18 +142,26 @@ anonymous_protocol(Host) ->
_Other -> sasl_anon
end.
%% Return true if multiple connections have been allowed in the config file
%% @spec (Host) -> bool()
%% Host = string()
%% @doc Return true if multiple connections have been allowed in the
%% config file.
%% defaults to false
allow_multiple_connections(Host) ->
case ejabberd_config:get_local_option({allow_multiple_connections, Host}) of
true -> true;
_Other -> false
end.
%% Check if user exist in the anonymus database
anonymous_user_exist(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
allow_multiple_connections(Host) when is_list(Host) ->
ejabberd_config:get_local_option({allow_multiple_connections, Host})
=:= true.
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
%% @doc Check if user exist in the anonymous database.
anonymous_user_exist(User, Server) when is_list(User), is_list(Server) ->
anonymous_user_exist(list_to_binary(User), list_to_binary(Server));
anonymous_user_exist(User, Server) when is_binary(User), is_binary(Server) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
case catch mnesia:dirty_read({anonymous, US}) of
[] ->
@@ -132,51 +170,81 @@ anonymous_user_exist(User, Server) ->
true
end.
%% Remove connection from Mnesia tables
remove_connection(SID, LUser, LServer) ->
%% @spec (SID, LUser, LServer) -> term()
%% SID = term()
%% LUser = string()
%% LServer = string()
%% @doc Remove connection from Mnesia tables.
remove_connection(SID, LUser, LServer) when is_binary(LUser), is_binary(LServer) ->
US = {LUser, LServer},
F = fun() ->
mnesia:delete_object({anonymous, US, SID})
end,
mnesia:transaction(F).
mnesia:async_dirty(F).
%% Register connection
register_connection(SID, #jid{luser = LUser, lserver = LServer}, Info) ->
AuthModule = xml:get_attr_s(auth_module, Info),
case AuthModule == ?MODULE of
true ->
%% @spec (SID, JID, Info) -> term()
%% SID = term()
%% JID = exmpp_jid:jid()
%% Info = [term()]
%% @doc Register connection.
register_connection(SID, JID, Info) when ?IS_JID(JID) ->
LUser = exmpp_jid:prep_node(JID),
LServer = exmpp_jid:prep_domain(JID),
case proplists:get_value(auth_module, Info) of
undefined ->
ok;
?MODULE ->
ejabberd_hooks:run(register_user, LServer, [LUser, LServer]),
US = {LUser, LServer},
mnesia:sync_dirty(
mnesia:async_dirty(
fun() -> mnesia:write(#anonymous{us = US, sid=SID})
end);
false ->
ok
_ ->
ok
end.
%% Remove an anonymous user from the anonymous users table
unregister_connection(SID, #jid{luser = LUser, lserver = LServer}, _) ->
%% @spec (SID, JID, Ignored) -> term()
%% SID = term()
%% JID = exmpp_jid:jid()
%% Ignored = term()
%% @doc Remove an anonymous user from the anonymous users table.
unregister_connection(SID, JID, _) when ?IS_JID(JID) ->
LUser = exmpp_jid:prep_node(JID),
LServer = exmpp_jid:prep_domain(JID),
purge_hook(anonymous_user_exist(LUser, LServer),
LUser, LServer),
remove_connection(SID, LUser, LServer).
%% Launch the hook to purge user data only for anonymous users
%% @spec (bool(), LUser, LServer) -> term()
%% LUser = string()
%% LServer = string()
%% @doc Launch the hook to purge user data only for anonymous users.
purge_hook(false, _LUser, _LServer) ->
ok;
purge_hook(true, LUser, LServer) ->
purge_hook(true, LUser, LServer) when is_binary(LUser), is_binary(LServer) ->
ejabberd_hooks:run(anonymous_purge_hook, LServer, [LUser, LServer]).
%% ---------------------------------
%% Specific anonymous auth functions
%% ---------------------------------
%% When anonymous login is enabled, check the password for permenant users
%% before allowing access
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% @doc When anonymous login is enabled, check the password for
%% permenant users before allowing access.
check_password(User, Server, Password) ->
check_password(User, Server, Password, undefined, undefined).
check_password(User, Server, _Password, _Digest, _DigestGen) ->
%% We refuse login for registered accounts (They cannot logged but
%% they however are "reserved")
case ejabberd_auth:is_user_exists_in_other_modules(?MODULE,
case ejabberd_auth:is_user_exists_in_other_modules(?MODULE,
User, Server) of
%% If user exists in other module, reject anonnymous authentication
true -> false;
@@ -185,6 +253,10 @@ check_password(User, Server, _Password, _Digest, _DigestGen) ->
false -> login(User, Server)
end.
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
login(User, Server) ->
case is_login_anonymous_enabled(Server) of
false -> false;
@@ -199,8 +271,13 @@ login(User, Server) ->
end
end.
%% When anonymous login is enabled, check that the user is permanent before
%% changing its password
%% @spec (User, Server, Password) -> ok | {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
%% @doc When anonymous login is enabled, check that the user is
%% permanent before changing its password.
set_password(User, Server, _Password) ->
case anonymous_user_exist(User, Server) of
true ->
@@ -209,22 +286,41 @@ set_password(User, Server, _Password) ->
{error, not_allowed}
end.
%% When anonymous login is enabled, check if permanent users are allowed on
%% the server:
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
%% @doc When anonymous login is enabled, check if permanent users are
%% allowed on the server:
try_register(_User, _Server, _Password) ->
{error, not_allowed}.
%% @spec () -> nil()
dirty_get_registered_users() ->
[].
get_vh_registered_users(_Server) ->
[].
%% @spec (Server) -> nil()
%% Server = string()
get_vh_registered_users(Server) ->
[{U, S} || {U, S, _R} <- ejabberd_sm:get_vh_session_list(list_to_binary(Server))].
%% @spec (User, Server) -> Password | false
%% User = string()
%% Server = string()
%% Password = nil()
%% @doc Return password of permanent user or false for anonymous users.
%% Return password of permanent user or false for anonymous users
get_password(User, Server) ->
get_password(User, Server, "").
%% @spec (User, Server, DefaultValue) -> DefaultValue | false
%% User = string()
%% Server = string()
%% DefaultValue = string()
get_password(User, Server, DefaultValue) ->
case anonymous_user_exist(User, Server) or login(User, Server) of
%% We return the default value if the user is anonymous
@@ -235,17 +331,39 @@ get_password(User, Server, DefaultValue) ->
false
end.
%% Returns true if the user exists in the DB or if an anonymous user is logged
%% under the given name
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
%% @doc Returns true if the user exists in the DB or if an anonymous
%% user is logged under the given name.
is_user_exists(User, Server) ->
anonymous_user_exist(User, Server).
%% @spec (User, Server) -> {error, not_allowed}
%% User = string()
%% Server = string()
remove_user(_User, _Server) ->
{error, not_allowed}.
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
remove_user(_User, _Server, _Password) ->
not_allowed.
%% @spec () -> bool()
plain_password_required() ->
false.
update_tables() ->
case catch mnesia:table_info(anonymous, local_content) of
false ->
mnesia:delete_table(anonymous);
_ ->
ok
end.
+300 -19
View File
@@ -5,7 +5,7 @@
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -29,12 +29,16 @@
%% External exports
-export([start/1,
stop/1,
set_password/3,
check_password/3,
check_password/5,
try_register/3,
dirty_get_registered_users/0,
get_vh_registered_users/1,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
get_vh_registered_users_number/2,
get_password/2,
get_password_s/2,
is_user_exists/2,
@@ -43,47 +47,145 @@
plain_password_required/0
]).
-include("ejabberd.hrl").
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
%% @spec (Host) -> ok
%% Host = string()
start(Host) ->
extauth:start(
Host, ejabberd_config:get_local_option({extauth_program, Host})),
ok.
case check_cache_last_options(Host) of
cache ->
ok = ejabberd_auth_storage:start(Host);
no_cache ->
ok
end.
stop(Host) ->
extauth:stop(Host),
case check_cache_last_options(Host) of
cache ->
ok = ejabberd_auth_storage:stop(Host);
no_cache ->
ok
end.
check_cache_last_options(Server) ->
%% if extauth_cache is enabled, then a mod_last module must also be enabled
case get_cache_option(Server) of
false -> no_cache;
{true, _CacheTime} ->
case get_mod_last_configured(Server) of
no_mod_last ->
?ERROR_MSG("In host ~p extauth is used, extauth_cache is enabled but "
"mod_last is not enabled.", [Server]),
no_cache;
_ -> cache
end
end.
%% @spec () -> bool()
plain_password_required() ->
true.
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
check_password(User, Server, Password) ->
extauth:check_password(User, Server, Password) andalso Password /= "".
case get_cache_option(Server) of
false -> check_password_extauth(User, Server, Password);
{true, CacheTime} -> check_password_cache(User, Server, Password, CacheTime)
end.
%% @spec (User, Server, Password, Digest, DigestGen) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% Digest = string()
%% DigestGen = function()
check_password(User, Server, Password, _Digest, _DigestGen) ->
check_password(User, Server, Password).
%% @spec (User, Server, Password) -> ok | {error, unknown_problem}
%% User = string()
%% Server = string()
%% Password = string()
set_password(User, Server, Password) ->
case extauth:set_password(User, Server, Password) of
true -> ok;
true -> set_password_storage(User, Server, Password),
ok;
_ -> {error, unknown_problem}
end.
try_register(_User, _Server, _Password) ->
{error, not_allowed}.
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
try_register(User, Server, Password) ->
case get_cache_option(Server) of
false -> try_register_extauth(User, Server, Password);
{true, _CacheTime} -> try_register_external_cache(User, Server, Password)
end.
%% @spec () -> nil()
%% @todo Write it.
%% @doc Return the list of all users handled by external.
%% TODO
%% Return the list of all users handled by external
dirty_get_registered_users() ->
[].
ejabberd_auth_storage:dirty_get_registered_users().
get_vh_registered_users(_Server) ->
[].
get_vh_registered_users(Server) ->
ejabberd_auth_storage:get_vh_registered_users(Server).
get_password(_User, _Server) ->
false.
get_vh_registered_users(Server, Data) ->
ejabberd_auth_storage:get_vh_registered_users(Server, Data).
get_password_s(_User, _Server) ->
"".
%% @spec (Server) -> nil()
%% Server = string()
get_vh_registered_users_number(Server) ->
ejabberd_auth_storage:get_vh_registered_users_number(Server).
get_vh_registered_users_number(Server, Data) ->
ejabberd_auth_storage:get_vh_registered_users_number(Server, Data).
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
%% @doc Get the user cached password, if possible.
%% The password can only be returned if cache is enabled, cached info exists and is fresh enough.
get_password(User, Server) ->
case get_cache_option(Server) of
false -> false;
{true, CacheTime} -> get_password_cache(User, Server, CacheTime)
end.
%% @spec (User, Server) -> nil()
%% User = string()
%% Server = string()
get_password_s(User, Server) ->
case get_password(User, Server) of
false -> [];
Other -> Other
end.
%% @spec (User, Server) -> true | false | {error, Error}
%% User = string()
%% Server = string()
is_user_exists(User, Server) ->
try extauth:is_user_exists(User, Server) of
Res -> Res
@@ -91,9 +193,188 @@ is_user_exists(User, Server) ->
_:Error -> {error, Error}
end.
remove_user(_User, _Server) ->
{error, not_allowed}.
%% @spec (User, Server) -> {error, not_allowed}
%% User = string()
%% Server = string()
remove_user(_User, _Server, _Password) ->
not_allowed.
remove_user(User, Server) ->
case extauth:remove_user(User, Server) of
false -> false;
true ->
case get_cache_option(Server) of
false -> false;
{true, _CacheTime} ->
ejabberd_auth_storage:remove_user(User, Server)
end
end.
%% @spec (User, Server, Password) -> not_allowed
%% User = string()
%% Server = string()
%% Password = string()
remove_user(User, Server, Password) ->
case extauth:remove_user(User, Server, Password) of
false -> false;
true ->
case get_cache_option(Server) of
false -> false;
{true, _CacheTime} ->
ejabberd_auth_storage:remove_user(User, Server, Password)
end
end.
%%%
%%% Extauth cache management
%%%
%% @spec (Host::string()) -> false | {true, CacheTime::integer()}
get_cache_option(Host) ->
case ejabberd_config:get_local_option({extauth_cache, Host}) of
CacheTime when is_integer(CacheTime) -> {true, CacheTime};
_ -> false
end.
%% @spec (User, Server, Password) -> true | false
check_password_extauth(User, Server, Password) ->
extauth:check_password(User, Server, Password) andalso Password /= "".
%% @spec (User, Server, Password) -> true | false
try_register_extauth(User, Server, Password) ->
extauth:try_register(User, Server, Password).
check_password_cache(User, Server, Password, CacheTime) ->
case get_last_access(User, Server) of
online ->
check_password_storage(User, Server, Password);
never ->
check_password_external_cache(User, Server, Password);
mod_last_required ->
?ERROR_MSG("extauth is used, extauth_cache is enabled but mod_last is not enabled in that host", []),
check_password_external_cache(User, Server, Password);
TimeStamp ->
%% If last access exists, compare last access with cache refresh time
case is_fresh_enough(TimeStamp, CacheTime) of
%% If no need to refresh, check password against Mnesia
true ->
case check_password_storage(User, Server, Password) of
%% If password valid in Mnesia, accept it
true ->
true;
%% Else (password nonvalid in Mnesia), check in extauth and cache result
false ->
check_password_external_cache(User, Server, Password)
end;
%% Else (need to refresh), check in extauth and cache result
false ->
check_password_external_cache(User, Server, Password)
end
end.
get_password_storage(User, Server) ->
ejabberd_auth_storage:get_password(User, Server).
%% @spec (User, Server, CacheTime) -> Password::string() | false
get_password_cache(User, Server, CacheTime) ->
case get_last_access(User, Server) of
online ->
get_password_storage(User, Server);
never ->
false;
mod_last_required ->
?ERROR_MSG("extauth is used, extauth_cache is enabled but mod_last is not enabled in that host", []),
false;
TimeStamp ->
case is_fresh_enough(TimeStamp, CacheTime) of
true ->
get_password_storage(User, Server);
false ->
false
end
end.
%% Check the password using extauth; if success then cache it
check_password_external_cache(User, Server, Password) ->
case check_password_extauth(User, Server, Password) of
true ->
set_password_storage(User, Server, Password), true;
false ->
false
end.
%% Try to register using extauth; if success then cache it
try_register_external_cache(User, Server, Password) ->
case try_register_extauth(User, Server, Password) of
{atomic, ok} = R ->
set_password_storage(User, Server, Password),
R;
_ -> {error, not_allowed}
end.
%% @spec (User, Server, Password) -> true | false
check_password_storage(User, Server, Password) ->
ejabberd_auth_storage:check_password(User, Server, Password).
%% @spec (User, Server, Password) -> ok | {error, invalid_jid}
set_password_storage(User, Server, Password) ->
ejabberd_auth_storage:set_password(User, Server, Password).
%% @spec (TimeLast, CacheTime) -> true | false
%% TimeLast = online | never | integer()
%% CacheTime = integer() | false
is_fresh_enough(online, _CacheTime) ->
true;
is_fresh_enough(never, _CacheTime) ->
false;
is_fresh_enough(TimeStampLast, CacheTime) ->
{MegaSecs, Secs, _MicroSecs} = now(),
Now = MegaSecs * 1000000 + Secs,
(TimeStampLast + CacheTime > Now).
%% @spec (User, Server) -> TimeStamp::integer() | online | never | mod_last_required
get_last_access(UserS, ServerS) ->
%% Code copied from mod_configure.erl
%% Code copied from web/ejabberd_web_admin.erl
%% TODO: Update time format to XEP-0202: Entity Time
User = list_to_binary(UserS),
Server = list_to_binary(ServerS),
case ejabberd_sm:get_user_resources(User, Server) of
[] ->
_US = {User, Server},
case get_last_info(User, Server) of
mod_last_required ->
mod_last_required;
not_found ->
never;
{ok, Timestamp, _Status} ->
Timestamp
end;
_ ->
online
end.
%% @spec (User, Server) -> {ok, Timestamp, Status} | not_found | mod_last_required
get_last_info(User, Server) ->
case get_mod_last_enabled(Server) of
mod_last -> mod_last:get_last_info(User, Server);
no_mod_last -> mod_last_required
end.
%% @spec (Server) -> mod_last | no_mod_last
get_mod_last_enabled(ServerB) when is_binary(ServerB)->
Server = binary_to_list(ServerB),
get_mod_last_enabled(Server);
get_mod_last_enabled(Server) ->
case gen_mod:is_loaded(Server, mod_last) of
true -> mod_last;
false -> no_mod_last
end.
get_mod_last_configured(Server) ->
case is_configured(Server, mod_last) of
true -> mod_last;
false -> no_mod_last
end.
is_configured(Host, Module) ->
lists:keymember(Module, 1, ejabberd_config:get_local_option({modules, Host})).
-382
View File
@@ -1,382 +0,0 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_auth_internal.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Purpose : Authentification via mnesia
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% 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
%%%
%%%----------------------------------------------------------------------
-module(ejabberd_auth_internal).
-author('alexey@process-one.net').
%% External exports
-export([start/1,
set_password/3,
check_password/3,
check_password/5,
try_register/3,
dirty_get_registered_users/0,
get_vh_registered_users/1,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
get_vh_registered_users_number/2,
get_password/2,
get_password_s/2,
is_user_exists/2,
remove_user/2,
remove_user/3,
plain_password_required/0
]).
-include("ejabberd.hrl").
-record(passwd, {us, password}).
-record(reg_users_counter, {vhost, count}).
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
start(Host) ->
mnesia:create_table(passwd, [{disc_copies, [node()]},
{attributes, record_info(fields, passwd)}]),
mnesia:create_table(reg_users_counter,
[{ram_copies, [node()]},
{attributes, record_info(fields, reg_users_counter)}]),
update_table(),
update_reg_users_counter_table(Host),
ok.
update_reg_users_counter_table(Server) ->
Set = get_vh_registered_users(Server),
Size = length(Set),
LServer = jlib:nameprep(Server),
set_vh_registered_users_counter(LServer, Size).
plain_password_required() ->
false.
check_password(User, Server, Password) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
case catch mnesia:dirty_read({passwd, US}) of
[#passwd{password = Password}] ->
Password /= "";
_ ->
false
end.
check_password(User, Server, Password, Digest, DigestGen) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
case catch mnesia:dirty_read({passwd, US}) of
[#passwd{password = Passwd}] ->
DigRes = if
Digest /= "" ->
Digest == DigestGen(Passwd);
true ->
false
end,
if DigRes ->
true;
true ->
(Passwd == Password) and (Password /= "")
end;
_ ->
false
end.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% ok | {error, invalid_jid}
set_password(User, Server, Password) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
if
(LUser == error) or (LServer == error) ->
{error, invalid_jid};
true ->
F = fun() ->
mnesia:write(#passwd{us = US,
password = Password})
end,
{atomic, ok} = mnesia:transaction(F),
ok
end.
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid} | {aborted, Reason}
try_register(User, Server, Password) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
if
(LUser == error) or (LServer == error) ->
{error, invalid_jid};
true ->
F = fun() ->
case mnesia:read({passwd, US}) of
[] ->
mnesia:write(#passwd{us = US,
password = Password}),
inc_vh_registered_users_counter(LServer),
ok;
[_E] ->
exists
end
end,
mnesia:transaction(F)
end.
%% Get all registered users in Mnesia
dirty_get_registered_users() ->
mnesia:dirty_all_keys(passwd).
get_vh_registered_users(Server) ->
LServer = jlib:nameprep(Server),
mnesia:dirty_select(
passwd,
[{#passwd{us = '$1', _ = '_'},
[{'==', {element, 2, '$1'}, LServer}],
['$1']}]).
get_vh_registered_users(Server, [{from, Start}, {to, End}])
when is_integer(Start) and is_integer(End) ->
get_vh_registered_users(Server, [{limit, End-Start+1}, {offset, Start}]);
get_vh_registered_users(Server, [{limit, Limit}, {offset, Offset}])
when is_integer(Limit) and is_integer(Offset) ->
case get_vh_registered_users(Server) of
[] ->
[];
Users ->
Set = lists:keysort(1, Users),
L = length(Set),
Start = if Offset < 1 -> 1;
Offset > L -> L;
true -> Offset
end,
lists:sublist(Set, Start, Limit)
end;
get_vh_registered_users(Server, [{prefix, Prefix}])
when is_list(Prefix) ->
Set = [{U,S} || {U, S} <- get_vh_registered_users(Server), lists:prefix(Prefix, U)],
lists:keysort(1, Set);
get_vh_registered_users(Server, [{prefix, Prefix}, {from, Start}, {to, End}])
when is_list(Prefix) and is_integer(Start) and is_integer(End) ->
get_vh_registered_users(Server, [{prefix, Prefix}, {limit, End-Start+1}, {offset, Start}]);
get_vh_registered_users(Server, [{prefix, Prefix}, {limit, Limit}, {offset, Offset}])
when is_list(Prefix) and is_integer(Limit) and is_integer(Offset) ->
case [{U,S} || {U, S} <- get_vh_registered_users(Server), lists:prefix(Prefix, U)] of
[] ->
[];
Users ->
Set = lists:keysort(1, Users),
L = length(Set),
Start = if Offset < 1 -> 1;
Offset > L -> L;
true -> Offset
end,
lists:sublist(Set, Start, Limit)
end;
get_vh_registered_users(Server, _) ->
get_vh_registered_users(Server).
get_vh_registered_users_number(Server) ->
LServer = jlib:nameprep(Server),
Query = mnesia:dirty_select(
reg_users_counter,
[{#reg_users_counter{vhost = LServer, count = '$1'},
[],
['$1']}]),
case Query of
[Count] ->
Count;
_ -> 0
end.
get_vh_registered_users_number(Server, [{prefix, Prefix}]) when is_list(Prefix) ->
Set = [{U, S} || {U, S} <- get_vh_registered_users(Server), lists:prefix(Prefix, U)],
length(Set);
get_vh_registered_users_number(Server, _) ->
get_vh_registered_users_number(Server).
inc_vh_registered_users_counter(LServer) ->
F = fun() ->
case mnesia:wread({reg_users_counter, LServer}) of
[C] ->
Count = C#reg_users_counter.count + 1,
C2 = C#reg_users_counter{count = Count},
mnesia:write(C2);
_ ->
mnesia:write(#reg_users_counter{vhost = LServer,
count = 1})
end
end,
mnesia:sync_dirty(F).
dec_vh_registered_users_counter(LServer) ->
F = fun() ->
case mnesia:wread({reg_users_counter, LServer}) of
[C] ->
Count = C#reg_users_counter.count - 1,
C2 = C#reg_users_counter{count = Count},
mnesia:write(C2);
_ ->
error
end
end,
mnesia:sync_dirty(F).
set_vh_registered_users_counter(LServer, Count) ->
F = fun() ->
mnesia:write(#reg_users_counter{vhost = LServer,
count = Count})
end,
mnesia:sync_dirty(F).
get_password(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
case catch mnesia:dirty_read(passwd, US) of
[#passwd{password = Password}] ->
Password;
_ ->
false
end.
get_password_s(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
case catch mnesia:dirty_read(passwd, US) of
[#passwd{password = Password}] ->
Password;
_ ->
[]
end.
%% @spec (User, Server) -> true | false | {error, Error}
is_user_exists(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
case catch mnesia:dirty_read({passwd, US}) of
[] ->
false;
[_] ->
true;
Other ->
{error, Other}
end.
%% @spec (User, Server) -> ok
%% @doc Remove user.
%% Note: it returns ok even if there was some problem removing the user.
remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
mnesia:delete({passwd, US}),
dec_vh_registered_users_counter(LServer)
end,
mnesia:transaction(F),
ok.
%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request
%% @doc Remove user if the provided password is correct.
remove_user(User, Server, Password) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
case mnesia:read({passwd, US}) of
[#passwd{password = Password}] ->
mnesia:delete({passwd, US}),
dec_vh_registered_users_counter(LServer),
ok;
[_] ->
not_allowed;
_ ->
not_exists
end
end,
case mnesia:transaction(F) of
{atomic, ok} ->
ok;
{atomic, Res} ->
Res;
_ ->
bad_request
end.
update_table() ->
Fields = record_info(fields, passwd),
case mnesia:table_info(passwd, attributes) of
Fields ->
ok;
[user, password] ->
?INFO_MSG("Converting passwd table from "
"{user, password} format", []),
Host = ?MYNAME,
{atomic, ok} = mnesia:create_table(
ejabberd_auth_internal_tmp_table,
[{disc_only_copies, [node()]},
{type, bag},
{local_content, true},
{record_name, passwd},
{attributes, record_info(fields, passwd)}]),
mnesia:transform_table(passwd, ignore, Fields),
F1 = fun() ->
mnesia:write_lock_table(ejabberd_auth_internal_tmp_table),
mnesia:foldl(
fun(#passwd{us = U} = R, _) ->
mnesia:dirty_write(
ejabberd_auth_internal_tmp_table,
R#passwd{us = {U, Host}})
end, ok, passwd)
end,
mnesia:transaction(F1),
mnesia:clear_table(passwd),
F2 = fun() ->
mnesia:write_lock_table(passwd),
mnesia:foldl(
fun(R, _) ->
mnesia:dirty_write(R)
end, ok, ejabberd_auth_internal_tmp_table)
end,
mnesia:transaction(F2),
mnesia:delete_table(ejabberd_auth_internal_tmp_table);
_ ->
?INFO_MSG("Recreating passwd table", []),
mnesia:transform_table(passwd, ignore, Fields)
end.
+209 -54
View File
@@ -5,7 +5,7 @@
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -66,13 +66,12 @@
servers,
backups,
port,
encrypt,
tls_options,
dn,
password,
base,
uids,
ufilter,
sfilter,
lfilter, %% Local filter (performed by ejabberd, not LDAP)
dn_filter,
dn_filter_attrs
@@ -95,27 +94,62 @@ handle_info(_Info, State) ->
%%% API
%%%----------------------------------------------------------------------
%% @spec (Host) -> term()
%% Host = string()
start(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
ChildSpec = {
Proc, {?MODULE, start_link, [Host]},
transient, 1000, worker, [?MODULE]
},
supervisor:start_child(ejabberd_sup, ChildSpec).
?DEBUG("Starting ~p for ~p.", [?MODULE, Host]),
case ejabberd_config:get_host_option(Host, ldap_servers) of
undefined -> check_bad_config(Host);
{host, _Host} -> ok;
_ ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
ChildSpec = {
Proc, {?MODULE, start_link, [Host]},
transient, 1000, worker, [?MODULE]
},
supervisor:start_child(ejabberd_sup, ChildSpec)
end.
check_bad_config(Host) ->
case ejabberd_config:get_local_option({ldap_servers, Host}) of
undefined ->
?ERROR_MSG("Can't start ~p for host ~p: missing ldap_servers configuration",
[?MODULE, Host]),
{error, bad_config};
_ -> ok
end.
%% @spec (Host) -> term()
%% Host = string()
stop(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
gen_server:call(Proc, stop),
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc).
case ejabberd_config:get_host_option(Host, ldap_servers) of
undefined -> ok;
{host, _Host} -> ok;
_ ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
gen_server:call(Proc, stop),
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc)
end.
%% @spec (Host) -> term()
%% Host = string()
start_link(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
gen_server:start_link({local, Proc}, ?MODULE, Host, []).
%% @hidden
terminate(_Reason, _State) ->
ok.
%% @spec (Host) -> {ok, State}
%% Host = string()
%% State = term()
init(Host) ->
State = parse_options(Host),
eldap_pool:start_link(State#state.eldap_id,
@@ -124,19 +158,26 @@ init(Host) ->
State#state.port,
State#state.dn,
State#state.password,
State#state.encrypt),
State#state.tls_options),
eldap_pool:start_link(State#state.bind_eldap_id,
State#state.servers,
State#state.backups,
State#state.port,
State#state.dn,
State#state.password,
State#state.encrypt),
State#state.tls_options),
{ok, State}.
%% @spec () -> true
plain_password_required() ->
true.
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
check_password(User, Server, Password) ->
%% In LDAP spec: empty password means anonymous authentication.
%% As ejabberd is providing other anonymous authentication mechanisms
@@ -150,16 +191,43 @@ check_password(User, Server, Password) ->
end
end.
%% @spec (User, Server, Password, Digest, DigestGen) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% Digest = string()
%% DigestGen = function()
check_password(User, Server, Password, _Digest, _DigestGen) ->
check_password(User, Server, Password).
set_password(_User, _Server, _Password) ->
{error, not_allowed}.
%% @spec (User, Server, Password) -> {error, Reason} | ok
%% User = string()
%% Server = string()
%% Password = string()
%% Reason = term()
set_password(User, Server, Password) ->
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
case find_user_dn(User, Server, State) of
false ->
{error, user_not_found};
DN ->
eldap_pool:modify_passwd(State#state.eldap_id, DN, Password)
end.
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
try_register(_User, _Server, _Password) ->
{error, not_allowed}.
%% @spec () -> [{LUser, LServer}]
%% LUser = string()
%% LServer = string()
dirty_get_registered_users() ->
Servers = ejabberd_config:get_vh_by_auth_method(ldap),
lists:flatmap(
@@ -167,22 +235,42 @@ dirty_get_registered_users() ->
get_vh_registered_users(Server)
end, Servers).
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
get_vh_registered_users(Server) ->
case catch get_vh_registered_users_ldap(Server) of
{'EXIT', _} -> [];
Result -> Result
end.
%% @spec (Server) -> Users_Number
%% Server = string()
%% Users_Number = integer()
get_vh_registered_users_number(Server) ->
length(get_vh_registered_users(Server)).
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
get_password(_User, _Server) ->
false.
%% @spec (User, Server) -> nil()
%% User = string()
%% Server = string()
get_password_s(_User, _Server) ->
"".
%% @spec (User, Server) -> true | false | {error, Error}
%% User = string()
%% Server = string()
is_user_exists(User, Server) ->
case catch is_user_exists_ldap(User, Server) of
{'EXIT', Error} ->
@@ -191,18 +279,33 @@ is_user_exists(User, Server) ->
Result
end.
%% @spec (User, Server) -> {error, not_allowed}
%% User = string()
%% Server = string()
remove_user(_User, _Server) ->
{error, not_allowed}.
%% @spec (User, Server, Password) -> not_allowed
%% User = string()
%% Server = string()
%% Password = string()
remove_user(_User, _Server, _Password) ->
not_allowed.
%%%----------------------------------------------------------------------
%%% Internal functions
%%%----------------------------------------------------------------------
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
check_password_ldap(User, Server, Password) ->
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
case find_user_dn(User, State) of
{ok, State} = get_state(Server),
case find_user_dn(User, Server, State) of
false ->
false;
DN ->
@@ -210,25 +313,44 @@ check_password_ldap(User, Server, Password) ->
ok -> true;
_ -> false
end
end.
end.
%% We need an ?MODULE server state to use for queries. This will
%% either be Server if this is a statically configured host or the
%% Server for a different host if this is a dynamically configured
%% vhost.
%% The {ldap_vhost, Server} -> Host. ejabberd config option specifies
%% which actual ?MODULE server to use for a particular Host. The value
%% of the option if it is defined or Server by default.
get_state(Server) ->
Host = case ejabberd_config:get_local_option({ldap_servers, Server}) of
{host, H} -> H;
_ -> Server
end,
eldap_utils:get_state(Host, ?MODULE).
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
get_vh_registered_users_ldap(Server) ->
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
UIDs = State#state.uids,
UIDs = eldap_utils:uids_domain_subst(Server, State#state.uids),
Eldap_ID = State#state.eldap_id,
Server = State#state.host,
SortedDNAttrs = eldap_utils:usort_attrs(State#state.dn_filter_attrs),
case eldap_filter:parse(State#state.sfilter) of
SearchFilter = build_sfilter(State, UIDs),
ResAttrs = result_attrs(State),
case eldap_filter:parse(SearchFilter) of
{ok, EldapFilter} ->
case eldap_pool:search(Eldap_ID, [{base, State#state.base},
{filter, EldapFilter},
{timeout, ?LDAP_SEARCH_TIMEOUT},
{attributes, SortedDNAttrs}]) of
{attributes, ResAttrs}]) of
#eldap_search_result{entries = Entries} ->
lists:flatmap(
fun(#eldap_entry{attributes = Attrs,
object_name = DN}) ->
case is_valid_dn(DN, Attrs, State) of
case is_valid_dn(DN, Server, Attrs, State) of
false -> [];
_ ->
case eldap_utils:find_ldap_attrs(UIDs, Attrs) of
@@ -236,9 +358,11 @@ get_vh_registered_users_ldap(Server) ->
{User, UIDFormat} ->
case eldap_utils:get_user_part(User, UIDFormat) of
{ok, U} ->
case jlib:nodeprep(U) of
error -> [];
LU -> [{LU, jlib:nameprep(Server)}]
try
[{exmpp_stringprep:nodeprep(U), exmpp_stringprep:nameprep(Server)}]
catch
_ ->
[]
end;
_ -> []
end
@@ -252,9 +376,13 @@ get_vh_registered_users_ldap(Server) ->
[]
end.
%% @spec (User, Server) -> bool()
%% User = string()
%% Server = string()
is_user_exists_ldap(User, Server) ->
{ok, State} = eldap_utils:get_state(Server, ?MODULE),
case find_user_dn(User, State) of
case find_user_dn(User, Server, State) of
false -> false;
_DN -> true
end.
@@ -268,16 +396,17 @@ handle_call(stop, _From, State) ->
handle_call(_Request, _From, State) ->
{reply, bad_request, State}.
find_user_dn(User, State) ->
DNAttrs = eldap_utils:usort_attrs(State#state.dn_filter_attrs),
case eldap_filter:parse(State#state.ufilter, [{"%u", User}]) of
find_user_dn(User, Server, State) ->
ResAttrs = result_attrs(State),
UserFilter = build_ufilter(State, Server),
case eldap_filter:parse(UserFilter, [{"%u", User}]) of
{ok, Filter} ->
case eldap_pool:search(State#state.eldap_id, [{base, State#state.base},
{filter, Filter},
{attributes, DNAttrs}]) of
{attributes, ResAttrs}]) of
#eldap_search_result{entries = [#eldap_entry{attributes = Attrs,
object_name = DN} | _]} ->
dn_filter(DN, Attrs, State);
dn_filter(DN, Server, Attrs, State);
_ ->
false
end;
@@ -286,20 +415,20 @@ find_user_dn(User, State) ->
end.
%% apply the dn filter and the local filter:
dn_filter(DN, Attrs, State) ->
dn_filter(DN, Server, Attrs, State) ->
%% Check if user is denied access by attribute value (local check)
case check_local_filter(Attrs, State) of
false -> false;
true -> is_valid_dn(DN, Attrs, State)
true -> is_valid_dn(DN, Server, Attrs, State)
end.
%% Check that the DN is valid, based on the dn filter
is_valid_dn(DN, _, #state{dn_filter = undefined}) ->
is_valid_dn(DN, _, _, #state{dn_filter = undefined}) ->
DN;
is_valid_dn(DN, Attrs, State) ->
is_valid_dn(DN, Server, Attrs, State) ->
DNAttrs = State#state.dn_filter_attrs,
UIDs = State#state.uids,
UIDs = eldap_utils:uids_domain_subst(Server, State#state.uids),
Values = [{"%s", eldap_utils:get_ldap_attr(Attr, Attrs), 1} || Attr <- DNAttrs],
SubstValues = case eldap_utils:find_ldap_attrs(UIDs, Attrs) of
"" -> Values;
@@ -311,10 +440,10 @@ is_valid_dn(DN, Attrs, State) ->
end ++ [{"%d", State#state.host}, {"%D", DN}],
case eldap_filter:parse(State#state.dn_filter, SubstValues) of
{ok, EldapFilter} ->
case eldap_pool:search(State#state.eldap_id, [
{base, State#state.base},
{filter, EldapFilter},
{attributes, ["dn"]}]) of
case eldap_pool:search(State#state.eldap_id,
[{base, State#state.base},
{filter, EldapFilter},
{attributes, ["dn"]}]) of
#eldap_search_result{entries = [_|_]} ->
DN;
_ ->
@@ -346,6 +475,30 @@ local_filter(equal, Attrs, FilterMatch) ->
local_filter(notequal, Attrs, FilterMatch) ->
not local_filter(equal, Attrs, FilterMatch).
result_attrs(#state{uids = UIDs, dn_filter_attrs = DNFilterAttrs}) ->
lists:foldl(
fun({UID}, Acc) ->
[UID | Acc];
({UID, _}, Acc) ->
[UID | Acc]
end, DNFilterAttrs, UIDs).
build_ufilter(State, VHost) ->
UIDs = eldap_utils:uids_domain_subst(VHost, State#state.uids),
SubFilter = lists:flatten(eldap_utils:generate_subfilter(UIDs)),
case State#state.ufilter of
"" -> SubFilter;
F -> "(&" ++ SubFilter ++ F ++ ")"
end.
build_sfilter(State, FormattedUIDs) ->
SubFilter = lists:flatten(eldap_utils:generate_subfilter(FormattedUIDs)),
UserFilter = case State#state.ufilter of
"" -> SubFilter;
F -> "(&" ++ SubFilter ++ F ++ ")"
end,
eldap_filter:do_sub(UserFilter, [{"%u", "*"}]).
%%%----------------------------------------------------------------------
%%% Auxiliary functions
%%%----------------------------------------------------------------------
@@ -358,6 +511,7 @@ parse_options(Host) ->
Backups -> Backups
end,
LDAPEncrypt = ejabberd_config:get_local_option({ldap_encrypt, Host}),
LDAPTLSVerify = ejabberd_config:get_local_option({ldap_tls_verify, Host}),
LDAPPort = case ejabberd_config:get_local_option({ldap_port, Host}) of
undefined -> case LDAPEncrypt of
tls -> ?LDAPS_PORT;
@@ -376,20 +530,21 @@ parse_options(Host) ->
end,
UIDs = case ejabberd_config:get_local_option({ldap_uids, Host}) of
undefined -> [{"uid", "%u"}];
UI -> eldap_utils:uids_domain_subst(Host, UI)
UI -> UI
end,
SubFilter = lists:flatten(eldap_utils:generate_subfilter(UIDs)),
UserFilter = case ejabberd_config:get_local_option({ldap_filter, Host}) of
undefined -> SubFilter;
"" -> SubFilter;
F -> "(&" ++ SubFilter ++ F ++ ")"
undefined -> "";
F -> F
end,
SearchFilter = eldap_filter:do_sub(UserFilter, [{"%u", "*"}]),
LDAPBase = ejabberd_config:get_local_option({ldap_base, Host}),
{DNFilter, DNFilterAttrs} =
case ejabberd_config:get_local_option({ldap_dn_filter, Host}) of
undefined -> {undefined, undefined};
{DNF, DNFA} -> {DNF, DNFA}
undefined ->
{undefined, []};
{DNF, undefined} ->
{DNF, []};
{DNF, DNFA} ->
{DNF, DNFA}
end,
LocalFilter = ejabberd_config:get_local_option({ldap_local_filter, Host}),
#state{host = Host,
@@ -398,13 +553,13 @@ parse_options(Host) ->
servers = LDAPServers,
backups = LDAPBackups,
port = LDAPPort,
encrypt = LDAPEncrypt,
tls_options = [{encrypt, LDAPEncrypt},
{tls_verify, LDAPTLSVerify}],
dn = RootDN,
password = Password,
base = LDAPBase,
uids = UIDs,
ufilter = UserFilter,
sfilter = SearchFilter,
lfilter = LocalFilter,
dn_filter = DNFilter,
dn_filter_attrs = DNFilterAttrs
-281
View File
@@ -1,281 +0,0 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_auth_odbc.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Purpose : Authentification via ODBC
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% 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
%%%
%%%----------------------------------------------------------------------
-module(ejabberd_auth_odbc).
-author('alexey@process-one.net').
%% External exports
-export([start/1,
set_password/3,
check_password/3,
check_password/5,
try_register/3,
dirty_get_registered_users/0,
get_vh_registered_users/1,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
get_vh_registered_users_number/2,
get_password/2,
get_password_s/2,
is_user_exists/2,
remove_user/2,
remove_user/3,
plain_password_required/0
]).
-include("ejabberd.hrl").
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
start(_Host) ->
ok.
plain_password_required() ->
false.
%% @spec (User, Server, Password) -> true | false | {error, Error}
check_password(User, Server, Password) ->
case jlib:nodeprep(User) of
error ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
try odbc_queries:get_password(LServer, Username) of
{selected, ["password"], [{Password}]} ->
Password /= ""; %% Password is correct, and not empty
{selected, ["password"], [{_Password2}]} ->
false; %% Password is not correct
{selected, ["password"], []} ->
false; %% Account does not exist
{error, _Error} ->
false %% Typical error is that table doesn't exist
catch
_:_ ->
false %% Typical error is database not accessible
end
end.
%% @spec (User, Server, Password, Digest, DigestGen) -> true | false | {error, Error}
check_password(User, Server, Password, Digest, DigestGen) ->
case jlib:nodeprep(User) of
error ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
try odbc_queries:get_password(LServer, Username) of
%% Account exists, check if password is valid
{selected, ["password"], [{Passwd}]} ->
DigRes = if
Digest /= "" ->
Digest == DigestGen(Passwd);
true ->
false
end,
if DigRes ->
true;
true ->
(Passwd == Password) and (Password /= "")
end;
{selected, ["password"], []} ->
false; %% Account does not exist
{error, _Error} ->
false %% Typical error is that table doesn't exist
catch
_:_ ->
false %% Typical error is database not accessible
end
end.
%% @spec (User::string(), Server::string(), Password::string()) ->
%% ok | {error, invalid_jid}
set_password(User, Server, Password) ->
case jlib:nodeprep(User) of
error ->
{error, invalid_jid};
LUser ->
Username = ejabberd_odbc:escape(LUser),
Pass = ejabberd_odbc:escape(Password),
LServer = jlib:nameprep(Server),
case catch odbc_queries:set_password_t(LServer, Username, Pass) of
{atomic, ok} -> ok;
Other -> {error, Other}
end
end.
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid}
try_register(User, Server, Password) ->
case jlib:nodeprep(User) of
error ->
{error, invalid_jid};
LUser ->
Username = ejabberd_odbc:escape(LUser),
Pass = ejabberd_odbc:escape(Password),
LServer = jlib:nameprep(Server),
case catch odbc_queries:add_user(LServer, Username, Pass) of
{updated, 1} ->
{atomic, ok};
_ ->
{atomic, exists}
end
end.
dirty_get_registered_users() ->
Servers = ejabberd_config:get_vh_by_auth_method(odbc),
lists:flatmap(
fun(Server) ->
get_vh_registered_users(Server)
end, Servers).
get_vh_registered_users(Server) ->
LServer = jlib:nameprep(Server),
case catch odbc_queries:list_users(LServer) of
{selected, ["username"], Res} ->
[{U, LServer} || {U} <- Res];
_ ->
[]
end.
get_vh_registered_users(Server, Opts) ->
LServer = jlib:nameprep(Server),
case catch odbc_queries:list_users(LServer, Opts) of
{selected, ["username"], Res} ->
[{U, LServer} || {U} <- Res];
_ ->
[]
end.
get_vh_registered_users_number(Server) ->
LServer = jlib:nameprep(Server),
case catch odbc_queries:users_number(LServer) of
{selected, [_], [{Res}]} ->
list_to_integer(Res);
_ ->
0
end.
get_vh_registered_users_number(Server, Opts) ->
LServer = jlib:nameprep(Server),
case catch odbc_queries:users_number(LServer, Opts) of
{selected, [_], [{Res}]} ->
list_to_integer(Res);
_Other ->
0
end.
get_password(User, Server) ->
case jlib:nodeprep(User) of
error ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
{selected, ["password"], [{Password}]} ->
Password;
_ ->
false
end
end.
get_password_s(User, Server) ->
case jlib:nodeprep(User) of
error ->
"";
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
{selected, ["password"], [{Password}]} ->
Password;
_ ->
""
end
end.
%% @spec (User, Server) -> true | false | {error, Error}
is_user_exists(User, Server) ->
case jlib:nodeprep(User) of
error ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
try odbc_queries:get_password(LServer, Username) of
{selected, ["password"], [{_Password}]} ->
true; %% Account exists
{selected, ["password"], []} ->
false; %% Account does not exist
{error, Error} ->
{error, Error} %% Typical error is that table doesn't exist
catch
_:B ->
{error, B} %% Typical error is database not accessible
end
end.
%% @spec (User, Server) -> ok | error
%% @doc Remove user.
%% Note: it may return ok even if there was some problem removing the user.
remove_user(User, Server) ->
case jlib:nodeprep(User) of
error ->
error;
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
catch odbc_queries:del_user(LServer, Username),
ok
end.
%% @spec (User, Server, Password) -> ok | error | not_exists | not_allowed
%% @doc Remove user if the provided password is correct.
remove_user(User, Server, Password) ->
case jlib:nodeprep(User) of
error ->
error;
LUser ->
Username = ejabberd_odbc:escape(LUser),
Pass = ejabberd_odbc:escape(Password),
LServer = jlib:nameprep(Server),
F = fun() ->
Result = odbc_queries:del_user_return_password(
LServer, Username, Pass),
case Result of
{selected, ["password"], [{Password}]} ->
ok;
{selected, ["password"], []} ->
not_exists;
_ ->
not_allowed
end
end,
{atomic, Result} = odbc_queries:sql_transaction(LServer, F),
Result
end.
+94 -12
View File
@@ -5,7 +5,7 @@
%%% Created : 5 Jul 2007 by Evgeniy Khramtsov <xram@jabber.ru>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -28,6 +28,7 @@
%% External exports
-export([start/1,
stop/1,
set_password/3,
check_password/3,
check_password/5,
@@ -45,6 +46,10 @@
%%====================================================================
%% API
%%====================================================================
%% @spec (Host) -> ok | term()
%% Host = string()
start(_Host) ->
case epam:start() of
{ok, _} -> ok;
@@ -52,57 +57,134 @@ start(_Host) ->
Err -> Err
end.
%% TODO: Stop epam if no other auth_pam are running.
stop(_Host) ->
ok.
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
set_password(_User, _Server, _Password) ->
{error, not_allowed}.
check_password(User, Server, Password, _Digest, _DigestGen) ->
%% @spec (User, Server, Password, Digest, DigestGen) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% Digest = string()
%% DigestGen = function()
check_password(User, Server, Password, _StreamID, _Digest) ->
check_password(User, Server, Password).
check_password(User, Host, Password) ->
Service = get_pam_service(Host),
case catch epam:authenticate(Service, User, Password) of
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
check_password(User, Server, Password) ->
Service = get_pam_service(Server),
UserInfo = case get_pam_userinfotype(Server) of
username -> User;
jid -> User++"@"++Server
end,
case catch epam:authenticate(Service, UserInfo, Password) of
true -> true;
_ -> false
end.
%% @spec (User, Server, Password) -> {error, not_allowed}
%% User = string()
%% Server = string()
%% Password = string()
try_register(_User, _Server, _Password) ->
{error, not_allowed}.
%% @spec () -> [{LUser, LServer}]
%% LUser = string()
%% LServer = string()
dirty_get_registered_users() ->
[].
get_vh_registered_users(_Host) ->
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
get_vh_registered_users(_Server) ->
[].
%% @spec (User, Server) -> Password | false
%% User = string()
%% Server = string()
%% Password = string()
get_password(_User, _Server) ->
false.
%% @spec (User, Server) -> Password | nil()
%% User = string()
%% Server = string()
%% Password = string()
get_password_s(_User, _Server) ->
"".
%% @spec (User, Server) -> true | false | {error, Error}
%% TODO: Improve this function to return an error instead of 'false' when connection to PAM failed
is_user_exists(User, Host) ->
Service = get_pam_service(Host),
case catch epam:acct_mgmt(Service, User) of
%% User = string()
%% Server = string()
%% TODO: Improve this function to return an error instead of 'false' when
%% connection to PAM failed
is_user_exists(User, Server) ->
Service = get_pam_service(Server),
UserInfo = case get_pam_userinfotype(Server) of
username -> User;
jid -> User++"@"++Server
end,
case catch epam:acct_mgmt(Service, UserInfo) of
true -> true;
_ -> false
end.
%% @spec (User, Server) -> {error, not_allowed}
%% User = string()
%% Server = string()
remove_user(_User, _Server) ->
{error, not_allowed}.
%% @spec (User, Server, Password) -> not_allowed
%% User = string()
%% Server = string()
%% Password = string()
remove_user(_User, _Server, _Password) ->
not_allowed.
%% @spec () -> bool()
plain_password_required() ->
true.
%%====================================================================
%% Internal functions
%%====================================================================
get_pam_service(Host) ->
case ejabberd_config:get_local_option({pam_service, Host}) of
%% @spec (Server) -> string()
%% Server = string()
get_pam_service(Server) ->
case ejabberd_config:get_local_option({pam_service, Server}) of
undefined -> "ejabberd";
Service -> Service
end.
get_pam_userinfotype(Host) ->
case ejabberd_config:get_local_option({pam_userinfotype, Host}) of
undefined -> username;
Type -> Type
end.
+477
View File
@@ -0,0 +1,477 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_auth_storage.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>, Stephan Maka
%%% Purpose : Authentification via gen_storage
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2011 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
%%%
%%%----------------------------------------------------------------------
%%% Database schema (version / storage / table)
%%%
%%% 2.1.x / mnesia / passwd
%%% us = {Username::string(), Host::string()}
%%% password = string()
%%%
%%% 2.1.x / odbc / users
%%% username = varchar250
%%% password = text
%%%
%%% 3.0.0-prealpha / mnesia / passwd
%%% Same as 2.1.x
%%%
%%% 3.0.0-prealpha / odbc / users
%%% Same as 2.1.x
%%%
%%% 3.0.0-alpha / mnesia / passwd
%%% user_host = {Username::string(), Host::string()}
%%% password = string()
%%%
%%% 3.0.0-alpha / odbc / passwd
%%% user = varchar150
%%% host = varchar150
%%% password = text
-module(ejabberd_auth_storage).
-author('alexey@process-one.net').
%% External exports
-export([start/1,
stop/1,
set_password/3,
check_password/3,
check_password/5,
try_register/3,
dirty_get_registered_users/0,
get_vh_registered_users/1,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
get_vh_registered_users_number/2,
get_password/2,
get_password_s/2,
is_user_exists/2,
remove_user/2,
remove_user/3,
plain_password_required/0
]).
-include("ejabberd.hrl").
-record(passwd, {user_host, password}).
-record(reg_users_counter, {vhost, count}).
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
%% @spec (Host) -> ok
%% Host = string()
start(Host) ->
Backend =
case ejabberd_config:get_local_option({auth_storage, Host}) of
undefined -> mnesia;
B -> B
end,
HostB = list_to_binary(Host),
gen_storage:create_table(Backend, HostB, passwd,
[{odbc_host, Host},
{disc_copies, [node()]},
{attributes, record_info(fields, passwd)},
{types, [{user_host, {text, text}}]}
]),
update_table(Host, Backend),
mnesia:create_table(reg_users_counter,
[{ram_copies, [node()]},
{attributes, record_info(fields, reg_users_counter)}]),
update_reg_users_counter_table(Host),
ok.
stop(_Host) ->
ok.
update_reg_users_counter_table(Server) ->
Set = get_vh_registered_users(Server),
Size = length(Set),
LServer = exmpp_jid:prep_domain(exmpp_jid:parse(Server)),
F = fun() ->
mnesia:write(#reg_users_counter{vhost = LServer,
count = Size})
end,
mnesia:sync_dirty(F).
%% @spec () -> bool()
plain_password_required() ->
false.
%% @spec (User, Server, Password) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
check_password(User, Server, Password) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
case catch gen_storage:dirty_read(LServer, {passwd, US}) of
[#passwd{password = Password}] ->
Password /= "";
_ ->
false
end.
%% @spec (User, Server, Password, Digest, DigestGen) -> bool()
%% User = string()
%% Server = string()
%% Password = string()
%% Digest = string()
%% DigestGen = function()
check_password(User, Server, Password, Digest, DigestGen) ->
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
case catch gen_storage:dirty_read(LServer, {passwd, US}) of
[#passwd{password = Passwd}] ->
DigRes = if
Digest /= "" ->
Digest == DigestGen(Passwd);
true ->
false
end,
if DigRes ->
true;
true ->
(Passwd == Password) and (Password /= "")
end;
_ ->
false
end.
%% @spec (User, Server, Password) -> ok | {error, invalid_jid}
%% User = string()
%% Server = string()
%% Password = string()
set_password(User, Server, Password) ->
LUser = (catch exmpp_stringprep:nodeprep(User)),
LServer = (catch exmpp_stringprep:nameprep(Server)),
case {LUser, LServer} of
{{stringprep, _, invalid_string, _}, _} ->
{error, invalid_jid};
{_, {stringprep, _, invalid_string, _}} ->
{error, invalid_jid};
US ->
%% TODO: why is this a transaction?
F = fun() ->
gen_storage:write(LServer,
#passwd{user_host = US,
password = Password})
end,
{atomic, ok} = gen_storage:transaction(LServer, passwd, F),
ok
end.
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid} | {aborted, Reason}
%% User = string()
%% Server = string()
%% Password = string()
try_register(User, Server, Password) ->
LUser = (catch exmpp_stringprep:nodeprep(User)),
LServer = (catch exmpp_stringprep:nameprep(Server)),
case {LUser, LServer} of
{{stringprep, _, invalid_string, _}, _} ->
{error, invalid_jid};
{_, {stringprep, _, invalid_string, _}} ->
{error, invalid_jid};
US ->
F = fun() ->
case gen_storage:read(LServer, {passwd, US}) of
[] ->
gen_storage:write(LServer,
#passwd{user_host = US,
password = Password}),
mnesia:dirty_update_counter(
reg_users_counter,
exmpp_jid:prep_domain(exmpp_jid:parse(Server)), 1),
ok;
[_E] ->
exists
end
end,
%% TODO: transaction return value?
gen_storage:transaction(LServer, passwd, F)
end.
%% @spec () -> [{LUser, LServer}]
%% LUser = string()
%% LServer = string()
%% @doc Get all registered users in Mnesia.
dirty_get_registered_users() ->
%% TODO:
exit(not_implemented).
%% @spec (Server) -> [{LUser, LServer}]
%% Server = string()
%% LUser = string()
%% LServer = string()
get_vh_registered_users(Server) ->
LServer = exmpp_stringprep:nameprep(Server),
lists:map(fun(#passwd{user_host = US}) ->
US
end,
gen_storage:dirty_select(LServer, passwd,
[{'=', user_host, {'_', LServer}}])).
%% @spec (Server, Opts) -> [{LUser, LServer}]
%% Server = string()
%% Opts = [{Opt, Val}]
%% Opt = atom()
%% Val = term()
%% LUser = string()
%% LServer = string()
%% @doc Return the registered users for the specified host.
%%
%% `Opts' can be one of the following:
%% <ul>
%% <li>`[{from, integer()}, {to, integer()}]'</li>
%% <li>`[{limit, integer()}, {offset, integer()}]'</li>
%% <li>`[{prefix, string()}]'</li>
%% <li>`[{prefix, string()}, {from, integer()}, {to, integer()}]'</li>
%% <li>`[{prefix, string()}, {limit, integer()}, {offset, integer()}]'</li>
%% </ul>
get_vh_registered_users(Server, [{from, Start}, {to, End}])
when is_integer(Start) and is_integer(End) ->
get_vh_registered_users(Server, [{limit, End-Start+1}, {offset, Start}]);
get_vh_registered_users(Server, [{limit, Limit}, {offset, Offset}])
when is_integer(Limit) and is_integer(Offset) ->
case get_vh_registered_users(Server) of
[] ->
[];
Users ->
Set = lists:keysort(1, Users),
L = length(Set),
Start = if Offset < 1 -> 1;
Offset > L -> L;
true -> Offset
end,
lists:sublist(Set, Start, Limit)
end;
get_vh_registered_users(Server, [{prefix, Prefix}])
when is_list(Prefix) ->
Set = [{U,S} || {U, S} <- get_vh_registered_users(Server), lists:prefix(Prefix, U)],
lists:keysort(1, Set);
get_vh_registered_users(Server, [{prefix, Prefix}, {from, Start}, {to, End}])
when is_list(Prefix) and is_integer(Start) and is_integer(End) ->
get_vh_registered_users(Server, [{prefix, Prefix}, {limit, End-Start+1}, {offset, Start}]);
get_vh_registered_users(Server, [{prefix, Prefix}, {limit, Limit}, {offset, Offset}])
when is_list(Prefix) and is_integer(Limit) and is_integer(Offset) ->
case [{U,S} || {U, S} <- get_vh_registered_users(Server), lists:prefix(Prefix, U)] of
[] ->
[];
Users ->
Set = lists:keysort(1, Users),
L = length(Set),
Start = if Offset < 1 -> 1;
Offset > L -> L;
true -> Offset
end,
lists:sublist(Set, Start, Limit)
end;
get_vh_registered_users(Server, _) ->
get_vh_registered_users(Server).
%% @spec (Server) -> Users_Number
%% Server = string()
%% Users_Number = integer()
get_vh_registered_users_number(Server) ->
LServer = exmpp_jid:prep_domain(exmpp_jid:parse(Server)),
Query = mnesia:dirty_select(
reg_users_counter,
[{#reg_users_counter{vhost = LServer, count = '$1'},
[],
['$1']}]),
case Query of
[Count] ->
Count;
_ -> 0
end.
%% @spec (Server, [{prefix, Prefix}]) -> Users_Number
%% Server = string()
%% Prefix = string()
%% Users_Number = integer()
get_vh_registered_users_number(Server, [{prefix, Prefix}]) when is_list(Prefix) ->
Set = [{U, S} || {U, S} <- get_vh_registered_users(Server), lists:prefix(Prefix, U)],
length(Set);
get_vh_registered_users_number(Server, _) ->
get_vh_registered_users_number(Server).
%% @spec (User, Server) -> Password | false
%% User = string()
%% Server = string()
%% Password = string()
get_password(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
case catch gen_storage:dirty_read(LServer, passwd, US) of
[#passwd{password = Password}] ->
Password;
_ ->
false
end
catch
_ ->
false
end.
%% @spec (User, Server) -> Password | nil()
%% User = string()
%% Server = string()
%% Password = string()
get_password_s(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
case catch gen_storage:dirty_read(LServer, passwd, US) of
[#passwd{password = Password}] ->
Password;
_ ->
[]
end
catch
_ ->
[]
end.
%% @spec (User, Server) -> true | false | {error, Error}
%% User = string()
%% Server = string()
is_user_exists(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
case catch gen_storage:dirty_read(LServer, {passwd, US}) of
[] ->
false;
[_] ->
true;
Other ->
{error, Other}
end
catch
_ ->
false
end.
%% @spec (User, Server) -> ok
%% User = string()
%% Server = string()
%% @doc Remove user.
%% Note: it returns ok even if there was some problem removing the user.
remove_user(User, Server) ->
try
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
gen_storage:delete(LServer, {passwd, US}),
mnesia:dirty_update_counter(reg_users_counter,
exmpp_jid:prep_domain(exmpp_jid:parse(Server)), -1)
end,
gen_storage:transaction(LServer, passwd, F),
ok
catch
_ ->
ok
end.
%% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request
%% User = string()
%% Server = string()
%% Password = string()
%% @doc Remove user if the provided password is correct.
remove_user(User, Server, Password) ->
try
LUser = exmpp_stringprep:nodeprep(User),
LServer = exmpp_stringprep:nameprep(Server),
US = {LUser, LServer},
F = fun() ->
case gen_storage:read(LServer, {passwd, US}) of
[#passwd{password = Password}] ->
gen_storage:delete(LServer, {passwd, US}),
mnesia:dirty_update_counter(reg_users_counter,
exmpp_jid:prep_domain(exmpp_jid:parse(Server)), -1),
ok;
[_] ->
not_allowed;
_ ->
not_exists
end
end,
case gen_storage:transaction(LServer, passwd, F) of
{atomic, ok} ->
ok;
{atomic, Res} ->
Res
end
catch
_ ->
bad_request
end.
update_table(Host, mnesia) ->
gen_storage_migration:migrate_mnesia(
Host, passwd,
[{passwd, [us, password],
fun({passwd, {User, _Host}, Password}) ->
#passwd{user_host = {User, Host},
password = Password}
end}]);
update_table(Host, odbc) ->
gen_storage_migration:migrate_odbc(
Host, [passwd],
[{"users", ["username", "password"],
fun(_, User, Password) ->
#passwd{user_host = {User, Host},
password = Password}
end}]).
+1123 -981
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -6,7 +6,7 @@
%%% Created : 2 Nov 2007 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
+520 -139
View File
@@ -5,7 +5,7 @@
%%% Created : 26 Apr 2008 by Evgeniy Khramtsov <xramtsov@gmail.com>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -24,6 +24,22 @@
%%%
%%%-------------------------------------------------------------------
%%% Database schema (version / storage / table)
%%%
%%% 2.1.x / mnesia / captcha
%%% id = string()
%%% pid = pid()
%%% key = string()
%%% tref = any()
%%% args = any()
%%%
%%% 3.0.0-alpha / ets / captcha
%%% id = string()
%%% pid = pid()
%%% key = string()
%%% tref = any()
%%% args = any()
-module(ejabberd_captcha).
-behaviour(gen_server).
@@ -35,32 +51,39 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-export([create_captcha/6, build_captcha_html/2, check_captcha/2,
process_reply/1, process/2, is_feature_available/0]).
-export([create_captcha/5, build_captcha_html/2, check_captcha/2,
process_reply/1, process/2, is_feature_available/0,
create_captcha_x/4, create_captcha_x/5]).
-include_lib("exmpp/include/exmpp.hrl").
-include("jlib.hrl").
-include("ejabberd.hrl").
-include("web/ejabberd_http.hrl").
-define(VFIELD(Type, Var, Value),
{xmlelement, "field", [{"type", Type}, {"var", Var}],
[{xmlelement, "value", [], [Value]}]}).
#xmlel{name = 'field',
attrs = [
#xmlattr{name = <<"type">>,
value = Type
},
#xmlattr{name = <<"var">>,
value = Var
}
],
children = [
#xmlel{name = 'value',
children = [Value]
}
]}).
-define(CAPTCHA_TEXT(Lang), translate:translate(Lang, "Enter the text you see")).
-define(CAPTCHA_TEXT(Lang), list_to_binary(translate:translate(Lang, "Enter the text you see"))).
-define(CAPTCHA_LIFETIME, 120000). % two minutes
-define(RPC_TIMEOUT, 5000).
-record(state, {}).
-record(captcha, {id, pid, key, tref, args}).
-define(T(S),
case catch mnesia:transaction(fun() -> S end) of
{atomic, Res} ->
Res;
{_, Reason} ->
?ERROR_MSG("mnesia transaction failed: ~p", [Reason]),
{error, Reason}
end).
%%====================================================================
%% API
%%====================================================================
@@ -71,47 +94,228 @@
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
create_captcha(Id, SID, From, To, Lang, Args)
when is_list(Id), is_list(Lang), is_list(SID),
is_record(From, jid), is_record(To, jid) ->
create_captcha(SID, From, To, Lang, Args)
when is_binary(Lang), is_binary(SID) ->
case create_image() of
{ok, Type, Key, Image} ->
B64Image = jlib:encode_base64(binary_to_list(Image)),
JID = jlib:jid_to_string(From),
CID = "sha1+" ++ sha:sha(Image) ++ "@bob.xmpp.org",
Data = {xmlelement, "data",
[{"xmlns", ?NS_BOB}, {"cid", CID},
{"max-age", "0"}, {"type", Type}],
[{xmlcdata, B64Image}]},
Id = randoms:get_string() ++ "-" ++ ejabberd_cluster:node_id(),
B64Image = list_to_binary(jlib:encode_base64(binary_to_list(Image))),
JID = exmpp_jid:to_list(From),
CID = list_to_binary(["sha1+", sha:sha(Image), "@bob.xmpp.org"]),
% Data = {xmlelement, "data",
% [{"xmlns", ?NS_BOB}, {"cid", CID},
% {"max-age", "0"}, {"type", Type}],
% [{xmlcdata, B64Image}]},
Data =
#xmlel{
name = 'data',
ns = ?NS_BOB,
attrs = [
#xmlattr{name = <<"cid">>,
value = CID
},
#xmlattr{name = <<"max-age">>,
value = <<"0">>
},
#xmlattr{name = <<"type">>,
value = Type
}
],
children = [#xmlcdata{cdata = B64Image}]},
% {xmlelement, "captcha", [{"xmlns", ?NS_CAPTCHA}],
% %% ?NS_DATA_FORMS is 'jabber:x:data'
% [{xmlelement, "x", [{"xmlns", "jabber:x:data"}, {"type", "form"}],
% [?VFIELD("hidden", "FORM_TYPE", {xmlcdata, ?NS_CAPTCHA}),
% ?VFIELD("hidden", "from", {xmlcdata, exmpp_jid:to_list(To)}),
% ?VFIELD("hidden", "challenge", {xmlcdata, Id}),
% ?VFIELD("hidden", "sid", {xmlcdata, SID}),
% {xmlelement, "field", [{"var", "ocr"}, {"label", ?CAPTCHA_TEXT(Lang)}],
% [{xmlelement, "media", [{"xmlns", ?NS_DATA_FORMS_MEDIA_s}],
% [{xmlelement, "uri", [{"type", Type}],
% [{xmlcdata, "cid:" ++ CID}]}]}]}]}]},
%% TODO : kael : write exmpp_captcha.erl
Captcha =
{xmlelement, "captcha", [{"xmlns", ?NS_CAPTCHA}],
[{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}],
[?VFIELD("hidden", "FORM_TYPE", {xmlcdata, ?NS_CAPTCHA}),
?VFIELD("hidden", "from", {xmlcdata, jlib:jid_to_string(To)}),
?VFIELD("hidden", "challenge", {xmlcdata, Id}),
?VFIELD("hidden", "sid", {xmlcdata, SID}),
{xmlelement, "field", [{"var", "ocr"}, {"label", ?CAPTCHA_TEXT(Lang)}],
[{xmlelement, "media", [{"xmlns", ?NS_MEDIA}],
[{xmlelement, "uri", [{"type", Type}],
[{xmlcdata, "cid:" ++ CID}]}]}]}]}]},
#xmlel{
name = 'captcha',
ns = ?NS_CAPTCHA,
children = [
#xmlel{name = 'x',
ns = ?NS_DATA_FORMS_s,
attrs = [
#xmlattr{name = <<"type">>,
value = <<"form">>
}
],
children = [
?VFIELD(<<"hidden">>, <<"FORM_TYPE">>, #xmlcdata{cdata = ?NS_CAPTCHA_b}),
?VFIELD(<<"hidden">>, <<"from">>, #xmlcdata{cdata = exmpp_jid:to_binary(To)}),
?VFIELD(<<"hidden">>, <<"challenge">>, #xmlcdata{cdata = list_to_binary(Id)}),
?VFIELD(<<"hidden">>, <<"sid">>, #xmlcdata{cdata = SID}),
#xmlel{name = 'field',
attrs = [
#xmlattr{name = <<"var">>,
value = <<"ocr">>
},
#xmlattr{name = <<"label">>,
value = ?CAPTCHA_TEXT(Lang)
}
],
children = [
#xmlel{ns = ?NS_DATA_FORMS, name = 'required'},
#xmlel{name = 'media',
ns = ?NS_DATA_FORMS_MEDIA_s,
children = [
#xmlel{name = 'uri',
attrs = [
#xmlattr{name = <<"type">>,
value = Type
}
],
children = [
#xmlcdata{cdata = list_to_binary(["cid:", CID])}
]
}
]
}
]
}
]
}
]
},
BodyString1 = translate:translate(Lang, "Your messages to ~s are being blocked. To unblock them, visit ~s"),
BodyString = io_lib:format(BodyString1, [JID, get_url(Id)]),
Body = {xmlelement, "body", [],
[{xmlcdata, BodyString}]},
OOB = {xmlelement, "x", [{"xmlns", ?NS_OOB}],
[{xmlelement, "url", [], [{xmlcdata, get_url(Id)}]}]},
Body =
#xmlel{name = 'body',
children = [
#xmlcdata{cdata = list_to_binary(BodyString)
}
]
},
OOB =
#xmlel{name = 'x',
ns = ?NS_OOBD_X_s,
children = [
#xmlel{name = 'url',
children = [
#xmlcdata{cdata = list_to_binary(get_url(Id))}
]
}
]
},
%Body = {xmlelement, "body", [],
% [{xmlcdata, BodyString}]},
%OOB = {xmlelement, "x", [{"xmlns", ?NS_OOBD_X_s}],
% [{xmlelement, "url", [], [{xmlcdata, get_url(Id)}]}]},
Tref = erlang:send_after(?CAPTCHA_LIFETIME, ?MODULE, {remove_id, Id}),
case ?T(mnesia:write(#captcha{id=Id, pid=self(), key=Key,
tref=Tref, args=Args})) of
ok ->
{ok, [Body, OOB, Captcha, Data]};
_Err ->
error
end;
ets:insert(captcha, #captcha{id=Id, pid=self(), key=Key,
tref=Tref, args=Args}),
{ok, Id, [Body, OOB, Captcha, Data]};
_Err ->
error
end.
create_captcha_x(SID, To, Lang, HeadEls) ->
create_captcha_x(SID, To, Lang, HeadEls, []).
create_captcha_x(SID, To, Lang, HeadEls, TailEls) ->
case create_image() of
{ok, Type, Key, Image} ->
Id = randoms:get_string() ++ "-" ++ ejabberd_cluster:node_id(),
B64Image = list_to_binary(jlib:encode_base64(binary_to_list(Image))),
CID = list_to_binary(["sha1+", sha:sha(Image), "@bob.xmpp.org"]),
Data =
#xmlel{
name = 'data',
ns = ?NS_BOB,
attrs = [
#xmlattr{name = <<"cid">>,
value = CID
},
#xmlattr{name = <<"max-age">>,
value = <<"0">>
},
#xmlattr{name = <<"type">>,
value = Type
}
],
children = [#xmlcdata{cdata = B64Image}]},
HelpTxt = translate:translate(
Lang,
"If you don't see the CAPTCHA image here, "
"visit the web page."),
Imageurl = list_to_binary(get_url(Id ++ "/image")),
Captcha =
#xmlel{name = 'x',
ns = ?NS_DATA_FORMS_s,
attrs = [
#xmlattr{name = <<"type">>,
value = <<"form">>
}
],
children = [
?VFIELD(<<"hidden">>, <<"FORM_TYPE">>, #xmlcdata{cdata = ?NS_CAPTCHA_b}) | HeadEls] ++ [
#xmlel{ns = ?NS_DATA_FORMS, name = 'field', attrs =
[?XMLATTR(<<"type">>, <<"fixed">>), ?XMLATTR(<<"label">>, HelpTxt)]},
?VFIELD(<<"hidden">>, <<"captchahidden">>, #xmlcdata{cdata = <<"workaround-for-psi">>}),
#xmlel{name = 'field',
attrs = [
#xmlattr{name = <<"type">>,
value = <<"text-single">>
},
#xmlattr{name = <<"label">>,
value = list_to_binary(translate:translate(Lang, "CAPTCHA web page"))
},
#xmlattr{name = <<"var">>,
value = <<"url">>
}
],
children = [
#xmlel{name = 'value',
children = [#xmlcdata{cdata = Imageurl}]
}
]},
?VFIELD(<<"hidden">>, <<"from">>, #xmlcdata{cdata = exmpp_jid:to_binary(To)}),
?VFIELD(<<"hidden">>, <<"challenge">>, #xmlcdata{cdata = list_to_binary(Id)}),
?VFIELD(<<"hidden">>, <<"sid">>, #xmlcdata{cdata = SID}),
#xmlel{name = 'field',
attrs = [
#xmlattr{name = <<"var">>,
value = <<"ocr">>
},
#xmlattr{name = <<"label">>,
value = ?CAPTCHA_TEXT(Lang)
}
],
children = [
#xmlel{ns = ?NS_DATA_FORMS, name = 'required'},
#xmlel{name = 'media',
ns = ?NS_DATA_FORMS_MEDIA_s,
children = [
#xmlel{name = 'uri',
attrs = [
#xmlattr{name = <<"type">>,
value = Type
}
],
children = [
#xmlcdata{cdata = list_to_binary(["cid:", CID])}
]
}
]
}
]
}
] ++ TailEls
},
Tref = erlang:send_after(?CAPTCHA_LIFETIME, ?MODULE, {remove_id, Id}),
ets:insert(captcha, #captcha{id=Id, key=Key, tref=Tref}),
{ok, [Captcha, Data]};
_ ->
error
end.
%% @spec (Id::string(), Lang::string()) -> {FormEl, {ImgEl, TextEl, IdEl, KeyEl}} | captcha_not_found
%% where FormEl = xmlelement()
%% ImgEl = xmlelement()
@@ -119,30 +323,106 @@ create_captcha(Id, SID, From, To, Lang, Args)
%% IdEl = xmlelement()
%% KeyEl = xmlelement()
build_captcha_html(Id, Lang) ->
case mnesia:dirty_read(captcha, Id) of
[#captcha{}] ->
ImgEl = {xmlelement, "img", [{"src", get_url(Id ++ "/image")}], []},
TextEl = {xmlcdata, ?CAPTCHA_TEXT(Lang)},
IdEl = {xmlelement, "input", [{"type", "hidden"},
{"name", "id"},
{"value", Id}], []},
KeyEl = {xmlelement, "input", [{"type", "text"},
{"name", "key"},
{"size", "10"}], []},
FormEl = {xmlelement, "form", [{"action", get_url(Id)},
{"name", "captcha"},
{"method", "POST"}],
[ImgEl,
{xmlelement, "br", [], []},
TextEl,
{xmlelement, "br", [], []},
IdEl,
KeyEl,
{xmlelement, "br", [], []},
{xmlelement, "input", [{"type", "submit"},
{"name", "enter"},
{"value", "OK"}], []}
]},
case lookup_captcha(Id) of
{ok, _} ->
%ImgEl = {xmlelement, "img", [{"src", get_url(Id ++ "/image")}], []},
ImgEl =
#xmlel{name = 'img',
attrs = [
#xmlattr{name = <<"src">>,
value = list_to_binary(get_url(Id ++ "/image"))
}
]
},
%TextEl = {xmlcdata, ?CAPTCHA_TEXT(Lang)},
TextEl = #xmlcdata{cdata = ?CAPTCHA_TEXT(Lang)},
%IdEl = {xmlelement, "input", [{"type", "hidden"},
% {"name", "id"},
% {"value", Id}], []},
IdEl =
#xmlel{name = 'input',
attrs = [
#xmlattr{name = <<"type">>,
value = <<"hidden">>
},
#xmlattr{name = <<"name">>,
value = <<"id">>
},
#xmlattr{name = <<"value">>,
value = list_to_binary(Id)
}
]
},
%KeyEl = {xmlelement, "input", [{"type", "text"},
% {"name", "key"},
% {"size", "10"}], []},
KeyEl =
#xmlel{name = 'input',
attrs = [
#xmlattr{name = <<"type">>,
value = <<"text">>
},
#xmlattr{name = <<"name">>,
value = <<"key">>
},
#xmlattr{name = <<"size">>,
value = <<"10">>
}
]
},
%FormEl = {xmlelement, "form", [{"action", get_url(Id)},
% {"name", "captcha"},
% {"method", "POST"}],
% [ImgEl,
% {xmlelement, "br", [], []},
% TextEl,
% {xmlelement, "br", [], []},
% IdEl,
% KeyEl,
% {xmlelement, "br", [], []},
% {xmlelement, "input", [{"type", "submit"},
% {"name", "enter"},
% {"value", "OK"}], []}
% ]},
FormEl =
#xmlel{name = 'form',
attrs = [
#xmlattr{name = <<"action">>,
value = list_to_binary(get_url(Id))
},
#xmlattr{name = <<"name">>,
value = <<"captcha">>
},
#xmlattr{name = <<"method">>,
value = <<"POST">>
}
],
children = [
ImgEl,
#xmlel{name = 'br'
},
TextEl,
#xmlel{name = 'br'
},
IdEl,
KeyEl,
#xmlel{name = 'br'
},
#xmlel{name = 'input',
attrs = [
#xmlattr{name = <<"type">>,
value = <<"submit">>
},
#xmlattr{name = <<"name">>,
value = <<"enter">>
},
#xmlattr{name = <<"value">>,
value = <<"OK">>
}
]
}
]
},
{FormEl, {ImgEl, TextEl, IdEl, KeyEl}};
_ ->
captcha_not_found
@@ -150,67 +430,71 @@ build_captcha_html(Id, Lang) ->
%% @spec (Id::string(), ProvidedKey::string()) -> captcha_valid | captcha_non_valid | captcha_not_found
check_captcha(Id, ProvidedKey) ->
?T(case mnesia:read(captcha, Id, write) of
[#captcha{pid=Pid, args=Args, key=StoredKey, tref=Tref}] ->
mnesia:delete({captcha, Id}),
erlang:cancel_timer(Tref),
if StoredKey == ProvidedKey ->
Pid ! {captcha_succeed, Args},
captcha_valid;
true ->
Pid ! {captcha_failed, Args},
captcha_non_valid
end;
_ ->
captcha_not_found
end).
case string:tokens(Id, "-") of
[_, NodeID] ->
case ejabberd_cluster:get_node_by_id(NodeID) of
Node when Node == node() ->
do_check_captcha(Id, ProvidedKey);
Node ->
case catch rpc:call(Node, ?MODULE, check_captcha,
[Id, ProvidedKey], ?RPC_TIMEOUT) of
{'EXIT', _} ->
captcha_not_found;
{badrpc, _} ->
captcha_not_found;
Res ->
Res
end
end;
_ ->
captcha_not_found
end.
process_reply({xmlelement, "captcha", _, _} = El) ->
case xml:get_subtag(El, "x") of
false ->
process_reply(El) ->
case exmpp_xml:get_element(El, x) of
undefined ->
{error, malformed};
Xdata ->
Fields = jlib:parse_xdata_submit(Xdata),
case {proplists:get_value("challenge", Fields),
proplists:get_value("ocr", Fields)} of
case catch {proplists:get_value("challenge", Fields),
proplists:get_value("ocr", Fields)} of
{[Id|_], [OCR|_]} ->
?T(case mnesia:read(captcha, Id, write) of
[#captcha{pid=Pid, args=Args, key=Key, tref=Tref}] ->
mnesia:delete({captcha, Id}),
erlang:cancel_timer(Tref),
if OCR == Key ->
Pid ! {captcha_succeed, Args},
ok;
true ->
Pid ! {captcha_failed, Args},
{error, bad_match}
end;
_ ->
{error, not_found}
end);
case check_captcha(Id, OCR) of
captcha_valid ->
ok;
captcha_non_valid ->
{error, bad_match};
captcha_not_found ->
{error, not_found}
end;
_ ->
{error, malformed}
end
end;
process_reply(_) ->
{error, malformed}.
end.
process(_Handlers, #request{method='GET', lang=Lang, path=[_, Id]}) ->
case build_captcha_html(Id, Lang) of
{FormEl, _} when is_tuple(FormEl) ->
{FormEl, CaptchaTuple} when is_tuple(CaptchaTuple) ->
Form =
{xmlelement, "div", [{"align", "center"}],
[FormEl]},
%{xmlelement, "div", [{"align", "center"}],
%[FormEl]},
#xmlel{name = 'div',
attrs = [
#xmlattr{name = <<"align">>,
value = <<"center">>
}
],
children = [FormEl]
},
ejabberd_web:make_xhtml([Form]);
captcha_not_found ->
ejabberd_web:error(not_found)
end;
process(_Handlers, #request{method='GET', path=[_, Id, "image"]}) ->
case mnesia:dirty_read(captcha, Id) of
[#captcha{key=Key}] ->
case lookup_captcha(Id) of
{ok, #captcha{key=Key}} ->
case create_image(Key) of
{ok, Type, _, Img} ->
{200,
@@ -230,10 +514,15 @@ process(_Handlers, #request{method='POST', q=Q, lang=Lang, path=[_, Id]}) ->
case check_captcha(Id, ProvidedKey) of
captcha_valid ->
Form =
{xmlelement, "p", [],
[{xmlcdata,
translate:translate(Lang, "The captcha is valid.")
}]},
%{xmlelement, "p", [],
% [{xmlcdata,
% translate:translate(Lang, "The captcha is valid.")
% }]},
#xmlel{name = 'p',
children = [
#xmlcdata{cdata = list_to_binary(translate:translate(Lang, "The captcha is valid."))}
]
},
ejabberd_web:make_xhtml([Form]);
captcha_non_valid ->
ejabberd_web:error(not_allowed);
@@ -244,15 +533,12 @@ process(_Handlers, #request{method='POST', q=Q, lang=Lang, path=[_, Id]}) ->
process(_Handlers, _Request) ->
ejabberd_web:error(not_found).
%%====================================================================
%% gen_server callbacks
%%====================================================================
init([]) ->
mnesia:create_table(captcha,
[{ram_copies, [node()]},
{attributes, record_info(fields, captcha)}]),
mnesia:add_table_copy(captcha, node(), ram_copies),
mnesia:delete_table(captcha),
ets:new(captcha, [named_table, public, {keypos, #captcha.id}]),
check_captcha_setup(),
{ok, #state{}}.
@@ -264,13 +550,17 @@ handle_cast(_Msg, State) ->
handle_info({remove_id, Id}, State) ->
?DEBUG("captcha ~p timed out", [Id]),
_ = ?T(case mnesia:read(captcha, Id, write) of
[#captcha{args=Args, pid=Pid}] ->
Pid ! {captcha_failed, Args},
mnesia:delete({captcha, Id});
_ ->
ok
end),
case ets:lookup(captcha, Id) of
[#captcha{args=Args, pid=Pid}] ->
if is_pid(Pid) ->
Pid ! {captcha_failed, Args};
true ->
ok
end,
ets:delete(captcha, Id);
_ ->
ok
end,
{noreply, State};
handle_info(_Info, State) ->
@@ -288,7 +578,7 @@ code_change(_OldVsn, State, _Extra) ->
%%--------------------------------------------------------------------
%% Function: create_image() -> {ok, Type, Key, Image} | {error, Reason}
%% Type = "image/png" | "image/jpeg" | "image/gif"
%% Key = string()
%% Key = binary()
%% Image = binary()
%% Reason = atom()
%%--------------------------------------------------------------------
@@ -302,11 +592,11 @@ create_image(Key) ->
Cmd = lists:flatten(io_lib:format("~s ~s", [FileName, Key])),
case cmd(Cmd) of
{ok, <<16#89, $P, $N, $G, $\r, $\n, 16#1a, $\n, _/binary>> = Img} ->
{ok, "image/png", Key, Img};
{ok, <<"image/png">>, Key, Img};
{ok, <<16#ff, 16#d8, _/binary>> = Img} ->
{ok, "image/jpeg", Key, Img};
{ok, <<"image/jpeg">>, Key, Img};
{ok, <<$G, $I, $F, $8, X, $a, _/binary>> = Img} when X==$7; X==$9 ->
{ok, "image/gif", Key, Img};
{ok, <<"image/gif">>, Key, Img};
{error, enodata = Reason} ->
?ERROR_MSG("Failed to process output from \"~s\". "
"Maybe ImageMagick's Convert program is not installed.",
@@ -328,17 +618,59 @@ get_prog_name() ->
FileName when is_list(FileName) ->
FileName;
_ ->
""
?DEBUG("The option captcha_cmd is not configured, but some "
"module wants to use the CAPTCHA feature.", []),
throw({error, option_not_configured_captcha_cmd})
end.
%% @doc (Str::string()) -> string()
get_url(Str) ->
case ejabberd_config:get_local_option(captcha_host) of
Host when is_list(Host) ->
"http://" ++ Host ++ "/captcha/" ++ Str;
CaptchaHost = ejabberd_config:get_local_option(captcha_host),
case string:tokens(CaptchaHost, ":") of
[TransferProt, Host, PortString] ->
TransferProt ++ ":" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str;
[Host, PortString] ->
TransferProt = atom_to_list(get_transfer_protocol(PortString)),
TransferProt ++ "://" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str;
_ ->
"http://" ++ ?MYNAME ++ "/captcha/" ++ Str
"http://" ++ ?MYNAME ++ ":5280/captcha/" ++ Str
end.
get_transfer_protocol(PortString) ->
PortNumber = list_to_integer(PortString),
PortListeners = get_port_listeners(PortNumber),
get_captcha_transfer_protocol(PortListeners).
get_port_listeners(PortNumber) ->
AllListeners = ejabberd_config:get_local_option(listen),
lists:filter(
fun({{Port, _Ip, _Netp}, _Module1, _Opts1}) when Port == PortNumber ->
true;
(_) ->
false
end,
AllListeners).
get_captcha_transfer_protocol([]) ->
throw("The port number mentioned in captcha_host is not "
"a ejabberd_http listener with 'captcha' option. "
"Change the port number or specify http:// in that option.");
get_captcha_transfer_protocol([{{_Port, _Ip, tcp}, ejabberd_http, Opts}
| Listeners]) ->
case lists:member(captcha, Opts) of
true ->
case lists:member(tls, Opts) of
true ->
https;
false ->
http
end;
false ->
get_captcha_transfer_protocol(Listeners)
end;
get_captcha_transfer_protocol([_ | Listeners]) ->
get_captcha_transfer_protocol(Listeners).
%%--------------------------------------------------------------------
%% Function: cmd(Cmd) -> Data | {error, Reason}
%% Cmd = string()
@@ -388,9 +720,10 @@ return(Port, TRef, Result) ->
Result.
is_feature_enabled() ->
case get_prog_name() of
"" -> false;
try get_prog_name() of
Prog when is_list(Prog) -> true
catch
_:_ -> false
end.
is_feature_available() ->
@@ -411,3 +744,51 @@ check_captcha_setup() ->
false ->
ok
end.
lookup_captcha(Id) ->
case string:tokens(Id, "-") of
[_, NodeID] ->
case ejabberd_cluster:get_node_by_id(NodeID) of
Node when Node == node() ->
case ets:lookup(captcha, Id) of
[C] ->
{ok, C};
_ ->
{error, enoent}
end;
Node ->
case catch rpc:call(Node, ets, lookup,
[captcha, Id], ?RPC_TIMEOUT) of
[C] ->
{ok, C};
_ ->
{error, enoent}
end
end;
_ ->
{error, enoent}
end.
do_check_captcha(Id, ProvidedKey) ->
case ets:lookup(captcha, Id) of
[#captcha{pid = Pid, args = Args, key = ValidKey, tref = Tref}] ->
ets:delete(captcha, Id),
erlang:cancel_timer(Tref),
if ValidKey == ProvidedKey ->
if is_pid(Pid) ->
Pid ! {captcha_succeed, Args};
true ->
ok
end,
captcha_valid;
true ->
if is_pid(Pid) ->
Pid ! {captcha_failed, Args};
true ->
ok
end,
captcha_non_valid
end;
_ ->
captcha_not_found
end.
+5 -3
View File
@@ -5,7 +5,7 @@
%%% Created : 27 Feb 2008 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -46,6 +46,8 @@ config() ->
check_database_modules() ->
[check_database_module(M)||M<-get_db_used()].
check_database_module(host) ->
ok;
check_database_module(odbc) ->
check_modules(odbc, [odbc, odbc_app, odbc_sup, ejabberd_odbc, ejabberd_odbc_sup, odbc_queries]);
check_database_module(mysql) ->
@@ -86,8 +88,8 @@ get_db_used() ->
DBs = lists:foldr(
fun([Domain, DB], Acc) ->
case check_odbc_option(
ejabberd_config:get_local_option(
{auth_method, Domain})) of
ejabberd_config:get_local_option
({auth_method, Domain})) of
true -> [get_db_type(DB)|Acc];
_ -> Acc
end
+177
View File
@@ -0,0 +1,177 @@
%%%-------------------------------------------------------------------
%%% File : ejabberd_cluster.erl
%%% Author : Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%% Description :
%%%
%%% Created : 2 Apr 2010 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%%-------------------------------------------------------------------
-module(ejabberd_cluster).
-behaviour(gen_server).
%% API
-export([start_link/0, get_node/1, get_node_new/1, announce/0,
node_id/0, get_node_by_id/1, get_nodes/0, rehash_timeout/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-define(HASHTBL, nodes_hash).
-define(HASHTBL_NEW, nodes_hash_new).
-define(POINTS, 16).
-define(REHASH_TIMEOUT, 5000).
-record(state, {}).
%%====================================================================
%% API
%%====================================================================
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
get_node(Key) ->
Hash = erlang:phash2(Key),
get_node_by_hash(?HASHTBL, Hash).
get_node_new(Key) ->
Hash = erlang:phash2(Key),
get_node_by_hash(?HASHTBL_NEW, Hash).
get_nodes() ->
%% TODO
mnesia:system_info(running_db_nodes).
announce() ->
gen_server:call(?MODULE, announce, infinity).
node_id() ->
integer_to_list(erlang:phash2(node())).
rehash_timeout() ->
?REHASH_TIMEOUT.
get_node_by_id(NodeID) when is_list(NodeID) ->
case catch list_to_existing_atom(NodeID) of
{'EXIT', _} ->
node();
Res ->
get_node_by_id(Res)
end;
get_node_by_id(NodeID) ->
case global:whereis_name(NodeID) of
Pid when is_pid(Pid) ->
node(Pid);
_ ->
node()
end.
%%====================================================================
%% gen_server callbacks
%%====================================================================
init([]) ->
net_kernel:monitor_nodes(true, [{node_type, visible}]),
ets:new(?HASHTBL, [named_table, public, ordered_set]),
ets:new(?HASHTBL_NEW, [named_table, public, ordered_set]),
register_node(),
AllNodes = mnesia:system_info(running_db_nodes),
OtherNodes = case AllNodes of
[_] ->
AllNodes;
_ ->
AllNodes -- [node()]
end,
append_nodes(?HASHTBL, OtherNodes),
append_nodes(?HASHTBL_NEW, AllNodes),
{ok, #state{}}.
handle_call(announce, _From, State) ->
case mnesia:system_info(running_db_nodes) of
[_MyNode] ->
ok;
Nodes ->
OtherNodes = Nodes -- [node()],
lists:foreach(
fun(Node) ->
{?MODULE, Node} ! {node_ready, node()}
end, OtherNodes),
?INFO_MSG("waiting for migration from nodes: ~w",
[OtherNodes]),
timer:sleep(?REHASH_TIMEOUT),
append_node(?HASHTBL, node())
end,
{reply, ok, State};
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info({node_ready, Node}, State) ->
?INFO_MSG("node ~p is ready, starting migration", [Node]),
append_node(?HASHTBL_NEW, Node),
ejabberd_hooks:run(node_hash_update, [?REHASH_TIMEOUT]),
timer:sleep(?REHASH_TIMEOUT),
?INFO_MSG("adding node ~p to hash", [Node]),
append_node(?HASHTBL, Node),
{noreply, State};
handle_info({nodedown, Node, _}, State) ->
?INFO_MSG("node ~p goes down", [Node]),
delete_node(?HASHTBL, Node),
delete_node(?HASHTBL_NEW, Node),
{noreply, State};
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
append_nodes(Tab, Nodes) ->
lists:foreach(
fun(Node) ->
append_node(Tab, Node)
end, Nodes).
append_node(Tab, Node) ->
lists:foreach(
fun(I) ->
Hash = erlang:phash2({I, Node}),
ets:insert(Tab, {Hash, Node})
end, lists:seq(1, ?POINTS)).
delete_node(Tab, Node) ->
lists:foreach(
fun(I) ->
Hash = erlang:phash2({I, Node}),
ets:delete(Tab, Hash)
end, lists:seq(1, ?POINTS)).
get_node_by_hash(Tab, Hash) ->
NodeHash = case ets:next(Tab, Hash) of
'$end_of_table' ->
ets:first(Tab);
NH ->
NH
end,
if NodeHash == '$end_of_table' ->
erlang:error(no_running_nodes);
true ->
case ets:lookup(Tab, NodeHash) of
[] ->
get_node_by_hash(Tab, Hash);
[{_, Node}] ->
Node
end
end.
register_node() ->
global:register_name(list_to_atom(node_id()), self()).
+9 -7
View File
@@ -5,7 +5,7 @@
%%% Created : 20 May 2008 by Badlop <badlop@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -356,15 +356,14 @@ get_tags_commands() ->
%% @doc Check access is allowed to that command.
%% At least one AccessCommand must be satisfied.
%% It may throw {error, Error} where:
%% Error = account_unprivileged | invalid_account_data | no_auth_provided
%% Error = account_unprivileged | invalid_account_data
check_access_commands([], _Auth, _Method, _Command, _Arguments) ->
ok;
check_access_commands(AccessCommands, Auth, Method, Command, Arguments) ->
{ok, User, Server} = check_auth(Auth),
AccessCommandsAllowed =
lists:filter(
fun({Access, Commands, ArgumentRestrictions}) ->
case check_access(Access, User, Server) of
case check_access(Access, Auth) of
true ->
check_access_command(Commands, Command, ArgumentRestrictions,
Method, Arguments);
@@ -379,7 +378,7 @@ check_access_commands(AccessCommands, Auth, Method, Command, Arguments) ->
end.
check_auth(noauth) ->
throw({error, no_auth_provided});
no_auth_provided;
check_auth({User, Server, Password}) ->
%% Check the account exists and password is valid
AccountPass = ejabberd_auth:get_password_s(User, Server),
@@ -394,9 +393,12 @@ get_md5(AccountPass) ->
lists:flatten([io_lib:format("~.16B", [X])
|| X <- binary_to_list(crypto:md5(AccountPass))]).
check_access(Access, User, Server) ->
check_access(all, _) ->
true;
check_access(Access, Auth) ->
{ok, User, Server} = check_auth(Auth),
%% Check this user has access permission
case acl:match_rule(Server, Access, jlib:make_jid(User, Server, "")) of
case acl:match_rule(Server, Access, exmpp_jid:make(User, Server, "")) of
allow -> true;
deny -> false
end.
+1 -1
View File
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
+253 -22
View File
@@ -5,7 +5,7 @@
%%% Created : 14 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -27,16 +27,32 @@
-module(ejabberd_config).
-author('alexey@process-one.net').
-export([start/0, load_file/1,
-export([start/0, load_file/1, get_host_option/2,
add_global_option/2, add_local_option/2,
mne_add_local_option/2, mne_del_local_option/1,
del_global_option/1, del_local_option/1,
get_global_option/1, get_local_option/1]).
-export([for_host/1
,configure_host/2
,delete_host/1
]).
-export([search/1]).
-export([get_vh_by_auth_method/1]).
-export([is_file_readable/1]).
-include("ejabberd.hrl").
-include("ejabberd_config.hrl").
-include_lib("kernel/include/file.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-record(state, {opts = [],
hosts = [],
override_local = false,
override_global = false,
override_acls = false}).
%% @type macro() = {macro_key(), macro_value()}
@@ -101,15 +117,14 @@ get_plain_terms_file(File1) ->
case file:consult(File) of
{ok, Terms} ->
include_config_files(Terms);
{error, {_LineNumber, erl_parse, _ParseMessage} = Reason} ->
ExitText = lists:flatten(File ++ " approximately in the line "
++ file:format_error(Reason)),
?ERROR_MSG("Problem loading ejabberd config file ~n~s", [ExitText]),
exit(ExitText);
{error, {LineNumber, erl_parse, _ParseMessage} = Reason} ->
ExitText = describe_config_problem(File, Reason, LineNumber),
?ERROR_MSG(ExitText, []),
exit_or_halt(ExitText);
{error, Reason} ->
ExitText = lists:flatten(File ++ ": " ++ file:format_error(Reason)),
?ERROR_MSG("Problem loading ejabberd config file ~n~s", [ExitText]),
exit(ExitText)
ExitText = describe_config_problem(File, Reason),
?ERROR_MSG(ExitText, []),
exit_or_halt(ExitText)
end.
%% @doc Convert configuration filename to absolute path.
@@ -152,7 +167,16 @@ search_hosts(Term, State) ->
end.
add_hosts_to_option(Hosts, State) ->
PrepHosts = normalize_hosts(Hosts),
PrepHosts1 = normalize_hosts(Hosts),
PrepHosts = ensure_localhost_is_first(PrepHosts1),
mnesia:transaction(
fun() ->
lists:foreach(
fun(H) ->
mnesia:write(#local_config{key = {H, host},
value = []})
end, PrepHosts)
end),
add_option(hosts, PrepHosts, State#state{hosts = PrepHosts}).
normalize_hosts(Hosts) ->
@@ -160,15 +184,89 @@ normalize_hosts(Hosts) ->
normalize_hosts([], PrepHosts) ->
lists:reverse(PrepHosts);
normalize_hosts([Host|Hosts], PrepHosts) ->
case jlib:nodeprep(Host) of
error ->
try
PrepHost = exmpp_stringprep:nodeprep(Host),
normalize_hosts(Hosts, [PrepHost|PrepHosts])
catch
_ ->
?ERROR_MSG("Can't load config file: "
"invalid host name [~p]", [Host]),
exit("invalid hostname");
PrepHost ->
normalize_hosts(Hosts, [PrepHost|PrepHosts])
exit("invalid hostname")
end.
%% @spec (Hosts::[string()]) -> [Localhost::string() | [string()]]
%% @doc Return the list where the first is surely "localhost".
ensure_localhost_is_first(Hosts) ->
case lists:all(fun is_list/1, Hosts) of
true ->
ensure_localhost_is_first1(Hosts);
false ->
?ERROR_MSG("This list of hosts is bad formed:~n~p", [Hosts]),
ensure_localhost_is_first1([])
end.
ensure_localhost_is_first1(["localhost" | _] = Hosts) ->
Hosts;
ensure_localhost_is_first1(Hosts) ->
case lists:member("localhost", Hosts) of
true ->
["localhost" | lists:delete("localhost", Hosts)];
false ->
?INFO_MSG("ejabberd added the default virtual host \"localhost\""
" to the list of hosts.", []),
["localhost" | Hosts]
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Errors reading the config file
describe_config_problem(Filename, Reason) ->
Text1 = lists:flatten("Problem loading ejabberd config file " ++ Filename),
Text2 = lists:flatten(" : " ++ file:format_error(Reason)),
ExitText = Text1 ++ Text2,
ExitText.
describe_config_problem(Filename, Reason, LineNumber) ->
Text1 = lists:flatten("Problem loading ejabberd config file " ++ Filename),
Text2 = lists:flatten(" approximately in the line "
++ file:format_error(Reason)),
ExitText = Text1 ++ Text2,
Lines = get_config_lines(Filename, LineNumber, 10, 3),
?ERROR_MSG("The following lines from your configuration file might be"
" relevant to the error: ~n~s", [Lines]),
ExitText.
get_config_lines(Filename, TargetNumber, PreContext, PostContext) ->
{ok, Fd} = file:open(Filename, [read]),
LNumbers = lists:seq(TargetNumber-PreContext, TargetNumber+PostContext),
NextL = io:get_line(Fd, no_prompt),
R = get_config_lines2(Fd, NextL, 1, LNumbers, []),
file:close(Fd),
R.
get_config_lines2(_Fd, eof, _CurrLine, _LNumbers, R) ->
lists:reverse(R);
get_config_lines2(_Fd, _NewLine, _CurrLine, [], R) ->
lists:reverse(R);
get_config_lines2(Fd, Data, CurrLine, [NextWanted | LNumbers], R) when is_list(Data) ->
NextL = io:get_line(Fd, no_prompt),
if
CurrLine >= NextWanted ->
Line2 = [integer_to_list(CurrLine), ": " | Data],
get_config_lines2(Fd, NextL, CurrLine+1, LNumbers, [Line2 | R]);
true ->
get_config_lines2(Fd, NextL, CurrLine+1, [NextWanted | LNumbers], R)
end.
%% If ejabberd isn't yet running in this node, then halt the node
exit_or_halt(ExitText) ->
case [Vsn || {ejabberd, _Desc, Vsn} <- application:which_applications()] of
[] ->
timer:sleep(1000),
halt(ExitText);
[_] ->
exit(ExitText)
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Support for 'include_config_file'
@@ -327,6 +425,8 @@ process_term(Term, State) ->
{host_config, Host, Terms} ->
lists:foldl(fun(T, S) -> process_host_term(T, Host, S) end,
State, Terms);
{clusterid, ClusterID} ->
add_option(clusterid, ClusterID, State);
{listen, Listeners} ->
Listeners2 =
lists:map(
@@ -343,6 +443,8 @@ process_term(Term, State) ->
add_option(outgoing_s2s_port, Port, State);
{outgoing_s2s_options, Methods, Timeout} ->
add_option(outgoing_s2s_options, {Methods, Timeout}, State);
{outgoing_s2s_local_address, Addr} ->
add_option(outgoing_s2s_local_address, Addr, State);
{s2s_dns_options, PropList} ->
add_option(s2s_dns_options, PropList, State);
{s2s_use_starttls, Port} ->
@@ -377,20 +479,19 @@ process_term(Term, State) ->
add_option(watchdog_large_heap, LH, State);
{registration_timeout, Timeout} ->
add_option(registration_timeout, Timeout, State);
{ejabberdctl_access_commands, ACs} ->
add_option(ejabberdctl_access_commands, ACs, State);
{captcha_cmd, Cmd} ->
add_option(captcha_cmd, Cmd, State);
{captcha_host, Host} ->
add_option(captcha_host, Host, State);
{ejabberdctl_access_commands, ACs} ->
add_option(ejabberdctl_access_commands, ACs, State);
{loglevel, Loglevel} ->
ejabberd_loglevel:set(Loglevel),
State;
{max_fsm_queue, N} ->
add_option(max_fsm_queue, N, State);
{_Opt, _Val} ->
lists:foldl(fun(Host, S) -> process_host_term(Term, Host, S) end,
State, State#state.hosts)
process_host_term(Term, global, State)
end.
process_host_term(Term, Host, State) ->
@@ -412,6 +513,15 @@ process_host_term(Term, Host, State) ->
State;
{odbc_server, ODBC_server} ->
add_option({odbc_server, Host}, ODBC_server, State);
{auth_method, Methods} ->
{Methods2, StorageOption} = replace_storage_auth(Host, Methods),
State2 = case StorageOption of
{auth_storage, Storage} ->
add_option({auth_storage, Host}, Storage, State);
undefined ->
State
end,
add_option({auth_method, Host}, Methods2, State2);
{Opt, Val} ->
add_option({Opt, Host}, Val, State)
end.
@@ -515,20 +625,47 @@ add_global_option(Opt, Val) ->
end).
add_local_option(Opt, Val) ->
mnesia:transaction(fun mne_add_local_option/2, [Opt, Val]).
mne_add_local_option(Opt, Val) ->
mnesia:write(#local_config{key = Opt,
value = Val}).
del_global_option(Opt) ->
mnesia:transaction(fun() ->
mnesia:write(#local_config{key = Opt,
value = Val})
mnesia:delete({config, Opt})
end).
del_local_option(Opt) ->
mnesia:transaction(fun() ->
mnesia:delete({local_config, Opt})
end).
get_global_option({Opt1, Host} = Opt) when is_list(Host) ->
case ets:lookup(config, Opt) of
[#config{value = Val}] ->
Val;
_ ->
get_global_option({Opt1, global})
end;
get_global_option(Opt) ->
case ets:lookup(config, Opt) of
[#config{value = Val}] when Opt == hosts ->
ensure_localhost_is_first(Val);
[#config{value = Val}] ->
Val;
_ ->
undefined
end.
get_local_option({Opt1, Host} = Opt) when is_list(Host) ->
case ets:lookup(local_config, Opt) of
[#local_config{value = Val}] ->
Val;
_ ->
get_local_option({Opt1, global})
end;
get_local_option(Opt) ->
case ets:lookup(local_config, Opt) of
[#local_config{value = Val}] ->
@@ -537,6 +674,17 @@ get_local_option(Opt) ->
undefined
end.
get_host_option(Host, Option) ->
case ets:lookup(local_config, {Option, Host}) of
[#local_config{value=V}] -> V;
_ -> undefined
end.
mne_del_local_option({_OptName, Host} = Opt) when is_list(Host) ->
mnesia:delete({local_config, Opt});
mne_del_local_option({Host, host} = Opt) when is_list(Host) ->
mnesia:delete({local_config, Opt}).
%% Return the list of hosts handled by a given module
get_vh_by_auth_method(AuthMethod) ->
mnesia:dirty_select(local_config,
@@ -555,3 +703,86 @@ is_file_readable(Path) ->
{error, _Reason} ->
false
end.
search(Pattern) ->
{atomic, Res} = mnesia:transaction(fun mnesia:select/2, [local_config, Pattern]),
Res.
for_host(Host) ->
mnesia:read({local_config, {Host, host}})
++ mnesia:select(local_config,
ets:fun2ms(fun (#local_config{key={_, H}})
when H =:= Host ->
object()
end))
++ acl:for_host(Host).
delete_host(Host) ->
mnesia_delete_objects(for_host(Host)),
ok.
configure_host(Host, Config) ->
HostExistenceTerm = {{Host, host}, []},
Records = host_terms_to_records(Host, [HostExistenceTerm | Config]),
mnesia_write_objects(Records),
ok.
host_terms_to_records(Host, Terms) ->
lists:foldl(fun (Term, Acc) ->
host_term_to_record(Term, Host, Acc)
end, [], Terms).
host_term_to_record({acl, ACLName, ACLData}, Host, Acc) ->
[acl:to_record(Host, ACLName, ACLData) | Acc];
host_term_to_record({access, RuleName, Rules}, Host, Acc) ->
[#config{key={access, RuleName, Host}, value=Rules} | Acc];
host_term_to_record({shaper, Name, Data}, Host, Acc) ->
[#config{key={shaper, Name, Host}, value=Data} | Acc];
host_term_to_record({host, _}, _Host, Acc) -> Acc;
host_term_to_record({hosts, _}, _Host, Acc) -> Acc;
host_term_to_record({{Host, host}, []}, Host, Acc) ->
[#local_config{key={Host, host}, value=[]} | Acc];
host_term_to_record({Opt, Val}, Host, Acc) when is_atom(Opt) ->
[#local_config{key={Opt, Host}, value=Val} | Acc].
mnesia_delete_objects(List) when is_list(List) ->
true = lists:all(fun (I) ->
ok =:= mnesia:delete_object(I)
end, List).
mnesia_write_objects(List) when is_list(List) ->
true = lists:all(fun (I) ->
ok =:= mnesia:write(I)
end, List).
%% Replace internal and odbc auth_methods with storage.
%% Only one storage type can be used, either internal or odbc.
replace_storage_auth(Host, Val) when not is_list(Val) ->
replace_storage_auth(Host, [Val]);
replace_storage_auth(Host, Val) ->
replace_storage_auth(Host, Val, [], undefined).
replace_storage_auth(_Host, [], Val2, Storage) ->
{lists:reverse(Val2), Storage};
replace_storage_auth(Host, [internal = Val | ValT], Val2, undefined) ->
Storage = {auth_storage, mnesia},
?WARNING_MSG("The auth method '~p' is deprecated.~nReplace it with 'storage'"
" and also add this option: ~n~p.", [Val, Storage]),
replace_storage_auth(Host, ValT, [storage | Val2], Storage);
replace_storage_auth(Host, [odbc = Val | ValT], Val2, undefined) ->
Storage = {auth_storage, odbc},
?WARNING_MSG("The auth method '~p' is deprecated.~nReplace it with 'storage'"
" and also add this option: ~n~p.", [Val, Storage]),
replace_storage_auth(Host, ValT, [storage | Val2], Storage);
replace_storage_auth(Host, [Val | ValT], Val2, Storage)
when (Val /= internal) and (Val /= odbc) ->
replace_storage_auth(Host, ValT, [Val | Val2], Storage);
replace_storage_auth(Host, [Val | _ValT], _Val2, Storage) ->
?CRITICAL_MSG("The auth method '~p' conflicts with~n~p in the host \"~p\"."
"~nOnly one of them can be used in each host.",
[Val, Storage, Host]),
throw({unacceptable_auth_conflict, Host, Val, Storage}).
+1 -6
View File
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -21,8 +21,3 @@
-record(config, {key, value}).
-record(local_config, {key, value}).
-record(state, {opts = [],
hosts = [],
override_local = false,
override_global = false,
override_acls = false}).
+53 -47
View File
@@ -5,7 +5,7 @@
%%% Created : 11 Jan 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -189,16 +189,20 @@ process(["help" | Mode]) ->
["help"] ->
print_usage_help(MaxC, ShCode),
?STATUS_SUCCESS;
[CommandString | _] ->
print_usage_commands(CommandString, MaxC, ShCode),
[CmdString | _] ->
CmdStringU = re:replace(CmdString, "-", "_", [global, {return, list}]),
print_usage_commands(CmdStringU, MaxC, ShCode),
?STATUS_SUCCESS
end;
process(Args) ->
AccessCommands = get_accesscommands(),
{String, Code} = process2(Args, AccessCommands),
io:format(String),
io:format("\n"),
case String of
[] -> ok;
_ ->
io:format("~s~n", [String])
end,
Code.
%% @spec (Args::[string()], AccessCommands) -> {String::string(), Code::integer()}
@@ -263,10 +267,8 @@ try_run_ctp(Args, Auth, AccessCommands) ->
%% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()}
try_call_command(Args, Auth, AccessCommands) ->
try call_command(Args, Auth, AccessCommands) of
{error, command_unknown} ->
{io_lib:format("Error: command ~p not known.", [hd(Args)]), ?STATUS_ERROR};
{error, wrong_number_parameters} ->
{"Error: wrong number of parameters", ?STATUS_ERROR};
{error, String} ->
{String, ?STATUS_ERROR};
Res ->
Res
catch
@@ -275,13 +277,13 @@ try_call_command(Args, Auth, AccessCommands) ->
{io_lib:format("Problem '~p ~p' occurred executing the command.~nStacktrace: ~p", [A, Why, Stack]), ?STATUS_ERROR}
end.
%% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()} | {error, ErrorType}
%% @spec (Args::[string()], Auth, AccessCommands) -> string() | integer() | {string(), integer()} | {error, string()}
call_command([CmdString | Args], Auth, AccessCommands) ->
{ok, CmdStringU, _} = regexp:gsub(CmdString, "-", "_"),
CmdStringU = re:replace(CmdString, "-", "_", [global,{return,list}]),
Command = list_to_atom(CmdStringU),
case ejabberd_commands:get_command_format(Command) of
{error, command_unknown} ->
{error, command_unknown};
{error, io_lib:format("Error: command ~p not known.", [CmdString])};
{ArgsFormat, ResultFormat} ->
case (catch format_args(Args, ArgsFormat)) of
ArgsFormatted when is_list(ArgsFormatted) ->
@@ -294,9 +296,8 @@ call_command([CmdString | Args], Auth, AccessCommands) ->
{L1, L2} when L1 < L2 -> {L2-L1, "less argument"};
{L1, L2} when L1 > L2 -> {L1-L2, "more argument"}
end,
{io_lib:format("Error: the command ~p requires ~p ~s.",
[CmdString, NumCompa, TextCompa]),
wrong_command_arguments}
{error, io_lib:format("Error: the command ~p requires ~p ~s.",
[CmdString, NumCompa, TextCompa])}
end
end.
@@ -314,18 +315,19 @@ format_args(Args, ArgsFormat) ->
[],
lists:zip(ArgsFormat, Args)).
format_arg(Arg, Format) ->
Parse = case Format of
integer ->
"~d";
string ->
NumChars = integer_to_list(string:len(Arg)),
"~" ++ NumChars ++ "c"
end,
format_arg(Arg, integer) ->
format_arg2(Arg, "~d");
format_arg("", string) ->
"";
format_arg(Arg, string) ->
NumChars = integer_to_list(string:len(Arg)),
Parse = "~" ++ NumChars ++ "c",
format_arg2(Arg, Parse).
format_arg2(Arg, Parse)->
{ok, [Arg2], _RemainingArguments} = io_lib:fread(Parse, Arg),
Arg2.
%%-----------------------------
%% Format result
%%-----------------------------
@@ -436,8 +438,7 @@ print_usage() ->
print_usage(dual, MaxC, ShCode).
print_usage(HelpMode, MaxC, ShCode) ->
AllCommands =
[
{"status", [], "Get ejabberd status"},
[{"status", [], "Get ejabberd status"},
{"stop", [], "Stop ejabberd"},
{"restart", [], "Restart ejabberd"},
{"help", ["[--tags [tag] | com?*]"], "Show help (try: ejabberdctl help help)"},
@@ -609,26 +610,26 @@ print_usage_tags(Tag, MaxC, ShCode) ->
print_usage_help(MaxC, ShCode) ->
LongDesc =
["The special 'help' ejabberdctl command provides help of ejabberd commands.\n\n"
"The format is:\n ", ?B("ejabberdctl"), " ", ?B("help"), " [", ?B("--tags"), " ", ?U("[tag]"), " | ", ?U("com?*"), "]\n\n"
"The special 'help' ejabberdctl command provides help of ejabberd commands.\n\n"
"The format is:\n "++?B("ejabberdctl")++" "++?B("help")++" ["++?B("--tags")++" "++?U("[tag]")++" | "++?U("com?*")++"]\n\n"
"The optional arguments:\n"
" ",?B("--tags")," Show all tags and the names of commands in each tag\n"
" ",?B("--tags"), " ", ?U("tag")," Show description of commands in this tag\n"
" ",?U("command")," Show detailed description of the command\n"
" ",?U("com?*")," Show detailed description of commands that match this glob.\n"
" "++?B("--tags")++" Show all tags and the names of commands in each tag\n"
" "++?B("--tags")++" "++?U("tag")++" Show description of commands in this tag\n"
" "++?U("command")++" Show detailed description of the command\n"
" "++?U("com?*")++" Show detailed description of commands that match this glob.\n"
" You can use ? to match a simple character,\n"
" and * to match several characters.\n"
"\n",
"Some example usages:\n",
" ejabberdctl help\n",
" ejabberdctl help --tags\n",
" ejabberdctl help --tags accounts\n",
" ejabberdctl help register\n",
" ejabberdctl help regist*\n",
"\n",
"Please note that 'ejabberdctl help' shows all ejabberd commands,\n",
"even those that cannot be used in the shell with ejabberdctl.\n",
"Those commands can be identified because the description starts with: *"],
"\n"
"Some example usages:\n"
" ejabberdctl help\n"
" ejabberdctl help --tags\n"
" ejabberdctl help --tags accounts\n"
" ejabberdctl help register\n"
" ejabberdctl help regist*\n"
"\n"
"Please note that 'ejabberdctl help' shows all ejabberd commands,\n"
"even those that cannot be used in the shell with ejabberdctl.\n"
"Those commands can be identified because the description starts with: *",
ArgsDef = [],
C = #ejabberd_commands{
desc = "Show help of ejabberd commands",
@@ -673,13 +674,13 @@ filter_commands(All, SubString) ->
end.
filter_commands_regexp(All, Glob) ->
RegExp = regexp:sh_to_awk(Glob),
RegExp = xmerl_regexp:sh_to_awk(Glob),
lists:filter(
fun(Command) ->
case regexp:first_match(Command, RegExp) of
{match, _, _} ->
case re:run(Command, RegExp, [{capture, none}]) of
match ->
true;
_ ->
nomatch ->
false
end
end,
@@ -695,6 +696,7 @@ print_usage_command(Cmd, MaxC, ShCode) ->
print_usage_command(Cmd, C, MaxC, ShCode)
end.
%% @spec (Cmd::string(), C::ejabberd_commands(), MaxC::integer(), ShCode::boolean()) -> ok
print_usage_command(Cmd, C, MaxC, ShCode) ->
#ejabberd_commands{
tags = TagsAtoms,
@@ -736,6 +738,10 @@ print_usage_command(Cmd, C, MaxC, ShCode) ->
?PRINT(["\n", NameFmt, "\n", ArgsFmt, "\n", ReturnsFmt, "\n\n", XmlrpcFmt, TagsFmt, "\n\n", DescFmt, "\n\n", LongDescFmt, NoteEjabberdctl], []).
format_usage_ctype(Type, _Indentation)
when (Type==atom) or (Type==integer) or (Type==string) or (Type==rescode) or (Type==restuple)->
io_lib:format("~p", [Type]);
format_usage_ctype({Name, Type}, _Indentation)
when (Type==atom) or (Type==integer) or (Type==string) or (Type==rescode) or (Type==restuple)->
io_lib:format("~p::~p", [Name, Type]);
+1 -1
View File
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
-97
View File
@@ -1,97 +0,0 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_debug.erl
%%% Author : Mickael Remond
%%% Purpose : ejabberd's application callback module
%%% Created : 6 may 2009 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% 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
%%%
%%%----------------------------------------------------------------------
-module(ejabberd_debug).
-export([eprof_start/0, fprof_start/0, stop/0]).
-export([pids/0]).
eprof_start() ->
eprof:start(),
eprof:profile(pids()).
fprof_start() ->
fprof:trace([start, {file, "/tmp/fprof"}, {procs, pids()}]).
%% Stop all profilers
stop() ->
catch eprof:stop(),
catch fprof:stop(),
ok.
pids() ->
lists:zf(
fun(Pid) ->
case process_info(Pid) of
ProcessInfo when is_list(ProcessInfo) ->
CurrentFunction = current_function(ProcessInfo),
InitialCall = initial_call(ProcessInfo),
RegisteredName = registered_name(ProcessInfo),
Ancestor = ancestor(ProcessInfo),
filter_pid(Pid, CurrentFunction, InitialCall, RegisteredName, Ancestor);
_ ->
false
end
end,
processes()).
current_function(ProcessInfo) ->
{value, {_, {CurrentFunction, _,_}}} =
lists:keysearch(current_function, 1, ProcessInfo),
atom_to_list(CurrentFunction).
initial_call(ProcessInfo) ->
{value, {_, {InitialCall, _,_}}} =
lists:keysearch(initial_call, 1, ProcessInfo),
atom_to_list(InitialCall).
registered_name(ProcessInfo) ->
case lists:keysearch(registered_name, 1, ProcessInfo) of
{value, {_, Name}} when is_atom(Name) -> atom_to_list(Name);
_ -> ""
end.
ancestor(ProcessInfo) ->
{value, {_, Dictionary}} = lists:keysearch(dictionary, 1, ProcessInfo),
case lists:keysearch('$ancestors', 1, Dictionary) of
{value, {_, [Ancestor|_T]}} when is_atom(Ancestor) ->
atom_to_list(Ancestor);
_ ->
""
end.
filter_pid(Pid, "ejabberd" ++ _, _InitialCall, _RegisteredName, _Ancestor) ->
{true, Pid};
filter_pid(Pid, _CurrentFunction, "ejabberd" ++ _, _RegisteredName, _Ancestor) ->
{true, Pid};
filter_pid(Pid, _CurrentFunction, _InitialCall, "ejabberd"++_, _Ancestor) ->
{true, Pid};
filter_pid(Pid, _CurrentFunction, _InitialCall, "stringprep"++_, _Ancestor) ->
{true, Pid};
filter_pid(Pid, _CurrentFunction, _InitialCall, _RegisteredName, "ejabberd"++_) ->
{true, Pid};
filter_pid(_Pid, _CurrentFunction, _InitialCall, _RegisteredName, _Ancestor) ->
false.
+42 -47
View File
@@ -5,7 +5,7 @@
%%% Created : 23 Aug 2006 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -45,6 +45,8 @@
get_peer_certificate/1,
get_verify_result/1,
close/1,
setopts/2,
change_controller/2,
sockname/1, peername/1]).
%% gen_server callbacks
@@ -94,18 +96,15 @@ start(Module, SockMod, Socket, Opts) ->
todo
end.
starttls(FsmRef, _TLSOpts) ->
%% TODO: Frontend improvements planned by Aleksey
%%gen_server:call(FsmRef, {starttls, TLSOpts}),
FsmRef.
starttls(FsmRef, TLSOpts) ->
starttls(FsmRef, TLSOpts, undefined).
starttls(FsmRef, TLSOpts, Data) ->
gen_server:call(FsmRef, {starttls, TLSOpts, Data}),
FsmRef.
compress(FsmRef) ->
gen_server:call(FsmRef, compress),
FsmRef.
compress(FsmRef, undefined).
compress(FsmRef, Data) ->
gen_server:call(FsmRef, {compress, Data}),
@@ -138,11 +137,14 @@ close(FsmRef) ->
sockname(FsmRef) ->
gen_server:call(FsmRef, sockname).
peername(_FsmRef) ->
%% TODO: Frontend improvements planned by Aleksey
%%gen_server:call(FsmRef, peername).
{ok, {{0, 0, 0, 0}, 0}}.
setopts(FsmRef, Opts) ->
gen_server:call(FsmRef, {setopts, Opts}).
change_controller(FsmRef, C2SPid) ->
gen_server:call(FsmRef, {change_controller, C2SPid}).
peername(FsmRef) ->
gen_server:call(FsmRef, peername).
%%====================================================================
%% gen_server callbacks
@@ -158,9 +160,16 @@ peername(_FsmRef) ->
init([Module, SockMod, Socket, Opts, Receiver]) ->
%% TODO: monitor the receiver
Node = ejabberd_node_groups:get_closest_node(backend),
IP = case peername(SockMod, Socket) of
{ok, IP1} ->
IP1;
_ ->
undefined
end,
{SockMod2, Socket2} = check_starttls(SockMod, Socket, Receiver, Opts),
{ok, Pid} =
rpc:call(Node, Module, start, [{?MODULE, self()}, Opts]),
rpc:call(Node, Module, start,
[{?MODULE, self()}, [{frontend_ip, IP} | Opts]]),
ejabberd_receiver:become_controller(Receiver, Pid),
{ok, #state{sockmod = SockMod2,
socket = Socket2,
@@ -175,38 +184,16 @@ init([Module, SockMod, Socket, Opts, Receiver]) ->
%% {stop, Reason, State}
%% Description: Handling call messages
%%--------------------------------------------------------------------
handle_call({starttls, TLSOpts}, _From, State) ->
{ok, TLSSocket} = tls:tcp_to_tls(State#state.socket, TLSOpts),
ejabberd_receiver:starttls(State#state.receiver, TLSSocket),
Reply = ok,
{reply, Reply, State#state{socket = TLSSocket, sockmod = tls},
?HIBERNATE_TIMEOUT};
handle_call({starttls, TLSOpts, Data}, _From, State) ->
{ok, TLSSocket} = tls:tcp_to_tls(State#state.socket, TLSOpts),
ejabberd_receiver:starttls(State#state.receiver, TLSSocket),
catch (State#state.sockmod):send(
State#state.socket, Data),
{ok, TLSSocket} = ejabberd_receiver:starttls(
State#state.receiver, TLSOpts, Data),
Reply = ok,
{reply, Reply, State#state{socket = TLSSocket, sockmod = tls},
?HIBERNATE_TIMEOUT};
handle_call(compress, _From, State) ->
{ok, ZlibSocket} = ejabberd_zlib:enable_zlib(
State#state.sockmod,
State#state.socket),
ejabberd_receiver:compress(State#state.receiver, ZlibSocket),
Reply = ok,
{reply, Reply, State#state{socket = ZlibSocket, sockmod = ejabberd_zlib},
?HIBERNATE_TIMEOUT};
handle_call({compress, Data}, _From, State) ->
{ok, ZlibSocket} = ejabberd_zlib:enable_zlib(
State#state.sockmod,
State#state.socket),
ejabberd_receiver:compress(State#state.receiver, ZlibSocket),
catch (State#state.sockmod):send(
State#state.socket, Data),
{ok, ZlibSocket} = ejabberd_receiver:compress(
State#state.receiver, Data),
Reply = ok,
{reply, Reply, State#state{socket = ZlibSocket, sockmod = ejabberd_zlib},
?HIBERNATE_TIMEOUT};
@@ -246,13 +233,7 @@ handle_call(close, _From, State) ->
handle_call(sockname, _From, State) ->
#state{sockmod = SockMod, socket = Socket} = State,
Reply =
case SockMod of
gen_tcp ->
inet:sockname(Socket);
_ ->
SockMod:sockname(Socket)
end,
Reply = peername(SockMod, Socket),
{reply, Reply, State, ?HIBERNATE_TIMEOUT};
handle_call(peername, _From, State) ->
@@ -266,6 +247,14 @@ handle_call(peername, _From, State) ->
end,
{reply, Reply, State, ?HIBERNATE_TIMEOUT};
handle_call({setopts, Opts}, _From, State) ->
ejabberd_receiver:setopts(State#state.receiver, Opts),
{reply, ok, State, ?HIBERNATE_TIMEOUT};
handle_call({change_controller, Pid}, _From, State) ->
ejabberd_receiver:change_controller(State#state.receiver, Pid),
{reply, ok, State, ?HIBERNATE_TIMEOUT};
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State, ?HIBERNATE_TIMEOUT}.
@@ -318,10 +307,16 @@ check_starttls(SockMod, Socket, Receiver, Opts) ->
end, Opts),
if
TLSEnabled ->
{ok, TLSSocket} = tls:tcp_to_tls(Socket, TLSOpts),
ejabberd_receiver:starttls(Receiver, TLSSocket),
{ok, TLSSocket} = ejabberd_receiver:starttls(Receiver, TLSOpts),
{tls, TLSSocket};
true ->
{SockMod, Socket}
end.
peername(SockMod, Socket) ->
case SockMod of
gen_tcp ->
inet:peername(Socket);
_ ->
SockMod:peername(Socket)
end.
+280
View File
@@ -0,0 +1,280 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_global_router.erl
%%% Author : Geoff Cant <gcant@process-one.net>
%%% Purpose : Router for virtual global routes
%%% Created : 07 Aug 2002 by Geoff Cant <gcant@process-one.net>
%%%
%%%
%%% 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
%%%
%%%----------------------------------------------------------------------
-module(ejabberd_global_router).
-behaviour(gen_server).
-include("ejabberd.hrl").
-include("ejabberd_global_router.hrl").
%% API
-export([start_link/0
,route/3
,route/4
,find_route/1
,register_route/1
,register_route/2
,unregister_route/1
,unregister_route/2
,expand_routes/1
,all_prefixes/0
,server_host/2
]).
%% Eunit test exports.
-export([remove_prefix/2
,find_prefix/2
]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-record(state, {}).
%%====================================================================
%% API
%%====================================================================
%%--------------------------------------------------------------------
%% @spec start_link() -> {ok,Pid} | ignore | {error,Error}
%% @doc Starts the server
%% @end
%%--------------------------------------------------------------------
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
route(From, To, Packet) ->
case find_route(To) of
Route = #global_route{} ->
route(Route, From, To, Packet);
no_route ->
ok
end.
route(#global_route{pids=Pids}, From, To, Packet) ->
Pid = pick_route(Pids),
Pid ! {route, From, To, Packet},
ok.
find_route(Domain) ->
case prefix_match(Domain, all_prefixes()) of
nomatch ->
no_route;
Prefix when is_list(Prefix) ->
dirty_get_route(Prefix)
end.
register_route(Prefix) ->
register_route(Prefix, self()).
register_route(Prefix, Pid) ->
Route = #global_route{prefix=Prefix,
pids=[Pid]},
{atomic, ok} = mnesia:transaction(fun write_route/1,
[Route]),
ok.
unregister_route(Prefix) ->
unregister_route(Prefix, self()).
unregister_route(Prefix, Pid) ->
mnesia:transaction(fun delete_route/2, [Prefix, Pid]).
expand_routes(Domain) ->
[expand_route(Prefix, Domain) || Prefix <- all_prefixes()].
expand_route(Prefix, Domain) ->
lists:append([Prefix, ".", Domain]).
all_prefixes() ->
mnesia:dirty_all_keys(global_route).
server_host(Host, Pid) ->
#global_route{prefix=P,pids=Pids} = find_route(Host),
true = lists:member(Pid, Pids),
remove_prefix(P, Host).
%%====================================================================
%% gen_server callbacks
%%====================================================================
%%--------------------------------------------------------------------
%% @private
%% @spec init(Args) -> {ok, State} |
%% {ok, State, Timeout} |
%% ignore |
%% {stop, Reason}
%% @doc Initialises the server's state
%% @end
%%--------------------------------------------------------------------
init([]) ->
update_tables(),
mnesia:create_table(global_route,
[{ram_copies, [node()]},
{type, set},
{attributes,
record_info(fields, global_route)}]),
mnesia:add_table_copy(global_route, node(), ram_copies),
{ok, #state{}}.
%%--------------------------------------------------------------------
%% @private
%% @spec
%% handle_call(Request, From, State) -> {reply, Reply, State} |
%% {reply, Reply, State, Timeout} |
%% {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, Reply, State} |
%% {stop, Reason, State}
%% @doc Call message handler callbacks
%% @end
%%--------------------------------------------------------------------
handle_call(Call, _From, State) ->
?WARNING_MSG("Unexpected call ~p.", [Call]),
{noreply, State}.
%%--------------------------------------------------------------------
%% @private
%% @spec
%% handle_cast(Msg, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% @doc Cast message handler callbacks
%% @end
%%--------------------------------------------------------------------
handle_cast(Msg, State) ->
?WARNING_MSG("Unexpected cast ~p", [Msg]),
{noreply, State}.
%%--------------------------------------------------------------------
%% @private
%% @spec
%% handle_info(Info, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% @doc Non gen-server message handler callbacks
%% @end
%%--------------------------------------------------------------------
handle_info(Info, State) ->
?WARNING_MSG("Unexpected info ~p", [Info]),
{noreply, State}.
%%--------------------------------------------------------------------
%% @private
%% @spec terminate(Reason, State) -> void()
%% @doc This function is called by a gen_server 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_server terminates with Reason.
%% The return value is ignored.
%% @end
%%--------------------------------------------------------------------
terminate(_Reason, _State) ->
ok.
%%--------------------------------------------------------------------
%% @private
%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
%% @doc Convert process state when code is changed
%% @end
%%--------------------------------------------------------------------
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
pick_route(Pids) when is_list(Pids) ->
pick_local_route(Pids).
pick_local_route(Pids) when is_list(Pids) ->
case [Pid || Pid <- Pids,
node(Pid) =:= node()] of
[] -> pick_remote_route(Pids);
LocalPids -> pick_one_route(LocalPids)
end.
pick_remote_route(Pids) when is_list(Pids) -> pick_one_route(Pids).
pick_one_route(Pids) when is_list(Pids) ->
hd(Pids). % should pick random pid?
update_tables() ->
CorrectAttributes = record_info(fields, global_route),
case catch mnesia:table_info(global_route, attributes) of
CorrectAttributes ->
ok;
IncorrectAttributes when is_list(IncorrectAttributes) ->
mnesia:delete_table(global_route);
{'EXIT', _} ->
ok
end.
write_route(R = #global_route{prefix=Prefix}) ->
NewRoute = case mnesia:read({global_route, Prefix}) of
[] -> R;
[OldRoute] ->
combine_routes(OldRoute, R)
end,
ok = mnesia:write(NewRoute).
delete_route(Prefix, Pid) ->
case mnesia:read({global_route, Prefix}, write) of
[] -> ok;
[#global_route{pids=[Pid]}] ->
mnesia:delete({global_route, Prefix});
[Route = #global_route{pids=Pids}] ->
mnesia:write(Route#global_route{pids=Pids -- [Pid]})
end.
combine_routes(R = #global_route{prefix=P, pids=APids},
#global_route{prefix=P, pids=BPids}) ->
R#global_route{pids=lists:usort(APids ++ BPids)}.
prefix_match(Domain, Prefixes) ->
case find_prefix(Domain, Prefixes) of
[] -> nomatch;
[Prefix] -> Prefix;
_Prefixes ->
erlang:error(multiple_prefix_matches)
end.
dirty_get_route(Prefix) ->
case mnesia:dirty_read({global_route, Prefix}) of
[Route = #global_route{}] ->
Route;
_ -> no_route
end.
find_prefix(Domain, PossiblePrefixes) ->
[Prefix
|| Prefix <- PossiblePrefixes,
lists:prefix(Prefix, Domain)].
remove_prefix(Prefix, Domain) ->
[$. | BareDomain] = Domain -- Prefix,
BareDomain.
%%--------------------------------------------------------------------
%%% Eunit Tests.
%%--------------------------------------------------------------------
+27
View File
@@ -0,0 +1,27 @@
%%%----------------------------------------------------------------------
%%% File : ejabberd_global_router.hrl
%%% Author : Geoff Cant <gcant@process-one.net>
%%% Purpose : Virtual global routes record definitions
%%% Created : 08 Aug 2002 by Geoff Cant <gcant@process-one.net>
%%%
%%%
%%% 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
%%%
%%%----------------------------------------------------------------------
-record(global_route, {prefix, pids}).
+49 -17
View File
@@ -5,7 +5,7 @@
%%% Created : 8 Aug 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -81,7 +81,8 @@ add(Hook, Host, Function, Seq) when is_function(Function) ->
add(Hook, Module, Function, Seq) ->
add(Hook, global, Module, Function, Seq).
add(Hook, Host, Module, Function, Seq) ->
add(Hook, Host, Module, Function, Seq)
when is_binary(Host) orelse is_atom(Host) ->
gen_server:call(ejabberd_hooks, {add, Hook, Host, Module, Function, Seq}).
add_dist(Hook, Node, Module, Function, Seq) ->
@@ -104,7 +105,8 @@ delete(Hook, Host, Function, Seq) when is_function(Function) ->
delete(Hook, Module, Function, Seq) ->
delete(Hook, global, Module, Function, Seq).
delete(Hook, Host, Module, Function, Seq) ->
delete(Hook, Host, Module, Function, Seq)
when is_binary(Host) orelse is_atom(Host) ->
gen_server:call(ejabberd_hooks, {delete, Hook, Host, Module, Function, Seq}).
delete_dist(Hook, Node, Module, Function, Seq) ->
@@ -117,14 +119,27 @@ delete_dist(Hook, Host, Node, Module, Function, Seq) ->
%% @doc Run the calls of this hook in order, don't care about function results.
%% If a call returns stop, no more calls are performed.
run(Hook, Args) ->
run(Hook, global, Args).
runx(Hook, global, Args).
run(Hook, Host, Args) ->
case ets:lookup(hooks, {Hook, Host}) of
run(Hook, Host, Args) when is_binary(Host) ->
case runx(Hook, Host, Args) of
stop -> stop;
_ -> runx(Hook, global, Args)
end;
run(Hook, Host, Args) when Host == global ->
runx(Hook, Host, Args).
runx(Hook, Host, Args) when is_binary(Host) orelse is_atom(Host) ->
case ets:lookup(hooks, {Hook, ejabberd:normalize_host(Host)}) of
[{_, Ls}] ->
run1(Ls, Hook, Args);
[] ->
ok
case ets:lookup(hooks, {Hook, global}) of
[{_, Ls}] ->
run1(Ls, Hook, Args);
[] ->
ok
end
end.
%% @spec (Hook::atom(), Val, Args) -> Val | stopped | NewVal
@@ -134,14 +149,29 @@ run(Hook, Host, Args) ->
%% If a call returns 'stop', no more calls are performed and 'stopped' is returned.
%% If a call returns {stopped, NewVal}, no more calls are performed and NewVal is returned.
run_fold(Hook, Val, Args) ->
run_fold(Hook, global, Val, Args).
run_foldx(Hook, global, Val, Args).
run_fold(Hook, Host, Val, Args) ->
case ets:lookup(hooks, {Hook, Host}) of
%% @spec (Hook::atom(), Host, Val, Args) -> Val | stopped | NewVal
%% Host = global | binary()
run_fold(Hook, Host, Val, Args) when is_binary(Host) ->
case run_foldx(Hook, Host, Val, Args) of
stopped -> stopped;
Val2 -> run_foldx(Hook, global, Val2, Args)
end;
run_fold(Hook, Host, Val, Args) when Host == global ->
run_foldx(Hook, Host, Val, Args).
run_foldx(Hook, Host, Val, Args) ->
case ets:lookup(hooks, {Hook, ejabberd:normalize_host(Host)}) of
[{_, Ls}] ->
run_fold1(Ls, Hook, Val, Args);
[] ->
Val
case ets:lookup(hooks, {Hook, global}) of
[{_, Ls}] ->
run_fold1(Ls, Hook, Val, Args);
[] ->
Val
end
end.
%%%----------------------------------------------------------------------
@@ -169,7 +199,8 @@ init([]) ->
%% {stop, Reason, State} (terminate/2 is called)
%%----------------------------------------------------------------------
handle_call({add, Hook, Host, Module, Function, Seq}, _From, State) ->
Reply = case ets:lookup(hooks, {Hook, Host}) of
NHost = ejabberd:normalize_host(Host),
Reply = case ets:lookup(hooks, {Hook, NHost}) of
[{_, Ls}] ->
El = {Seq, Module, Function},
case lists:member(El, Ls) of
@@ -177,12 +208,12 @@ handle_call({add, Hook, Host, Module, Function, Seq}, _From, State) ->
ok;
false ->
NewLs = lists:merge(Ls, [El]),
ets:insert(hooks, {{Hook, Host}, NewLs}),
ets:insert(hooks, {{Hook, NHost}, NewLs}),
ok
end;
[] ->
NewLs = [{Seq, Module, Function}],
ets:insert(hooks, {{Hook, Host}, NewLs}),
ets:insert(hooks, {{Hook, NHost}, NewLs}),
ok
end,
{reply, Reply, State};
@@ -205,10 +236,11 @@ handle_call({add, Hook, Host, Node, Module, Function, Seq}, _From, State) ->
end,
{reply, Reply, State};
handle_call({delete, Hook, Host, Module, Function, Seq}, _From, State) ->
Reply = case ets:lookup(hooks, {Hook, Host}) of
NHost = ejabberd:normalize_host(Host),
Reply = case ets:lookup(hooks, {Hook, NHost}) of
[{_, Ls}] ->
NewLs = lists:delete({Seq, Module, Function}, Ls),
ets:insert(hooks, {{Hook, Host}, NewLs}),
ets:insert(hooks, {{Hook, NHost}, NewLs}),
ok;
[] ->
ok
@@ -295,7 +327,7 @@ run1([{_Seq, Module, Function} | Ls], Hook, Args) ->
[Reason, {Hook, Args}]),
run1(Ls, Hook, Args);
stop ->
ok;
stop;
_ ->
run1(Ls, Hook, Args)
end.
+492
View File
@@ -0,0 +1,492 @@
%%%-------------------------------------------------------------------
%%% File : ejabberd_hosts.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Description : Synchronises running VHosts with the hosts table in the Mnesia database.
%%% Created : 16 Nov 2007 by Alexey Shchepin <alexey@process-one.net>
%%%-------------------------------------------------------------------
%%% Database schema (version / storage / table)
%%%
%%% 3.0.0-alpha-x / mnesia / hosts
%%% host = string()
%%% clusterid = integer()
%%% config = string()
%%%
%%% 3.0.0-alpha-x / odbc / hosts
%%% host = varchar150
%%% clusterid = integer
%%% config = text
-module(ejabberd_hosts).
-behaviour(gen_server).
%% External API
-export([start_link/0
,reload/0
]).
%% Host Registration API
-export([register/1
,register/2
,registered/1
,running/1
,registered/0
,remove/1
,update_host_conf/2
]).
%% Host control API
-export([start_host/1
,start_hosts/1
,stop_host/1
,stop_hosts/1
,load_host_cert/2
]).
%% Private utility functions
-export([get_hosts/1
,config_from_string/2
,get_host_config/2
,diff_hosts/0
,diff_hosts/1
,diff_hosts/2
,reload_hosts/0
,delete_host_config/1
]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include("ejabberd.hrl").
-include("ejabberd_commands.hrl").
-include("ejabberd_config.hrl").
-include_lib("stdlib/include/ms_transform.hrl").
-record(state, {state=wait_odbc,
backend=mnesia,
odbc_wait_time=120}).
-record(hosts, {host, clusterid, config}).
-define(RELOAD_INTERVAL, timer:seconds(60)).
-define(ODBC_STARTUP_TIME, 120). % 2minute limit for ODBC startup.
%% The vhost where the table 'hosts' is stored
%% The table 'hosts' is defined in gen_storage as being for the "localhost" vhost
-define(HOSTS_HOST, list_to_binary(?MYNAME)).
%%====================================================================
%% API
%%====================================================================
reload() ->
?MODULE ! reload.
%% Creates a vhost in the system.
register(Host) when is_list(Host) -> ?MODULE:register(Host, "").
register(Host, Config) when is_list(Host), is_list(Config) ->
true = exmpp_stringprep:is_node(Host),
ID = get_clusterid(),
H = #hosts{host = Host, clusterid = ID, config = Config},
ok = gen_storage:dirty_write(?HOSTS_HOST, H),
reload(),
ok.
%% Updates host configuration
update_host_conf(Host, Config) when is_list(Host), is_list(Config) ->
true = exmpp_stringprep:is_node(Host),
case registered(Host) of
false -> {error, host_process_not_registered};
true ->
remove(Host),
?MODULE:register(Host, Config)
end.
%% Removes a vhost from the system,
%% XXX deleting all ODBC data.
remove(Host) when is_list(Host) ->
true = exmpp_stringprep:is_node(Host),
ID = get_clusterid(),
gen_storage:dirty_delete_where(
?HOSTS_HOST, hosts,
[{'andalso',
{'==', clusterid, ID},
{'==', host, Host}}]),
reload(),
ok.
registered() ->
mnesia:dirty_select(local_config,
ets:fun2ms(fun (#local_config{key={Host, host}}) ->
Host
end)).
registered(Host) when is_list(Host) ->
case mnesia:dirty_read({local_config, {Host, host}}) of
[{local_config, {Host, host}, _}] -> true;
[] -> false
end.
running(global) -> true;
running(HostString) when is_list(HostString) ->
Host = list_to_binary(HostString),
Routes = [H
|| {H, _, {apply, ejabberd_local, route}} <- ejabberd_router:read_route(Host),
H =:= Host],
Routes =/= [].
load_host_cert(Host, PemData) ->
File = cert_filename(Host),
ok = file:write_file(File, PemData),
configure_host_cert(Host, File).
%%--------------------------------------------------------------------
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
%% Description: Starts the server
%%--------------------------------------------------------------------
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
%%====================================================================
%% gen_server callbacks
%%====================================================================
%%--------------------------------------------------------------------
%% Function: init(Args) -> {ok, State} |
%% {ok, State, Timeout} |
%% ignore |
%% {stop, Reason}
%% Description: Initiates the server
%%--------------------------------------------------------------------
init([]) ->
Backend = mnesia, %%+++ TODO: allow to configure this in ejabberd.cfg
configure_static_hosts(),
get_clusterid(), %% this is to report an error if the option wasn't configured
ejabberd_commands:register_commands(commands()),
%% Wait up to 120 seconds for odbc to start
{ok, #state{state=wait_odbc,backend=Backend,odbc_wait_time=?ODBC_STARTUP_TIME}, timer:seconds(1)}.
%%--------------------------------------------------------------------
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
%% {reply, Reply, State, Timeout} |
%% {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, Reply, State} |
%% {stop, Reason, State}
%% Description: Handling call messages
%%--------------------------------------------------------------------
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
%%--------------------------------------------------------------------
%% Function: handle_cast(Msg, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% Description: Handling cast messages
%%--------------------------------------------------------------------
handle_cast(_Msg, State) ->
{noreply, State}.
%%--------------------------------------------------------------------
%% Function: handle_info(Info, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
%% {stop, Reason, State}
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
%% Wait for odbc to start.
handle_info(timeout, State = #state{state=wait_odbc,backend=Backend,odbc_wait_time=N}) when N > 0 ->
case (Backend /= odbc) orelse ejabberd_odbc:running(?MYNAME) of
true ->
?DEBUG("ejabberd_hosts: odbc now running.",[]),
%% The table 'hosts' is defined in gen_storage as being for the "localhost" vhost
Host = ?MYNAME,
HostB = list_to_binary(Host),
gen_storage:create_table(Backend, HostB, hosts,
[{disc_only_copies, [node()]},
{odbc_host, Host},
{attributes, record_info(fields, hosts)},
{types, [{host, text},
{clusterid, int},
{config, text}]}]),
%% Now let's add the default vhost: "localhost"
gen_storage:dirty_write(HostB, #hosts{host = Host,
clusterid = 1,
config = ""}),
self() ! reload,
timer:send_interval(?RELOAD_INTERVAL, reload),
{noreply, State#state{state=running,odbc_wait_time=0}};
false ->
{noreply,State#state{odbc_wait_time=N-1},timer:seconds(1)}
end;
handle_info(timeout, State=#state{state=running}) ->
?WARNING_MSG("Spurious timeout message when odbc is already running.", []),
{noreply, State};
handle_info(reload, State = #state{state=running}) ->
try reload_hosts()
catch
Class:Error ->
StackTrace = erlang:get_stacktrace(),
?ERROR_MSG("~p while synchonising running vhosts with database: ~p~n~p", [Class, Error, StackTrace])
end,
{noreply, State};
handle_info(reload, State = #state{state=wait_odbc}) ->
?ERROR_MSG("Tried to reload vhosts while waiting for odbc startup.", []),
handle_info(timeout, State);
handle_info({reload, Host}, State = #state{state=running}) ->
try reload_host(Host)
catch
Class:Error ->
StackTrace = erlang:get_stacktrace(),
?ERROR_MSG("~p while synchonising running ~p with database: ~p~n~p", [Host, Class, Error, StackTrace])
end,
{noreply, State};
handle_info({reload, Host}, State = #state{state=wait_odbc}) ->
?ERROR_MSG("Tried to reload ~p while waiting for odbc startup.", [Host]),
handle_info(timeout, State);
handle_info(_Info, State) ->
{noreply, State}.
%%--------------------------------------------------------------------
%% Function: terminate(Reason, State) -> void()
%% Description: This function is called by a gen_server 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_server terminates with Reason.
%% The return value is ignored.
%%--------------------------------------------------------------------
terminate(_Reason, _State) ->
ejabberd_commands:unregister_commands(commands()),
ok.
%%--------------------------------------------------------------------
%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
%% Description: Convert process state when code is changed
%%--------------------------------------------------------------------
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
reload_hosts() ->
reload_hosts(get_hosts(odbc)).
reload_hosts(NewHosts) ->
{AddedHosts,RemovedHosts} = diff_hosts(NewHosts),
%% Avoid removing permanent hosts (staticly configured hosts)
DeletedHosts = [H || H <- RemovedHosts,
ejabberd_config:get_host_option(H, permanent) =/= true],
AddHostConfig = lists:map(fun (Host) ->
{Host, get_host_config(odbc,Host)}
end, AddedHosts),
update_config(AddHostConfig,DeletedHosts),
RemovedNotDelete = RemovedHosts -- DeletedHosts,
ejabberd_config:add_global_option(hosts, NewHosts++RemovedNotDelete), % overwrite hosts list
stop_hosts(DeletedHosts),
start_hosts(AddedHosts),
ejabberd_local:refresh_iq_handlers(),
{DeletedHosts, AddedHosts}.
%% updates the configuration of an existing virtual host
reload_host(Host) ->
Config = get_host_config(odbc,Host),
F = fun() ->
mnesia:write_lock_table(local_config),
ejabberd_config:configure_host(Host, Config),
ok
end,
{atomic, ok} = mnesia:transaction(F),
% restart host
stop_host(Host),
start_host(Host),
ejabberd_local:refresh_iq_handlers(),
ok.
%% Apply the vhost changes (new, removed vhosts, configuration) to mnesia
update_config(AddHostConfig, RemoveHosts) ->
F = fun() ->
mnesia:write_lock_table(local_config),
lists:foreach(fun configure_new_host/1, AddHostConfig),
lists:foreach(fun delete_host_config/1, RemoveHosts),
ok
end,
{atomic, ok} = mnesia:transaction(F).
%% Write the configuration data for a new vhost to mnesia (currently only modules)
configure_new_host({H, Config}) when is_list(Config) ->
reconfigure_host_cert(H),
ejabberd_config:configure_host(H, Config).
%% Delete the mnesia config data for a vhost.
%% Needs to mirror any data we insert in configure_new_host (currently only modules)
delete_host_config(Host) ->
ejabberd_config:delete_host(Host).
%% Startup a list of vhosts
start_hosts([]) -> ok;
start_hosts(AddHosts) when is_list(AddHosts) ->
?DEBUG("ejabberd_hosts adding hosts: ~P", [AddHosts, 10]),
lists:foreach(fun start_host/1, AddHosts).
%% Start a single vhost (route, modules)
start_host(Host) when is_list(Host) ->
?DEBUG("Starting host ~p", [Host]),
ejabberd_router:register_route(Host, {apply, ejabberd_local, route}),
case ejabberd_config:get_local_option({modules, Host}) of
undefined -> ok;
Modules when is_list(Modules) ->
lists:foreach(
fun({Module, Args}) ->
gen_mod:start_module(Host, Module, Args)
end, Modules)
end,
case auth_method(Host) of
{host_method, HostMethod} ->
ejabberd_auth:start_method(Host, HostMethod)
end,
ok.
%% Shut down a list of vhosts.
stop_hosts([]) -> ok;
stop_hosts(RemoveHosts) when is_list(RemoveHosts)->
?DEBUG("ejabberd_hosts removing hosts: ~p", [RemoveHosts]),
lists:foreach(fun stop_host/1, RemoveHosts).
%% Shut down a single vhost. (Routes, modules)
stop_host(Host) when is_list(Host) ->
?DEBUG("Stopping host ~p", [Host]),
ejabberd_router:force_unregister_route(list_to_binary(Host)),
lists:foreach(fun(Module) ->
gen_mod:stop_module_keep_config(Host, Module)
end, gen_mod:loaded_modules(Host)),
case auth_method(Host) of
{host_method, Method} ->
ejabberd_auth:stop_method(Host, Method)
end.
%% Get the current vhost list from a variety of sources (ODBC, internal)
get_hosts(ejabberd) -> ?MYHOSTS;
get_hosts(odbc) ->
ClusterID = get_clusterid(),
Hosts = gen_storage:dirty_select(?HOSTS_HOST, hosts, [{'=', clusterid, ClusterID}]),
lists:map(fun (#hosts{host = Host}) ->
exmpp_stringprep:nameprep(Host)
end, Hosts).
%% Retreive the text format config for host Host from ODBC and covert
%% it into a {host, Host, Config} tuple.
get_host_config(odbc, Host) ->
case gen_storage:dirty_read(?HOSTS_HOST, hosts, Host) of
[] ->
erlang:error({no_such_host, Host});
[H] ->
config_from_string(Host, H#hosts.config);
E ->
erlang:error({host_config_error, E})
end.
%% Convert a plaintext string into a host config tuple.
config_from_string(_Host, "") -> [];
config_from_string(_Host, Config) ->
{ok, Tokens, _} = erl_scan:string(Config),
case erl_parse:parse_term(Tokens) of
{ok, List} when is_list(List) ->
List;
E ->
erlang:error({bad_host_config, Config, E})
end.
diff_hosts() ->
diff_hosts(get_hosts(odbc)).
diff_hosts(NewHosts) ->
diff_hosts(NewHosts, get_hosts(ejabberd)).
%% Given the new list of vhosts and the old list, return the list of
%% hosts added since last time and the list of hosts that have been
%% removed.
diff_hosts(NewHosts, OldHosts) ->
RemoveHosts = OldHosts -- NewHosts,
AddHosts = NewHosts -- OldHosts,
{AddHosts,RemoveHosts}.
%% XXX - this should be part of auth, not hosts.
auth_method(Host) ->
case ejabberd_config:get_host_option(Host, auth_method) of
undefined ->
[Default] = ejabberd_config:get_host_option(global, auth_method),
{host_method, Default};
Other ->
{host_method, Other}
end.
configure_static_hosts() ->
?DEBUG("Node startup - configuring hosts: ~p", [?MYHOSTS]),
%% Add a null configuration for all MYHOSTS - this ensures
%% the 'I'm a host' term gets written to the config table.
%% We don't need any configuration options because these are
%% statically configured hosts already configured by ejabberd_config.
F = fun () ->
lists:foreach(fun (H) -> ejabberd_config:configure_host(H, [{permanent, true}]) end,
?MYHOSTS)
end,
mnesia:transaction(F).
cert_filename(Host) ->
Dir = ejabberd_config:get_local_option({domain_certdir, global}),
filename:join(Dir, Host ++ ".pem").
configure_host_cert(Host, File) ->
ejabberd_config:add_local_option({domain_certfile, Host}, File),
ok.
reconfigure_host_cert(Host) ->
File = cert_filename(Host),
case ejabberd_config:is_file_readable(File) of
true ->
ejabberd_config:mne_add_local_option({domain_certfile, Host}, File),
ok;
false ->
no_cert
end.
get_clusterid() ->
case ejabberd_config:get_local_option(clusterid) of
ID when is_integer(ID) ->
ID;
undefined ->
?ERROR_MSG("Please add to your ejabberd.cfg the line: ~n {clusterid, 1}.", []),
1;
Other ->
?ERROR_MSG("Change your misconfigured {clusterid, ~p} to the value: ~p", [Other, 1]),
1
end.
commands() ->
[
%% The commands status, stop and restart are implemented also in ejabberd_ctl
%% They are defined here so that other interfaces can use them too
#ejabberd_commands{name = host_list, tags = [hosts],
desc = "Get a list of registered virtual hosts",
module = ?MODULE, function = registered,
args = [],
result = {hosts, {list, {host, string}}}},
#ejabberd_commands{name = host_register, tags = [hosts],
desc = "Register and start a virtual host",
module = ?MODULE, function = register,
args = [{host, string}], result = {res, rescode}},
#ejabberd_commands{name = host_remove, tags = [hosts],
desc = "Stop and remove a virtual host",
module = ?MODULE, function = remove,
args = [{host, string}], result = {res, rescode}}
].
+133 -33
View File
@@ -5,7 +5,7 @@
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -31,10 +31,12 @@
init/3,
start_listeners/0,
start_listener/3,
stop_listeners/0,
stop_listener/2,
parse_listener_portip/2,
add_listener/3,
delete_listener/2
delete_listener/2,
rate_limit/2
]).
-include("ejabberd.hrl").
@@ -47,8 +49,42 @@ start_link() ->
init(_) ->
ets:new(listen_sockets, [named_table, public]),
bind_tcp_ports(),
{ok, {{one_for_one, 10, 1}, []}}.
bind_tcp_ports() ->
case ejabberd_config:get_local_option(listen) of
undefined ->
ignore;
Ls ->
lists:foreach(
fun({Port, Module, Opts}) ->
ModuleRaw = strip_frontend(Module),
case ModuleRaw:socket_type() of
independent -> ok;
_ ->
bind_tcp_port(Port, Module, Opts)
end
end, Ls)
end.
bind_tcp_port(PortIP, Module, RawOpts) ->
try check_listener_options(RawOpts) of
ok ->
{Port, IPT, IPS, IPV, Proto, OptsClean} = parse_listener_portip(PortIP, RawOpts),
{_Opts, SockOpts} = prepare_opts(IPT, IPV, OptsClean),
case Proto of
udp -> ok;
_ ->
ListenSocket = listen_tcp(PortIP, Module, SockOpts, Port, IPS),
ets:insert(listen_sockets, {PortIP, ListenSocket})
end
catch
throw:{error, Error} ->
?ERROR_MSG(Error, [])
end.
start_listeners() ->
case ejabberd_config:get_local_option(listen) of
undefined ->
@@ -98,15 +134,7 @@ start_dependent(Port, Module, Opts) ->
init(PortIP, Module, RawOpts) ->
{Port, IPT, IPS, IPV, Proto, OptsClean} = parse_listener_portip(PortIP, RawOpts),
%% The first inet|inet6 and the last {ip, _} work,
%% so overriding those in Opts
Opts = [IPV | OptsClean] ++ [{ip, IPT}],
SockOpts = lists:filter(fun({ip, _}) -> true;
(inet6) -> true;
(inet) -> true;
({backlog, _}) -> true;
(_) -> false
end, Opts),
{Opts, SockOpts} = prepare_opts(IPT, IPV, OptsClean),
if Proto == udp ->
init_udp(PortIP, Module, Opts, SockOpts, Port, IPS);
true ->
@@ -127,26 +155,39 @@ init_udp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
end.
init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
SockOpts2 = case erlang:system_info(otp_release) >= "R13B" of
true -> [{send_timeout_close, true} | SockOpts];
false -> []
end,
Res = gen_tcp:listen(Port, [binary,
{packet, 0},
{active, false},
{reuseaddr, true},
{nodelay, true},
{send_timeout, ?TCP_SEND_TIMEOUT},
{keepalive, true} |
SockOpts2]),
case Res of
{ok, ListenSocket} ->
%% Inform my parent that this port was opened succesfully
proc_lib:init_ack({ok, self()}),
%% And now start accepting connection attempts
accept(ListenSocket, Module, Opts);
{error, Reason} ->
socket_error(Reason, PortIP, Module, SockOpts, Port, IPS)
ListenSocket = listen_tcp(PortIP, Module, SockOpts, Port, IPS),
%% Inform my parent that this port was opened succesfully
proc_lib:init_ack({ok, self()}),
%% And now start accepting connection attempts
accept(ListenSocket, Module, Opts).
listen_tcp(PortIP, Module, SockOpts, Port, IPS) ->
case ets:lookup(listen_sockets, PortIP) of
[{PortIP, ListenSocket}] ->
?INFO_MSG("Reusing listening port for ~p", [Port]),
ets:delete(listen_sockets, Port),
ListenSocket;
_ ->
SockOpts2 = try erlang:system_info(otp_release) >= "R13B" of
true -> [{send_timeout_close, true} | SockOpts];
false -> SockOpts
catch
_:_ -> []
end,
Res = gen_tcp:listen(Port, [binary,
{packet, 0},
{active, false},
{reuseaddr, true},
{nodelay, true},
{send_timeout, ?TCP_SEND_TIMEOUT},
{keepalive, true} |
SockOpts2]),
case Res of
{ok, ListenSocket} ->
ListenSocket;
{error, Reason} ->
socket_error(Reason, PortIP, Module, SockOpts, Port, IPS)
end
end.
%% @spec (PortIP, Opts) -> {Port, IPT, IPS, IPV, OptsClean}
@@ -191,6 +232,18 @@ parse_listener_portip(PortIP, Opts) ->
end,
{Port, IPT, IPS, IPV, Proto, OptsClean}.
prepare_opts(IPT, IPV, OptsClean) ->
%% The first inet|inet6 and the last {ip, _} work,
%% so overriding those in Opts
Opts = [IPV | OptsClean] ++ [{ip, IPT}],
SockOpts = lists:filter(fun({ip, _}) -> true;
(inet6) -> true;
(inet) -> true;
({backlog, _}) -> true;
(_) -> false
end, Opts),
{Opts, SockOpts}.
add_proto(Port, Opts) when is_integer(Port) ->
{Port, get_proto(Opts)};
add_proto({Port, Proto}, _Opts) when is_atom(Proto) ->
@@ -222,6 +275,9 @@ get_ip_tuple(IPOpt, _IPVOpt) ->
IPOpt.
accept(ListenSocket, Module, Opts) ->
accept(ListenSocket, Module, Opts, 0).
accept(ListenSocket, Module, Opts, Interval) ->
NewInterval = check_rate_limit(Interval),
case gen_tcp:accept(ListenSocket) of
{ok, Socket} ->
case {inet:sockname(Socket), inet:peername(Socket)} of
@@ -236,11 +292,11 @@ accept(ListenSocket, Module, Opts) ->
false -> ejabberd_socket
end,
CallMod:start(strip_frontend(Module), gen_tcp, Socket, Opts),
accept(ListenSocket, Module, Opts);
accept(ListenSocket, Module, Opts, NewInterval);
{error, Reason} ->
?INFO_MSG("(~w) Failed TCP accept: ~w",
[ListenSocket, Reason]),
accept(ListenSocket, Module, Opts)
accept(ListenSocket, Module, Opts, NewInterval)
end.
udp_recv(Socket, Module, Opts) ->
@@ -304,6 +360,14 @@ start_listener_sup(Port, Module, Opts) ->
[?MODULE]},
supervisor:start_child(ejabberd_listeners, ChildSpec).
stop_listeners() ->
Ports = ejabberd_config:get_local_option(listen),
lists:foreach(
fun({PortIpNetp, Module, _Opts}) ->
delete_listener(PortIpNetp, Module)
end,
Ports).
%% @spec (PortIP, Module) -> ok
%% where
%% PortIP = {Port, IPT | IPS}
@@ -460,3 +524,39 @@ format_error(Reason) ->
ReasonStr ->
ReasonStr
end.
%% Set interval between two accepts on given port
rate_limit([], _Interval) ->
ok;
rate_limit([Port|Ports], Interval) ->
rate_limit(Port, Interval),
rate_limit(Ports, Interval);
rate_limit(Port, Interval) ->
case get_listener_pid_by_port(Port) of
undefined -> no_listener;
Pid -> Pid ! {rate_limit, Interval}, ok
end.
get_listener_pid_by_port(Port) ->
ListenerPids = [Pid || {{P,_,_},Pid,_,_} <-
supervisor:which_children(erlang:whereis(ejabberd_listeners)),
P == Port],
ListenerPid = case ListenerPids of
[] -> undefined;
[LPid|_] -> LPid
end,
ListenerPid.
check_rate_limit(Interval) ->
NewInterval = receive
{rate_limit, AcceptInterval} ->
AcceptInterval
after 0 ->
Interval
end,
case NewInterval of
0 -> ok;
Ms ->
timer:sleep(Ms)
end,
NewInterval.
+111 -81
View File
@@ -5,7 +5,7 @@
%%% Created : 30 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -34,10 +34,12 @@
-export([route/3,
route_iq/4,
route_iq/5,
process_iq_reply/3,
register_iq_handler/4,
register_iq_handler/5,
register_iq_response_handler/4,
register_iq_response_handler/5,
unregister_iq_handler/2,
unregister_iq_response_handler/2,
refresh_iq_handlers/0,
@@ -48,8 +50,9 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-include_lib("exmpp/include/exmpp.hrl").
-include("ejabberd.hrl").
-include("jlib.hrl").
-record(state, {}).
@@ -60,6 +63,12 @@
%% This value is used in SIP and Megaco for a transaction lifetime.
-define(IQ_TIMEOUT, 32000).
% These are the namespace already declared by the stream opening. This is
% used at serialization time.
-define(DEFAULT_NS, ?NS_JABBER_CLIENT).
-define(PREFIXED_NS,
[{?NS_XMPP, ?NS_XMPP_pfx}, {?NS_DIALBACK, ?NS_DIALBACK_pfx}]).
%%====================================================================
%% API
%%====================================================================
@@ -71,33 +80,38 @@ start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
process_iq(From, To, Packet) ->
IQ = jlib:iq_query_info(Packet),
case IQ of
#iq{xmlns = XMLNS} ->
Host = To#jid.lserver,
case ets:lookup(?IQTABLE, {XMLNS, Host}) of
case exmpp_iq:xmlel_to_iq(Packet) of
#iq{kind = request, ns = XMLNS} = IQ_Rec ->
Host = exmpp_jid:prep_domain(To),
case ets:lookup(?IQTABLE, {XMLNS, ejabberd:normalize_host(Host)}) of
[{_, Module, Function}] ->
ResIQ = Module:Function(From, To, IQ),
ResIQ = Module:Function(From, To, IQ_Rec),
if
ResIQ /= ignore ->
ejabberd_router:route(
To, From, jlib:iq_to_xml(ResIQ));
Reply = exmpp_iq:iq_to_xmlel(ResIQ, To, From),
ejabberd_router:route(To, From, Reply);
true ->
ok
end;
[{_, Module, Function, Opts}] ->
gen_iq_handler:handle(Host, Module, Function, Opts,
From, To, IQ);
From, To, IQ_Rec);
[] ->
Err = jlib:make_error_reply(
Packet, ?ERR_FEATURE_NOT_IMPLEMENTED),
ejabberd_router:route(To, From, Err)
case ets:lookup(?IQTABLE, {XMLNS, global}) of
[{_, Module, Function, Opts}] ->
gen_iq_handler:handle(
global, Module, Function, Opts,
From, To, IQ_Rec);
[] ->
Err = exmpp_iq:error(Packet, 'feature-not-implemented'),
ejabberd_router:route(To, From, Err)
end
end;
reply ->
IQReply = jlib:iq_query_or_response_info(Packet),
process_iq_reply(From, To, IQReply);
#iq{kind = response} = IQReply ->
%%IQReply = jlib:iq_query_or_response_info(IQ_Rec),
process_iq_reply(From, To, IQReply);
_ ->
Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST),
Err = exmpp_iq:error(Packet, 'bad-request'),
ejabberd_router:route(To, From, Err),
ok
end.
@@ -113,7 +127,18 @@ process_iq_reply(From, To, #iq{id = ID} = IQ) ->
_ ->
nothing
end.
%% #xmlelement{} used for retro-compatibility
route(FromOld, ToOld, #xmlelement{} = PacketOld) ->
catch throw(for_stacktrace), % To have a stacktrace.
io:format("~nLOCAL: old #xmlelement:~n~p~n~p~n~n",
[PacketOld, erlang:get_stacktrace()]),
% XXX OLD FORMAT: From, To, Packet.
From = jlib:from_old_jid(FromOld),
To = jlib:from_old_jid(ToOld),
Packet = exmpp_xml:xmlelement_to_xmlel(PacketOld, [?NS_JABBER_CLIENT],
[{?NS_XMPP, ?NS_XMPP_pfx}]),
route(From, To, Packet);
route(From, To, Packet) ->
case catch do_route(From, To, Packet) of
{'EXIT', Reason} ->
@@ -123,23 +148,35 @@ route(From, To, Packet) ->
ok
end.
route_iq(From, To, #iq{type = Type} = IQ, F) when is_function(F) ->
route_iq(From, To, IQ, F) ->
route_iq(From, To, IQ, F, undefined).
route_iq(From, To, #iq{type = Type} = IQ, F, Timeout) when is_function(F) ->
Packet = if Type == set; Type == get ->
ID = randoms:get_string(),
Host = From#jid.lserver,
register_iq_response_handler(Host, ID, undefined, F),
jlib:iq_to_xml(IQ#iq{id = ID});
ID = list_to_binary(ejabberd_router:make_id()),
Host = exmpp_jid:prep_domain(From),
register_iq_response_handler(Host, ID, undefined, F, Timeout),
exmpp_iq:iq_to_xmlel(IQ#iq{id = ID});
true ->
jlib:iq_to_xml(IQ)
exmpp_iq:iq_to_xmlel(IQ)
end,
ejabberd_router:route(From, To, Packet).
register_iq_response_handler(_Host, ID, Module, Function) ->
TRef = erlang:start_timer(?IQ_TIMEOUT, ejabberd_local, ID),
mnesia:dirty_write(#iq_response{id = ID,
module = Module,
function = Function,
timer = TRef}).
register_iq_response_handler(Host, ID, Module, Function) ->
register_iq_response_handler(Host, ID, Module, Function, undefined).
register_iq_response_handler(_Host, ID, Module, Function, Timeout0) ->
Timeout = case Timeout0 of
undefined ->
?IQ_TIMEOUT;
N when is_integer(N), N > 0 ->
N
end,
TRef = erlang:start_timer(Timeout, ejabberd_local, ID),
ets:insert(iq_response, #iq_response{id = ID,
module = Module,
function = Function,
timer = TRef}).
register_iq_handler(Host, XMLNS, Module, Fun) ->
ejabberd_local ! {register_iq_handler, Host, XMLNS, Module, Fun}.
@@ -158,7 +195,7 @@ refresh_iq_handlers() ->
ejabberd_local ! refresh_iq_handlers.
bounce_resource_packet(From, To, Packet) ->
Err = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND),
Err = exmpp_stanza:reply_with_error(Packet, 'item-not-found'),
ejabberd_router:route(To, From, Err),
stop.
@@ -176,16 +213,14 @@ bounce_resource_packet(From, To, Packet) ->
init([]) ->
lists:foreach(
fun(Host) ->
ejabberd_router:register_route(Host, {apply, ?MODULE, route}),
ejabberd_hooks:add(local_send_to_resource_hook, Host,
?MODULE, bounce_resource_packet, 100)
ejabberd_router:register_route(Host, {apply, ?MODULE, route})
end, ?MYHOSTS),
ejabberd_hooks:add(local_send_to_resource_hook, global,
?MODULE, bounce_resource_packet, 100),
catch ets:new(?IQTABLE, [named_table, public]),
update_table(),
mnesia:create_table(iq_response,
[{ram_copies, [node()]},
{attributes, record_info(fields, iq_response)}]),
mnesia:add_table_copy(iq_response, node(), ram_copies),
mnesia:delete_table(iq_response),
catch ets:new(iq_response, [named_table, public,
{keypos, #iq_response.id}]),
{ok, #state{}}.
%%--------------------------------------------------------------------
@@ -216,6 +251,18 @@ handle_cast(_Msg, State) ->
%% {stop, Reason, State}
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
%% #xmlelement{} used for retro-compatibility
handle_info({route, FromOld, ToOld, #xmlelement{} = PacketOld}, State) ->
catch throw(for_stacktrace), % To have a stacktrace.
io:format("~nLOCAL: old #xmlelement:~n~p~n~p~n~n",
[PacketOld, erlang:get_stacktrace()]),
% XXX OLD FORMAT: From, To, Packet.
From = jlib:from_old_jid(FromOld),
To = jlib:from_old_jid(ToOld),
Packet = exmpp_xml:xmlelement_to_xmlel(PacketOld, [?NS_JABBER_CLIENT],
[{?NS_XMPP, ?NS_XMPP_pfx}]),
handle_info({route, From, To, Packet}, State);
handle_info({route, From, To, Packet}, State) ->
case catch do_route(From, To, Packet) of
{'EXIT', Reason} ->
@@ -226,21 +273,21 @@ handle_info({route, From, To, Packet}, State) ->
end,
{noreply, State};
handle_info({register_iq_handler, Host, XMLNS, Module, Function}, State) ->
ets:insert(?IQTABLE, {{XMLNS, Host}, Module, Function}),
ets:insert(?IQTABLE, {{XMLNS, ejabberd:normalize_host(Host)}, Module, Function}),
catch mod_disco:register_feature(Host, XMLNS),
{noreply, State};
handle_info({register_iq_handler, Host, XMLNS, Module, Function, Opts}, State) ->
ets:insert(?IQTABLE, {{XMLNS, Host}, Module, Function, Opts}),
ets:insert(?IQTABLE, {{XMLNS, ejabberd:normalize_host(Host)}, Module, Function, Opts}),
catch mod_disco:register_feature(Host, XMLNS),
{noreply, State};
handle_info({unregister_iq_handler, Host, XMLNS}, State) ->
case ets:lookup(?IQTABLE, {XMLNS, Host}) of
case ets:lookup(?IQTABLE, {XMLNS, ejabberd:normalize_host(Host)}) of
[{_, Module, Function, Opts}] ->
gen_iq_handler:stop_iq_handler(Module, Function, Opts);
_ ->
ok
end,
ets:delete(?IQTABLE, {XMLNS, Host}),
ets:delete(?IQTABLE, {XMLNS, ejabberd:normalize_host(Host)}),
catch mod_disco:unregister_feature(Host, XMLNS),
{noreply, State};
handle_info(refresh_iq_handlers, State) ->
@@ -257,7 +304,7 @@ handle_info(refresh_iq_handlers, State) ->
end, ets:tab2list(?IQTABLE)),
{noreply, State};
handle_info({timeout, _TRef, ID}, State) ->
process_iq_timeout(ID),
spawn(fun() -> process_iq_timeout(ID) end),
{noreply, State};
handle_info(_Info, State) ->
{noreply, State}.
@@ -285,67 +332,50 @@ code_change(_OldVsn, State, _Extra) ->
do_route(From, To, Packet) ->
?DEBUG("local route~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
[From, To, Packet, 8]),
LNode = exmpp_jid:prep_node(To),
LResource = exmpp_jid:prep_resource(To),
if
To#jid.luser /= "" ->
LNode /= undefined ->
ejabberd_sm:route(From, To, Packet);
To#jid.lresource == "" ->
{xmlelement, Name, _Attrs, _Els} = Packet,
case Name of
"iq" ->
LResource == undefined ->
case Packet of
_ when ?IS_IQ(Packet) ->
process_iq(From, To, Packet);
"message" ->
_ when ?IS_MESSAGE(Packet) ->
ok;
"presence" ->
_ when ?IS_PRESENCE(Packet) ->
ok;
_ ->
ok
end;
true ->
{xmlelement, _Name, Attrs, _Els} = Packet,
case xml:get_attr_s("type", Attrs) of
"error" -> ok;
"result" -> ok;
case exmpp_stanza:get_type(Packet) of
<<"error">> -> ok;
<<"result">> -> ok;
_ ->
ejabberd_hooks:run(local_send_to_resource_hook,
To#jid.lserver,
exmpp_jid:prep_domain(To),
[From, To, Packet])
end
end.
update_table() ->
case catch mnesia:table_info(iq_response, attributes) of
[id, module, function] ->
mnesia:delete_table(iq_response);
[id, module, function, timer] ->
ok;
{'EXIT', _} ->
ok
end.
get_iq_callback(ID) ->
case mnesia:dirty_read(iq_response, ID) of
case ets:lookup(iq_response, ID) of
[#iq_response{module = Module, timer = TRef,
function = Function}] ->
cancel_timer(TRef),
mnesia:dirty_delete(iq_response, ID),
ets:delete(iq_response, ID),
{ok, Module, Function};
_ ->
error
end.
process_iq_timeout(ID) ->
spawn(fun process_iq_timeout/0) ! ID.
process_iq_timeout() ->
receive
ID ->
case get_iq_callback(ID) of
{ok, undefined, Function} ->
Function(timeout);
_ ->
ok
end
after 5000 ->
case get_iq_callback(ID) of
{ok, undefined, Function} ->
Function(timeout);
_ ->
ok
end.
+14 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 23 Oct 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2009 ProcessOne
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -151,6 +151,19 @@ write_event(Fd, {Time, {info_msg, _GL, {Pid, Format, Args}}}) ->
F = add_node("ERROR: ~p - ~p~n", Pid),
file:write(Fd, io_lib:format(T ++ F, [Format,Args]))
end;
write_event(Fd, {Time, {warning_report, _GL, {Pid, std_warning, Rep}}}) ->
T = write_time(Time, "WARNING REPORT"),
S = format_report(Rep),
file:write(Fd, io_lib:format(T ++ S ++ add_node("", Pid), []));
write_event(Fd, {Time, {warning_msg, _GL, {Pid, Format, Args}}}) ->
T = write_time(Time, "WARNING REPORT"),
case catch io_lib:format(add_node(Format,Pid), Args) of
S when is_list(S) ->
file:write(Fd, io_lib:format(T ++ S, []));
_ ->
F = add_node("ERROR: ~p - ~p~n", Pid),
file:write(Fd, io_lib:format(T ++ F, [Format,Args]))
end;
write_event(_, _) ->
ok.

Some files were not shown because too many files have changed in this diff Show More