Compare commits

...

160 Commits

Author SHA1 Message Date
Badlop 0dbedb69a6 Recompile translations 2015-07-27 11:45:04 +02:00
Badlop 5788609e5c Updated Spanish translation 2015-07-27 11:43:31 +02:00
Badlop 5305b4a82c Updated Hebrew translation (thanks to Isratine Citizen) 2015-07-27 11:41:38 +02:00
Badlop d03d08539b Reuse some strings in WebAdmin's Listening Ports 2015-07-27 11:40:56 +02:00
Paweł Chmielowski 76104cd117 Fix problem with merging values from multiple config files 2015-07-24 15:46:08 +02:00
Christophe Romain e211bf7131 Ensure config snippet is loaded at module installation (EJAB-1741) 2015-07-24 15:09:57 +02:00
Christophe Romain 32fc586c08 Allow contribution to include .yml or .yaml config file 2015-07-24 14:30:31 +02:00
Christophe Romain 8fedc945bf Allow migration of old pubsub items with xmlelement in body (#479) 2015-07-24 13:44:01 +02:00
Christophe Romain d481017746 Merge pull request #642 from weiss/pep-on-caps-update
Also send PEP notifications when local contact updates CAPS
2015-07-24 12:07:22 +02:00
Badlop 19aad464da Provide command for ODBC's convert_to_scram 2015-07-23 13:16:15 +02:00
Paweł Chmielowski 8df134e025 Don't crash web admin when displaying info about websocket using users 2015-07-22 11:54:11 +02:00
Christophe Romain 9091fcb1a1 Let nodetree call default flat plugin now
this fix mistake from previous commit 311fedaa
2015-07-22 11:20:06 +02:00
Christophe Romain 9aa2d92d90 Allow include of simple dependencies (EJAB-1737)(#391)
Either contributed module include dependencies this way
  deps/
    dep1/
      src/
      include/
    dep1/
      src/
      include/

Or includes rebar.config or rebar.config.script:
In this case, only git is supported (if git command available)
and ext_mod checkout code in deps directory.

In both case, only basic built procedure is supported. ext_mod
does not do more than bare compilation like this:
erlc -I include src/*erl
2015-07-22 10:48:44 +02:00
Christophe Romain 311fedaa12 Let flat be default plugin (#609) 2015-07-22 10:37:26 +02:00
Christophe Romain 9c36a9df78 Do not init nodes from mod_pubsub (#609)
Let each plugin do its own initialisation in init_plugins
init_nodes was an old function to be removed.
2015-07-22 08:03:27 +02:00
Christophe Romain b47a27f3ac Merge pull request #608 from weiss/bare-jid-subscription
PubSub: Check for node subscription of bare JID
2015-07-22 07:58:34 +02:00
Evgeny Khramtsov 531638e946 Merge pull request #632 from weiss/increase-max-ack-queue
XEP-0198: Increase default value of "max_ack_queue" option
2015-07-21 12:36:01 +03:00
Evgeny Khramtsov a724893887 Merge pull request #618 from weiss/muc-message-hook
New hook: muc_filter_packet
2015-07-21 12:35:27 +03:00
Evgeniy Khramtsov 7f4c74dec9 Print content types more gracefully 2015-07-17 14:29:11 +03:00
Evgeniy Khramtsov 44cc99d616 Get rid of 'db_type' for mod_blocking in test suite 2015-07-16 13:32:46 +03:00
Badlop 7395cc910e Set direction of resource and connection (#650) 2015-07-15 21:39:13 +02:00
Badlop c53d764119 If local guide.html file not found, redirect to the online guide 2015-07-15 20:45:55 +02:00
Badlop 3eb0b161b2 Update links to Guide in WebAdmin 2015-07-15 20:40:13 +02:00
Badlop 65551afcba Support RTL page direction in WebAdmin for Hebrew (#650) 2015-07-15 19:01:32 +02:00
Badlop f4376671ac Set LTR direction to Raw links (#650) 2015-07-15 18:51:31 +02:00
Badlop c012d7555b Add links in WebAdmin to ejabberd and ProcessOne (#661) 2015-07-15 13:10:12 +02:00
Badlop 9ede414f01 Support more mod_muc_admin translation strings (#659) 2015-07-15 11:54:35 +02:00
Mickael Remond 062d2d696f Update dev section to show erl command-line start command 2015-07-11 11:20:38 +02:00
Evgeniy Khramtsov a53191fed5 Add "complete" attribute to MAM final response (EJABS-2484) 2015-07-10 14:05:47 +03:00
Evgeniy Khramtsov 8e27decdfd Fix mod_mam compatibility with RSM for other backends 2015-07-10 13:59:33 +03:00
Evgeniy Khramtsov 0dfc8ade68 Fix tests related to MAM 2015-07-10 13:57:27 +03:00
Jerome Sautret 1db65e3614 Fix mod_mam compatibility with RSM (only with odbc backend). 2015-07-10 13:56:33 +03:00
Evgeniy Khramtsov a168340838 During halt only shutdown MUC rooms on local node 2015-07-08 15:35:26 +03:00
Jerome Sautret 6604b9efbb Fix MAM tests (EJABS-2480). 2015-07-08 15:34:34 +03:00
Jerome Sautret 2598375051 Changed mam iq get to set as specified by XEP-0313 v0.3 2015-07-08 13:15:14 +03:00
Holger Weiss 0f96414279 Trigger PEP notifications on CAPS updates
Let mod_pubsub send last items whenever a contact updates the entity
capabilities.  This was already done for remote contacts and is now also
done for local contacts.
2015-07-07 09:33:00 +02:00
Holger Weiss edb18deb8f mod_pubsub: Explain caps_update usage in a comment
The reason to use the caps_update hook for sending last items to remote
contacts is probably not obvious.
2015-07-06 23:45:25 +02:00
Mickael Remond 0770252e9b Fix dialyzer warning
The function is call with binary format from ejabberd_c2s.
2015-07-05 13:33:34 +02:00
Evgeniy Khramtsov b0453ea2ce Remove ehyperloglog dependency 2015-07-03 13:18:35 +03:00
Holger Weiss b7d7dc5201 XEP-0198: Increase timeout during resumption
Give gen_fsm:sync_send_all_state_event/3 a little more time to transfer
the (possibly somewhat large) c2s #state during session resumption.
2015-07-03 11:35:22 +02:00
Holger Weiss 5856f6d06a XEP-0198: Increase default "max_ack_queue" value
During login, clients might receive a relatively large number of stanzas
in one go.  For some users, the default value of the "max_ack_queue"
option turned out to be too small in that situation.
2015-07-03 11:35:22 +02:00
Holger Weiss a25051fead New hook: muc_filter_packet
Add a hook that allows for modifying or dropping MUC room messages.

Closes #491.
2015-07-03 11:34:44 +02:00
Holger Weiss 95138864f4 Let Travis grab MySQL 5.6 from repo.mysql.com
We need MySQL 5.6 or newer in order to get support for InnoDB FULLTEXT
Indexes.

Closes #624.
2015-07-03 01:21:22 +02:00
Holger Weiss 4045c848c4 Send notifications on MUC configuration changes
Notify clients when the room configuration changes, as mandated by
XEP-0045, #10.2.1.

Closes #623.
2015-07-02 00:36:16 +02:00
Evgeny Khramtsov 3267d4c923 Merge pull request #628 from joudinet/master
configure.ac: add AC_CONFIG_MACRO_DIR
2015-06-30 12:06:49 +03:00
Johan Oudinet 0e7d2b73be configure.ac: add AC_CONFIG_MACRO_DIR
Otherwise, autoconf fails to find extra macros defined in the m4
directory.
2015-06-30 10:53:45 +02:00
Mickael Remond 0474804d4b Version number must be SemVersion in mix
Semantic version expects versioning with 3 components
2015-06-29 23:32:00 +02:00
Mickael Remond 56034e6ed5 Use https url for git dependencies for consistency 2015-06-29 23:23:31 +02:00
Mickael Remond df57a07dd5 Keep the version hardcoded in mix.exs file
Generated the mix.exs file through configure is not possible when using mix, as
it does not run configure after having downloaded the dependencies.
#621
2015-06-29 23:14:18 +02:00
Evgeniy Khramtsov 3c12d1a960 Do not rely on behaviour info when doing config validation 2015-06-29 22:50:34 +03:00
badlop 87d6ad395f Merge pull request #620 from weiss/omit-non-anon-msg
Omit warning message regarding non-anonymous MUC room
2015-06-29 15:18:04 +02:00
Holger Weiss 7c7e51b6e8 Omit warning message regarding non-anonymous room
Previous versions of XEP-0045 suggested sending a warning message to new
occupants of a non-anonymous MUC room.  The current revision (1.25) says
that a status code of "100" must be returned with the user's initial
presence, instead.  We already do this (in addition to generating the
warning message).

Receiving the warning message each time the client joins the room can
become annoying, especially when reconnections occur frequently (e.g.,
on mobile devices).  So, we omit it, now.
2015-06-28 14:05:55 +02:00
Badlop 4ae1b4db03 When passwords are scrammed, report check_password_hash cannot work (#559) 2015-06-25 13:39:45 +02:00
Badlop 72f35a6dc6 Add xep definition to mod_mam 2015-06-24 11:58:37 +02:00
Evgeniy Khramtsov 83cce468a5 Add MAM (XEP-0313) support 2015-06-22 16:56:08 +03:00
Badlop 6631078884 Document a few more supported protocols 2015-06-22 13:11:37 +02:00
Holger Weiss fc0754c609 Add s2s_dhfile to list of known options 2015-06-20 00:14:54 +02:00
Holger Weiss 73a0fb418c Update comment that explains how to set up node_mb
Specify settings that make sense with current ejabberd versions, and use
the YAML configuration format.  Also, specify the "urn:xmpp:microblog:0"
namespace, as that's the microblogging node name currently defined by
XEP-0277.
2015-06-19 23:13:36 +02:00
Holger Weiss 04038c01f7 PubSub: Check for node subscription of bare JID
Don't just check whether the full JID is subscribed when a node
subscription is required to list or publish items.  If the bare JID is
subscribed, these requests are now also accepted.
2015-06-19 00:50:08 +02:00
Christophe Romain 4dc23a5d81 Allow several ';' passed in commands (#599) 2015-06-18 14:59:00 +02:00
Badlop 36a96ae3f5 change_room_option misses handling some room options #604 2015-06-18 13:13:49 +02:00
Christophe Romain d528457ba5 Don't force persistence if cache enabled (fix previous commit) 2015-06-18 12:54:46 +02:00
Christophe Romain e5a98b100d Fix max_items and don't let PEP depends on item cache 2015-06-18 12:06:29 +02:00
Badlop 1cf2dfe63a New hide_sensitive_log_data option to hide client IP in log (#452 #471) 2015-06-17 11:32:42 +02:00
Christophe Romain 3c47a5bb75 Allow password with ';' passed in ejabberdctl (#599) 2015-06-17 08:59:09 +02:00
Holger Weiss e608274243 Add s2s_dhfile option to configuration validator 2015-06-16 15:18:34 +02:00
Alexey Shchepin 2110b929bc Merge pull request #581 from weiss/dh-param-file
New options: dhfile and s2s_dhfile
2015-06-16 11:59:06 +03:00
Paweł Chmielowski dcf5aefea0 Add option to set net_ticktime (EJAB-1742) 2015-06-15 14:57:07 +02:00
Badlop 357ff6c8f7 Fix bug introduced in commit b88fa6f617 2015-06-04 15:47:02 +02:00
Badlop c04053cfae Use https instead of git in rebar file for dependencies url (#589) 2015-06-04 13:12:49 +02:00
Badlop fe10c6f6f2 Pick first local multicast service, otherwise remote (ejabberd-contrib#105) 2015-06-04 12:13:10 +02:00
badlop 7206bff4a4 Merge pull request #592 from weiss/omit-subject-body
Don't add body element to MUC subject messages
2015-06-04 11:04:05 +02:00
Holger Weiss 6c712b6caa Don't add body element to MUC subject messages 2015-06-04 09:55:38 +02:00
Evgeny Khramtsov faa4851dbf Merge pull request #591 from jpegger/patch-1
Anonymous authmodule not registering correctly anonymous users in DB
2015-06-03 20:42:00 +03:00
jpegger 6f48f22c71 Authmodule using old style XML:get_attr_s() 2015-06-03 18:11:35 +02:00
Evgeniy Khramtsov 9a9633dbc5 Do not ignore unknown options so far 2015-06-03 16:21:22 +03:00
Evgeniy Khramtsov c1119b1f39 Remove unused validation code 2015-06-03 16:05:17 +03:00
Evgeniy Khramtsov ab196b4b02 Move opt_type/1 function out of if-else block 2015-06-03 15:52:19 +03:00
Evgeniy Khramtsov 730fd55ec9 Fix typo 2015-06-03 15:45:15 +03:00
Evgeniy Khramtsov 0ae9ef2b41 Add missing options of ejabberd_logger to validator 2015-06-03 15:25:20 +03:00
Evgeniy Khramtsov 83faff37e5 Add missing options of mod_muc to validator 2015-06-03 15:18:09 +03:00
Badlop 4ed6a3d78f Fix commands export2odbc, connected_users_vhost and push_alltoall (#586) 2015-06-02 12:52:15 +02:00
badlop 0de7864880 Merge pull request #585 from CorCornelisse/master
push_roster* not updated on binarification
2015-06-02 12:24:46 +02:00
Evgeniy Khramtsov 157ff4d093 Merge branch 'master' of github.com:processone/ejabberd 2015-06-01 15:38:37 +03:00
Evgeniy Khramtsov fb6267f38e Add config validation at startup 2015-06-01 15:38:27 +03:00
Badlop 9a802185ad Fix anonymous user login, it wasn't stored in anonymous mnesia table 2015-06-01 14:34:49 +02:00
Evgeniy Khramtsov a9f7d9481f Do not try to fetch module options via eldap_utils 2015-06-01 15:22:31 +03:00
Evgeniy Khramtsov ea7de2097f Reorganize get_opt() code in some modules 2015-06-01 15:20:49 +03:00
Evgeniy Khramtsov 48213b09ce Get rid of some fuzzy macros as it makes syntax tools getting mad 2015-06-01 15:19:56 +03:00
Cor Cornelisse 22d9011c0c These arguments should be binary instead of strings, otherwise it won't work properly 2015-06-01 13:30:26 +02:00
Badlop 100827ec6e In xmlrpc use process_unicode_codepoints instead of list_to_binary 2015-05-29 15:49:12 +02:00
Evgeniy Khramtsov a291e7d4e6 Fix MUC room options vaildation 2015-05-29 12:08:36 +03:00
Christophe Romain 6cba7bf834 Add correct package version for mix (#577) 2015-05-29 09:30:16 +02:00
Evgeniy Khramtsov e8ffbbb0b4 Validate MUC room options from the configuration file 2015-05-28 11:42:17 +03:00
badlop 6a9c9616d0 Merge pull request #582 from badlop/master-badlop-578
An auth external module requires ext_mod to be started first (#578)
2015-05-27 13:49:20 +02:00
Badlop d0443bb714 An auth external module requires ext_mod to be started first (#578) 2015-05-27 13:10:15 +02:00
Holger Weiss 5585fb1ecf New options: dhfile and s2s_dhfile
Let admins specify a file that contains custom parameters for
Diffie-Hellman key exchange.
2015-05-26 21:06:04 +02:00
Christophe Romain b83c07251c Fix pubsub/odbc crash on remote user unsubscribe (EJAB-1483) 2015-05-26 19:19:57 +02:00
Alexey Shchepin b2f98099bb Merge pull request #569 from weiss/send-element-error-checking
Update send_element error checking (EJAB-1739)
2015-05-26 15:59:50 +03:00
Mickael Remond 9574e71e8d Include session record from header file instead of duplicating it 2015-05-26 10:08:46 +02:00
Paweł Chmielowski 3af507cc43 Fix merging of not yaml config files 2015-05-25 15:37:46 +02:00
Christophe Romain e54e556e01 Fix use of publish_only affiliation with odbc backend 2015-05-22 18:47:17 +02:00
Christophe Romain 90225a4744 Minor cosmetic changes and add ping command 2015-05-22 17:28:40 +02:00
Badlop 0d322d8dab Add fold markers to config file for Vim editors 2015-05-22 12:42:24 +02:00
Badlop be6ac85f31 A few more... Fix epmd not in PATH (#484)(thanks to acediac) 2015-05-22 10:40:24 +02:00
Badlop b07cb1ed84 Use namespace definitions when possible 2015-05-21 17:04:14 +02:00
Badlop 0c725b5fac Document protocol support (EJABS-1620) 2015-05-21 17:04:05 +02:00
Badlop 3b24923458 Fix dialyzer warning in mod_muc_admin:206 2015-05-21 12:00:41 +02:00
badlop b04f3a4c93 Merge pull request #573 from sezuan/fix_odbc
Fix some string/binary issues with non-native ODBC drivers
2015-05-21 11:31:47 +02:00
Christophe Romain 3188941af2 Add minor robustness on cluster scripts 2015-05-20 14:06:03 +02:00
Christophe Romain fcdb519770 Add missing sm table (thanks to Rasim Kalimullin)(EJAB-1740) 2015-05-20 13:50:59 +02:00
Evgeny Khramtsov 8985a47468 Merge pull request #576 from processone/revert-570-fix_added_sm_table_to_pg
Revert "added sm table to pg.sql"
2015-05-20 13:59:04 +03:00
Evgeny Khramtsov 05011e6918 Revert "added sm table to pg.sql" 2015-05-20 13:57:44 +03:00
Evgeny Khramtsov da68b9a572 Merge pull request #570 from sezuan/fix_added_sm_table_to_pg
added sm table to pg.sql
2015-05-20 13:46:02 +03:00
Holger Weiss 889459b45c Fix function specification 2015-05-20 12:13:15 +02:00
Christophe Romain 1854b5e411 Remove obsolete doc and win32 files (EJAB-1738) 2015-05-20 11:43:29 +02:00
Evgeniy Khramtsov 3b267eaa61 Do not bounce normal messages sent to unavailable resource 2015-05-19 10:58:36 +03:00
Holger Weiss fba13a0b93 Simplify XEP-0203 (Delayed Delivery) code a bit
Now that XEP-0091 support is removed, the XEP-0203 code can be
simplified a little further.  This doesn't change the behavior.
2015-05-18 21:26:51 +02:00
Christophe Romain 8bb994dbca Call integer_to_binary using jlib (#554) 2015-05-18 17:30:25 +02:00
Holger Weiss dfbef8be8f Remove XEP-0091 tags from test suite 2015-05-18 14:38:57 +02:00
Badlop 2af659b737 Remove deprecated XEP-0090 Entity Time and 91 Delayed Delivery (EJAB-849) 2015-05-18 12:38:25 +02:00
Matthias Rieber 16532dd643 Fixed some string()/binary() issues in ejabberd_odbc 2015-05-18 12:14:56 +02:00
Holger Weiss 555c1736b7 Revert "Fix EJABBERD_OPTS quoting for Elixir"
This reverts commit 2a15453d98.

The commit broke the case where 'log_rotate_date' is set to "$D0", for
example.
2015-05-18 00:48:56 +02:00
Evgeny Khramtsov e66b45d886 Merge pull request #571 from sezuan/fix_export_term
fixed erl_prettypr in encode_term
2015-05-17 22:44:14 +03:00
Matthias Rieber 0800a9733c pg - added sm table 2015-05-17 21:38:33 +02:00
Matthias Rieber f5c9dfbc93 fixed erl_prettypr in encode_term 2015-05-17 19:37:49 +02:00
Badlop 084d0c4efe New command get_room_options (#567) 2015-05-15 17:47:10 +02:00
Holger Weiss 61afd668c2 Fix indentation 2015-05-15 15:50:43 +02:00
Paweł Chmielowski de7ff536b2 Load config snippets for modules installed with ext_mod (EJAB-1741) 2015-05-15 12:30:15 +02:00
Paweł Chmielowski 5dbe7a3c6c Export modules_dir/0 2015-05-15 12:27:59 +02:00
Holger Weiss 6efce7f706 Cosmetic change: Simplify error checking
Let send_stanza_and_ack_req/2 update the #state instead of propagating
the value returned by send_element/2.  This doesn't change the behavior.
2015-05-14 01:04:23 +02:00
Holger Weiss 42c7205739 Don't assume send_element/2 returns ok or error
Let send_text/2 and (therefore) send_element/2 return {error, Reason}
instead of error for consistency, and let send_stanza_and_ack_req/2
interpret any non-ok value as an error.  (EJAB-1739)
2015-05-14 00:58:36 +02:00
Christophe Romain dbcfd38c18 Allow run joincluster as non root when ejabberd installed as root (#497) 2015-05-13 15:54:28 +02:00
Christophe Romain 09f5565ca0 Merge pull request #503 from weiss/fix-quoting-for-elixir
Fix EJABBERD_OPTS quoting for Elixir
2015-05-13 15:46:40 +02:00
Badlop d885435552 Fix setting 'description' with change_room_option command (#567) 2015-05-12 17:37:39 +02:00
Mickaël Rémond eca3b46ee1 Merge pull request #560 from benlangfeld/feature/dev-vm
Point out availability of development environment
2015-05-12 09:52:12 +02:00
Badlop f817762cc4 New max_users_presence mod_muc option (thanks to anhcoi123)(#562) 2015-05-08 13:09:25 +02:00
Badlop 25beb46391 Fix check_password_hash argument parsing (#559) 2015-05-08 12:04:04 +02:00
Badlop 7ab6c4b4fd Try to support access_commands in YAML (ejabberd-contrib#45) 2015-05-07 18:34:05 +02:00
Badlop b0b004b26e Revert "Add private and roster local handlers (EJAB-682)" due to #556
This reverts commit 2e194bd997.
2015-05-07 17:07:49 +02:00
Badlop f7d9bb7ce4 Don't announce register feature once user is authenticated (#41) 2015-05-07 11:41:59 +02:00
Evgeny Khramtsov b0b3870b2e Merge pull request #561 from weiss/muc-mark-private
Tag private MUC messages with muc#user namespace
2015-05-06 13:56:13 +03:00
Holger Weiss 7297b23508 Tag private MUC messages with muc#user namespace
Make it possible for clients to identify private MUC messages.  One use
case would be to filter out undesired carbon copies of those.
2015-05-05 22:00:05 +02:00
Ben Langfeld 6eab111d05 Point out availability of development environment 2015-05-05 09:24:41 -03:00
Badlop fa99519f8b Simplify internal code of get_last and set_last commands 2015-05-05 12:54:20 +02:00
Badlop 96c62acb1b Improve get_last command to provide also last activity status 2015-05-05 12:46:21 +02:00
Badlop 77e57afae1 Fix set_last command to work with recent ejabberd (#555) 2015-05-05 12:45:53 +02:00
Evgeniy Khramtsov 60fe008268 Remove duplicated code 2015-04-29 14:51:45 +03:00
Christophe Romain 6987e85602 Improve module install code, allows better error checking 2015-04-29 13:30:03 +02:00
Badlop 7492ecae52 New command get_user_rooms 2015-04-29 13:22:49 +02:00
Christophe Romain 4440b03b89 Fix fetching from git@github url and allow compilation from ejabberd sources 2015-04-29 10:19:15 +02:00
Christophe Romain 01718a4e42 Merge pull request #549 from joudinet/master
ejabberdctl: define mnesia options
2015-04-28 17:34:57 +02:00
badlop 6f99775115 Merge pull request #547 from weiss/fix-account-jid-disco
Fix service discovery handling for account JIDs
2015-04-27 19:39:32 +02:00
Johan Oudinet bd43385415 ejabberdctl: define mnesia options
In addition to factorize how the mnesia dir option is given to erl
commands, it allows one to set extra mnesia options via the
MNESIA_OPTIONS environment variable.
2015-04-27 17:25:07 +02:00
Badlop 987e337c66 Rely on core routine for handling affiliation changes (thanks to Ben Langfeld)
This ensures that all of the usual stanzas and such go out
2015-04-27 17:00:22 +02:00
Holger Weiss dc449687a0 mod_disco: Apply minor readability improvements 2015-04-26 16:36:17 +02:00
Holger Weiss 0edba763fb mod_disco: Omit 'roster_get' call if possible
As a small optimization, avoid running the 'roster_get' hook in the
(common) case where a client requests service discovery information for
its own bare JID.
2015-04-26 16:32:03 +02:00
Holger Weiss 50f35f1b07 Fix service disco handling for bare account JIDs
Don't swap the sending and receiving JIDs while checking whether the
client that requested service discovery information for a bare account
JID is a subscribed contact.
2015-04-26 16:22:09 +02:00
Evgeniy Khramtsov 9c85cb5f25 Fix validating function for iqdisc 2015-04-23 14:59:18 +03:00
Holger Weiss 2a15453d98 Fix EJABBERD_OPTS quoting for Elixir 2015-02-24 23:59:39 +01:00
163 changed files with 8405 additions and 12569 deletions
+11
View File
@@ -8,7 +8,18 @@ services:
- riak
before_install:
#
# We need MySQL 5.6 or newer in order to get support for FULLTEXT indexes
# with InnoDB. As soon as Travis ships that version, the following lines
# (except for the "apt-get update" call) can go away.
#
# See: https://github.com/travis-ci/travis-ci/issues/1986
#
- sudo sed -i -e s/table_cache/table_open_cache/ -e /log_slow_queries/d /etc/mysql/my.cnf
- sudo apt-key adv --keyserver pgp.mit.edu --recv-keys 5072E1F5
- sudo add-apt-repository 'deb http://repo.mysql.com/apt/ubuntu/ precise mysql-5.6'
- sudo apt-get -qq update
- sudo apt-get -qq -o Dpkg::Options::=--force-confold install mysql-server-5.6
install:
- sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev libsqlite3-dev
+2 -13
View File
@@ -101,10 +101,6 @@ xref: all
translations:
contrib/extract_translations/prepare-translation.sh -updateall
doc:
echo making $$target in doc; \
(cd doc && $(MAKE) $$target) || exit 1
edoc:
$(ERL) -noinput +B -eval \
'case edoc:application(ejabberd, ".", []) of ok -> halt(0); error -> halt(1) end.'
@@ -207,16 +203,9 @@ install: all
#
# Documentation
$(INSTALL) -d $(DOCDIR)
[ -f doc/dev.html ] \
&& $(INSTALL) -m 644 doc/dev.html $(DOCDIR) \
|| echo "No doc/dev.html was built"
[ -f doc/guide.html ] \
&& $(INSTALL) -m 644 doc/guide.html $(DOCDIR) \
|| echo "No doc/guide.html was built"
[ -f doc/guide.pdf ] \
&& $(INSTALL) -m 644 doc/guide.pdf $(DOCDIR) \
|| echo "No doc/guide.pdf was built"
$(INSTALL) -m 644 doc/*.png $(DOCDIR)
|| echo "Documentation not included in sources"
$(INSTALL) -m 644 COPYING $(DOCDIR)
uninstall: uninstall-binary
@@ -326,6 +315,6 @@ test:
quicktest:
$(REBAR) skip_deps=true ct suites=elixir
.PHONY: src doc edoc dialyzer Makefile TAGS clean clean-rel distclean rel \
.PHONY: src edoc dialyzer Makefile TAGS clean clean-rel distclean rel \
install uninstall uninstall-binary uninstall-all translations deps test spec \
quicktest erlang_plt deps_plt ejabberd_plt
-176
View File
@@ -1,176 +0,0 @@
include Makefile.inc
ALL : build
REL=..\release
EREL=$(REL)\ejabberd-$(EJABBERD_VERSION)
EBIN_DIR=$(EREL)\ebin
SRC_DIR=$(EREL)\src
PRIV_DIR=$(EREL)\priv
SO_DIR=$(EREL)
MSGS_DIR=$(EREL)\msgs
WIN32_DIR=$(EREL)\win32
DOC_DIR=$(EREL)\doc
NSIS_SCRIPT=win32\ejabberd.nsi
NSIS_HEADER=win32\ejabberd.nsh
installer : $(NSIS_SCRIPT) $(NSIS_HEADER)
makensis $(NSIS_SCRIPT)
$(NSIS_HEADER) : Makefile.inc
echo !define OUTFILEDIR "..\$(REL)" >$(NSIS_HEADER)
echo !define TESTDIR "..\$(REL)\ejabberd-$(EJABBERD_VERSION)" >>$(NSIS_HEADER)
echo !define VERSION "$(EJABBERD_VERSION)" >>$(NSIS_HEADER)
release_clean :
if exist $(REL) rd /s /q $(REL)
release : build release_clean
mkdir $(REL)
mkdir $(EREL)
mkdir $(EBIN_DIR)
copy *.beam $(EBIN_DIR)
@erase $(EBIN_DIR)\configure.beam
copy *.app $(EBIN_DIR)
copy *.dll $(SO_DIR)
mkdir $(MSGS_DIR)
copy msgs\*.msg $(MSGS_DIR)
mkdir $(WIN32_DIR)
copy win32\ejabberd.cfg $(EREL)
copy win32\inetrc $(EREL)
copy $(SYSTEMROOT)\system32\libeay32.dll $(EREL)
copy $(SYSTEMROOT)\system32\ssleay32.dll $(EREL)
copy win32\ejabberd.ico $(WIN32_DIR)
mkdir $(SRC_DIR)
copy *.app $(SRC_DIR)
copy *.erl $(SRC_DIR)
copy *.hrl $(SRC_DIR)
copy *.c $(SRC_DIR)
mkdir $(SRC_DIR)\eldap
copy eldap\eldap.* $(SRC_DIR)\eldap
copy eldap\ELDAPv3.asn $(SRC_DIR)\eldap
mkdir $(SRC_DIR)\mod_irc
copy mod_irc\*.erl $(SRC_DIR)\mod_irc
copy mod_irc\*.c $(SRC_DIR)\mod_irc
mkdir $(SRC_DIR)\mod_muc
copy mod_muc\*.erl $(SRC_DIR)\mod_muc
mkdir $(SRC_DIR)\mod_pubsub
copy mod_pubsub\*.erl $(SRC_DIR)\mod_pubsub
mkdir $(SRC_DIR)\mod_proxy65
copy mod_proxy65\*.erl $(SRC_DIR)\mod_proxy65
copy mod_proxy65\*.hrl $(SRC_DIR)\mod_proxy65
mkdir $(SRC_DIR)\stringprep
copy stringprep\*.erl $(SRC_DIR)\stringprep
copy stringprep\*.c $(SRC_DIR)\stringprep
copy stringprep\*.tcl $(SRC_DIR)\stringprep
mkdir $(SRC_DIR)\stun
copy stun\*.erl $(SRC_DIR)\stun
copy stun\*.hrl $(SRC_DIR)\stun
mkdir $(SRC_DIR)\tls
copy tls\*.erl $(SRC_DIR)\tls
copy tls\*.c $(SRC_DIR)\tls
mkdir $(SRC_DIR)\ejabberd_zlib
copy ejabberd_zlib\*.erl $(SRC_DIR)\ejabberd_zlib
copy ejabberd_zlib\*.c $(SRC_DIR)\ejabberd_zlib
mkdir $(SRC_DIR)\web
copy web\*.erl $(SRC_DIR)\web
mkdir $(SRC_DIR)\odbc
copy odbc\*.erl $(SRC_DIR)\odbc
copy odbc\*.sql $(EREL)
mkdir $(DOC_DIR)
copy ..\doc\*.txt $(DOC_DIR)
copy ..\doc\*.html $(DOC_DIR)
copy ..\doc\*.png $(DOC_DIR)
SOURCE = expat_erl.c
OBJECT = expat_erl.o
DLL = expat_erl.dll
build : $(DLL) compile-beam all-recursive
all-recursive :
cd eldap
nmake -nologo -f Makefile.win32
cd ..\mod_irc
nmake -nologo -f Makefile.win32
cd ..\mod_muc
nmake -nologo -f Makefile.win32
cd ..\mod_pubsub
nmake -nologo -f Makefile.win32
cd ..\mod_proxy65
nmake -nologo -f Makefile.win32
cd ..\stringprep
nmake -nologo -f Makefile.win32
cd ..\stun
nmake -nologo -f Makefile.win32
cd ..\tls
nmake -nologo -f Makefile.win32
cd ..\ejabberd_zlib
nmake -nologo -f Makefile.win32
cd ..\web
nmake -nologo -f Makefile.win32
cd ..\odbc
nmake -nologo -f Makefile.win32
cd ..
compile-beam : XmppAddr.hrl
erl -s make all report -noinput -s erlang halt
XmppAddr.hrl : XmppAddr.asn1
erlc -bber_bin +der +compact_bit_string +optimize +noobj XmppAddr.asn1
CLEAN : clean-recursive clean-local
clean-local :
-@erase $(OBJECT)
-@erase $(DLL)
-@erase expat_erl.exp
-@erase expat_erl.lib
-@erase *.beam
-@erase XmppAddr.asn1db
-@erase XmppAddr.erl
-@erase XmppAddr.hrl
clean-recursive :
cd eldap
nmake -nologo -f Makefile.win32 clean
cd ..\mod_irc
nmake -nologo -f Makefile.win32 clean
cd ..\mod_muc
nmake -nologo -f Makefile.win32 clean
cd ..\mod_pubsub
nmake -nologo -f Makefile.win32 clean
cd ..\mod_proxy65
nmake -nologo -f Makefile.win32 clean
cd ..\stringprep
nmake -nologo -f Makefile.win32 clean
cd ..\stun
nmake -nologo -f Makefile.win32 clean
cd ..\tls
nmake -nologo -f Makefile.win32 clean
cd ..\ejabberd_zlib
nmake -nologo -f Makefile.win32 clean
cd ..\web
nmake -nologo -f Makefile.win32 clean
cd ..\odbc
nmake -nologo -f Makefile.win32 clean
cd ..
distclean : release_clean clean
-@erase $(NSIS_HEADER)
-@erase Makefile.inc
CC=cl.exe
CC_FLAGS=-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT $(EXPAT_FLAG) -MD -Ox -I"$(ERLANG_DIR)\usr\include" -I"$(EI_DIR)\include" -I"$(EXPAT_DIR)\source\lib"
LD=link.exe
LD_FLAGS=-release -nologo -incremental:no -dll "$(EI_DIR)\lib\ei_md.lib" "$(EI_DIR)\lib\erl_interface_md.lib" "$(EXPAT_LIB)" MSVCRT.LIB kernel32.lib advapi32.lib gdi32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib
$(DLL) : $(OBJECT)
$(LD) $(LD_FLAGS) -out:$@ $<
$(OBJECT) : $(SOURCE)
$(CC) $(CC_FLAGS) -c -Fo$@ $<
+12
View File
@@ -152,6 +152,18 @@ Operation Guide available online and in the `doc` directory of the source
tarball.
Development
-----------
In order to assist in the development of ejabberd, and particularly the
execution of the test suite, a Vagrant environment is available at
https://github.com/processone/ejabberd-vagrant-dev.
To start ejabberd in development mode from the repository directory, you can
type a command like:
EJABBERD_CONFIG_PATH=ejabberd.yml erl -pa ebin -pa deps/*/ebin -pa test -s ejabberd
Links
-----
+2
View File
@@ -6,6 +6,8 @@ AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 0.0`
REQUIRE_ERLANG_MIN="5.9.1 (Erlang/OTP R15B01)"
REQUIRE_ERLANG_MAX="9.0.0 (No Max)"
AC_CONFIG_MACRO_DIR([m4])
# Checks for programs.
AC_PROG_MAKE_SET
AC_PROG_INSTALL
-62
View File
@@ -1,62 +0,0 @@
# $Id$
SHELL = /bin/sh
CONTRIBUTED_MODULES = ""
#ifeq ($(shell ls mod_http_bind.tex),mod_http_bind.tex)
# CONTRIBUTED_MODULES += "\\n\\setboolean{modhttpbind}{true}"
#endif
all: release pdf html
release:
@printf '%s\n' "Notes for the releaser:"
@printf '%s\n' "* Do not forget to add a link to the release notes in guide.tex"
@printf '%s\n' "* Do not forget to update the version number in ebin/ejabberd.app!"
@printf '%s\n' "* Do not forget to update the features in introduction.tex (including \new{} and \improved{} tags)."
@printf '%s\n' "Press any key to continue"
##@read foo
@printf '%s\n' "% ejabberd version (automatically generated)." > version.tex
@printf '%s\n' "\newcommand{\version}{"`sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../ebin/ejabberd.app`"}" >> version.tex
@printf '%s' "% Contributed modules (automatically generated)." > contributed_modules.tex
@printf '%b\n' "$(CONTRIBUTED_MODULES)" >> contributed_modules.tex
html: guide.html dev.html features.html
pdf: guide.pdf features.pdf
clean:
rm -f *.aux
rm -f *.haux
rm -f *.htoc
rm -f *.idx
rm -f *.ilg
rm -f *.ind
rm -f *.log
rm -f *.out
rm -f *.pdf
rm -f *.toc
[ ! -f contributed_modules.tex ] || rm contributed_modules.tex
distclean: clean
rm -f *.html
guide.html: guide.tex
hevea -fix -pedantic guide.tex
dev.html: dev.tex
hevea -fix -pedantic dev.tex
features.html: features.tex
hevea -fix -pedantic features.tex
guide.pdf: guide.tex
pdflatex guide.tex
pdflatex guide.tex
pdflatex guide.tex
makeindex guide.idx
pdflatex guide.tex
features.pdf: features.tex
pdflatex features.tex
-18
View File
@@ -1,18 +0,0 @@
APPNAME = ejabberd
VSN = $(shell sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../../src/ejabberd.app)
DOCDIR=.
SRCDIR=../../src
.PHONY = all
all: docs
clean:
rm -f *.html
rm edoc-info
rm erlang.png
docs:
erl -noshell -run edoc_run application \
"'$(APPNAME)'" '"$(SRCDIR)"' '[{dir,"$(DOCDIR)"},{packages, false},{todo,true},{private,true},{def,{vsn,"$(VSN)"}},{stylesheet,"process-one.css"},{overview,"$(DOCDIR)/overview.edoc"}]' -s init stop
-10
View File
@@ -1,10 +0,0 @@
@author Mickael Remond <mickael.remond@process-one.net>
[http://www.process-one.net/]
@copyright 2013 ProcessOne
@version {@vsn}, {@date} {@time}
@title ejabberd Development API Documentation
@doc
== Introduction ==
TODO: Insert content from Jerome documentation.
-92
View File
@@ -1,92 +0,0 @@
html, body {
font-family: Verdana, sans-serif;
color: #000;
background-color: #fff;
}
h1 {
color: #4a5389;
border-bottom: solid 1px #000;
}
h2 {
font-size: 24px;
text-align: right;
color: #4a5389;
border-bottom: 1px solid #000;
}
h3 {
font-size: 18px;
color: #900;
}
h4 {
font-size: 14px;
color: #000;
}
a[href] {
color: #4a5389;
}
a[href]:hover {
background-color: #ecefff;
}
p, li, dd {
text-align: justify;
}
li {
margin-top: 0.3em;
}
li:first-child {
margin-top: 0px;
}
blockquote {
color: #555;
}
caption {
font-style: italic;
color: #009;
text-align: left;
margin-left: 20px;
}
table[border="1"] {
border-collapse: collapse;
margin-bottom: 1em;
}
table[border="1"] td {
border: 1px solid #ddd;
}
pre, tt, code {
color: #461b7e;
}
pre {
margin:1ex 2ex;
border:1px dashed lightgrey;
background-color:#f9f9f9;
padding:0.5ex;
}
pre em {
font-style: normal;
font-weight: bold;
}
dt {
margin:0ex 2ex;
font-weight:bold;
}
dd {
margin:0ex 0ex 1ex 4ex;
}
-437
View File
@@ -1,437 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<meta name="generator" content="hevea 2.09">
<style type="text/css">
.li-itemize{margin:1ex 0ex;}
.li-enumerate{margin:1ex 0ex;}
.dd-description{margin:0ex 0ex 1ex 4ex;}
.dt-description{margin:0ex;}
.toc{list-style:none;}
.footnotetext{margin:0ex; padding:0ex;}
div.footnotetext P{margin:0px; text-indent:1em;}
.thefootnotes{text-align:left;margin:0ex;}
.dt-thefootnotes{margin:0em;}
.dd-thefootnotes{margin:0em 0em 0em 2em;}
.footnoterule{margin:1em auto 1em 0px;width:50%;}
.caption{padding-left:2ex; padding-right:2ex; margin-left:auto; margin-right:auto}
.title{margin:2ex auto;text-align:center}
.titlemain{margin:1ex 2ex 2ex 1ex;}
.titlerest{margin:0ex 2ex;}
.center{text-align:center;margin-left:auto;margin-right:auto;}
.flushleft{text-align:left;margin-left:0ex;margin-right:auto;}
.flushright{text-align:right;margin-left:auto;margin-right:0ex;}
div table{margin-left:inherit;margin-right:inherit;margin-bottom:2px;margin-top:2px}
td table{margin:auto;}
table{border-collapse:collapse;}
td{padding:0;}
.cellpadding0 tr td{padding:0;}
.cellpadding1 tr td{padding:1px;}
pre{text-align:left;margin-left:0ex;margin-right:auto;}
blockquote{margin-left:4ex;margin-right:4ex;text-align:left;}
td p{margin:0px;}
.boxed{border:1px solid black}
.textboxed{border:1px solid black}
.vbar{border:none;width:2px;background-color:black;}
.hbar{border:none;height:2px;width:100%;background-color:black;}
.hfill{border:none;height:1px;width:200%;background-color:black;}
.vdisplay{border-collapse:separate;border-spacing:2px;width:auto; empty-cells:show; border:2px solid red;}
.vdcell{white-space:nowrap;padding:0px; border:2px solid green;}
.display{border-collapse:separate;border-spacing:2px;width:auto; border:none;}
.dcell{white-space:nowrap;padding:0px; border:none;}
.dcenter{margin:0ex auto;}
.vdcenter{border:solid #FF8000 2px; margin:0ex auto;}
.minipage{text-align:left; margin-left:0em; margin-right:auto;}
.marginpar{border:solid thin black; width:20%; text-align:left;}
.marginparleft{float:left; margin-left:0ex; margin-right:1ex;}
.marginparright{float:right; margin-left:1ex; margin-right:0ex;}
.theorem{text-align:left;margin:1ex auto 1ex 0ex;}
.part{margin:2ex auto;text-align:center}
</style>
<title>Ejabberd community 14.05-120-gedfb5fc Developers Guide
</title>
</head>
<body >
<!--HEVEA command line is: /usr/bin/hevea -fix -pedantic dev.tex -->
<!--CUT STYLE article--><!--CUT DEF section 1 --><p><a id="titlepage"></a>
</p><table class="title"><tr><td style="padding:1ex"><h1 class="titlemain">Ejabberd community 14.05-120-gedfb5fc Developers Guide</h1><h3 class="titlerest">Alexey Shchepin <br>
<a href="mailto:alexey@sevcom.net"><span style="font-family:monospace">mailto:alexey@sevcom.net</span></a> <br>
<a href="xmpp:aleksey@jabber.ru"><span style="font-family:monospace">xmpp:aleksey@jabber.ru</span></a></h3></td></tr>
</table><div class="center">
<img src="logo.png" alt="logo.png">
</div><blockquote class="quotation"><span style="font-style:italic">I can thoroughly recommend ejabberd for ease of setup &#X2013;
Kevin Smith, Current maintainer of the Psi project</span></blockquote><!--TOC section id="intro" Contents-->
<h2 id="intro" class="section">Contents</h2><!--SEC END --><ul class="toc"><li class="li-toc">
<a href="#sec2">1&#XA0;&#XA0;Key Features</a>
</li><li class="li-toc"><a href="#sec3">2&#XA0;&#XA0;Additional Features</a>
</li><li class="li-toc"><a href="#sec4">3&#XA0;&#XA0;How it Works</a>
<ul class="toc"><li class="li-toc">
<a href="#sec5">3.1&#XA0;&#XA0;Router</a>
</li><li class="li-toc"><a href="#sec6">3.2&#XA0;&#XA0;Local Router</a>
</li><li class="li-toc"><a href="#sec7">3.3&#XA0;&#XA0;Session Manager</a>
</li><li class="li-toc"><a href="#sec8">3.4&#XA0;&#XA0;S2S Manager</a>
</li></ul>
</li><li class="li-toc"><a href="#sec9">4&#XA0;&#XA0;Authentication</a>
<ul class="toc">
<ul class="toc"><li class="li-toc">
<a href="#sec10">4.0.1&#XA0;&#XA0;External</a>
</li></ul>
</ul>
</li><li class="li-toc"><a href="#sec11">5&#XA0;&#XA0;XML Representation</a>
</li><li class="li-toc"><a href="#sec12">6&#XA0;&#XA0;Module <span style="font-family:monospace">xml</span></a>
</li><li class="li-toc"><a href="#sec13">7&#XA0;&#XA0;Module <span style="font-family:monospace">xml_stream</span></a>
</li><li class="li-toc"><a href="#sec14">8&#XA0;&#XA0;Modules</a>
<ul class="toc"><li class="li-toc">
<a href="#sec15">8.1&#XA0;&#XA0;Module gen_iq_handler</a>
</li><li class="li-toc"><a href="#sec16">8.2&#XA0;&#XA0;Services</a>
</li></ul>
</li></ul><p>Introduction
</p><p><span style="font-family:monospace">ejabberd</span> is a free and open source instant messaging server written in <a href="http://www.erlang.org/">Erlang/OTP</a>.</p><p><span style="font-family:monospace">ejabberd</span> is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication.</p><p><span style="font-family:monospace">ejabberd</span> is designed to be a rock-solid and feature rich XMPP server.</p><p><span style="font-family:monospace">ejabberd</span> is suitable for small deployments, whether they need to be scalable or not, as well as extremely big deployments.</p>
<!--TOC section id="sec2" Key Features-->
<h2 id="sec2" class="section">1&#XA0;&#XA0;Key Features</h2><!--SEC END --><p>
<a id="keyfeatures"></a>
</p><p><span style="font-family:monospace">ejabberd</span> is:
</p><ul class="itemize"><li class="li-itemize">
Cross-platform: <span style="font-family:monospace">ejabberd</span> runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.</li><li class="li-itemize">Distributed: You can run <span style="font-family:monospace">ejabberd</span> on a cluster of machines and all of them will serve the same Jabber domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.</li><li class="li-itemize">Fault-tolerant: You can deploy an <span style="font-family:monospace">ejabberd</span> cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced &#X2018;on the fly&#X2019;.</li><li class="li-itemize">Administrator Friendly: <span style="font-family:monospace">ejabberd</span> is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
<ul class="itemize"><li class="li-itemize">
Comprehensive documentation.
</li><li class="li-itemize">Straightforward installers for Linux, Mac OS X, and Windows. </li><li class="li-itemize">Web Administration.
</li><li class="li-itemize">Shared Roster Groups.
</li><li class="li-itemize">Command line administration tool. </li><li class="li-itemize">Can integrate with existing authentication mechanisms.
</li><li class="li-itemize">Capability to send announce messages.
</li></ul></li><li class="li-itemize">Internationalized: <span style="font-family:monospace">ejabberd</span> leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
<ul class="itemize"><li class="li-itemize">
Translated to 25 languages. </li><li class="li-itemize">Support for <a href="http://www.ietf.org/rfc/rfc3490.txt">IDNA</a>.
</li></ul></li><li class="li-itemize">Open Standards: <span style="font-family:monospace">ejabberd</span> is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
<ul class="itemize"><li class="li-itemize">
Fully XMPP compliant.
</li><li class="li-itemize">XML-based protocol.
</li><li class="li-itemize"><a href="http://www.ejabberd.im/protocols">Many protocols supported</a>.
</li></ul></li></ul>
<!--TOC section id="sec3" Additional Features-->
<h2 id="sec3" class="section">2&#XA0;&#XA0;Additional Features</h2><!--SEC END --><p>
<a id="addfeatures"></a>
</p><p>Moreover, <span style="font-family:monospace">ejabberd</span> comes with a wide range of other state-of-the-art features:
</p><ul class="itemize"><li class="li-itemize">
Modular
<ul class="itemize"><li class="li-itemize">
Load only the modules you want.
</li><li class="li-itemize">Extend <span style="font-family:monospace">ejabberd</span> with your own custom modules.
</li></ul>
</li><li class="li-itemize">Security
<ul class="itemize"><li class="li-itemize">
SASL and STARTTLS for c2s and s2s connections.
</li><li class="li-itemize">STARTTLS and Dialback s2s connections.
</li><li class="li-itemize">Web Admin accessible via HTTPS secure access.
</li></ul>
</li><li class="li-itemize">Databases
<ul class="itemize"><li class="li-itemize">
Internal database for fast deployment (Mnesia).
</li><li class="li-itemize">Native MySQL support.
</li><li class="li-itemize">Native PostgreSQL support.
</li><li class="li-itemize">ODBC data storage support.
</li><li class="li-itemize">Microsoft SQL Server support. </li><li class="li-itemize">Riak NoSQL database support.
</li></ul>
</li><li class="li-itemize">Authentication
<ul class="itemize"><li class="li-itemize">
Internal Authentication.
</li><li class="li-itemize">PAM, LDAP, ODBC and Riak. </li><li class="li-itemize">External Authentication script.
</li></ul>
</li><li class="li-itemize">Others
<ul class="itemize"><li class="li-itemize">
Support for virtual hosting.
</li><li class="li-itemize">Compressing XML streams with Stream Compression (<a href="http://www.xmpp.org/extensions/xep-0138.html">XEP-0138</a>).
</li><li class="li-itemize">Statistics via Statistics Gathering (<a href="http://www.xmpp.org/extensions/xep-0039.html">XEP-0039</a>).
</li><li class="li-itemize">IPv6 support both for c2s and s2s connections.
</li><li class="li-itemize"><a href="http://www.xmpp.org/extensions/xep-0045.html">Multi-User Chat</a> module with support for clustering and HTML logging. </li><li class="li-itemize">Users Directory based on users vCards.
</li><li class="li-itemize"><a href="http://www.xmpp.org/extensions/xep-0060.html">Publish-Subscribe</a> component with support for <a href="http://www.xmpp.org/extensions/xep-0163.html">Personal Eventing via Pubsub</a>.
</li><li class="li-itemize">Support for web clients: <a href="http://www.xmpp.org/extensions/xep-0025.html">HTTP Polling</a> and <a href="http://www.xmpp.org/extensions/xep-0206.html">HTTP Binding (BOSH)</a> services.
</li><li class="li-itemize">IRC transport.
</li><li class="li-itemize">SIP support.
</li><li class="li-itemize">Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
</li></ul>
</li></ul>
<!--TOC section id="sec4" How it Works-->
<h2 id="sec4" class="section">3&#XA0;&#XA0;How it Works</h2><!--SEC END --><p>
<a id="howitworks"></a></p><p>A XMPP domain is served by one or more <span style="font-family:monospace">ejabberd</span> nodes. These nodes can
be run on different machines that are connected via a network. They all must
have the ability to connect to port 4369 of all another nodes, and must have
the same magic cookie (see Erlang/OTP documentation, in other words the file
<span style="font-family:monospace">~ejabberd/.erlang.cookie</span> must be the same on all nodes). This is
needed because all nodes exchange information about connected users, S2S
connections, registered services, etc&#X2026;</p><p>Each <span style="font-family:monospace">ejabberd</span> node have following modules:
</p><ul class="itemize"><li class="li-itemize">
router;
</li><li class="li-itemize">local router.
</li><li class="li-itemize">session manager;
</li><li class="li-itemize">S2S manager;
</li></ul>
<!--TOC subsection id="sec5" Router-->
<h3 id="sec5" class="subsection">3.1&#XA0;&#XA0;Router</h3><!--SEC END --><p>This module is the main router of XMPP packets on each node. It routes
them based on their destinations domains. It has two tables: local and global
routes. First, domain of packet destination searched in local table, and if it
found, then the packet is routed to appropriate process. If no, then it
searches in global table, and is routed to the appropriate <span style="font-family:monospace">ejabberd</span> node or
process. If it does not exists in either tables, then it sent to the S2S
manager.</p>
<!--TOC subsection id="sec6" Local Router-->
<h3 id="sec6" class="subsection">3.2&#XA0;&#XA0;Local Router</h3><!--SEC END --><p>This module routes packets which have a destination domain equal to this server
name. If destination JID has a non-empty user part, then it routed to the
session manager, else it is processed depending on it&#X2019;s content.</p>
<!--TOC subsection id="sec7" Session Manager-->
<h3 id="sec7" class="subsection">3.3&#XA0;&#XA0;Session Manager</h3><!--SEC END --><p>This module routes packets to local users. It searches for what user resource
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 id="sec8" S2S Manager-->
<h3 id="sec8" class="subsection">3.4&#XA0;&#XA0;S2S Manager</h3><!--SEC END --><p>This module routes packets to other XMPP servers. First, it checks if an
open S2S connection from the domain of the packet source to the domain of
packet destination already exists. If it is open on another node, then it
routes the packet to S2S manager on that node, if it is open on this node, then
it is routed to the process that serves this connection, and if a connection
does not exist, then it is opened and registered.</p>
<!--TOC section id="sec9" Authentication-->
<h2 id="sec9" class="section">4&#XA0;&#XA0;Authentication</h2><!--SEC END -->
<!--TOC subsubsection id="sec10" External-->
<h4 id="sec10" class="subsubsection">4.0.1&#XA0;&#XA0;External</h4><!--SEC END --><p>
<a id="externalauth"></a>
</p><p>The external authentication script follows
<a href="http://www.erlang.org/doc/tutorial/c_portdriver.html">the erlang port driver API</a>.</p><p>That script is supposed to do theses actions, in an infinite loop:
</p><ul class="itemize"><li class="li-itemize">
read from stdin: AABBBBBBBBB.....
<ul class="itemize"><li class="li-itemize">
A: 2 bytes of length data (a short in network byte order)
</li><li class="li-itemize">B: a string of length found in A that contains operation in plain text
operation are as follows:
<ul class="itemize"><li class="li-itemize">
auth:User:Server:Password (check if a username/password pair is correct)
</li><li class="li-itemize">isuser:User:Server (check if it&#X2019;s a valid user)
</li><li class="li-itemize">setpass:User:Server:Password (set user&#X2019;s password)
</li><li class="li-itemize">tryregister:User:Server:Password (try to register an account)
</li><li class="li-itemize">removeuser:User:Server (remove this account)
</li><li class="li-itemize">removeuser3:User:Server:Password (remove this account if the password is correct)
</li></ul>
</li></ul>
</li><li class="li-itemize">write to stdout: AABB
<ul class="itemize"><li class="li-itemize">
A: the number 2 (coded as a short, which is bytes length of following result)
</li><li class="li-itemize">B: the result code (coded as a short), should be 1 for success/valid, or 0 for failure/invalid
</li></ul>
</li></ul><p>Example python script
</p><pre class="verbatim">#!/usr/bin/python
import sys
from struct import *
def from_ejabberd():
input_length = sys.stdin.read(2)
(size,) = unpack('&gt;h', input_length)
return sys.stdin.read(size).split(':')
def to_ejabberd(bool):
answer = 0
if bool:
answer = 1
token = pack('&gt;hh', 2, answer)
sys.stdout.write(token)
sys.stdout.flush()
def auth(username, server, password):
return True
def isuser(username, server):
return True
def setpass(username, server, password):
return True
while True:
data = from_ejabberd()
success = False
if data[0] == "auth":
success = auth(data[1], data[2], data[3])
elif data[0] == "isuser":
success = isuser(data[1], data[2])
elif data[0] == "setpass":
success = setpass(data[1], data[2], data[3])
to_ejabberd(success)
</pre>
<!--TOC section id="sec11" XML Representation-->
<h2 id="sec11" class="section">5&#XA0;&#XA0;XML Representation</h2><!--SEC END --><p>
<a id="xmlrepr"></a></p><p>Each XML stanza is represented as the following tuple:
</p><pre class="verbatim">XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
Name = string()
Attrs = [Attr]
Attr = {Key, Val}
Key = string()
Val = string()
ElementOrCDATA = XMLElement | CDATA
CDATA = {xmlcdata, string()}
</pre><p>E.&#XA0;g. this stanza:
</p><pre class="verbatim">&lt;message to='test@conference.example.org' type='groupchat'&gt;
&lt;body&gt;test&lt;/body&gt;
&lt;/message&gt;
</pre><p>is represented as the following structure:
</p><pre class="verbatim">{xmlelement, "message",
[{"to", "test@conference.example.org"},
{"type", "groupchat"}],
[{xmlelement, "body",
[],
[{xmlcdata, "test"}]}]}}
</pre>
<!--TOC section id="sec12" Module <span style="font-family:monospace">xml</span>-->
<h2 id="sec12" class="section">6&#XA0;&#XA0;Module <span style="font-family:monospace">xml</span></h2><!--SEC END --><p>
<a id="xmlmod"></a></p><dl class="description"><dt class="dt-description">
</dt><dd class="dd-description"><code>element_to_string(El) -&gt; string()</code>
<pre class="verbatim">El = XMLElement
</pre>Returns string representation of XML stanza <span style="font-family:monospace">El</span>.</dd><dt class="dt-description"></dt><dd class="dd-description"><code>crypt(S) -&gt; string()</code>
<pre class="verbatim">S = string()
</pre>Returns string which correspond to <span style="font-family:monospace">S</span> with encoded XML special
characters.</dd><dt class="dt-description"></dt><dd class="dd-description"><code>remove_cdata(ECList) -&gt; EList</code>
<pre class="verbatim">ECList = [ElementOrCDATA]
EList = [XMLElement]
</pre><span style="font-family:monospace">EList</span> is a list of all non-CDATA elements of ECList.</dd><dt class="dt-description"></dt><dd class="dd-description"><code>get_path_s(El, Path) -&gt; Res</code>
<pre class="verbatim">El = XMLElement
Path = [PathItem]
PathItem = PathElem | PathAttr | PathCDATA
PathElem = {elem, Name}
PathAttr = {attr, Name}
PathCDATA = cdata
Name = string()
Res = string() | XMLElement
</pre>If <span style="font-family:monospace">Path</span> is empty, then returns <span style="font-family:monospace">El</span>. Else sequentially
consider elements of <span style="font-family:monospace">Path</span>. Each element is one of:
<dl class="description"><dt class="dt-description">
</dt><dd class="dd-description"><code>{elem, Name}</code> <span style="font-family:monospace">Name</span> is name of subelement of
<span style="font-family:monospace">El</span>, if such element exists, then this element considered in
following steps, else returns empty string.
</dd><dt class="dt-description"></dt><dd class="dd-description"><code>{attr, Name}</code> If <span style="font-family:monospace">El</span> have attribute <span style="font-family:monospace">Name</span>, then
returns value of this attribute, else returns empty string.
</dd><dt class="dt-description"></dt><dd class="dd-description"><code>cdata</code> Returns CDATA of <span style="font-family:monospace">El</span>.
</dd></dl></dd><dt class="dt-description"></dt><dd class="dd-description">TODO:
<pre class="verbatim"> get_cdata/1, get_tag_cdata/1
get_attr/2, get_attr_s/2
get_tag_attr/2, get_tag_attr_s/2
get_subtag/2
</pre></dd></dl>
<!--TOC section id="sec13" Module <span style="font-family:monospace">xml_stream</span>-->
<h2 id="sec13" class="section">7&#XA0;&#XA0;Module <span style="font-family:monospace">xml_stream</span></h2><!--SEC END --><p>
<a id="xmlstreammod"></a></p><dl class="description"><dt class="dt-description">
</dt><dd class="dd-description"><code>parse_element(Str) -&gt; XMLElement | {error, Err}</code>
<pre class="verbatim">Str = string()
Err = term()
</pre>Parses <span style="font-family:monospace">Str</span> using XML parser, returns either parsed element or error
tuple.
</dd></dl>
<!--TOC section id="sec14" Modules-->
<h2 id="sec14" class="section">8&#XA0;&#XA0;Modules</h2><!--SEC END --><p>
<a id="emods"></a></p>
<!--TOC subsection id="sec15" Module gen_iq_handler-->
<h3 id="sec15" class="subsection">8.1&#XA0;&#XA0;Module gen_iq_handler</h3><!--SEC END --><p>
<a id="geniqhandl"></a></p><p>The module <code>gen_iq_handler</code> allows to easily write handlers for IQ packets
of particular XML namespaces that addressed to server or to users bare JIDs.</p><p>In this module the following functions are defined:
</p><dl class="description"><dt class="dt-description">
</dt><dd class="dd-description"><code>add_iq_handler(Component, Host, NS, Module, Function, Type)</code>
<pre class="verbatim">Component = Module = Function = atom()
Host = NS = string()
Type = no_queue | one_queue | parallel
</pre>Registers function <code>Module:Function</code> as handler for IQ packets on
virtual host <code>Host</code> that contain child of namespace <code>NS</code> in
<code>Component</code>. Queueing discipline is <code>Type</code>. There are at least
two components defined:
<dl class="description"><dt class="dt-description">
</dt><dd class="dd-description"><code>ejabberd_local</code> Handles packets that addressed to server JID;
</dd><dt class="dt-description"></dt><dd class="dd-description"><code>ejabberd_sm</code> Handles packets that addressed to users bare JIDs.
</dd></dl>
</dd><dt class="dt-description"></dt><dd class="dd-description"><code>remove_iq_handler(Component, Host, NS)</code>
<pre class="verbatim">Component = atom()
Host = NS = string()
</pre>Removes IQ handler on virtual host <code>Host</code> for namespace <code>NS</code> from
<code>Component</code>.
</dd></dl><p>Handler function must have the following type:
</p><dl class="description"><dt class="dt-description">
</dt><dd class="dd-description"><code>Module:Function(From, To, IQ)</code>
<pre class="verbatim">From = To = jid()
</pre></dd></dl><pre class="verbatim">-module(mod_cputime).
-behaviour(gen_mod).
-export([start/2,
stop/1,
process_local_iq/3]).
-include("ejabberd.hrl").
-include("jlib.hrl").
-define(NS_CPUTIME, "ejabberd:cputime").
start(Host, Opts) -&gt;
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_CPUTIME,
?MODULE, process_local_iq, IQDisc).
stop(Host) -&gt;
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_CPUTIME).
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -&gt;
case Type of
set -&gt;
{iq, ID, error, XMLNS,
[SubEl, ?ERR_NOT_ALLOWED]};
get -&gt;
CPUTime = element(1, erlang:statistics(runtime))/1000,
SCPUTime = lists:flatten(io_lib:format("~.3f", CPUTime)),
{iq, ID, result, XMLNS,
[{xmlelement, "query",
[{"xmlns", ?NS_CPUTIME}],
[{xmlelement, "cputime", [], [{xmlcdata, SCPUTime}]}]}]}
end.
</pre>
<!--TOC subsection id="sec16" Services-->
<h3 id="sec16" class="subsection">8.2&#XA0;&#XA0;Services</h3><!--SEC END --><p>
<a id="services"></a></p><pre class="verbatim">-module(mod_echo).
-behaviour(gen_mod).
-export([start/2, init/1, stop/1]).
-include("ejabberd.hrl").
-include("jlib.hrl").
start(Host, Opts) -&gt;
MyHost = gen_mod:get_opt(host, Opts, "echo." ++ Host),
register(gen_mod:get_module_proc(Host, ?PROCNAME),
spawn(?MODULE, init, [MyHost])).
init(Host) -&gt;
ejabberd_router:register_local_route(Host),
loop(Host).
loop(Host) -&gt;
receive
{route, From, To, Packet} -&gt;
ejabberd_router:route(To, From, Packet),
loop(Host);
stop -&gt;
ejabberd_router:unregister_route(Host),
ok;
_ -&gt;
loop(Host)
end.
stop(Host) -&gt;
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
Proc ! stop,
{wait, Proc}.
</pre><!--CUT END -->
<!--HTMLFOOT-->
<!--ENDHTML-->
<!--FOOTER-->
<hr style="height:2"><blockquote class="quote"><em>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
</em><a href="http://hevea.inria.fr/index.html"><em>H</em><em><span style="font-size:small"><sup>E</sup></span></em><em>V</em><em><span style="font-size:small"><sup>E</sup></span></em><em>A</em></a><em>.</em></blockquote></body>
</html>
-470
View File
@@ -1,470 +0,0 @@
\documentclass[a4paper,10pt]{article}
%% Packages
\usepackage{graphics}
\usepackage{hevea}
\usepackage{makeidx}
\usepackage{verbatim}
%% Index
\makeindex
% Remove the index anchors from the HTML version to save size and bandwith.
\newcommand{\ind}[1]{\begin{latexonly}\index{#1}\end{latexonly}}
%% Images
\newcommand{\logoscale}{0.7}
\newcommand{\imgscale}{0.58}
\newcommand{\insimg}[1]{\insscaleimg{\imgscale}{#1}}
\newcommand{\insscaleimg}[2]{
\imgsrc{#2}{}
\begin{latexonly}
\scalebox{#1}{\includegraphics{#2}}
\end{latexonly}
}
%% Various
\newcommand{\ns}[1]{\texttt{#1}}
\newcommand{\ejabberd}{\texttt{ejabberd}}
\newcommand{\Jabber}{Jabber}
\newcommand{\XMPP}{XMPP}
%% Modules
\newcommand{\module}[1]{\texttt{#1}}
\newcommand{\modadhoc}{\module{mod\_adhoc}}
\newcommand{\modannounce}{\module{mod\_announce}}
\newcommand{\modconfigure}{\module{mod\_configure}}
\newcommand{\moddisco}{\module{mod\_disco}}
\newcommand{\modecho}{\module{mod\_echo}}
\newcommand{\modirc}{\module{mod\_irc}}
\newcommand{\modlast}{\module{mod\_last}}
\newcommand{\modlastodbc}{\module{mod\_last\_odbc}}
\newcommand{\modmuc}{\module{mod\_muc}}
\newcommand{\modmuclog}{\module{mod\_muc\_log}}
\newcommand{\modoffline}{\module{mod\_offline}}
\newcommand{\modofflineodbc}{\module{mod\_offline\_odbc}}
\newcommand{\modprivacy}{\module{mod\_privacy}}
\newcommand{\modprivate}{\module{mod\_private}}
\newcommand{\modpubsub}{\module{mod\_pubsub}}
\newcommand{\modregister}{\module{mod\_register}}
\newcommand{\modroster}{\module{mod\_roster}}
\newcommand{\modrosterodbc}{\module{mod\_roster\_odbc}}
\newcommand{\modservicelog}{\module{mod\_service\_log}}
\newcommand{\modsharedroster}{\module{mod\_shared\_roster}}
\newcommand{\modstats}{\module{mod\_stats}}
\newcommand{\modtime}{\module{mod\_time}}
\newcommand{\modvcard}{\module{mod\_vcard}}
\newcommand{\modvcardldap}{\module{mod\_vcard\_ldap}}
\newcommand{\modvcardodbc}{\module{mod\_vcard\_odbc}}
\newcommand{\modversion}{\module{mod\_version}}
%% Title page
\include{version}
\title{Ejabberd \version\ Developers Guide}
\author{Alexey Shchepin \\
\ahrefurl{mailto:alexey@sevcom.net} \\
\ahrefurl{xmpp:aleksey@jabber.ru}}
%% Options
\newcommand{\marking}[1]{#1} % Marking disabled
\newcommand{\quoting}[2][yozhik]{} % Quotes disabled
\newcommand{\new}{\begin{latexonly}\marginpar{\textsc{new}}\end{latexonly}} % Highlight new features
\newcommand{\improved}{\begin{latexonly}\marginpar{\textsc{improved}}\end{latexonly}} % Highlight improved features
\newcommand{\moreinfo}[1]{} % Hide details
%% Footnotes
\newcommand{\txepref}[2]{\footahref{http://www.xmpp.org/extensions/xep-#1.html}{#2}}
\newcommand{\xepref}[1]{\txepref{#1}{XEP-#1}}
\begin{document}
\label{titlepage}
\begin{titlepage}
\maketitle{}
\begin{center}
{\insscaleimg{\logoscale}{logo.png}
\par
}
\end{center}
\begin{quotation}\textit{I can thoroughly recommend ejabberd for ease of setup --
Kevin Smith, Current maintainer of the Psi project}\end{quotation}
\end{titlepage}
\tableofcontents{}
% Input introduction.tex
\input{introduction}
\section{How it Works}
\label{howitworks}
A \XMPP{} domain is served by one or more \ejabberd{} nodes. These nodes can
be run on different machines that are connected via a network. They all must
have the ability to connect to port 4369 of all another nodes, and must have
the same magic cookie (see Erlang/OTP documentation, in other words the file
\texttt{\~{}ejabberd/.erlang.cookie} must be the same on all nodes). This is
needed because all nodes exchange information about connected users, S2S
connections, registered services, etc\ldots
Each \ejabberd{} node have following modules:
\begin{itemize}
\item router;
\item local router.
\item session manager;
\item S2S manager;
\end{itemize}
\subsection{Router}
This module is the main router of \XMPP{} packets on each node. It routes
them based on their destinations domains. It has two tables: local and global
routes. First, domain of packet destination searched in local table, and if it
found, then the packet is routed to appropriate process. If no, then it
searches in global table, and is routed to the appropriate \ejabberd{} node or
process. If it does not exists in either tables, then it sent to the S2S
manager.
\subsection{Local Router}
This module routes packets which have a destination domain equal to this server
name. If destination JID has a non-empty user part, then it routed to the
session manager, else it is processed depending on it's content.
\subsection{Session Manager}
This module routes packets to local users. It searches for what user resource
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.
\subsection{S2S Manager}
This module routes packets to other \XMPP{} servers. First, it checks if an
open S2S connection from the domain of the packet source to the domain of
packet destination already exists. If it is open on another node, then it
routes the packet to S2S manager on that node, if it is open on this node, then
it is routed to the process that serves this connection, and if a connection
does not exist, then it is opened and registered.
\section{Authentication}
\subsubsection{External}
\label{externalauth}
\ind{external authentication}
The external authentication script follows
\footahref{http://www.erlang.org/doc/tutorial/c_portdriver.html}{the erlang port driver API}.
That script is supposed to do theses actions, in an infinite loop:
\begin{itemize}
\item read from stdin: AABBBBBBBBB.....
\begin{itemize}
\item A: 2 bytes of length data (a short in network byte order)
\item B: a string of length found in A that contains operation in plain text
operation are as follows:
\begin{itemize}
\item auth:User:Server:Password (check if a username/password pair is correct)
\item isuser:User:Server (check if it's a valid user)
\item setpass:User:Server:Password (set user's password)
\item tryregister:User:Server:Password (try to register an account)
\item removeuser:User:Server (remove this account)
\item removeuser3:User:Server:Password (remove this account if the password is correct)
\end{itemize}
\end{itemize}
\item write to stdout: AABB
\begin{itemize}
\item A: the number 2 (coded as a short, which is bytes length of following result)
\item B: the result code (coded as a short), should be 1 for success/valid, or 0 for failure/invalid
\end{itemize}
\end{itemize}
Example python script
\begin{verbatim}
#!/usr/bin/python
import sys
from struct import *
def from_ejabberd():
input_length = sys.stdin.read(2)
(size,) = unpack('>h', input_length)
return sys.stdin.read(size).split(':')
def to_ejabberd(bool):
answer = 0
if bool:
answer = 1
token = pack('>hh', 2, answer)
sys.stdout.write(token)
sys.stdout.flush()
def auth(username, server, password):
return True
def isuser(username, server):
return True
def setpass(username, server, password):
return True
while True:
data = from_ejabberd()
success = False
if data[0] == "auth":
success = auth(data[1], data[2], data[3])
elif data[0] == "isuser":
success = isuser(data[1], data[2])
elif data[0] == "setpass":
success = setpass(data[1], data[2], data[3])
to_ejabberd(success)
\end{verbatim}
\section{XML Representation}
\label{xmlrepr}
Each XML stanza is represented as the following tuple:
\begin{verbatim}
XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
Name = string()
Attrs = [Attr]
Attr = {Key, Val}
Key = string()
Val = string()
ElementOrCDATA = XMLElement | CDATA
CDATA = {xmlcdata, string()}
\end{verbatim}
E.\,g. this stanza:
\begin{verbatim}
<message to='test@conference.example.org' type='groupchat'>
<body>test</body>
</message>
\end{verbatim}
is represented as the following structure:
\begin{verbatim}
{xmlelement, "message",
[{"to", "test@conference.example.org"},
{"type", "groupchat"}],
[{xmlelement, "body",
[],
[{xmlcdata, "test"}]}]}}
\end{verbatim}
\section{Module \texttt{xml}}
\label{xmlmod}
\begin{description}
\item{\verb|element_to_string(El) -> string()|}
\begin{verbatim}
El = XMLElement
\end{verbatim}
Returns string representation of XML stanza \texttt{El}.
\item{\verb|crypt(S) -> string()|}
\begin{verbatim}
S = string()
\end{verbatim}
Returns string which correspond to \texttt{S} with encoded XML special
characters.
\item{\verb|remove_cdata(ECList) -> EList|}
\begin{verbatim}
ECList = [ElementOrCDATA]
EList = [XMLElement]
\end{verbatim}
\texttt{EList} is a list of all non-CDATA elements of ECList.
\item{\verb|get_path_s(El, Path) -> Res|}
\begin{verbatim}
El = XMLElement
Path = [PathItem]
PathItem = PathElem | PathAttr | PathCDATA
PathElem = {elem, Name}
PathAttr = {attr, Name}
PathCDATA = cdata
Name = string()
Res = string() | XMLElement
\end{verbatim}
If \texttt{Path} is empty, then returns \texttt{El}. Else sequentially
consider elements of \texttt{Path}. Each element is one of:
\begin{description}
\item{\verb|{elem, Name}|} \texttt{Name} is name of subelement of
\texttt{El}, if such element exists, then this element considered in
following steps, else returns empty string.
\item{\verb|{attr, Name}|} If \texttt{El} have attribute \texttt{Name}, then
returns value of this attribute, else returns empty string.
\item{\verb|cdata|} Returns CDATA of \texttt{El}.
\end{description}
\item{TODO:}
\begin{verbatim}
get_cdata/1, get_tag_cdata/1
get_attr/2, get_attr_s/2
get_tag_attr/2, get_tag_attr_s/2
get_subtag/2
\end{verbatim}
\end{description}
\section{Module \texttt{xml\_stream}}
\label{xmlstreammod}
\begin{description}
\item{\verb!parse_element(Str) -> XMLElement | {error, Err}!}
\begin{verbatim}
Str = string()
Err = term()
\end{verbatim}
Parses \texttt{Str} using XML parser, returns either parsed element or error
tuple.
\end{description}
\section{Modules}
\label{emods}
%\subsection{gen\_mod behaviour}
%\label{genmod}
%TBD
\subsection{Module gen\_iq\_handler}
\label{geniqhandl}
The module \verb|gen_iq_handler| allows to easily write handlers for IQ packets
of particular XML namespaces that addressed to server or to users bare JIDs.
In this module the following functions are defined:
\begin{description}
\item{\verb|add_iq_handler(Component, Host, NS, Module, Function, Type)|}
\begin{verbatim}
Component = Module = Function = atom()
Host = NS = string()
Type = no_queue | one_queue | parallel
\end{verbatim}
Registers function \verb|Module:Function| as handler for IQ packets on
virtual host \verb|Host| that contain child of namespace \verb|NS| in
\verb|Component|. Queueing discipline is \verb|Type|. There are at least
two components defined:
\begin{description}
\item{\verb|ejabberd_local|} Handles packets that addressed to server JID;
\item{\verb|ejabberd_sm|} Handles packets that addressed to users bare JIDs.
\end{description}
\item{\verb|remove_iq_handler(Component, Host, NS)|}
\begin{verbatim}
Component = atom()
Host = NS = string()
\end{verbatim}
Removes IQ handler on virtual host \verb|Host| for namespace \verb|NS| from
\verb|Component|.
\end{description}
Handler function must have the following type:
\begin{description}
\item{\verb|Module:Function(From, To, IQ)|}
\begin{verbatim}
From = To = jid()
\end{verbatim}
\end{description}
\begin{verbatim}
-module(mod_cputime).
-behaviour(gen_mod).
-export([start/2,
stop/1,
process_local_iq/3]).
-include("ejabberd.hrl").
-include("jlib.hrl").
-define(NS_CPUTIME, "ejabberd:cputime").
start(Host, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_CPUTIME,
?MODULE, process_local_iq, IQDisc).
stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_CPUTIME).
process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
case Type of
set ->
{iq, ID, error, XMLNS,
[SubEl, ?ERR_NOT_ALLOWED]};
get ->
CPUTime = element(1, erlang:statistics(runtime))/1000,
SCPUTime = lists:flatten(io_lib:format("~.3f", CPUTime)),
{iq, ID, result, XMLNS,
[{xmlelement, "query",
[{"xmlns", ?NS_CPUTIME}],
[{xmlelement, "cputime", [], [{xmlcdata, SCPUTime}]}]}]}
end.
\end{verbatim}
\subsection{Services}
\label{services}
%TBD
%TODO: use \verb|proc_lib|
\begin{verbatim}
-module(mod_echo).
-behaviour(gen_mod).
-export([start/2, init/1, stop/1]).
-include("ejabberd.hrl").
-include("jlib.hrl").
start(Host, Opts) ->
MyHost = gen_mod:get_opt(host, Opts, "echo." ++ Host),
register(gen_mod:get_module_proc(Host, ?PROCNAME),
spawn(?MODULE, init, [MyHost])).
init(Host) ->
ejabberd_router:register_local_route(Host),
loop(Host).
loop(Host) ->
receive
{route, From, To, Packet} ->
ejabberd_router:route(To, From, Packet),
loop(Host);
stop ->
ejabberd_router:unregister_route(Host),
ok;
_ ->
loop(Host)
end.
stop(Host) ->
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
Proc ! stop,
{wait, Proc}.
\end{verbatim}
\end{document}
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

-143
View File
@@ -1,143 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<meta name="generator" content="hevea 2.09">
<style type="text/css">
.li-itemize{margin:1ex 0ex;}
.li-enumerate{margin:1ex 0ex;}
.dd-description{margin:0ex 0ex 1ex 4ex;}
.dt-description{margin:0ex;}
.toc{list-style:none;}
.footnotetext{margin:0ex; padding:0ex;}
div.footnotetext P{margin:0px; text-indent:1em;}
.thefootnotes{text-align:left;margin:0ex;}
.dt-thefootnotes{margin:0em;}
.dd-thefootnotes{margin:0em 0em 0em 2em;}
.footnoterule{margin:1em auto 1em 0px;width:50%;}
.caption{padding-left:2ex; padding-right:2ex; margin-left:auto; margin-right:auto}
.title{margin:2ex auto;text-align:center}
.titlemain{margin:1ex 2ex 2ex 1ex;}
.titlerest{margin:0ex 2ex;}
.center{text-align:center;margin-left:auto;margin-right:auto;}
.flushleft{text-align:left;margin-left:0ex;margin-right:auto;}
.flushright{text-align:right;margin-left:auto;margin-right:0ex;}
div table{margin-left:inherit;margin-right:inherit;margin-bottom:2px;margin-top:2px}
td table{margin:auto;}
table{border-collapse:collapse;}
td{padding:0;}
.cellpadding0 tr td{padding:0;}
.cellpadding1 tr td{padding:1px;}
pre{text-align:left;margin-left:0ex;margin-right:auto;}
blockquote{margin-left:4ex;margin-right:4ex;text-align:left;}
td p{margin:0px;}
.boxed{border:1px solid black}
.textboxed{border:1px solid black}
.vbar{border:none;width:2px;background-color:black;}
.hbar{border:none;height:2px;width:100%;background-color:black;}
.hfill{border:none;height:1px;width:200%;background-color:black;}
.vdisplay{border-collapse:separate;border-spacing:2px;width:auto; empty-cells:show; border:2px solid red;}
.vdcell{white-space:nowrap;padding:0px; border:2px solid green;}
.display{border-collapse:separate;border-spacing:2px;width:auto; border:none;}
.dcell{white-space:nowrap;padding:0px; border:none;}
.dcenter{margin:0ex auto;}
.vdcenter{border:solid #FF8000 2px; margin:0ex auto;}
.minipage{text-align:left; margin-left:0em; margin-right:auto;}
.marginpar{border:solid thin black; width:20%; text-align:left;}
.marginparleft{float:left; margin-left:0ex; margin-right:1ex;}
.marginparright{float:right; margin-left:1ex; margin-right:0ex;}
.theorem{text-align:left;margin:1ex auto 1ex 0ex;}
.part{margin:2ex auto;text-align:center}
SPAN{width:20%; float:right; text-align:left; margin-left:auto;}
</style>
<title>Ejabberd community 14.05-120-gedfb5fc Feature Sheet
</title>
</head>
<body >
<!--HEVEA command line is: /usr/bin/hevea -fix -pedantic features.tex -->
<!--CUT STYLE article--><!--CUT DEF section 1 --><p><a id="titlepage"></a>
</p><table class="title"><tr><td style="padding:1ex"><h1 class="titlemain">Ejabberd community 14.05-120-gedfb5fc Feature Sheet</h1><h3 class="titlerest">Sander Devrieze <br>
<a href="mailto:s.devrieze@pandora.be"><span style="font-family:monospace">mailto:s.devrieze@pandora.be</span></a> <br>
<a href="xmpp:sander@devrieze.dyndns.org"><span style="font-family:monospace">xmpp:sander@devrieze.dyndns.org</span></a></h3></td></tr>
</table><div class="center">
<img src="logo.png" alt="logo.png">
</div><blockquote class="quotation"><span style="color:#921700"><span style="font-style:italic">I can thoroughly recommend ejabberd for ease of setup &#X2013;
Kevin Smith, Current maintainer of the Psi project</span></span></blockquote><p>Introduction
<a id="intro"></a></p><blockquote class="quotation"><span style="color:#921700"><span style="font-style:italic">I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. &#X2014;
Joeri</span></span></blockquote><p><span style="font-family:monospace">ejabberd</span> is a <span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">free and open source</span></span></span> instant messaging server written in <a href="http://www.erlang.org/">Erlang/OTP</a>.</p><p><span style="font-family:monospace">ejabberd</span> is <span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">cross-platform</span></span></span>, distributed, fault-tolerant, and based on open standards to achieve real-time communication.</p><p><span style="font-family:monospace">ejabberd</span> is designed to be a <span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">rock-solid and feature rich</span></span></span> XMPP server.</p><p><span style="font-family:monospace">ejabberd</span> is suitable for small deployments, whether they need to be <span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">scalable</span></span></span> or not, as well as extremely big deployments.</p>
<!--TOC section id="sec1" Key Features-->
<h2 id="sec1" class="section">Key Features</h2><!--SEC END --><p>
<a id="keyfeatures"></a>
</p><blockquote class="quotation"><span style="color:#921700"><span style="font-style:italic">Erlang seems to be tailor-made for writing stable, robust servers. &#X2014;
Peter Saint-Andr&#XE9;, Executive Director of the Jabber Software Foundation</span></span></blockquote><p><span style="font-family:monospace">ejabberd</span> is:
</p><ul class="itemize"><li class="li-itemize">
<span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Cross-platform:</span></span></span> <span style="font-family:monospace">ejabberd</span> runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.</li><li class="li-itemize"><span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Distributed:</span></span></span> You can run <span style="font-family:monospace">ejabberd</span> on a cluster of machines and all of them will serve the same Jabber domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.</li><li class="li-itemize"><span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Fault-tolerant:</span></span></span> You can deploy an <span style="font-family:monospace">ejabberd</span> cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced &#X2018;on the fly&#X2019;.</li><li class="li-itemize"><span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Administrator Friendly:</span></span></span> <span style="font-family:monospace">ejabberd</span> is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
<ul class="itemize"><li class="li-itemize">
Comprehensive documentation.
</li><li class="li-itemize">Straightforward installers for Linux, Mac OS X, and Windows. </li><li class="li-itemize">Web Administration.
</li><li class="li-itemize">Shared Roster Groups.
</li><li class="li-itemize">Command line administration tool. </li><li class="li-itemize">Can integrate with existing authentication mechanisms.
</li><li class="li-itemize">Capability to send announce messages.
</li></ul></li><li class="li-itemize"><span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Internationalized:</span></span></span> <span style="font-family:monospace">ejabberd</span> leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
<ul class="itemize"><li class="li-itemize">
Translated to 25 languages. </li><li class="li-itemize">Support for <a href="http://www.ietf.org/rfc/rfc3490.txt">IDNA</a>.
</li></ul></li><li class="li-itemize"><span style="font-weight:bold"><span style="font-size:large"><span style="color:#001376">Open Standards:</span></span></span> <span style="font-family:monospace">ejabberd</span> is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
<ul class="itemize"><li class="li-itemize">
Fully XMPP compliant.
</li><li class="li-itemize">XML-based protocol.
</li><li class="li-itemize"><a href="http://www.ejabberd.im/protocols">Many protocols supported</a>.
</li></ul></li></ul>
<!--TOC section id="sec2" Additional Features-->
<h2 id="sec2" class="section">Additional Features</h2><!--SEC END --><p>
<a id="addfeatures"></a>
</p><blockquote class="quotation"><span style="color:#921700"><span style="font-style:italic">ejabberd is making inroads to solving the "buggy incomplete server" problem &#X2014;
Justin Karneges, Founder of the Psi and the Delta projects</span></span></blockquote><p>Moreover, <span style="font-family:monospace">ejabberd</span> comes with a wide range of other state-of-the-art features:
</p><ul class="itemize"><li class="li-itemize">
Modular
<ul class="itemize"><li class="li-itemize">
Load only the modules you want.
</li><li class="li-itemize">Extend <span style="font-family:monospace">ejabberd</span> with your own custom modules.
</li></ul>
</li><li class="li-itemize">Security
<ul class="itemize"><li class="li-itemize">
SASL and STARTTLS for c2s and s2s connections.
</li><li class="li-itemize">STARTTLS and Dialback s2s connections.
</li><li class="li-itemize">Web Admin accessible via HTTPS secure access.
</li></ul>
</li><li class="li-itemize">Databases
<ul class="itemize"><li class="li-itemize">
Internal database for fast deployment (Mnesia).
</li><li class="li-itemize">Native MySQL support.
</li><li class="li-itemize">Native PostgreSQL support.
</li><li class="li-itemize">ODBC data storage support.
</li><li class="li-itemize">Microsoft SQL Server support. </li><li class="li-itemize">Riak NoSQL database support.
</li></ul>
</li><li class="li-itemize">Authentication
<ul class="itemize"><li class="li-itemize">
Internal Authentication.
</li><li class="li-itemize">PAM, LDAP, ODBC and Riak. </li><li class="li-itemize">External Authentication script.
</li></ul>
</li><li class="li-itemize">Others
<ul class="itemize"><li class="li-itemize">
Support for virtual hosting.
</li><li class="li-itemize">Compressing XML streams with Stream Compression (<a href="http://www.xmpp.org/extensions/xep-0138.html">XEP-0138</a>).
</li><li class="li-itemize">Statistics via Statistics Gathering (<a href="http://www.xmpp.org/extensions/xep-0039.html">XEP-0039</a>).
</li><li class="li-itemize">IPv6 support both for c2s and s2s connections.
</li><li class="li-itemize"><a href="http://www.xmpp.org/extensions/xep-0045.html">Multi-User Chat</a> module with support for clustering and HTML logging. </li><li class="li-itemize">Users Directory based on users vCards.
</li><li class="li-itemize"><a href="http://www.xmpp.org/extensions/xep-0060.html">Publish-Subscribe</a> component with support for <a href="http://www.xmpp.org/extensions/xep-0163.html">Personal Eventing via Pubsub</a>.
</li><li class="li-itemize">Support for web clients: <a href="http://www.xmpp.org/extensions/xep-0025.html">HTTP Polling</a> and <a href="http://www.xmpp.org/extensions/xep-0206.html">HTTP Binding (BOSH)</a> services.
</li><li class="li-itemize">IRC transport.
</li><li class="li-itemize">SIP support.
</li><li class="li-itemize">Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
</li></ul>
</li></ul><!--CUT END -->
<!--HTMLFOOT-->
<!--ENDHTML-->
<!--FOOTER-->
<hr style="height:2"><blockquote class="quote"><em>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
</em><a href="http://hevea.inria.fr/index.html"><em>H</em><em><span style="font-size:small"><sup>E</sup></span></em><em>V</em><em><span style="font-size:small"><sup>E</sup></span></em><em>A</em></a><em>.</em></blockquote></body>
</html>
-136
View File
@@ -1,136 +0,0 @@
\documentclass[a4paper,10pt]{article}
%% Packages
\usepackage{epsfig}
\usepackage{fancyhdr}
\usepackage{graphics}
\usepackage{hevea}
\usepackage[pdftex,colorlinks,unicode,urlcolor=blue,linkcolor=blue,pdftitle=Ejabberd\
Feature\ Sheet,pdfauthor=Sander\
Devrieze,pdfsubject=ejabberd,pdfkeywords=ejabberd]{hyperref}
\usepackage{verbatim}
\usepackage{color}
%% Index
% Remove the index anchors from the HTML version to save size and bandwith.
\newcommand{\ind}[1]{\begin{latexonly}\index{#1}\end{latexonly}}
%% Images
\newcommand{\logoscale}{0.7}
\newcommand{\imgscale}{0.58}
\newcommand{\insimg}[1]{\insscaleimg{\imgscale}{#1}}
\newcommand{\insscaleimg}[2]{
\imgsrc{#2}{}
\begin{latexonly}
\scalebox{#1}{\includegraphics{#2}}
\end{latexonly}
}
%% Various
\newcommand{\bracehack}{\def\{{\char"7B}\def\}{\char"7D}}
\newcommand{\titem}[1]{\item[\bracehack\texttt{#1}]}
\newcommand{\ns}[1]{\texttt{#1}}
\newcommand{\jid}[1]{\texttt{#1}}
\newcommand{\option}[1]{\texttt{#1}}
\newcommand{\poption}[1]{{\bracehack\texttt{#1}}}
\newcommand{\node}[1]{\texttt{#1}}
\newcommand{\term}[1]{\texttt{#1}}
\newcommand{\shell}[1]{\texttt{#1}}
\newcommand{\ejabberd}{\texttt{ejabberd}}
\newcommand{\Jabber}{Jabber}
%% Title page
\include{version}
\title{Ejabberd \version\ Feature Sheet}
\author{Sander Devrieze \\
\ahrefurl{mailto:s.devrieze@pandora.be} \\
\ahrefurl{xmpp:sander@devrieze.dyndns.org}}
% Options
\newcommand{\marking}[1]{\textbf{\begin{large}\textcolor{ejblue}{#1}\end{large}}} % Marking enabled
\newcommand{\quoting}[2][yozhik]{\begin{quotation}\textcolor{#1}{\textit{#2}}\end{quotation}} % Quotes enabled
\newcommand{\new}{\marginpar{\textcolor{red}{\textsc{new}}}} % Highlight new features
\newcommand{\improved}{\marginpar{\textcolor{orange}{\textsc{improved}}}} % Highlight improved features
\setcounter{secnumdepth}{-1} % Disable section numbering
%% To by-pass errors in the HTML version.
\newstyle{SPAN}{width:20\%; float:right; text-align:left; margin-left:auto;}
\definecolor{orange} {cmyk}{0.000,0.333,1.000,0.000}
%% Footnotes
\begin{latexonly}
\global\parskip=9pt plus 3pt minus 1pt
\global\parindent=0pt
\gdef\ahrefurl#1{\href{#1}{\texttt{#1}}}
\gdef\footahref#1#2{#2\footnote{\href{#1}{\texttt{#1}}}}
\end{latexonly}
\newcommand{\txepref}[2]{\footahref{http://www.xmpp.org/extensions/xep-#1.html}{#2}}
\newcommand{\xepref}[1]{\txepref{#1}{XEP-#1}}
%% Fancy header
\fancyhf{}
\pagestyle{fancy}
\rhead{\textcolor{ejblue}{The Expandable Jabber/XMPP Daemon.}}
\renewcommand{\headrule}{{\color{ejblue}%
\hrule width\headwidth height\headrulewidth \vskip-\headrulewidth}}
\lhead{\setlength{\unitlength}{-6mm}
\begin{picture}(0,0)
\put(5.8,3.25){\includegraphics[width=1.3\textwidth]{yozhikheader.png}}
\end{picture}}
% Official ejabberd colours
\definecolor{ejblue} {cmyk}{1.000,0.831,0.000,0.537} %RGB: 0,0,118 HTML: 000076
\definecolor{ejgreenyellow}{cmyk}{0.079,0.000,0.275,0.102} %RGB: 209,229,159 HTML: d1e59f
\definecolor{ejgreendark} {cmyk}{0.131,0.000,0.146,0.220} %RGB: 166,199,162 HTML: a6c7a2
\definecolor{ejgreen} {cmyk}{0.077,0.000,0.081,0.078} %RGB: 216,236,215 HTML: d8ecd7
\definecolor{ejgreenwhite} {cmyk}{0.044,0.000,0.048,0.020} %RGB: 239,250,238 HTML: effaee
\definecolor{yozhik} {cmyk}{0.000,0.837,1.000,0.424} %RGB: 147,0,0 HTML: 930000
\begin{document}
\label{titlepage}
\begin{titlepage}
\maketitle{}
\thispagestyle{empty}
\begin{center}
{\insscaleimg{\logoscale}{logo.png}
\par
}
\end{center}
\quoting{I can thoroughly recommend ejabberd for ease of setup --
Kevin Smith, Current maintainer of the Psi project}
\end{titlepage}
\newpage
% Set the page counter to 2 so that the titlepage and the second page do not
% have the same page number. This fixes the PDFLaTeX warning "destination with
% the same identifier".
\begin{latexonly}
\setcounter{page}{2}
\pagecolor{ejgreenwhite}
\end{latexonly}
% Input introduction.tex
\input{introduction}
\end{document}
%% TODO
% * illustrations (e.g. screenshot from web interface)
% * commented parts
% * slides, guide and html version
% * cleaning and improving LaTeX code
% * key features: something like this (shorter)? (more focussed on Erlang now): "To reach the goal of high
% availability, performance and clustering, ejabberd is written in Erlang, a programming language perfectly
% suited for this. Besides that, some parts are written in C to also incude the advantages of this language. In
% short, ejabberd is a perfect mix of mainly Erlang code, peppered with some C code to get the final touch!"
% <picture of a cocktail>
% * key features: saying that ejabberd the only XMPP server is that can do real clustering:
% http://www.jivesoftware.org/forums/thread.jspa?threadID=14602
% "What I find interesting is that *no* XMPP servers truly provide clustering. This includes all the commercial
% servers. The one partial exception appears to be ejabberd, which can cluster certain data such as sessions,
% but not all services such as MUC."
% * try it today: links to migration tutorials
-105
View File
@@ -1,105 +0,0 @@
digraph messages {
//concentrate=true;
subgraph clusterclients {
client1 [shape = box];
client2 [shape = box];
client3 [shape = box];
style = dashed;
label = "Clients";
}
subgraph clusternode1 {
subgraph clusterc2s1 {
c2s11;
c2s12;
style = invis;
}
subgraph clusterservices1 {
service11;
service12;
service13;
style = invis;
}
//subgraph clusters2s1 {
//s2s11;
//s2s12;
//style = invis;
//}
c2s11 -> auth1;
c2s12 -> auth1;
auth1 -> c2s11;
auth1 -> c2s12;
c2s11 -> sm1;
c2s11 -> router1;
c2s12 -> sm1;
c2s12 -> router1;
router1 -> local1;
router1 -> service11;
router1 -> service12;
router1 -> service13;
router1 -> s2s11;
router1 -> s2s12;
service11 -> router1;
service12 -> router1;
service13 -> router1;
s2s11 -> router1;
s2s12 -> router1;
local1 -> sm1;
sm1 -> c2s11;
sm1 -> c2s12;
style = dashed;
label = "Node1";
}
subgraph clusternode2 {
c2s2 -> auth2;
auth2 -> c2s2;
c2s2 -> sm2;
c2s2 -> router2;
router2 -> local2;
router2 -> service21;
router2 -> s2s21;
service21 -> router2;
s2s21 -> router2;
local2 -> sm2;
sm2 -> c2s2;
style = dashed;
label = "Node2";
}
subgraph clusterservers {
server1 [shape = box];
server2 [shape = box];
server3 [shape = box];
style = dashed;
label = "Servers";
}
client1 -> c2s11;
client2 -> c2s12;
client3 -> c2s2;
c2s11 -> client1 [constraint=false];
c2s12 -> client2 [constraint=false];
c2s2 -> client3 [constraint=false];
s2s11 -> server1 [minlen = 2];
s2s12 -> server2 [minlen = 2];
s2s21 -> server3 [minlen = 2];
server1 -> s2s11 [constraint=false];
server2 -> s2s12 [constraint=false];
server3 -> s2s21 [constraint=false];
router1 -> router2;
router2 -> router1;
sm1 -> sm2;
sm2 -> sm1;
label = "Data Flows";
}
-6494
View File
File diff suppressed because it is too large Load Diff
-135
View File
@@ -1,135 +0,0 @@
\chapter{Introduction}
\label{intro}
%% TODO: improve the feature sheet with a nice table to highlight new features.
\quoting{I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. ---
Joeri}
%ejabberd is a free and open source instant messaging server written in Erlang. ejabberd is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication (Jabber/XMPP).
\ejabberd{} is a \marking{free and open source} instant messaging server written in \footahref{http://www.erlang.org/}{Erlang/OTP}.
\ejabberd{} is \marking{cross-platform}, distributed, fault-tolerant, and based on open standards to achieve real-time communication.
\ejabberd{} is designed to be a \marking{rock-solid and feature rich} XMPP server.
\ejabberd{} is suitable for small deployments, whether they need to be \marking{scalable} or not, as well as extremely big deployments.
%\subsection{Layout with example deployment (title needs a better name)}
%\label{layout}
%In this section there will be a graphical overview like these:\\
%\verb|http://www.tipic.com/var/timp/timp_dep.gif| \\
%\verb|http://www.jabber.com/images/jabber_Com_Platform.jpg| \\
%\verb|http://www.antepo.com/files/OPN45systemdatasheet.pdf| \\
%A page full with names of Jabber client that are known to work with ejabberd. \begin{tiny}tiny font\end{tiny}
%\subsection{Try It Today}
%\label{trytoday}
%(Not sure if I will include/finish this section for the next version.)
%\begin{itemize}
%\item Erlang REPOS
%\item Packages in distributions
%\item Windows binary
%\item source tar.gz
%\item Migration from Jabberd14 (and so also Jabberd2 because you can migrate from version 2 back to 14) and Jabber Inc. XCP possible.
%\end{itemize}
\newpage
\section{Key Features}
\label{keyfeatures}
\ind{features!key features}
\quoting{Erlang seems to be tailor-made for writing stable, robust servers. ---
Peter Saint-Andr\'e, Executive Director of the Jabber Software Foundation}
\ejabberd{} is:
\begin{itemize}
\item \marking{Cross-platform:} \ejabberd{} runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.
\item \marking{Distributed:} You can run \ejabberd{} on a cluster of machines and all of them will serve the same \Jabber{} domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.
\item \marking{Fault-tolerant:} You can deploy an \ejabberd{} cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced `on the fly'.
\item \marking{Administrator Friendly:} \ejabberd{} is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
\begin{itemize}
\item Comprehensive documentation.
\item Straightforward installers for Linux, Mac OS X, and Windows. %%\improved{}
\item Web Administration.
\item Shared Roster Groups.
\item Command line administration tool. %%\improved{}
\item Can integrate with existing authentication mechanisms.
\item Capability to send announce messages.
\end{itemize}
\item \marking{Internationalized:} \ejabberd{} leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
\begin{itemize}
\item Translated to 25 languages. %%\improved{}
\item Support for \footahref{http://tools.ietf.org/html/rfc3490}{IDNA}.
\end{itemize}
\item \marking{Open Standards:} \ejabberd{} is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
\begin{itemize}
\item Fully XMPP compliant.
\item XML-based protocol.
\item \footahref{http://www.ejabberd.im/protocols}{Many protocols supported}.
\end{itemize}
\end{itemize}
\newpage
\section{Additional Features}
\label{addfeatures}
\ind{features!additional features}
\quoting{ejabberd is making inroads to solving the "buggy incomplete server" problem ---
Justin Karneges, Founder of the Psi and the Delta projects}
Moreover, \ejabberd{} comes with a wide range of other state-of-the-art features:
\begin{itemize}
\item Modular
\begin{itemize}
\item Load only the modules you want.
\item Extend \ejabberd{} with your own custom modules.
\end{itemize}
\item Security
\begin{itemize}
\item SASL and STARTTLS for c2s and s2s connections.
\item STARTTLS and Dialback s2s connections.
\item Web Admin accessible via HTTPS secure access.
\end{itemize}
\item Databases
\begin{itemize}
\item Internal database for fast deployment (Mnesia).
\item Native MySQL support.
\item Native PostgreSQL support.
\item ODBC data storage support.
\item Microsoft SQL Server support. %%\new{}
\item Riak NoSQL database support.
\end{itemize}
\item Authentication
\begin{itemize}
\item Internal Authentication.
\item PAM, LDAP, ODBC and Riak. %%\improved{}
\item External Authentication script.
\end{itemize}
\item Others
\begin{itemize}
\item Support for virtual hosting.
\item Compressing XML streams with Stream Compression (\xepref{0138}).
\item Statistics via Statistics Gathering (\xepref{0039}).
\item IPv6 support both for c2s and s2s connections.
\item \txepref{0045}{Multi-User Chat} module with support for clustering and HTML logging. %%\improved{}
\item Users Directory based on users vCards.
\item \txepref{0060}{Publish-Subscribe} component with support for \txepref{0163}{Personal Eventing via Pubsub}.
\item Support for web clients: \txepref{0025}{HTTP Polling} and \txepref{0206}{HTTP Binding (BOSH)} services.
\item IRC transport.
\item SIP support.
\item Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
\end{itemize}
\end{itemize}
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

+36 -22
View File
@@ -1,5 +1,5 @@
###
### ejabberd configuration file
###' ejabberd configuration file
###
###
@@ -24,8 +24,8 @@
### > Art thou not Romeo,
### and a Montague?
### =======
### LOGGING
###. =======
###' LOGGING
##
## loglevel: Verbosity of log files generated by ejabberd.
@@ -72,9 +72,18 @@ log_rate_limit: 100
## watchdog_admins:
## - "bob@example.com"
###. ===============
###' NODE PARAMETERS
### ================
### SERVED HOSTNAMES
##
## net_ticktime: Specifies net_kernel tick time in seconds. This options must have
## identical value on all nodes, and in most cases shouldn't be changed at all from
## default value.
##
## net_ticktime: 60
###. ================
###' SERVED HOSTNAMES
##
## hosts: Domains served by ejabberd.
@@ -94,8 +103,8 @@ hosts:
##
## route_subdomains: s2s
### ===============
### LISTENING PORTS
###. ===============
###' LISTENING PORTS
##
## listen: The ports ejabberd will listen on, which service each is handled
@@ -169,6 +178,9 @@ listen:
## register: true
captcha: true
###. ==================
###' S2S GLOBAL OPTIONS
##
## s2s_use_starttls: Enable STARTTLS + Dialback for S2S connections.
## Allowed values are: false optional required required_trusted
@@ -214,8 +226,8 @@ listen:
## - ipv6
## outgoing_s2s_timeout: 10000
### ==============
### AUTHENTICATION
###. ==============
###' AUTHENTICATION
##
## auth_method: Method used to authenticate the users.
@@ -305,8 +317,8 @@ auth_method: internal
## - internal
## - anonymous
### ==============
### DATABASE SETUP
###. ==============
###' DATABASE SETUP
## ejabberd by default uses the internal Mnesia database,
## so you do not necessarily need this section.
@@ -366,8 +378,8 @@ auth_method: internal
##
## odbc_keepalive_interval: undefined
### ===============
### TRAFFIC SHAPERS
###. ===============
###' TRAFFIC SHAPERS
shaper:
##
@@ -448,8 +460,8 @@ acl:
## user:
## - "bob-local": "localhost"
### ============
### ACCESS RULES
###. ============
###' ACCESS RULES
access:
## Maximum number of simultaneous sessions allowed for a single user:
max_user_sessions:
@@ -518,8 +530,8 @@ access:
## register:
## all: deny
### ================
### DEFAULT LANGUAGE
###. ================
###' DEFAULT LANGUAGE
##
## language: Default language used for server messages.
@@ -533,8 +545,8 @@ language: "en"
## "localhost":
## language: "ru"
### =======
### CAPTCHA
###. =======
###' CAPTCHA
##
## Full path to a script that generates the image.
@@ -551,8 +563,8 @@ language: "en"
##
## captcha_limit: 5
### =======
### MODULES
###. =======
###' MODULES
##
## Modules enabled in all ejabberd virtual hosts.
@@ -668,7 +680,9 @@ modules:
allow_contrib_modules: true
###.
###'
### Local Variables:
### mode: yaml
### End:
### vim: set filetype=yaml tabstop=8
### vim: set filetype=yaml tabstop=8 foldmarker=###',###. foldmethod=marker:
+30 -19
View File
@@ -16,9 +16,6 @@ IEX={{bindir}}/iex
EPMD={{bindir}}/epmd
INSTALLUSER={{installuser}}
# Compatibility in ZSH
#setopt shwordsplit 2>/dev/null
# check the proper system user is used if defined
if [ "$INSTALLUSER" != "" ] ; then
EXEC_CMD="false"
@@ -112,6 +109,8 @@ DATETIME=`date "+%Y%m%d-%H%M%S"`
ERL_CRASH_DUMP=$LOGS_DIR/erl_crash_$DATETIME.dump
ERL_INETRC=$ETC_DIR/inetrc
# define mnesia options
MNESIA_OPTS="-mnesia dir \"\\\"$SPOOL_DIR\\\"\" $MNESIA_OPTIONS"
# define erl parameters
ERL_OPTIONS=$(echo $ERL_OPTIONS | sed 's/ /\\ /g')
ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS"
@@ -177,7 +176,7 @@ start()
$NAME $ERLANG_NODE \
-noinput -detached \
-pa $EJABBERD_EBIN_PATH \
-mnesia dir \"\\\"$SPOOL_DIR\\\"\" \
$MNESIA_OPTS \
$KERNEL_OPTS \
$EJABBERD_OPTS \
-s ejabberd \
@@ -218,7 +217,7 @@ live()
$EXEC_CMD "$ERL \
$NAME $ERLANG_NODE \
-pa $EJABBERD_EBIN_PATH \
-mnesia dir \"\\\"$SPOOL_DIR\\\"\" \
$MNESIA_OPTS \
$KERNEL_OPTS \
$EJABBERD_OPTS \
-s ejabberd \
@@ -239,14 +238,6 @@ iexlive()
--erl \"$ERLANG_OPTS\" --erl $ARGS --erl \"$@\""
}
etop()
{
$EXEC_CMD "$ERL \
$NAME debug-${TTY}-${ERLANG_NODE} \
-hidden -s etop -s erlang halt -output text -node $ERLANG_NODE"
}
# TODO: refactor debug warning and livewarning
debugwarning()
{
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
@@ -268,7 +259,7 @@ debugwarning()
echo "Press return to continue"
read foo
echo ""
fi
fi
}
livewarning()
@@ -295,7 +286,26 @@ livewarning()
fi
}
# TODO: Make iex command display only if ejabberd Elixir support has been enabled
etop()
{
TTY=`tty | sed -e 's/.*\///g'`
$EXEC_CMD "$ERL \
$NAME debug-${TTY}-${ERLANG_NODE} \
-hidden -s etop -s erlang halt -output text -node $ERLANG_NODE"
}
ping()
{
TTY=`tty | sed -e 's/.*\///g'`
$EXEC_CMD "$ERL \
$NAME ping-${TTY}-${ERLANG_NODE} \
-hidden \
-pa $EJABBERD_EBIN_PATH \
$KERNEL_OPTS $ERLANG_OPTS \
-eval 'io:format(\"~p~n\",[net_adm:ping($1)])' \
-s erlang halt -output text -noinput"
}
help()
{
echo ""
@@ -326,9 +336,9 @@ ctl()
# flock that can lock a file descriptor.
MAXCONNID=100
CONNLOCKDIR={{localstatedir}}/lock/ejabberdctl
FLOCK='/usr/bin/flock'
FLOCK=/usr/bin/flock
if [ ! -x "$FLOCK" ] || [ ! -d "$CONNLOCKDIR" ] ; then
JOT='/usr/bin/jot'
JOT=/usr/bin/jot
if [ ! -x "$JOT" ] ; then
# no flock or jot, simply invoke ctlexec()
CTL_CONN="ctl-${ERLANG_NODE}"
@@ -395,7 +405,7 @@ ctl()
ctlexec()
{
CONN_NAME=$1; shift
COMMAND=$@
COMMAND=$(echo $@ | sed 's/;/\\;/g')
$EXEC_CMD "$ERL \
$NAME ${CONN_NAME} \
-noinput \
@@ -408,7 +418,7 @@ ctlexec()
# stop epmd if there is no other running node
stop_epmd()
{
$EPMD -names 2>/dev/null | grep -q name || epmd -kill >/dev/null
$EPMD -names 2>/dev/null | grep -q name || $EPMD -kill >/dev/null
}
# make sure node not already running and node name unregistered
@@ -468,6 +478,7 @@ case $ARGS in
' iexdebug') iexdebug;;
' live') live;;
' iexlive') iexlive;;
' ping'*) ping ${ARGS# ping};;
' etop') etop;;
' started') wait_for_status 0 30 2;; # wait 30x2s before timeout
' stopped') wait_for_status 3 15 2 && stop_epmd;; # wait 15x2s before timeout
+5
View File
@@ -1,3 +1,6 @@
-ifndef(EJABBERD_SM_HRL).
-define(EJABBERD_SM_HRL, true).
-record(session, {sid, usr, us, priority, info}).
-record(session_counter, {vhost, count}).
-type sid() :: {erlang:timestamp(), pid()}.
@@ -5,3 +8,5 @@
-type info() :: [{conn, atom()} | {ip, ip()} | {node, atom()}
| {oor, boolean()} | {auth_module, atom()}].
-type prio() :: undefined | integer().
-endif.
+2 -2
View File
@@ -110,8 +110,8 @@
-record(muc_online_users, {us = {<<>>, <<>>} :: {binary(), binary()},
resource = <<>> :: binary() | '_',
room = <<>> :: binary() | '_',
host = <<>> :: binary() | '_'}).
room = <<>> :: binary() | '_' | '$1',
host = <<>> :: binary() | '_' | '$2'}).
-type muc_online_users() :: #muc_online_users{}.
+2 -2
View File
@@ -35,12 +35,10 @@
-define(NS_BLOCKING, <<"urn:xmpp:blocking">>).
-define(NS_PRIVATE, <<"jabber:iq:private">>).
-define(NS_VERSION, <<"jabber:iq:version">>).
-define(NS_TIME90, <<"jabber:iq:time">>).
-define(NS_TIME, <<"urn:xmpp:time">>).
-define(NS_LAST, <<"jabber:iq:last">>).
-define(NS_XDATA, <<"jabber:x:data">>).
-define(NS_IQDATA, <<"jabber:iq:data">>).
-define(NS_DELAY91, <<"jabber:x:delay">>).
-define(NS_DELAY, <<"urn:xmpp:delay">>).
-define(NS_HINTS, <<"urn:xmpp:hints">>).
-define(NS_EXPIRE, <<"jabber:x:expire">>).
@@ -143,6 +141,8 @@
-define(NS_CAPTCHA, <<"urn:xmpp:captcha">>).
-define(NS_MEDIA, <<"urn:xmpp:media-element">>).
-define(NS_BOB, <<"urn:xmpp:bob">>).
-define(NS_MAM_TMP, <<"urn:xmpp:mam:tmp">>).
-define(NS_MAM_0, <<"urn:xmpp:mam:0">>).
-define(NS_PING, <<"urn:xmpp:ping">>).
-define(NS_CARBONS_2, <<"urn:xmpp:carbons:2">>).
-define(NS_CARBONS_1, <<"urn:xmpp:carbons:1">>).
+17 -17
View File
@@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do
def project do
[app: :ejabberd,
version: "15.03.0",
version: "15.06.0",
elixir: "~> 1.0",
elixirc_paths: ["lib"],
compile_path: ".",
@@ -25,21 +25,21 @@ defmodule Ejabberd.Mixfile do
defp deps do
[
{:p1_xml, github: "processone/xml"},
{:p1_logger, github: "processone/p1_logger"},
{:p1_yaml, github: "processone/p1_yaml"},
{:p1_tls, github: "processone/tls"},
{:p1_stringprep, github: "processone/stringprep"},
{:p1_zlib, github: "processone/zlib"},
{:p1_cache_tab, github: "processone/cache_tab"},
{:p1_utils, github: "processone/p1_utils"},
{:p1_iconv, github: "processone/eiconv"},
{:esip, github: "processone/p1_sip"},
{:p1_stun, github: "processone/stun"},
{:ehyperloglog, github: "vaxelfel/eHyperLogLog"},
{:p1_mysql, github: "processone/mysql"},
{:p1_pgsql, github: "processone/pgsql"},
{:eredis, github: "wooga/eredis"}
{:p1_xml, git: "https://github.com/processone/xml"},
{:p1_logger, git: "https://github.com/processone/p1_logger"},
{:p1_yaml, git: "https://github.com/processone/p1_yaml"},
{:p1_tls, git: "https://github.com/processone/tls"},
{:p1_stringprep, git: "https://github.com/processone/stringprep"},
{:p1_zlib, git: "https://github.com/processone/zlib"},
{:p1_cache_tab, git: "https://github.com/processone/cache_tab"},
{:p1_utils, git: "https://github.com/processone/p1_utils"},
{:p1_iconv, git: "https://github.com/processone/eiconv"},
{:esip, git: "https://github.com/processone/p1_sip"},
{:p1_stun, git: "https://github.com/processone/stun"},
{:ehyperloglog, git: "https://github.com/vaxelfel/eHyperLogLog"},
{:p1_mysql, git: "https://github.com/processone/mysql"},
{:p1_pgsql, git: "https://github.com/processone/pgsql"},
{:eredis, git: "https://github.com/wooga/eredis"}
]
end
end
@@ -65,7 +65,7 @@ defmodule Mix.Tasks.Compile.Asn1 do
options = options ++ [:noobj, outdir: Erlang.to_erl_file(Path.dirname(output))]
case :asn1ct.compile(Erlang.to_erl_file(input), options) do
:ok -> {:ok, :done}
error -> error
error -> error
end
end)
end
+7 -2
View File
@@ -60,7 +60,6 @@
{"Database Tables Configuration at ","Configuración de tablas de la base de datos en "}.
{"December","diciembre"}.
{"Default users as participants","Los usuarios son participantes por defecto"}.
{"Delete","Eliminar"}.
{"Delete message of the day","Borrar mensaje del dia"}.
{"Delete message of the day on all hosts","Borrar el mensaje del día en todos los dominios"}.
{"Delete Selected","Eliminar los seleccionados"}.
@@ -77,6 +76,7 @@
{"Either approve or decline the voice request.","Aprueba o rechaza la petición de voz."}.
{"ejabberd IRC module","Módulo de IRC para ejabberd"}.
{"ejabberd MUC module","Módulo de MUC para ejabberd"}.
{"ejabberd Multicast service","Servicio Multicast de ejabberd"}.
{"ejabberd Publish-Subscribe module","Módulo de Publicar-Subscribir de ejabberd"}.
{"ejabberd SOCKS5 Bytestreams module","Módulo SOCKS5 Bytestreams para ejabberd"}.
{"ejabberd vCard module","Módulo vCard para ejabberd"}.
@@ -164,6 +164,7 @@
{"Listened Ports at ","Puertos de escucha en "}.
{"Listened Ports","Puertos de escucha"}.
{"List of modules to start","Lista de módulos a iniciar"}.
{"List of rooms","Lista de salas"}.
{"Low level update script","Script de actualización a bajo nivel"}.
{"Make participants list public","La lista de participantes es pública"}.
{"Make room CAPTCHA protected","Proteger la sala con CAPTCHA"}.
@@ -189,6 +190,8 @@
{"Modules at ~p","Módulos en ~p"}.
{"Modules","Módulos"}.
{"Monday","lunes"}.
{"Multicast","Multicast"}.
{"Multi-User Chat","Salas de Charla"}.
{"Name:","Nombre:"}.
{"Name","Nombre"}.
{"Never","Nunca"}.
@@ -241,6 +244,7 @@
{"Path to File","Ruta al fichero"}.
{"Pending","Pendiente"}.
{"Period: ","Periodo: "}.
{"Permanent rooms","Salas permanentes"}.
{"Persist items to storage","Persistir elementos al almacenar"}.
{"Ping","Ping"}.
{"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Ten en cuenta que estas opciones solo harán copia de seguridad de la base de datos Mnesia embebida. Si estás usando ODBC tendrás que hacer también copia de seguridad de tu base de datos SQL."}.
@@ -258,6 +262,7 @@
{"Raw","Crudo"}.
{"Really delete message of the day?","¿Está seguro de quere borrar el mensaje del dia?"}.
{"Register a Jabber account","Registrar una cuenta Jabber"}.
{"Registered nicknames","Apodos registrados"}.
{"Registered Users:","Usuarios registrados:"}.
{"Registered Users","Usuarios registrados"}.
{"Register","Registrar"}.
@@ -338,7 +343,6 @@
{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","No importa si usas mayúsculas: macbeth es lo mismo que MacBeth y Macbeth."}.
{"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Esta página te permite crear una cuenta Jabber este servidor Jabber. Tu JID (Jabber IDentificador) será de la forma: nombredeusuario@servidor. Por favor lee detenidamente las instrucciones para rellenar correctamente los campos."}.
{"This page allows to unregister a Jabber account in this Jabber server.","Esta página te permite borrar tu cuenta Jabber en este servidor Jabber."}.
{"This room is not anonymous","Sala no anónima"}.
{"Thursday","jueves"}.
{"Time delay","Retraso temporal"}.
{"Time","Fecha"}.
@@ -346,6 +350,7 @@
{"Too many unacked stanzas","Demasiados mensajes sin haber reconocido recibirlos"}.
{"To","Para"}.
{"To ~s","A ~s"}.
{"Total rooms","Salas totales"}.
{"Transactions Aborted:","Transacciones abortadas:"}.
{"Transactions Committed:","Transacciones finalizadas:"}.
{"Transactions Logged:","Transacciones registradas:"}.
+435 -407
View File
File diff suppressed because it is too large Load Diff
+101 -68
View File
@@ -11,9 +11,9 @@
{"Add User","הוסף משתמש"}.
{"Administration of ","ניהול של "}.
{"Administration","הנהלה"}.
{"A friendly name for the node","שם ידידותי עבור הממסר"}.
{"A friendly name for the node","שם ידידותי עבור הצומת"}.
{"All activity","כל פעילות"}.
{"Allow this Jabber ID to subscribe to this pubsub node?","להתיר לכתובת JID זו להירשם אל ממסר PubSub זה?"}.
{"Allow this Jabber ID to subscribe to this pubsub node?","להתיר לכתובת JID זו להירשם לצומת PubSub זה?"}.
{"Allow users to change the subject","התר למשתמשים לשנות את הנושא"}.
{"Allow users to query other users","התר למשתמשים לתשאל משתמשים אחרים"}.
{"Allow users to send invites","התר למשתמשים לשלוח הזמנות"}.
@@ -23,13 +23,14 @@
{"Allow visitors to send status text in presence updates","התר למבקרים לשלוח טקסט מצב בעדכוני נוכחות"}.
{"Allow visitors to send voice requests","התר למבקרים לשלוח בקשות ביטוי"}.
{"All Users","כל המשתמשים"}.
{"Announcements","מודעות"}.
{"Announcements","בשורות"}.
{"anyone","לכל אחד"}.
{"April","אפריל"}.
{"August","אוגוסט"}.
{"Backup Management","ניהול גיבוי"}.
{"Backup to File at ","גבה אל קובץ אצל "}.
{"Backup","גבה"}.
{"Backup of ~p","גיבוי של ~p"}.
{"Backup to File at ","גבה לקובץ אצל "}.
{"Backup","גיבוי"}.
{"Bad format","פורמט רע"}.
{"Birthday","יום הולדת"}.
{"CAPTCHA web page","עמוד רשת CAPTCHA"}.
@@ -37,10 +38,10 @@
{"Change User Password","שנה סיסמת משתמש"}.
{"Characters not allowed:","תווים לא מורשים:"}.
{"Chatroom configuration modified","תצורת חדר שיחה שונתה"}.
{"Chatroom is created","חדר שיחה נוצר"}.
{"Chatroom is destroyed","חדר שיחה הרוס"}.
{"Chatroom is started","חדר שיחה מותחל"}.
{"Chatroom is stopped","חדר שיחה הופסק"}.
{"Chatroom is created","חדר שיחה הינו נוצר"}.
{"Chatroom is destroyed","חדר שיחה הינו הרוס"}.
{"Chatroom is started","חדר שיחה הינו מותחל"}.
{"Chatroom is stopped","חדר שיחה הינו מופסק"}.
{"Chatrooms","חדרי שיחה"}.
{"Choose a username and password to register with this server","בחר שם משתמש וסיסמה להירשם עם שרת זה"}.
{"Choose modules to stop","בחר מודולים להפסקה"}.
@@ -54,27 +55,28 @@
{"Connections parameters","פרמטרים של חיבור"}.
{"Country","ארץ"}.
{"CPU Time:","זמן מחשב (CPU):"}.
{"Database Tables at ~p","טבלאות מסד נתונים אצל ~p"}.
{"Database Tables Configuration at ","תצורת טבלאות מסד נתונים אצל "}.
{"Database","מסד נתונים"}.
{"December","דצמבר"}.
{"Default users as participants","משתמשים משתמטים כמשתתפים"}.
{"Delete message of the day on all hosts","מחק הודעת היום בכל המארחים"}.
{"Delete message of the day","מחק הודעת היום"}.
{"Delete message of the day on all hosts","מחק את בשורת היום בכל המארחים"}.
{"Delete message of the day","מחק את בשורת היום"}.
{"Delete Selected","מחק נבחרות"}.
{"Delete User","מחק משתמש"}.
{"Delete","מחק"}.
{"Deliver event notifications","מסירת התראות אירוע"}.
{"Deliver payloads with event notifications","מסירת מטען ייעוד (מטע״ד) יחד עם התראות אירוע"}.
{"Deliver payloads with event notifications","מסירת מטעני ייעוד (מטע״ד) יחד עם התראות אירוע"}.
{"Description:","תיאור:"}.
{"Disc only copy","העתק של תקליטור בלבד"}.
{"Displayed Groups:","קבוצות מוצגות:"}.
{"Don't tell your password to anybody, not even the administrators of the Jabber server.","אל תגלה את הסיסמה שלך לאף אחד, אפילו לא למנהלים של שרת Jabber"}.
{"Dump Backup to Text File at ","השלך גיבוי אל קובץ טקסט אצל "}.
{"Dump to Text File","השלך אל קובץ טקסט"}.
{"Don't tell your password to anybody, not even the administrators of the Jabber server.","אל תגלה את הסיסמה שלך לאף אחד, אפילו לא למנהלים של שרת Jabber."}.
{"Dump Backup to Text File at ","השלך גיבוי לקובץ טקסט אצל "}.
{"Dump to Text File","השלך לקובץ טקסט"}.
{"Edit Properties","ערוך מאפיינים"}.
{"Either approve or decline the voice request.","או שתאשר או שתדחה את בקשת הביטוי."}.
{"ejabberd IRC module","מודול IRC של ejabberd"}.
{"ejabberd MUC module","מודול MUC של ejabberd"}.
{"ejabberd Multicast service","שירות שידור מרובב של ejabberd"}.
{"ejabberd Publish-Subscribe module","מודול Publish-Subscribe של ejabberd"}.
{"ejabberd SOCKS5 Bytestreams module","מודול SOCKS5 Bytestreams של ejabberd"}.
{"ejabberd vCard module","מודול vCard של ejabberd"}.
@@ -86,25 +88,27 @@
{"End User Session","סיים סשן משתמש"}.
{"Enter list of {Module, [Options]}","הזן רשימה של {מודול, [אפשרויות]}"}.
{"Enter nickname you want to register","הזן שם כינוי אשר ברצונך לרושמו"}.
{"Enter path to backup file","הזן נתיב אל קובץ גיבוי"}.
{"Enter path to jabberd14 spool dir","הזן נתיב אל מדור סליל (spool dir) של jabberd14"}.
{"Enter path to jabberd14 spool file","הזן נתיב אל קובץ סליל (spool file) של jabberd14"}.
{"Enter path to text file","הזן נתיב אל קובץ טקסט"}.
{"Enter path to backup file","הזן נתיב לקובץ גיבוי"}.
{"Enter path to jabberd14 spool dir","הזן נתיב למדור סליל (spool dir) של jabberd14"}.
{"Enter path to jabberd14 spool file","הזן נתיב לקובץ סליל (spool file) של jabberd14"}.
{"Enter path to text file","הזן נתיב לקובץ טקסט"}.
{"Enter the text you see","הזן את הטקסט אותו הינך רואה"}.
{"Enter username and encodings you wish to use for connecting to IRC servers. Press 'Next' to get more fields to fill in. Press 'Complete' to save settings.","הזן שם משתמש וקידודים בהם ברצונך להשתמש לשם התחברות אל שרתים של IRC. לחץ 'הבא' כדי להשיג עוד שדות למילוי. לחץ 'סיים' כדי לשמור הגדרות."}.
{"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","הזן שם משתמש, קידודים, פורטים וסיסמאות בהם ברצונך להשתמש לשם התחברות אל שרתים של IRC"}.
{"Enter username and encodings you wish to use for connecting to IRC servers. Press 'Next' to get more fields to fill in. Press 'Complete' to save settings.","הזן שם משתמש וקידודים בהם ברצונך להשתמש לצורך התחברות לשרתי IRC. לחץ 'הבא' כדי להשיג עוד שדות למילוי. לחץ 'סיים' כדי לשמור הגדרות."}.
{"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","הזן שם משתמש, קידודים, פורטים וסיסמאות בהם ברצונך להשתמש לצורך התחברות לשרתי IRC"}.
{"Erlang Jabber Server","שרת ג׳אבּר Erlang"}.
{"Error","שגיאה"}.
{"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","דוגמא: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}.
{"Exclude Jabber IDs from CAPTCHA challenge","הוצא כתובות של Jabber מתוך אתגר CAPTCHA"}.
{"Export data of all users in the server to PIEFXIS files (XEP-0227):","ייצוא מידע של כל המשתמשים אשר מצויים בשרת זה אל קבצי PIEFXIS (XEP-0227):"}.
{"Export data of users in a host to PIEFXIS files (XEP-0227):","ייצוא מידע של כל המשתמשים בתוך מארח אל קבצי PIEFXIS (XEP-0227):"}.
{"Export all tables as SQL queries to a file:","יצא את כל טבלאות בתור שאילתות SQL לתוך קובץ:"}.
{"Export data of all users in the server to PIEFXIS files (XEP-0227):","יצא מידע של כל המשתמשים שבתוך בשרת זה לתוך קבצי PIEFXIS (XEP-0227):"}.
{"Export data of users in a host to PIEFXIS files (XEP-0227):","יצא מידע של כל המשתמשים שבתוך מארח לתוך קבצי PIEFXIS (XEP-0227):"}.
{"Family Name","שם משפחה"}.
{"February","פברואר"}.
{"Fill in fields to search for any matching Jabber User","מלא את שדות אלו כדי לחפש עבור כל משתמש Jabber מבוקש"}.
{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","מלא את התבניות כדי לחפש עבור כל משתמש Jabber מבוקש (באפשרותך להוסיף * בסוף שדה כדי להתאים אל מחרוזת-משנה)"}.
{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","מלא את התבניות כדי לחפש עבור כל משתמש Jabber מבוקש (באפשרותך להוסיף * בסוף שדה כדי להתאים למחרוזת-משנה)"}.
{"Friday","יום שישי"}.
{"From ~s","מאת ~s"}.
{"From","מן"}.
{"From","מאת"}.
{"Full Name","שם מלא"}.
{"Get Number of Online Users","השג מספר של משתמשים מקוונים"}.
{"Get Number of Registered Users","השג מספר של משתמשים רשומים"}.
@@ -125,12 +129,12 @@
{"If you want to specify different ports, passwords, encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\", port, \"password\"}'. By default this service use \"~s\" encoding, port ~p, empty password.","אם ברצונך לציין פורטים, סיסמאות, קידודים אחרים עבור שרתים של IRC, מלא את רשימה זו עם ערכים בפורמט '{\"irc server\", \"encoding\", port, \"password\"}'. באופן משתמט שירות זה משתמש בקידוד \"~s\", פורט ~p, סיסמה ריקה."}.
{"Import Directory","ייבוא מדור"}.
{"Import File","ייבוא קובץ"}.
{"Import user data from jabberd14 spool file:","ייבוא נתוני משתמש מתוך קובץ סליל (spool file) של jabberd14:"}.
{"Import user data from jabberd14 spool file:","יבא נתוני משתמש מתוך קובץ סליל (spool file) של jabberd14:"}.
{"Import User from File at ","ייבוא משתמש מתוך קובץ אצל "}.
{"Import users data from a PIEFXIS file (XEP-0227):","ייבוא מידע משתמשים מתוך קובץ PIEFXIS (XEP-0227):"}.
{"Import users data from jabberd14 spool directory:","ייבוא נתוני משתמשים מתוך מדור סליל (spool directory) של jabberd14:"}.
{"Import users data from a PIEFXIS file (XEP-0227):","יבא מידע משתמשים מתוך קובץ PIEFXIS (XEP-0227):"}.
{"Import users data from jabberd14 spool directory:","יבא נתוני משתמשים מתוך מדור סליל (spool directory) של jabberd14:"}.
{"Import Users from Dir at ","ייבוא משתמשים מתוך מדור אצל "}.
{"Import Users From jabberd14 Spool Files","ייבוא משתמשים מתוך קבצי סליל (Spool Files) של jabberd14"}.
{"Import Users From jabberd14 Spool Files","יבא משתמשים מתוך קבצי סליל (Spool Files) של jabberd14"}.
{"Invalid affiliation: ~s","סינוף שגוי: ~s"}.
{"Invalid role: ~s","תפקיד שגוי: ~s"}.
{"IP addresses","כתובות IP"}.
@@ -146,18 +150,22 @@
{"Jabber ID ~s is invalid","מזהה Jabber ~s הינו שגוי"}.
{"Jabber ID","מזהה Jabber"}.
{"January","ינואר"}.
{"Join IRC channel","הצטרף אל ערוץ IRC"}.
{"Join IRC channel","הצטרף לערוץ IRC"}.
{"joins the room","נכנס/ת אל החדר"}.
{"Join the IRC channel here.","הצטרף אל ערוץ IRC כאן."}.
{"Join the IRC channel in this Jabber ID: ~s","הצטרף אל ערוץ IRC במזהה Jabber זה: ~s"}.
{"Join the IRC channel here.","הצטרף לערוץ IRC כאן."}.
{"Join the IRC channel in this Jabber ID: ~s","הצטרף לערוץ IRC במזהה Jabber זה: ~s"}.
{"July","יולי"}.
{"June","יוני"}.
{"Last Activity","פעילות אחרונה"}.
{"Last login","כניסה אחרונה"}.
{"Last month","חודש אחרון"}.
{"Last year","שנה אחרונה"}.
{"leaves the room","עוזב/ת אל החדר"}.
{"leaves the room","עוזב/ת את החדר"}.
{"Listened Ports at ","פורטים מואזנים אצל "}.
{"Listened Ports","פורטים מואזנים"}.
{"List of modules to start","רשימה של מודולים להפעלה"}.
{"List of rooms","רשימה של חדרים"}.
{"Low level update script","תסריט עדכון Low level"}.
{"Make participants list public","הפוך רשימת משתתפים אל פומבית"}.
{"Make room CAPTCHA protected","הפוך חדר אל מוגן CAPTCHA"}.
{"Make room members-only","הפוך חדר אל חברים-בלבד"}.
@@ -168,7 +176,7 @@
{"March","מרץ"}.
{"Maximum Number of Occupants","מספר מרבי של נוכחים"}.
{"Max # of items to persist","מספר מרבי של פריטים לקיבוע"}.
{"Max payload size in bytes","גודל מרבי של מטען הייעוד ביחידות מידה של byte"}.
{"Max payload size in bytes","גודל מרבי של מטען ייעוד (payload) ביחידות מידה של byte"}.
{"May","מאי"}.
{"Members:","חברים:"}.
{"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","שנן את הסיסמה שלך, או רשום אותה בנייר שמור במקום בטוח. אצל Jabber אין דרך אוטומטית לשחזר את הסיסמה שלך במידה וזו תישמט מתוך זיכרונך."}.
@@ -178,9 +186,12 @@
{"Minimum interval between voice requests (in seconds)","תדירות מינימלית בין בקשות ביטוי (בשניות)"}.
{"moderators only","לאחראים בלבד"}.
{"Modified modules","מודולים שהותאמו"}.
{"Modules at ~p","מודולים אצל ~p"}.
{"Modules","מודולים"}.
{"Module","מודול"}.
{"Monday","יום שני"}.
{"Multicast","שידור מרובב"}.
{"Multi-User Chat","שיחה מרובת משתמשים"}.
{"Name:","שם:"}.
{"Name","שם"}.
{"Never","אף פעם"}.
@@ -188,17 +199,20 @@
{"Nickname Registration at ","רישום שם כינוי אצל "}.
{"Nickname ~s does not exist in the room","שם כינוי ~s לא קיים בחדר"}.
{"Nickname","שם כינוי"}.
{"No body provided for announce message","לא סופק גוף עבור הודעת בשורה"}.
{"nobody","אף אחד"}.
{"No Data","אין מידע"}.
{"Node ID","מזהה ממסר (NID)"}.
{"Node not found","ממסר לא נמצא"}.
{"Nodes","ממסרים"}.
{"Node ID","מזהה צומת (NID)"}.
{"Node not found","צומת לא נמצא"}.
{"Node ~p","צומת ~p"}.
{"Nodes","צמתים"}.
{"No limit","ללא הגבלה"}.
{"None","אין"}.
{"No resource provided","לא סופק משאב"}.
{"Not Found","לא נמצא"}.
{"Notify subscribers when items are removed from the node","הודע מנויים כאשר פריטים מוסרים מתוך הממסר"}.
{"Notify subscribers when the node configuration changes","הודע מנויים כאשר תצורת הממסר משתנה"}.
{"Notify subscribers when the node is deleted","הודע מנויים כאשר הממסר נמחק"}.
{"Notify subscribers when items are removed from the node","הודע מנויים כאשר פריטים מוסרים מתוך הצומת"}.
{"Notify subscribers when the node configuration changes","הודע מנויים כאשר תצורת הצומת משתנה"}.
{"Notify subscribers when the node is deleted","הודע מנויים כאשר הצומת נמחק"}.
{"November","נובמבר"}.
{"Number of occupants","מספר של נוכחים"}.
{"Number of online users","מספר של משתמשים מקוונים"}.
@@ -211,7 +225,7 @@
{"Online Users:","משתמשים מקוונים:"}.
{"Online Users","משתמשים מקוונים"}.
{"Online","מקוון"}.
{"Only deliver notifications to available users","מסור התראות אל משתמשים זמינים בלבד"}.
{"Only deliver notifications to available users","מסור התראות למשתמשים זמינים בלבד"}.
{"Only moderators and participants are allowed to change the subject in this room","רק אחראים ומשתתפים רשאים לשנות את הנושא בחדר זה"}.
{"Only moderators are allowed to change the subject in this room","רק אחראים רשאים לשנות את הנושא בחדר זה"}.
{"Options","אפשרויות"}.
@@ -220,34 +234,40 @@
{"Outgoing s2s Connections:","חיבורי s2s יוצאים:"}.
{"Outgoing s2s Connections","חיבורי s2s יוצאים"}.
{"Outgoing s2s Servers:","שרתי s2s יוצאים:"}.
{"Packet","חבילת מידע"}.
{"Password ~b","סיסמה ~b"}.
{"Password Verification:","אימות סיסמה:"}.
{"Password Verification","אימות סיסמה"}.
{"Password:","סיסמה:"}.
{"Password","סיסמה"}.
{"Path to Dir","נתיב אל מדור"}.
{"Path to File","נתיב אל קובץ"}.
{"Path to Dir","נתיב למדור"}.
{"Path to File","נתיב לקובץ"}.
{"Pending","ממתינות"}.
{"Period: ","משך זמן: "}.
{"Permanent rooms","חדרים קבועים"}.
{"Persist items to storage","פריטים קבועים לאחסון"}.
{"Ping","פינג"}.
{"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","נא לשים לב כי אפשרויות אלו יגבו את מסד הנתונים המובנה Mnesia בלבד. אם הינך עושה שימוש במודול ODBC, עליך גם לגבות את מסד הנתונים SQL אשר מצוי ברשותך בנפרד."}.
{"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","אנא שים לב כי אפשרויות אלו יגבו את מסד הנתונים המובנה Mnesia בלבד. אם הינך עושה שימוש במודול ODBC, עליך גם לגבות את מסד הנתונים SQL אשר מצוי ברשותך בנפרד."}.
{"Pong","פונג"}.
{"Port ~b","פורט ~b"}.
{"Port","פורט"}.
{"Present real Jabber IDs to","הצג כתובות JID ממשיות"}.
{"private, ","פרטי, "}.
{"Protocol","פרוטוקול"}.
{"Publish-Subscribe","Publish-Subscribe"}.
{"PubSub subscriber request","בקשת מנוי PubSub"}.
{"Purge all items when the relevant publisher goes offline","טיהור כל הפריטים כאשר המפרסם הרלוונטי "}.
{"RAM and disc copy","העתק RAM וגם תקליטור"}.
{"RAM copy","העתק RAM"}.
{"Really delete message of the day?","באמת למחוק את הודעת היום?"}.
{"Raw","גולמי"}.
{"Really delete message of the day?","באמת למחוק את בשורת היום?"}.
{"Register a Jabber account","רשום חשבון Jabber"}.
{"Registered nicknames","שמות כינוי רשומים"}.
{"Registered Users:","משתמשים רשומים:"}.
{"Registered Users","משתמשים רשומים"}.
{"Register","הרשם"}.
{"Registration in mod_irc for ","רישום בתוך mod_irc עבור "}.
{"Remote copy","עותק מרוחק"}.
{"Remote copy","העתק מרוחק"}.
{"Remove All Offline Messages","הסר את כל ההודעות הלא מקוונות"}.
{"Remove User","הסר משתמש"}.
{"Remove","הסר"}.
@@ -269,69 +289,81 @@
{"Roster size","גודל רשימה"}.
{"Roster","רשימה"}.
{"RPC Call Error","שגיאת קריאת RPC"}.
{"Running Nodes","ממסרים שמורצים כעת"}.
{"Running Nodes","צמתים מורצים"}.
{"~s access rule configuration","~s תצורת כללי גישה"}.
{"Saturday","יום שבת"}.
{"Script check","בדיקת תסריט"}.
{"Search Results for ","תוצאות חיפוש עבור "}.
{"Search users in ","חיפוש משתמשים אצל "}.
{"Send announcement to all online users on all hosts","שלח מודעות אל כל המשתמשים המקוונים בכל המארחים"}.
{"Send announcement to all online users","שלח מודעות אל כל המשתמשים המקוונים"}.
{"Send announcement to all users on all hosts","שלח מודעות אל כל המשתמשים בכל המארחים"}.
{"Send announcement to all users","שלח מודעות אל כל המשתמשים"}.
{"Send announcement to all online users on all hosts","שלח בשורה לכל המשתמשים המקוונים בכל המארחים"}.
{"Send announcement to all online users","שלח בשורה לכל המשתמשים המקוונים"}.
{"Send announcement to all users on all hosts","שלח בשורה לכל המשתמשים בכל המארחים"}.
{"Send announcement to all users","שלח בשורה לכל המשתמשים"}.
{"September","ספטמבר"}.
{"Server ~b","שרת ~b"}.
{"Server:","שרת:"}.
{"Set message of the day and send to online users","קבע הודעת היום ושלח אל משתמשים מקוונים"}.
{"Set message of the day on all hosts and send to online users","קבע הודעת היום בכל המארחים ושלח אל משתמשים מקוונים"}.
{"Set message of the day and send to online users","קבע את בשורת היום ושלח למשתמשים מקוונים"}.
{"Set message of the day on all hosts and send to online users","קבע את בשורת היום בכל המארחים ושלח למשתמשים מקוונים"}.
{"Shared Roster Groups","קבוצות רשימה משותפות"}.
{"Show Integral Table","הצג טבלה אינטגרלית"}.
{"Show Ordinary Table","הצג טבלה רגילה"}.
{"Shut Down Service","כבה שירות"}.
{"~s invites you to the room ~s","~s מזמינך אל החדר ~s"}.
{"~s invites you to the room ~s","~s מזמינך לחדר ~s"}.
{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","לקוחות Jabber מסוימים יכולים לאחסן את הסיסמה שלך על המחשב שלך. השתמש בתכונה זו רק אם אתה סמוך כי המחשב שלך הינו מוגן."}.
{"Specify the access model","ציין את מודל הגישה"}.
{"Specify the event message type","ציין את טיפוס הודעת האירוע"}.
{"Specify the publisher model","ציין את מודל הפרסום"}.
{"~s's Offline Messages Queue","תור הודעות לא מקוונות של ~s"}.
{"Start Modules at ","התחל מודולים אצל "}.
{"Start Modules","התחל מודולים"}.
{"Start","התחל"}.
{"Statistics of ~p","סטטיסטיקות עבור ~p"}.
{"Statistics of ~p","סטטיסטיקות של ~p"}.
{"Statistics","סטטיסטיקה"}.
{"Stop Modules at ","הפסק מודולים אצל "}.
{"Stop Modules","הפסק מודולים"}.
{"Stopped Nodes","ממסרים שנפסקו"}.
{"Stopped Nodes","צמתים שנפסקו"}.
{"Stop","הפסק"}.
{"Storage Type","טיפוס אחסון"}.
{"Store binary backup:","אחסן גיבוי בינארי:"}.
{"Store plain text backup:","אחסן גיבוי טקסט גלוי (plain text):"}.
{"Subject","נושא"}.
{"Submit","שליחה"}.
{"Submitted","נשלח"}.
{"Submit","שלח"}.
{"Subscriber Address","כתובת מנוי"}.
{"Subscription","מִנּוּי"}.
{"Subscription","הרשמה"}.
{"Sunday","יום ראשון"}.
{"The CAPTCHA is valid.","CAPTCHA הינה בתוקף."}.
{"The collections with which a node is affiliated","האוספים עמם צומת מסונף"}.
{"the password is","הסיסמה היא"}.
{"The password of your Jabber account was successfully changed.","סיסמת חשבון Jabber שונתה בהצלחה."}.
{"There was an error changing the password: ","אירעה שגיאה בשינוי הסיסמה: "}.
{"There was an error creating the account: ","אירעה שגיאה ביצירת החשבון: "}.
{"There was an error deleting the account: ","אירעה שגיאה במחיקת החשבון: "}.
{"This IP address is blacklisted in ~s","כתובת IP זו רשומה ברשימה שחורה בתוך ~s"}.
{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","חלק זה אינו ער לרישיות: macbeth הינה זהה כשם MacBeth וגם Macbeth."}.
{"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","עמוד זה מתיר ליצור חשבון Jabber בשרת Jabber זה. כתובת JID (Jabber IDentifier) תגובש באופן של: username@server. נא לקרוא בזהירות את ההוראות למילוי השדות באופן נכון."}.
{"This page allows to unregister a Jabber account in this Jabber server.","עמוד זה מתיר לך לבטל רישום של חשבון Jabber בשרת Jabber זה."}.
{"This room is not anonymous","חדר זה אינו אנונימי"}.
{"Thursday","יום חמישי"}.
{"Time delay","זמן שיהוי"}.
{"Time","זמן"}.
{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","יותר מדי (~p) אימותים כושלים מתוך כתובת IP זו (~s). הכתובת תורשה לקבל גישה בשעה ~s UTC"}.
{"Too many unacked stanzas","יותר מדי סטנזות בלי אישורי קבלה"}.
{"To ~s","אל ~s"}.
{"To","אל"}.
{"Transactions Aborted:","טרנזקציות בוטלו:"}.
{"Transactions Committed:","טרנזקציות בוצעו:"}.
{"Transactions Logged:","טרנזקציות נרשמו:"}.
{"Transactions Restarted:","טרנזקציות הותחלו מחדש:"}.
{"Total rooms","חדרים סה״כ"}.
{"To","לכבוד"}.
{"Transactions Aborted:","טרנזקציות שבוטלו:"}.
{"Transactions Committed:","טרנזקציות שבוצעו:"}.
{"Transactions Logged:","טרנזקציות שנרשמו:"}.
{"Transactions Restarted:","טרנזקציות שהותחלו מחדש:"}.
{"Tuesday","יום שלישי"}.
{"Unauthorized","לא מורשה"}.
{"Unregister a Jabber account","בטל רישום חשבון Jabber"}.
{"Unregister","בטל רישום"}.
{"Update message of the day (don't send)","עדכן הודעת היום (אל תשלח)"}.
{"Update message of the day on all hosts (don't send)","עדכן הודעת היום בכל המארחים (אל תשלח)"}.
{"Update message of the day (don't send)","עדכן את בשורת היום (אל תשלח)"}.
{"Update message of the day on all hosts (don't send)","עדכן את בשורת היום בכל המארחים (אל תשלח)"}.
{"Update plan","תכנית עדכון"}.
{"Update ~p","עדכון ~p"}.
{"Update script","תסריט עדכון"}.
{"Update","עדכן"}.
{"Uptime:","זמן פעילות:"}.
{"Use of STARTTLS required","נדרש שימוש של STARTTLS"}.
@@ -339,6 +371,7 @@
{"User Management","ניהול משתמשים"}.
{"Username:","שם משתמש:"}.
{"Users Last Activity","פעילות משתמשים אחרונה"}.
{"User ~s","משתמש ~s"}.
{"Users","משתמשים"}.
{"User","משתמש"}.
{"Validate","הענק תוקף"}.
@@ -356,4 +389,4 @@
{"You need an x:data capable client to search","עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי לחפש"}.
{"Your Jabber account was successfully created.","חשבון Jabber נוצר בהצלחה."}.
{"Your Jabber account was successfully deleted.","חשבון Jabber נמחק בהצלחה."}.
{"Your messages to ~s are being blocked. To unblock them, visit ~s","ההודעות שלך לערוץ ~s הינן חסומות. כדי למנוע את חסימתן, בקר בכתובת ~s"}.
{"Your messages to ~s are being blocked. To unblock them, visit ~s","ההודעות שלך לערוץ ~s הינן חסומות. כדי לבטל את חסימתן, בקר בכתובת ~s"}.
+533 -535
View File
File diff suppressed because it is too large Load Diff
+22 -23
View File
@@ -54,15 +54,14 @@ SrcDirs = lists:foldl(
Acc
end, [], Cfg),
Deps = [{p1_cache_tab, ".*", {git, "git://github.com/processone/cache_tab"}},
{p1_tls, ".*", {git, "git://github.com/processone/tls"}},
{p1_stringprep, ".*", {git, "git://github.com/processone/stringprep"}},
{p1_xml, ".*", {git, "git://github.com/processone/xml"}},
{esip, ".*", {git, "git://github.com/processone/p1_sip"}},
{p1_stun, ".*", {git, "git://github.com/processone/stun"}},
{p1_yaml, ".*", {git, "git://github.com/processone/p1_yaml"}},
{ehyperloglog, ".*", {git, "https://github.com/vaxelfel/eHyperLogLog.git"}},
{p1_utils, ".*", {git, "git://github.com/processone/p1_utils"}}],
Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab"}},
{p1_tls, ".*", {git, "https://github.com/processone/tls"}},
{p1_stringprep, ".*", {git, "https://github.com/processone/stringprep"}},
{p1_xml, ".*", {git, "https://github.com/processone/xml"}},
{esip, ".*", {git, "https://github.com/processone/p1_sip"}},
{p1_stun, ".*", {git, "https://github.com/processone/stun"}},
{p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml"}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils"}}],
ConfigureCmd = fun(Pkg, Flags) ->
{'get-deps',
@@ -87,32 +86,32 @@ PostHooks = [ConfigureCmd("p1_tls", ""),
CfgDeps = lists:flatmap(
fun({mysql, true}) ->
[{p1_mysql, ".*", {git, "git://github.com/processone/mysql"}}];
[{p1_mysql, ".*", {git, "https://github.com/processone/mysql"}}];
({pgsql, true}) ->
[{p1_pgsql, ".*", {git, "git://github.com/processone/pgsql"}}];
[{p1_pgsql, ".*", {git, "https://github.com/processone/pgsql"}}];
({sqlite, true}) ->
[{sqlite3, ".*", {git, "git://github.com/alexeyr/erlang-sqlite3"}}];
[{sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3"}}];
({pam, true}) ->
[{p1_pam, ".*", {git, "git://github.com/processone/epam"}}];
[{p1_pam, ".*", {git, "https://github.com/processone/epam"}}];
({zlib, true}) ->
[{p1_zlib, ".*", {git, "git://github.com/processone/zlib"}}];
[{p1_zlib, ".*", {git, "https://github.com/processone/zlib"}}];
({riak, true}) ->
[{riakc, ".*", {git, "git://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}];
[{riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}];
({json, true}) ->
[{jiffy, ".*", {git, "git://github.com/davisp/jiffy"}}];
[{jiffy, ".*", {git, "https://github.com/davisp/jiffy"}}];
({elixir, true}) ->
[{rebar_elixir_plugin, ".*", {git, "git://github.com/yrashk/rebar_elixir_plugin"}},
{elixir, ".*", {git, "git://github.com/elixir-lang/elixir", {branch, "v1.0"}}}];
[{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin"}},
{elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {branch, "v1.0"}}}];
({iconv, true}) ->
[{p1_iconv, ".*", {git, "git://github.com/processone/eiconv"}}];
[{p1_iconv, ".*", {git, "https://github.com/processone/eiconv"}}];
({lager, true}) ->
[{lager, ".*", {git, "git://github.com/basho/lager"}}];
[{lager, ".*", {git, "https://github.com/basho/lager"}}];
({lager, false}) ->
[{p1_logger, ".*", {git, "git://github.com/processone/p1_logger"}}];
[{p1_logger, ".*", {git, "https://github.com/processone/p1_logger"}}];
({tools, true}) ->
[{meck, "0.*", {git, "https://github.com/eproxus/meck"}}];
({redis, true}) ->
[{eredis, ".*", {git, "git://github.com/wooga/eredis"}}];
({redis, true}) ->
[{eredis, ".*", {git, "https://github.com/wooga/eredis"}}];
(_) ->
[]
end, Cfg),
+24
View File
@@ -270,3 +270,27 @@ CREATE TABLE caps_features (
);
CREATE INDEX i_caps_features_node_subnode ON caps_features (node, subnode);
CREATE TABLE archive (
username text NOT NULL,
timestamp BIGINT UNSIGNED NOT NULL,
peer text NOT NULL,
bare_peer text NOT NULL,
xml text NOT NULL,
txt text,
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX i_username ON archive(username);
CREATE INDEX i_timestamp ON archive(timestamp);
CREATE INDEX i_peer ON archive(peer);
CREATE INDEX i_bare_peer ON archive(bare_peer);
CREATE TABLE archive_prefs (
username text NOT NULL PRIMARY KEY,
def text NOT NULL,
always text NOT NULL,
never text NOT NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
);
+25
View File
@@ -85,6 +85,31 @@ CREATE TABLE spool (
CREATE INDEX i_despool USING BTREE ON spool(username);
CREATE INDEX i_spool_created_at USING BTREE ON spool(created_at);
CREATE TABLE archive (
username varchar(250) NOT NULL,
timestamp BIGINT UNSIGNED NOT NULL,
peer varchar(250) NOT NULL,
bare_peer varchar(250) NOT NULL,
xml text NOT NULL,
txt text,
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARACTER SET utf8;
CREATE FULLTEXT INDEX i_text ON archive(txt);
CREATE INDEX i_username USING BTREE ON archive(username);
CREATE INDEX i_timestamp USING BTREE ON archive(timestamp);
CREATE INDEX i_peer USING BTREE ON archive(peer);
CREATE INDEX i_bare_peer USING BTREE ON archive(bare_peer);
CREATE TABLE archive_prefs (
username varchar(250) NOT NULL PRIMARY KEY,
def text NOT NULL,
always text NOT NULL,
never text NOT NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARACTER SET utf8;
CREATE TABLE vcard (
username varchar(250) PRIMARY KEY,
vcard mediumtext NOT NULL,
+37
View File
@@ -85,6 +85,29 @@ CREATE TABLE spool (
CREATE INDEX i_despool ON spool USING btree (username);
CREATE TABLE archive (
username text NOT NULL,
timestamp BIGINT NOT NULL,
peer text NOT NULL,
bare_peer text NOT NULL,
xml text NOT NULL,
txt text,
id SERIAL,
created_at TIMESTAMP NOT NULL DEFAULT now()
);
CREATE INDEX i_username ON archive USING btree (username);
CREATE INDEX i_timestamp ON archive USING btree (timestamp);
CREATE INDEX i_peer ON archive USING btree (peer);
CREATE INDEX i_bare_peer ON archive USING btree (bare_peer);
CREATE TABLE archive_prefs (
username text NOT NULL PRIMARY KEY,
def text NOT NULL,
always text NOT NULL,
never text NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT now()
);
CREATE TABLE vcard (
username text PRIMARY KEY,
@@ -288,3 +311,17 @@ CREATE TABLE caps_features (
);
CREATE INDEX i_caps_features_node_subnode ON caps_features USING btree (node, subnode);
CREATE TABLE sm (
usec bigint NOT NULL,
pid text NOT NULL,
node text NOT NULL,
username text NOT NULL,
resource text NOT NULL,
priority text NOT NULL,
info text NOT NULL
);
CREATE UNIQUE INDEX i_sm_sid ON sm USING btree (usec, pid);
CREATE INDEX i_sm_node ON sm USING btree (node);
CREATE INDEX i_sm_username ON sm USING btree (username);
+9 -2
View File
@@ -25,11 +25,14 @@
-module(acl).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-export([start/0, to_record/3, add/3, add_list/3,
add_local/3, add_list_local/3, load_from_config/0,
match_rule/3, match_acl/3, transform_options/1]).
add_local/3, add_list_local/3, load_from_config/0,
match_rule/3, match_acl/3, transform_options/1,
opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -476,3 +479,7 @@ transform_options({access, Name, Rules}, Opts) ->
[{access, [{Name, NewRules}]}|Opts];
transform_options(Opt, Opts) ->
[Opt|Opts].
opt_type(access) -> fun (V) -> V end;
opt_type(acl) -> fun (V) -> V end;
opt_type(_) -> [access, acl].
+11 -1
View File
@@ -25,10 +25,13 @@
-module(cyrsasl).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-export([start/0, register_mechanism/3, listmech/1,
server_new/7, server_start/3, server_step/2]).
server_new/7, server_start/3, server_step/2,
opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -237,3 +240,10 @@ is_disabled(Mechanism) ->
[str:to_upper(V)]
end, []),
lists:member(Mechanism, Disabled).
opt_type(disable_sasl_mechanisms) ->
fun (V) when is_list(V) ->
lists:map(fun (M) -> str:to_upper(M) end, V);
(V) -> [str:to_upper(V)]
end;
opt_type(_) -> [disable_sasl_mechanisms].
+2
View File
@@ -26,6 +26,8 @@
-module(cyrsasl_anonymous).
-protocol({xep, 175, '1.2'}).
-export([start/1, stop/0, mech_new/4, mech_step/2]).
-behaviour(cyrsasl).
+7 -1
View File
@@ -25,9 +25,12 @@
-module(cyrsasl_digest).
-behaviour(ejabberd_config).
-author('alexey@sevcom.net').
-export([start/1, stop/0, mech_new/4, mech_step/2, parse/1]).
-export([start/1, stop/0, mech_new/4, mech_step/2,
parse/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -256,3 +259,6 @@ response(KeyVals, User, Passwd, Nonce, AuthzId,
":", NC/binary, ":", CNonce/binary, ":", QOP/binary,
":", (hex((erlang:md5(A2))))/binary>>,
hex((erlang:md5(T))).
opt_type(fqdn) -> fun iolist_to_binary/1;
opt_type(_) -> [fqdn].
+2
View File
@@ -27,6 +27,8 @@
-author('stephen.roettger@googlemail.com').
-protocol({rfc, 5802}).
-export([start/1, stop/0, mech_new/4, mech_step/2]).
-include("ejabberd.hrl").
+10
View File
@@ -26,6 +26,16 @@
-module(ejabberd).
-author('alexey@process-one.net').
-protocol({xep, 4, '2.9'}).
-protocol({xep, 86, '1.0'}).
-protocol({xep, 106, '1.1'}).
-protocol({xep, 170, '1.0'}).
-protocol({xep, 205, '1.0'}).
-protocol({xep, 212, '1.0'}).
-protocol({xep, 216, '1.0'}).
-protocol({xep, 243, '1.0'}).
-protocol({xep, 270, '1.0'}).
-export([start/0, stop/0, start_app/1, start_app/2,
get_pid_file/0, check_app/1]).
+5 -19
View File
@@ -42,7 +42,6 @@
%% Purge DB
delete_expired_messages/0, delete_old_messages/1,
%% Mnesia
export2odbc/2,
set_master/1,
backup_mnesia/1, restore_mnesia/1,
dump_mnesia/1, dump_table/2, load_mnesia/1,
@@ -168,6 +167,10 @@ commands() ->
desc = "Export all tables as SQL queries to a file",
module = ejd2odbc, function = export,
args = [{host, string}, {file, string}], result = {res, rescode}},
#ejabberd_commands{name = convert_to_scram, tags = [odbc],
desc = "Convert the passwords in 'users' ODBC table to SCRAM",
module = ejabberd_auth_odbc, function = convert_to_scram,
args = [{host, binary}], result = {res, rescode}},
#ejabberd_commands{name = convert_to_yaml, tags = [config],
desc = "Convert the input file from Erlang to YAML format",
@@ -191,7 +194,7 @@ commands() ->
#ejabberd_commands{name = export2odbc, tags = [mnesia],
desc = "Export virtual host information from Mnesia tables to SQL files",
module = ?MODULE, function = export2odbc,
module = ejd2odbc, function = export,
args = [{host, string}, {directory, string}],
result = {res, rescode}},
#ejabberd_commands{name = set_master, tags = [mnesia],
@@ -408,23 +411,6 @@ delete_old_messages(Days) ->
%%% Mnesia management
%%%
export2odbc(Host, Directory) ->
Tables = [{export_last, last},
{export_offline, offline},
{export_private_storage, private_storage},
{export_roster, roster},
{export_vcard, vcard},
{export_vcard_search, vcard_search},
{export_passwd, passwd}],
Export = fun({TableFun, Table}) ->
Filename = filename:join([Directory, atom_to_list(Table)++".txt"]),
io:format("Trying to export Mnesia table '~p' on Host '~s' to file '~s'~n", [Table, Host, Filename]),
Res = (catch ejd2odbc:TableFun(Host, Filename)),
io:format(" Result: ~p~n", [Res])
end,
lists:foreach(Export, Tables),
ok.
set_master("self") ->
set_master(node());
set_master(NodeString) when is_list(NodeString) ->
+28 -5
View File
@@ -24,11 +24,14 @@
%%%----------------------------------------------------------------------
-module(ejabberd_app).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(application).
-export([start_modules/0,start/2, prep_stop/1, stop/1, init/0]).
-export([start_modules/0, start/2, prep_stop/1, stop/1,
init/0, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -51,7 +54,7 @@ start(normal, _Args) ->
ejabberd_admin:start(),
gen_mod:start(),
ejabberd_config:start(),
set_loglevel_from_config(),
set_settings_from_config(),
acl:start(),
shaper:start(),
connect_nodes(),
@@ -59,13 +62,13 @@ start(normal, _Args) ->
ejabberd_rdbms:start(),
ejabberd_riak_sup:start(),
ejabberd_sm:start(),
ejabberd_auth:start(),
cyrsasl:start(),
% Profiling
%ejabberd_debug:eprof_start(),
%ejabberd_debug:fprof_start(),
maybe_add_nameservers(),
ext_mod:start(),
ejabberd_auth:start(),
start_modules(),
ejabberd_listener:start_listeners(),
?INFO_MSG("ejabberd ~s is started in the node ~p", [?VERSION, node()]),
@@ -231,12 +234,17 @@ delete_pid_file() ->
file:delete(PidFilename)
end.
set_loglevel_from_config() ->
set_settings_from_config() ->
Level = ejabberd_config:get_option(
loglevel,
fun(P) when P>=0, P=<5 -> P end,
4),
ejabberd_logger:set(Level).
ejabberd_logger:set(Level),
Ticktime = ejabberd_config:get_option(
net_ticktime,
opt_type(net_ticktime),
60),
net_kernel:set_net_ticktime(Ticktime).
start_apps() ->
crypto:start(),
@@ -248,3 +256,18 @@ start_apps() ->
ejabberd:start_app(p1_stringprep),
ejabberd:start_app(p1_zlib),
ejabberd:start_app(p1_cache_tab).
opt_type(net_ticktime) ->
fun (P) when is_integer(P), P > 0 -> P end;
opt_type(cluster_nodes) ->
fun (Ns) -> true = lists:all(fun is_atom/1, Ns), Ns end;
opt_type(loglevel) ->
fun (P) when P >= 0, P =< 5 -> P end;
opt_type(modules) ->
fun (Mods) ->
lists:map(fun ({M, A}) when is_atom(M), is_list(A) ->
{M, A}
end,
Mods)
end;
opt_type(_) -> [cluster_nodes, loglevel, modules, net_ticktime].
+10 -1
View File
@@ -27,6 +27,8 @@
-module(ejabberd_auth).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
%% External exports
@@ -42,7 +44,7 @@
remove_user/2, remove_user/3, plain_password_required/1,
store_type/1, entropy/1]).
-export([auth_modules/1]).
-export([auth_modules/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -453,3 +455,10 @@ import(Server, riak, Passwd) ->
ejabberd_auth_riak:import(Server, riak, Passwd);
import(_, _, _) ->
pass.
opt_type(auth_method) ->
fun (V) when is_list(V) ->
true = lists:all(fun is_atom/1, V), V;
(V) when is_atom(V) -> [V]
end;
opt_type(_) -> [auth_method].
+17 -6
View File
@@ -24,6 +24,8 @@
%%%----------------------------------------------------------------------
-module(ejabberd_auth_anonymous).
-behaviour(ejabberd_config).
-author('mickael.remond@process-one.net').
-export([start/1,
@@ -36,16 +38,15 @@
unregister_connection/3
]).
%% Function used by ejabberd_auth:
-export([login/2, set_password/3, check_password/3,
check_password/5, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2, get_vh_registered_users_number/1,
get_vh_registered_users_number/2, get_password_s/2,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
get_vh_registered_users_number/2, get_password_s/2,
get_password/2, get_password/3, is_user_exists/2,
remove_user/2, remove_user/3, store_type/0,
plain_password_required/0]).
plain_password_required/0, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -141,7 +142,7 @@ remove_connection(SID, LUser, LServer) ->
%% Register connection
register_connection(SID,
#jid{luser = LUser, lserver = LServer}, Info) ->
AuthModule = list_to_atom(binary_to_list(xml:get_attr_s(<<"auth_module">>, Info))),
AuthModule = proplists:get_value(auth_module, Info, undefined),
case AuthModule == (?MODULE) of
true ->
ejabberd_hooks:run(register_user, LServer,
@@ -269,3 +270,13 @@ plain_password_required() -> false.
store_type() ->
plain.
opt_type(allow_multiple_connections) ->
fun (V) when is_boolean(V) -> V end;
opt_type(anonymous_protocol) ->
fun (sasl_anon) -> sasl_anon;
(login_anon) -> login_anon;
(both) -> both
end;
opt_type(_) ->
[allow_multiple_connections, anonymous_protocol].
+12 -3
View File
@@ -25,11 +25,12 @@
-module(ejabberd_auth_external).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(ejabberd_auth).
%% External exports
-export([start/1, set_password/3, check_password/3,
check_password/5, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
@@ -37,8 +38,8 @@
get_vh_registered_users_number/1,
get_vh_registered_users_number/2, get_password/2,
get_password_s/2, is_user_exists/2, remove_user/2,
remove_user/3, store_type/0,
plain_password_required/0]).
remove_user/3, store_type/0, plain_password_required/0,
opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -311,3 +312,11 @@ get_mod_last_configured(Server) ->
is_configured(Host, Module) ->
gen_mod:is_loaded(Host, Module).
opt_type(extauth_cache) ->
fun (false) -> undefined;
(I) when is_integer(I), I >= 0 -> I
end;
opt_type(extauth_program) ->
fun (V) -> binary_to_list(iolist_to_binary(V)) end;
opt_type(_) -> [extauth_cache, extauth_program].
+6 -2
View File
@@ -25,11 +25,12 @@
-module(ejabberd_auth_internal).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(ejabberd_auth).
%% External exports
-export([start/1, set_password/3, check_password/3,
check_password/5, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
@@ -38,7 +39,7 @@
get_vh_registered_users_number/2, get_password/2,
get_password_s/2, is_user_exists/2, remove_user/2,
remove_user/3, store_type/0, export/1, import/1,
import/3, plain_password_required/0]).
import/3, plain_password_required/0, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -484,3 +485,6 @@ import(_LServer, mnesia, #passwd{} = P) ->
mnesia:dirty_write(P);
import(_, _, _) ->
pass.
opt_type(auth_password_format) -> fun (V) -> V end;
opt_type(_) -> [auth_password_format].
+34 -9
View File
@@ -25,6 +25,8 @@
-module(ejabberd_auth_ldap).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(gen_server).
@@ -34,16 +36,15 @@
-export([init/1, handle_info/2, handle_call/3,
handle_cast/2, terminate/2, code_change/3]).
%% External exports
-export([start/1, stop/1, start_link/1, set_password/3,
check_password/3, check_password/5, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
get_vh_registered_users/2,
get_vh_registered_users_number/1,
get_vh_registered_users_number/2, get_password/2,
get_password_s/2, is_user_exists/2, remove_user/2,
remove_user/3, store_type/0,
plain_password_required/0]).
remove_user/3, store_type/0, plain_password_required/0,
opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -360,7 +361,7 @@ parse_options(Host) ->
Eldap_ID = jlib:atom_to_binary(gen_mod:get_module_proc(Host, ?MODULE)),
Bind_Eldap_ID = jlib:atom_to_binary(
gen_mod:get_module_proc(Host, bind_ejabberd_auth_ldap)),
UIDsTemp = eldap_utils:get_opt(
UIDsTemp = gen_mod:get_opt(
{ldap_uids, Host}, [],
fun(Us) ->
lists:map(
@@ -375,7 +376,7 @@ parse_options(Host) ->
end, [{<<"uid">>, <<"%u">>}]),
UIDs = eldap_utils:uids_domain_subst(Host, UIDsTemp),
SubFilter = eldap_utils:generate_subfilter(UIDs),
UserFilter = case eldap_utils:get_opt(
UserFilter = case gen_mod:get_opt(
{ldap_filter, Host}, [],
fun check_filter/1, <<"">>) of
<<"">> ->
@@ -386,7 +387,7 @@ parse_options(Host) ->
SearchFilter = eldap_filter:do_sub(UserFilter,
[{<<"%u">>, <<"*">>}]),
{DNFilter, DNFilterAttrs} =
eldap_utils:get_opt({ldap_dn_filter, Host}, [],
gen_mod:get_opt({ldap_dn_filter, Host}, [],
fun([{DNF, DNFA}]) ->
NewDNFA = case DNFA of
undefined ->
@@ -398,7 +399,7 @@ parse_options(Host) ->
NewDNF = check_filter(DNF),
{NewDNF, NewDNFA}
end, {undefined, []}),
LocalFilter = eldap_utils:get_opt(
LocalFilter = gen_mod:get_opt(
{ldap_local_filter, Host}, [], fun(V) -> V end),
#state{host = Host, eldap_id = Eldap_ID,
bind_eldap_id = Bind_Eldap_ID,
@@ -418,3 +419,27 @@ check_filter(F) ->
NewF = iolist_to_binary(F),
{ok, _} = eldap_filter:parse(NewF),
NewF.
opt_type(ldap_dn_filter) ->
fun ([{DNF, DNFA}]) ->
NewDNFA = case DNFA of
undefined -> [];
_ -> [iolist_to_binary(A) || A <- DNFA]
end,
NewDNF = check_filter(DNF),
{NewDNF, NewDNFA}
end;
opt_type(ldap_filter) -> fun check_filter/1;
opt_type(ldap_local_filter) -> fun (V) -> V end;
opt_type(ldap_uids) ->
fun (Us) ->
lists:map(fun ({U, P}) ->
{iolist_to_binary(U), iolist_to_binary(P)};
({U}) -> {iolist_to_binary(U)};
(U) -> {iolist_to_binary(U)}
end,
lists:flatten(Us))
end;
opt_type(_) ->
[ldap_dn_filter, ldap_filter, ldap_local_filter,
ldap_uids].
+7 -4
View File
@@ -25,11 +25,12 @@
-module(ejabberd_auth_odbc).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(ejabberd_auth).
%% External exports
-export([start/1, set_password/3, check_password/3,
check_password/5, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
@@ -37,9 +38,8 @@
get_vh_registered_users_number/1,
get_vh_registered_users_number/2, get_password/2,
get_password_s/2, is_user_exists/2, remove_user/2,
remove_user/3, store_type/0,
plain_password_required/0,
convert_to_scram/1]).
remove_user/3, store_type/0, plain_password_required/0,
convert_to_scram/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -467,3 +467,6 @@ convert_to_scram(Server) ->
Error -> Error
end
end.
opt_type(auth_password_format) -> fun (V) -> V end;
opt_type(_) -> [auth_password_format].
+15 -9
View File
@@ -24,22 +24,21 @@
%%%-------------------------------------------------------------------
-module(ejabberd_auth_pam).
-behaviour(ejabberd_config).
-author('xram@jabber.ru').
-behaviour(ejabberd_auth).
%% External exports
%%====================================================================
%% API
%%====================================================================
-export([start/1, set_password/3, check_password/3,
check_password/5, try_register/3,
dirty_get_registered_users/0, get_vh_registered_users/1,
get_vh_registered_users/2, get_vh_registered_users_number/1,
get_vh_registered_users_number/2,
get_password/2, get_password_s/2, is_user_exists/2,
remove_user/2, remove_user/3, store_type/0,
plain_password_required/0]).
get_vh_registered_users/2,
get_vh_registered_users_number/1,
get_vh_registered_users_number/2, get_password/2,
get_password_s/2, is_user_exists/2, remove_user/2,
remove_user/3, store_type/0, plain_password_required/0,
opt_type/1]).
start(_Host) ->
ejabberd:start_app(p1_pam).
@@ -118,3 +117,10 @@ get_pam_userinfotype(Host) ->
(jid) -> jid
end,
username).
opt_type(pam_service) -> fun iolist_to_binary/1;
opt_type(pam_userinfotype) ->
fun (username) -> username;
(jid) -> jid
end;
opt_type(_) -> [pam_service, pam_userinfotype].
+76 -65
View File
@@ -25,8 +25,14 @@
-module(ejabberd_c2s).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-protocol({xep, 78, '2.5'}).
-protocol({xep, 138, '2.0'}).
-protocol({xep, 198, '1.3'}).
-update_info({update, 0}).
-define(GEN_FSM, p1_fsm).
@@ -50,23 +56,12 @@
get_subscribed/1,
transform_listen_option/2]).
%% gen_fsm callbacks
-export([init/1,
wait_for_stream/2,
wait_for_auth/2,
wait_for_feature_request/2,
wait_for_bind/2,
wait_for_session/2,
wait_for_sasl_response/2,
wait_for_resume/2,
session_established/2,
handle_event/3,
handle_sync_event/4,
code_change/4,
handle_info/3,
terminate/3,
print_state/1
]).
-export([init/1, wait_for_stream/2, wait_for_auth/2,
wait_for_feature_request/2, wait_for_bind/2,
wait_for_session/2, wait_for_sasl_response/2,
wait_for_resume/2, session_established/2,
handle_event/3, handle_sync_event/4, code_change/4,
handle_info/3, terminate/3, print_state/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -169,14 +164,14 @@
%% XEP-0198:
-define(IS_STREAM_MGMT_TAG(Name),
Name == <<"enable">>;
Name == <<"resume">>;
Name == <<"a">>;
Name == <<"r">>).
(Name == <<"enable">>) or
(Name == <<"resume">>) or
(Name == <<"a">>) or
(Name == <<"r">>)).
-define(IS_SUPPORTED_MGMT_XMLNS(Xmlns),
Xmlns == ?NS_STREAM_MGMT_2;
Xmlns == ?NS_STREAM_MGMT_3).
(Xmlns == ?NS_STREAM_MGMT_2) or
(Xmlns == ?NS_STREAM_MGMT_3)).
-define(MGMT_FAILED(Condition, Xmlns),
#xmlel{name = <<"failed">>,
@@ -288,6 +283,7 @@ init([{SockMod, Socket}, Opts]) ->
StartTLSRequired orelse TLSEnabled,
TLSOpts1 = lists:filter(fun ({certfile, _}) -> true;
({ciphers, _}) -> true;
({dhfile, _}) -> true;
(_) -> false
end,
Opts),
@@ -312,7 +308,7 @@ init([{SockMod, Socket}, Opts]) ->
MaxAckQueue = case proplists:get_value(max_ack_queue, Opts) of
Limit when is_integer(Limit), Limit > 0 -> Limit;
infinity -> infinity;
_ -> 500
_ -> 1000
end,
ResumeTimeout = case proplists:get_value(resume_timeout, Opts) of
Timeout when is_integer(Timeout), Timeout >= 0 -> Timeout;
@@ -457,14 +453,14 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
false ->
[]
end,
StreamFeatures1 = TLSFeature ++ CompressFeature ++ Mechs,
StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features,
Server, StreamFeatures1, [Server]),
send_element(StateData,
#xmlel{name = <<"stream:features">>,
attrs = [],
children =
TLSFeature ++ CompressFeature ++ Mechs
++
ejabberd_hooks:run_fold(c2s_stream_features,
Server, [], [Server])}),
StreamFeatures}),
fsm_next_state(wait_for_feature_request,
StateData#state{
server = Server,
@@ -489,7 +485,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
false ->
[]
end,
StreamFeatures = [#xmlel{name = <<"bind">>,
StreamFeatures1 = [#xmlel{name = <<"bind">>,
attrs = [{<<"xmlns">>, ?NS_BIND}],
children = []},
#xmlel{name = <<"session">>,
@@ -499,9 +495,9 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
RosterVersioningFeature ++
StreamManagementFeature ++
ejabberd_hooks:run_fold(c2s_post_auth_features,
Server, [], [Server]) ++
ejabberd_hooks:run_fold(c2s_stream_features,
Server, [], [Server]),
StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features,
Server, StreamFeatures1, [Server]),
send_element(StateData,
#xmlel{name = <<"stream:features">>,
attrs = [],
@@ -643,7 +639,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
?INFO_MSG("(~w) Accepted legacy authentication for ~s by ~p from ~s",
[StateData#state.socket,
jlib:jid_to_string(JID), AuthModule,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[true, U, StateData#state.server,
StateData#state.ip]),
@@ -684,7 +680,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
?INFO_MSG("(~w) Failed legacy authentication for ~s from ~s",
[StateData#state.socket,
jlib:jid_to_string(JID),
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[false, U, StateData#state.server,
StateData#state.ip]),
@@ -705,7 +701,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
"for ~s from ~s",
[StateData#state.socket,
jlib:jid_to_string(JID),
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[false, U, StateData#state.server,
StateData#state.ip]),
@@ -760,7 +756,7 @@ wait_for_feature_request({xmlstreamelement, El},
?INFO_MSG("(~w) Accepted authentication for ~s "
"by ~p from ~s",
[StateData#state.socket, U, AuthModule,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[true, U, StateData#state.server,
StateData#state.ip]),
@@ -787,7 +783,7 @@ wait_for_feature_request({xmlstreamelement, El},
?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s",
[StateData#state.socket,
Username, StateData#state.server,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[false, Username, StateData#state.server,
StateData#state.ip]),
@@ -913,7 +909,7 @@ wait_for_sasl_response({xmlstreamelement, El},
?INFO_MSG("(~w) Accepted authentication for ~s "
"by ~p from ~s",
[StateData#state.socket, U, AuthModule,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[true, U, StateData#state.server,
StateData#state.ip]),
@@ -936,7 +932,7 @@ wait_for_sasl_response({xmlstreamelement, El},
?INFO_MSG("(~w) Accepted authentication for ~s "
"by ~p from ~s",
[StateData#state.socket, U, AuthModule,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[true, U, StateData#state.server,
StateData#state.ip]),
@@ -965,7 +961,7 @@ wait_for_sasl_response({xmlstreamelement, El},
?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s",
[StateData#state.socket,
Username, StateData#state.server,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[false, Username, StateData#state.server,
StateData#state.ip]),
@@ -1264,12 +1260,14 @@ session_established2(El, StateData) ->
_ ->
case Name of
<<"presence">> ->
PresenceEl =
PresenceEl0 =
ejabberd_hooks:run_fold(c2s_update_presence,
Server, NewEl,
[User, Server]),
ejabberd_hooks:run(user_send_packet, Server,
[FromJID, ToJID, PresenceEl]),
PresenceEl =
ejabberd_hooks:run_fold(
user_send_packet, Server, PresenceEl0,
[NewStateData, FromJID, ToJID]),
case ToJID of
#jid{user = User, server = Server,
resource = <<"">>} ->
@@ -1289,16 +1287,18 @@ session_established2(El, StateData) ->
process_privacy_iq(FromJID, ToJID, IQ,
NewStateData);
_ ->
ejabberd_hooks:run(user_send_packet, Server,
[FromJID, ToJID, NewEl]),
NewEl0 = ejabberd_hooks:run_fold(
user_send_packet, Server, NewEl,
[NewStateData, FromJID, ToJID]),
check_privacy_route(FromJID, NewStateData,
FromJID, ToJID, NewEl)
FromJID, ToJID, NewEl0)
end;
<<"message">> ->
ejabberd_hooks:run(user_send_packet, Server,
[FromJID, ToJID, NewEl]),
NewEl0 = ejabberd_hooks:run_fold(
user_send_packet, Server, NewEl,
[NewStateData, FromJID, ToJID]),
check_privacy_route(FromJID, NewStateData, FromJID,
ToJID, NewEl);
ToJID, NewEl0);
_ -> NewStateData
end
end,
@@ -1696,11 +1696,13 @@ handle_info({route, From, To,
Attrs2 =
jlib:replace_from_to_attrs(jlib:jid_to_string(From),
jlib:jid_to_string(To), NewAttrs),
FixedPacket = #xmlel{name = Name, attrs = Attrs2, children = Els},
FixedPacket0 = #xmlel{name = Name, attrs = Attrs2, children = Els},
FixedPacket = ejabberd_hooks:run_fold(
user_receive_packet,
NewState#state.server,
FixedPacket0,
[NewState, NewState#state.jid, From, To]),
SentStateData = send_packet(NewState, FixedPacket),
ejabberd_hooks:run(user_receive_packet,
SentStateData#state.server,
[SentStateData#state.jid, From, To, FixedPacket]),
ejabberd_hooks:run(c2s_loop_debug, [{route, From, To, Packet}]),
fsm_next_state(StateName, SentStateData);
true ->
@@ -1891,7 +1893,7 @@ send_text(StateData, Text) when StateData#state.mgmt_state == active ->
case catch (StateData#state.sockmod):send(StateData#state.socket, Text) of
{'EXIT', _} ->
(StateData#state.sockmod):close(StateData#state.socket),
error;
{error, closed};
_ ->
ok
end;
@@ -1912,12 +1914,7 @@ send_stanza(StateData, Stanza) when StateData#state.csi_state == inactive ->
send_stanza(StateData, Stanza) when StateData#state.mgmt_state == pending ->
mgmt_queue_add(StateData, Stanza);
send_stanza(StateData, Stanza) when StateData#state.mgmt_state == active ->
NewStateData = case send_stanza_and_ack_req(StateData, Stanza) of
ok ->
StateData;
error ->
StateData#state{mgmt_state = pending}
end,
NewStateData = send_stanza_and_ack_req(StateData, Stanza),
mgmt_queue_add(NewStateData, Stanza);
send_stanza(StateData, Stanza) ->
send_element(StateData, Stanza),
@@ -2028,6 +2025,7 @@ get_conn_type(StateData) ->
p1_tls -> c2s_compressed_tls
end;
ejabberd_http_bind -> http_bind;
ejabberd_http_ws -> websocket;
_ -> unknown
end.
@@ -2830,11 +2828,12 @@ send_stanza_and_ack_req(StateData, Stanza) ->
AckReq = #xmlel{name = <<"r">>,
attrs = [{<<"xmlns">>, StateData#state.mgmt_xmlns}],
children = []},
case send_element(StateData, Stanza) of
ok ->
send_element(StateData, AckReq);
error ->
error
case send_element(StateData, Stanza) == ok andalso
send_element(StateData, AckReq) == ok of
true ->
StateData;
false ->
StateData#state{mgmt_state = pending}
end.
mgmt_queue_add(StateData, El) ->
@@ -3012,7 +3011,7 @@ inherit_session_state(#state{user = U, server = S} = StateData, ResumeID) ->
end.
resume_session({Time, PID}) ->
(?GEN_FSM):sync_send_all_state_event(PID, {resume_session, Time}, 3000).
(?GEN_FSM):sync_send_all_state_event(PID, {resume_session, Time}, 5000).
make_resume_id(StateData) ->
{Time, _} = StateData#state.sid,
@@ -3126,3 +3125,15 @@ pack_string(String, Pack) ->
transform_listen_option(Opt, Opts) ->
[Opt|Opts].
opt_type(domain_certfile) -> fun iolist_to_binary/1;
opt_type(max_fsm_queue) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(resource_conflict) ->
fun (setresource) -> setresource;
(closeold) -> closeold;
(closenew) -> closenew;
(acceptnew) -> acceptnew
end;
opt_type(_) ->
[domain_certfile, max_fsm_queue, resource_conflict].
+6 -1
View File
@@ -26,9 +26,11 @@
-module(ejabberd_c2s_config).
-behaviour(ejabberd_config).
-author('mremond@process-one.net').
-export([get_c2s_limits/0]).
-export([get_c2s_limits/0, opt_type/1]).
%% Get first c2s configuration limitations to apply it to other c2s
%% connectors.
@@ -63,3 +65,6 @@ select_opts_values([{max_stanza_size, Value} | Opts],
[{max_stanza_size, Value} | SelectedValues]);
select_opts_values([_Opt | Opts], SelectedValues) ->
select_opts_values(Opts, SelectedValues).
opt_type(listen) -> fun (V) -> V end;
opt_type(_) -> [listen].
+16 -1
View File
@@ -25,6 +25,10 @@
-module(ejabberd_captcha).
-behaviour(ejabberd_config).
-protocol({xep, 158, '1.0'}).
-behaviour(gen_server).
%% API
@@ -37,7 +41,7 @@
-export([create_captcha/6, build_captcha_html/2,
check_captcha/2, process_reply/1, process/2,
is_feature_available/0, create_captcha_x/5,
create_captcha_x/6]).
create_captcha_x/6, opt_type/1]).
-include("jlib.hrl").
@@ -693,3 +697,14 @@ clean_treap(Treap, CleanPriority) ->
now_priority() ->
{MSec, Sec, USec} = now(),
-((MSec * 1000000 + Sec) * 1000000 + USec).
opt_type(captcha_cmd) ->
fun (FileName) ->
F = iolist_to_binary(FileName), if F /= <<"">> -> F end
end;
opt_type(captcha_host) -> fun iolist_to_binary/1;
opt_type(captcha_limit) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(listen) -> fun (V) -> V end;
opt_type(_) ->
[captcha_cmd, captcha_host, captcha_limit, listen].
+9
View File
@@ -376,6 +376,15 @@ check_access_commands(AccessCommands, Auth, Method, Command, Arguments) ->
AccessCommandsAllowed =
lists:filter(
fun({Access, Commands, ArgumentRestrictions}) ->
case check_access(Access, Auth) of
true ->
check_access_command(Commands, Command, ArgumentRestrictions,
Method, Arguments);
false ->
false
end;
({Access, Commands}) ->
ArgumentRestrictions = [],
case check_access(Access, Auth) of
true ->
check_access_command(Commands, Command, ArgumentRestrictions,
+122 -16
View File
@@ -36,13 +36,14 @@
prepare_opt_val/4, convert_table_to_binary/5,
transform_options/1, collect_options/1,
convert_to_yaml/1, convert_to_yaml/2,
env_binary_to_list/2]).
env_binary_to_list/2, opt_type/1, may_hide_data/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("ejabberd_config.hrl").
-include_lib("kernel/include/file.hrl").
-callback opt_type(atom()) -> function() | [atom()].
%% @type macro() = {macro_key(), macro_value()}
@@ -65,7 +66,8 @@ start() ->
{attributes, record_info(fields, local_config)}]),
mnesia:add_table_copy(local_config, node(), ram_copies),
Config = get_ejabberd_config_path(),
State = read_file(Config),
State0 = read_file(Config),
State = validate_opts(State0),
%% This start time is used by mod_last:
{MegaSecs, Secs, _} = now(),
UnixTime = MegaSecs*1000000 + Secs,
@@ -114,7 +116,8 @@ get_env_config() ->
%% @spec (File::string()) -> #state{}.
read_file(File) ->
read_file(File, [{replace_macros, true},
{include_files, true}]).
{include_files, true},
{include_modules_configs, true}]).
read_file(File, Opts) ->
Terms1 = get_plain_terms_file(File, Opts),
@@ -200,7 +203,14 @@ get_plain_terms_file(File1, Opts) ->
File = get_absolute_path(File1),
case consult(File) of
{ok, Terms} ->
BinTerms = strings_to_binary(Terms),
BinTerms1 = strings_to_binary(Terms),
ModInc = case proplists:get_bool(include_modules_configs, Opts) of
true ->
filelib:wildcard(ext_mod:modules_dir() ++ "/*/conf/*.{yml,yaml}");
_ ->
[]
end,
BinTerms = BinTerms1 ++ [{include_config_file, list_to_binary(V)} || V <- ModInc],
case proplists:get_bool(include_files, Opts) of
true ->
include_config_files(BinTerms);
@@ -374,7 +384,26 @@ include_config_files(Terms) ->
fun({File, Opts}) ->
include_config_file(File, Opts)
end, lists:flatten(FileOpts)),
Terms1 ++ Terms2.
SpecialTerms = dict:from_list([{hosts, []}, {listen, []}, {modules, []}]),
PartDict = dict:store(rest, [], SpecialTerms),
Partition = fun(L) ->
lists:foldr(fun({Name, Val} = Pair, Dict) ->
case dict:find(Name, SpecialTerms) of
{ok, _} ->
dict:append_list(Name, Val, Dict);
_ ->
dict:append(rest, Pair, Dict)
end;
(Tuple, Dict2) ->
dict:append(rest, Tuple, Dict2)
end, PartDict, L)
end,
Merged = dict:merge(fun(_Name, V1, V2) -> V1 ++ V2 end,
Partition(Terms1), Partition(Terms2)),
Rest = dict:fetch(rest, Merged),
dict:to_list(dict:erase(rest, Merged)) ++ Rest.
transform_include_option({include_config_file, File}) when is_list(File) ->
case is_string(File) of
@@ -452,11 +481,11 @@ split_terms_macros(Terms) ->
lists:foldl(
fun(Term, {TOs, Ms}) ->
case Term of
{define_macro, Key, Value} ->
{define_macro, Key, Value} ->
case is_correct_macro({Key, Value}) of
true ->
true ->
{TOs, Ms++[{Key, Value}]};
false ->
false ->
exit({macro_not_properly_defined, Term})
end;
{define_macro, KeyVals} ->
@@ -686,6 +715,45 @@ get_option(Opt, F, Default) ->
end
end.
get_modules_with_options() ->
{ok, Mods} = application:get_key(ejabberd, modules),
lists:foldl(
fun(Mod, D) ->
case catch Mod:opt_type('') of
Opts when is_list(Opts) ->
lists:foldl(
fun(Opt, Acc) ->
dict:append(Opt, Mod, Acc)
end, D, Opts);
{'EXIT', {undef, _}} ->
D
end
end, dict:new(), [?MODULE|Mods]).
validate_opts(#state{opts = Opts} = State) ->
ModOpts = get_modules_with_options(),
NewOpts = lists:filter(
fun(#local_config{key = {Opt, _Host}, value = Val}) ->
case dict:find(Opt, ModOpts) of
{ok, [Mod|_]} ->
VFun = Mod:opt_type(Opt),
case catch VFun(Val) of
{'EXIT', _} ->
?ERROR_MSG("ignoring option '~s' with "
"invalid value: ~p",
[Opt, Val]),
false;
_ ->
true
end;
_ ->
?ERROR_MSG("unknown option '~s' will be likely"
" ignored", [Opt]),
true
end
end, Opts),
State#state{opts = NewOpts}.
-spec get_vh_by_auth_method(atom()) -> [binary()].
%% Return the list of hosts handled by a given module
@@ -745,14 +813,24 @@ replace_module(Module) ->
false -> Module
end.
replace_modules(Modules) -> lists:map( fun({Module, Opts}) -> case
replace_module(Module) of {NewModule, DBType} ->
emit_deprecation_warning(Module, NewModule, DBType), NewOpts =
[{db_type, DBType} | lists:keydelete(db_type, 1, Opts)],
{NewModule, transform_module_options(Module, NewOpts)}; NewModule
-> if Module /= NewModule -> emit_deprecation_warning(Module,
NewModule); true -> ok end, {NewModule,
transform_module_options(Module, Opts)} end end, Modules).
replace_modules(Modules) ->
lists:map(
fun({Module, Opts}) ->
case replace_module(Module) of
{NewModule, DBType} ->
emit_deprecation_warning(Module, NewModule, DBType),
NewOpts = [{db_type, DBType} |
lists:keydelete(db_type, 1, Opts)],
{NewModule, transform_module_options(Module, NewOpts)};
NewModule ->
if Module /= NewModule ->
emit_deprecation_warning(Module, NewModule);
true ->
ok
end,
{NewModule, transform_module_options(Module, Opts)}
end
end, Modules).
%% Elixir module naming
%% ====================
@@ -1062,3 +1140,31 @@ emit_deprecation_warning(Module, NewModule) ->
?WARNING_MSG("Module ~s is deprecated, use ~s instead",
[Module, NewModule])
end.
opt_type(hosts) ->
fun(L) when is_list(L) ->
lists:map(
fun(H) ->
iolist_to_binary(H)
end, L)
end;
opt_type(language) ->
fun iolist_to_binary/1;
opt_type(_) ->
[hosts, language].
-spec may_hide_data(string()) -> string();
(binary()) -> binary().
may_hide_data(Data) ->
case ejabberd_config:get_option(
hide_sensitive_log_data,
fun(false) -> false;
(true) -> true
end,
false) of
false ->
Data;
true ->
"hidden_by_ejabberd"
end.
+18 -6
View File
@@ -44,14 +44,13 @@
-module(ejabberd_ctl).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-export([start/0,
init/0,
process/1,
process2/2,
register_commands/3,
unregister_commands/3]).
-export([start/0, init/0, process/1, process2/2,
register_commands/3, unregister_commands/3,
opt_type/1]).
-include("ejabberd_ctl.hrl").
-include("ejabberd_commands.hrl").
@@ -353,6 +352,15 @@ format_result(String, {_Name, string}) when is_list(String) ->
format_result(Binary, {_Name, string}) when is_binary(Binary) ->
io_lib:format("~s", [binary_to_list(Binary)]);
format_result(Atom, {_Name, string}) when is_atom(Atom) ->
io_lib:format("~s", [atom_to_list(Atom)]);
format_result(Integer, {_Name, string}) when is_integer(Integer) ->
io_lib:format("~s", [integer_to_list(Integer)]);
format_result(Other, {_Name, string}) ->
io_lib:format("~p", [Other]);
format_result(Code, {_Name, rescode}) ->
make_status(Code);
@@ -792,3 +800,7 @@ print(Format, Args) ->
%%format_usage_xmlrpc(ArgsDef, ResultDef) ->
%% ["aaaa bbb ccc"].
opt_type(ejabberdctl_access_commands) ->
fun (V) when is_list(V) -> V end;
opt_type(_) -> [ejabberdctl_access_commands].
+8 -2
View File
@@ -25,6 +25,8 @@
-module(ejabberd_http).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
%% External exports
@@ -32,8 +34,7 @@
socket_type/0, receive_headers/1, url_encode/1,
transform_listen_option/2]).
%% Callbacks
-export([init/2]).
-export([init/2, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -95,6 +96,7 @@ init({SockMod, Socket}, Opts) ->
TLSEnabled = proplists:get_bool(tls, Opts),
TLSOpts1 = lists:filter(fun ({certfile, _}) -> true;
({ciphers, _}) -> true;
({dhfile, _}) -> true;
(_) -> false
end,
Opts),
@@ -870,3 +872,7 @@ transform_listen_option({request_handlers, Hs}, Opts) ->
[{request_handlers, Hs1} | Opts];
transform_listen_option(Opt, Opts) ->
[Opt|Opts].
opt_type(trusted_proxies) ->
fun (TPs) -> [iolist_to_binary(TP) || TP <- TPs] end;
opt_type(_) -> [trusted_proxies].
+3
View File
@@ -10,6 +10,9 @@
-module(ejabberd_http_bind).
-protocol({xep, 124, '1.11'}).
-protocol({xep, 206, '1.4'}).
-behaviour(gen_fsm).
%% External exports
+12 -4
View File
@@ -24,16 +24,17 @@
%%%----------------------------------------------------------------------
-module(ejabberd_http_ws).
-behaviour(ejabberd_config).
-author('ecestari@process-one.net').
-behaviour(gen_fsm).
% External exports
-export([start/1, start_link/1, init/1, handle_event/3,
handle_sync_event/4, code_change/4, handle_info/3,
terminate/3, send_xml/2, setopts/2, sockname/1, peername/1,
controlling_process/2, become_controller/2, close/1,
socket_handoff/6]).
terminate/3, send_xml/2, setopts/2, sockname/1,
peername/1, controlling_process/2, become_controller/2,
close/1, socket_handoff/6, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -353,3 +354,10 @@ parsed_items(List) ->
after 0 ->
lists:reverse(List)
end.
opt_type(websocket_ping_interval) ->
fun (I) when is_integer(I), I >= 0 -> I end;
opt_type(websocket_timeout) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(_) ->
[websocket_ping_interval, websocket_timeout].
+11 -13
View File
@@ -24,20 +24,15 @@
%%%----------------------------------------------------------------------
-module(ejabberd_listener).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-export([start_link/0, init/1, start/3,
init/3,
start_listeners/0,
start_listener/3,
stop_listeners/0,
stop_listener/2,
parse_listener_portip/2,
add_listener/3,
delete_listener/2,
transform_options/1,
validate_cfg/1
]).
-export([start_link/0, init/1, start/3, init/3,
start_listeners/0, start_listener/3, stop_listeners/0,
stop_listener/2, parse_listener_portip/2,
add_listener/3, delete_listener/2, transform_options/1,
validate_cfg/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -302,7 +297,7 @@ accept(ListenSocket, Module, Opts) ->
case {inet:sockname(Socket), inet:peername(Socket)} of
{{ok, {Addr, Port}}, {ok, {PAddr, PPort}}} ->
?INFO_MSG("(~w) Accepted connection ~s:~p -> ~s:~p",
[Socket, inet_parse:ntoa(PAddr), PPort,
[Socket, ejabberd_config:may_hide_data(inet_parse:ntoa(PAddr)), PPort,
inet_parse:ntoa(Addr), Port]);
_ ->
ok
@@ -660,3 +655,6 @@ prepare_mod(sip) ->
esip_socket;
prepare_mod(Mod) when is_atom(Mod) ->
Mod.
opt_type(listen) -> fun validate_cfg/1;
opt_type(_) -> [listen].
+14 -1
View File
@@ -25,8 +25,10 @@
%%%-------------------------------------------------------------------
-module(ejabberd_logger).
-behaviour(ejabberd_config).
%% API
-export([start/0, reopen_log/0, get/0, set/1, get_log_path/0]).
-export([start/0, reopen_log/0, get/0, set/1, get_log_path/0, opt_type/1]).
-include("ejabberd.hrl").
@@ -61,6 +63,17 @@ get_log_path() ->
end
end.
opt_type(log_rotate_date) ->
fun(S) -> binary_to_list(iolist_to_binary(S)) end;
opt_type(log_rotate_size) ->
fun(I) when is_integer(I), I >= 0 -> I end;
opt_type(log_rotate_count) ->
fun(I) when is_integer(I), I >= 0 -> I end;
opt_type(log_rate_limit) ->
fun(I) when is_integer(I), I >= 0 -> I end;
opt_type(_) ->
[log_rotate_date, log_rotate_size, log_rotate_count, log_rate_limit].
-ifdef(LAGER).
get_integer_env(Name, Default) ->
+11 -3
View File
@@ -24,6 +24,8 @@
%%%----------------------------------------------------------------------
-module(ejabberd_node_groups).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(gen_server).
@@ -35,9 +37,8 @@
get_members/1,
get_closest_node/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3, opt_type/1]).
-define(PG2, pg2).
@@ -163,3 +164,10 @@ code_change(_OldVsn, State, _Extra) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
opt_type(node_type) ->
fun (frontend) -> frontend;
(backend) -> backend;
(generic) -> generic
end;
opt_type(_) -> [node_type].
+30 -5
View File
@@ -25,6 +25,8 @@
-module(ejabberd_odbc).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-define(GEN_FSM, p1_fsm).
@@ -51,9 +53,9 @@
handle_info/3, terminate/3, print_state/1,
code_change/4]).
%% gen_fsm states
-export([connecting/2, connecting/3,
session_established/2, session_established/3]).
session_established/2, session_established/3,
opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -193,7 +195,8 @@ to_bool(_) -> false.
encode_term(Term) ->
escape(list_to_binary(
erl_prettypr:format(erl_syntax:abstract(Term)))).
erl_prettypr:format(erl_syntax:abstract(Term),
[{paper, 65535}, {ribbon, 65535}]))).
decode_term(Bin) ->
Str = binary_to_list(<<Bin/binary, ".">>),
@@ -509,7 +512,8 @@ abort_on_driver_error(Reply, From) ->
%% Open an ODBC database connection
odbc_connect(SQLServer) ->
ejabberd:start_app(odbc),
odbc:connect(binary_to_list(SQLServer), [{scrollable_cursors, off}]).
odbc:connect(binary_to_list(SQLServer), [{scrollable_cursors, off},
{binary_strings, on}]).
%% == Native SQLite code
@@ -634,7 +638,7 @@ mysql_item_to_odbc(Columns, Recs) ->
{selected, [element(2, Column) || Column <- Columns], Recs}.
to_odbc({selected, Columns, Recs}) ->
{selected, Columns, [tuple_to_list(Rec) || Rec <- Recs]};
{selected, [list_to_binary(Column) || Column <- Columns], [tuple_to_list(Rec) || Rec <- Recs]};
to_odbc(Res) ->
Res.
@@ -690,3 +694,24 @@ fsm_limit_opts() ->
N when is_integer(N) -> [{max_queue, N}];
_ -> []
end.
opt_type(max_fsm_queue) ->
fun (N) when is_integer(N), N > 0 -> N end;
opt_type(odbc_database) -> fun iolist_to_binary/1;
opt_type(odbc_keepalive_interval) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(odbc_password) -> fun iolist_to_binary/1;
opt_type(odbc_port) ->
fun (P) when is_integer(P), P > 0, P < 65536 -> P end;
opt_type(odbc_server) -> fun iolist_to_binary/1;
opt_type(odbc_type) ->
fun (mysql) -> mysql;
(pgsql) -> pgsql;
(sqlite) -> sqlite;
(odbc) -> odbc
end;
opt_type(odbc_username) -> fun iolist_to_binary/1;
opt_type(_) ->
[max_fsm_queue, odbc_database, odbc_keepalive_interval,
odbc_password, odbc_port, odbc_server, odbc_type,
odbc_username].
+17 -2
View File
@@ -25,11 +25,13 @@
-module(ejabberd_odbc_sup).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
%% API
-export([start_link/1, init/1, add_pid/2, remove_pid/2,
get_pids/1, get_random_pid/1, transform_options/1]).
get_pids/1, get_random_pid/1, transform_options/1,
opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -205,3 +207,16 @@ read_lines(Fd, File, Acc) ->
?ERROR_MSG("Failed read from lite.sql, reason: ~p", [Err]),
[]
end.
opt_type(odbc_pool_size) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(odbc_start_interval) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(odbc_type) ->
fun (mysql) -> mysql;
(pgsql) -> pgsql;
(sqlite) -> sqlite;
(odbc) -> odbc
end;
opt_type(_) ->
[odbc_pool_size, odbc_start_interval, odbc_type].
+9 -2
View File
@@ -38,8 +38,12 @@
-module(ejabberd_piefxis).
%% API
-export([import_file/1, export_server/1, export_host/2]).
-behaviour(ejabberd_config).
-protocol({xep, 227, '1.0'}).
-export([import_file/1, export_server/1, export_host/2,
opt_type/1]).
-define(CHUNK_SIZE, 1024*20). %20k
@@ -735,3 +739,6 @@ print(Fd, String) ->
%%%==================================
%%% vim: set filetype=erlang tabstop=8 foldmarker=%%%%,%%%= foldmethod=marker:
file:write(Fd, String).
opt_type(auth_password_format) -> fun (X) -> X end;
opt_type(_) -> [auth_password_format].
+11 -1
View File
@@ -25,9 +25,11 @@
-module(ejabberd_rdbms).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-export([start/0]).
-export([start/0, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -83,3 +85,11 @@ needs_odbc(Host) ->
odbc -> {true, odbc};
undefined -> false
end.
opt_type(odbc_type) ->
fun (mysql) -> mysql;
(pgsql) -> pgsql;
(sqlite) -> sqlite;
(odbc) -> odbc
end;
opt_type(_) -> [odbc_type].
+16 -9
View File
@@ -24,17 +24,13 @@
%%%----------------------------------------------------------------------
-module(ejabberd_riak_sup).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
%% API
-export([start/0,
start_link/0,
init/1,
get_pids/0,
transform_options/1,
get_random_pid/0,
get_random_pid/1
]).
-export([start/0, start_link/0, init/1, get_pids/0,
transform_options/1, get_random_pid/0, get_random_pid/1,
opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -158,3 +154,14 @@ transform_options({riak_server, {S, P}}, Opts) ->
[{riak_server, S}, {riak_port, P}|Opts];
transform_options(Opt, Opts) ->
[Opt|Opts].
opt_type(modules) -> fun (L) when is_list(L) -> L end;
opt_type(riak_pool_size) ->
fun (N) when is_integer(N), N >= 1 -> N end;
opt_type(riak_port) -> fun (_) -> true end;
opt_type(riak_server) -> fun (_) -> true end;
opt_type(riak_start_interval) ->
fun (N) when is_integer(N), N >= 1 -> N end;
opt_type(_) ->
[modules, riak_pool_size, riak_port, riak_server,
riak_start_interval].
+7 -2
View File
@@ -25,6 +25,8 @@
-module(ejabberd_router).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(gen_server).
@@ -43,9 +45,8 @@
-export([start_link/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3]).
handle_info/2, terminate/2, code_change/3, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -406,3 +407,7 @@ update_tables() ->
false -> ok
end.
opt_type(domain_balancing_component_number) ->
fun (N) when is_integer(N), N > 1 -> N end;
opt_type(_) -> [domain_balancing_component_number].
+11 -7
View File
@@ -202,14 +202,18 @@ do_route(From, Domain, Destinations, Packet) ->
%% If no multicast service is available in this server, send manually
[] -> do_route_normal(From, Destinations, Packet);
%% If available, send the packet using multicast service
[R] ->
case R#route_multicast.pid of
Pid when is_pid(Pid) ->
Pid ! {route_trusted, From, Destinations, Packet};
_ -> do_route_normal(From, Destinations, Packet)
end
%% If some is available, send the packet using multicast service
Rs when is_list(Rs) ->
Pid = pick_multicast_pid(Rs),
Pid ! {route_trusted, From, Destinations, Packet}
end.
pick_multicast_pid(Rs) ->
List = case [R || R <- Rs, node(R#route_multicast.pid) == node()] of
[] -> Rs;
RLocals -> RLocals
end,
(hd(List))#route_multicast.pid.
do_route_normal(From, Destinations, Packet) ->
[ejabberd_router:route(From, To, Packet) || To <- Destinations].
+14 -2
View File
@@ -25,6 +25,10 @@
-module(ejabberd_s2s).
-protocol({xep, 220, '1.1'}).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(gen_server).
@@ -44,8 +48,8 @@
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3]).
%% ejabberd API
-export([get_info_s2s_connections/1, transform_options/1]).
-export([get_info_s2s_connections/1,
transform_options/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -771,3 +775,11 @@ match_labels([DL | DLabels], [PL | PLabels]) ->
end;
false -> false
end.
opt_type(route_subdomains) ->
fun (s2s) -> s2s;
(local) -> local
end;
opt_type(s2s_access) ->
fun (A) when is_atom(A) -> A end;
opt_type(_) -> [route_subdomains, s2s_access].
+39 -4
View File
@@ -25,6 +25,8 @@
-module(ejabberd_s2s_in).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(p1_fsm).
@@ -32,11 +34,10 @@
%% External exports
-export([start/2, start_link/2, socket_type/0]).
%% gen_fsm callbacks
-export([init/1, wait_for_stream/2,
wait_for_feature_request/2, stream_established/2,
handle_event/3, handle_sync_event/4, code_change/4,
handle_info/3, print_state/1, terminate/3]).
handle_info/3, print_state/1, terminate/3, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -184,9 +185,14 @@ init([{SockMod, Socket}, Opts]) ->
undefined -> TLSOpts2;
ProtocolOpts -> [{protocol_options, ProtocolOpts} | TLSOpts2]
end,
TLSOpts4 = case ejabberd_config:get_option(
s2s_dhfile, fun iolist_to_binary/1) of
undefined -> TLSOpts3;
DHFile -> [{dhfile, DHFile} | TLSOpts3]
end,
TLSOpts = case proplists:get_bool(tls_compression, Opts) of
false -> [compression_none | TLSOpts3];
true -> TLSOpts3
false -> [compression_none | TLSOpts4];
true -> TLSOpts4
end,
Timer = erlang:start_timer(?S2STIMEOUT, self(), []),
{ok, wait_for_stream,
@@ -710,3 +716,32 @@ fsm_limit_opts(Opts) ->
N -> [{max_queue, N}]
end
end.
opt_type(domain_certfile) -> fun iolist_to_binary/1;
opt_type(max_fsm_queue) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(s2s_certfile) -> fun iolist_to_binary/1;
opt_type(s2s_ciphers) -> fun iolist_to_binary/1;
opt_type(s2s_dhfile) -> fun iolist_to_binary/1;
opt_type(s2s_protocol_options) ->
fun (Options) ->
[_ | O] = lists:foldl(fun (X, Acc) -> X ++ Acc end, [],
[["|" | binary_to_list(Opt)]
|| Opt <- Options, is_binary(Opt)]),
iolist_to_binary(O)
end;
opt_type(s2s_tls_compression) ->
fun (true) -> true;
(false) -> false
end;
opt_type(s2s_use_starttls) ->
fun (false) -> false;
(true) -> true;
(optional) -> optional;
(required) -> required;
(required_trusted) -> required_trusted
end;
opt_type(_) ->
[domain_certfile, max_fsm_queue, s2s_certfile,
s2s_ciphers, s2s_dhfile, s2s_protocol_options,
s2s_tls_compression, s2s_use_starttls].
+69 -22
View File
@@ -25,6 +25,8 @@
-module(ejabberd_s2s_out).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(p1_fsm).
@@ -37,26 +39,14 @@
stop_connection/1,
transform_options/1]).
%% p1_fsm callbacks (same as gen_fsm)
-export([init/1,
open_socket/2,
wait_for_stream/2,
wait_for_validation/2,
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,
handle_event/3,
handle_sync_event/4,
handle_info/3,
terminate/3,
print_state/1,
code_change/4,
test_get_addr_port/1,
get_addr_port/1]).
-export([init/1, open_socket/2, wait_for_stream/2,
wait_for_validation/2, 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, handle_event/3,
handle_sync_event/4, handle_info/3, terminate/3,
print_state/1, code_change/4, test_get_addr_port/1,
get_addr_port/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -207,13 +197,18 @@ init([From, Server, Type]) ->
undefined -> TLSOpts2;
ProtocolOpts -> [{protocol_options, ProtocolOpts} | TLSOpts2]
end,
TLSOpts4 = case ejabberd_config:get_option(
s2s_dhfile, fun iolist_to_binary/1) of
undefined -> TLSOpts3;
DHFile -> [{dhfile, DHFile} | TLSOpts3]
end,
TLSOpts = case ejabberd_config:get_option(
{s2s_tls_compression, From},
fun(true) -> true;
(false) -> false
end, true) of
false -> [compression_none | TLSOpts3];
true -> TLSOpts3
false -> [compression_none | TLSOpts4];
true -> TLSOpts4
end,
{New, Verify} = case Type of
{new, Key} -> {Key, false};
@@ -1365,3 +1360,55 @@ fsm_limit_opts() ->
undefined -> [];
N -> [{max_queue, N}]
end.
opt_type(domain_certfile) -> fun iolist_to_binary/1;
opt_type(max_fsm_queue) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(outgoing_s2s_families) ->
fun (Families) ->
true = lists:all(fun (ipv4) -> true;
(ipv6) -> true
end,
Families),
Families
end;
opt_type(outgoing_s2s_port) ->
fun (I) when is_integer(I), I > 0, I =< 65536 -> I end;
opt_type(outgoing_s2s_timeout) ->
fun (TimeOut) when is_integer(TimeOut), TimeOut > 0 ->
TimeOut;
(infinity) -> infinity
end;
opt_type(s2s_certfile) -> fun iolist_to_binary/1;
opt_type(s2s_ciphers) -> fun iolist_to_binary/1;
opt_type(s2s_dhfile) -> fun iolist_to_binary/1;
opt_type(s2s_dns_retries) ->
fun (I) when is_integer(I), I >= 0 -> I end;
opt_type(s2s_dns_timeout) ->
fun (I) when is_integer(I), I >= 0 -> I end;
opt_type(s2s_max_retry_delay) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(s2s_protocol_options) ->
fun (Options) ->
[_ | O] = lists:foldl(fun (X, Acc) -> X ++ Acc end, [],
[["|" | binary_to_list(Opt)]
|| Opt <- Options, is_binary(Opt)]),
iolist_to_binary(O)
end;
opt_type(s2s_tls_compression) ->
fun (true) -> true;
(false) -> false
end;
opt_type(s2s_use_starttls) ->
fun (true) -> true;
(false) -> false;
(optional) -> optional;
(required) -> required;
(required_trusted) -> required_trusted
end;
opt_type(_) ->
[domain_certfile, max_fsm_queue, outgoing_s2s_families,
outgoing_s2s_port, outgoing_s2s_timeout, s2s_certfile,
s2s_ciphers, s2s_dhfile, s2s_dns_retries, s2s_dns_timeout,
s2s_max_retry_delay, s2s_protocol_options,
s2s_tls_compression, s2s_use_starttls].
+9 -2
View File
@@ -25,8 +25,12 @@
-module(ejabberd_service).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-protocol({xep, 114, '1.6'}).
-define(GEN_FSM, p1_fsm).
-behaviour(?GEN_FSM).
@@ -35,11 +39,10 @@
-export([start/2, start_link/2, send_text/2,
send_element/2, socket_type/0, transform_listen_option/2]).
%% gen_fsm callbacks
-export([init/1, wait_for_stream/2,
wait_for_handshake/2, stream_established/2,
handle_event/3, handle_sync_event/4, code_change/4,
handle_info/3, terminate/3, print_state/1]).
handle_info/3, terminate/3, print_state/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -402,3 +405,7 @@ fsm_limit_opts(Opts) ->
N -> [{max_queue, N}]
end
end.
opt_type(max_fsm_queue) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(_) -> [max_fsm_queue].
+13 -2
View File
@@ -25,6 +25,8 @@
-module(ejabberd_sm).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(gen_server).
@@ -64,9 +66,8 @@
is_existing_resource/3
]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3]).
handle_info/2, terminate/2, code_change/3, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -539,6 +540,8 @@ do_route(From, To, #xmlel{} = Packet) ->
<<"message">> ->
case xml:get_attr_s(<<"type">>, Attrs) of
<<"chat">> -> route_message(From, To, Packet, chat);
<<"normal">> -> route_message(From, To, Packet, normal);
<<"">> -> route_message(From, To, Packet, normal);
<<"error">> -> ok;
_ ->
Err = jlib:make_error_reply(Packet,
@@ -803,3 +806,11 @@ kick_user(User, Server) ->
PID ! kick
end, Resources),
length(Resources).
opt_type(sm_db_type) ->
fun (mnesia) -> mnesia;
(internal) -> mnesia;
(odbc) -> odbc;
(redis) -> redis
end;
opt_type(_) -> [sm_db_type].
+19 -8
View File
@@ -8,16 +8,13 @@
%%%-------------------------------------------------------------------
-module(ejabberd_sm_redis).
-behaviour(ejabberd_config).
-behaviour(ejabberd_sm).
%% API
-export([init/0,
set_session/1,
delete_session/4,
get_sessions/0,
get_sessions/1,
get_sessions/2,
get_sessions/3]).
-export([init/0, set_session/1, delete_session/4,
get_sessions/0, get_sessions/1, get_sessions/2,
get_sessions/3, opt_type/1]).
-include("ejabberd.hrl").
-include("ejabberd_sm.hrl").
@@ -207,3 +204,17 @@ clean_table() ->
"server ~s: ~p", [LServer, Err])
end
end, ?MYHOSTS).
opt_type(redis_connect_timeout) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(redis_db) ->
fun (I) when is_integer(I), I >= 0 -> I end;
opt_type(redis_password) -> fun iolist_to_list/1;
opt_type(redis_port) ->
fun (P) when is_integer(P), P > 0, P < 65536 -> P end;
opt_type(redis_reconnect_timeout) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(redis_server) -> fun iolist_to_list/1;
opt_type(_) ->
[redis_connect_timeout, redis_db, redis_password,
redis_port, redis_reconnect_timeout, redis_server].
+5 -2
View File
@@ -25,8 +25,11 @@
%%%-------------------------------------------------------------------
-module(ejabberd_stun).
%% API
-export([tcp_init/2, udp_init/2, udp_recv/5, start/2, socket_type/0]).
-protocol({rfc, 5766}).
-protocol({xep, 176, '1.0'}).
-export([tcp_init/2, udp_init/2, udp_recv/5, start/2,
socket_type/0]).
-include("ejabberd.hrl").
-include("logger.hrl").
+12 -2
View File
@@ -25,6 +25,8 @@
-module(ejabberd_system_monitor).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(gen_server).
@@ -33,9 +35,8 @@
-export([start_link/0, process_command/3,
process_remote_command/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3]).
handle_info/2, terminate/2, code_change/3, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -331,3 +332,12 @@ process_remote_command([setlh, NewValue]) ->
io_lib:format("Result of set large heap: ~p --> ~p",
[OldLH, NewLH]);
process_remote_command(_) -> throw(unknown_command).
opt_type(watchdog_admins) ->
fun (JIDs) ->
[jlib:jid_tolower(jlib:string_to_jid(iolist_to_binary(S)))
|| S <- JIDs]
end;
opt_type(watchdog_large_heap) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(_) -> [watchdog_admins, watchdog_large_heap].
+54 -39
View File
@@ -27,12 +27,13 @@
-module(ejabberd_web_admin).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
%% External exports
-export([process/2, list_users/4,
list_users_in_diapason/4, pretty_print_xml/1,
term_to_id/1]).
term_to_id/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -166,15 +167,15 @@ process([<<"doc">>, LocalFile], _Request) ->
?DEBUG("Delivering content.", []),
{200, [{<<"Server">>, <<"ejabberd">>}], FileContents};
{error, Error} ->
?DEBUG("Delivering error: ~p", [Error]),
Help = <<" ", FileName/binary,
" - Try to specify the path to ejabberd "
"documentation with the environment variable "
"EJABBERD_DOC_PATH. Check the ejabberd "
"Guide for more information.">>,
?INFO_MSG("Problem '~p' accessing the local Guide file ~s", [Error, Help]),
case Error of
eacces -> {403, [], <<"Forbidden", Help/binary>>};
enoent -> {404, [], <<"Not found", Help/binary>>};
enoent -> {307, [{<<"Location">>, <<"http://docs.ejabberd.im/admin/guide/configuration/">>}], <<"Not found", Help/binary>>};
_Else ->
{404, [], <<(iolist_to_binary(atom_to_list(Error)))/binary, Help/binary>>}
end
@@ -202,7 +203,7 @@ process([<<"server">>, SHost | RPath] = Path,
{unauthorized, Error} ->
{BadUser, _BadPass} = Auth,
{IPT, _Port} = Request#request.ip,
IPS = jlib:ip_to_list(IPT),
IPS = ejabberd_config:may_hide_data(jlib:ip_to_list(IPT)),
?WARNING_MSG("Access of ~p from ~p failed with error: ~p",
[BadUser, IPS, Error]),
{401,
@@ -234,7 +235,7 @@ process(RPath,
{unauthorized, Error} ->
{BadUser, _BadPass} = Auth,
{IPT, _Port} = Request#request.ip,
IPS = jlib:ip_to_list(IPT),
IPS = ejabberd_config:may_hide_data(jlib:ip_to_list(IPT)),
?WARNING_MSG("Access of ~p from ~p failed with error: ~p",
[BadUser, IPS, Error]),
{401,
@@ -295,7 +296,7 @@ make_xhtml(Els, Host, Node, Lang, JID) ->
#xmlel{name = <<"html">>,
attrs =
[{<<"xmlns">>, <<"http://www.w3.org/1999/xhtml">>},
{<<"xml:lang">>, Lang}, {<<"lang">>, Lang}],
{<<"xml:lang">>, Lang}, {<<"lang">>, Lang}]++direction(Lang),
children =
[#xmlel{name = <<"head">>, attrs = [],
children =
@@ -339,8 +340,15 @@ make_xhtml(Els, Host, Node, Lang, JID) ->
[{xmlcdata, <<"">>}])]),
?XAE(<<"div">>, [{<<"id">>, <<"copyrightouter">>}],
[?XAE(<<"div">>, [{<<"id">>, <<"copyright">>}],
[?XC(<<"p">>,
<<"ejabberd (c) 2002-2015 ProcessOne">>)])])])]}}.
[?XE(<<"p">>,
[?AC(<<"https://www.ejabberd.im/">>, <<"ejabberd">>),
?C(<<" (c) 2002-2015 ">>),
?AC(<<"https://www.process-one.net/">>, <<"ProcessOne">>)]
)])])])]}}.
direction(ltr) -> [{<<"dir">>, <<"ltr">>}];
direction(<<"he">>) -> [{<<"dir">>, <<"rtl">>}];
direction(_) -> [].
get_base_path(global, cluster) -> <<"/admin/">>;
get_base_path(Host, cluster) ->
@@ -509,7 +517,7 @@ css(Host) ->
"0px;\n}\n\nh3 {\n color: #000044;\n "
" font-family: Verdana, Arial, Helvetica, "
"sans-serif; \n font-size: 10pt;\n "
"font-weight: bold;\n text-align: left;\n "
"font-weight: bold;\n "
" padding-top: 20px;\n padding-bottom: "
"2px;\n margin-top: 0px;\n margin-bottom: "
"0px;\n}\n\n#content a:link {\n color: "
@@ -589,7 +597,7 @@ logo_fill() ->
process_admin(global,
#request{path = [], auth = {_, _, AJID},
lang = Lang}) ->
make_xhtml((?H1GL((?T(<<"Administration">>)), <<"toc">>,
make_xhtml((?H1GL((?T(<<"Administration">>)), <<"">>,
<<"Contents">>))
++
[?XE(<<"ul">>,
@@ -658,7 +666,7 @@ process_admin(Host,
[{{acl, '$1', '$2'}}]}])),
{NumLines, ACLsP} = term_to_paragraph(ACLs, 80),
make_xhtml((?H1GL((?T(<<"Access Control Lists">>)),
<<"ACLDefinition">>, <<"ACL Definition">>))
<<"acl-definition">>, <<"ACL Definition">>))
++
case Res of
ok -> [?XREST(<<"Submitted">>)];
@@ -667,7 +675,7 @@ process_admin(Host,
end
++
[?XAE(<<"form">>,
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}],
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr),
[?TEXTAREA(<<"acls">>,
(iolist_to_binary(integer_to_list(lists:max([16,
NumLines])))),
@@ -694,7 +702,7 @@ process_admin(Host,
[{{acl, {'$1', Host}, '$2'}, [],
[{{acl, '$1', '$2'}}]}])),
make_xhtml((?H1GL((?T(<<"Access Control Lists">>)),
<<"ACLDefinition">>, <<"ACL Definition">>))
<<"acl-definition">>, <<"ACL Definition">>))
++
case Res of
ok -> [?XREST(<<"Submitted">>)];
@@ -702,9 +710,9 @@ process_admin(Host,
nothing -> []
end
++
[?XE(<<"p">>, [?ACT(<<"../acls-raw/">>, <<"Raw">>)])] ++
[?XAE(<<"p">>, direction(ltr), [?ACT(<<"../acls-raw/">>, <<"Raw">>)])] ++
[?XAE(<<"form">>,
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}],
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr),
[acls_to_xhtml(ACLs), ?BR,
?INPUTT(<<"submit">>, <<"delete">>,
<<"Delete Selected">>),
@@ -760,7 +768,7 @@ process_admin(Host,
[{{access, '$1', '$2'}}]}]),
{NumLines, AccessP} = term_to_paragraph(lists:keysort(2,Access), 80),
make_xhtml((?H1GL((?T(<<"Access Rules">>)),
<<"AccessRights">>, <<"Access Rights">>))
<<"access-rights">>, <<"Access Rights">>))
++
case Res of
ok -> [?XREST(<<"Submitted">>)];
@@ -769,7 +777,7 @@ process_admin(Host,
end
++
[?XAE(<<"form">>,
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}],
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr),
[?TEXTAREA(<<"access">>,
(iolist_to_binary(integer_to_list(lists:max([16,
NumLines])))),
@@ -793,7 +801,7 @@ process_admin(Host,
[{{access, {'$1', Host}, '$2'}, [],
[{{access, '$1', '$2'}}]}]),
make_xhtml((?H1GL((?T(<<"Access Rules">>)),
<<"AccessRights">>, <<"Access Rights">>))
<<"access-rights">>, <<"Access Rights">>))
++
case Res of
ok -> [?XREST(<<"Submitted">>)];
@@ -801,10 +809,10 @@ process_admin(Host,
nothing -> []
end
++
[?XE(<<"p">>, [?ACT(<<"../access-raw/">>, <<"Raw">>)])]
[?XAE(<<"p">>, direction(ltr), [?ACT(<<"../access-raw/">>, <<"Raw">>)])]
++
[?XAE(<<"form">>,
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}],
[{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr),
[access_rules_to_xhtml(AccessRules, Lang), ?BR,
?INPUTT(<<"submit">>, <<"delete">>,
<<"Delete Selected">>)])],
@@ -852,7 +860,7 @@ process_admin(global,
lang = Lang}) ->
Res = list_vhosts(Lang, AJID),
make_xhtml((?H1GL((?T(<<"Virtual Hosts">>)),
<<"virtualhost">>, <<"Virtual Hosting">>))
<<"virtual-hosting">>, <<"Virtual Hosting">>))
++ Res,
global, Lang, AJID);
process_admin(Host,
@@ -1549,18 +1557,24 @@ user_info(User, Server, Query, Lang) ->
c2s_compressed_tls ->
<<"tls+zlib">>;
http_bind ->
<<"http-bind">>
<<"http-bind">>;
websocket ->
<<"websocket">>;
_ ->
<<"unknown">>
end,
<<" (", ConnS/binary,
<<ConnS/binary,
"://",
(jlib:ip_to_list(IP))/binary,
":",
(jlib:integer_to_binary(Port))/binary,
"#",
(jlib:atom_to_binary(Node))/binary,
")">>
(jlib:atom_to_binary(Node))/binary>>
end,
?LI([?C((<<R/binary, FIP/binary>>))])
case direction(Lang) of
[{_, <<"rtl">>}] -> ?LI([?C((<<FIP/binary, " - ", R/binary>>))]);
_ -> ?LI([?C((<<R/binary, " - ", FIP/binary>>))])
end
end,
lists:sort(Resources))))]
end,
@@ -1871,9 +1885,7 @@ get_node(global, Node, [<<"backup">>], Query, Lang) ->
[?XRES(<<(?T(<<"Error">>))/binary, ": ",
(list_to_binary(io_lib:format("~p", [Error])))/binary>>)]
end,
(?H1GL(list_to_binary(io_lib:format(?T(<<"Backup of ~p">>), [Node])),
<<"list-eja-commands">>,
<<"List of ejabberd Commands">>))
[?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Backup of ~p">>), [Node])))]
++
ResS ++
[?XCT(<<"p">>,
@@ -2035,7 +2047,7 @@ get_node(global, Node, [<<"ports">>], Query, Lang) ->
[]])),
H1String = <<(?T(<<"Listened Ports at ">>))/binary,
(iolist_to_binary(atom_to_list(Node)))/binary>>,
(?H1GL(H1String, <<"listened">>, <<"Listening Ports">>))
(?H1GL(H1String, <<"listening-ports">>, <<"Listening Ports">>))
++
case Res of
ok -> [?XREST(<<"Submitted">>)];
@@ -2063,7 +2075,7 @@ get_node(Host, Node, [<<"modules">>], Query, Lang)
NewModules = lists:sort(rpc:call(Node, gen_mod,
loaded_modules_with_opts, [Host])),
H1String = list_to_binary(io_lib:format(?T(<<"Modules at ~p">>), [Node])),
(?H1GL(H1String, <<"modoverview">>,
(?H1GL(H1String, <<"modules-overview">>,
<<"Modules Overview">>))
++
case Res of
@@ -2380,18 +2392,18 @@ node_ports_to_xhtml(Ports, Lang) ->
[?INPUTS(<<"text">>,
<<"module", SSPort/binary>>,
SModule, <<"15">>)]),
?XE(<<"td">>,
?XAE(<<"td">>, direction(ltr),
[?TEXTAREA(<<"opts", SSPort/binary>>,
(iolist_to_binary(integer_to_list(NumLines))),
<<"35">>, SOptsClean)]),
?XE(<<"td">>,
[?INPUTT(<<"submit">>,
<<"add", SSPort/binary>>,
<<"Update">>)]),
<<"Restart">>)]),
?XE(<<"td">>,
[?INPUTT(<<"submit">>,
<<"delete", SSPort/binary>>,
<<"Delete">>)])])
<<"Stop">>)])])
end,
Ports)
++
@@ -2406,12 +2418,12 @@ node_ports_to_xhtml(Ports, Lang) ->
?XE(<<"td">>,
[?INPUTS(<<"text">>, <<"modulenew">>, <<"">>,
<<"15">>)]),
?XE(<<"td">>,
?XAE(<<"td">>, direction(ltr),
[?TEXTAREA(<<"optsnew">>, <<"2">>, <<"35">>,
<<"[]">>)]),
?XAE(<<"td">>, [{<<"colspan">>, <<"2">>}],
[?INPUTT(<<"submit">>, <<"addnew">>,
<<"Add New">>)])])]))]).
<<"Start">>)])])]))]).
make_netprot_html(NetProt) ->
?XAE(<<"select">>, [{<<"name">>, <<"netprotnew">>}],
@@ -2523,7 +2535,7 @@ node_modules_to_xhtml(Modules, Lang) ->
40),
?XE(<<"tr">>,
[?XC(<<"td">>, SModule),
?XE(<<"td">>,
?XAE(<<"td">>, direction(ltr),
[?TEXTAREA(<<"opts", SModule/binary>>,
(iolist_to_binary(integer_to_list(NumLines))),
<<"40">>, SOpts)]),
@@ -2542,7 +2554,7 @@ node_modules_to_xhtml(Modules, Lang) ->
[?XE(<<"tr">>,
[?XE(<<"td">>,
[?INPUT(<<"text">>, <<"modulenew">>, <<"">>)]),
?XE(<<"td">>,
?XAE(<<"td">>, direction(ltr),
[?TEXTAREA(<<"optsnew">>, <<"2">>, <<"40">>,
<<"[]">>)]),
?XAE(<<"td">>, [{<<"colspan">>, <<"2">>}],
@@ -2877,3 +2889,6 @@ make_menu_item(item, 3, URI, Name, Lang) ->
%%%==================================
%%% vim: set foldmethod=marker foldmarker=%%%%,%%%=:
opt_type(access) -> fun (V) -> V end;
opt_type(_) -> [access].
+2
View File
@@ -38,6 +38,8 @@
-module(ejabberd_websocket).
-protocol({rfc, 6455}).
-author('ecestari@process-one.net').
-export([check/2, socket_handoff/8]).
+33 -4
View File
@@ -2,8 +2,26 @@
%%% File : ejabberd_xmlrpc.erl
%%% Author : Badlop <badlop@process-one.net>
%%% Purpose : XML-RPC server that frontends ejabberd commands
%%% Created : 21 Aug 2007 by Badlop <badlop@ono.com>
%%% Id : $Id: ejabberd_xmlrpc.erl 595 2008-05-20 11:39:31Z badlop $
%%% Created : 21 Aug 2007 by Badlop <badlop@process-one.net>
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2015 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
%%%
%%%----------------------------------------------------------------------
%%% TODO: Implement a command in ejabberdctl 'help COMMAND LANGUAGE' that shows
@@ -440,7 +458,7 @@ format_arg({array, Elements}, {list, ElementsDef})
[format_arg(Element, ElementsDef)
|| Element <- Elements];
format_arg(Arg, integer) when is_integer(Arg) -> Arg;
format_arg(Arg, binary) when is_list(Arg) -> list_to_binary(Arg);
format_arg(Arg, binary) when is_list(Arg) -> process_unicode_codepoints(Arg);
format_arg(Arg, binary) when is_binary(Arg) -> Arg;
format_arg(Arg, string) when is_list(Arg) -> Arg;
format_arg(Arg, string) when is_binary(Arg) -> binary_to_list(Arg);
@@ -448,7 +466,12 @@ format_arg(undefined, binary) -> <<>>;
format_arg(undefined, string) -> "";
format_arg(Arg, Format) ->
?ERROR_MSG("don't know how to format Arg ~p for format ~p", [Arg, Format]),
throw({error_formatting_argument, Arg, Format}).
error.
process_unicode_codepoints(Str) ->
iolist_to_binary(lists:map(fun(X) when X > 255 -> unicode:characters_to_binary([X]);
(Y) -> Y
end, Str)).
%% -----------------------------
%% Result
@@ -466,6 +489,12 @@ format_result(String, {Name, string}) when is_list(String) ->
{struct, [{Name, lists:flatten(String)}]};
format_result(Binary, {Name, string}) when is_binary(Binary) ->
{struct, [{Name, binary_to_list(Binary)}]};
format_result(Atom, {Name, string}) when is_atom(Atom) ->
{struct, [{Name, atom_to_list(Atom)}]};
format_result(Integer, {Name, string}) when is_integer(Integer) ->
{struct, [{Name, integer_to_list(Integer)}]};
format_result(Other, {Name, string}) ->
{struct, [{Name, io_lib:format("~p", [Other])}]};
format_result(String, {Name, binary}) when is_list(String) ->
{struct, [{Name, lists:flatten(String)}]};
format_result(Binary, {Name, binary}) when is_binary(Binary) ->
+3 -2
View File
@@ -29,7 +29,8 @@
-include("logger.hrl").
-export([export/2, export/3, import_file/2, import/2, import/3]).
-export([export/2, export/3, import_file/2, import/2,
import/3]).
-define(MAX_RECORDS_PER_TRANSACTION, 100).
@@ -54,7 +55,7 @@ modules() ->
mod_offline,
mod_privacy,
mod_private,
mod_pubsub,
%% mod_pubsub,
mod_roster,
mod_shared_roster,
mod_vcard,
-1
View File
@@ -80,7 +80,6 @@
-export([get_status/1]).
%% gen_fsm callbacks
-export([init/1, connecting/2, connecting/3,
wait_bind_response/3, active/3, active_bind/3,
handle_event/3, handle_sync_event/4, handle_info/3,
+58 -40
View File
@@ -24,20 +24,14 @@
%%%----------------------------------------------------------------------
-module(eldap_utils).
-behaviour(ejabberd_config).
-author('mremond@process-one.net').
-export([generate_subfilter/1,
find_ldap_attrs/2,
get_ldap_attr/2,
get_user_part/2,
make_filter/2,
get_state/2,
case_insensitive_match/2,
get_opt/3,
get_opt/4,
get_config/2,
decode_octet_string/3,
uids_domain_subst/2]).
-export([generate_subfilter/1, find_ldap_attrs/2,
get_ldap_attr/2, get_user_part/2, make_filter/2,
get_state/2, case_insensitive_match/2, get_config/2,
decode_octet_string/3, uids_domain_subst/2, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -171,64 +165,48 @@ uids_domain_subst(Host, UIDs) ->
end,
UIDs).
-spec get_opt({atom(), binary()}, list(), fun()) -> any().
get_opt({Key, Host}, Opts, F) ->
get_opt({Key, Host}, Opts, F, undefined).
-spec get_opt({atom(), binary()}, list(), fun(), any()) -> any().
get_opt({Key, Host}, Opts, F, Default) ->
case gen_mod:get_opt(Key, Opts, F, undefined) of
undefined ->
ejabberd_config:get_option(
{Key, Host}, F, Default);
Val ->
Val
end.
-spec get_config(binary(), list()) -> eldap_config().
get_config(Host, Opts) ->
Servers = get_opt({ldap_servers, Host}, Opts,
Servers = gen_mod:get_opt({ldap_servers, Host}, Opts,
fun(L) ->
[iolist_to_binary(H) || H <- L]
end, [<<"localhost">>]),
Backups = get_opt({ldap_backups, Host}, Opts,
Backups = gen_mod:get_opt({ldap_backups, Host}, Opts,
fun(L) ->
[iolist_to_binary(H) || H <- L]
end, []),
Encrypt = get_opt({ldap_encrypt, Host}, Opts,
Encrypt = gen_mod:get_opt({ldap_encrypt, Host}, Opts,
fun(tls) -> tls;
(starttls) -> starttls;
(none) -> none
end, none),
TLSVerify = get_opt({ldap_tls_verify, Host}, Opts,
TLSVerify = gen_mod:get_opt({ldap_tls_verify, Host}, Opts,
fun(hard) -> hard;
(soft) -> soft;
(false) -> false
end, false),
TLSCAFile = get_opt({ldap_tls_cacertfile, Host}, Opts,
TLSCAFile = gen_mod:get_opt({ldap_tls_cacertfile, Host}, Opts,
fun iolist_to_binary/1),
TLSDepth = get_opt({ldap_tls_depth, Host}, Opts,
TLSDepth = gen_mod:get_opt({ldap_tls_depth, Host}, Opts,
fun(I) when is_integer(I), I>=0 -> I end),
Port = get_opt({ldap_port, Host}, Opts,
Port = gen_mod:get_opt({ldap_port, Host}, Opts,
fun(I) when is_integer(I), I>0 -> I end,
case Encrypt of
tls -> ?LDAPS_PORT;
starttls -> ?LDAP_PORT;
_ -> ?LDAP_PORT
end),
RootDN = get_opt({ldap_rootdn, Host}, Opts,
RootDN = gen_mod:get_opt({ldap_rootdn, Host}, Opts,
fun iolist_to_binary/1,
<<"">>),
Password = get_opt({ldap_password, Host}, Opts,
Password = gen_mod:get_opt({ldap_password, Host}, Opts,
fun iolist_to_binary/1,
<<"">>),
Base = get_opt({ldap_base, Host}, Opts,
Base = gen_mod:get_opt({ldap_base, Host}, Opts,
fun iolist_to_binary/1,
<<"">>),
OldDerefAliases = get_opt({deref_aliases, Host}, Opts,
OldDerefAliases = gen_mod:get_opt({deref_aliases, Host}, Opts,
fun(never) -> never;
(searching) -> searching;
(finding) -> finding;
@@ -236,7 +214,7 @@ get_config(Host, Opts) ->
end, unspecified),
DerefAliases =
if OldDerefAliases == unspecified ->
get_opt({ldap_deref_aliases, Host}, Opts,
gen_mod:get_opt({ldap_deref_aliases, Host}, Opts,
fun(never) -> never;
(searching) -> searching;
(finding) -> finding;
@@ -367,3 +345,43 @@ collect_parts_bit([{?N_BIT_STRING,<<Unused,Bits/binary>>}|Rest],Acc,Uacc) ->
collect_parts_bit(Rest,[Bits|Acc],Unused+Uacc);
collect_parts_bit([],Acc,Uacc) ->
list_to_binary([Uacc|lists:reverse(Acc)]).
opt_type(deref_aliases) ->
fun (never) -> never;
(searching) -> searching;
(finding) -> finding;
(always) -> always
end;
opt_type(ldap_backups) ->
fun (L) -> [iolist_to_binary(H) || H <- L] end;
opt_type(ldap_base) -> fun iolist_to_binary/1;
opt_type(ldap_deref_aliases) ->
fun (never) -> never;
(searching) -> searching;
(finding) -> finding;
(always) -> always
end;
opt_type(ldap_encrypt) ->
fun (tls) -> tls;
(starttls) -> starttls;
(none) -> none
end;
opt_type(ldap_password) -> fun iolist_to_binary/1;
opt_type(ldap_port) ->
fun (I) when is_integer(I), I > 0 -> I end;
opt_type(ldap_rootdn) -> fun iolist_to_binary/1;
opt_type(ldap_servers) ->
fun (L) -> [iolist_to_binary(H) || H <- L] end;
opt_type(ldap_tls_cacertfile) -> fun iolist_to_binary/1;
opt_type(ldap_tls_depth) ->
fun (I) when is_integer(I), I >= 0 -> I end;
opt_type(ldap_tls_verify) ->
fun (hard) -> hard;
(soft) -> soft;
(false) -> false
end;
opt_type(_) ->
[deref_aliases, ldap_backups, ldap_base,
ldap_deref_aliases, ldap_encrypt, ldap_password,
ldap_port, ldap_rootdn, ldap_servers,
ldap_tls_cacertfile, ldap_tls_depth, ldap_tls_verify].
+138 -25
View File
@@ -24,15 +24,16 @@
%%%----------------------------------------------------------------------
-module(ext_mod).
-behaviour(ejabberd_config).
-author("Christophe Romain <christophe.romain@process-one.net>").
%% Packaging service
-export([start/0, stop/0, update/0, check/1,
available_command/0, available/0, available/1,
installed_command/0, installed/0, installed/1,
install/1, uninstall/1,
upgrade/0, upgrade/1,
add_sources/2, del_sources/1]).
available_command/0, available/0, available/1,
installed_command/0, installed/0, installed/1,
install/1, uninstall/1, upgrade/0, upgrade/1,
add_sources/2, del_sources/1, modules_dir/0,
opt_type/1]).
-include("ejabberd_commands.hrl").
@@ -163,6 +164,7 @@ install(Package) when is_binary(Package) ->
case compile_and_install(Module, Attrs) of
ok ->
code:add_patha(module_ebin_dir(Module)),
ejabberd_config:reload_file(),
ok;
Error ->
delete_path(module_lib_dir(Module)),
@@ -181,7 +183,8 @@ uninstall(Package) when is_binary(Package) ->
code:purge(Module),
code:delete(Module),
code:del_path(module_ebin_dir(Module)),
delete_path(module_lib_dir(Module));
delete_path(module_lib_dir(Module)),
ejabberd_config:reload_file();
false ->
{error, not_installed}
end.
@@ -302,7 +305,15 @@ extract_url(Path, DestDir) ->
++[{error, unsupported_source}]).
extract_github_master(Repos, DestDir) ->
case extract(zip, geturl(Repos ++ "/archive/master.zip"), DestDir) of
Base = case string:tokens(Repos, ":") of
["git@github.com", T1] -> "https://github.com/"++T1;
_ -> Repos
end,
Url = case lists:reverse(Base) of
[$t,$i,$g,$.|T2] -> lists:reverse(T2);
_ -> Base
end,
case extract(zip, geturl(Url++"/archive/master.zip"), DestDir) of
ok ->
RepDir = filename:join(DestDir, module_name(Repos)),
file:rename(RepDir++"-master", RepDir);
@@ -310,9 +321,23 @@ extract_github_master(Repos, DestDir) ->
Error
end.
copy_file(From, To) ->
filelib:ensure_dir(To),
file:copy(From, To).
copy(From, To) ->
case filelib:is_dir(From) of
true ->
Copy = fun(F) ->
SubFrom = filename:join(From, F),
SubTo = filename:join(To, F),
copy(SubFrom, SubTo)
end,
lists:foldl(fun({ok, C2}, {ok, C1}) -> {ok, C1+C2};
({ok, _}, Error) -> Error;
(Error, _) -> Error
end, {ok, 0},
[Copy(filename:basename(X)) || X<-filelib:wildcard(From++"/*")]);
false ->
filelib:ensure_dir(To),
file:copy(From, To)
end.
delete_path(Path) ->
case filelib:is_dir(Path) of
@@ -422,9 +447,14 @@ compile_and_install(Module, Spec) ->
true ->
{ok, Dir} = file:get_cwd(),
file:set_cwd(SrcDir),
Result = case compile(Module, Spec, LibDir) of
ok -> install(Module, Spec, LibDir);
Error -> Error
Result = case compile_deps(Module, Spec, LibDir) of
ok ->
case compile(Module, Spec, LibDir) of
ok -> install(Module, Spec, LibDir);
Error -> Error
end;
Error ->
Error
end,
file:set_cwd(Dir),
Result;
@@ -436,19 +466,47 @@ compile_and_install(Module, Spec) ->
end
end.
compile_deps(_Module, _Spec, DestDir) ->
case filelib:is_dir("deps") of
true -> ok;
false -> fetch_rebar_deps()
end,
Ebin = filename:join(DestDir, "ebin"),
filelib:ensure_dir(filename:join(Ebin, ".")),
Result = lists:foldl(fun(Dep, Acc) ->
Inc = filename:join(Dep, "include"),
Src = filename:join(Dep, "src"),
Options = [{outdir, Ebin}, {i, Inc}],
[file:copy(App, Ebin) || App <- filelib:wildcard(Src++"/*.app")],
Acc++[case compile:file(File, Options) of
{ok, _} -> ok;
{ok, _, _} -> ok;
{ok, _, _, _} -> ok;
error -> {error, {compilation_failed, File}};
Error -> Error
end
|| File <- filelib:wildcard(Src++"/*.erl")]
end, [], filelib:wildcard("deps/*")),
case lists:dropwhile(
fun(ok) -> true;
(_) -> false
end, Result) of
[] -> ok;
[Error|_] -> Error
end.
compile(_Module, _Spec, DestDir) ->
Ebin = filename:join(DestDir, "ebin"),
filelib:ensure_dir(filename:join(Ebin, ".")),
EjabBin = filename:dirname(code:which(ejabberd)),
EjabInc = filename:join(filename:dirname(EjabBin), "include"),
Logger = case code:is_loaded(lager) of
{file, _} -> [{d, 'LAGER'}];
_ -> []
end,
XmlHrl = filename:join(EjabInc, "xml.hrl"),
Logger = [{d, 'LAGER'} || code:is_loaded(lager)=/=false],
ExtLib = [{d, 'NO_EXT_LIB'} || filelib:is_file(XmlHrl)],
Options = [{outdir, Ebin}, {i, "include"}, {i, EjabInc},
{d, 'NO_EXT_LIB'}, %% use include instead of include_lib
verbose, report_errors, report_warnings]
++ Logger,
++ Logger ++ ExtLib,
[file:copy(App, Ebin) || App <- filelib:wildcard("src/*.app")],
Result = [case compile:file(File, Options) of
{ok, _} -> ok;
{ok, _, _} -> ok;
@@ -465,11 +523,59 @@ compile(_Module, _Spec, DestDir) ->
[Error|_] -> Error
end.
install(Module, _Spec, DestDir) ->
SpecFile = filename:flatten([Module, ".spec"]),
[copy_file(File, filename:join(DestDir, File))
|| File <- [SpecFile | filelib:wildcard("{ebin,priv,conf,include}/**")]],
ok.
install(Module, Spec, DestDir) ->
Errors = lists:dropwhile(fun({_, {ok, _}}) -> true;
(_) -> false
end, [{File, copy(File, filename:join(DestDir, File))}
|| File <- filelib:wildcard("{ebin,priv,conf,include}/**")]),
Result = case Errors of
[{F, {error, E}}|_] ->
{error, {F, E}};
[] ->
SpecPath = proplists:get_value(path, Spec),
SpecFile = filename:flatten([Module, ".spec"]),
copy(filename:join(SpecPath, SpecFile), filename:join(DestDir, SpecFile))
end,
case Result of
{ok, _} -> ok;
Error -> Error
end.
%% -- minimalist rebar spec parser, only support git
fetch_rebar_deps() ->
case rebar_deps("rebar.config")++rebar_deps("rebar.config.script") of
[] ->
ok;
Deps ->
filelib:ensure_dir(filename:join("deps", ".")),
lists:foreach(fun({_App, Cmd}) ->
os:cmd("cd deps; "++Cmd++"; cd ..")
end, Deps)
end.
rebar_deps(Script) ->
case file:script(Script) of
{ok, Config} when is_list(Config) ->
[rebar_dep(Dep) || Dep <- proplists:get_value(deps, Config, [])];
{ok, {deps, Deps}} ->
[rebar_dep(Dep) || Dep <- Deps];
_ ->
[]
end.
rebar_dep({App, _, {git, Url}}) ->
{App, "git clone "++Url++" "++filename:basename(App)};
rebar_dep({App, _, {git, Url, {branch, Ref}}}) ->
{App, "git clone -n "++Url++" "++filename:basename(App)++
"; (cd "++filename:basename(App)++
"; git checkout -q origin/"++Ref++")"};
rebar_dep({App, _, {git, Url, {tag, Ref}}}) ->
{App, "git clone -n "++Url++" "++filename:basename(App)++
"; (cd "++filename:basename(App)++
"; git checkout -q "++Ref++")"};
rebar_dep({App, _, {git, Url, Ref}}) ->
{App, "git clone -n "++Url++" "++filename:basename(App)++
"; (cd "++filename:basename(App)++
"; git checkout -q "++Ref++")"}.
%% -- YAML spec parser
@@ -484,3 +590,10 @@ format({Key, Val}) when is_binary(Val) ->
{Key, binary_to_list(Val)};
format({Key, Val}) -> % TODO: improve Yaml parsing
{Key, Val}.
opt_type(allow_contrib_modules) ->
fun (false) -> false;
(no) -> false;
(_) -> true
end;
opt_type(_) -> [allow_contrib_modules].
+7 -1
View File
@@ -25,11 +25,13 @@
-module(extauth).
-behaviour(ejabberd_config).
-author('leifj@it.su.se').
-export([start/2, stop/1, init/2, check_password/3,
set_password/3, try_register/3, remove_user/2,
remove_user/3, is_user_exists/2]).
remove_user/3, is_user_exists/2, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -157,3 +159,7 @@ encode(L) -> str:join(L, <<":">>).
decode([0, 0]) -> false;
decode([0, 1]) -> true.
opt_type(extauth_instances) ->
fun (V) when is_integer(V), V > 0 -> V end;
opt_type(_) -> [extauth_instances].
+90 -42
View File
@@ -1,7 +1,6 @@
%%%----------------------------------------------------------------------
%%% File : gen_mod.erl
%%% Author : Alexey Shchepin <alexey@process-one.net>
%%% Purpose :
%%% Purpose :
%%% Created : 24 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
%%%
@@ -18,22 +17,26 @@
%%% 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.,
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%% You should have received a copy of the GNU General Public License
%%% along with this program; if not, write to the Free Software
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
%%% 02111-1307 USA
%%%
%%%----------------------------------------------------------------------
-module(gen_mod).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-export([start/0, start_module/2, start_module/3, stop_module/2,
stop_module_keep_config/2, get_opt/3, get_opt/4,
get_opt_host/3, db_type/1, db_type/2, get_module_opt/5,
get_module_opt_host/3, loaded_modules/1,
loaded_modules_with_opts/1, get_hosts/2,
get_module_proc/2, is_loaded/2, default_db/1]).
-export([start/0, start_module/2, start_module/3,
stop_module/2, stop_module_keep_config/2, get_opt/3,
get_opt/4, get_opt_host/3, db_type/1, db_type/2,
get_module_opt/4, get_module_opt/5, get_module_opt_host/3,
loaded_modules/1, loaded_modules_with_opts/1,
get_hosts/2, get_module_proc/2, is_loaded/2,
start_modules/1, default_db/1, v_db/1, opt_type/1]).
%%-export([behaviour_info/1]).
@@ -45,11 +48,13 @@
opts = [] :: opts() | '_' | '$2'}).
-type opts() :: [{atom(), any()}].
-type db_type() :: odbc | mnesia | riak.
-callback start(binary(), opts()) -> any().
-callback stop(binary()) -> any().
-export_type([opts/0]).
-export_type([db_type/0]).
%%behaviour_info(callbacks) -> [{start, 2}, {stop, 1}];
%%behaviour_info(_Other) -> undefined.
@@ -60,6 +65,17 @@ start() ->
{keypos, #ejabberd_module.module_host}]),
ok.
-spec start_modules(binary()) -> any().
start_modules(Host) ->
Modules = ejabberd_config:get_option(
{modules, Host},
fun(L) when is_list(L) -> L end, []),
lists:foreach(
fun({Module, Opts}) ->
start_module(Host, Module, Opts)
end, Modules).
-spec start_module(binary(), atom()) -> any().
start_module(Host, Module) ->
@@ -75,7 +91,8 @@ start_module(Host, Module) ->
-spec start_module(binary(), atom(), opts()) -> any().
start_module(Host, Module, Opts) ->
start_module(Host, Module, Opts0) ->
Opts = validate_opts(Module, Opts0),
ets:insert(ejabberd_modules,
#ejabberd_module{module_host = {Module, Host},
opts = Opts}),
@@ -107,18 +124,12 @@ is_app_running(AppName) ->
-spec stop_module(binary(), atom()) -> error | {aborted, any()} | {atomic, any()}.
%% @doc Stop the module in a host, and forget its configuration.
stop_module(Host, Module) ->
case stop_module_keep_config(Host, Module) of
error -> error;
ok -> ok
end.
%% @doc Stop the module in a host, but keep its configuration.
%% As the module configuration is kept in the Mnesia local_config table,
%% when ejabberd is restarted the module will be started again.
%% This function is useful when ejabberd is being stopped
%% and it stops all modules.
-spec stop_module_keep_config(binary(), atom()) -> error | ok.
stop_module_keep_config(Host, Module) ->
@@ -155,13 +166,20 @@ wait_for_stop1(MonitorReference) ->
-type check_fun() :: fun((any()) -> any()) | {module(), atom()}.
-spec get_opt(atom(), opts(), check_fun()) -> any().
-spec get_opt(atom() | {atom(), binary()|global}, opts(), check_fun()) -> any().
get_opt(Opt, Opts, F) ->
get_opt(Opt, Opts, F, undefined).
-spec get_opt(atom(), opts(), check_fun(), any()) -> any().
-spec get_opt(atom() | {atom(), binary()|global}, opts(), check_fun(), any()) -> any().
get_opt({Opt, Host}, Opts, F, Default) ->
case lists:keysearch(Opt, 1, Opts) of
false ->
ejabberd_config:get_option({Opt, Host}, F, Default);
{value, {_, Val}} ->
ejabberd_config:prepare_opt_val(Opt, Val, F, Default)
end;
get_opt(Opt, Opts, F, Default) ->
case lists:keysearch(Opt, 1, Opts) of
false ->
@@ -170,6 +188,11 @@ get_opt(Opt, Opts, F, Default) ->
ejabberd_config:prepare_opt_val(Opt, Val, F, Default)
end.
-spec get_module_opt(global | binary(), atom(), atom(), check_fun()) -> any().
get_module_opt(Host, Module, Opt, F) ->
get_module_opt(Host, Module, Opt, F, undefined).
-spec get_module_opt(global | binary(), atom(), atom(), check_fun(), any()) -> any().
get_module_opt(global, Module, Opt, F, Default) ->
@@ -209,39 +232,60 @@ get_opt_host(Host, Opts, Default) ->
Val = get_opt(host, Opts, fun iolist_to_binary/1, Default),
ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host).
-spec db_type(opts()) -> odbc | mnesia | riak.
validate_opts(Module, Opts) ->
lists:filter(
fun({Opt, Val}) ->
case catch Module:mod_opt_type(Opt) of
VFun when is_function(VFun) ->
case catch VFun(Val) of
{'EXIT', _} ->
?ERROR_MSG("ignoring invalid value '~p' for "
"option '~s' of module '~s'",
[Val, Opt, Module]),
false;
_ ->
true
end;
L when is_list(L) ->
SOpts = str:join([[$', atom_to_list(A), $'] || A <- L], <<", ">>),
?ERROR_MSG("unknown option '~s' for module '~s' will be"
" likely ignored, available options are: ~s",
[Opt, Module, SOpts]),
true;
{'EXIT', {undef, _}} ->
?WARNING_MSG("module '~s' doesn't export mod_opt_type/1",
[Module]),
true
end;
(Junk) ->
?ERROR_MSG("failed to understand option ~p for module '~s'",
[Junk, Module]),
false
end, Opts).
-spec v_db(db_type() | internal) -> db_type().
v_db(odbc) -> odbc;
v_db(internal) -> mnesia;
v_db(mnesia) -> mnesia;
v_db(riak) -> riak.
-spec db_type(opts()) -> db_type().
db_type(Opts) ->
db_type(global, Opts).
-spec db_type(binary() | global, atom() | opts()) -> odbc | mnesia | riak.
-spec db_type(binary() | global, atom() | opts()) -> db_type().
db_type(Host, Module) when is_atom(Module) ->
get_module_opt(Host, Module, db_type,
fun(odbc) -> odbc;
(internal) -> mnesia;
(mnesia) -> mnesia;
(riak) -> riak
end,
default_db(Host));
get_module_opt(Host, Module, db_type, fun v_db/1, default_db(Host));
db_type(Host, Opts) when is_list(Opts) ->
get_opt(db_type, Opts,
fun(odbc) -> odbc;
(internal) -> mnesia;
(mnesia) -> mnesia;
(riak) -> riak
end,
default_db(Host)).
get_opt(db_type, Opts, fun v_db/1, default_db(Host)).
-spec default_db(binary() | global) -> odbc | mnesia | riak.
-spec default_db(binary() | global) -> db_type().
default_db(Host) ->
ejabberd_config:get_option({default_db, Host},
fun(odbc) -> odbc;
(mnesia) -> mnesia;
(riak) -> riak;
(internal) -> mnesia
end, mnesia).
ejabberd_config:get_option({default_db, Host}, fun v_db/1, mnesia).
-spec loaded_modules(binary()) -> [atom()].
@@ -288,3 +332,7 @@ get_module_proc(Host, Base) ->
is_loaded(Host, Module) ->
ets:member(ejabberd_modules, {Module, Host}).
opt_type(default_db) -> fun v_db/1;
opt_type(modules) -> fun (L) when is_list(L) -> L end;
opt_type(_) -> [default_db, modules].
+15 -29
View File
@@ -27,6 +27,10 @@
-author('alexey@process-one.net').
-protocol({xep, 59, '1.0'}).
-protocol({xep, 82, '1.1'}).
-protocol({xep, 203, '2.0'}).
-compile({no_auto_import, [atom_to_binary/2,
binary_to_integer/1,
integer_to_binary/1]}).
@@ -54,9 +58,6 @@
atom_to_binary/1, binary_to_atom/1, tuple_to_binary/1,
l2i/1, i2l/1, i2l/2, queue_drop_while/2]).
%% TODO: Remove once XEP-0091 is Obsolete
%% TODO: Remove once XEP-0091 is Obsolete
-include("ejabberd.hrl").
-include("jlib.hrl").
@@ -612,19 +613,10 @@ add_delay_info(El, From, Time) ->
binary()) -> xmlel().
add_delay_info(El, From, Time, Desc) ->
%% TODO: Remove support for <x/>, XEP-0091 is obsolete.
El1 = add_delay_info(El, From, Time, Desc, <<"delay">>, ?NS_DELAY),
El2 = add_delay_info(El1, From, Time, Desc, <<"x">>, ?NS_DELAY91),
El2.
-spec add_delay_info(xmlel(), jid() | ljid() | binary(), erlang:timestamp(),
binary(), binary(), binary()) -> xmlel().
add_delay_info(El, From, Time, Desc, Name, XMLNS) ->
case xml:get_subtag_with_xmlns(El, Name, XMLNS) of
case xml:get_subtag_with_xmlns(El, <<"delay">>, ?NS_DELAY) of
false ->
%% Add new tag
DelayTag = create_delay_tag(Time, From, Desc, XMLNS),
DelayTag = create_delay_tag(Time, From, Desc),
xml:append_subtags(El, [DelayTag]);
DelayTag ->
%% Update existing tag
@@ -645,34 +637,28 @@ add_delay_info(El, From, Time, Desc, Name, XMLNS) ->
DelayTag#xmlel{children = [{xmlcdata, OldDesc}]}
end
end,
NewEl = xml:remove_subtags(El, Name, {<<"xmlns">>, XMLNS}),
NewEl = xml:remove_subtags(El, <<"delay">>, {<<"xmlns">>, ?NS_DELAY}),
xml:append_subtags(NewEl, [NewDelayTag])
end.
-spec create_delay_tag(erlang:timestamp(), jid() | ljid() | binary(), binary(),
binary()) -> xmlel() | error.
-spec create_delay_tag(erlang:timestamp(), jid() | ljid() | binary(), binary())
-> xmlel() | error.
create_delay_tag(TimeStamp, FromJID, Desc, XMLNS) when is_tuple(FromJID) ->
create_delay_tag(TimeStamp, FromJID, Desc) when is_tuple(FromJID) ->
From = jlib:jid_to_string(FromJID),
{Name, Stamp} = case XMLNS of
?NS_DELAY ->
{<<"delay">>, now_to_utc_string(TimeStamp, 3)};
?NS_DELAY91 ->
DateTime = calendar:now_to_universal_time(TimeStamp),
{<<"x">>, timestamp_to_iso(DateTime)}
end,
Stamp = now_to_utc_string(TimeStamp, 3),
Children = case Desc of
<<"">> -> [];
_ -> [{xmlcdata, Desc}]
end,
#xmlel{name = Name,
#xmlel{name = <<"delay">>,
attrs =
[{<<"xmlns">>, XMLNS}, {<<"from">>, From},
[{<<"xmlns">>, ?NS_DELAY}, {<<"from">>, From},
{<<"stamp">>, Stamp}],
children = Children};
create_delay_tag(DateTime, Host, Desc, XMLNS) when is_binary(Host) ->
create_delay_tag(DateTime, Host, Desc) when is_binary(Host) ->
FromJID = jlib:make_jid(<<"">>, Host, <<"">>),
create_delay_tag(DateTime, FromJID, Desc, XMLNS).
create_delay_tag(DateTime, FromJID, Desc).
-type tz() :: {binary(), {integer(), integer()}} | {integer(), integer()} | utc.
+8 -1
View File
@@ -27,13 +27,15 @@
-author('henoch@dtek.chalmers.se').
-protocol({xep, 50, '1.2'}).
-behaviour(gen_mod).
-export([start/2, stop/1, process_local_iq/3,
process_sm_iq/3, get_local_commands/5,
get_local_identity/5, get_local_features/5,
get_sm_commands/5, get_sm_identity/5, get_sm_features/5,
ping_item/4, ping_command/4]).
ping_item/4, ping_command/4, mod_opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -278,3 +280,8 @@ ping_command(_Acc, _From, _To,
true -> {error, ?ERR_BAD_REQUEST}
end;
ping_command(Acc, _From, _To, _Request) -> Acc.
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(report_commands_node) ->
fun (B) when is_boolean(B) -> B end;
mod_opt_type(_) -> [iqdisc, report_commands_node].
+46 -118
View File
@@ -30,75 +30,32 @@
-include("logger.hrl").
-export([start/2, stop/1,
%% Node
compile/1,
get_cookie/0,
remove_node/1,
export2odbc/2,
%% Accounts
set_password/3,
check_password_hash/4,
delete_old_users/1,
delete_old_users_vhost/2,
ban_account/3,
num_active_users/2,
%% Sessions
num_resources/2,
resource_num/3,
kick_session/4,
status_num/2, status_num/1,
status_list/2, status_list/1,
connected_users_info/0,
connected_users_vhost/1,
set_presence/7,
user_sessions_info/2,
%% Vcard
set_nickname/3,
get_vcard/3,
get_vcard/4,
get_vcard_multi/4,
set_vcard/4,
set_vcard/5,
%% Roster
add_rosteritem/7,
delete_rosteritem/4,
process_rosteritems/5,
get_roster/2,
push_roster/3,
push_roster_all/1,
push_alltoall/2,
%% mod_last
get_last/2,
set_last/4,
%% mod_private
private_get/4,
private_set/3,
%% mod_shared_roster
srg_create/5,
srg_delete/2,
srg_list/1,
srg_get_info/2,
srg_get_members/2,
srg_user_add/4,
srg_user_del/4,
%% Stanza
send_message/5,
send_stanza_c2s/4,
privacy_set/3,
%% Stats
stats/1, stats/2
]).
-export([start/2, stop/1, compile/1, get_cookie/0,
remove_node/1, set_password/3,
check_password_hash/4, delete_old_users/1,
delete_old_users_vhost/2, ban_account/3,
num_active_users/2, num_resources/2, resource_num/3,
kick_session/4, status_num/2, status_num/1,
status_list/2, status_list/1, connected_users_info/0,
connected_users_vhost/1, set_presence/7,
user_sessions_info/2, set_nickname/3, get_vcard/3,
get_vcard/4, get_vcard_multi/4, set_vcard/4,
set_vcard/5, add_rosteritem/7, delete_rosteritem/4,
process_rosteritems/5, get_roster/2, push_roster/3,
push_roster_all/1, push_alltoall/2, get_last/2,
private_get/4, private_set/3, srg_create/5,
srg_delete/2, srg_list/1, srg_get_info/2,
srg_get_members/2, srg_user_add/4, srg_user_del/4,
send_message/5, send_stanza_c2s/4, privacy_set/3,
stats/1, stats/2, mod_opt_type/1]).
-include("ejabberd.hrl").
-include("ejabberd_commands.hrl").
-include("mod_roster.hrl").
-include("ejabberd_sm.hrl").
-include("jlib.hrl").
%% Copied from ejabberd_sm.erl
-record(session, {sid, usr, us, priority, info}).
%%%
%%% gen_mod
%%%
@@ -155,11 +112,6 @@ commands() ->
module = ?MODULE, function = remove_node,
args = [{node, string}],
result = {res, rescode}},
#ejabberd_commands{name = export2odbc, tags = [mnesia], %% Copied to ejabberd 2.1.x after 11
desc = "Export Mnesia tables to files in directory",
module = ?MODULE, function = export2odbc,
args = [{host, string}, {path, string}],
result = {res, rescode}},
#ejabberd_commands{name = num_active_users, tags = [accounts, stats],
desc = "Get number of users active in the last days",
@@ -191,7 +143,7 @@ commands() ->
desc = "Check if the password hash is correct",
longdesc = "Allowed hash methods: md5, sha.",
module = ?MODULE, function = check_password_hash,
args = [{user, binary}, {host, binary}, {passwordhash, binary}, {hashmethod, binary}],
args = [{user, binary}, {host, binary}, {passwordhash, string}, {hashmethod, string}],
result = {res, rescode}},
#ejabberd_commands{name = change_password, tags = [accounts],
desc = "Change the password of an account",
@@ -276,7 +228,7 @@ commands() ->
tags = [session],
desc = "Get the list of established sessions in a vhost",
module = ?MODULE, function = connected_users_vhost,
args = [{host, string}],
args = [{host, binary}],
result = {connected_users_vhost, {list, {sessions, string}}}},
#ejabberd_commands{name = user_sessions_info,
tags = [session],
@@ -421,21 +373,21 @@ commands() ->
#ejabberd_commands{name = push_roster, tags = [roster],
desc = "Push template roster from file to a user",
module = ?MODULE, function = push_roster,
args = [{file, string}, {user, string}, {host, string}],
args = [{file, binary}, {user, binary}, {host, binary}],
result = {res, rescode}},
#ejabberd_commands{name = push_roster_all, tags = [roster],
desc = "Push template roster from file to all those users",
module = ?MODULE, function = push_roster_all,
args = [{file, string}],
args = [{file, binary}],
result = {res, rescode}},
#ejabberd_commands{name = push_alltoall, tags = [roster],
desc = "Add all the users to all the users of Host in Group",
module = ?MODULE, function = push_alltoall,
args = [{host, string}, {group, string}],
args = [{host, binary}, {group, binary}],
result = {res, rescode}},
#ejabberd_commands{name = get_last, tags = [last],
desc = "Get last activity information",
desc = "Get last activity information (timestamp and status)",
longdesc = "Timestamp is the seconds since"
"1970-01-01 00:00:00 UTC, for example: date +%s",
module = ?MODULE, function = get_last,
@@ -445,8 +397,8 @@ commands() ->
desc = "Set last activity information",
longdesc = "Timestamp is the seconds since"
"1970-01-01 00:00:00 UTC, for example: date +%s",
module = ?MODULE, function = set_last,
args = [{user, string}, {host, string}, {timestamp, integer}, {status, string}],
module = mod_last, function = store_last_info,
args = [{user, binary}, {host, binary}, {timestamp, integer}, {status, binary}],
result = {res, rescode}},
#ejabberd_commands{name = private_get, tags = [private],
@@ -548,25 +500,6 @@ remove_node(Node) ->
mnesia:del_table_copy(schema, list_to_atom(Node)),
ok.
export2odbc(Host, Directory) ->
Tables = [
{export_last, last},
{export_offline, offline},
{export_passwd, passwd},
{export_private_storage, private_storage},
{export_roster, roster},
{export_vcard, vcard},
{export_vcard_search, vcard_search}],
Export = fun({TableFun, Table}) ->
Filename = filename:join([Directory, atom_to_list(Table)++".txt"]),
io:format("Trying to export Mnesia table '~p' on Host '~s' to file '~s'~n", [Table, Host, Filename]),
Res = (catch ejd2odbc:TableFun(Host, Filename)),
io:format(" Result: ~p~n", [Res])
end,
lists:foreach(Export, Tables),
ok.
%%%
%%% Accounts
%%%
@@ -582,12 +515,16 @@ set_password(User, Host, Password) ->
%% Copied some code from ejabberd_commands.erl
check_password_hash(User, Host, PasswordHash, HashMethod) ->
AccountPass = ejabberd_auth:get_password_s(User, Host),
AccountPassHash = case HashMethod of
"md5" -> get_md5(AccountPass);
"sha" -> get_sha(AccountPass);
AccountPassHash = case {AccountPass, HashMethod} of
{A, _} when is_tuple(A) -> scrammed;
{_, "md5"} -> get_md5(AccountPass);
{_, "sha"} -> get_sha(AccountPass);
_ -> undefined
end,
case AccountPassHash of
scrammed ->
?ERROR_MSG("Passwords are scrammed, and check_password_hash can not work.", []),
throw(passwords_scrammed_command_cannot_work);
undefined -> error;
PasswordHash -> ok;
_ -> error
@@ -680,7 +617,7 @@ delete_old_users(Days, Users) ->
%% If it isnt
[] ->
%% Look for his last_activity
case (get_lastactivity_module(LServer)):get_last_info(LUser, LServer) of
case mod_last:get_last_info(LUser, LServer) of
%% If it is
%% existent:
{ok, TimeStamp, _Status} ->
@@ -714,13 +651,6 @@ delete_old_users(Days, Users) ->
Users_removed = lists:filter(F, Users),
{removed, length(Users_removed), Users_removed}.
get_lastactivity_module(Server) ->
case lists:member(mod_last, gen_mod:loaded_modules(Server)) of
true -> mod_last;
_ -> mod_last_odbc
end.
%%
%% Ban account
@@ -1076,7 +1006,7 @@ subscribe(LU, LS, User, Server, Nick, Group, Subscription, _Xattrs) ->
mod_roster:set_items(
LU, LS,
{xmlel, <<"query">>,
[{<<"xmlns">>, <<"jabber:iq:roster">>}],
[{<<"xmlns">>, ?NS_ROSTER}],
[ItemEl]}).
delete_rosteritem(LocalUser, LocalServer, User, Server) ->
@@ -1093,7 +1023,7 @@ unsubscribe(LU, LS, User, Server) ->
mod_roster:set_items(
LU, LS,
{xmlel, <<"query">>,
[{<<"xmlns">>, <<"jabber:iq:roster">>}],
[{<<"xmlns">>, ?NS_ROSTER}],
[ItemEl]}).
%% -----------------------------
@@ -1220,13 +1150,12 @@ build_broadcast(U, S, SubsAtom) when is_atom(SubsAtom) ->
%%%
get_last(User, Server) ->
Mod = get_lastactivity_module(Server),
case ejabberd_sm:get_user_resources(User, Server) of
[] ->
case Mod:get_last_info(User, Server) of
case mod_last:get_last_info(User, Server) of
not_found ->
"Never";
{ok, Shift, _Status} ->
{ok, Shift, Status} ->
TimeStamp = {Shift div 1000000,
Shift rem 1000000,
0},
@@ -1234,17 +1163,13 @@ get_last(User, Server) ->
calendar:now_to_local_time(TimeStamp),
lists:flatten(
io_lib:format(
"~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
[Year, Month, Day, Hour, Minute, Second]))
"~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w ~s",
[Year, Month, Day, Hour, Minute, Second, Status]))
end;
_ ->
"Online"
end.
set_last(User, Server, Timestamp, Status) ->
Mod = get_lastactivity_module(Server),
Mod:store_last_info(User, Server, Timestamp, Status).
%%%
%%% Private Storage
%%%
@@ -1263,7 +1188,7 @@ private_get(Username, Host, Element, Ns) ->
[{xmlel, Element, [{<<"xmlns">>, Ns}], []}]}},
ResIq = mod_private:process_sm_iq(From, To, IQ),
[{xmlel, <<"query">>,
[{<<"xmlns">>, <<"jabber:iq:private">>}],
[{<<"xmlns">>, ?NS_PRIVATE}],
[SubEl]}] = ResIq#iq.sub_el,
binary_to_list(xml:element_to_binary(SubEl)).
@@ -1572,3 +1497,6 @@ is_glob_match(String, <<"!", Glob/binary>>) ->
not is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob));
is_glob_match(String, Glob) ->
is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)).
mod_opt_type(module_resource) -> fun (A) -> A end;
mod_opt_type(_) -> [module_resource].
+10 -14
View File
@@ -31,20 +31,11 @@
-behaviour(gen_mod).
-export([start/2,
init/0,
stop/1,
export/1,
import/1,
import/3,
announce/3,
send_motd/1,
disco_identity/5,
disco_features/5,
disco_items/5,
send_announcement_to_all/3,
announce_commands/4,
announce_items/4]).
-export([start/2, init/0, stop/1, export/1, import/1,
import/3, announce/3, send_motd/1, disco_identity/5,
disco_features/5, disco_items/5,
send_announcement_to_all/3, announce_commands/4,
announce_items/4, mod_opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -1152,3 +1143,8 @@ import(_LServer, riak, #motd_users{us = {_, S}} = Users) ->
[{'2i', [{<<"server">>, S}]}]);
import(_, _, _) ->
pass.
mod_opt_type(access) ->
fun (A) when is_atom(A) -> A end;
mod_opt_type(db_type) -> fun gen_mod:v_db/1;
mod_opt_type(_) -> [access, db_type].
+6 -1
View File
@@ -28,8 +28,10 @@
-behaviour(gen_mod).
-protocol({xep, 191, '1.2'}).
-export([start/2, stop/1, process_iq/3,
process_iq_set/4, process_iq_get/5]).
process_iq_set/4, process_iq_get/5, mod_opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -449,3 +451,6 @@ process_blocklist_get(LUser, LServer, odbc) ->
end;
{'EXIT', _} -> error
end.
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(_) -> [iqdisc].
+42 -34
View File
@@ -29,6 +29,8 @@
-author('henoch@dtek.chalmers.se').
-protocol({xep, 115, '1.5'}).
-behaviour(gen_server).
-behaviour(gen_mod).
@@ -45,10 +47,9 @@
-export([init/1, handle_info/2, handle_call/3,
handle_cast/2, terminate/2, code_change/3]).
%% hook handlers
-export([user_send_packet/3, user_receive_packet/4,
-export([user_send_packet/4, user_receive_packet/5,
c2s_presence_in/2, c2s_filter_packet/6,
c2s_broadcast_recipients/6]).
c2s_broadcast_recipients/6, mod_opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -142,11 +143,12 @@ read_caps([_ | Tail], Result) ->
read_caps(Tail, Result);
read_caps([], Result) -> Result.
user_send_packet(#jid{luser = User, lserver = Server} = From,
user_send_packet(#xmlel{name = <<"presence">>, attrs = Attrs,
children = Els} = Pkt,
_C2SState,
#jid{luser = User, lserver = Server} = From,
#jid{luser = User, lserver = Server,
lresource = <<"">>},
#xmlel{name = <<"presence">>, attrs = Attrs,
children = Els} = Pkt) ->
lresource = <<"">>}) ->
Type = xml:get_attr_s(<<"type">>, Attrs),
if Type == <<"">>; Type == <<"available">> ->
case read_caps(Els) of
@@ -157,13 +159,14 @@ user_send_packet(#jid{luser = User, lserver = Server} = From,
true -> ok
end,
Pkt;
user_send_packet( _From, _To, Pkt) ->
user_send_packet(Pkt, _C2SState, _From, _To) ->
Pkt.
user_receive_packet(#jid{lserver = Server},
From, _To,
#xmlel{name = <<"presence">>, attrs = Attrs,
children = Els} = Pkt) ->
user_receive_packet(#xmlel{name = <<"presence">>, attrs = Attrs,
children = Els} = Pkt,
_C2SState,
#jid{lserver = Server},
From, _To) ->
Type = xml:get_attr_s(<<"type">>, Attrs),
IsRemote = not lists:member(From#jid.lserver, ?MYHOSTS),
if IsRemote and
@@ -176,7 +179,7 @@ user_receive_packet(#jid{lserver = Server},
true -> ok
end,
Pkt;
user_receive_packet( _JID, _From, _To, Pkt) ->
user_receive_packet(Pkt, _C2SState, _JID, _From, _To) ->
Pkt.
-spec caps_stream_features([xmlel()], binary()) -> [xmlel()].
@@ -240,27 +243,24 @@ c2s_presence_in(C2SState,
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(To#jid.lserver, Caps)]);
true -> ok
end,
NewRs = case Caps of
nothing when Insert == true -> Rs;
_ when Insert == true ->
case gb_trees:lookup(LFrom, Rs) of
{value, Caps} -> Rs;
none ->
ejabberd_hooks:run(caps_add, To#jid.lserver,
[From, To,
get_features(To#jid.lserver, Caps)]),
gb_trees:insert(LFrom, Caps, Rs);
_ ->
ejabberd_hooks:run(caps_update, To#jid.lserver,
[From, To,
get_features(To#jid.lserver, Caps)]),
gb_trees:update(LFrom, Caps, Rs)
end;
_ -> gb_trees:delete_any(LFrom, Rs)
end,
ejabberd_c2s:set_aux_field(caps_resources, NewRs,
C2SState);
true -> C2SState
@@ -752,3 +752,11 @@ import_next(LServer, DBType, NodePair) ->
ok
end,
import_next(LServer, DBType, ets:next(caps_features_tmp, NodePair)).
mod_opt_type(cache_life_time) ->
fun (I) when is_integer(I), I > 0 -> I end;
mod_opt_type(cache_size) ->
fun (I) when is_integer(I), I > 0 -> I end;
mod_opt_type(db_type) -> fun gen_mod:v_db/1;
mod_opt_type(_) ->
[cache_life_time, cache_size, db_type].
+13 -12
View File
@@ -26,6 +26,7 @@
%%%----------------------------------------------------------------------
-module (mod_carboncopy).
-author ('ecestari@process-one.net').
-protocol({xep, 280, '0.8'}).
-behavior(gen_mod).
@@ -33,13 +34,9 @@
-export([start/2,
stop/1]).
%% Hooks:
-export([user_send_packet/3,
user_receive_packet/4,
iq_handler2/3,
iq_handler1/3,
remove_connection/4,
is_carbon_copy/1]).
-export([user_send_packet/4, user_receive_packet/5,
iq_handler2/3, iq_handler1/3, remove_connection/4,
is_carbon_copy/1, mod_opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -127,10 +124,10 @@ iq_handler(From, _To, #iq{type=set, sub_el = #xmlel{name = Operation, children
iq_handler(_From, _To, IQ, _CC)->
IQ#iq{type=error, sub_el = [?ERR_NOT_ALLOWED]}.
user_send_packet(From, To, Packet) ->
user_send_packet(Packet, _C2SState, From, To) ->
check_and_forward(From, To, Packet, sent).
user_receive_packet(JID, _From, To, Packet) ->
user_receive_packet(Packet, _C2SState, JID, _From, To) ->
check_and_forward(JID, To, Packet, received).
% verifier si le trafic est local
@@ -145,14 +142,15 @@ check_and_forward(JID, To, Packet, Direction)->
true ->
case is_carbon_copy(Packet) of
false ->
send_copies(JID, To, Packet, Direction);
send_copies(JID, To, Packet, Direction),
Packet;
true ->
%% stop the hook chain, we don't want mod_logdb to register
%% this message (duplicate)
stop
{stop, Packet}
end;
_ ->
ok
Packet
end.
remove_connection(User, Server, Resource, _Status)->
@@ -287,3 +285,6 @@ is_chat_or_normal_message(_Packet) -> false.
list(User, Server)->
mnesia:dirty_select(?TABLE, [{#carboncopy{us = {User, Server}, resource = '$2', version = '$3'}, [], [{{'$2','$3'}}]}]).
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(_) -> [iqdisc].
+15 -2
View File
@@ -25,11 +25,14 @@
-module(mod_client_state).
-author('holger@zedat.fu-berlin.de').
-protocol({xep, 85, '2.1'}).
-protocol({xep, 352, '0.1'}).
-behavior(gen_mod).
-export([start/2, stop/1, add_stream_feature/2, filter_presence/2,
filter_chat_states/2]).
-export([start/2, stop/1, add_stream_feature/2,
filter_presence/2, filter_chat_states/2,
mod_opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -107,3 +110,13 @@ filter_chat_states(_Action, #xmlel{name = <<"message">>} = Stanza) ->
{stop, send}
end;
filter_chat_states(Action, _Stanza) -> Action.
mod_opt_type(drop_chat_states) ->
fun (true) -> true;
(false) -> false
end;
mod_opt_type(queue_presence) ->
fun (true) -> true;
(false) -> false
end;
mod_opt_type(_) -> [drop_chat_states, queue_presence].
+7 -6
View File
@@ -23,20 +23,19 @@
%%%
%%%----------------------------------------------------------------------
%%% Implements most of XEP-0133: Service Administration Version 1.1
%%% (2005-08-19)
-module(mod_configure).
-author('alexey@process-one.net').
-protocol({xep, 133, '1.1'}).
-behaviour(gen_mod).
-export([start/2, stop/1, get_local_identity/5,
get_local_features/5, get_local_items/5,
adhoc_local_items/4, adhoc_local_commands/4,
get_sm_identity/5, get_sm_features/5, get_sm_items/5,
adhoc_sm_items/4, adhoc_sm_commands/4]).
adhoc_sm_items/4, adhoc_sm_commands/4, mod_opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -2023,14 +2022,14 @@ stop_node(From, Host, ENode, Action, XData) ->
#xmlel{name = <<"x">>,
attrs =
[{<<"xmlns">>,
<<"jabber:x:data">>},
?NS_XDATA},
{<<"type">>, <<"submit">>}],
children = SubEls},
others =
[#xmlel{name = <<"x">>,
attrs =
[{<<"xmlns">>,
<<"jabber:x:data">>},
?NS_XDATA},
{<<"type">>, <<"submit">>}],
children = SubEls}]},
To = jlib:make_jid(<<"">>, Host, <<"">>),
@@ -2149,3 +2148,5 @@ set_sm_form(User, Server, <<"config">>,
end;
set_sm_form(_User, _Server, _Node, _Request, _Fields) ->
{error, ?ERR_SERVICE_UNAVAILABLE}.
mod_opt_type(_) -> [].
+22 -1
View File
@@ -25,11 +25,14 @@
-module(mod_configure2).
-behaviour(ejabberd_config).
-author('alexey@process-one.net').
-behaviour(gen_mod).
-export([start/2, stop/1, process_local_iq/3]).
-export([start/2, stop/1, process_local_iq/3,
mod_opt_type/1, opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -195,3 +198,21 @@ process_get(#xmlel{name = <<"last">>, attrs = Attrs}) ->
%%process_get({xmlelement, Name, Attrs, SubEls}) ->
%% {result, };
process_get(_) -> {error, ?ERR_BAD_REQUEST}.
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(_) -> [iqdisc].
opt_type(registration_watchers) ->
fun (JIDs) when is_list(JIDs) ->
lists:map(fun (J) ->
#xmlel{name = <<"jid">>, attrs = [],
children =
[{xmlcdata, iolist_to_binary(J)}]}
end,
JIDs)
end;
opt_type(welcome_message) ->
fun ({Subj, Body}) ->
{iolist_to_binary(Subj), iolist_to_binary(Body)}
end;
opt_type(_) -> [registration_watchers, welcome_message].

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