Compare commits

...

295 Commits

Author SHA1 Message Date
Jerome Sautret 18f6b02065 Added 2.1.8 release notes. 2011-06-06 11:18:10 +02:00
Badlop 33544569fb Fix crash when user publishes an item (EJAB-1457) 2011-06-01 23:22:25 +02:00
Badlop 529ab22a79 Recompile the Guide 2011-05-31 22:31:24 +02:00
Badlop 9f6afab09c Update ejabberd version number to 2.1.7 2011-05-31 22:31:22 +02:00
Badlop 2137c03da1 Recompile translations 2011-05-31 22:31:20 +02:00
Badlop 58fe9d3345 Add release_notes_2.1.7.txt 2011-05-31 22:30:57 +02:00
Badlop deb5e45bff Fix some typos in the Guide 2011-05-31 21:12:31 +02:00
Badlop bd1df027c6 Disable all entity expansions (thanks to Alexey Shchepin)(EJAB-1451) 2011-05-31 21:12:29 +02:00
Badlop 20290cab01 Update the 'configure' script with: aclocal; autoconf 2011-05-31 21:03:45 +02:00
Christophe Romain adcf2d5c4e Pubsub node maxitem forced to 0 if non persistent node (thanks to Karim Gemayel)(EJAB-1434) 2011-05-31 15:51:30 +02:00
Christophe Romain 8faafc5b0d apply filtered notification to PEP last items (thanks to karim Gemayel)(EJAB-1456) 2011-05-31 15:40:07 +02:00
Badlop 370093afde Fix minor English error 2011-05-31 12:27:45 +02:00
Badlop 32d3d1626b New ERL_EPMD_ADDRESS that works since Erlang/OTP R14B03 2011-05-31 12:26:44 +02:00
Badlop d4d28e038b Cut the string when calling halt/1 2011-05-30 17:11:32 +02:00
Evgeniy Khramtsov d6a076dae8 Under some circumstances the "uri" variable in StartNamespaceDeclHandler could be NULL. We check this now. 2011-05-30 22:39:56 +10:00
Badlop 2cacf21d51 Fix a recent commit about "Set script as executable" 2011-05-30 11:46:13 +02:00
Badlop 0874b93e7c Support anonymous accounts in Shared Roster @all@ directive (EJAB-1264)
With this change, logged anonymous accounts are considered to be registered.
2011-05-30 11:00:21 +02:00
Badlop ba9094a089 Add link in the Backup page to the Guide 2011-05-29 20:51:33 +02:00
Badlop bfebcebeb7 Support XEP-0191 Simple Communications Blocking (thanks to Stephan Maka)(EJAB-695) 2011-05-27 11:47:22 +02:00
Badlop 1c0b99e162 A user can query his own Last activity, even if not subscribed to oneself 2011-05-26 12:50:40 +02:00
Badlop f850bcbbc9 Several fixes and improvements in ejabberd.init.template
Changes:
* Set script as executable
* Add LSB tags and overrides, copied from Debian's ejabberd package
* Add chkconfig support (thanks to Ivan Martinez)(EJAB-1450)
* Don't use nounset, as that breaks when no argument is provided
* Add status command
2011-05-24 23:46:44 +02:00
Evgeniy Khramtsov 7bc879c6f4 When checking captcha setup, try to generate image only when captcha is enabled in order to avoid logging of confusing error 2011-05-18 12:48:02 +10:00
Badlop f7d532f2f7 When module start fails during server start, stop erlang (EJAB-1446) 2011-05-16 22:33:59 +02:00
Evgeniy Khramtsov dfbf32ecba Note that ejabberd works with CGP LDAP server 2011-05-07 10:32:52 +10:00
Christophe Romain 17abbf3d82 Owner can delete any items from its own node (EJAB-1445) 2011-05-06 13:58:49 +02:00
Evgeniy Khramtsov dfbfd90f8c Take into consideration internal queue length when sorting processes queues 2011-05-05 16:08:28 +10:00
Evgeniy Khramtsov 84c1cf8033 Do not accept XML with undefined prefixes (EJAB-680) 2011-05-03 20:26:07 +10:00
Badlop 5a0cfe7e2b Reorganize the push_item function, and handle version not_found (EJAB-1420) 2011-04-29 20:34:08 +02:00
Badlop 714dce84db No need to inform that XEP-0237 is optional; clarified in XEP version 1.2 2011-04-29 20:34:06 +02:00
Badlop b807b21a59 Show configuration for HTTPS http_bind 2011-04-28 13:24:18 +02:00
Badlop 4f4c8eb61e mod_register Access now also controls account unregistrations 2011-04-26 22:55:04 +02:00
Badlop 3952888f94 Escape user input in mod_privacy_odbc (EJAB-1442) 2011-04-26 20:57:48 +02:00
Badlop 9b145385af Throw error when captcha fails at server start, not later at runtime 2011-04-26 13:59:08 +02:00
jabber 897b46c31d Do not decrease MUC admin's role/affiliation 2011-04-18 21:06:05 +10:00
Evgeniy Khramtsov 72299ab078 Add captcha_limit option to the example config 2011-04-18 16:16:10 +10:00
Evgeniy Khramtsov e7ab83b612 Remove forgotten -compile(export_all). 2011-04-18 16:09:05 +10:00
Evgeniy Khramtsov 07cf6f09b8 Implement CAPTCHA limit 2011-04-18 16:06:36 +10:00
Evgeniy Khramtsov 252ee6228b Fix syntax error 2011-04-18 15:50:24 +10:00
Evgeniy Khramtsov cf6264f507 CAPTCHA whitelist support 2011-04-18 15:47:06 +10:00
Badlop 4f1ececbd1 Try to improve support for roster_version in MSSQL (EJAB-1437) 2011-04-14 23:11:37 +02:00
Badlop 70bf5b4eda The responses to HEAD must have empty Body 2011-04-12 23:31:08 +02:00
Badlop f59a979f7c Support as read-only HTTP method not only GET, also HEAD 2011-04-12 23:13:46 +02:00
Badlop 05e3893f60 If extauth script crashes, ejabberd should restart it (EJAB-1428) 2011-04-11 21:27:19 +02:00
Badlop 7d7621c67c Support more captcha_host value formats (EJAB-1418) 2011-04-11 19:59:26 +02:00
Badlop 449e56ed52 Send jid attribute when occupant is banned (EJAB-1432) 2011-04-07 12:54:39 +02:00
Badlop aded966370 mod_ping uses iqdisc no_queue by default (thanks to Chris Moos)(EJAB-1435) 2011-04-07 12:08:31 +02:00
Badlop dac1f328d7 Clarify {iqdisc, no_queue} 2011-04-07 12:06:31 +02:00
Badlop 90ea752046 Updated Japanese translation (thanks to Mako N) 2011-03-30 19:18:26 +02:00
Badlop e4b3bd5005 Fix typo (thanks to Krzee) 2011-03-17 12:15:31 +01:00
Badlop abcbcd1f2c Update the changed string in the PO translation files 2011-03-13 18:34:55 +01:00
Badlop 18fd67b311 Change string in WebAdmin to reuse an existing one 2011-03-13 18:34:50 +01:00
Badlop b116957982 Fix bashism and make some lines similar to master branch (EJAB-1404) 2011-03-09 16:25:05 +01:00
Badlop a1f20a5bc0 If the port number isn't listener, then specify the protocol (EJAB-1418) 2011-03-03 11:38:00 +01:00
Badlop e0d14c3b8d captcha_host must have the port number to get protocol (EJAB-1418) 2011-03-03 00:02:43 +01:00
Badlop 1548a18b5e mod_irc must send presence unavailable to the departing occupant (EJAB-1417) 2011-03-01 22:33:11 +01:00
Badlop 339fa6e41b ejabberdctl needs space between INET_DIST_INTERFACE (thanks to Dale Chase)(EJAB-1416) 2011-02-28 18:40:45 +01:00
Badlop db0962804d Tweak pg2_backport.erl to work with Erlang older than R13A (EJAB-1349) 2011-02-22 23:44:45 +01:00
Badlop 677d8b1a29 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:34:15 +01:00
Badlop 850218c2df Forward old messages to newly spawned extauth process (thanks to Mika Seppänen)(EJAB-1385) 2011-02-21 16:13:41 +01:00
Badlop 1c89914382 New route_iq/5 accepting Timeout (thanks to Edwin Fine)(EJAB-1398)
Also new register_iq_response_handler/5
2011-02-21 13:44:39 +01:00
Badlop fe40a9c5f6 New DIST_USE_INTERFACE to restrict IP where erlang connections are listened (EJAB-1404) 2011-02-16 23:53:29 +01:00
Badlop bc0ae5a017 New Indonesian translation (thanks to Irfan Mahfudz Guntur)(EJAB-1407) 2011-02-16 13:46:20 +01:00
Christophe Romain 91ab7e029b fix empty pubsub payload check on odbc version 2011-02-14 16:45:49 +01:00
Christophe Romain c3a88c713b fix empty pubsub payload check 2011-02-14 16:41:32 +01:00
Christophe Romain fd52f2cb7d update copyright up to 2011 2011-02-14 13:50:55 +01:00
Badlop f91eb52890 Provide HTTPS URL in CAPTCHA form when listener has 'tls' option (EJAB-1406) 2011-02-14 13:11:21 +01:00
Badlop ca59a7f027 Fix typo in French translation 2011-02-11 20:19:59 +01:00
Badlop 6dea2d2307 Escape output from ctlexec() to erl script (thanks to Dan Scott)(EJAB-1399) 2011-02-09 16:38:54 +01:00
Badlop 650b2802b5 Remove erroneous comment (EJAB-645) 2011-02-03 17:23:09 +01:00
Badlop 6ddc66db9f Handle Tigase's unexpected version=1.0 when ejabberd doesn't announce it (EJAB-1379) 2011-01-31 19:43:28 +01:00
Badlop 792512459d mod_pres_counter prevents subscription flood (thanks to Ahmed Omar and Alexey Shchepin)(EJAB-1388) 2011-01-31 18:52:07 +01:00
Badlop 0359e345b0 Add to example config file access_from comment 2011-01-28 17:13:44 +01:00
Badlop a09c319357 Update exmpp version to 0.9.6 2011-01-28 12:46:09 +01:00
Badlop 36166aa40e Comment unused code 2011-01-28 12:11:34 +01:00
Badlop a25c9c5df3 Don't let presence-in privacy rule block a presence subscription using ODBC (EJAB-255) 2011-01-19 20:58:57 +01:00
Badlop 6e3a9ac4fd Fix delayed response of a timeout call was reused for next login (EJAB-1385) 2011-01-19 19:06:46 +01:00
Badlop f4c74c147b Clarify more the expected content of welcome_message mod_register option 2011-01-17 23:46:08 +01:00
Badlop 0edda6150b Clarify error message when BOSH query is sent to non-running module 2011-01-12 21:22:43 +01:00
Mickaël Rémond bd43505db9 Use route instead of send_element to go through standard workflow Offline messages should thus be tracked for ack if needed (TEXTO-226).
Signed-off-by: Evgeniy Khramtsov <ekhramtsov@process-one.net>
2011-01-04 15:21:10 +01:00
Badlop a2e1d2030a Keep the order of stanzas when BOSH sends several (EJAB-1374) 2010-12-30 13:42:53 +01:00
Evgeniy Khramtsov 4c8b034874 Change c2s state before offline messages resending 2010-12-28 21:09:15 +09:00
Alexey Shchepin b47c50145d Make jlib:ip_to_list safe to use 2010-12-20 19:29:05 +02:00
Badlop b9f4daca46 Revert branch name back to 2.1.x 2010-12-20 13:10:33 +01:00
Evgeniy Khramtsov 606c207e21 Make sure 'closed' event is correctly processed on every state 2010-12-17 17:26:20 +09:00
W. Andrew Loe III d9c01e8ed9 Ignore OS X libraries. 2010-12-15 17:01:14 +01:00
Badlop 3e9c9fc750 Remove Type and Spec, backport list comprehensions, so R12B-5 can compile 2010-12-13 12:17:28 +01:00
Badlop fbcb9bb154 Recompile the Guide 2010-12-13 11:15:19 +01:00
Badlop 6242fd2bb8 Update ejabberd version number to 2.1.6 2010-12-13 11:15:18 +01:00
Badlop 1c566057f8 Recompile translations 2010-12-13 11:15:16 +01:00
Badlop aa59d8f1f0 Add release notes for ejabberd 2.1.6 2010-12-13 11:15:14 +01:00
Badlop 6dd35923b0 Fix warning about unused variables 2010-12-13 11:14:39 +01:00
Badlop b9bbe19d4c Option to reject S2S connection if untrusted certificate (EJAB-464) 2010-12-11 02:29:53 +01:00
Badlop 44b2002504 Include From attribute in the stream header of outgoing S2S connections 2010-12-11 02:29:52 +01:00
Badlop faf422202f When TLS is required in s2s, add subelement to stream:features starttls 2010-12-11 02:29:50 +01:00
Badlop eb884c80d0 Add option to require encryption in S2S connections (EJAB-495) 2010-12-11 02:29:48 +01:00
Badlop b83dd9f954 Support for X-Forwarded-For HTTP header (EJAB-1356) 2010-12-07 16:47:55 +01:00
Christophe Romain fd828c3e9b update pubsub_odbc patch 2010-12-07 14:00:40 +01:00
Christophe Romain 79648ce853 add node attribute to pubsub subscribe event (EJAB-1361) 2010-12-07 13:51:10 +01:00
Badlop ddc94a8c96 Update Czech Translation (thanks to Lukáš Polívka) 2010-12-06 12:04:12 +01:00
Badlop aa413d63da Fix detection of mod_last at server start (EJAB-641) 2010-12-03 17:26:12 +01:00
Badlop 548be4cf3d Update example extauth script with tryregister, removeuser and removeuser3 (EJAB-641) 2010-12-03 17:26:10 +01:00
Pablo Polvorin 0e5b0b43fa Revert "Fix cyrsasl_digest RFC-2831 2.1.2.1 (EJAB-476)"
This reverts commit c890b17834.
This change made ejabberd more strict in protocol compliance, which breaks Psi 0.14 and other clients.
We must grant a grace period to client developers to fix their clients. So this isn't going to be included
in 2.1.x.
2010-12-03 11:12:43 -03:00
Badlop 8258f5940b Support PostgreSQL 9.0 (EJAB-1359)(thanks to Stephen Gibberd and Konstantin Nikiforov) 2010-12-03 12:43:05 +01:00
Pablo Polvorin c890b17834 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:55:06 -03:00
Christophe Romain f0a848ef45 fix pubsub cross domain eventing (EJAB-1340) 2010-12-02 13:56:45 +01:00
Badlop 20d66e6736 Update Greek translation (thanks to James Iakovos Mandelis) 2010-12-01 13:28:20 +01:00
Evgeniy Khramtsov 731c9b86e0 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:24:51 +09:00
Badlop 955343f6aa When the Password attribute is missing in PIEFXIS file, don't check account auth. 2010-12-01 00:55:09 +01:00
Otavio Fernandes 1b73ac5118 Corrections on pt_BR translations. 2010-11-30 22:43:04 +01:00
Badlop 9ee8191939 Update Ukrainian translation (thanks to Ruslan Rakhmanin) 2010-11-30 22:43:02 +01:00
Christopher tofu Zorn f2231a2282 expose find_connection for routing in other modules (if needed) 2010-11-29 20:05:39 +01:00
Christopher tofu Zorn 3e24408710 add the ability to send raw xml packets over http bind 2010-11-29 20:05:37 +01:00
Badlop 3e67200d64 Update mod_register_web string in PO files 2010-11-29 19:35:18 +01:00
Badlop 6374b5b1e7 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:34:26 +01:00
Badlop 26ac75bdc9 Support negative part-hour TZ values (thanks to Alexander Zhukov)(EJAB-1301) 2010-11-29 14:36:09 +01:00
Alexey Shchepin 1d1496a667 Don't loop when there is nothing after a stream start 2010-11-26 17:08:00 +01:00
Andreas Köhler e34eebb5ad 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:14:46 +01:00
Badlop 776930fa06 Update French translation (thanks to Nicolas Vérité) 2010-11-25 21:31:21 +01:00
Badlop 38af7c85a6 Update German translation (thanks to Nikolaus Polak) 2010-11-25 21:31:19 +01:00
Badlop 99b7a285d7 Update Japanese translation (thanks to Tsukasa Hamano) 2010-11-24 17:10:54 +01:00
Badlop 19e20f75d7 Update Chinese translation (thanks to Shelley Shyan) 2010-11-24 13:42:19 +01:00
Evgeniy Khramtsov b8d6aee1ce Merge branch 'caps' into 2.1.x
Conflicts:
	src/ejabberd_c2s.erl
2010-11-24 16:45:05 +09:00
Otavio Fernandes 48b768b5b0 Updating Brazilian Portuguese (pt_BR) translations for v2.1.6 2010-11-23 17:54:37 +01:00
Badlop bd604945c9 Update Polish translation (thanks to Zbyszek Żółkiewski) 2010-11-23 13:07:14 +01:00
Badlop 0a59ebe405 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:04:07 +01:00
Christophe Romain 32eaa01929 Revert "populate pubsub#roster_groups_allowed in node configuration options (EJAB-1344)"
This reverts commit dfaeb3bc88.
2010-11-22 11:15:04 +01:00
Badlop baf9363bdf Disapprove the use of R14A and R14B due to the rwlock bug. 2010-11-19 15:33:48 +01:00
Badlop 12aaa0125b Update Russian translation (thanks to Evgeniy Khramtsov) 2010-11-19 15:15:47 +01:00
Badlop cb7cd9abb8 Update translate files 2010-11-19 13:47:24 +01:00
Badlop ca701e1675 Update the Spanish translation 2010-11-19 13:45:32 +01:00
Badlop 9b88fd6646 Fix some English strings 2010-11-19 13:44:30 +01:00
Badlop 76ca7ae7f0 Translate mod_register_web to Ukrainian (thanks to Rain) 2010-11-19 00:23:40 +01:00
Evgeniy Khramtsov 1ab223568d Document mod_shared_roster_ldap (thanks to Marcin Owsiany) 2010-11-18 16:59:35 +09:00
Badlop 043effc3ce Translate mod_register_web to Spanish 2010-11-17 23:16:46 +01:00
Badlop 4fd1a8ba63 Translate mod_register_web to Russian (thanks to Rain) 2010-11-17 22:42:43 +01:00
Badlop 36303fb4be Update strings to translate 2010-11-17 22:36:56 +01:00
Badlop 62357b9589 Add extract_translations.beam to gitignore 2010-11-17 22:35:33 +01:00
Badlop 808029b868 Fix http-bind supervisor to support multiple vhosts (EJAB-1321) 2010-11-17 20:31:28 +01:00
Andreas Köhler cfd377b98e Fix R12B5 compatibility in ejabberd_http_bind.erl (EJAB-1343)
erlang:max/2 and :min/2 are new functions
2010-11-17 13:01:17 +01:00
Andreas Köhler 6eeb355a22 Use LFrom and LTo consistently in ejabberd_s2s_in:stream_established/2 (EJAB-1342) 2010-11-17 12:57:05 +01:00
Evgeniy Khramtsov a0e2e943b4 Do not start mod_proxy65 if it is unable to bind an address (EJAB-1336) 2010-11-17 18:13:19 +09:00
Evgeniy Khramtsov 78931d8efa Use MEDIUMTEXT type for vcard avatars in MySQL schema (EJAB-1252) 2010-11-17 17:36:51 +09:00
Evgeniy Khramtsov 0d2a8cd04f Do not print full error message when LDAP timeout occurs (EJAB-1324) 2010-11-17 17:14:47 +09:00
Evgeniy Khramtsov 97087eb3b9 Set SSL_MODE_RELEASE_BUFFERS mode when available (EJAB-1351) 2010-11-17 13:54:27 +09:00
Badlop 6eeef62ce4 Provide new, not old, affiliation in kick/ban presence with codes 321 and 301 2010-11-16 00:03:09 +01:00
Evgeniy Khramtsov 0ccff15599 Strip status when needed in presence-unavailable as well 2010-11-15 13:47:31 +09:00
Badlop 325fb8caef Fix typos in the example configuration file 2010-11-12 21:24:01 +01:00
Andreas Köhler 18ef908759 Before binding tcp ports, checks the socket type and listener options
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:46:18 +01:00
Andreas Köhler 1f1d2bd5f5 Bind listener ports early and start accepting connections later
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:46:16 +01:00
Andreas Köhler 0c484369c9 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:40:04 +01:00
Andreas Köhler 100f2e9a13 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:40:03 +01:00
Andreas Köhler 510fd8cf73 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:40:01 +01:00
Andreas Köhler 080922a3de 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:40:00 +01:00
Andreas Köhler cb7d8c8ead Use ejabberd_c2s:privacy_check_packet/5 for all those hook folded runs in the c2s module 2010-11-10 15:39:59 +01:00
Andreas Köhler c47252aea1 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:39:57 +01:00
Andreas Köhler f96074057c 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:39:55 +01:00
Christophe Romain dfaeb3bc88 populate pubsub#roster_groups_allowed in node configuration options (thanks to Karim Gemayel)(EJAB-1344) 2010-11-10 15:15:03 +01:00
Christophe Romain c31f59e326 fix bad plugin order issue injected in previous patch (EJAB-1286) 2010-11-09 14:32:40 +01:00
Andreas Köhler 7c2b9eaf97 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:57 +01:00
Andreas Köhler 79f5251d69 Change max restart strategy of ejabberd_odbc_sup to handle some SQL timeouts. 2010-11-08 18:41:03 +01:00
Christophe Romain 917e8640c2 avoid node_call to break transaction (thanks to Karim Gemayel)(EJAB-1286) 2010-11-08 11:16:51 +01:00
Andreas Köhler c4bc0e7252 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:49:52 +01:00
Evgeniy Khramtsov 1f16e4783c Take care of xml:lang attribute in unauthenticated stanzas as well 2010-11-06 13:58:52 +09:00
Badlop 7f3a5066c6 New ip_access option restricts which IPs can register (thanks to Alexey Shchepin)(EJAB-915) 2010-11-05 19:33:52 +01:00
Badlop 6f3713a67d Disable mod_register_web in default config because by default captcha is disabled 2010-11-05 19:33:50 +01:00
Badlop abfb4a2841 Recompile the Guide 2010-11-05 18:21:20 +01:00
Badlop f672fd0824 Added mod_register_web: web page for account registration (EJAB-471) 2010-11-05 18:19:52 +01:00
Evgeniy Khramtsov 60b36beda8 Disable LRU caching algorithm for LDAP shared rosters 2010-11-05 17:01:18 +09:00
Evgeniy Khramtsov c4289095e0 Do not store long language tag to avoid possible DoS/flood attacks 2010-11-05 05:10:18 +09:00
Evgeniy Khramtsov 31757116fc LDAP shared roster support (thanks to Realloc and Marcin Owsiany) 2010-11-05 02:34:45 +09:00
Jonas Ådahl 2f68733708 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:52 +01:00
Badlop dccaff0544 Correct in the Guide the default mod_irc encoding
The default option value was last changed in  EJAB-302,
but the Guide was not properly updated yet.
2010-11-02 22:47:28 +01:00
Badlop 184ec38510 Implement the mod_irc option default_encoding, it was already documented
Related:
http://www.ejabberd.im/node/4270#comment-56609
http://www.ejabberd.im/node/4270#comment-56780
2010-11-02 22:40:08 +01:00
Badlop 2d59efb515 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 13:51:36 +01:00
Evgeniy Khramtsov 195d22d906 Merge branch '2.1.x' of git+ssh://gitorious.process-one.net/ejabberd/mainline into 2.1.x 2010-11-01 22:23:01 +09:00
Evgeniy Khramtsov ab80513755 Do not run set_last request inside a transaction 2010-11-01 22:22:41 +09:00
Badlop 8a116411bb Fix errors in EDoc comments 2010-10-28 18:48:27 +02:00
Badlop bd3889b6ec Include a Required xml element in the captcha field 2010-10-27 00:50:17 +02:00
Andreas Köhler 400fb69f15 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:32:15 +02:00
Andreas Köhler 9da45d40c7 Re-use the TLSSock argument in tls:send/2 (EJAB-1327) 2010-10-26 19:30:32 +02:00
Evgeniy Khramtsov 23db206ea1 * Add top-level instructions for x:data incompatible clients
* Remove trailing dot
2010-10-26 03:47:14 +10:00
Badlop 964b7b6b67 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-10-25 19:00:52 +02:00
Badlop 9c5f34794a Workaround for Psi's wrong Type in form submission 2010-10-25 18:58:31 +02:00
Badlop eca7588abf Recompile the guide.html 2010-10-25 18:57:54 +02:00
Badlop a15d583d4d Add CAPTCHA example configurations to cfg (EJAB-1262)(EJAB-1326) 2010-10-25 18:57:39 +02:00
Evgeniy Khramtsov e03c453c78 Provide image url in registration form when captcha is enabled 2010-10-25 23:36:31 +10:00
Evgeniy Khramtsov 641dc7d695 Add password entropy check (EJAB-1326) 2010-10-24 17:17:30 +10:00
Evgeniy Khramtsov 0a1b0498a6 * Rename option captcha to captcha_protected for consistency.
* Document captcha_protected option
2010-10-24 15:45:42 +10:00
Evgeniy Khramtsov a6858a6ce4 Merge branch '2.1.x' of git+ssh://gitorious.process-one.net/ejabberd/mainline into 2.1.x 2010-10-24 15:30:37 +10:00
Evgeniy Khramtsov f4beeb1706 CAPTCHA IBR support (EJAB-1262) 2010-10-24 15:30:16 +10:00
Badlop 75298b4c27 Improve example of outoging_s2s_options 2010-10-22 23:14:24 +02:00
Christophe Romain 011464e6ac improve documentation (thanks to Karim Gemayel) 2010-10-21 11:14:24 +02:00
Peter Lemenkov c53e8012b2 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:05:31 +02:00
Badlop fe04d57284 Fix bug in mod_pubsub in_subscription return value 2010-10-19 00:26:36 +02:00
Christophe Romain 0f3bd782c4 documentation update (thanks to Karim Gemayel) 2010-10-18 16:53:21 +02:00
Badlop 91cf9194d8 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:53:12 +02:00
Badlop e2dbad6242 Check privacy of outgoing IQ stanzas (EJAB-1320) 2010-10-16 22:53:10 +02:00
Badlop 84d4a1619b Check privacy of incoming IQ stanzas (EJAB-1320) 2010-10-16 22:53:08 +02:00
Badlop 16fae4d117 Add support to ejabberd_ctl to handle anonymous command arguments 2010-10-15 21:53:03 +02:00
Badlop 76f7548935 Rename aclocal.m4 to acinclude.m4 (thanks to Andreas Köhler)
Also fixed minor typos, added the compiled aclocal.m4 to gitignore.
As the 2.1.x branch includes the 'configure' script, it isn't needed
to document here how to build it, only in the master branch.

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:29:47 +02:00
Badlop 2d08dcf11a Fix errors detected by Dialyzer 2010-10-15 13:17:32 +02:00
Badlop 7af47b9dbe Document ejabberd_loglevel using EDoc (EJAB-225) 2010-10-15 13:17:19 +02:00
Andreas Köhler 437da38342 Fix unused variable warning in ejabberd_loglevel 2010-10-15 13:15:52 +02:00
Andreas Köhler 801ee586b7 Add set_custom/2, clear_custom/0 and clear_custom/1 to ejabberd_loglevel 2010-10-15 13:15:50 +02:00
Andreas Köhler 6ff3fda14b Document new loglevel configuration form. 2010-10-15 13:15:49 +02:00
Andreas Köhler cfca2b502a 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:15:48 +02:00
Andreas Köhler e1a4ae8264 Use warning_msg event type for warning log level. 2010-10-15 13:15:46 +02:00
Andreas Köhler 19826858a4 Add warning message and report handlers to ejabberd_logger_h.erl. 2010-10-15 13:15:45 +02:00
Andreas Köhler 0c2677bc50 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:15:44 +02:00
Andreas Köhler d1c1902687 Use records for encoding static loglevel information. 2010-10-15 13:15:42 +02:00
Badlop a5230c46c2 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:15:40 +02:00
Badlop 95ce77f80d Include a gitignore file in the ejabberd git repository (EJAB-1312) 2010-10-14 19:53:31 +02:00
Christophe Romain a93f4f7750 make http-bind restartable (thanks to Andreas Köhler)(EJAB-1318) 2010-10-13 10:54:12 +02:00
Evgeniy Khramtsov ac87749d55 add find_s2s_bridge hook 2010-10-11 18:40:57 +10:00
Evgeniy Khramtsov 50b747041f use one_queue IQ discipline by default 2010-10-05 21:28:45 +10:00
Evgeniy Khramtsov 36df8c9035 implement lifetime for broken hashes 2010-10-05 21:27:28 +10:00
Evgeniy Khramtsov 58a5ed9cdc change caps hook name 2010-10-03 16:04:29 +10:00
Evgeniy Khramtsov 5ea909885e call caps hook when caps is changed 2010-10-03 16:02:50 +10:00
Evgeniy Khramtsov 1f2c9b7971 fixes typo in stop_connection/1 2010-09-28 14:20:02 +10:00
Evgeniy Khramtsov c13940e1de new CAPS processing 2010-09-28 14:18:57 +10:00
Evgeniy Khramtsov 8e5297f4c3 fixes default value for cache_life_time 2010-09-21 04:31:18 +10:00
Andreas Köhler 3278f019cb Add missing needdb check in mod_privacy, to enable blocking by group and subscription again. 2010-09-17 18:48:45 +02:00
Andreas Köhler e2c3925b7d 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 18:48:43 +02:00
Badlop 8a0ccfc401 Support timezone West of UTC (thanks to Edwin Fine)(EJAB-1301) 2010-09-13 12:06:13 +02:00
Evgeniy Khramtsov c29b2fda99 cache lifetime should be converted in microseconds 2010-09-08 02:33:49 +10:00
Evgeniy Khramtsov c75b7b2b12 Implemented dirty (non-atomic) functions; added copyright notice 2010-08-31 18:06:02 +10:00
Badlop c754c91ad1 Add IPv6 support to mod_irc (thanks to Matthias Schiffer)(EJAB-1298) 2010-08-30 23:25:02 +02:00
Evgeniy Khramtsov 6952324509 implemented backend-independed key-value cacheing table; applied to mod_caps.erl first 2010-08-30 14:02:47 +10:00
Badlop 4b5ef8f2ce Add mod_pubsub_odbc to list of ODBC modules (EJAB-1293) 2010-08-21 18:56:01 +02:00
Badlop d87fff1a4c Bugfix http-poll for correctly parsing binary (thanks to Peter Lemenkov) 2010-08-19 17:38:38 +02:00
Evgeniy Khramtsov 3024bb0cbf fixes ampersand escaping (EJAB-1258) 2010-08-19 16:28:31 +10:00
Evgeniy Khramtsov f8dd973373 fixes typo for table copy 2010-08-10 19:42:22 +10:00
Badlop 972440c2ca When user joins non-anonymous room, warn also in presence stanza (EJAB-310) 2010-08-07 20:48:36 +02:00
Badlop b14899d41a Update the 'configure' script 2010-08-07 19:42:56 +02:00
Evgeniy Khramtsov d2d8a09b4a Make MD2 autodetected (EJAB-1285) 2010-08-07 22:04:57 +10:00
Evgeniy Khramtsov 1ea09b09a2 Make xml.c correctly compiles on R14A (EJAB-1288) 2010-08-07 21:06:50 +10:00
Badlop 071c0a1afe Go back to the 2.1.x branch name 2010-08-05 20:39:55 +02:00
Badlop 4ed00c3d1f Fix detection of Erlang R11 and older (thanks to Mathias Ertl)(EJAB-1287) 2010-08-05 20:27:12 +02:00
Evgeniy Khramtsov c9ff370278 Loading ASN.1 driver explicitly to avoid races in LDAP (EJAB-1284) 2010-08-04 19:23:52 +10:00
Badlop 8ab8da82c4 Update ejabberd version number to 2.1.5 2010-08-02 17:38:36 +02:00
Badlop 4b6a42f539 New 2.1.5 release notes 2010-08-02 17:33:16 +02:00
Christophe Romain 8a251ccafe enforce disco features results (thanks to Karim)(EJAB-1033, EJAB-1228, EJAB-1238) 2010-08-02 17:07:23 +02:00
Badlop 550363cd52 Support parallel extauth script (thanks to Jesse Thompson)(EJAB-1280) 2010-07-30 20:33:03 +02:00
Badlop 367353100b Don't say v1.2, because that number is never increased and is confusing 2010-07-28 19:59:39 +02:00
Badlop 5113d28bb4 Return Registered element when account exists (thanks to PioneerMike) 2010-07-28 19:32:42 +02:00
Badlop c8df607173 Fix typo (thanks to Evgeniy Khramtsov) 2010-07-23 00:38:15 +02:00
Badlop c8033833f9 When logging s2s out connection attempt or success, log if TLS is used 2010-07-23 00:25:43 +02:00
Badlop cf4f0dbe6d The command Update now returns meaningful message and exit-status (EJAB-1237) 2010-07-22 16:32:55 +02:00
Evgeniy Khramtsov 8c4884d665 Use driver allocators in iconv_erl.c for reflecting memory in erlang:memory(system) 2010-07-20 15:28:22 +10:00
Evgeniy Khramtsov 26f6eebaa9 Use driver allocators in ejabberd_zlib_drv.c for reflecting memory in erlang:memory(system) 2010-07-20 14:57:23 +10:00
Badlop ac84267b22 Describe what a user gets when he hits the registration_timeout limit 2010-07-19 12:08:02 +02:00
Evgeniy Khramtsov 5030f35558 correct handling of SQL boolean types (EJAB-1275) 2010-07-14 21:23:21 +10:00
Evgeniy Khramtsov d7930d7f82 Use driver allocators in expat for reflecting memory in erlang:memory(system) 2010-07-14 14:19:16 +10:00
Badlop 42ddc297fe Fix my flock change from last friday 2010-07-12 18:53:16 +02:00
Badlop e82db8cc7f Remove ejabberd_debug because p1_prof provides similar and better features 2010-07-12 16:02:52 +02:00
Badlop 10d43c7cc6 Only compile and install p1_prof when: make debugtools=true 2010-07-12 16:02:41 +02:00
Badlop d539fd28c1 Recompile the 'configure' script 2010-07-12 15:18:15 +02:00
Badlop 12e00c57f9 When using OTP R14, use public_key library instead of old ssl (EJAB-953) 2010-07-12 13:57:07 +02:00
Badlop 0c95cf7e61 Mention missing modules in the overview table 2010-07-11 12:14:23 +02:00
Badlop d106f741d9 Some systems delete the lock dir; in such case don't use flock at all 2010-07-09 22:39:13 +02:00
Evgeniy Khramtsov 6c96157d1b Added functions to collect statistics about queues, memory, reductions etc. Several cleanups 2010-07-10 01:36:12 +10:00
Evgeniy Khramtsov a42a012f94 Added new ejabberd profiler 2010-07-05 13:43:44 +10:00
Badlop 7e90d6cf92 Fix print of command result that contains ~ (thanks to Tsukasa Hamano) 2010-07-03 00:42:54 +02:00
Badlop e19ac27803 Show some more room options in the log file 2010-07-02 15:19:54 +02:00
Badlop c100cbedd1 Document the mod_muc option captcha_protected 2010-07-02 13:08:33 +02:00
Evgeniy Khramtsov 4c2e7e38a1 Use ets insead of asking supervisor in ejabberd_odbc_sup:get_pids/1 (Thanks to Alexey Shchepin) 2010-07-02 20:31:42 +10:00
Badlop fa22b23435 Recompile the Guide and Configure 2010-07-01 17:03:36 +02:00
Badlop c3c23a04f6 Requirement of OpenSSL increased from 0.9.6 to 0.9.8 2010-07-01 17:01:13 +02:00
Badlop ae6545989e Fix typo in --enable-transient_supervisors 2010-07-01 16:59:26 +02:00
Badlop baeb3d076e Document the optional --enable-nif 2010-07-01 16:57:47 +02:00
Badlop 0ac5684bf0 Clarify that to use the optional --enable-nif, R13B04 is needed. 2010-07-01 16:51:26 +02:00
Evgeniy Khramtsov 715cc5ea3b New configure option: --enable-nif 2010-07-01 20:54:01 +10:00
Badlop d9e2931ed9 Fix privacy check when serving local Last (thanks to Brian Acton)(EJAB-1271) 2010-06-29 11:58:05 +02:00
Badlop 1531541331 Fix problem when FIREWALL_WINDOW options for erl kernel were used
http://www.ejabberd.im/node/4120
2010-06-28 13:17:55 +02:00
Badlop b7e02cc42e Inform client that SSL session caching is disabled (thanks to Pawel Chmielowski) 2010-06-25 18:33:49 +02:00
Badlop 3ab90c9d3a Don't ask for client certificate when using tls (EJAB-1267) 2010-06-25 18:33:46 +02:00
Badlop 1b7948f50a OpenSSL is required, not optional 2010-06-25 16:56:44 +02:00
Badlop fe23dbd76e When account is deleted, delete also member of stored shared rosters. 2010-06-24 00:02:16 +02:00
Evgeniy Khramtsov 21d2f4efab now admins are able to see private rooms in disco (EJAB-1269) 2010-06-23 17:44:35 +10:00
Evgeniy Khramtsov f66f049ef3 Added support for all hash functions required by XEP-0115 2010-06-22 03:10:41 +10:00
Evgeniy Khramtsov 49dd83e731 Added md2/1 support 2010-06-22 02:56:34 +10:00
Evgeniy Khramtsov 9cd2d5e0cf New OpenSSL functions wrapper: sha224/1, sha256/1, sha384/1, sha512/1 2010-06-22 02:30:16 +10:00
Badlop fab705dc13 Rebuilt the configure script with: autoconf 2010-06-16 16:05:45 +02:00
Peter Lemenkov a84f8bc9ef 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:05:07 +02:00
Peter Lemenkov 2477b735bf 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:05:07 +02:00
Peter Lemenkov 8db328af60 Install dev.html, and guide.pdf if it exists
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
2010-06-16 16:05:07 +02:00
Christophe Romain bc2280be70 remove outdated and useless file, use ejabberdctl.template instead 2010-06-16 12:20:08 +02:00
Badlop a28aaa1fdd Log error when HTTP request has ambiguous Host header (EJAB-1261) 2010-06-16 11:33:17 +02:00
Badlop afa0f4d403 Fix for Erlang R12, that doesn't support: true andalso ok 2010-06-15 22:59:53 +02:00
Jerome Sautret 0e5b930b22 Discard queued requests that are too old (the caller has already got a timeout). 2010-06-11 16:35:45 +02:00
Badlop 7d8f8a7e99 Explain that 2 LDAP connections are established per vhost 2010-06-10 13:58:55 +02:00
Badlop a7924adee9 Fix typo in update_list command (EJAB-1237) 2010-06-07 15:58:16 +02:00
Badlop d4ec7a2f01 New optional BOSH connection attribute process-delay (EJAB-1257) 2010-06-07 13:44:55 +02:00
Badlop e0fab19345 Revert version number from 2.1.4 tag to 2.1.x branch 2010-06-04 11:26:42 +02:00
Evgeniy Khramtsov 4646a5dbb8 fixes wrong SQL escaping when --enable-full-xml is set 2010-06-04 13:31:34 +10:00
266 changed files with 23262 additions and 9999 deletions
+38
View File
@@ -0,0 +1,38 @@
#
# You can add personal rules in your file .git/info/exclude
*.swp
*~
/contrib/extract_translations/extract_translations.beam
/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/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
+4 -4
View File
@@ -9,9 +9,9 @@ To compile ejabberd you need:
- GNU Make
- GCC
- Libexpat 1.95 or higher
- Erlang/OTP R10B-9 or higher. Recommended versions: R12B-5 and R13B04
- OpenSSL 0.9.6 or higher, for STARTTLS, SASL and SSL
encryption. Optional, highly recommended.
- Erlang/OTP R10B-9 or higher. Recommended: R12B-5 and R13B04.
Avoid R14A and R14B.
- 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.
@@ -20,7 +20,7 @@ To compile ejabberd you need:
- GNU Iconv 1.8 or higher, for the IRC Transport
(mod_irc). Optional. Not needed on systems with GNU Libc.
- ImageMagick's Convert program. Optional. For CAPTCHA challenges.
- exmpp 0.9.2 or higher. Optional. For import/export XEP-0227 files.
- exmpp 0.9.6 or higher. Optional. For import/export XEP-0227 files.
1. Compile and install on *nix systems
+3 -3
View File
@@ -2,7 +2,7 @@
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<TITLE>Ejabberd 2.1.4 Developers Guide
<TITLE>Ejabberd 2.1.7 Developers Guide
</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
@@ -49,7 +49,7 @@ TD P{margin:0px;}
<!--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.4 Developers Guide</H1><H3 CLASS="titlerest">Alexey Shchepin<BR>
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.1.7 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">
@@ -170,7 +170,7 @@ manager.</P><!--TOC subsection Local Router-->
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
packet must be sent 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
+1 -1
View File
@@ -141,7 +141,7 @@ session manager, else it is processed depending on it's content.
\subsection{Session Manager}
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
packet must be sent 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.
+2 -2
View File
@@ -2,7 +2,7 @@
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<TITLE>Ejabberd 2.1.4 Feature Sheet
<TITLE>Ejabberd 2.1.7 Feature Sheet
</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
@@ -50,7 +50,7 @@ SPAN{width:20%; float:right; text-align:left; margin-left:auto;}
<!--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.4 Feature Sheet</H1><H3 CLASS="titlerest">Sander Devrieze<BR>
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.1.7 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">
+500 -155
View File
File diff suppressed because it is too large Load Diff
+556 -56
View File
@@ -66,6 +66,7 @@
\newcommand{\module}[1]{\texttt{#1}}
\newcommand{\modadhoc}{\module{mod\_adhoc}}
\newcommand{\modannounce}{\module{mod\_announce}}
\newcommand{\modblocking}{\module{mod\_blocking}}
\newcommand{\modcaps}{\module{mod\_caps}}
\newcommand{\modconfigure}{\module{mod\_configure}}
\newcommand{\moddisco}{\module{mod\_disco}}
@@ -80,6 +81,7 @@
\newcommand{\modoffline}{\module{mod\_offline}}
\newcommand{\modofflineodbc}{\module{mod\_offline\_odbc}}
\newcommand{\modping}{\module{mod\_ping}}
\newcommand{\modprescounter}{\module{mod\_pres\_counter}}
\newcommand{\modprivacy}{\module{mod\_privacy}}
\newcommand{\modprivacyodbc}{\module{mod\_privacy\_odbc}}
\newcommand{\modprivate}{\module{mod\_private}}
@@ -88,10 +90,12 @@
\newcommand{\modpubsub}{\module{mod\_pubsub}}
\newcommand{\modpubsubodbc}{\module{mod\_pubsub\_odbc}}
\newcommand{\modregister}{\module{mod\_register}}
\newcommand{\modregisterweb}{\module{mod\_register\_web}}
\newcommand{\modroster}{\module{mod\_roster}}
\newcommand{\modrosterodbc}{\module{mod\_roster\_odbc}}
\newcommand{\modservicelog}{\module{mod\_service\_log}}
\newcommand{\modsharedroster}{\module{mod\_shared\_roster}}
\newcommand{\modsharedrosterldap}{\module{mod\_shared\_roster\_ldap}}
\newcommand{\modsic}{\module{mod\_sic}}
\newcommand{\modstats}{\module{mod\_stats}}
\newcommand{\modtime}{\module{mod\_time}}
@@ -311,14 +315,15 @@ To compile \ejabberd{} on a `Unix-like' operating system, you need:
\item GCC
\item Libexpat 1.95 or higher
\item Erlang/OTP R10B-9 or higher. The recommended versions are R12B-5 and R13B04.
\item OpenSSL 0.9.6 or higher, for STARTTLS, SASL and SSL encryption. Optional, highly recommended.
Don't use R14A or R14B because \footahref{http://www.erlang.org/cgi-bin/ezmlm-cgi/4/54598}{they have a bug}.
\item OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption.
\item Zlib 1.2.3 or higher, for Stream Compression support (\xepref{0138}). Optional.
\item Erlang mysql library. Optional. For MySQL authentication or storage. See section \ref{compilemysql}.
\item Erlang pgsql library. Optional. For PostgreSQL authentication or storage. See section \ref{compilepgsql}.
\item PAM library. Optional. For Pluggable Authentication Modules (PAM). See section \ref{pam}.
\item GNU Iconv 1.8 or higher, for the IRC Transport (mod\_irc). Optional. Not needed on systems with GNU Libc. See section \ref{modirc}.
\item ImageMagick's Convert program. Optional. For CAPTCHA challenges. See section \ref{captcha}.
\item exmpp 0.9.2 or higher. Optional. For import/export user data with \xepref{0227} XML files.
\item exmpp 0.9.6 or higher. Optional. For import/export user data with \xepref{0227} XML files.
\end{itemize}
\makesubsection{download}{Download Source Code}
@@ -382,6 +387,10 @@ Some options that you may be interested in modifying:
\titem{--disable-transient-supervisors}
Disable the use of Erlang/OTP supervision for transient processes.
\titem{--enable-nif}
Replaces some critical Erlang functions with equivalents written in C to improve performance.
This feature requires Erlang/OTP R13B04 or higher.
\end{description}
\makesubsection{install}{Install}
@@ -817,7 +826,7 @@ The available modules, their purpose and the options allowed by each one are:
\titem{\texttt{ejabberd\_http}}
Handles incoming HTTP connections.\\
Options: \texttt{captcha}, \texttt{certfile}, \texttt{http\_bind}, \texttt{http\_poll},
\texttt{request\_handlers}, \texttt{tls}, \texttt{web\_admin}\\
\texttt{request\_handlers}, \texttt{tls}, \texttt{trusted\_proxies}, \texttt{web\_admin}\\
\end{description}
@@ -939,6 +948,10 @@ This is a detailed description of each option allowed by the listening modules:
which can be enabled in \ejabberd{} with the option \term{starttls}.
If this option is set, you should also set the \option{certfile} option.
The option \term{tls} can also be used in \term{ejabberd\_http} to support HTTPS.
\titem{\{trusted\_proxies, all | [IpString]\}} \ind{options!trusted\_proxies}
Specify what proxies are trusted when an HTTP request contains the header \term{X-Forwarded-For}
You can specify \term{all} to allow all proxies, or specify a list of IPs in string format.
The default value is: \term{["127.0.0.1"]}
\titem{web\_admin} \ind{options!web\_admin}\ind{web admin}This option
enables the Web Admin for \ejabberd{} administration which is available
at \verb|http://server:port/admin/|. Login and password are the username and
@@ -951,14 +964,17 @@ This is a detailed description of each option allowed by the listening modules:
There are some additional global options that can be specified in the ejabberd configuration file (outside \term{listen}):
\begin{description}
\titem{\{s2s\_use\_starttls, true|false\}}
\ind{options!s2s\_use\_starttls}\ind{STARTTLS}This option defines whether to
use STARTTLS for s2s connections.
\titem{\{s2s\_use\_starttls, false|optional|required|required\_trusted\}}
\ind{options!s2s\_use\_starttls}\ind{STARTTLS}This option defines if
s2s connections don't use STARTTLS encryption; if STARTTLS can be used optionally;
if STARTTLS is required to establish the connection;
or if STARTTLS is required and the remote certificate must be valid and trusted.
The default value is to not use STARTTLS: \term{false}.
\titem{\{s2s\_certfile, Path\}} \ind{options!s2s\_certificate}Full path to a
file containing a SSL certificate.
\titem{\{domain\_certfile, Domain, Path\}} \ind{options!domain\_certfile}
Full path to the file containing the SSL certificate for a specific domain.
\titem{\{outgoing\_s2s\_options, Methods, Timeout\}} \ind{options!outgoing\_s2s\_options}
\titem{\{outgoing\_s2s\_options, [Family, ...], Timeout\}} \ind{options!outgoing\_s2s\_options}
Specify which address families to try, in what order, and connect timeout in milliseconds.
By default it first tries connecting with IPv4, if that fails it tries using IPv6,
with a timeout of 10000 milliseconds.
@@ -1013,7 +1029,7 @@ However, the c2s and s2s connections to the domain \term{example.com} use the fi
\item Port 5269 listens for s2s connections with STARTTLS. The socket is set for IPv6 instead of IPv4.
\item Port 3478 listens for STUN requests over UDP.
\item Port 5280 listens for HTTP requests, and serves the HTTP Poll service.
\item Port 5281 listens for HTTP requests, and serves the Web Admin using HTTPS as explained in
\item Port 5281 listens for HTTP requests, using HTTPS to serve HTTP-Bind (BOSH) and the Web Admin as explained in
section~\ref{webadmin}. The socket only listens connections to the IP address 127.0.0.1.
\end{itemize}
\begin{verbatim}
@@ -1042,13 +1058,15 @@ However, the c2s and s2s connections to the domain \term{example.com} use the fi
]},
{{5281, "127.0.0.1"}, ejabberd_http, [
web_admin,
http_bind,
tls, {certfile, "/etc/ejabberd/server.pem"},
]}
]
}.
{s2s_use_starttls, true}.
{s2s_use_starttls, optional}.
{s2s_certfile, "/etc/ejabberd/server.pem"}.
{domain_certfile, "example.com", "/etc/ejabberd/example_com.pem"}.
{outgoing_s2s_options, [ipv4, ipv6], 10000}.
\end{verbatim}
In this example, the following configuration defines that:
@@ -1057,7 +1075,7 @@ In this example, the following configuration defines that:
on port 5223 (SSL, IP 192.168.0.1 and fdca:8ab6:a243:75ef::1) and denied
for the user called `\term{bad}'.
\item s2s connections are listened for on port 5269 (all IPv4 addresses)
with STARTTLS for secured traffic enabled.
with STARTTLS for secured traffic strictly required, and the certificates are verified.
Incoming and outgoing connections of remote XMPP servers are denied,
only two servers can connect: "jabber.example.org" and "example.com".
\item Port 5280 is serving the Web Admin and the HTTP Polling service
@@ -1138,7 +1156,7 @@ In this example, the following configuration defines that:
{service_check_from, false}]}
]
}.
{s2s_use_starttls, true}.
{s2s_use_starttls, required_trusted}.
{s2s_certfile, "/path/to/ssl.pem"}.
{s2s_default_policy, deny}.
{{s2s_host,"jabber.example.org"}, allow}.
@@ -1235,6 +1253,10 @@ These are the specific options:
Indicate in this option the full path to the external authentication script.
The script must be executable by ejabberd.
\titem{\{extauth\_instances, Integer\}}
Indicate how many instances of the script to run simultaneously to serve authentication in the virtual host.
The default value is the minimum number: 1.
\titem{\{extauth\_cache, false|CacheTimeInteger\}}
The value \term{false} disables the caching feature, this is the default.
The integer \term{0} (zero) enables caching for statistics, but doesn't use that cached information to authenticate users.
@@ -1246,11 +1268,13 @@ These are the specific options:
If caching is enabled, \term{mod\_last} or \term{mod\_last\_odbc} must be enabled also in that vhost.
\end{description}
This example sets external authentication, the extauth script, and enables caching for 10 minutes:
This example sets external authentication, the extauth script, enables caching for 10 minutes,
and starts three instances of the script for each virtual host defined in ejabberd:
\begin{verbatim}
{auth_method, [external]}.
{extauth_program, "/etc/ejabberd/JabberAuth.class.php"}.
{extauth_cache, 600}.
{extauth_instances, 3}.
\end{verbatim}
\makesubsubsection{saslanonymous}{SASL Anonymous and Anonymous Login}
@@ -1452,7 +1476,7 @@ declarations of ACLs in the configuration file have the following syntax:
with a name that matches \term{UserRegexp} at any server that matches
\term{ServerRegexp}. Example:
\begin{verbatim}
{acl, yohzik, {node_regexp, "^yohzik$", "^example.(com|org)$"}}.
{acl, yozhik, {node_regexp, "^yozhik$", "^example.(com|org)$"}}.
\end{verbatim}
\titem{\{user\_glob, Glob\}}
\titem{\{user\_glob, Glob, Server\}}
@@ -1611,11 +1635,14 @@ The configurable options are:
\titem{\{captcha\_cmd, Path\}}
Full path to a script that generates the image.
The default value is an empty string: \term{""}
\titem{\{captcha\_host, Host\}}
Host part of the URL sent to the user.
You can include the port number.
The URL sent to the user is formed by: \term{http://Host/captcha/}
The default value is the first hostname configured.
\titem{\{captcha\_host, ProtocolHostPort\}}
ProtocolHostPort is a string with the host, and optionally the Protocol and Port number.
It must identify where ejabberd listens for CAPTCHA requests.
The URL sent to the user is formed by: \term{Protocol://Host:Port/captcha/}
The default value is: protocol \term{http}, the first hostname configured, and port \term{80}.
If you specify a port number that does not match exactly an ejabberd listener
(because you are using a reverse proxy or other port-forwarding tool),
then you must specify the transfer protocol, as seen in the example below.
\end{description}
Additionally, an \term{ejabberd\_http} listener must be enabled with the \term{captcha} option.
@@ -1627,6 +1654,8 @@ Example configuration:
{captcha_cmd, "/lib/ejabberd/priv/bin/captcha.sh"}.
{captcha_host, "example.org:5280"}.
%% {captcha_host, "https://example.org:443"}.
%% {captcha_host, "http://example.com"}.
{listen,
[
@@ -1839,6 +1868,7 @@ The following LDAP servers are tested with \ejabberd{}:
\item \footahref{http://www.microsoft.com/activedirectory/}{Active Directory}
(see section~\ref{ad})
\item \footahref{http://www.openldap.org/}{OpenLDAP}
\item \footahref{http://www.communigate.com/}{CommuniGate Pro}
\item Normally any LDAP compatible server should work; inform us about your
success with a not-listed server so that we can list it here.
\end{itemize}
@@ -2195,8 +2225,7 @@ module loaded!
\ind{databases!LDAP}
\ejabberd{} has built-in LDAP support. You can authenticate users against LDAP
server and use LDAP directory as vCard storage. Shared rosters are not supported
yet.
server and use LDAP directory as vCard storage.
Usually \ejabberd{} treats LDAP as a read-only storage:
it is possible to consult data, but not possible to
@@ -2208,6 +2237,9 @@ and LDAP server supports
\makesubsubsection{ldapconnection}{Connection}
Two connections are established to the LDAP server per vhost,
one for authentication and other for regular calls.
Parameters:
\begin{description}
\titem{\{ldap\_servers, [Servers, ...]\}} \ind{options!ldap\_server}List of IP addresses or DNS names of your
@@ -2242,11 +2274,12 @@ Example:
{ldap_password, "secret"}.
\end{verbatim}
Note that current LDAP implementation does not support SASL authentication.
\makesubsubsection{ldapauth}{Authentication}
You can authenticate users against an LDAP directory. Available options are:
You can authenticate users against an LDAP directory.
Note that current LDAP implementation does not support SASL authentication.
Available options are:
\begin{description}
\titem{\{ldap\_base, Base\}}\ind{options!ldap\_base}LDAP base directory which stores
@@ -2493,10 +2526,13 @@ The following table lists all modules included in \ejabberd{}.
\hline
\hline \modadhoc{} & Ad-Hoc Commands (\xepref{0050}) & \\
\hline \ahrefloc{modannounce}{\modannounce{}} & Manage announcements & recommends \modadhoc{} \\
\hline \modblocking{} & Simple Communications Blocking (\xepref{0191}) & \modprivacy{} \\
\hline \modcaps{} & Entity Capabilities (\xepref{0115}) & \\
\hline \modconfigure{} & Server configuration using Ad-Hoc & \modadhoc{} \\
\hline \ahrefloc{moddisco}{\moddisco{}} & Service Discovery (\xepref{0030}) & \\
\hline \ahrefloc{modecho}{\modecho{}} & Echoes XMPP stanzas & \\
\hline \ahrefloc{modhttpbind}{\modhttpbind{}} & XMPP over Bosh service (HTTP Binding) & \\
\hline \ahrefloc{modhttpfileserver}{\modhttpfileserver{}} & Small HTTP file server & \\
\hline \ahrefloc{modirc}{\modirc{}} & IRC transport & \\
\hline \ahrefloc{modlast}{\modlast{}} & Last Activity (\xepref{0012}) & \\
\hline \ahrefloc{modlast}{\modlastodbc{}} & Last Activity (\xepref{0012}) & supported DB (*) \\
@@ -2505,19 +2541,23 @@ The following table lists all modules included in \ejabberd{}.
\hline \ahrefloc{modoffline}{\modoffline{}} & Offline message storage (\xepref{0160}) & \\
\hline \ahrefloc{modoffline}{\modofflineodbc{}} & Offline message storage (\xepref{0160}) & supported DB (*) \\
\hline \ahrefloc{modping}{\modping{}} & XMPP Ping and periodic keepalives (\xepref{0199}) & \\
\hline \ahrefloc{modprivacy}{\modprivacy{}} & Blocking Communication (XMPP IM) & \\
\hline \ahrefloc{modprivacy}{\modprivacyodbc{}} & Blocking Communication (XMPP IM) & supported DB (*) \\
\hline \ahrefloc{modprescounter}{\modprivacy{}} & Detect presence subscription flood & \\
\hline \ahrefloc{modprivacy}{\modprivacy{}} & Blocking Communication (\xepref{0016}) & \\
\hline \ahrefloc{modprivacy}{\modprivacyodbc{}} & Blocking Communication (\xepref{0016}) & supported DB (*) \\
\hline \ahrefloc{modprivate}{\modprivate{}} & Private XML Storage (\xepref{0049}) & \\
\hline \ahrefloc{modprivate}{\modprivateodbc{}} & Private XML Storage (\xepref{0049}) & supported DB (*) \\
\hline \ahrefloc{modproxy}{\modproxy{}} & SOCKS5 Bytestreams (\xepref{0065}) & \\
\hline \ahrefloc{modpubsub}{\modpubsub{}} & Pub-Sub (\xepref{0060}), PEP (\xepref{0163}) & \modcaps{} \\
\hline \ahrefloc{modpubsub}{\modpubsubodbc{}} & Pub-Sub (\xepref{0060}), PEP (\xepref{0163}) & supported DB (*) and \modcaps{} \\
\hline \ahrefloc{modregister}{\modregister{}} & In-Band Registration (\xepref{0077}) & \\
\hline \ahrefloc{modregisterweb}{\modregisterweb{}} & Web for Account Registrations & \\
\hline \ahrefloc{modroster}{\modroster{}} & Roster management (XMPP IM) & \\
\hline \ahrefloc{modroster}{\modrosterodbc{}} & Roster management (XMPP IM) & supported DB (*) \\
\hline \ahrefloc{modservicelog}{\modservicelog{}} & Copy user messages to logger service & \\
\hline \ahrefloc{modsharedroster}{\modsharedroster{}} & Shared roster management & \modroster{} or \\
& & \modrosterodbc\\
\hline \ahrefloc{modsharedrosterldap}{\modsharedrosterldap{}} & LDAP Shared roster management & \modroster{} or \\
& & \modrosterodbc\\
\hline \ahrefloc{modsic}{\modsic{}} & Server IP Check (\xepref{0279}) & \\
\hline \ahrefloc{modstats}{\modstats{}} & Statistics Gathering (\xepref{0039}) & \\
\hline \ahrefloc{modtime}{\modtime{}} & Entity Time (\xepref{0202}) & \\
@@ -2544,8 +2584,8 @@ You can see which database backend each module needs by looking at the suffix:
\end{itemize}
If you want to,
it is possible to use a relational database to store pieces of
information. You can do this by changing the module name to a name with an
it is possible to use a relational database to store the tables created by some ejabberd modules.
You can do this by changing the module name to a name with an
\term{\_odbc} suffix in \ejabberd{} config file. You can use a relational
database for the following data:
@@ -2558,6 +2598,7 @@ database for the following data:
\item Users' VCARD: Use \term{mod\_vcard\_odbc} instead of \term{mod\_vcard}.
\item Private XML storage: Use \term{mod\_private\_odbc} instead of \term{mod\_private}.
\item User rules for blocking communications: Use \term{mod\_privacy\_odbc} instead of \term{mod\_privacy}.
\item Pub-Sub nodes, items and subscriptions: Use \term{mod\_pubsub\_odbc} instead of \term{mod\_pubsub}.
\end{itemize}
You can find more
@@ -2586,15 +2627,16 @@ The syntax is:
Possible \term{Value} are:
\begin{description}
\titem{no\_queue} All queries of a namespace with this processing discipline are
processed immediately. This also means that no other packets can be processed
processed directly. This means that the XMPP connection that sends this IQ query gets blocked:
no other packets can be processed
until this one has been completely processed. Hence this discipline is not
recommended if the processing of a query can take a relatively long time.
\titem{one\_queue} In this case a separate queue is created for the processing
of IQ queries of a namespace with this discipline. In addition, the processing
of this queue is done in parallel with that of other packets. This discipline
is most recommended.
\titem{\{queues, N\}} N separate queues are created to process the
queries. The queries are thus process in parallel, but in a
\titem{\{queues, N\}} N separate queues are created to process the
queries. The queries are thus processed in parallel, but in a
controlled way.
\titem{parallel} For every packet with this discipline a separate Erlang process
is spawned. Consequently, all these packets are processed in parallel.
@@ -3010,7 +3052,7 @@ End user information:
to join a channel, and to set custom IRC username and encoding.
\item When using a popular \XMPP{} server, it can occur that no
connection can be achieved with some IRC servers because they limit the
number of conections from one IP.
number of connections from one IP.
\end{itemize}
Options:
@@ -3019,7 +3061,7 @@ Options:
\titem{\{access, AccessName\}} \ind{options!access}This option can be used to specify who
may use the IRC transport (default value: \term{all}).
\titem{\{default\_encoding, Encoding\}} \ind{options!defaultencoding}Set the default IRC encoding.
Default value: \term{"koi8-r"}
Default value: \term{"iso8859-1"}
\end{description}
Examples:
@@ -3193,6 +3235,10 @@ Module options:
\titem{\{anonymous, true|false\}} The room is anonymous:
occupants don't see the real JIDs of other occupants.
Note that the room moderators can always see the real JIDs of the occupants.
\titem{\{captcha\_protected, false\}}
When a user tries to join a room where he has no affiliation (not owner, admin or member),
the room requires him to fill a CAPTCHA challenge (see section \ref{captcha})
in order to accept her join in the room.
\titem{\{logging, false|true\}} The public messages are logged using \term{mod\_muc\_log}.
\titem{\{max\_users, 200\}} Maximum number of occupants in the room.
\titem{\{members\_by\_default, true|false\}} The occupants that enter the room are participants by default, so they have 'voice'.
@@ -3521,6 +3567,39 @@ and if a client does not answer to the ping in less than 32 seconds, its connect
]}.
\end{verbatim}
\makesubsection{modprescounter}{\modprescounter{}}
\ind{modules!\modprescounter{}}
This module detects flood/spam in presence subscription stanza traffic.
If a user sends or receives more of those stanzas in a time interval,
the exceeding stanzas are silently dropped, and warning is logged.
Configuration options:
\begin{description}
\titem{\{count, StanzaNumber\}}\ind{options!count}
The number of subscription presence stanzas
(subscribe, unsubscribe, subscribed, unsubscribed)
allowed for any direction (input or output)
per time interval.
Please note that two users subscribing to each other usually generate
4 stanzas, so the recommended value is 4 or more.
The default value is: 5.
\titem{\{interval, Seconds\}}\ind{options!interval}
The time interval defined in seconds.
The default value is 60.
\end{description}
This example enables the module, and allows up to 5 presence subscription stanzas
to be sent or received by the users in 60 seconds:
\begin{verbatim}
{modules,
[
...
{mod_pres_counter, [{count, 5}, {interval, 60}]},
...
]}.
\end{verbatim}
\makesubsection{modprivacy}{\modprivacy{}}
\ind{modules!\modprivacy{}}\ind{Blocking Communication}\ind{Privacy Rules}\ind{protocols!RFC 3921: XMPP IM}
@@ -3745,15 +3824,28 @@ enables end users to use a \XMPP{} client to:
Options:
\begin{description}
\titem{\{access, AccessName\}} \ind{options!access}This option can be configured to specify
rules to restrict registration. If a rule returns `deny' on the requested
user name, registration for that user name is denied. (there are no
restrictions by default).
\titem{\{access, AccessName\}} \ind{options!access}
Specify rules to restrict what usernames can be registered and unregistered.
If a rule returns `deny' on the requested username,
registration and unregistration of that user name is denied.
There are no restrictions by default.
\titem{\{access\_from, AccessName\}} \ind{options!access\_from}By default, \ejabberd{}
doesn't allow to register new accounts from s2s or existing c2s sessions. You can
change it by defining access rule in this option. Use with care: allowing registration
from s2s leads to uncontrolled massive accounts creation by rogue users.
\titem{\{welcome\_message, Message\}} \ind{options!welcomem}Set a welcome message that
\titem{\{captcha\_protected, false|true\}} \ind{options!captcha\_protected}
Protect registrations with CAPTCHA (see section \ref{captcha}). The default is \term{false}.
\titem{\{ip\_access, [ \{allow|deny, IPaddress\}, ...]\}} \ind{options!ip\_access}
Define rules to allow or deny account registration depending
in the IP address of the XMPP client.
If there is no matching IP mask, the default rule is ``allow''.
IPv6 addresses are supported, but not tested.
The default option value is an empty list: \term{[]}.
\titem{\{password\_strength, Entropy\}} \ind{options!password\_strength}
This option sets the minimum informational entropy for passwords. The value \term{Entropy}
is a number of bits of entropy. The recommended minimum is 32 bits.
The default is 0, i.e. no checks are performed.
\titem{\{welcome\_message, \{Subject, Body\}\}} \ind{options!welcomem}Set a welcome message that
is sent to each newly registered account. The first string is the subject, and
the second string is the message body.
In the body you can set a newline with the characters: \verb|\n|
@@ -3765,16 +3857,19 @@ from s2s leads to uncontrolled massive accounts creation by rogue users.
This module reads also another option defined globally for the server:
\term{\{registration\_timeout, Timeout\}}. \ind{options!registratimeout}
This option limits the frequency of registration from a given IP or username.
So, a user can't register a new account from the same IP address or JID during
this number of seconds after previous registration.
Timeout is expressed in seconds, and must be an integer.
So, a user that tries to register a new account from the same IP address or JID during
this number of seconds after his previous registration
will receive an error \term{resource-constraint} with the explanation:
``Users are not allowed to register accounts so quickly''.
The timeout is expressed in seconds, and it must be an integer.
To disable this limitation,
instead of an integer put a word like: \term{infinity}.
Default value: 600 seconds.
Examples:
\begin{itemize}
\item Next example prohibits the registration of too short account names:
\item Next example prohibits the registration of too short account names,
and allows to create accounts only to clients of the local network:
\begin{verbatim}
{acl, shortname, {user_glob, "?"}}.
{acl, shortname, {user_glob, "??"}}.
@@ -3787,7 +3882,10 @@ Examples:
{modules,
[
...
{mod_register, [{access, register}]},
{mod_register, [{access, register},
{ip_access, [{allow, "127.0.0.0/8"},
{deny, "0.0.0.0/0"}]}
]},
...
]}.
\end{verbatim}
@@ -3832,6 +3930,49 @@ Also define a registration timeout of one hour:
\end{verbatim}
\end{itemize}
\makesubsection{modregisterweb}{\modregisterweb{}}
\ind{modules!\modregisterweb{}}
This module provides a web page where people can:
\begin{itemize}
\item Register a new account on the server.
\item Change the password from an existing account on the server.
\item Delete an existing account on the server.
\end{itemize}
This module supports CAPTCHA image to register a new account.
To enable this feature, configure the options captcha\_cmd and captcha\_host.
Options:
\begin{description}
\titem{\{registration\_watchers, [ JID, ...]\}} \ind{options!rwatchers}This option defines a
list of JIDs which will be notified each time a new account is registered.
\end{description}
This example configuration shows how to enable the module and the web handler:
\begin{verbatim}
{listen, [
...
{5281, ejabberd_http, [
tls,
{certfile, "/etc/ejabberd/certificate.pem"},
register
]},
...
]}.
{modules,
[
...
{mod_register_web, []},
...
]}.
\end{verbatim}
The users can visit this page: https://localhost:5281/register/
It is important to include the last / character in the URL,
otherwise the subpages URL will be incorrect.
\makesubsection{modroster}{\modroster{}}
\ind{modules!\modroster{}}\ind{roster management}\ind{protocols!RFC 3921: XMPP IM}
@@ -3852,7 +3993,8 @@ Options:
This option does not affect the client in any way.
This option is only useful if Roster Versioning is enabled.
This option is disabled by default.
Important: if you use \modsharedroster, you must disable this option.
Important: if you use \modsharedroster{} or \modsharedrosterldap{},
you must disable this option.
\end{description}
This example configuration enables Roster Versioning with storage of current id:
@@ -3924,11 +4066,13 @@ has a unique identification and the following parameters:
\item[Name] The name of the group, which will be displayed in the roster.
\item[Description] The description of the group. This parameter does not affect
anything.
\item[Members] A list of full JIDs of group members, entered one per line in
\item[Members] A list of JIDs of group members, entered one per line in
the Web Admin.
To put as members all the registered users in the virtual hosts,
you can use the special directive: @all@.
Note that this directive is designed for a small server with just a few hundred users.
The special member directive \term{@all@}
represents all the registered users in the virtual host;
which is only recommended for a small server with just a few hundred users.
The special member directive \term{@online@}
represents the online users in the virtual host.
\item[Displayed groups] A list of groups that will be in the rosters of this
group's members.
\end{description}
@@ -4014,6 +4158,349 @@ Examples:
\end{table}
\end{itemize}
\makesubsection{modsharedrosterldap}{\modsharedrosterldap{}}
\ind{modules!\modsharedrosterldap{}}\ind{shared roster groups ldap}
This module lets the server administrator
automatically populate users' rosters (contact lists) with entries based on
users and groups defined in an LDAP-based directory.
\makesubsubsection{msrlconfigparams}{Configuration parameters}
The module accepts the following configuration parameters. Some of them, if
unspecified, default to the values specified for the top level of
configuration. This lets you avoid specifying, for example, the bind password,
in multiple places.
\makeparagraph{msrlfilters}{Filters}
These parameters specify LDAP filters used to query for shared roster information.
All of them are run against the \verb|ldap_base|.
\begin{description}
\titem{{\tt ldap\_rfilter}}
So called ``Roster Filter''. Used to find names of all ``shared roster'' groups.
See also the \verb|ldap_groupattr| parameter.
If unspecified, defaults to the top-level parameter of the same name.
You {\em must} specify it in some place in the configuration, there is no default.
\titem{{\tt ldap\_ufilter}}
``User Filter'' -- used for retrieving the human-readable name of roster
entries (usually full names of people in the roster).
See also the parameters \verb|ldap_userdesc| and \verb|ldap_useruid|.
If unspecified, defaults to the top-level parameter of the same name.
If that one also is unspecified, then the filter is assembled from values of
other parameters as follows (\verb|[ldap_SOMETHING]| is used to mean ``the
value of the configuration parameter {\tt ldap\_SOMETHING}''):
\begin{verbatim}
(&(&([ldap_memberattr]=[ldap_memberattr_format])([ldap_groupattr]=%g))[ldap_filter])
\end{verbatim}
Subsequently {\tt \%u} and {\tt \%g} are replaced with a {\tt *}. This means
that given the defaults, the filter sent to the LDAP server is would be
\verb|(&(memberUid=*)(cn=*))|. If however the {\tt ldap\_memberattr\_format}
is something like \verb|uid=%u,ou=People,o=org|, then the filter will be
\verb|(&(memberUid=uid=*,ou=People,o=org)(cn=*))|.
\titem{{\tt ldap\_gfilter}}
``Group Filter'' -- used when retrieving human-readable name (a.k.a.
``Display Name'') and the members of a group.
See also the parameters \verb|ldap_groupattr|, \verb|ldap_groupdesc| and \verb|ldap_memberattr|.
If unspecified, defaults to the top-level parameter of the same name.
If that one also is unspecified, then the filter is constructed exactly in the
same way as {\tt User Filter}.
\titem{{\tt ldap\_filter}}
Additional filter which is AND-ed together with {\tt User Filter} and {\tt
Group Filter}.
If unspecified, defaults to the top-level parameter of the same name. If that
one is also unspecified, then no additional filter is merged with the other
filters.
\end{description}
Note that you will probably need to manually define the {\tt User} and {\tt
Group Filter}s (since the auto-assembled ones will not work) if:
\begin{itemize}
\item your {\tt ldap\_memberattr\_format} is anything other than a simple {\tt \%u},
\item {\bf and} the attribute specified with {\tt ldap\_memberattr} does not support substring matches.
\end{itemize}
An example where it is the case is OpenLDAP and {\tt (unique)MemberName} attribute from the {\tt groupOf(Unique)Names} objectClass.
A symptom of this problem is that you will see messages such as the following in your {\tt slapd.log}:
\begin{verbatim}
get_filter: unknown filter type=130
filter="(&(?=undefined)(?=undefined)(something=else))"
\end{verbatim}
\makesubsubsection{msrlattrs}{Attributes}
These parameters specify the names of the attributes which hold interesting data
in the entries returned by running filters specified in
section~\ref{msrlfilters}.
\begin{description}
\titem{{\tt ldap\_groupattr}}
The name of the attribute that holds the group name, and that is used to differentiate between them.
Retrieved from results of the ``Roster Filter'' and ``Group Filter''.
Defaults to {\tt cn}.
\titem{{\tt ldap\_groupdesc}}
The name of the attribute which holds the human-readable group name in the
objects you use to represent groups.
Retrieved from results of the ``Group Filter''.
Defaults to whatever {\tt ldap\_groupattr} is set.
\titem{{\tt ldap\_memberattr}}
The name of the attribute which holds the IDs of the members of a group.
Retrieved from results of the ``Group Filter''.
Defaults to {\tt memberUid}.
The name of the attribute differs depending on the {\tt objectClass} you use
for your group objects, for example:
\begin{description}
\item{{\tt posixGroup}} $\rightarrow{}$ {\tt memberUid}
\item{{\tt groupOfNames}} $\rightarrow{}$ {\tt member}
\item{{\tt groupOfUniqueNames}} $\rightarrow{}$ {\tt uniqueMember}
\end{description}
\titem{{\tt ldap\_userdesc}}
The name of the attribute which holds the human-readable user name.
Retrieved from results of the ``User Filter''.
Defaults to {\tt cn}.
\titem{{\tt ldap\_useruid}}
The name of the attribute which holds the ID of a roster item. Value of this
attribute in the roster item objects needs to match the ID retrieved from the
{\tt ldap\_memberattr} attribute of a group object.
Retrieved from results of the ``User Filter''.
Defaults to {\tt cn}.
\end{description}
\makesubsubsection{msrlcontrolparams}{Control parameters}
These paramters control the behaviour of the module.
\begin{description}
\titem{{\tt ldap\_memberattr\_format}}
A globbing format for extracting user ID from the value of the attribute named by
\verb|ldap_memberattr|.
Defaults to {\tt \%u}, which means that the whole value is the member ID. If
you change it to something different, you may also need to specify the User
and Group Filters manually --- see section~\ref{msrlfilters}.
\titem{{\tt ldap\_memberattr\_format\_re}}
A regex for extracting user ID from the value of the attribute named by
\verb|ldap_memberattr|.
An example value {\tt "CN=($\backslash{}\backslash{}$w*),(OU=.*,)*DC=company,DC=com"} works for user IDs such as the following:
\begin{itemize}
\item \texttt{CN=Romeo,OU=Montague,DC=company,DC=com}
\item \texttt{CN=Abram,OU=Servants,OU=Montague,DC=company,DC=com}
\item \texttt{CN=Juliet,OU=Capulet,DC=company,DC=com}
\item \texttt{CN=Peter,OU=Servants,OU=Capulet,DC=company,DC=com}
\end{itemize}
In case:
\begin{itemize}
\item the option is unset,
\item or the {\tt re} module in unavailable in the current Erlang environment,
\item or the regular expression does not compile,
\end{itemize}
then instead of a regular expression, a simple format specified by {\tt
ldap\_memberattr\_format} is used. Also, in the last two cases an error
message is logged during the module initialization.
Also, note that in all cases {\tt ldap\_memberattr\_format} (and {\em not} the
regex version) is used for constructing the default ``User/Group Filter'' ---
see section~\ref{msrlfilters}.
\titem{{\tt ldap\_auth\_check}}
Whether the module should check (via the ejabberd authentication subsystem)
for existence of each user in the shared LDAP roster. See
section~\ref{msrlconfigroster} form more information. Set to {\tt off} if you
want to disable the check.
Defaults to {\tt on}.
\titem{{\tt ldap\_user\_cache\_validity}}
Number of seconds for which the cache for roster item full names is considered
fresh after retrieval. 300 by default. See section~\ref{msrlconfigroster} on
how it is used during roster retrieval.
\titem{{\tt ldap\_group\_cache\_validity}}
Number of seconds for which the cache for group membership is considered
fresh after retrieval. 300 by default. See section~\ref{msrlconfigroster} on
how it is used during roster retrieval.
\end{description}
\makesubsubsection{msrlconnparams}{Connection parameters}
The module also accepts the connection parameters, all of which default to the
top-level parameter of the same name, if unspecified. See~\ref{ldapconnection}
for more information about them.
\makesubsubsection{msrlconfigroster}{Retrieving the roster}
When the module is called to retrieve the shared roster for a user, the
following algorithm is used:
\begin{enumerate}
\item \label{step:rfilter} A list of names of groups to display is created: the {\tt Roster Filter}
is run against the base DN, retrieving the values of the attribute named by
{\tt ldap\_groupattr}.
\item Unless the group cache is fresh (see the {\tt
ldap\_group\_cache\_validity} option), it is refreshed:
\begin{enumerate}
\item Information for all groups is retrieved using a single query: the {\tt
Group Filter} is run against the Base DN, retrieving the values of attributes
named by {\tt ldap\_groupattr} (group ID), {\tt ldap\_groupdesc} (group
``Display Name'') and {\tt ldap\_memberattr} (IDs of group members).
\item group ``Display Name'', read from the attribute named by {\tt
ldap\_groupdesc}, is stored in the cache for the given group
\item the following processing takes place for each retrieved value of
attribute named by {\tt ldap\_memberattr}:
\begin{enumerate}
\item the user ID part of it is extracted using {\tt
ldap\_memberattr\_format(\_re)},
\item then (unless {\tt ldap\_auth\_check} is set to {\tt off}) for each
found user ID, the module checks (using the \ejabberd{} authentication
subsystem) whether such user exists in the given virtual host. It is
skipped if the check is enabled and fails.
This step is here for historical reasons. If you have a tidy DIT and
properly defined ``Roster Filter'' and ``Group Filter'', it is safe to
disable it by setting {\tt ldap\_auth\_check} to {\tt off} --- it will
speed up the roster retrieval.
\item the user ID is stored in the list of members in the cache for the
given group
\end{enumerate}
\end{enumerate}
\item For each item (group name) in the list of groups retrieved in step~\ref{step:rfilter}:
\begin{enumerate}
\item the display name of a shared roster group is retrieved from the group
cache
\item for each IDs of users which belong to the group, retrieved from the
group cache:
\begin{enumerate}
\item the ID is skipped if it's the same as the one for which we are
retrieving the roster. This is so that the user does not have himself in
the roster.
\item the display name of a shared roster user is retrieved:
\begin{enumerate}
\item first, unless the user name cache is fresh (see the {\tt
ldap\_user\_cache\_validity} option), it is refreshed by running the
{\tt User Filter}, against the Base DN, retrieving the values of
attributes named by {\tt ldap\_useruid} and {\tt ldap\_userdesc}.
\item then, the display name for the given user ID is retrieved from the
user name cache.
\end{enumerate}
\end{enumerate}
\end{enumerate}
\end{enumerate}
\makesubsubsection{msrlconfigexample}{Configuration examples}
Since there are many possible
\footahref{http://en.wikipedia.org/wiki/Directory\_Information\_Tree}{DIT}
layouts, it will probably be easiest to understand how to configure the module
by looking at an example for a given DIT (or one resembling it).
\makeparagraph{msrlconfigexampleflat}{Flat DIT}
This seems to be the kind of DIT for which this module was initially designed.
Basically there are just user objects, and group membership is stored in an
attribute individually for each user. For example in a layout shown in
figure~\ref{fig:msrl-dit-flat}, the group of each user is stored in its {\tt
ou} attribute.
\begin{figure}[htbp]
\centering
\insscaleimg{0.4}{msrl-dit-flat.png}
\caption{Flat DIT graph}
\label{fig:msrl-dit-flat}
\end{figure}
Such layout has a few downsides, including:
\begin{itemize}
\item information duplication -- the group name is repeated in every member object
\item difficult group management -- information about group members is not
centralized, but distributed between member objects
\item inefficiency -- the list of unique group names has to be computed by iterating over all users
\end{itemize}
This however seems to be a common DIT layout, so the module keeps supporting it.
You can use the following configuration\ldots
\begin{verbatim}
{mod_shared_roster_ldap,[
{ldap_base, "ou=flat,dc=nodomain"},
{ldap_rfilter, "(objectClass=inetOrgPerson)"},
{ldap_groupattr, "ou"},
{ldap_memberattr, "cn"},
{ldap_filter, "(objectClass=inetOrgPerson)"},
{ldap_userdesc, "displayName"}
]},
\end{verbatim}
\ldots to be provided with a roster as shown in figure~\ref{fig:msrl-roster-flat} upon connecting as user {\tt czesio}.
\begin{figure}[htbp]
\centering
\insscaleimg{1}{msrl-roster-flat.png}
\caption{Roster from flat DIT}
\label{fig:msrl-roster-flat}
\end{figure}
\makeparagraph{msrlconfigexampledeep}{Deep DIT}
This type of DIT contains distinctly typed objects for users and groups -- see figure~\ref{fig:msrl-dit-deep}.
They are shown separated into different subtrees, but it's not a requirement.
\begin{figure}[htbp]
\centering
\insscaleimg{0.35}{msrl-dit-deep.png}
\caption{Example ``deep'' DIT graph}
\label{fig:msrl-dit-deep}
\end{figure}
If you use the following example module configuration with it:
\begin{verbatim}
{mod_shared_roster_ldap,[
{ldap_base, "ou=deep,dc=nodomain"},
{ldap_rfilter, "(objectClass=groupOfUniqueNames)"},
{ldap_filter, ""},
{ldap_gfilter, "(&(objectClass=groupOfUniqueNames)(cn=%g))"},
{ldap_groupdesc, "description"},
{ldap_memberattr, "uniqueMember"},
{ldap_memberattr_format, "cn=%u,ou=people,ou=deep,dc=nodomain"},
{ldap_ufilter, "(&(objectClass=inetOrgPerson)(cn=%u))"},
{ldap_userdesc, "displayName"}
]},
\end{verbatim}
\ldots and connect as user {\tt czesio}, then \ejabberd{} will provide you with
the roster shown in figure~\ref{fig:msrl-roster-deep}.
\begin{figure}[htbp]
\centering
\insscaleimg{1}{msrl-roster-deep.png}
\caption{Example roster from ``deep'' DIT}
\label{fig:msrl-roster-deep}
\end{figure}
\makesubsection{modsic}{\modsic{}}
\ind{modules!\modstats{}}\ind{protocols!XEP-0279: Server IP Check}
@@ -4141,7 +4628,7 @@ Examples:
\makesubsection{modvcardldap}{\modvcardldap{}}
\ind{modules!\modvcardldap{}}\ind{JUD}\ind{Jabber User Directory}\ind{vCard}\ind{protocols!XEP-0054: vcard-temp}
%TODO: verify if the referers to the LDAP section are still correct
%TODO: verify if the referrers to the LDAP section are still correct
\ejabberd{} can map LDAP attributes to vCard fields. This behaviour is
implemented in the \modvcardldap{} module. This module does not depend on the
@@ -4493,6 +4980,8 @@ The environment variables:
This path is used to read the file \term{.erlang.cookie}.
\titem{ERL\_CRASH\_DUMP}
Path to the file where crash reports will be dumped.
\titem{ERL\_EPMD\_ADDRESS}
IP address where epmd listens for connections (see section \ref{epmd}).
\titem{ERL\_INETRC}
Indicates which IP name resolution to use.
If using \term{-sname}, specify either this option or \term{-kernel inetrc filepath}.
@@ -4516,12 +5005,15 @@ The command line parameters:
If using \term{-sname}, specify either this option or \term{ERL\_INETRC}.
\titem{-kernel inet\_dist\_listen\_min 4200 inet\_dist\_listen\_min 4210}
Define the first and last ports that \term{epmd} (section \ref{epmd}) can listen to.
\titem{-kernel inet\_dist\_use\_interface "\{ 127,0,0,1 \}"}
Define the IP address where this Erlang node listens for other nodes
connections (see section \ref{epmd}).
\titem{-detached}
Starts the Erlang system detached from the system console.
Useful for running daemons and backgrounds processes.
Useful for running daemons and background processes.
\titem{-noinput}
Ensures that the Erlang system never tries to read any input.
Useful for running daemons and backgrounds processes.
Useful for running daemons and background processes.
\titem{-pa /var/lib/ejabberd/ebin}
Specify the directory where Erlang binary files (*.beam) are located.
\titem{-s ejabberd}
@@ -4911,6 +5403,8 @@ In order for this communication to work,
\term{epmd} must be running and listening for name requests in the port 4369.
You should block the port 4369 in the firewall in such a way that
only the programs in your machine can access it.
or configure the option \term{ERL\_EPMD\_ADDRESS} in the file \term{ejabberdctl.cfg}
(this option works only in Erlang/OTP R14B03 or higher).
If you build a cluster of several \ejabberd{} instances,
each \ejabberd{} instance is called an \ejabberd{} node.
@@ -4928,6 +5422,12 @@ The Erlang command-line parameter used internally is, for example:
\begin{verbatim}
erl ... -kernel inet_dist_listen_min 4370 inet_dist_listen_max 4375
\end{verbatim}
It is also possible to configure in \term{ejabberdctl.cfg}
the network interface where the Erlang node will listen and accept connections.
The Erlang command-line parameter used internally is, for example:
\begin{verbatim}
erl ... -kernel inet_dist_use_interface "{127,0,0,1}"
\end{verbatim}
\makesection{cookie}{Erlang Cookie}
@@ -5190,8 +5690,11 @@ An \ejabberd{} node writes two log files:
\titem{erlang.log} is the Erlang/OTP system log, with the messages reported by Erlang/OTP using SASL (System Architecture Support Libraries)
\end{description}
The option \term{loglevel} modifies the verbosity of the file ejabberd.log. The syntax is:
\esyntax{\{loglevel, Level\}.}
The option \term{loglevel} modifies the verbosity of the file ejabberd.log. The syntax is one of:
\begin{description}
\titem{\{loglevel, Level\}.} The standard form to set a global log level.
\titem{\{loglevel, \{Level, [\{Module, Level\}, ...]\}\}.} The given Erlang modules will be logged with specific log levels, all others will use the default log level.
\end{description}
The possible \term{Level} are:
\begin{description}
@@ -5309,10 +5812,6 @@ The Web Admin also supports the \verb|Accept-Language| HTTP header.
\end{figure}
%\section{Ultra Complex Example}
%\label{ultracomplexexample}
%TODO: a very big example covering the whole guide, with a good explanation before the example: different authenticaton mechanisms, transports, ACLs, multple virtual hosts, virtual host specific settings and general settings, modules,...
\makechapter{releasenotes}{Release Notes}
\ind{release notes}
@@ -5326,6 +5825,7 @@ Thanks to all people who contributed to this guide:
\item Badlop (\ahrefurl{xmpp:badlop@jabberes.org})
\item Evgeniy Khramtsov (\ahrefurl{xmpp:xram@jabber.ru})
\item Florian Zumbiehl (\ahrefurl{xmpp:florz@florz.de})
\item Marcin Owsiany (\ahrefurl{xmpp:marcin.owsiany@gmail.com})
\item Michael Grigutsch (\ahrefurl{xmpp:migri@jabber.i-pobox.net})
\item Mickael Remond (\ahrefurl{xmpp:mremond@process-one.net})
\item Sander Devrieze (\ahrefurl{xmpp:s.devrieze@gmail.com})
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

+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.4
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/
+97
View File
@@ -0,0 +1,97 @@
Release Notes
ejabberd 2.1.7
ejabberd 2.1.7 is the eighth 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.7
Download the source code and installers from:
http://www.process-one.net/en/ejabberd/
The changes are:
* BOSH and Web
- Clarify error message when BOSH query is sent to non-running module
- Keep the order of stanzas when BOSH sends several (EJAB-1374)
- Show configuration for HTTPS http_bind
- Support as read-only HTTP method not only GET, also HEAD
- The responses to HEAD must have empty Body
* CAPTCHA
- If the port number isn't listener, then specify the protocol (EJAB-1418)
- New CAPTCHA limit
- New CAPTCHA whitelist support
- Only check system at startup if option is enabled
- Provide HTTPS URL in CAPTCHA form when listener has 'tls' option (EJAB-1406)
- Show captcha_limit option in the example config
- Support more captcha_host value formats (EJAB-1418)
- Throw error when captcha fails at server start, not later at runtime
- captcha_host must have the port number to get protocol (EJAB-1418)
* Core ejabberd
- Disable all entity expansions (EJAB-1451)
- Do not accept XML with undefined prefixes (EJAB-680)
- Make jlib:ip_to_list safe to use
- Make sure 'closed' event is correctly processed on every state
- New route_iq/5 accepting Timeout (EJAB-1398)
- Take into consideration internal queue length when sorting processes queues
- Use route instead of send_element to go through standard workflow
* Erlang/OTP compatibility
- Remove Type and Spec, backport list comprehensions, so R12B-5 can compile
- Tweak pg2_backport.erl to work with Erlang older than R13A (EJAB-1349)
* ODBC
- Don't let presence-in privacy rule block a presence subscription (EJAB-255)
- Escape user input in mod_privacy_odbc (EJAB-1442)
- Try to improve support for roster_version in MSSQL (EJAB-1437)
* Pubsub/PEP/Caps
- Apply filtered notification to PEP last items (EJAB-1456)
- Fix empty pubsub payload check
- Owner can delete any items from its own node (EJAB-1445)
- Pubsub node maxitem forced to 0 if non persistent node (EJAB-1434)
- Reorganize the push_item function, and handle version not_found (EJAB-1420)
* Scripts
- ejabberd.init: Several fixes and improvements
- ejabberdctl: Escape output from ctlexec() to erl script (EJAB-1399)
- ejabberdctl: Fix bashism and mimic master branch (EJAB-1404)
- ejabberdctl: Fix space between INET_DIST_INTERFACE (EJAB-1416)
- ejabberdctl: New DIST_USE_INTERFACE restricts IP of erlang listen (EJAB-1404)
- ejabberdctl: New ERL_EPMD_ADDRESS that works since Erlang/OTP R14B03
- extauth: Fix delayed response of timeout was reused for next login (EJAB-1385)
- extauth: Forward old messages to newly spawned extauth process (EJAB-1385)
- extauth: If script crashes, ejabberd should restart it (EJAB-1428)
* XEP support
- mod_blocking: New XEP-0191 Simple Communications Blocking (EJAB-695)
- No need to inform that XEP-0237 is optional; clarified in XEP version 1.2
* Miscellanea:
- If a module start fails during server start, stop erlang (EJAB-1446)
- New Indonesian translation (EJAB-1407)
- LDAP: Note that ejabberd works with CGP LDAP server
- S2S: Handle Tigase's unexpected version=1.0 (EJAB-1379)
- mod_irc: Send presence unavailable to the departing occupant (EJAB-1417)
- mod_last: Allow user to query his own Last activity
- mod_muc: Do not decrease MUC admin's role/affiliation
- mod_muc: Send jid attribute when occupant is banned (EJAB-1432)
- mod_offline: Change c2s state before offline messages resending
- mod_ping: Use iqdisc no_queue by default (EJAB-1435)
- mod_pres_counter: Prevent subscription flood (EJAB-1388)
- mod_register Access now also controls account unregistrations
- mod_register: Clarify more the expected content of welcome_message option
- mod_shared_roster: Fix support for anonymous accounts in @all@ (EJAB-1264)
- mod_shared_roster: New @online@ directive (EJAB-1391)
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
+21
View File
@@ -0,0 +1,21 @@
Release Notes
ejabberd 2.1.8
ejabberd 2.1.8 is the ninth release in ejabberd 2.1.x branch,
and includes a PubSub regression bugfix.
Download the source code and installers from:
http://www.process-one.net/en/ejabberd/
The change is:
- Fix issue on PubSub preventing publication of items (EJAB-1457)
Bug reports
You can officially report bugs on ProcessOne support site:
http://support.process-one.net/
+1 -1
View File
@@ -1,2 +1,2 @@
% ejabberd version (automatically generated).
\newcommand{\version}{2.1.4}
\newcommand{\version}{2.1.7}
+16
View File
@@ -42,6 +42,22 @@ while(1)
# password is null. Return 1 if the user $user\@$domain exitst.
$result = 1;
},last SWITCH;
$op eq 'tryregister' and do
{
$result = 1;
},last SWITCH;
$op eq 'removeuser' and do
{
# password is null. Return 1 if the user $user\@$domain exitst.
$result = 1;
},last SWITCH;
$op eq 'removeuser3' and do
{
$result = 1;
},last SWITCH;
};
my $out = pack "nn",2,$result ? 1 : 0;
syswrite STDOUT,$out;
+21 -5
View File
@@ -30,16 +30,16 @@ else
INIT_USER=$(INSTALLUSER)
endif
EFLAGS += @ERLANG_SSL39@ -pa .
EFLAGS += @ERLANG_SSLVER@ -pa .
ERLANG_CFLAGS += @ERLANG_SSLVER@
# make debug=true to compile Erlang module with debug informations.
ifdef debug
EFLAGS+=+debug_info +export_all
endif
DEBUGTOOLS = ejabberd_debug.erl
ifdef ejabberd_debug
EFLAGS+=-Dejabberd_debug
DEBUGTOOLS = p1_prof.erl
ifdef debugtools
SOURCES+=$(DEBUGTOOLS)
endif
@@ -55,10 +55,20 @@ ifeq (@full_xml@, true)
EFLAGS+=-DFULL_XML_SUPPORT
endif
ifeq (@nif@, true)
EFLAGS+=-DNIF
ERLSHLIBS=xml.so
endif
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)
@@ -68,7 +78,7 @@ 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
ERLSHLIBS += expat_erl.so
ERLBEHAVS = cyrsasl.erl gen_mod.erl p1_fsm.erl
SOURCES_ALL = $(wildcard *.erl)
SOURCES_MISC = $(ERLBEHAVS) $(DEBUGTOOLS)
@@ -198,6 +208,7 @@ install: all
sed -e "s*@ctlscriptpath@*$(SBINDIR)*" \
-e "s*@installuser@*$(INIT_USER)*" ejabberd.init.template \
> ejabberd.init
chmod 755 ejabberd.init
#
# Binary Erlang files
install -d $(BEAMDIR)
@@ -250,9 +261,14 @@ install: all
#
# Documentation
install -d $(DOCDIR)
install -m 644 ../doc/dev.html $(DOCDIR)
install -m 644 ../doc/guide.html $(DOCDIR)
install -m 644 ../doc/*.png $(DOCDIR)
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
+15 -14
View File
@@ -1,4 +1,4 @@
AC_DEFUN(AM_WITH_EXPAT,
AC_DEFUN([AM_WITH_EXPAT],
[ AC_ARG_WITH(expat,
[AC_HELP_STRING([--with-expat=PREFIX], [prefix where EXPAT is installed])])
@@ -32,7 +32,7 @@ AC_DEFUN(AM_WITH_EXPAT,
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 +68,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 +103,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,7 +121,6 @@ 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",
@@ -130,11 +129,13 @@ start() ->
file:write_file("conftest.out", list_to_binary(EIDirS ++ EILibS ++ ssldef() ++ 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 +185,7 @@ _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`
# End line
ERLANG_DIR=`cat conftest.out | tail -n 1`
@@ -193,12 +194,12 @@ _EOF
AC_SUBST(ERLANG_CFLAGS)
AC_SUBST(ERLANG_LIBS)
AC_SUBST(ERLANG_SSL39)
AC_SUBST(ERLANG_SSLVER)
AC_SUBST(ERLC)
AC_SUBST(ERL)
])
AC_DEFUN(AC_MOD_ENABLE,
AC_DEFUN([AC_MOD_ENABLE],
[
$1=
make_$1=
@@ -308,7 +309,7 @@ size_t iconv();
])
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;
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 18 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 31 Oct 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2010 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).
+53
View File
@@ -0,0 +1,53 @@
%%%-------------------------------------------------------------------
%%% File : cache_tab_sup.erl
%%% Author : Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%% Description : Cache tables supervisor
%%%
%%% Created : 30 Aug 2010 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-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_sup).
-behaviour(supervisor).
%% API
-export([start_link/0]).
%% Supervisor callbacks
-export([init/1]).
-define(SERVER, ?MODULE).
%%====================================================================
%% API functions
%%====================================================================
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
%%====================================================================
%% Supervisor callbacks
%%====================================================================
init([]) ->
{ok, {{one_for_one,10,1}, []}}.
%%====================================================================
%% Internal functions
%%====================================================================
+413 -311
View File
File diff suppressed because it is too large Load Diff
+14 -2
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
@@ -81,7 +81,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)
@@ -94,6 +94,15 @@ AC_ARG_ENABLE(full_xml,
esac],[full_xml=false])
AC_SUBST(full_xml)
AC_ARG_ENABLE(nif,
[AC_HELP_STRING([--enable-nif], [replace some functions with C equivalents. Requires Erlang R13B04 or higher (default: no)])],
[case "${enableval}" in
yes) nif=true ;;
no) nif=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-nif) ;;
esac],[nif=false])
AC_SUBST(nif)
AC_CONFIG_FILES([Makefile
$make_mod_irc
$make_mod_muc
@@ -139,6 +148,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)
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 27 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -6,7 +6,7 @@
%%% Created : 23 Aug 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 11 Mar 2003 by Alexey Shchepin <alexey@sevcom.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+2 -1
View File
@@ -2,7 +2,7 @@
{application, ejabberd,
[{description, "ejabberd"},
{vsn, "2.1.4"},
{vsn, "2.1.7"},
{modules, [acl,
adhoc,
configure,
@@ -115,6 +115,7 @@
nodetree_virtual,
p1_fsm,
p1_mnesia,
p1_prof,
randoms,
sha,
shaper,
+38 -3
View File
@@ -162,6 +162,7 @@
captcha,
http_bind,
http_poll,
%%register,
web_admin
]}
@@ -169,10 +170,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.
@@ -474,10 +475,14 @@
%%{captcha_cmd, "/lib/ejabberd/priv/bin/captcha.sh"}.
%%
%% Host part of the URL sent to the user.
%% Host for the URL and port where ejabberd listens for CAPTCHA requests.
%%
%%{captcha_host, "example.org:5280"}.
%%
%% Limit CAPTCHA calls per minute for JID/IP to avoid DoS.
%%
%%{captcha_limit, 5}.
%%%. =======
%%%' MODULES
@@ -489,6 +494,7 @@
[
{mod_adhoc, []},
{mod_announce, [{access, announce}]}, % recommends mod_adhoc
{mod_blocking,[]}, % requires mod_privacy
{mod_caps, []},
{mod_configure,[]}, % requires mod_adhoc
{mod_disco, []},
@@ -510,6 +516,7 @@
%%{mod_muc_log,[]},
{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,[]},
@@ -521,6 +528,16 @@
{plugins, ["flat", "hometree", "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.
@@ -534,8 +551,26 @@
%%
%%{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,[]},
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2010 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 -4
View File
@@ -1,6 +1,20 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: ejabberd
# Required-Start: $remote_fs $network $named $time
# Required-Stop: $remote_fs $network $named $time
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Starts ejabberd jabber server
# Description: Starts ejabberd jabber server, an XMPP
# compliant server written in Erlang.
### END INIT INFO
# chkconfig: 2345 90 10
# description: ejabberd XMPP server
set -o errexit
set -o nounset
DIR=@ctlscriptpath@
CTL="$DIR"/ejabberdctl
@@ -32,14 +46,17 @@ case "$1" in
su - $USER -c "$CTL stopped"
echo "done."
;;
status)
test -x "$CTL" || exit 0
echo "Getting ejabberd status..."
su - $USER -c "$CTL status"
;;
force-reload|restart)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload}"
echo "Usage: $0 {start|stop|restart|force-reload|status}"
exit 1
esac
+7 -4
View File
@@ -5,7 +5,7 @@
%%% Created : 7 May 2006 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -99,14 +99,14 @@ commands() ->
#ejabberd_commands{name = update_list, tags = [server],
desc = "List modified modules that can be updated",
module = ?MODULE, function = update_list_modified,
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, rescode}},
result = {res, restuple}},
#ejabberd_commands{name = register, tags = [accounts],
desc = "Register a user",
@@ -305,7 +305,10 @@ update(ModStr) ->
update_module(ModuleNameString) ->
ModuleName = list_to_atom(ModuleNameString),
ejabberd_update:update([ModuleName]).
case ejabberd_update:update([ModuleName]) of
{ok, Res} -> {ok, io_lib:format("Updated: ~p", [Res])};
{error, Reason} -> {error, Reason}
end.
%%%
%%% Account management
+4 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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,7 @@ start(normal, _Args) ->
db_init(),
sha:start(),
stringprep_sup:start_link(),
xml:start(),
start(),
translate:start(),
acl:start(),
@@ -56,6 +57,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(),
+26 -2
View File
@@ -5,7 +5,7 @@
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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,7 +49,8 @@
is_user_exists_in_other_modules/3,
remove_user/2,
remove_user/3,
plain_password_required/1
plain_password_required/1,
entropy/1
]).
-export([auth_modules/1]).
@@ -318,6 +319,29 @@ remove_user(User, Server, Password) ->
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
+4 -3
View File
@@ -5,7 +5,7 @@
%%% Created : 17 Feb 2006 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -143,6 +143,7 @@ register_connection(SID, #jid{luser = LUser, lserver = LServer}, Info) ->
AuthModule = xml:get_attr_s(auth_module, Info),
case AuthModule == ?MODULE of
true ->
ejabberd_hooks:run(register_user, LServer, [LUser, LServer]),
US = {LUser, LServer},
mnesia:sync_dirty(
fun() -> mnesia:write(#anonymous{us = US, sid=SID})
@@ -215,8 +216,8 @@ try_register(_User, _Server, _Password) ->
dirty_get_registered_users() ->
[].
get_vh_registered_users(_Server) ->
[].
get_vh_registered_users(Server) ->
[{U, S} || {U, S, _R} <- ejabberd_sm:get_vh_session_list(Server)].
%% Return password of permanent user or false for anonymous users
+17 -5
View File
@@ -5,7 +5,7 @@
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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,7 +66,7 @@ check_cache_last_options(Server) ->
case get_cache_option(Server) of
false -> no_cache;
{true, _CacheTime} ->
case get_mod_last_enabled(Server) of
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]),
@@ -290,15 +290,27 @@ get_last_info(User, Server) ->
case get_mod_last_enabled(Server) of
mod_last -> mod_last:get_last_info(User, Server);
mod_last_odbc -> mod_last_odbc:get_last_info(User, Server);
mod_mod_last -> mod_last_required
no_mod_last -> mod_last_required
end.
%% @spec (Server) -> mod_last | mod_last_odbc | no_mod_last
get_mod_last_enabled(Server) ->
ML = lists:member(mod_last, gen_mod:loaded_modules(Server)),
MLO = lists:member(mod_last_odbc, gen_mod:loaded_modules(Server)),
ML = gen_mod:is_loaded(Server, mod_last),
MLO = gen_mod:is_loaded(Server, mod_last_odbc),
case {ML, MLO} of
{true, _} -> mod_last;
{false, true} -> mod_last_odbc;
{false, false} -> no_mod_last
end.
get_mod_last_configured(Server) ->
ML = is_configured(Server, mod_last),
MLO = is_configured(Server, mod_last_odbc),
case {ML, MLO} of
{true, _} -> mod_last;
{false, true} -> mod_last_odbc;
{false, false} -> no_mod_last
end.
is_configured(Host, Module) ->
lists:keymember(Module, 1, ejabberd_config:get_local_option({modules, Host})).
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 5 Jul 2007 by Evgeniy Khramtsov <xram@jabber.ru>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+259 -210
View File
@@ -5,7 +5,7 @@
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -40,6 +40,11 @@
send_element/2,
socket_type/0,
get_presence/1,
get_aux_field/2,
set_aux_field/3,
del_aux_field/2,
get_subscription/2,
broadcast/4,
get_subscribed/1]).
%% gen_fsm callbacks
@@ -96,6 +101,7 @@
conn = unknown,
auth_module = unknown,
ip,
aux_fields = [],
lang}).
%-define(DBGFSM, true).
@@ -154,6 +160,39 @@ socket_type() ->
get_presence(FsmRef) ->
?GEN_FSM:sync_send_all_state_event(FsmRef, {get_presence}, 1000).
get_aux_field(Key, #state{aux_fields = Opts}) ->
case lists:keysearch(Key, 1, Opts) of
{value, {_, Val}} ->
{ok, Val};
_ ->
error
end.
set_aux_field(Key, Val, #state{aux_fields = Opts} = State) ->
Opts1 = lists:keydelete(Key, 1, Opts),
State#state{aux_fields = [{Key, Val}|Opts1]}.
del_aux_field(Key, #state{aux_fields = Opts} = State) ->
Opts1 = lists:keydelete(Key, 1, Opts),
State#state{aux_fields = Opts1}.
get_subscription(From = #jid{}, StateData) ->
get_subscription(jlib:jid_tolower(From), StateData);
get_subscription(LFrom, StateData) ->
LBFrom = setelement(3, LFrom, ""),
F = ?SETS:is_element(LFrom, StateData#state.pres_f) orelse
?SETS:is_element(LBFrom, StateData#state.pres_f),
T = ?SETS:is_element(LFrom, StateData#state.pres_t) orelse
?SETS:is_element(LBFrom, StateData#state.pres_t),
if F and T -> both;
F -> from;
T -> to;
true -> none
end.
broadcast(FsmRef, Type, From, Packet) ->
FsmRef ! {broadcast, Type, From, Packet}.
stop(FsmRef) ->
?GEN_FSM:send_event(FsmRef, closed).
@@ -196,8 +235,8 @@ init([{SockMod, Socket}, Opts]) ->
%% Check if IP is blacklisted:
case is_ip_blacklisted(IP) of
true ->
?INFO_MSG("Connection attempt from blacklisted IP: ~s",
[jlib:ip_to_list(IP)]),
?INFO_MSG("Connection attempt from blacklisted IP: ~s (~w)",
[jlib:ip_to_list(IP), IP]),
{stop, normal};
false ->
Socket1 =
@@ -247,7 +286,19 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
Server = jlib:nameprep(xml:get_attr_s("to", Attrs)),
case lists:member(Server, ?MYHOSTS) of
true ->
Lang = xml:get_attr_s("xml:lang", Attrs),
Lang = case xml:get_attr_s("xml:lang", Attrs) of
Lang1 when length(Lang1) =< 35 ->
%% As stated in BCP47, 4.4.1:
%% Protocols or specifications that
%% specify limited buffer sizes for
%% language tags MUST allow for
%% language tags of at least 35 characters.
Lang1;
_ ->
%% Do not store long language tag to
%% avoid possible DoS/flood attacks
""
end,
change_shaper(StateData, jlib:make_jid("", Server, "")),
case xml:get_attr_s("version", Attrs) of
"1.0" ->
@@ -627,7 +678,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
Socket = StateData#state.socket,
TLSSocket = (StateData#state.sockmod):starttls(
Socket, TLSOpts,
xml:element_to_string(
xml:element_to_binary(
{xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []})),
fsm_next_state(wait_for_stream,
StateData#state{socket = TLSSocket,
@@ -650,7 +701,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
Socket = StateData#state.socket,
ZlibSocket = (StateData#state.sockmod):compress(
Socket,
xml:element_to_string(
xml:element_to_binary(
{xmlelement, "compressed",
[{"xmlns", ?NS_COMPRESS}], []})),
fsm_next_state(wait_for_stream,
@@ -1000,7 +1051,9 @@ session_established2(El, StateData) ->
end;
"iq" ->
case jlib:iq_query_info(NewEl) of
#iq{xmlns = ?NS_PRIVACY} = IQ ->
#iq{xmlns = Xmlns} = IQ
when Xmlns == ?NS_PRIVACY;
Xmlns == ?NS_BLOCKING ->
process_privacy_iq(
FromJID, ToJID, IQ, StateData);
_ ->
@@ -1008,8 +1061,7 @@ session_established2(El, StateData) ->
user_send_packet,
Server,
[FromJID, ToJID, NewEl]),
ejabberd_router:route(
FromJID, ToJID, NewEl),
check_privacy_route(FromJID, StateData, FromJID, ToJID, NewEl),
StateData
end;
"message" ->
@@ -1103,35 +1155,39 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
{Pass, NewAttrs, NewState} =
case Name of
"presence" ->
State = ejabberd_hooks:run_fold(
c2s_presence_in, StateData#state.server,
StateData,
[{From, To, Packet}]),
case xml:get_attr_s("type", Attrs) of
"probe" ->
LFrom = jlib:jid_tolower(From),
LBFrom = jlib:jid_remove_resource(LFrom),
NewStateData =
case ?SETS:is_element(
LFrom, StateData#state.pres_a) orelse
LFrom, State#state.pres_a) orelse
?SETS:is_element(
LBFrom, StateData#state.pres_a) of
LBFrom, State#state.pres_a) of
true ->
StateData;
State;
false ->
case ?SETS:is_element(
LFrom, StateData#state.pres_f) of
LFrom, State#state.pres_f) of
true ->
A = ?SETS:add_element(
LFrom,
StateData#state.pres_a),
StateData#state{pres_a = A};
State#state.pres_a),
State#state{pres_a = A};
false ->
case ?SETS:is_element(
LBFrom, StateData#state.pres_f) of
LBFrom, State#state.pres_f) of
true ->
A = ?SETS:add_element(
LBFrom,
StateData#state.pres_a),
StateData#state{pres_a = A};
State#state.pres_a),
State#state{pres_a = A};
false ->
StateData
State
end
end
end,
@@ -1139,66 +1195,59 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
{false, Attrs, NewStateData};
"error" ->
NewA = remove_element(jlib:jid_tolower(From),
StateData#state.pres_a),
{true, Attrs, StateData#state{pres_a = NewA}};
State#state.pres_a),
{true, Attrs, State#state{pres_a = NewA}};
"invisible" ->
Attrs1 = lists:keydelete("type", 1, Attrs),
{true, [{"type", "unavailable"} | Attrs1], StateData};
{true, [{"type", "unavailable"} | Attrs1], State};
"subscribe" ->
SRes = is_privacy_allow(From, To, Packet, StateData#state.privacy_list),
{SRes, Attrs, StateData};
SRes = is_privacy_allow(State, From, To, Packet, in),
{SRes, Attrs, State};
"subscribed" ->
SRes = is_privacy_allow(From, To, Packet, StateData#state.privacy_list),
{SRes, Attrs, StateData};
SRes = is_privacy_allow(State, From, To, Packet, in),
{SRes, Attrs, State};
"unsubscribe" ->
SRes = is_privacy_allow(From, To, Packet, StateData#state.privacy_list),
{SRes, Attrs, StateData};
SRes = is_privacy_allow(State, From, To, Packet, in),
{SRes, Attrs, State};
"unsubscribed" ->
SRes = is_privacy_allow(From, To, Packet, StateData#state.privacy_list),
{SRes, Attrs, StateData};
SRes = is_privacy_allow(State, From, To, Packet, in),
{SRes, Attrs, State};
_ ->
case ejabberd_hooks:run_fold(
privacy_check_packet, StateData#state.server,
allow,
[StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, To, Packet},
in]) of
case privacy_check_packet(State, From, To, Packet, in) of
allow ->
LFrom = jlib:jid_tolower(From),
LBFrom = jlib:jid_remove_resource(LFrom),
case ?SETS:is_element(
LFrom, StateData#state.pres_a) orelse
LFrom, State#state.pres_a) orelse
?SETS:is_element(
LBFrom, StateData#state.pres_a) of
LBFrom, State#state.pres_a) of
true ->
{true, Attrs, StateData};
{true, Attrs, State};
false ->
case ?SETS:is_element(
LFrom, StateData#state.pres_f) of
LFrom, State#state.pres_f) of
true ->
A = ?SETS:add_element(
LFrom,
StateData#state.pres_a),
State#state.pres_a),
{true, Attrs,
StateData#state{pres_a = A}};
State#state{pres_a = A}};
false ->
case ?SETS:is_element(
LBFrom, StateData#state.pres_f) of
LBFrom, State#state.pres_f) of
true ->
A = ?SETS:add_element(
LBFrom,
StateData#state.pres_a),
State#state.pres_a),
{true, Attrs,
StateData#state{pres_a = A}};
State#state{pres_a = A}};
false ->
{true, Attrs, StateData}
{true, Attrs, State}
end
end
end;
deny ->
{false, Attrs, StateData}
{false, Attrs, State}
end
end;
"broadcast" ->
@@ -1236,67 +1285,52 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
send_element(StateData, PrivPushEl),
{false, Attrs, StateData#state{privacy_list = NewPL}}
end;
[{blocking, What}] ->
route_blocking(What, StateData),
{false, Attrs, StateData};
_ ->
{false, Attrs, StateData}
end;
"iq" ->
IQ = jlib:iq_query_info(Packet),
case IQ of
#iq{xmlns = ?NS_VCARD} when (To#jid.luser == "") or (To#jid.lresource == "") ->
Host = StateData#state.server,
case ets:lookup(sm_iqtable, {?NS_VCARD, Host}) of
[{_, Module, Function, Opts}] ->
gen_iq_handler:handle(Host, Module, Function, Opts,
From, To, IQ);
[] ->
Err = jlib:make_error_reply(
Packet, ?ERR_FEATURE_NOT_IMPLEMENTED),
ejabberd_router:route(To, From, Err)
end,
{false, Attrs, StateData};
#iq{} ->
case ejabberd_hooks:run_fold(
privacy_check_packet, StateData#state.server,
allow,
[StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, To, Packet},
in]) of
allow ->
{true, Attrs, StateData};
deny ->
Err = jlib:make_error_reply(
Packet, ?ERR_FEATURE_NOT_IMPLEMENTED),
#iq{xmlns = ?NS_LAST} ->
LFrom = jlib:jid_tolower(From),
LBFrom = jlib:jid_remove_resource(LFrom),
HasFromSub = (?SETS:is_element(LFrom, StateData#state.pres_f) orelse ?SETS:is_element(LBFrom, StateData#state.pres_f))
andalso is_privacy_allow(StateData, To, From, {xmlelement, "presence", [], []}, out),
case HasFromSub of
true ->
case privacy_check_packet(StateData, From, To, Packet, in) of
allow ->
{true, Attrs, StateData};
deny ->
{false, Attrs, StateData}
end;
_ ->
Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN),
ejabberd_router:route(To, From, Err),
{false, Attrs, StateData}
end;
_ ->
{true, Attrs, StateData}
end;
"message" ->
case ejabberd_hooks:run_fold(
privacy_check_packet, StateData#state.server,
allow,
[StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, To, Packet},
in]) of
allow ->
case ejabberd_hooks:run_fold(
feature_check_packet, StateData#state.server,
allow,
[StateData#state.jid,
StateData#state.server,
StateData#state.pres_last,
{From, To, Packet},
in]) of
IQ when (is_record(IQ, iq)) or (IQ == reply) ->
case privacy_check_packet(StateData, From, To, Packet, in) of
allow ->
{true, Attrs, StateData};
deny ->
deny when is_record(IQ, iq) ->
Err = jlib:make_error_reply(
Packet, ?ERR_SERVICE_UNAVAILABLE),
ejabberd_router:route(To, From, Err),
{false, Attrs, StateData};
deny when IQ == reply ->
{false, Attrs, StateData}
end;
IQ when (IQ == invalid) or (IQ == not_iq) ->
{false, Attrs, StateData}
end;
"message" ->
case privacy_check_packet(StateData, From, To, Packet, in) of
allow ->
{true, Attrs, StateData};
deny ->
{false, Attrs, StateData}
end;
@@ -1360,6 +1394,17 @@ handle_info({force_update_presence, LUser}, StateName,
StateData
end,
{next_state, StateName, NewStateData};
handle_info({broadcast, Type, From, Packet}, StateName, StateData) ->
Recipients = ejabberd_hooks:run_fold(
c2s_broadcast_recipients, StateData#state.server,
[],
[StateData, Type, From, Packet]),
lists:foreach(
fun(USR) ->
ejabberd_router:route(
From, jlib:make_jid(USR), Packet)
end, lists:usort(Recipients)),
fsm_next_state(StateName, StateData);
handle_info(Info, StateName, StateData) ->
?ERROR_MSG("Unexpected info: ~p", [Info]),
fsm_next_state(StateName, StateData).
@@ -1452,15 +1497,19 @@ change_shaper(StateData, JID) ->
StateData#state.shaper, JID),
(StateData#state.sockmod):change_shaper(StateData#state.socket, Shaper).
send_text(StateData, Text) when StateData#state.xml_socket ->
?DEBUG("Send Text on stream = ~p", [lists:flatten(Text)]),
(StateData#state.sockmod):send_xml(StateData#state.socket,
{xmlstreamraw, Text});
send_text(StateData, Text) ->
?DEBUG("Send XML on stream = ~p", [lists:flatten(Text)]),
?DEBUG("Send XML on stream = ~p", [Text]),
(StateData#state.sockmod):send(StateData#state.socket, Text).
send_element(StateData, El) when StateData#state.xml_socket ->
(StateData#state.sockmod):send_xml(StateData#state.socket,
{xmlstreamelement, El});
send_element(StateData, El) ->
send_text(StateData, xml:element_to_string(El)).
send_text(StateData, xml:element_to_binary(El)).
send_header(StateData, Server, Version, Lang)
when StateData#state.xml_socket ->
@@ -1591,14 +1640,7 @@ process_presence_probe(From, To, StateData) ->
[jlib:timestamp_to_xml(Timestamp, utc, To, ""),
%% TODO: Delete the next line once XEP-0091 is Obsolete
jlib:timestamp_to_xml(Timestamp)]),
case ejabberd_hooks:run_fold(
privacy_check_packet, StateData#state.server,
allow,
[StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{To, From, Packet},
out]) of
case privacy_check_packet(StateData, To, From, Packet, out) of
deny ->
ok;
allow ->
@@ -1696,37 +1738,33 @@ presence_update(From, Packet, StateData) ->
StateData#state.pres_invis,
?DEBUG("from unavail = ~p~n", [FromUnavail]),
NewState =
NewStateData = StateData#state{pres_last = Packet,
pres_invis = false,
pres_timestamp = Timestamp},
if
FromUnavail ->
ejabberd_hooks:run(user_available_hook,
StateData#state.server,
[StateData#state.jid]),
NewStateData#state.server,
[NewStateData#state.jid]),
if NewPriority >= 0 ->
resend_offline_messages(StateData),
resend_subscription_requests(StateData);
resend_offline_messages(NewStateData),
resend_subscription_requests(NewStateData);
true ->
ok
end,
presence_broadcast_first(
From, StateData#state{pres_last = Packet,
pres_invis = false,
pres_timestamp = Timestamp
}, Packet);
presence_broadcast_first(From, NewStateData, Packet);
true ->
presence_broadcast_to_trusted(StateData,
presence_broadcast_to_trusted(NewStateData,
From,
StateData#state.pres_f,
StateData#state.pres_a,
NewStateData#state.pres_f,
NewStateData#state.pres_a,
Packet),
if OldPriority < 0, NewPriority >= 0 ->
resend_offline_messages(StateData);
resend_offline_messages(NewStateData);
true ->
ok
end,
StateData#state{pres_last = Packet,
pres_invis = false,
pres_timestamp = Timestamp
}
NewStateData
end,
NewState
end.
@@ -1793,44 +1831,35 @@ presence_track(From, To, Packet, StateData) ->
end.
check_privacy_route(From, StateData, FromRoute, To, Packet) ->
case ejabberd_hooks:run_fold(
privacy_check_packet, StateData#state.server,
allow,
[StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, To, Packet},
out]) of
case privacy_check_packet(StateData, From, To, Packet, out) of
deny ->
Lang = StateData#state.lang,
ErrText = "Your active privacy list has denied the routing of this stanza.",
Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
ejabberd_router:route(To, From, Err),
ok;
allow ->
ejabberd_router:route(FromRoute, To, Packet)
end.
privacy_check_packet(StateData, From, To, Packet, Dir) ->
ejabberd_hooks:run_fold(
privacy_check_packet, StateData#state.server,
allow,
[StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, To, Packet},
Dir]).
%% Check if privacy rules allow this delivery
is_privacy_allow(From, To, Packet, PrivacyList) ->
User = To#jid.user,
Server = To#jid.server,
allow == ejabberd_hooks:run_fold(
privacy_check_packet, Server,
allow,
[User,
Server,
PrivacyList,
{From, To, Packet},
in]).
is_privacy_allow(StateData, From, To, Packet, Dir) ->
allow == privacy_check_packet(StateData, From, To, Packet, Dir).
presence_broadcast(StateData, From, JIDSet, Packet) ->
lists:foreach(fun(JID) ->
FJID = jlib:make_jid(JID),
case ejabberd_hooks:run_fold(
privacy_check_packet, StateData#state.server,
allow,
[StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, FJID, Packet},
out]) of
case privacy_check_packet(StateData, From, FJID, Packet, out) of
deny ->
ok;
allow ->
@@ -1844,14 +1873,7 @@ presence_broadcast_to_trusted(StateData, From, T, A, Packet) ->
case ?SETS:is_element(JID, T) of
true ->
FJID = jlib:make_jid(JID),
case ejabberd_hooks:run_fold(
privacy_check_packet, StateData#state.server,
allow,
[StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, FJID, Packet},
out]) of
case privacy_check_packet(StateData, From, FJID, Packet, out) of
deny ->
ok;
allow ->
@@ -1882,14 +1904,7 @@ presence_broadcast_first(From, StateData, Packet) ->
As = ?SETS:fold(
fun(JID, A) ->
FJID = jlib:make_jid(JID),
case ejabberd_hooks:run_fold(
privacy_check_packet, StateData#state.server,
allow,
[StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, FJID, Packet},
out]) of
case privacy_check_packet(StateData, From, FJID, Packet, out) of
deny ->
ok;
allow ->
@@ -1944,14 +1959,7 @@ roster_change(IJID, ISubscription, StateData) ->
if
Cond1 ->
?DEBUG("C1: ~p~n", [LIJID]),
case ejabberd_hooks:run_fold(
privacy_check_packet, StateData#state.server,
allow,
[StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, To, P},
out]) of
case privacy_check_packet(StateData, From, To, P, out) of
deny ->
ok;
allow ->
@@ -1966,14 +1974,7 @@ roster_change(IJID, ISubscription, StateData) ->
?DEBUG("C2: ~p~n", [LIJID]),
PU = {xmlelement, "presence",
[{"type", "unavailable"}], []},
case ejabberd_hooks:run_fold(
privacy_check_packet, StateData#state.server,
allow,
[StateData#state.user,
StateData#state.server,
StateData#state.privacy_list,
{From, To, PU},
out]) of
case privacy_check_packet(StateData, From, To, PU, out) of
deny ->
ok;
allow ->
@@ -2051,25 +2052,16 @@ process_privacy_iq(From, To,
NewStateData.
resend_offline_messages(#state{user = User,
server = Server,
privacy_list = PrivList} = StateData) ->
case ejabberd_hooks:run_fold(resend_offline_messages_hook,
Server,
[],
[User, Server]) of
resend_offline_messages(StateData) ->
case ejabberd_hooks:run_fold(
resend_offline_messages_hook, StateData#state.server,
[],
[StateData#state.user, StateData#state.server]) of
Rs when is_list(Rs) ->
lists:foreach(
fun({route,
From, To, {xmlelement, Name, Attrs, Els} = Packet}) ->
Pass = case ejabberd_hooks:run_fold(
privacy_check_packet, Server,
allow,
[User,
Server,
PrivList,
{From, To, Packet},
in]) of
From, To, {xmlelement, _Name, _Attrs, _Els} = Packet}) ->
Pass = case privacy_check_packet(StateData, From, To, Packet, in) of
allow ->
true;
deny ->
@@ -2077,16 +2069,18 @@ resend_offline_messages(#state{user = User,
end,
if
Pass ->
Attrs2 = jlib:replace_from_to_attrs(
jlib:jid_to_string(From),
jlib:jid_to_string(To),
Attrs),
FixedPacket = {xmlelement, Name, Attrs2, Els},
send_element(StateData, FixedPacket),
ejabberd_hooks:run(user_receive_packet,
StateData#state.server,
[StateData#state.jid,
From, To, FixedPacket]);
%% Attrs2 = jlib:replace_from_to_attrs(
%% jlib:jid_to_string(From),
%% jlib:jid_to_string(To),
%% Attrs),
%% FixedPacket = {xmlelement, Name, Attrs2, Els},
%% Use route instead of send_element to go through standard workflow
ejabberd_router:route(From, To, Packet);
%% send_element(StateData, FixedPacket),
%% ejabberd_hooks:run(user_receive_packet,
%% StateData#state.server,
%% [StateData#state.jid,
%% From, To, FixedPacket]);
true ->
ok
end
@@ -2122,7 +2116,17 @@ get_statustag(Presence) ->
end.
process_unauthenticated_stanza(StateData, El) ->
case jlib:iq_query_info(El) of
NewEl = case xml:get_tag_attr_s("xml:lang", El) of
"" ->
case StateData#state.lang of
"" -> El;
Lang ->
xml:replace_tag_attr("xml:lang", Lang, El)
end;
_ ->
El
end,
case jlib:iq_query_info(NewEl) of
#iq{} = IQ ->
Res = ejabberd_hooks:run_fold(c2s_unauthenticated_iq,
StateData#state.server,
@@ -2238,6 +2242,51 @@ bounce_messages() ->
ok
end.
%%%----------------------------------------------------------------------
%%% XEP-0191
%%%----------------------------------------------------------------------
route_blocking(What, StateData) ->
SubEl =
case What of
{block, JIDs} ->
{xmlelement, "block",
[{"xmlns", ?NS_BLOCKING}],
lists:map(
fun(JID) ->
{xmlelement, "item",
[{"jid", jlib:jid_to_string(JID)}],
[]}
end, JIDs)};
{unblock, JIDs} ->
{xmlelement, "unblock",
[{"xmlns", ?NS_BLOCKING}],
lists:map(
fun(JID) ->
{xmlelement, "item",
[{"jid", jlib:jid_to_string(JID)}],
[]}
end, JIDs)};
unblock_all ->
{xmlelement, "unblock",
[{"xmlns", ?NS_BLOCKING}], []}
end,
PrivPushIQ =
#iq{type = set, xmlns = ?NS_BLOCKING,
id = "push",
sub_el = [SubEl]},
PrivPushEl =
jlib:replace_from_to(
jlib:jid_remove_resource(
StateData#state.jid),
StateData#state.jid,
jlib:iq_to_xml(PrivPushIQ)),
send_element(StateData, PrivPushEl),
%% No need to replace active privacy list here,
%% blocking pushes are always accompanied by
%% Privacy List pushes
ok.
%%%----------------------------------------------------------------------
%%% JID Set memory footprint reduction code
%%%----------------------------------------------------------------------
+1 -1
View File
@@ -6,7 +6,7 @@
%%% Created : 2 Nov 2007 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+221 -45
View File
@@ -5,7 +5,7 @@
%%% Created : 26 Apr 2008 by Evgeniy Khramtsov <xramtsov@gmail.com>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -36,7 +36,8 @@
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]).
process_reply/1, process/2, is_feature_available/0,
create_captcha_x/5, create_captcha_x/6]).
-include("jlib.hrl").
-include("ejabberd.hrl").
@@ -48,8 +49,9 @@
-define(CAPTCHA_TEXT(Lang), translate:translate(Lang, "Enter the text you see")).
-define(CAPTCHA_LIFETIME, 120000). % two minutes
-define(LIMIT_PERIOD, 60*1000*1000). % one minute
-record(state, {}).
-record(state, {limits = treap:empty()}).
-record(captcha, {id, pid, key, tref, args}).
-define(T(S),
@@ -71,11 +73,12 @@
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),
create_captcha(SID, From, To, Lang, Limiter, Args)
when is_list(Lang), is_list(SID),
is_record(From, jid), is_record(To, jid) ->
case create_image() of
case create_image(Limiter) of
{ok, Type, Key, Image} ->
Id = randoms:get_string(),
B64Image = jlib:encode_base64(binary_to_list(Image)),
JID = jlib:jid_to_string(From),
CID = "sha1+" ++ sha:sha(Image) ++ "@bob.xmpp.org",
@@ -91,7 +94,8 @@ create_captcha(Id, SID, From, To, Lang, Args)
?VFIELD("hidden", "challenge", {xmlcdata, Id}),
?VFIELD("hidden", "sid", {xmlcdata, SID}),
{xmlelement, "field", [{"var", "ocr"}, {"label", ?CAPTCHA_TEXT(Lang)}],
[{xmlelement, "media", [{"xmlns", ?NS_MEDIA}],
[{xmlelement, "required", [], []},
{xmlelement, "media", [{"xmlns", ?NS_MEDIA}],
[{xmlelement, "uri", [{"type", Type}],
[{xmlcdata, "cid:" ++ CID}]}]}]}]}]},
BodyString1 = translate:translate(Lang, "Your messages to ~s are being blocked. To unblock them, visit ~s"),
@@ -104,12 +108,61 @@ create_captcha(Id, SID, From, To, Lang, Args)
case ?T(mnesia:write(#captcha{id=Id, pid=self(), key=Key,
tref=Tref, args=Args})) of
ok ->
{ok, [Body, OOB, Captcha, Data]};
_Err ->
error
{ok, Id, [Body, OOB, Captcha, Data]};
Err ->
{error, Err}
end;
_Err ->
error
Err ->
Err
end.
create_captcha_x(SID, To, Lang, Limiter, HeadEls) ->
create_captcha_x(SID, To, Lang, Limiter, HeadEls, []).
create_captcha_x(SID, To, Lang, Limiter, HeadEls, TailEls) ->
case create_image(Limiter) of
{ok, Type, Key, Image} ->
Id = randoms:get_string(),
B64Image = jlib:encode_base64(binary_to_list(Image)),
CID = "sha1+" ++ sha:sha(Image) ++ "@bob.xmpp.org",
Data = {xmlelement, "data",
[{"xmlns", ?NS_BOB}, {"cid", CID},
{"max-age", "0"}, {"type", Type}],
[{xmlcdata, B64Image}]},
HelpTxt = translate:translate(
Lang,
"If you don't see the CAPTCHA image here, "
"visit the web page."),
Imageurl = get_url(Id ++ "/image"),
Captcha =
{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}],
[?VFIELD("hidden", "FORM_TYPE", {xmlcdata, ?NS_CAPTCHA}) | HeadEls] ++
[{xmlelement, "field", [{"type", "fixed"}],
[{xmlelement, "value", [], [{xmlcdata, HelpTxt}]}]},
{xmlelement, "field", [{"type", "hidden"}, {"var", "captchahidden"}],
[{xmlelement, "value", [], [{xmlcdata, "workaround-for-psi"}]}]},
{xmlelement, "field",
[{"type", "text-single"},
{"label", translate:translate(Lang, "CAPTCHA web page")},
{"var", "url"}],
[{xmlelement, "value", [], [{xmlcdata, Imageurl}]}]},
?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, "required", [], []},
{xmlelement, "media", [{"xmlns", ?NS_MEDIA}],
[{xmlelement, "uri", [{"type", Type}],
[{xmlcdata, "cid:" ++ CID}]}]}]}] ++ TailEls},
Tref = erlang:send_after(?CAPTCHA_LIFETIME, ?MODULE, {remove_id, Id}),
case ?T(mnesia:write(#captcha{id=Id, key=Key, tref=Tref})) of
ok ->
{ok, [Captcha, Data]};
Err ->
{error, Err}
end;
Err ->
Err
end.
%% @spec (Id::string(), Lang::string()) -> {FormEl, {ImgEl, TextEl, IdEl, KeyEl}} | captcha_not_found
@@ -155,10 +208,18 @@ check_captcha(Id, ProvidedKey) ->
mnesia:delete({captcha, Id}),
erlang:cancel_timer(Tref),
if StoredKey == ProvidedKey ->
Pid ! {captcha_succeed, Args},
if is_pid(Pid) ->
Pid ! {captcha_succeed, Args};
true ->
ok
end,
captcha_valid;
true ->
Pid ! {captcha_failed, Args},
if is_pid(Pid) ->
Pid ! {captcha_failed, Args};
true ->
ok
end,
captcha_non_valid
end;
_ ->
@@ -166,24 +227,32 @@ check_captcha(Id, ProvidedKey) ->
end).
process_reply({xmlelement, "captcha", _, _} = El) ->
process_reply({xmlelement, _, _, _} = El) ->
case xml:get_subtag(El, "x") of
false ->
{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},
if is_pid(Pid) ->
Pid ! {captcha_succeed, Args};
true ->
ok
end,
ok;
true ->
Pid ! {captcha_failed, Args},
if is_pid(Pid) ->
Pid ! {captcha_failed, Args};
true ->
ok
end,
{error, bad_match}
end;
_ ->
@@ -208,16 +277,19 @@ process(_Handlers, #request{method='GET', lang=Lang, path=[_, Id]}) ->
ejabberd_web:error(not_found)
end;
process(_Handlers, #request{method='GET', path=[_, Id, "image"]}) ->
process(_Handlers, #request{method='GET', path=[_, Id, "image"], ip = IP}) ->
{Addr, _Port} = IP,
case mnesia:dirty_read(captcha, Id) of
[#captcha{key=Key}] ->
case create_image(Key) of
case create_image(Addr, Key) of
{ok, Type, _, Img} ->
{200,
[{"Content-Type", Type},
{"Cache-Control", "no-cache"},
{"Last-Modified", httpd_util:rfc1123_date()}],
Img};
{error, limit} ->
ejabberd_web:error(not_allowed);
_ ->
ejabberd_web:error(not_found)
end;
@@ -256,6 +328,20 @@ init([]) ->
check_captcha_setup(),
{ok, #state{}}.
handle_call({is_limited, Limiter, RateLimit}, _From, State) ->
NowPriority = now_priority(),
CleanPriority = NowPriority + ?LIMIT_PERIOD,
Limits = clean_treap(State#state.limits, CleanPriority),
case treap:lookup(Limiter, Limits) of
{ok, _, Rate} when Rate >= RateLimit ->
{reply, true, State#state{limits = Limits}};
{ok, Priority, Rate} ->
NewLimits = treap:insert(Limiter, Priority, Rate+1, Limits),
{reply, false, State#state{limits = NewLimits}};
_ ->
NewLimits = treap:insert(Limiter, NowPriority, 1, Limits),
{reply, false, State#state{limits = NewLimits}}
end;
handle_call(_Request, _From, State) ->
{reply, bad_request, State}.
@@ -266,7 +352,11 @@ 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},
if is_pid(Pid) ->
Pid ! {captcha_failed, Args};
true ->
ok
end,
mnesia:delete({captcha, Id});
_ ->
ok
@@ -293,11 +383,22 @@ code_change(_OldVsn, State, _Extra) ->
%% Reason = atom()
%%--------------------------------------------------------------------
create_image() ->
create_image(undefined).
create_image(Limiter) ->
%% Six numbers from 1 to 9.
Key = string:substr(randoms:get_string(), 1, 6),
create_image(Key).
create_image(Limiter, Key).
create_image(Key) ->
create_image(Limiter, Key) ->
case is_limited(Limiter) of
true ->
{error, limit};
false ->
do_create_image(Key)
end.
do_create_image(Key) ->
FileName = get_prog_name(),
Cmd = lists:flatten(io_lib:format("~s ~s", [FileName, Key])),
case cmd(Cmd) of
@@ -327,20 +428,82 @@ get_prog_name() ->
case ejabberd_config:get_local_option(captcha_cmd) of
FileName when is_list(FileName) ->
FileName;
_ ->
Value when (Value == undefined) or (Value == "") ->
?DEBUG("The option captcha_cmd is not configured, but some "
"module wants to use the CAPTCHA feature.", []),
throw({error, option_not_configured_captcha_cmd})
false
end.
get_url(Str) ->
case ejabberd_config:get_local_option(captcha_host) of
Host when is_list(Host) ->
CaptchaHost = ejabberd_config:get_local_option(captcha_host),
case string:tokens(CaptchaHost, ":") of
[Host] ->
"http://" ++ Host ++ "/captcha/" ++ Str;
["http"++_ = TransferProt, Host] ->
TransferProt ++ ":" ++ Host ++ "/captcha/" ++ Str;
[Host, PortString] ->
TransferProt = atom_to_list(get_transfer_protocol(PortString)),
TransferProt ++ "://" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str;
[TransferProt, Host, PortString] ->
TransferProt ++ ":" ++ Host ++ ":" ++ PortString ++ "/captcha/" ++ Str;
_ ->
"http://" ++ ?MYNAME ++ "/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).
is_limited(undefined) ->
false;
is_limited(Limiter) ->
case ejabberd_config:get_local_option(captcha_limit) of
Int when is_integer(Int), Int > 0 ->
case catch gen_server:call(?MODULE, {is_limited, Limiter, Int},
5000) of
true ->
true;
false ->
false;
Err ->
?ERROR_MSG("Call failed: ~p", [Err]),
false
end;
_ ->
false
end.
%%--------------------------------------------------------------------
%% Function: cmd(Cmd) -> Data | {error, Reason}
%% Cmd = string()
@@ -389,28 +552,41 @@ return(Port, TRef, Result) ->
catch port_close(Port),
Result.
is_feature_enabled() ->
try get_prog_name() of
Prog when is_list(Prog) -> true
catch
_:_ -> false
end.
is_feature_available() ->
case is_feature_enabled() of
false -> false;
true ->
case create_image() of
{ok, _, _, _} -> true;
_Error -> false
end
case get_prog_name() of
Prog when is_list(Prog) -> true;
false -> false
end.
check_captcha_setup() ->
case is_feature_enabled() andalso not is_feature_available() of
case is_feature_available() of
true ->
?CRITICAL_MSG("Captcha is enabled in the option captcha_cmd, "
"but it can't generate images.", []);
case create_image() of
{ok, _, _, _} ->
ok;
_Err ->
?CRITICAL_MSG("Captcha is enabled in the option captcha_cmd, "
"but it can't generate images.", []),
throw({error, captcha_cmd_enabled_but_fails})
end;
false ->
ok
end.
clean_treap(Treap, CleanPriority) ->
case treap:is_empty(Treap) of
true ->
Treap;
false ->
{_Key, Priority, _Value} = treap:get_root(Treap),
if
Priority > CleanPriority ->
clean_treap(treap:delete_root(Treap), CleanPriority);
true ->
Treap
end
end.
now_priority() ->
{MSec, Sec, USec} = now(),
-((MSec*1000000 + Sec)*1000000 + USec).
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 27 Feb 2008 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 20 May 2008 by Badlop <badlop@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+4 -2
View File
@@ -5,7 +5,7 @@
%%% Created : 14 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -215,7 +215,7 @@ exit_or_halt(ExitText) ->
case [Vsn || {ejabberd, _Desc, Vsn} <- application:which_applications()] of
[] ->
timer:sleep(1000),
halt(ExitText);
halt(string:substr(ExitText, 1, 199));
[_] ->
exit(ExitText)
end.
@@ -431,6 +431,8 @@ process_term(Term, State) ->
add_option(captcha_cmd, Cmd, State);
{captcha_host, Host} ->
add_option(captcha_host, Host, State);
{captcha_limit, Limit} ->
add_option(captcha_limit, Limit, State);
{ejabberdctl_access_commands, ACs} ->
add_option(ejabberdctl_access_commands, ACs, State);
{loglevel, Loglevel} ->
+1 -1
View File
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+6 -3
View File
@@ -5,7 +5,7 @@
%%% Created : 11 Jan 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -201,8 +201,7 @@ process(Args) ->
case String of
[] -> ok;
_ ->
io:format(String),
io:format("\n")
io:format("~s~n", [String])
end,
Code.
@@ -742,6 +741,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-2010 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-2010 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License
%%% along with this program; if not, write to the Free Software
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
%%% 02111-1307 USA
%%%
%%%----------------------------------------------------------------------
-module(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.
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 23 Aug 2006 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 8 Aug 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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 -32
View File
@@ -5,7 +5,7 @@
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -48,8 +48,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 ->
@@ -99,15 +133,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 ->
@@ -128,28 +154,39 @@ init_udp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
end.
init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
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} ->
%% 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}
@@ -194,6 +231,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) ->
+19 -5
View File
@@ -5,7 +5,7 @@
%%% Created : 30 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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,
@@ -123,19 +125,31 @@ 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),
register_iq_response_handler(Host, ID, undefined, F, Timeout),
jlib:iq_to_xml(IQ#iq{id = ID});
true ->
jlib:iq_to_xml(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),
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),
mnesia:dirty_write(#iq_response{id = ID,
module = Module,
function = Function,
+14 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 23 Oct 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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.
+118 -52
View File
@@ -9,7 +9,7 @@
%%% Created : 29 Nov 2006 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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,32 +31,59 @@
-module(ejabberd_loglevel).
-author('mickael.remond@process-one.net').
-export([set/1, get/0]).
-export([set/1,
get/0,
set_custom/2,
clear_custom/0,
clear_custom/1]).
-include("ejabberd.hrl").
-define(LOGMODULE, "error_logger").
%% Error levels:
-define(LOG_LEVELS,[ {0, no_log, "No log"}
,{1, critical, "Critical"}
,{2, error, "Error"}
,{3, warning, "Warning"}
,{4, info, "Info"}
,{5, debug, "Debug"}
]).
-record(loglevel, {ordinal,
name,
description,
function = no_log,
event_type = no_log,
msg_prefix = no_log}).
-define(LOG_LEVELS,
[#loglevel{ordinal = 0, name = no_log, description = "No log"},
#loglevel{ordinal = 1, name = critical, description = "Critical",
function = critical_msg, event_type = error, msg_prefix = "C"},
#loglevel{ordinal = 2, name = error, description = "Error",
function = error_msg, event_type = error, msg_prefix = "E"},
#loglevel{ordinal = 3, name = warning, description = "Warning",
function = warning_msg, event_type = warning_msg, msg_prefix = "W"},
#loglevel{ordinal = 4, name = info, description = "Info",
function = info_msg, event_type = info_msg, msg_prefix = "I"},
#loglevel{ordinal = 5, name = debug, description = "Debug",
function = debug_msg, event_type = info_msg, msg_prefix = "D"}]).
%% @type level() = integer() | atom().
%% @spec () -> {DefaultLevelOrdinal::integer(), [{Module::atom(), LevelOrdinal::integer()}]}
%% @doc Get the default and all custom levels
get() ->
Level = ejabberd_logger:get(),
case lists:keysearch(Level, 1, ?LOG_LEVELS) of
{value, Result} -> Result;
_ -> erlang:error({no_such_loglevel, Level})
{DefaultLevel, _CustomLevels} = ejabberd_logger:get(),
case lists:keysearch(DefaultLevel, #loglevel.ordinal, ?LOG_LEVELS) of
{value, Result = #loglevel{}} ->
{Result#loglevel.ordinal, Result#loglevel.name, Result#loglevel.description};
_ ->
erlang:error({no_such_loglevel, DefaultLevel})
end.
set(LogLevel) when is_atom(LogLevel) ->
set(level_to_integer(LogLevel));
set(Loglevel) when is_integer(Loglevel) ->
%% @spec (DefaultLevel::level() | {DefaultLevel::level(), [{Module::atom(), Level::level()}]}) ->
%% {module, ejabberd_logger}
%% @doc Set the default and all custom levels
set(DefaultLevel) when is_atom(DefaultLevel) orelse is_integer(DefaultLevel) ->
set({DefaultLevel, []});
set({DefaultLevel, CustomLevels}) when is_list(CustomLevels) ->
DefaultInt = level_to_integer(DefaultLevel),
CustomInts = [level_to_integer(C) || C <- CustomLevels],
Loglevel = {DefaultInt, CustomInts},
try
{Mod,Code} = dynamic_compile:from_string(ejabberd_logger_src(Loglevel)),
code:load_binary(Mod, ?LOGMODULE ++ ".erl", Code)
@@ -64,11 +91,45 @@ set(Loglevel) when is_integer(Loglevel) ->
Type:Error -> ?CRITICAL_MSG("Error compiling logger (~p): ~p~n", [Type, Error])
end;
set(_) ->
exit("Loglevel must be an integer").
exit("Invalid loglevel format").
%% @spec (Module::atom(), CustomLevel::level()) -> ok
%% @doc Set a custom level
set_custom(Module, Level) ->
{DefaultLevel, CustomLevels} = ejabberd_logger:get(),
case lists:keysearch(Module, 1, CustomLevels) of
{value, {Module, Level}} ->
ok;
{value, _} ->
set({DefaultLevel, lists:keyreplace(Module, 1, CustomLevels, {Module, Level})});
_ ->
set({DefaultLevel, [{Module, Level} | CustomLevels]})
end.
%% @spec () -> ok
%% @doc Clear all custom levels
clear_custom() ->
{DefaultLevel, _CustomLevels} = ejabberd_logger:get(),
set({DefaultLevel, []}).
%% @spec (Module::atom()) -> ok
%% @doc Clear a custom level
clear_custom(Module) ->
{DefaultLevel, CustomLevels} = ejabberd_logger:get(),
case lists:keysearch(Module, 1, CustomLevels) of
{value, _} ->
set({DefaultLevel, lists:keydelete(Module, 1, CustomLevels)});
_ ->
ok
end.
level_to_integer(Level) when is_integer(Level) ->
Level;
level_to_integer({Module, Level}) ->
{Module, level_to_integer(Level)};
level_to_integer(Level) ->
case lists:keysearch(Level, 2, ?LOG_LEVELS) of
{value, {Int, Level, _Desc}} -> Int;
case lists:keysearch(Level, #loglevel.name, ?LOG_LEVELS) of
{value, #loglevel{ordinal = Int}} -> Int;
_ -> erlang:error({no_such_loglevel, Level})
end.
@@ -77,7 +138,12 @@ level_to_integer(Level) ->
%% This allows to dynamically change log level while keeping a
%% very efficient code.
ejabberd_logger_src(Loglevel) ->
L = integer_to_list(Loglevel),
lists:flatten([header_src(),
get_src(Loglevel),
[log_src(Loglevel, LevelSpec) || LevelSpec <- ?LOG_LEVELS],
notify_src()]).
header_src() ->
"-module(ejabberd_logger).
-author('mickael.remond@process-one.net').
@@ -87,42 +153,42 @@ ejabberd_logger_src(Loglevel) ->
error_msg/4,
critical_msg/4,
get/0]).
".
get() -> "++ L ++".
get_src(Loglevel) ->
io_lib:format("get() -> ~w.
", [Loglevel]).
%% Helper functions
debug_msg(Module, Line, Format, Args) when " ++ L ++ " >= 5 ->
notify(info_msg,
\"D(~p:~p:~p) : \"++Format++\"~n\",
[self(), Module, Line]++Args);
debug_msg(_,_,_,_) -> ok.
log_src(_Loglevel, #loglevel{function = no_log}) ->
[];
log_src({DefaultLevel, [{Module, Level} | Tail]}, Spec = #loglevel{ordinal = MinLevel})
when Level < MinLevel andalso MinLevel =< DefaultLevel ->
[atom_to_list(Spec#loglevel.function), "(", atom_to_list(Module), ", _, _, _) -> ok;
", log_src({DefaultLevel, Tail}, Spec)];
log_src({DefaultLevel, [{Module, Level} | Tail]}, Spec = #loglevel{ordinal = MinLevel})
when DefaultLevel < MinLevel andalso MinLevel =< Level ->
[atom_to_list(Spec#loglevel.function), "(", atom_to_list(Module), " = Module, Line, Format, Args) ->",
log_notify_src(Spec), ";
", log_src({DefaultLevel, Tail}, Spec)];
log_src({DefaultLevel, [_Head | Tail]}, Spec = #loglevel{}) ->
log_src({DefaultLevel, Tail}, Spec);
log_src({DefaultLevel, []}, Spec = #loglevel{ordinal = MinLevel})
when DefaultLevel < MinLevel ->
[atom_to_list(Spec#loglevel.function), "(_, _, _, _) -> ok.
"];
log_src({_DefaultLevel, []}, Spec = #loglevel{}) ->
[atom_to_list(Spec#loglevel.function), "(Module, Line, Format, Args) ->",
log_notify_src(Spec), ".
"].
info_msg(Module, Line, Format, Args) when " ++ L ++ " >= 4 ->
notify(info_msg,
\"I(~p:~p:~p) : \"++Format++\"~n\",
[self(), Module, Line]++Args);
info_msg(_,_,_,_) -> ok.
warning_msg(Module, Line, Format, Args) when " ++ L ++ " >= 3 ->
notify(error,
\"W(~p:~p:~p) : \"++Format++\"~n\",
[self(), Module, Line]++Args);
warning_msg(_,_,_,_) -> ok.
error_msg(Module, Line, Format, Args) when " ++ L ++ " >= 2 ->
notify(error,
\"E(~p:~p:~p) : \"++Format++\"~n\",
[self(), Module, Line]++Args);
error_msg(_,_,_,_) -> ok.
critical_msg(Module, Line, Format, Args) when " ++ L ++ " >= 1 ->
notify(error,
\"C(~p:~p:~p) : \"++Format++\"~n\",
[self(), Module, Line]++Args);
critical_msg(_,_,_,_) -> ok.
log_notify_src(Spec = #loglevel{}) ->
["notify(", atom_to_list(Spec#loglevel.event_type), ",
\"", Spec#loglevel.msg_prefix, "(~p:~p:~p) : \"++Format++\"~n\",
[self(), Module, Line | Args])"].
notify_src() ->
%% Distribute the message to the Erlang error logger
notify(Type, Format, Args) ->
"notify(Type, Format, Args) ->
LoggerMsg = {Type, group_leader(), {self(), Format, Args}},
gen_event:notify(error_logger, LoggerMsg).
".
+12 -6
View File
@@ -5,7 +5,7 @@
%%% Created : 1 Nov 2006 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -40,6 +40,12 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-ifdef(SSL40).
-define(PG2, pg2).
-else.
-define(PG2, pg2_backport).
-endif.
-record(state, {}).
%%====================================================================
@@ -54,20 +60,20 @@ start_link() ->
join(Name) ->
PG = {?MODULE, Name},
pg2:create(PG),
pg2:join(PG, whereis(?MODULE)).
?PG2:create(PG),
?PG2:join(PG, whereis(?MODULE)).
leave(Name) ->
PG = {?MODULE, Name},
pg2:leave(PG, whereis(?MODULE)).
?PG2:leave(PG, whereis(?MODULE)).
get_members(Name) ->
PG = {?MODULE, Name},
[node(P) || P <- pg2:get_members(PG)].
[node(P) || P <- ?PG2:get_members(PG)].
get_closest_node(Name) ->
PG = {?MODULE, Name},
node(pg2:get_closest_pid(PG)).
node(?PG2:get_closest_pid(PG)).
%%====================================================================
%% gen_server callbacks
+28 -18
View File
@@ -5,7 +5,7 @@
%%% Created : 17 Jul 2008 by Pablo Polvorin <pablo.polvorin@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -153,8 +153,8 @@ process_elements(Elements,State) ->
process_element(El=#xmlel{name=user, ns=_XMLNS},
State=#parsing_state{host=Host}) ->
case add_user(El,Host) of
{error, _Other} -> error;
_ -> ok
ok -> ok;
{error, _Other} -> error
end,
State;
@@ -196,34 +196,44 @@ process_element(El,State) ->
add_user(El, Domain) ->
User = exmpp_xml:get_attribute(El,name,none),
Password = exmpp_xml:get_attribute(El,password,none),
add_user(El, Domain, ?BTL(User), ?BTL(Password)).
add_user(El, Domain, User, Password).
%% @spec (El::xmlel(), Domain::string(), User::string(), Password::string())
%% -> ok | {atomic, exists} | {error, not_allowed}
%% @spec (El::xmlel(), Domain::string(), User::binary(), Password::binary() | none)
%% -> ok | {error, ErrorText::string()}
%% @doc Add a new user to the database.
%% If user already exists, it will be only updated.
add_user(El, Domain, User, Password) ->
add_user(El, Domain, UserBinary, none) ->
User = ?BTL(UserBinary),
io:format("Account ~s@~s will not be created, updating it...~n",
[User, Domain]),
io:format(""),
populate_user_with_elements(El, Domain, User),
ok;
add_user(El, Domain, UserBinary, PasswordBinary) ->
User = ?BTL(UserBinary),
Password = ?BTL(PasswordBinary),
case create_user(User,Password,Domain) of
ok ->
ok = exmpp_xml:foreach(
fun(_,Child) ->
populate_user(User,Domain,Child)
end,
El),
populate_user_with_elements(El, Domain, User),
ok;
{atomic, exists} ->
io:format("Account ~s@~s already exists, updating it...~n",
[User, Domain]),
io:format(""),
ok = exmpp_xml:foreach(
fun(_,Child) ->
populate_user(User,Domain,Child)
end,
El);
populate_user_with_elements(El, Domain, User),
ok;
{error, Other} ->
?ERROR_MSG("Error adding user ~s@~s: ~p~n", [User, Domain, Other])
?ERROR_MSG("Error adding user ~s@~s: ~p~n", [User, Domain, Other]),
{error, Other}
end.
populate_user_with_elements(El, Domain, User) ->
exmpp_xml:foreach(
fun (_,Child) ->
populate_user(User,Domain,Child)
end,
El).
%% @spec (User::string(), Password::string(), Domain::string())
%% -> ok | {atomic, exists} | {error, not_allowed}
%% @doc Create a new user
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 10 Nov 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 27 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+20 -19
View File
@@ -5,7 +5,7 @@
%%% Created : 7 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -37,6 +37,7 @@
get_connections_pids/1,
try_register/1,
remove_connection/3,
find_connection/2,
dirty_get_connections/0,
allow_host/2,
incoming_s2s_number/0,
@@ -408,22 +409,21 @@ needed_connections_number(Ls, MaxS2SConnectionsNumber,
is_service(From, To) ->
LFromDomain = From#jid.lserver,
case ejabberd_config:get_local_option({route_subdomains, LFromDomain}) of
s2s -> % bypass RFC 3920 10.3
false;
_ ->
LDstDomain = To#jid.lserver,
P = fun(Domain) -> is_subdomain(LDstDomain, Domain) end,
lists:any(P, ?MYHOSTS)
s2s -> % bypass RFC 3920 10.3
false;
_ ->
Hosts = ?MYHOSTS,
P = fun(ParentDomain) -> lists:member(ParentDomain, Hosts) end,
lists:any(P, parent_domains(To#jid.lserver))
end.
%%--------------------------------------------------------------------
%% Function: is_subdomain(Domain1, Domain2) -> true | false
%% Description: Return true if Domain1 (a string representing an
%% internet domain name) is a subdomain (or the same domain) of
%% Domain2
%% --------------------------------------------------------------------
is_subdomain(Domain1, Domain2) ->
lists:suffix(string:tokens(Domain2, "."), string:tokens(Domain1, ".")).
parent_domains(Domain) ->
lists:foldl(
fun(Label, []) ->
[Label];
(Label, [Head | Tail]) ->
[Label ++ "." ++ Head, Head | Tail]
end, [], lists:reverse(string:tokens(Domain, "."))).
send_element(Pid, El) ->
Pid ! {send_element, El}.
@@ -486,10 +486,11 @@ update_tables() ->
%% Check if host is in blacklist or white list
allow_host(MyServer, S2SHost) ->
case lists:filter(
fun(Host) ->
is_subdomain(MyServer, Host)
end, ?MYHOSTS) of
Hosts = ?MYHOSTS,
case lists:dropwhile(
fun(ParentDomain) ->
not lists:member(ParentDomain, Hosts)
end, parent_domains(MyServer)) of
[MyHost|_] ->
allow_host1(MyHost, S2SHost);
[] ->
+73 -30
View File
@@ -5,7 +5,7 @@
%%% Created : 6 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -48,6 +48,11 @@
-include("ejabberd.hrl").
-include("jlib.hrl").
-ifdef(SSL40).
-include_lib("public_key/include/public_key.hrl").
-define(PKIXEXPLICIT, 'OTP-PUB-KEY').
-define(PKIXIMPLICIT, 'OTP-PUB-KEY').
-else.
-ifdef(SSL39).
-include_lib("ssl/include/ssl_pkix.hrl").
-define(PKIXEXPLICIT, 'OTP-PKIX').
@@ -58,6 +63,7 @@
-define(PKIXEXPLICIT, 'PKIX1Explicit88').
-define(PKIXIMPLICIT, 'PKIX1Implicit88').
-endif.
-endif.
-include("XmppAddr.hrl").
-define(DICT, dict).
@@ -68,7 +74,10 @@
shaper,
tls = false,
tls_enabled = false,
tls_required = false,
tls_certverify = false,
tls_options = [],
server,
authenticated = false,
auth_domain,
connections = ?DICT:new(),
@@ -144,12 +153,16 @@ init([{SockMod, Socket}, Opts]) ->
{value, {_, S}} -> S;
_ -> none
end,
StartTLS = case ejabberd_config:get_local_option(s2s_use_starttls) of
undefined ->
false;
UseStartTLS ->
UseStartTLS
end,
{StartTLS, TLSRequired, TLSCertverify} = case ejabberd_config:get_local_option(s2s_use_starttls) of
UseTls when (UseTls==undefined) or (UseTls==false) ->
{false, false, false};
UseTls when (UseTls==true) or (UseTls==optional) ->
{true, false, false};
required ->
{true, true, false};
required_trusted ->
{true, true, true}
end,
TLSOpts = case ejabberd_config:get_local_option(s2s_certfile) of
undefined ->
[];
@@ -164,6 +177,8 @@ init([{SockMod, Socket}, Opts]) ->
shaper = Shaper,
tls = StartTLS,
tls_enabled = false,
tls_required = TLSRequired,
tls_certverify = TLSCertverify,
tls_options = TLSOpts,
timer = Timer}}.
@@ -187,16 +202,18 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
StateData#state.tls_enabled ->
case (StateData#state.sockmod):get_peer_certificate(
StateData#state.socket) of
{ok, _Cert} ->
case (StateData#state.sockmod):get_verify_result(
StateData#state.socket) of
{ok, Cert} ->
case (StateData#state.sockmod):get_verify_result(StateData#state.socket) of
0 ->
[{xmlelement, "mechanisms",
[{"xmlns", ?NS_SASL}],
[{xmlelement, "mechanism", [],
[{xmlcdata, "EXTERNAL"}]}]}];
_ ->
[]
CertVerifyRes ->
case StateData#state.tls_certverify of
true -> {error_cert_verif, CertVerifyRes, Cert};
false -> []
end
end;
error ->
[]
@@ -207,18 +224,33 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
StartTLS = if
StateData#state.tls_enabled ->
[];
true ->
[{xmlelement, "starttls",
[{"xmlns", ?NS_TLS}], []}]
(not StateData#state.tls_enabled) and (not StateData#state.tls_required) ->
[{xmlelement, "starttls", [{"xmlns", ?NS_TLS}], []}];
(not StateData#state.tls_enabled) and StateData#state.tls_required ->
[{xmlelement, "starttls", [{"xmlns", ?NS_TLS}],
[{xmlelement, "required", [], []}]
}]
end,
send_element(StateData,
{xmlelement, "stream:features", [],
SASL ++ StartTLS ++
ejabberd_hooks:run_fold(
s2s_stream_features,
Server,
[], [Server])}),
{next_state, wait_for_feature_request, StateData};
case SASL of
{error_cert_verif, CertVerifyResult, Certificate} ->
CertError = tls:get_cert_verify_string(CertVerifyResult, Certificate),
RemoteServer = xml:get_attr_s("from", Attrs),
?INFO_MSG("Closing s2s connection: ~s <--> ~s (~s)", [StateData#state.server, RemoteServer, CertError]),
send_text(StateData, xml:element_to_string(?SERRT_POLICY_VIOLATION("en", CertError))),
{atomic, Pid} = ejabberd_s2s:find_connection(jlib:make_jid("", Server, ""), jlib:make_jid("", RemoteServer, "")),
ejabberd_s2s_out:stop_connection(Pid),
{stop, normal, StateData};
_ ->
send_element(StateData,
{xmlelement, "stream:features", [],
SASL ++ StartTLS ++
ejabberd_hooks:run_fold(
s2s_stream_features,
Server,
[], [Server])}),
{next_state, wait_for_feature_request, StateData#state{server = Server}}
end;
{"jabber:server", _, Server, true} when
StateData#state.authenticated ->
send_text(StateData, ?STREAM_HEADER(" version='1.0'")),
@@ -260,15 +292,26 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
SockMod == gen_tcp ->
?DEBUG("starttls", []),
Socket = StateData#state.socket,
TLSOpts = StateData#state.tls_options,
TLSOpts = case ejabberd_config:get_local_option(
{domain_certfile,
StateData#state.server}) of
undefined ->
StateData#state.tls_options;
CertFile ->
[{certfile, CertFile} |
lists:keydelete(
certfile, 1,
StateData#state.tls_options)]
end,
TLSSocket = (StateData#state.sockmod):starttls(
Socket, TLSOpts,
xml:element_to_string(
xml:element_to_binary(
{xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []})),
{next_state, wait_for_stream,
StateData#state{socket = TLSSocket,
streamid = new_id(),
tls_enabled = true
tls_enabled = true,
tls_options = TLSOpts
}};
{?NS_SASL, "auth"} when TLSEnabled ->
Mech = xml:get_attr_s("mechanism", Attrs),
@@ -358,11 +401,11 @@ stream_established({xmlstreamelement, El}, StateData) ->
LFrom = jlib:nameprep(From),
%% Checks if the from domain is allowed and if the to
%% domain is handled by this server:
case {ejabberd_s2s:allow_host(To, From),
case {ejabberd_s2s:allow_host(LTo, LFrom),
lists:member(LTo, ejabberd_router:dirty_get_all_domains())} of
{true, true} ->
ejabberd_s2s_out:terminate_if_waiting_delay(To, From),
ejabberd_s2s_out:start(To, From,
ejabberd_s2s_out:terminate_if_waiting_delay(LTo, LFrom),
ejabberd_s2s_out:start(LTo, LFrom,
{verify, self(),
Key, StateData#state.streamid}),
Conns = ?DICT:store({LFrom, LTo}, wait_for_verification,
@@ -618,7 +661,7 @@ send_text(StateData, Text) ->
(StateData#state.sockmod):send(StateData#state.socket, Text).
send_element(StateData, El) ->
send_text(StateData, xml:element_to_string(El)).
send_text(StateData, xml:element_to_binary(El)).
change_shaper(StateData, Host, JID) ->
+76 -26
View File
@@ -5,7 +5,7 @@
%%% Created : 6 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -44,6 +44,7 @@
wait_for_features/2,
wait_for_auth_result/2,
wait_for_starttls_proceed/2,
relay_to_bridge/2,
reopen_socket/2,
wait_before_retry/2,
stream_established/2,
@@ -65,13 +66,14 @@
tls = false,
tls_required = false,
tls_enabled = false,
tls_options = [],
tls_options = [connect],
authenticated = false,
db_enabled = true,
try_auth = true,
myname, server, queue,
delay_to_retry = undefined_delay,
new = false, verify = false,
bridge,
timer}).
%%-define(DBGFSM, true).
@@ -106,6 +108,7 @@
"xmlns:stream='http://etherx.jabber.org/streams' "
"xmlns='jabber:server' "
"xmlns:db='jabber:server:dialback' "
"from='~s' "
"to='~s'~s>"
).
@@ -136,7 +139,7 @@ start_connection(Pid) ->
p1_fsm:send_event(Pid, init).
stop_connection(Pid) ->
p1_fsm:send_event(Pid, stop).
p1_fsm:send_event(Pid, closed).
%%%----------------------------------------------------------------------
%%% Callback functions from p1_fsm
@@ -152,16 +155,18 @@ stop_connection(Pid) ->
init([From, Server, Type]) ->
process_flag(trap_exit, true),
?DEBUG("started: ~p", [{From, Server, Type}]),
TLS = case ejabberd_config:get_local_option(s2s_use_starttls) of
undefined ->
false;
UseStartTLS ->
UseStartTLS
{TLS, TLSRequired} = case ejabberd_config:get_local_option(s2s_use_starttls) of
UseTls when (UseTls==undefined) or (UseTls==false) ->
{false, false};
UseTls when (UseTls==true) or (UseTls==optional) ->
{true, false};
UseTls when (UseTls==required) or (UseTls==required_trusted) ->
{true, true}
end,
UseV10 = TLS,
TLSOpts = case ejabberd_config:get_local_option(s2s_certfile) of
undefined ->
[];
[connect];
CertFile ->
[{certfile, CertFile}, connect]
end,
@@ -175,6 +180,7 @@ init([From, Server, Type]) ->
Timer = erlang:start_timer(?S2STIMEOUT, self(), []),
{ok, open_socket, #state{use_v10 = UseV10,
tls = TLS,
tls_required = TLSRequired,
tls_options = TLSOpts,
queue = queue:new(),
myname = From,
@@ -192,7 +198,8 @@ init([From, Server, Type]) ->
open_socket(init, StateData) ->
log_s2s_out(StateData#state.new,
StateData#state.myname,
StateData#state.server),
StateData#state.server,
StateData#state.tls),
?DEBUG("open_socket: ~p", [{StateData#state.myname,
StateData#state.server,
StateData#state.new,
@@ -221,16 +228,27 @@ open_socket(init, StateData) ->
tls_enabled = false,
streamid = new_id()},
send_text(NewStateData, io_lib:format(?STREAM_HEADER,
[StateData#state.server,
[StateData#state.myname, StateData#state.server,
Version])),
{next_state, wait_for_stream, NewStateData, ?FSMTIMEOUT};
{error, _Reason} ->
?INFO_MSG("s2s connection: ~s -> ~s (remote server not found)",
[StateData#state.myname, StateData#state.server]),
wait_before_reconnect(StateData)
%%{stop, normal, StateData}
case ejabberd_hooks:run_fold(find_s2s_bridge,
undefined,
[StateData#state.myname,
StateData#state.server]) of
{Mod, Fun, Type} ->
?INFO_MSG("found a bridge to ~s for: ~s -> ~s",
[Type, StateData#state.myname,
StateData#state.server]),
NewStateData = StateData#state{bridge={Mod, Fun}},
{next_state, relay_to_bridge, NewStateData};
_ ->
wait_before_reconnect(StateData)
end
end;
open_socket(stop, StateData) ->
open_socket(closed, StateData) ->
?INFO_MSG("s2s connection: ~s -> ~s (stopped in open socket)",
[StateData#state.myname, StateData#state.server]),
{stop, normal, StateData};
@@ -298,6 +316,10 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
{"jabber:server", "jabber:server:dialback", true} when
StateData#state.use_v10 ->
{next_state, wait_for_features, StateData, ?FSMTIMEOUT};
%% Clause added to handle Tigase's workaround for an old ejabberd bug:
{"jabber:server", "jabber:server:dialback", true} when
not StateData#state.use_v10 ->
send_db_request(StateData);
{"jabber:server", "", true} when StateData#state.use_v10 ->
{next_state, wait_for_features, StateData#state{db_enabled = false}, ?FSMTIMEOUT};
{NSProvided, DB, _} ->
@@ -337,16 +359,21 @@ wait_for_validation({xmlstreamelement, El}, StateData) ->
case is_verify_res(El) of
{result, To, From, Id, Type} ->
?DEBUG("recv result: ~p", [{From, To, Id, Type}]),
case Type of
"valid" ->
case {Type, StateData#state.tls_enabled, StateData#state.tls_required} of
{"valid", Enabled, Required} when (Enabled==true) or (Required==false) ->
send_queue(StateData, StateData#state.queue),
?INFO_MSG("Connection established: ~s -> ~s",
[StateData#state.myname, StateData#state.server]),
?INFO_MSG("Connection established: ~s -> ~s with TLS=~p",
[StateData#state.myname, StateData#state.server, StateData#state.tls_enabled]),
ejabberd_hooks:run(s2s_connect_hook,
[StateData#state.myname,
StateData#state.server]),
{next_state, stream_established,
StateData#state{queue = queue:new()}};
{"valid", Enabled, Required} when (Enabled==false) and (Required==true) ->
%% TODO: bounce packets
?INFO_MSG("Closing s2s connection: ~s -> ~s (TLS is required but unavailable)",
[StateData#state.myname, StateData#state.server]),
{stop, normal, StateData};
_ ->
%% TODO: bounce packets
?INFO_MSG("Closing s2s connection: ~s -> ~s (invalid dialback key)",
@@ -539,7 +566,7 @@ wait_for_auth_result({xmlstreamelement, El}, StateData) ->
ejabberd_socket:reset_stream(StateData#state.socket),
send_text(StateData,
io_lib:format(?STREAM_HEADER,
[StateData#state.server,
[StateData#state.myname, StateData#state.server,
" version='1.0'"])),
{next_state, wait_for_stream,
StateData#state{streamid = new_id(),
@@ -607,7 +634,7 @@ wait_for_starttls_proceed({xmlstreamelement, El}, StateData) ->
Socket = StateData#state.socket,
TLSOpts = case ejabberd_config:get_local_option(
{domain_certfile,
StateData#state.server}) of
StateData#state.myname}) of
undefined ->
StateData#state.tls_options;
CertFile ->
@@ -619,11 +646,12 @@ wait_for_starttls_proceed({xmlstreamelement, El}, StateData) ->
TLSSocket = ejabberd_socket:starttls(Socket, TLSOpts),
NewStateData = StateData#state{socket = TLSSocket,
streamid = new_id(),
tls_enabled = true
tls_enabled = true,
tls_options = TLSOpts
},
send_text(NewStateData,
io_lib:format(?STREAM_HEADER,
[StateData#state.server,
[StateData#state.myname, StateData#state.server,
" version='1.0'"])),
{next_state, wait_for_stream, NewStateData, ?FSMTIMEOUT};
_ ->
@@ -676,6 +704,15 @@ reopen_socket(closed, StateData) ->
wait_before_retry(_Event, StateData) ->
{next_state, wait_before_retry, StateData, ?FSMTIMEOUT}.
relay_to_bridge(stop, StateData) ->
wait_before_reconnect(StateData);
relay_to_bridge(closed, StateData) ->
?INFO_MSG("relay to bridge: ~s -> ~s (closed)",
[StateData#state.myname, StateData#state.server]),
{stop, normal, StateData};
relay_to_bridge(_Event, StateData) ->
{next_state, relay_to_bridge, StateData}.
stream_established({xmlstreamelement, El}, StateData) ->
?DEBUG("s2S stream established", []),
case is_verify_res(El) of
@@ -826,6 +863,19 @@ handle_info({send_element, El}, StateName, StateData) ->
wait_before_retry ->
bounce_element(El, ?ERR_REMOTE_SERVER_NOT_FOUND),
{next_state, StateName, StateData};
relay_to_bridge ->
%% In this state we relay all outbound messages
%% to a foreign protocol bridge such as SMTP, SIP, etc.
{Mod, Fun} = StateData#state.bridge,
?DEBUG("relaying stanza via ~p:~p/1", [Mod, Fun]),
case catch Mod:Fun(El) of
{'EXIT', Reason} ->
?ERROR_MSG("Error while relaying to bridge: ~p", [Reason]),
bounce_element(El, ?ERR_INTERNAL_SERVER_ERROR),
wait_before_reconnect(StateData);
_ ->
{next_state, StateName, StateData}
end;
_ ->
Q = queue:in(El, StateData#state.queue),
{next_state, StateName, StateData#state{queue = Q},
@@ -892,7 +942,7 @@ send_text(StateData, Text) ->
ejabberd_socket:send(StateData#state.socket, Text).
send_element(StateData, El) ->
send_text(StateData, xml:element_to_string(El)).
send_text(StateData, xml:element_to_binary(El)).
send_queue(StateData, Q) ->
case queue:out(Q) of
@@ -1151,10 +1201,10 @@ outgoing_s2s_timeout() ->
%% Human readable S2S logging: Log only new outgoing connections as INFO
%% Do not log dialback
log_s2s_out(false, _, _) -> ok;
log_s2s_out(false, _, _, _) -> ok;
%% Log new outgoing connections:
log_s2s_out(_, Myname, Server) ->
?INFO_MSG("Trying to open s2s connection: ~s -> ~s",[Myname, Server]).
log_s2s_out(_, Myname, Server, Tls) ->
?INFO_MSG("Trying to open s2s connection: ~s -> ~s with TLS=~p", [Myname, Server, Tls]).
%% Calculate timeout depending on which state we are in:
%% Can return integer > 0 | infinity
+6 -3
View File
@@ -5,7 +5,7 @@
%%% Created : 6 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -347,12 +347,15 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
Attrs2 = jlib:replace_from_to_attrs(jlib:jid_to_string(From),
jlib:jid_to_string(To),
Attrs),
Text = xml:element_to_string({xmlelement, Name, Attrs2, Els}),
Text = xml:element_to_binary({xmlelement, Name, Attrs2, Els}),
send_text(StateData, Text);
deny ->
Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED),
ejabberd_router:route_error(To, From, Err, Packet)
end,
{next_state, StateName, StateData};
handle_info(Info, StateName, StateData) ->
?ERROR_MSG("Unexpected info: ~p", [Info]),
{next_state, StateName, StateData}.
@@ -391,7 +394,7 @@ send_text(StateData, Text) ->
(StateData#state.sockmod):send(StateData#state.socket, Text).
send_element(StateData, El) ->
send_text(StateData, xml:element_to_string(El)).
send_text(StateData, xml:element_to_binary(El)).
new_id() ->
randoms:get_string().
+9 -5
View File
@@ -5,7 +5,7 @@
%%% Created : 24 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -573,10 +573,14 @@ route_message(From, To, Packet) ->
_ ->
case ejabberd_auth:is_user_exists(LUser, LServer) of
true ->
is_privacy_allow(From, To, Packet) andalso
ejabberd_hooks:run(offline_message_hook,
LServer,
[From, To, Packet]);
case is_privacy_allow(From, To, Packet) of
true ->
ejabberd_hooks:run(offline_message_hook,
LServer,
[From, To, Packet]);
false ->
ok
end;
_ ->
Err = jlib:make_error_reply(
Packet, ?ERR_SERVICE_UNAVAILABLE),
+8 -2
View File
@@ -5,7 +5,7 @@
%%% Created : 23 Aug 2006 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -87,7 +87,13 @@ start(Module, SockMod, Socket, Opts) ->
end,
ReceiverMod:become_controller(Receiver, Pid);
{error, _Reason} ->
SockMod:close(Socket)
SockMod:close(Socket),
case ReceiverMod of
ejabberd_receiver ->
ReceiverMod:close(Receiver);
_ ->
ok
end
end;
independent ->
ok;
+9 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -177,6 +177,13 @@ init([]) ->
infinity,
supervisor,
[ejabberd_tmp_sup]},
CacheTabSupervisor =
{cache_tab_sup,
{cache_tab_sup, start_link, []},
permanent,
infinity,
supervisor,
[cache_tab_sup]},
{ok, {{one_for_one, 10, 1},
[Hooks,
NodeGroups,
@@ -196,6 +203,7 @@ init([]) ->
IQSupervisor,
STUNSupervisor,
FrontendSocketSupervisor,
CacheTabSupervisor,
Listener]}}.
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 21 Mar 2007 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 18 Jul 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 27 Jan 2006 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 19 Jan 2006 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+18 -9
View File
@@ -1,5 +1,5 @@
/*
* ejabberd, Copyright (C) 2002-2010 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,6 +32,15 @@ typedef struct {
z_stream *i_stream;
} ejabberd_zlib_data;
static void* zlib_alloc(void* data, unsigned int items, unsigned int size)
{
return (void*) driver_alloc(items*size);
}
static void zlib_free(void* data, void* addr)
{
driver_free(addr);
}
static ErlDrvData ejabberd_zlib_drv_start(ErlDrvPort port, char *buff)
{
@@ -39,18 +48,18 @@ static ErlDrvData ejabberd_zlib_drv_start(ErlDrvPort port, char *buff)
(ejabberd_zlib_data *)driver_alloc(sizeof(ejabberd_zlib_data));
d->port = port;
d->d_stream = (z_stream *)malloc(sizeof(z_stream));
d->d_stream = (z_stream *)driver_alloc(sizeof(z_stream));
d->d_stream->zalloc = (alloc_func)0;
d->d_stream->zfree = (free_func)0;
d->d_stream->zalloc = zlib_alloc;
d->d_stream->zfree = zlib_free;
d->d_stream->opaque = (voidpf)0;
deflateInit(d->d_stream, Z_DEFAULT_COMPRESSION);
d->i_stream = (z_stream *)malloc(sizeof(z_stream));
d->i_stream = (z_stream *)driver_alloc(sizeof(z_stream));
d->i_stream->zalloc = (alloc_func)0;
d->i_stream->zfree = (free_func)0;
d->i_stream->zalloc = zlib_alloc;
d->i_stream->zfree = zlib_free;
d->i_stream->opaque = (voidpf)0;
inflateInit(d->i_stream);
@@ -65,10 +74,10 @@ static void ejabberd_zlib_drv_stop(ErlDrvData handle)
ejabberd_zlib_data *d = (ejabberd_zlib_data *)handle;
deflateEnd(d->d_stream);
free(d->d_stream);
driver_free(d->d_stream);
inflateEnd(d->i_stream);
free(d->i_stream);
driver_free(d->i_stream);
driver_free((char *)handle);
}
+28 -1
View File
@@ -50,12 +50,39 @@
#
#FIREWALL_WINDOW=
#.
#' INET_DIST_INTERFACE: IP address where this Erlang node listens other nodes
#
# This communication is used by ejabberdctl command line tool,
# and in a cluster of several ejabberd nodes.
# Notice that the IP address must be specified in the Erlang syntax.
#
# Default: {127,0,0,1}
#
INET_DIST_INTERFACE={127,0,0,1}
#.
#' ERL_EPMD_ADDRESS: IP addresses where epmd listens for connections
#
# IMPORTANT: This option works only in Erlang/OTP R14B03 and newer.
#
# This environment variable may be set to a comma-separated
# list of IP addresses, in which case the epmd daemon
# will listen only on the specified address(es) and on the
# loopback address (which is implicitly added to the list if it
# has not been specified). The default behaviour is to listen on
# all available IP addresses.
#
# Default: 0.0.0.0
#
#ERL_EPMD_ADDRESS=127.0.0.1
#.
#' ERL_PROCESSES: Maximum number of Erlang processes
#
# Erlang consumes a lot of lightweight processes. If there is a lot of activity
# on ejabberd so that the maximum number of processes is reached, people will
# experiment greater latency times. As these processes are implemented in
# experience greater latency times. As these processes are implemented in
# Erlang, and therefore not related to the operating system processes, you do
# not have to worry about allowing a huge number of them.
#
+27 -8
View File
@@ -76,13 +76,15 @@ fi
NAME=-name
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && NAME=-sname
if [ "$FIREWALL_WINDOW" = "" ] ; then
KERNEL_OPTS=""
else
KERNEL_OPTS="-kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}"
KERNEL_OPTS=""
if [ "$FIREWALL_WINDOW" != "" ] ; then
KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}"
fi
if [ "$INET_DIST_INTERFACE" != "" ] ; then
KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_use_interface \"${INET_DIST_INTERFACE}\""
fi
ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS $KERNEL_OPTS"
ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS"
# define additional environment variables
if [ "$EJABBERDDIR" = "" ]; then
@@ -114,6 +116,10 @@ HOME=$SPOOLDIR
# create the home dir with the proper user if doesn't exist, because it stores cookie file
[ -d $HOME ] || $EXEC_CMD "mkdir -p $HOME"
# Change to a directory readable by INSTALLUSER to
# prevent "File operation error: eacces." messages
cd $HOME
# export global variables
export EJABBERD_CONFIG_PATH
export EJABBERD_MSGS_PATH
@@ -123,6 +129,7 @@ export EJABBERD_BIN_PATH
export EJABBERD_DOC_PATH
export EJABBERD_PID_PATH
export ERL_CRASH_DUMP
export ERL_EPMD_ADDRESS
export ERL_INETRC
export ERL_MAX_PORTS
export ERL_MAX_ETS_TABLES
@@ -141,6 +148,7 @@ start ()
-noinput -detached \
-pa $EJABBERD_EBIN_PATH \
-mnesia dir \"\\\"$SPOOLDIR\\\"\" \
$KERNEL_OPTS \
-s ejabberd \
-sasl sasl_error_logger \\{file,\\\"$SASL_LOG_PATH\\\"\\} \
$ERLANG_OPTS $ARGS \"$@\""
@@ -174,6 +182,7 @@ debug ()
$NAME debug-${TTY}-${ERLANG_NODE} \
-remsh $ERLANG_NODE \
-hidden \
$KERNEL_OPTS \
$ERLANG_OPTS $ARGS \"$@\""
}
@@ -203,6 +212,7 @@ live ()
$NAME $ERLANG_NODE \
-pa $EJABBERD_EBIN_PATH \
-mnesia dir \"\\\"$SPOOLDIR\\\"\" \
$KERNEL_OPTS \
-s ejabberd \
$ERLANG_OPTS $ARGS \"$@\""
}
@@ -236,7 +246,7 @@ ctl ()
MAXCONNID=100
CONNLOCKDIR=@LOCALSTATEDIR@/lock/ejabberdctl
FLOCK='/usr/bin/flock'
if [ ! -x "$FLOCK" ] ; then
if [ ! -x "$FLOCK" ] || [ ! -d "$CONNLOCKDIR" ] ; then
JOT='/usr/bin/jot'
if [ ! -x "$JOT" ] ; then
# no flock or jot, simply invoke ctlexec()
@@ -305,12 +315,21 @@ ctlexec ()
{
CONN_NAME=$1; shift
COMMAND=$@
$EXEC_CMD "$ERL \
CTLEXEC="$ERL \
$NAME ${CONN_NAME} \
-noinput \
-hidden \
-pa $EJABBERD_EBIN_PATH \
-s ejabberd_ctl -extra $ERLANG_NODE $COMMAND"
$KERNEL_OPTS \
-s ejabberd_ctl -extra $ERLANG_NODE"
# quote input from the command line
for i in $COMMAND; do
CTLEXEC="$CTLEXEC '$i'";
done
$EXEC_CMD "$CTLEXEC"
}
# display ctl usage
+4 -5
View File
@@ -5,7 +5,7 @@
%%% Created : 22 Aug 2005 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -141,8 +141,7 @@ export_offline(Server, Output) ->
TimeStamp))]},
XML =
ejabberd_odbc:escape(
lists:flatten(
xml:element_to_string(NewPacket))),
xml:element_to_binary(NewPacket)),
["insert into spool(username, xml) "
"values ('", Username, "', '",
XML,
@@ -176,7 +175,7 @@ export_vcard(Server, Output) ->
when LServer == Host ->
Username = ejabberd_odbc:escape(LUser),
SVCARD = ejabberd_odbc:escape(
lists:flatten(xml:element_to_string(VCARD))),
xml:element_to_binary(VCARD)),
["delete from vcard where username='", Username, "';"
"insert into vcard(username, vcard) "
"values ('", Username, "', '", SVCARD, "');"];
@@ -260,7 +259,7 @@ export_private_storage(Server, Output) ->
Username = ejabberd_odbc:escape(LUser),
LXMLNS = ejabberd_odbc:escape(XMLNS),
SData = ejabberd_odbc:escape(
lists:flatten(xml:element_to_string(Data))),
xml:element_to_binary(Data)),
odbc_queries:set_private_data_sql(Username, LXMLNS, SData);
(_Host, _R) ->
[]
+1
View File
@@ -11,6 +11,7 @@ ASN_FLAGS = -bber_bin +optimize +driver
ERLANG_CFLAGS = @ERLANG_CFLAGS@
ERLANG_LIBS = @ERLANG_LIBS@
EFLAGS += @ERLANG_SSLVER@
EFLAGS += -I ..
EFLAGS += -pz ..
+1 -1
View File
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+3 -3
View File
@@ -6,7 +6,7 @@
%%% Author: Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -171,7 +171,7 @@ do_sub(S, {RegExp, New, Times}, Iter) ->
end.
replace_amps(String) ->
lists:map(
lists:flatmap(
fun($&) -> "\\&";
(Chr) -> Chr
(Chr) -> [Chr]
end, String).
+12 -4
View File
@@ -5,7 +5,7 @@
%%% Created : 12 Nov 2006 by Evgeniy Khramtsov <xram@jabber.ru>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -37,6 +37,12 @@
-include("ejabberd.hrl").
-ifdef(SSL40).
-define(PG2, pg2).
-else.
-define(PG2, pg2_backport).
-endif.
%%====================================================================
%% API
%%====================================================================
@@ -51,14 +57,14 @@ modify_passwd(PoolName, DN, Passwd) ->
start_link(Name, Hosts, Backups, Port, Rootdn, Passwd, Opts) ->
PoolName = make_id(Name),
pg2:create(PoolName),
?PG2:create(PoolName),
lists:foreach(
fun(Host) ->
ID = erlang:ref_to_list(make_ref()),
case catch eldap:start_link(ID, [Host|Backups], Port,
Rootdn, Passwd, Opts) of
{ok, Pid} ->
pg2:join(PoolName, Pid);
?PG2:join(PoolName, Pid);
_ ->
error
end
@@ -68,9 +74,11 @@ start_link(Name, Hosts, Backups, Port, Rootdn, Passwd, Opts) ->
%% Internal functions
%%====================================================================
do_request(Name, {F, Args}) ->
case pg2:get_closest_pid(make_id(Name)) of
case ?PG2:get_closest_pid(make_id(Name)) of
Pid when is_pid(Pid) ->
case catch apply(eldap, F, [Pid | Args]) of
{'EXIT', {timeout, _}} ->
?ERROR_MSG("LDAP request failed: timed out", []);
{'EXIT', Reason} ->
?ERROR_MSG("LDAP request failed: eldap:~p(~p)~nReason: ~p",
[F, Args, Reason]),
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 12 Oct 2006 by Mickael Remond <mremond@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+77 -5
View File
@@ -1,5 +1,5 @@
/*
* ejabberd, Copyright (C) 2002-2010 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
@@ -35,12 +35,41 @@
#define PARSE_FINAL_COMMAND 1
ei_x_buff event_buf;
ei_x_buff xmlns_buf;
typedef struct {
ErlDrvPort port;
XML_Parser parser;
} expat_data;
static XML_Memory_Handling_Suite ms = {driver_alloc, driver_realloc, driver_free};
void encode_name(const XML_Char *name)
{
char *name_start;
char *prefix_start;
char *buf;
int name_len, prefix_len, buf_len;
if ((name_start = strchr(name, '\n'))) {
if ((prefix_start = strchr(name_start+1, '\n'))) {
name_len = prefix_start - name_start;
prefix_len = strlen(prefix_start+1);
buf_len = prefix_len + name_len;
buf = driver_alloc(buf_len);
memcpy(buf, prefix_start+1, prefix_len);
memcpy(buf+prefix_len, name_start, name_len);
buf[prefix_len] = ':';
ei_x_encode_string_len(&event_buf, buf, buf_len);
driver_free(buf);
} else {
ei_x_encode_string(&event_buf, name_start+1);
};
} else {
ei_x_encode_string(&event_buf, name);
}
}
void *erlXML_StartElementHandler(expat_data *d,
const XML_Char *name,
const XML_Char **atts)
@@ -51,7 +80,10 @@ void *erlXML_StartElementHandler(expat_data *d,
ei_x_encode_tuple_header(&event_buf, 2);
ei_x_encode_long(&event_buf, XML_START);
ei_x_encode_tuple_header(&event_buf, 2);
ei_x_encode_string(&event_buf, name);
encode_name(name);
ei_x_append(&event_buf, &xmlns_buf);
ei_x_free(&xmlns_buf);
ei_x_new(&xmlns_buf);
for (i = 0; atts[i]; i += 2) {}
@@ -62,7 +94,7 @@ void *erlXML_StartElementHandler(expat_data *d,
for (i = 0; atts[i]; i += 2)
{
ei_x_encode_tuple_header(&event_buf, 2);
ei_x_encode_string(&event_buf, atts[i]);
encode_name(atts[i]);
ei_x_encode_string(&event_buf, atts[i+1]);
}
}
@@ -78,7 +110,7 @@ void *erlXML_EndElementHandler(expat_data *d,
ei_x_encode_list_header(&event_buf, 1);
ei_x_encode_tuple_header(&event_buf, 2);
ei_x_encode_long(&event_buf, XML_END);
ei_x_encode_string(&event_buf, name);
encode_name(name);
return NULL;
}
@@ -93,12 +125,45 @@ void *erlXML_CharacterDataHandler(expat_data *d,
return NULL;
}
void *erlXML_StartNamespaceDeclHandler(expat_data *d,
const XML_Char *prefix,
const XML_Char *uri)
{
int prefix_len;
char *buf;
/* From the expat documentation:
"For a default namespace declaration (xmlns='...'),
the prefix will be null ...
... The URI will be null for the case where
the default namespace is being unset."
FIXME: I'm not quite sure what all that means */
if (uri == NULL)
return NULL;
ei_x_encode_list_header(&xmlns_buf, 1);
ei_x_encode_tuple_header(&xmlns_buf, 2);
if (prefix) {
prefix_len = strlen(prefix);
buf = driver_alloc(7 + prefix_len);
strcpy(buf, "xmlns:");
strcpy(buf+6, prefix);
ei_x_encode_string(&xmlns_buf, buf);
driver_free(buf);
} else {
ei_x_encode_string(&xmlns_buf, "xmlns");
};
ei_x_encode_string(&xmlns_buf, uri);
return NULL;
}
static ErlDrvData expat_erl_start(ErlDrvPort port, char *buff)
{
expat_data* d = (expat_data*)driver_alloc(sizeof(expat_data));
d->port = port;
d->parser = XML_ParserCreate("UTF-8");
d->parser = XML_ParserCreate_MM("UTF-8", &ms, "\n");
XML_SetUserData(d->parser, d);
set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
@@ -110,6 +175,11 @@ static ErlDrvData expat_erl_start(ErlDrvPort port, char *buff)
XML_SetCharacterDataHandler(
d->parser, (XML_CharacterDataHandler)erlXML_CharacterDataHandler);
XML_SetStartNamespaceDeclHandler(
d->parser, (XML_StartNamespaceDeclHandler) erlXML_StartNamespaceDeclHandler);
XML_SetReturnNSTriplet(d->parser, 1);
XML_SetDefaultHandler(d->parser, NULL);
return (ErlDrvData)d;
}
@@ -136,6 +206,7 @@ static int expat_erl_control(ErlDrvData drv_data,
case PARSE_COMMAND:
case PARSE_FINAL_COMMAND:
ei_x_new_with_version(&event_buf);
ei_x_new(&xmlns_buf);
res = XML_Parse(d->parser, buf, len, command == PARSE_FINAL_COMMAND);
if(!res)
@@ -159,6 +230,7 @@ static int expat_erl_control(ErlDrvData drv_data,
memcpy(b->orig_bytes, event_buf.buff, size);
ei_x_free(&event_buf);
ei_x_free(&xmlns_buf);
*rbuf = (char *)b;
return size;
+62 -15
View File
@@ -5,7 +5,7 @@
%%% Created : 30 Jul 2004 by Leif Johansson <leifj@it.su.se>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -43,16 +43,36 @@
-define(CALL_TIMEOUT, 10000). % Timeout is in milliseconds: 10 seconds == 10000
start(Host, ExtPrg) ->
spawn(?MODULE, init, [Host, ExtPrg]).
lists:foreach(
fun(This) ->
start_instance(get_process_name(Host, This), ExtPrg)
end,
lists:seq(0, get_instances(Host)-1)
).
init(Host, ExtPrg) ->
register(gen_mod:get_module_proc(Host, eauth), self()),
start_instance(ProcessName, ExtPrg) ->
spawn(?MODULE, init, [ProcessName, ExtPrg]).
restart_instance(ProcessName, ExtPrg) ->
unregister(ProcessName),
start_instance(ProcessName, ExtPrg).
init(ProcessName, ExtPrg) ->
register(ProcessName, self()),
process_flag(trap_exit,true),
Port = open_port({spawn, ExtPrg}, [{packet,2}]),
loop(Port, ?INIT_TIMEOUT).
loop(Port, ?INIT_TIMEOUT, ProcessName, ExtPrg).
stop(Host) ->
gen_mod:get_module_proc(Host, eauth) ! stop.
lists:foreach(
fun(This) ->
get_process_name(Host, This) ! stop
end,
lists:seq(0, get_instances(Host)-1)
).
get_process_name(Host, Integer) ->
gen_mod:get_module_proc(lists:append([Host, integer_to_list(Integer)]), eauth).
check_password(User, Server, Password) ->
call_port(Server, ["auth", User, Server, Password]).
@@ -77,29 +97,45 @@ remove_user(User, Server, Password) ->
call_port(Server, Msg) ->
LServer = jlib:nameprep(Server),
gen_mod:get_module_proc(LServer, eauth) ! {call, self(), Msg},
ProcessName = get_process_name(LServer, random_instance(get_instances(LServer))),
ProcessName ! {call, self(), Msg},
receive
{eauth,Result} ->
Result
end.
loop(Port, Timeout) ->
random_instance(MaxNum) ->
{A1,A2,A3} = now(),
random:seed(A1, A2, A3),
random:uniform(MaxNum) - 1.
get_instances(Server) ->
case ejabberd_config:get_local_option({extauth_instances, Server}) of
Num when is_integer(Num) -> Num;
_ -> 1
end.
loop(Port, Timeout, ProcessName, ExtPrg) ->
receive
{call, Caller, Msg} ->
Port ! {self(), {command, encode(Msg)}},
port_command(Port, encode(Msg)),
receive
{Port, {data, Data}} ->
?DEBUG("extauth call '~p' received data response:~n~p", [Msg, Data]),
Caller ! {eauth, decode(Data)};
Caller ! {eauth, decode(Data)},
loop(Port, ?CALL_TIMEOUT, ProcessName, ExtPrg);
{Port, Other} ->
?ERROR_MSG("extauth call '~p' received strange response:~n~p", [Msg, Other]),
Caller ! {eauth, false}
Caller ! {eauth, false},
loop(Port, ?CALL_TIMEOUT, ProcessName, ExtPrg)
after
Timeout ->
?ERROR_MSG("extauth call '~p' didn't receive response", [Msg]),
Caller ! {eauth, false}
end,
loop(Port, ?CALL_TIMEOUT);
Caller ! {eauth, false},
Pid = restart_instance(ProcessName, ExtPrg),
flush_buffer_and_forward_messages(Pid),
exit(port_terminated)
end;
stop ->
Port ! {self(), close},
receive
@@ -107,10 +143,21 @@ loop(Port, Timeout) ->
exit(normal)
end;
{'EXIT', Port, Reason} ->
?CRITICAL_MSG("~p ~n", [Reason]),
?CRITICAL_MSG("extauth script has exitted abruptly with reason '~p'", [Reason]),
Pid = restart_instance(ProcessName, ExtPrg),
flush_buffer_and_forward_messages(Pid),
exit(port_terminated)
end.
flush_buffer_and_forward_messages(Pid) ->
receive
Message ->
Pid ! Message,
flush_buffer_and_forward_messages(Pid)
after 0 ->
true
end.
join(List, Sep) ->
lists:foldl(fun(A, "") -> A;
(A, Acc) -> Acc ++ Sep ++ A
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 22 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+19 -6
View File
@@ -5,7 +5,7 @@
%%% Created : 24 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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,15 +66,28 @@ start_module(Host, Module, Opts) ->
ets:insert(ejabberd_modules,
#ejabberd_module{module_host = {Module, Host},
opts = Opts}),
case catch Module:start(Host, Opts) of
{'EXIT', Reason} ->
try Module:start(Host, Opts)
catch Class:Reason ->
del_module_mnesia(Host, Module),
ets:delete(ejabberd_modules, {Module, Host}),
?ERROR_MSG("~p", [Reason]);
_ ->
ok
ErrorText = io_lib:format("Problem starting the module ~p for host ~p ~n options: ~p~n ~p: ~p",
[Module, Host, Opts, Class, Reason]),
?CRITICAL_MSG(ErrorText, []),
case is_app_running(ejabberd) of
true ->
erlang:raise(Class, Reason, erlang:get_stacktrace());
false ->
?CRITICAL_MSG("ejabberd initialization was aborted because a module start failed.", []),
timer:sleep(3000),
erlang:halt(string:substr(lists:flatten(ErrorText), 1, 199))
end
end.
is_app_running(AppName) ->
%% Use a high timeout to prevent a false positive in a high load system
Timeout = 15000,
lists:keymember(AppName, 1, application:which_applications(Timeout)).
%% @doc Stop the module in a host, and forget its configuration.
stop_module(Host, Module) ->
case stop_module_keep_config(Host, Module) of
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 10 Apr 2004 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 2 Feb 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+14 -3
View File
@@ -5,7 +5,7 @@
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -364,6 +364,8 @@ get_iq_namespace({xmlelement, Name, _Attrs, Els}) when Name == "iq" ->
get_iq_namespace(_) ->
"".
%% @spec (xmlelement()) -> iq() | reply | invalid | not_iq
iq_query_info(El) ->
iq_info_internal(El, request).
@@ -455,6 +457,8 @@ parse_xdata_submit(El) ->
case xml:get_attr_s("type", Attrs) of
"submit" ->
lists:reverse(parse_xdata_fields(Els, []));
"form" -> %% This is a workaround to accept Psi's wrong forms
lists:reverse(parse_xdata_fields(Els, []));
_ ->
invalid
end.
@@ -557,7 +561,7 @@ rsm_encode_count(Count, Arr)->
i2l(I) when is_integer(I) -> integer_to_list(I);
i2l(L) when is_list(L) -> L.
%% Timezone = utc | {Hours, Minutes}
%% Timezone = utc | {Sign::string(), {Hours, Minutes}} | {Hours, Minutes}
%% Hours = integer()
%% Minutes = integer()
timestamp_to_iso({{Year, Month, Day}, {Hour, Minute, Second}}, Timezone) ->
@@ -568,6 +572,8 @@ timestamp_to_iso({{Year, Month, Day}, {Hour, Minute, Second}}, Timezone) ->
Timezone_string =
case Timezone of
utc -> "Z";
{Sign, {TZh, TZm}} ->
io_lib:format("~s~2..0w:~2..0w", [Sign, TZh, TZm]);
{TZh, TZm} ->
Sign = case TZh >= 0 of
true -> "+";
@@ -793,5 +799,10 @@ e(X) -> exit({bad_encode_base64_token, X}).
%% Convert Erlang inet IP to list
ip_to_list({IP, _Port}) ->
ip_to_list(IP);
ip_to_list({_,_,_,_,_,_,_,_} = Ipv6Address) ->
inet_parse:ntoa(Ipv6Address);
%% This function clause could use inet_parse too:
ip_to_list({A,B,C,D}) ->
lists:flatten(io_lib:format("~w.~w.~w.~w",[A,B,C,D])).
lists:flatten(io_lib:format("~w.~w.~w.~w",[A,B,C,D]));
ip_to_list(IP) ->
lists:flatten(io_lib:format("~w", [IP])).
+2 -1
View File
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
%%% ejabberd, Copyright (C) 2002-2010 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,6 +30,7 @@
-define(NS_ROSTER, "jabber:iq:roster").
-define(NS_ROSTER_VER, "urn:xmpp:features:rosterver").
-define(NS_PRIVACY, "jabber:iq:privacy").
-define(NS_BLOCKING, "urn:xmpp:blocking").
-define(NS_PRIVATE, "jabber:iq:private").
-define(NS_VERSION, "jabber:iq:version").
-define(NS_TIME90, "jabber:iq:time"). % TODO: Remove once XEP-0090 is Obsolete
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 15 Nov 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 11 Aug 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
+333
View File
@@ -0,0 +1,333 @@
%%%----------------------------------------------------------------------
%%% File : mod_blocking.erl
%%% Author : Stephan Maka
%%% Purpose : XEP-0191: Simple Communications Blocking
%%% Created : 24 Aug 2008 by Stephan Maka <stephan@spaceboyz.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(mod_blocking).
-behaviour(gen_mod).
-export([start/2, stop/1,
process_iq/3,
process_iq_set/4,
process_iq_get/5]).
-include("ejabberd.hrl").
-include("jlib.hrl").
-include("mod_privacy.hrl").
start(Host, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
ejabberd_hooks:add(privacy_iq_get, Host,
?MODULE, process_iq_get, 40),
ejabberd_hooks:add(privacy_iq_set, Host,
?MODULE, process_iq_set, 40),
mod_disco:register_feature(Host, ?NS_BLOCKING),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING,
?MODULE, process_iq, IQDisc).
stop(Host) ->
ejabberd_hooks:delete(privacy_iq_get, Host,
?MODULE, process_iq_get, 40),
ejabberd_hooks:delete(privacy_iq_set, Host,
?MODULE, process_iq_set, 40),
mod_disco:unregister_feature(Host, ?NS_BLOCKING),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_BLOCKING).
process_iq(_From, _To, IQ) ->
SubEl = IQ#iq.sub_el,
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}.
process_iq_get(_, From, _To,
#iq{xmlns = ?NS_BLOCKING,
sub_el = {xmlelement, "blocklist", _, _}},
_) ->
#jid{luser = LUser, lserver = LServer} = From,
process_blocklist_get(LUser, LServer);
process_iq_get(Acc, _, _, _, _) ->
Acc.
process_iq_set(_, From, _To, #iq{xmlns = ?NS_BLOCKING,
sub_el = {xmlelement, SubElName, _, SubEls}}) ->
#jid{luser = LUser, lserver = LServer} = From,
case {SubElName, xml:remove_cdata(SubEls)} of
{"block", []} ->
{error, ?ERR_BAD_REQUEST};
{"block", Els} ->
JIDs = parse_blocklist_items(Els, []),
process_blocklist_block(LUser, LServer, JIDs);
{"unblock", []} ->
process_blocklist_unblock_all(LUser, LServer);
{"unblock", Els} ->
JIDs = parse_blocklist_items(Els, []),
process_blocklist_unblock(LUser, LServer, JIDs);
_ ->
{error, ?ERR_BAD_REQUEST}
end;
process_iq_set(Acc, _, _, _) ->
Acc.
is_list_needdb(Items) ->
lists:any(
fun(X) ->
case X#listitem.type of
subscription -> true;
group -> true;
_ -> false
end
end, Items).
list_to_blocklist_jids([], JIDs) ->
JIDs;
list_to_blocklist_jids([#listitem{type = jid,
action = deny,
value = JID} = Item | Items], JIDs) ->
case Item of
#listitem{match_all = true} ->
Match = true;
#listitem{match_iq = true,
match_message = true,
match_presence_in = true,
match_presence_out = true} ->
Match = true;
_ ->
Match = false
end,
if
Match ->
list_to_blocklist_jids(Items, [JID | JIDs]);
true ->
list_to_blocklist_jids(Items, JIDs)
end;
% Skip Privacy List items than cannot be mapped to Blocking items
list_to_blocklist_jids([_ | Items], JIDs) ->
list_to_blocklist_jids(Items, JIDs).
parse_blocklist_items([], JIDs) ->
JIDs;
parse_blocklist_items([{xmlelement, "item", Attrs, _} | Els], JIDs) ->
case xml:get_attr("jid", Attrs) of
{value, JID1} ->
JID = jlib:jid_tolower(jlib:string_to_jid(JID1)),
parse_blocklist_items(Els, [JID | JIDs]);
false ->
% Tolerate missing jid attribute
parse_blocklist_items(Els, JIDs)
end;
parse_blocklist_items([_ | Els], JIDs) ->
% Tolerate unknown elements
parse_blocklist_items(Els, JIDs).
process_blocklist_block(LUser, LServer, JIDs) ->
F =
fun() ->
case mnesia:wread({privacy, {LUser, LServer}}) of
[] ->
% No lists yet
P = #privacy{us = {LUser, LServer}},
% TODO: i18n here:
NewDefault = "Blocked contacts",
NewLists1 = [],
List = [];
[#privacy{default = Default,
lists = Lists} = P] ->
case lists:keysearch(Default, 1, Lists) of
{value, {_, List}} ->
% Default list exists
NewDefault = Default,
NewLists1 = lists:keydelete(Default, 1, Lists);
false ->
% No default list yet, create one
% TODO: i18n here:
NewDefault = "Blocked contacts",
NewLists1 = Lists,
List = []
end
end,
AlreadyBlocked = list_to_blocklist_jids(List, []),
NewList =
lists:foldr(fun(JID, List1) ->
case lists:member(JID, AlreadyBlocked) of
true ->
List1;
false ->
[#listitem{type = jid,
value = JID,
action = deny,
order = 0,
match_all = true
} | List1]
end
end, List, JIDs),
NewLists = [{NewDefault, NewList} | NewLists1],
mnesia:write(P#privacy{default = NewDefault,
lists = NewLists}),
{ok, NewDefault, NewList}
end,
case mnesia:transaction(F) of
{atomic, {error, _} = Error} ->
Error;
{atomic, {ok, Default, List}} ->
broadcast_list_update(LUser, LServer, Default, List),
broadcast_blocklist_event(LUser, LServer, {block, JIDs}),
{result, []};
_ ->
{error, ?ERR_INTERNAL_SERVER_ERROR}
end.
process_blocklist_unblock_all(LUser, LServer) ->
F =
fun() ->
case mnesia:read({privacy, {LUser, LServer}}) of
[] ->
% No lists, nothing to unblock
ok;
[#privacy{default = Default,
lists = Lists} = P] ->
case lists:keysearch(Default, 1, Lists) of
{value, {_, List}} ->
% Default list, remove all deny items
NewList =
lists:filter(
fun(#listitem{action = A}) ->
A =/= deny
end, List),
NewLists1 = lists:keydelete(Default, 1, Lists),
NewLists = [{Default, NewList} | NewLists1],
mnesia:write(P#privacy{lists = NewLists}),
{ok, Default, NewList};
false ->
% No default list, nothing to unblock
ok
end
end
end,
case mnesia:transaction(F) of
{atomic, {error, _} = Error} ->
Error;
{atomic, ok} ->
{result, []};
{atomic, {ok, Default, List}} ->
broadcast_list_update(LUser, LServer, Default, List),
broadcast_blocklist_event(LUser, LServer, unblock_all),
{result, []};
_ ->
{error, ?ERR_INTERNAL_SERVER_ERROR}
end.
process_blocklist_unblock(LUser, LServer, JIDs) ->
F =
fun() ->
case mnesia:read({privacy, {LUser, LServer}}) of
[] ->
% No lists, nothing to unblock
ok;
[#privacy{default = Default,
lists = Lists} = P] ->
case lists:keysearch(Default, 1, Lists) of
{value, {_, List}} ->
% Default list, remove matching deny items
NewList =
lists:filter(
fun(#listitem{action = deny,
type = jid,
value = JID}) ->
not(lists:member(JID, JIDs));
(_) ->
true
end, List),
NewLists1 = lists:keydelete(Default, 1, Lists),
NewLists = [{Default, NewList} | NewLists1],
mnesia:write(P#privacy{lists = NewLists}),
{ok, Default, NewList};
false ->
% No default list, nothing to unblock
ok
end
end
end,
case mnesia:transaction(F) of
{atomic, {error, _} = Error} ->
Error;
{atomic, ok} ->
{result, []};
{atomic, {ok, Default, List}} ->
broadcast_list_update(LUser, LServer, Default, List),
broadcast_blocklist_event(LUser, LServer, {unblock, JIDs}),
{result, []};
_ ->
{error, ?ERR_INTERNAL_SERVER_ERROR}
end.
broadcast_list_update(LUser, LServer, Name, List) ->
NeedDb = is_list_needdb(List),
ejabberd_router:route(
jlib:make_jid(LUser, LServer, ""),
jlib:make_jid(LUser, LServer, ""),
{xmlelement, "broadcast", [],
[{privacy_list,
#userlist{name = Name, list = List, needdb = NeedDb},
Name}]}).
broadcast_blocklist_event(LUser, LServer, Event) ->
JID = jlib:make_jid(LUser, LServer, ""),
ejabberd_router:route(
JID, JID,
{xmlelement, "broadcast", [],
[{blocking, Event}]}).
process_blocklist_get(LUser, LServer) ->
case catch mnesia:dirty_read(privacy, {LUser, LServer}) of
{'EXIT', _Reason} ->
{error, ?ERR_INTERNAL_SERVER_ERROR};
[] ->
{result, [{xmlelement, "blocklist", [{"xmlns", ?NS_BLOCKING}], []}]};
[#privacy{default = Default, lists = Lists}] ->
case lists:keysearch(Default, 1, Lists) of
{value, {_, List}} ->
JIDs = list_to_blocklist_jids(List, []),
Items = lists:map(
fun(JID) ->
?DEBUG("JID: ~p",[JID]),
{xmlelement, "item",
[{"jid", jlib:jid_to_string(JID)}], []}
end, JIDs),
{result,
[{xmlelement, "blocklist", [{"xmlns", ?NS_BLOCKING}],
Items}]};
_ ->
{result, [{xmlelement, "blocklist", [{"xmlns", ?NS_BLOCKING}], []}]}
end
end.
+266 -50
View File
@@ -5,7 +5,7 @@
%%% Created : 7 Oct 2006 by Magnus Henoch <henoch@dtek.chalmers.se>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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
@@ -53,12 +53,16 @@
]).
%% hook handlers
-export([user_send_packet/3]).
-export([user_send_packet/3,
user_receive_packet/4,
c2s_presence_in/2,
c2s_broadcast_recipients/5]).
-include("ejabberd.hrl").
-include("jlib.hrl").
-define(PROCNAME, ejabberd_mod_caps).
-define(BAD_HASH_LIFETIME, 600). %% in seconds
-record(caps, {node, version, hash, exts}).
-record(caps_features, {node_pair, features = []}).
@@ -98,12 +102,13 @@ get_features(#caps{node = Node, version = Version, exts = Exts}) ->
SubNodes = [Version | Exts],
lists:foldl(
fun(SubNode, Acc) ->
case mnesia:dirty_read({caps_features,
node_to_binary(Node, SubNode)}) of
[] ->
Acc;
[#caps_features{features = Features}] ->
binary_to_features(Features) ++ Acc
BinaryNode = node_to_binary(Node, SubNode),
case cache_tab:lookup(caps_features, BinaryNode,
caps_read_fun(BinaryNode)) of
{ok, Features} when is_list(Features) ->
binary_to_features(Features) ++ Acc;
_ ->
Acc
end
end, [], SubNodes).
@@ -158,6 +163,22 @@ user_send_packet(#jid{luser = User, lserver = Server} = From,
user_send_packet(_From, _To, _Packet) ->
ok.
user_receive_packet(#jid{lserver = Server}, From, _To,
{xmlelement, "presence", Attrs, Els}) ->
Type = xml:get_attr_s("type", Attrs),
if Type == ""; Type == "available" ->
case read_caps(Els) of
nothing ->
ok;
#caps{version = Version, exts = Exts} = Caps ->
feature_request(Server, From, Caps, [Version | Exts])
end;
true ->
ok
end;
user_receive_packet(_JID, _From, _To, _Packet) ->
ok.
caps_stream_features(Acc, MyHost) ->
case make_my_disco_hash(MyHost) of
"" ->
@@ -193,17 +214,95 @@ disco_info(_Acc, Host, Module, ?EJABBERD_URI ++ "#" ++ [_|_], Lang) ->
disco_info(Acc, _Host, _Module, _Node, _Lang) ->
Acc.
c2s_presence_in(C2SState, {From, To, {_, _, Attrs, Els}}) ->
Type = xml:get_attr_s("type", Attrs),
Subscription = ejabberd_c2s:get_subscription(From, C2SState),
Insert = ((Type == "") or (Type == "available"))
and ((Subscription == both) or (Subscription == to)),
Delete = (Type == "unavailable") or (Type == "error") or (Type == "invisible"),
if Insert or Delete ->
LFrom = jlib:jid_tolower(From),
Rs = case ejabberd_c2s:get_aux_field(caps_resources, C2SState) of
{ok, Rs1} ->
Rs1;
error ->
gb_trees:empty()
end,
Caps = read_caps(Els),
{CapsUpdated, NewRs} =
case Caps of
nothing when Insert == true ->
{false, Rs};
_ when Insert == true ->
case gb_trees:lookup(LFrom, Rs) of
{value, Caps} ->
{false, Rs};
none ->
{true, gb_trees:insert(LFrom, Caps, Rs)};
_ ->
{true, gb_trees:update(LFrom, Caps, Rs)}
end;
_ ->
{false, gb_trees:delete_any(LFrom, Rs)}
end,
if CapsUpdated ->
ejabberd_hooks:run(caps_update, To#jid.lserver,
[From, To, get_features(Caps)]);
true ->
ok
end,
ejabberd_c2s:set_aux_field(caps_resources, NewRs, C2SState);
true ->
C2SState
end.
c2s_broadcast_recipients(InAcc, C2SState, {pep_message, Feature},
_From, _Packet) ->
case ejabberd_c2s:get_aux_field(caps_resources, C2SState) of
{ok, Rs} ->
gb_trees_fold(
fun(USR, Caps, Acc) ->
case lists:member(Feature, get_features(Caps)) of
true ->
[USR|Acc];
false ->
Acc
end
end, InAcc, Rs);
_ ->
InAcc
end;
c2s_broadcast_recipients(Acc, _, _, _, _) ->
Acc.
%%====================================================================
%% gen_server callbacks
%%====================================================================
init([Host, _Opts]) ->
init([Host, Opts]) ->
case catch mnesia:table_info(caps_features, storage_type) of
{'EXIT', _} ->
ok;
disc_only_copies ->
ok;
_ ->
mnesia:delete_table(caps_features)
end,
mnesia:create_table(caps_features,
[{disc_copies, [node()]},
[{disc_only_copies, [node()]},
{local_content, true},
{attributes, record_info(fields, caps_features)}]),
mnesia:add_table_copy(caps_features, node(), disc_copies),
mnesia:add_table_copy(caps_features, node(), disc_only_copies),
MaxSize = gen_mod:get_opt(cache_size, Opts, 1000),
LifeTime = gen_mod:get_opt(cache_life_time, Opts, timer:hours(24) div 1000),
cache_tab:new(caps_features, [{max_size, MaxSize}, {life_time, LifeTime}]),
ejabberd_hooks:add(c2s_presence_in, Host,
?MODULE, c2s_presence_in, 75),
ejabberd_hooks:add(c2s_broadcast_recipients, Host,
?MODULE, c2s_broadcast_recipients, 75),
ejabberd_hooks:add(user_send_packet, Host,
?MODULE, user_send_packet, 75),
ejabberd_hooks:add(user_receive_packet, Host,
?MODULE, user_receive_packet, 75),
ejabberd_hooks:add(c2s_stream_features, Host,
?MODULE, caps_stream_features, 75),
ejabberd_hooks:add(s2s_stream_features, Host,
@@ -229,8 +328,14 @@ handle_info(_Info, State) ->
terminate(_Reason, State) ->
Host = State#state.host,
ejabberd_hooks:delete(c2s_presence_in, Host,
?MODULE, c2s_presence_in, 75),
ejabberd_hooks:delete(c2s_broadcast_recipients, Host,
?MODULE, c2s_broadcast_recipients, 75),
ejabberd_hooks:delete(user_send_packet, Host,
?MODULE, user_send_packet, 75),
ejabberd_hooks:delete(user_receive_packet, Host,
?MODULE, user_receive_packet, 75),
ejabberd_hooks:delete(c2s_stream_features, Host,
?MODULE, caps_stream_features, 75),
ejabberd_hooks:delete(s2s_stream_features, Host,
@@ -252,22 +357,33 @@ code_change(_OldVsn, State, _Extra) ->
feature_request(Host, From, Caps, [SubNode | Tail] = SubNodes) ->
Node = Caps#caps.node,
BinaryNode = node_to_binary(Node, SubNode),
case mnesia:dirty_read({caps_features, BinaryNode}) of
[] ->
IQ = #iq{type = get,
xmlns = ?NS_DISCO_INFO,
sub_el = [{xmlelement, "query",
[{"xmlns", ?NS_DISCO_INFO},
{"node", Node ++ "#" ++ SubNode}],
[]}]},
F = fun(IQReply) ->
feature_response(
IQReply, Host, From, Caps, SubNodes)
end,
ejabberd_local:route_iq(
jlib:make_jid("", Host, ""), From, IQ, F);
_ ->
feature_request(Host, From, Caps, Tail)
case cache_tab:lookup(caps_features, BinaryNode,
caps_read_fun(BinaryNode)) of
{ok, Fs} when is_list(Fs) ->
feature_request(Host, From, Caps, Tail);
Other ->
NeedRequest = case Other of
{ok, TS} ->
now_ts() >= TS + ?BAD_HASH_LIFETIME;
_ ->
true
end,
if NeedRequest ->
IQ = #iq{type = get,
xmlns = ?NS_DISCO_INFO,
sub_el = [{xmlelement, "query",
[{"xmlns", ?NS_DISCO_INFO},
{"node", Node ++ "#" ++ SubNode}],
[]}]},
F = fun(IQReply) ->
feature_response(
IQReply, Host, From, Caps, SubNodes)
end,
ejabberd_local:route_iq(
jlib:make_jid("", Host, ""), From, IQ, F);
true ->
feature_request(Host, From, Caps, Tail)
end
end;
feature_request(_Host, _From, _Caps, []) ->
ok.
@@ -276,35 +392,32 @@ feature_response(#iq{type = result,
sub_el = [{xmlelement, _, _, Els}]},
Host, From, Caps, [SubNode | SubNodes]) ->
BinaryNode = node_to_binary(Caps#caps.node, SubNode),
IsValid = case Caps#caps.hash of
"sha-1" ->
Caps#caps.version == make_disco_hash(Els, sha1);
"md5" ->
Caps#caps.version == make_disco_hash(Els, md5);
_ ->
true
end,
if IsValid ->
case check_hash(Caps, Els) of
true ->
Features = lists:flatmap(
fun({xmlelement, "feature", FAttrs, _}) ->
[xml:get_attr_s("var", FAttrs)];
(_) ->
[]
end, Els),
mnesia:dirty_write(
#caps_features{node_pair = BinaryNode,
features = features_to_binary(Features)});
true ->
mnesia:dirty_write(#caps_features{node_pair = BinaryNode})
BinaryFeatures = features_to_binary(Features),
cache_tab:insert(
caps_features, BinaryNode, BinaryFeatures,
caps_write_fun(BinaryNode, BinaryFeatures));
false ->
%% We cache current timestamp and will probe the client
%% after BAD_HASH_LIFETIME seconds.
cache_tab:insert(caps_features, BinaryNode, now_ts(),
caps_write_fun(BinaryNode, now_ts()))
end,
feature_request(Host, From, Caps, SubNodes);
feature_response(timeout, _Host, _From, _Caps, _SubNodes) ->
ok;
feature_response(_IQResult, Host, From, Caps, [SubNode | SubNodes]) ->
%% We got type=error or invalid type=result stanza, so
%% we cache empty feature not to probe the client permanently
%% We got type=error or invalid type=result stanza or timeout,
%% so we cache current timestamp and will probe the client
%% after BAD_HASH_LIFETIME seconds.
BinaryNode = node_to_binary(Caps#caps.node, SubNode),
mnesia:dirty_write(#caps_features{node_pair = BinaryNode}),
cache_tab:insert(caps_features, BinaryNode, now_ts(),
caps_write_fun(BinaryNode, now_ts())),
feature_request(Host, From, Caps, SubNodes).
node_to_binary(Node, SubNode) ->
@@ -313,6 +426,23 @@ node_to_binary(Node, SubNode) ->
features_to_binary(L) -> [list_to_binary(I) || I <- L].
binary_to_features(L) -> [binary_to_list(I) || I <- L].
caps_read_fun(Node) ->
fun() ->
case mnesia:dirty_read({caps_features, Node}) of
[#caps_features{features = Features}] ->
{ok, Features};
_ ->
error
end
end.
caps_write_fun(Node, Features) ->
fun() ->
mnesia:dirty_write(
#caps_features{node_pair = Node,
features = Features})
end.
make_my_disco_hash(Host) ->
JID = jlib:make_jid("", Host, ""),
case {ejabberd_hooks:run_fold(disco_local_features,
@@ -339,17 +469,86 @@ make_my_disco_hash(Host) ->
""
end.
make_disco_hash(DiscoEls, Algo) when Algo == sha1; Algo == md5 ->
-ifdef(HAVE_MD2).
make_disco_hash(DiscoEls, Algo) ->
Concat = [concat_identities(DiscoEls),
concat_features(DiscoEls),
concat_info(DiscoEls)],
base64:encode_to_string(
if Algo == sha1 ->
crypto:sha(Concat);
if Algo == md2 ->
sha:md2(Concat);
Algo == md5 ->
crypto:md5(Concat)
crypto:md5(Concat);
Algo == sha1 ->
crypto:sha(Concat);
Algo == sha224 ->
sha:sha224(Concat);
Algo == sha256 ->
sha:sha256(Concat);
Algo == sha384 ->
sha:sha384(Concat);
Algo == sha512 ->
sha:sha512(Concat)
end).
check_hash(Caps, Els) ->
case Caps#caps.hash of
"md2" ->
Caps#caps.version == make_disco_hash(Els, md2);
"md5" ->
Caps#caps.version == make_disco_hash(Els, md5);
"sha-1" ->
Caps#caps.version == make_disco_hash(Els, sha1);
"sha-224" ->
Caps#caps.version == make_disco_hash(Els, sha224);
"sha-256" ->
Caps#caps.version == make_disco_hash(Els, sha256);
"sha-384" ->
Caps#caps.version == make_disco_hash(Els, sha384);
"sha-512" ->
Caps#caps.version == make_disco_hash(Els, sha512);
_ ->
true
end.
-else.
make_disco_hash(DiscoEls, Algo) ->
Concat = [concat_identities(DiscoEls),
concat_features(DiscoEls),
concat_info(DiscoEls)],
base64:encode_to_string(
if Algo == md5 ->
crypto:md5(Concat);
Algo == sha1 ->
crypto:sha(Concat);
Algo == sha224 ->
sha:sha224(Concat);
Algo == sha256 ->
sha:sha256(Concat);
Algo == sha384 ->
sha:sha384(Concat);
Algo == sha512 ->
sha:sha512(Concat)
end).
check_hash(Caps, Els) ->
case Caps#caps.hash of
"md5" ->
Caps#caps.version == make_disco_hash(Els, md5);
"sha-1" ->
Caps#caps.version == make_disco_hash(Els, sha1);
"sha-224" ->
Caps#caps.version == make_disco_hash(Els, sha224);
"sha-256" ->
Caps#caps.version == make_disco_hash(Els, sha256);
"sha-384" ->
Caps#caps.version == make_disco_hash(Els, sha384);
"sha-512" ->
Caps#caps.version == make_disco_hash(Els, sha512);
_ ->
true
end.
-endif.
concat_features(Els) ->
lists:usort(
lists:flatmap(
@@ -411,3 +610,20 @@ concat_xdata_fields(Fields) ->
Acc
end, ["", []], Fields),
[Form, $<, lists:sort(Res)].
gb_trees_fold(F, Acc, Tree) ->
Iter = gb_trees:iterator(Tree),
gb_trees_fold_iter(F, Acc, Iter).
gb_trees_fold_iter(F, Acc, Iter) ->
case gb_trees:next(Iter) of
{Key, Val, NewIter} ->
NewAcc = F(Key, Val, Acc),
gb_trees_fold_iter(F, NewAcc, NewIter);
_ ->
Acc
end.
now_ts() ->
{MegaSecs, Secs, _} = now(),
MegaSecs*1000000 + Secs.
+1 -1
View File
@@ -5,7 +5,7 @@
%%% Created : 19 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2010 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

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