Compare commits
598 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e87d332394 | |||
| bc7f93ad1e | |||
| 9f822dd2b8 | |||
| 3cba2cb1ec | |||
| 834c680f97 | |||
| f075e92f08 | |||
| fbb512cb5a | |||
| 0f80523736 | |||
| 01e1f677c7 | |||
| cf929e730f | |||
| 5c32ba49e2 | |||
| 2ccbff3b98 | |||
| d00f0fb1f4 | |||
| 7fd7e53e4a | |||
| ed502673f4 | |||
| 87d2eb5f9a | |||
| 0c501b760f | |||
| 0a047d790f | |||
| c4d17d939d | |||
| 561025ba32 | |||
| 15e77e9c0f | |||
| 120e581865 | |||
| 528aabf49c | |||
| 18d9f18642 | |||
| a983df4848 | |||
| 0559edd1cd | |||
| 2683b340ae | |||
| cc7b68b7c5 | |||
| 104009b3a9 | |||
| e01eb734b4 | |||
| cb57cfa1a6 | |||
| 146adce3d6 | |||
| 2c4647a980 | |||
| 7690320f0f | |||
| 4575649e10 | |||
| d53a54d900 | |||
| 479da33092 | |||
| f650fc83ae | |||
| 17a7844e40 | |||
| 864e113256 | |||
| e7e8f2f63a | |||
| 3063a84fe2 | |||
| 5a35405cd5 | |||
| 4ef2d08456 | |||
| ede5a353e8 | |||
| b88fa6f617 | |||
| 3882c4d514 | |||
| d24dc4e9c8 | |||
| afaf68159d | |||
| a7f578089a | |||
| 173d9761ca | |||
| 9dc9d75502 | |||
| 06db65e108 | |||
| cc958f7787 | |||
| 8781c8346b | |||
| ad4b41730e | |||
| 5935b4e104 | |||
| d1f09a29b9 | |||
| df88d9f2e5 | |||
| 466278fde1 | |||
| 0a19dac4fd | |||
| 7e6d310fe4 | |||
| ffe3ea8917 | |||
| 455039ae69 | |||
| a78a0a65fe | |||
| ba8f38e2eb | |||
| 9899935e42 | |||
| 865509757c | |||
| 2cb16bc509 | |||
| 00dfcc1e10 | |||
| 4163626844 | |||
| f60c721f84 | |||
| e97e56d776 | |||
| 6b916e7a04 | |||
| 6279c3fd8d | |||
| 6900a41e7d | |||
| a456482e2f | |||
| 30687c40ef | |||
| 16311b73c8 | |||
| b85357d280 | |||
| 946b64e166 | |||
| 46d035c142 | |||
| 982215d644 | |||
| 5afa1f6ade | |||
| c566b1d01e | |||
| 84c227e6ae | |||
| ab12270837 | |||
| 3b96525550 | |||
| 62ccf1cf0e | |||
| d5ecd32cec | |||
| e770d3174d | |||
| 2446b66016 | |||
| f69d1ca282 | |||
| 830fdccd21 | |||
| 5cc30c3977 | |||
| 8efae1f05b | |||
| de3e1c3508 | |||
| 8184326eb9 | |||
| f47a59de2f | |||
| ee0ecd2419 | |||
| 7138cc5633 | |||
| f95f22aea0 | |||
| 25e5253f33 | |||
| 41dc1efde4 | |||
| 1d2efcc168 | |||
| dfb21e802e | |||
| 9a0b951855 | |||
| 7819986ec0 | |||
| 295681283a | |||
| 5b0d8b7776 | |||
| 1d2ef85b33 | |||
| b550f247e7 | |||
| 565f064b15 | |||
| 7db4587eeb | |||
| fad0d867fc | |||
| 56dab7ddbe | |||
| 74b67fa0dc | |||
| 067958d705 | |||
| dec1e1f67f | |||
| 76b9098a25 | |||
| 2399aba67d | |||
| 94cdcd7b34 | |||
| bf33f74ef8 | |||
| 8cf43cf750 | |||
| 2d748115ee | |||
| 0b22277b11 | |||
| c7d9b46b6f | |||
| d2edcf1288 | |||
| 160c9d7698 | |||
| ecd35f7ba8 | |||
| 0c24e18b5e | |||
| 96d6aacede | |||
| adaa067333 | |||
| 724a31fa13 | |||
| 1ccc0d8bcb | |||
| 3f3f64c217 | |||
| 97fa57c360 | |||
| 7bdc1151b1 | |||
| 4bbf16b21a | |||
| d87ca9fb7b | |||
| 7b3209cc7f | |||
| 1d782db84f | |||
| e109f352e3 | |||
| 6e63ee480e | |||
| 90fb19797d | |||
| 415936146b | |||
| 277e1dc3ff | |||
| 56175fef1b | |||
| ef89497d3f | |||
| 7aec0337e1 | |||
| e49cf604e9 | |||
| 61c8836740 | |||
| 57dec40007 | |||
| 29a841d8c7 | |||
| c18413c52b | |||
| 0a9212583d | |||
| 19446967fa | |||
| 8d9a9228d9 | |||
| 72fd353988 | |||
| c90786527e | |||
| 1a320baad8 | |||
| b8c98232b8 | |||
| f723c00762 | |||
| 4d59f677a9 | |||
| 7a48e30523 | |||
| f0887e45b8 | |||
| 2ca563e328 | |||
| 2e169167d4 | |||
| 11b2921971 | |||
| 646b445515 | |||
| 50d7046517 | |||
| c3eaa29f70 | |||
| ac2ba399a9 | |||
| fda73c3d16 | |||
| a1ce33ebf8 | |||
| 9be9949dab | |||
| 0f1d95a074 | |||
| 2430e6691b | |||
| bfd028beea | |||
| 2cb0f92fe6 | |||
| 2ae7d0a122 | |||
| f1ad6f017b | |||
| c658984531 | |||
| 191eeed7c9 | |||
| 01a3c1c2e1 | |||
| 8e3a49d369 | |||
| c48b7f272b | |||
| 4a9417c501 | |||
| 72049e5323 | |||
| 33e0bf1c19 | |||
| 5ed7f10153 | |||
| 2802b6cee2 | |||
| 44828c54fe | |||
| ae0d31a8c9 | |||
| 7274dafe10 | |||
| bc2e26fecd | |||
| 2d4c39cd54 | |||
| 9484b11383 | |||
| 848e1497d1 | |||
| 2daf95e93f | |||
| 1b1d9b5a73 | |||
| 5836eb5bc2 | |||
| 5c88f6423a | |||
| 56d61c2784 | |||
| 0917209711 | |||
| 8c22b154c9 | |||
| 436f0832c1 | |||
| 5d0de39127 | |||
| 92f89e3d45 | |||
| f91caf7108 | |||
| 38c016a041 | |||
| 4f63cb21c2 | |||
| 2e70c59471 | |||
| f00725dffb | |||
| 4205108f30 | |||
| 651de2ca8e | |||
| e79290fb56 | |||
| db3c469d4d | |||
| 7d93463d31 | |||
| 5d79dff4f3 | |||
| 58fd56e6a2 | |||
| f1e6365ee1 | |||
| 4a02df8b6d | |||
| bee9ffd91e | |||
| 3e232952ea | |||
| c0001184fd | |||
| abeaac1c11 | |||
| 6427d9398a | |||
| 677b358a9a | |||
| b997c4325a | |||
| 9c279f2e06 | |||
| 46f01b962a | |||
| 9db39a5e4c | |||
| 43000d9ce4 | |||
| 33368b7e5c | |||
| a087af7060 | |||
| 3d3a4f7543 | |||
| 9ff3ce8bd1 | |||
| 4efca05149 | |||
| f19e19e2b6 | |||
| 25676b43ed | |||
| 870d822f08 | |||
| 320abee110 | |||
| 0579fc80ec | |||
| 08ff969896 | |||
| 40ef406ec7 | |||
| 790201afc0 | |||
| f2003943db | |||
| 014d61955c | |||
| c068712373 | |||
| 467ccdffbd | |||
| 48d7ec1a92 | |||
| 105b421418 | |||
| 277fe5ab25 | |||
| 744018425b | |||
| 1f4e0c8aea | |||
| e0c9242dcf | |||
| 0456b78d87 | |||
| 568068c79f | |||
| b5c4fe6626 | |||
| 64205426bf | |||
| 89025eea39 | |||
| 4a918c5b18 | |||
| 9a7c26eaa8 | |||
| eb803832b7 | |||
| 4ef0dd6997 | |||
| b5f1b17926 | |||
| fd298521e2 | |||
| 99c28ab4d6 | |||
| 2d6a838905 | |||
| 792b5a24df | |||
| 19cc687928 | |||
| 86a6667122 | |||
| 07501f8085 | |||
| dd77236d75 | |||
| 926c9193e7 | |||
| a5987633e0 | |||
| aa8dce9804 | |||
| edfb5fc2f8 | |||
| 91fcdf9f6a | |||
| 54cfd5091f | |||
| 2fe8e0dea5 | |||
| 9d62d13492 | |||
| f40d5e4a89 | |||
| c559c9425a | |||
| 6a73b96459 | |||
| 538d4ffbd0 | |||
| c15dc01cff | |||
| f1d0b05db5 | |||
| a60dd672b7 | |||
| e82219185b | |||
| 0490c2f139 | |||
| a4b02c38db | |||
| 47763c10e3 | |||
| fc692ea512 | |||
| 28479321bb | |||
| 2b8c4acd57 | |||
| ee40c0e9a7 | |||
| 9a55ffba7a | |||
| 50a73d1188 | |||
| 76ebebf2a0 | |||
| aba7150af1 | |||
| 26a4d91297 | |||
| 9265720f92 | |||
| 273631c242 | |||
| bb8a0f71e6 | |||
| ffdb39d269 | |||
| 8fae4748a1 | |||
| 643a31dcea | |||
| 31440a586c | |||
| 1ef2dd45f3 | |||
| b29615561c | |||
| 7892b72bcb | |||
| 4b82a38cf7 | |||
| c20acbf4d8 | |||
| e66899e68e | |||
| 87f8c2ecd8 | |||
| 62be3bc111 | |||
| c485aea48b | |||
| 6f4b4ad087 | |||
| 3e8a0af6d1 | |||
| 12ab5a749f | |||
| ddfbca5830 | |||
| 9e72529544 | |||
| 11aa51373a | |||
| 5992582bc5 | |||
| e0e74a9d5e | |||
| cc228db337 | |||
| c546ce2439 | |||
| fdda4d506f | |||
| 5de16493d1 | |||
| 2381a8d609 | |||
| 39f1005006 | |||
| 6441c284e0 | |||
| 0aea9c74bd | |||
| 9a0d77571d | |||
| f446e7fc0b | |||
| b75b5ebeb2 | |||
| d19903877d | |||
| f271ea6eef | |||
| c76201b6b4 | |||
| 86f2af6fdc | |||
| da22da23cd | |||
| f45654a16a | |||
| bb952f9ecc | |||
| ad2d3964ef | |||
| 2cd17c7988 | |||
| 32998f7e18 | |||
| 7261cb29ac | |||
| 8fb1bb1f5f | |||
| 5a29d56d94 | |||
| 0cb9ea3643 | |||
| 7d54fdea51 | |||
| 99ca8281fa | |||
| 3a27b1dd0c | |||
| f9c5e349fb | |||
| 50a4c5a6ab | |||
| ed0c89f876 | |||
| 702cddd4ff | |||
| 4d1332c30f | |||
| 402fb9665d | |||
| b2e84405c1 | |||
| 52221127cc | |||
| dceab3689d | |||
| 123b01aaa0 | |||
| 572938aa49 | |||
| 48600ae71d | |||
| 59f6efeaf7 | |||
| 737b0ae5dc | |||
| 8925975c86 | |||
| ab9667f917 | |||
| 6baf3a24de | |||
| 735bd95659 | |||
| 69abb48c90 | |||
| 419a98d45a | |||
| 0dc8429d16 | |||
| b9210d491a | |||
| 5d855f3723 | |||
| 6b996061a2 | |||
| fca640f50f | |||
| 5010cea1a4 | |||
| 5726636053 | |||
| b7a542e074 | |||
| 9c37450fe4 | |||
| c39ce133de | |||
| dd543af2f6 | |||
| 6d06f22f64 | |||
| 862166511c | |||
| 4e54c53abb | |||
| a6ddab1e9d | |||
| 3c045ba8aa | |||
| 6e8dd5bdff | |||
| f6da708b02 | |||
| 23fdf0e889 | |||
| 9121ca14de | |||
| f4a3dbea70 | |||
| 47efe4e6a9 | |||
| 03fd88e4ec | |||
| 9b16d09261 | |||
| 5d22159e9a | |||
| 003fd321ee | |||
| 6d5bfcfe9b | |||
| 15369ff9d7 | |||
| a60fda7df4 | |||
| 318b0f2208 | |||
| b995178e30 | |||
| 181e7a823e | |||
| 0716a8cdae | |||
| 90a5c054d4 | |||
| 115da54557 | |||
| e88a5c6b3c | |||
| 79a49b1175 | |||
| c511194c2e | |||
| d3ed12d4ba | |||
| e7c94975eb | |||
| 47f627e605 | |||
| d343447cc9 | |||
| cc1f93d7a0 | |||
| 58717923eb | |||
| 1aa56af541 | |||
| 8b1f92575a | |||
| 66437c5e4d | |||
| 52f3acbdb1 | |||
| a6244275b7 | |||
| 402dec8354 | |||
| 4bdf1bc7a6 | |||
| faa6ad26a0 | |||
| bd0060715e | |||
| 530ac43758 | |||
| 2723056fae | |||
| f3aa74a043 | |||
| 872cc12dd8 | |||
| 70f00a1b1f | |||
| 3b3f3b9131 | |||
| 32abcbca6c | |||
| a0917a8e9b | |||
| fafec77e56 | |||
| 478b4f19bd | |||
| b73b139f24 | |||
| 806c0e56e1 | |||
| d0ffcb7fd4 | |||
| 955487391d | |||
| e00215a12f | |||
| 47a39ce738 | |||
| ebd760b7c9 | |||
| f8417f7c1f | |||
| 3c98de69dc | |||
| ab6774d93d | |||
| 58aa200297 | |||
| a1337cb73f | |||
| e7e4055cbb | |||
| 1d771fe646 | |||
| 8e2bc8d19e | |||
| 0117787317 | |||
| 16e5d66572 | |||
| 6a95422af8 | |||
| 35faffe7da | |||
| a6fe7425dd | |||
| d83368d73d | |||
| c545b3de6d | |||
| 02e0649d18 | |||
| 0904b8b8ff | |||
| ec6c58a21c | |||
| b3714a1b2e | |||
| 81a906af01 | |||
| 65519cf262 | |||
| a1b8c54c16 | |||
| a6408e9281 | |||
| 0e0bd3329d | |||
| ce22239d85 | |||
| 375a1dd759 | |||
| 9563b0228f | |||
| 8419322884 | |||
| c37aa1b46d | |||
| 599fdb9ac2 | |||
| ebbceab93f | |||
| bb2c8b59f8 | |||
| 0af3f9388f | |||
| 4073394e7a | |||
| 29aead19d9 | |||
| 16dd6b03c6 | |||
| d09c268b20 | |||
| 6d1055abec | |||
| 68e62d7442 | |||
| 49bdbf2895 | |||
| a21d2298af | |||
| 1aa4ed3f35 | |||
| eabca82765 | |||
| 71dba66330 | |||
| d805d198ac | |||
| 0734562ded | |||
| ffe9f3c192 | |||
| 219f9276d1 | |||
| f988aad940 | |||
| 3a3f8240c1 | |||
| 9ec014c184 | |||
| e9d104ec47 | |||
| 86e17c379c | |||
| 4bc8b6bc9f | |||
| 9497dbff17 | |||
| 37d4109e8a | |||
| b73f28c93e | |||
| c98d539bb3 | |||
| 4b52a8e4e3 | |||
| d350cc6361 | |||
| 727197613a | |||
| cc6a4787af | |||
| 27a7b38dee | |||
| 45687c52dc | |||
| 7af7b7d3f0 | |||
| d97b4fd9ca | |||
| f93758a3cd | |||
| 77d6d36a9d | |||
| 57ba57b908 | |||
| c9d4f2146c | |||
| 46001aafaa | |||
| ad680c508e | |||
| be43aa85f4 | |||
| 285c4c17cf | |||
| a21edc2f3a | |||
| 515331baad | |||
| b3b12effbc | |||
| fbf71f86f3 | |||
| 9d5426315f | |||
| c114eb3736 | |||
| 66006ba017 | |||
| f3bbfb1c66 | |||
| 766ab1eb46 | |||
| 76fb7d284a | |||
| 2d441b3305 | |||
| 0befeb7d93 | |||
| a2679e9d51 | |||
| 37f409d254 | |||
| e02a4913d2 | |||
| 1250ee5d77 | |||
| 8b9c49440a | |||
| 5bf3c784da | |||
| a5a065290b | |||
| ac0e199d36 | |||
| a97c716352 | |||
| 2150b10901 | |||
| 5c36c44689 | |||
| d5f90965d7 | |||
| 2da6933bb7 | |||
| e360c56f87 | |||
| 2b527f5e9a | |||
| 88a200e100 | |||
| 633d47f784 | |||
| 7d594086c3 | |||
| 0f0e99ccd3 | |||
| 9ef1ad0b6e | |||
| afba5bc5f5 | |||
| 4a02893dac | |||
| e211bf522e | |||
| 46b2d91105 | |||
| c29ba14dbf | |||
| 4c8aeefa7f | |||
| 8e628fdad3 | |||
| 8538997d61 | |||
| 26dee37268 | |||
| e82a79efd5 | |||
| 63a7011c38 | |||
| 4c8b6fe16b | |||
| 565b8bf7e6 | |||
| 5ccc6db093 | |||
| 9422164dda | |||
| cbbfd921b4 | |||
| d63be79df9 | |||
| 155c8bb29a | |||
| e107e78773 | |||
| 27302fb7ac | |||
| d03de1bb43 | |||
| 33764bb931 | |||
| eadc899046 | |||
| 5a1300bc70 | |||
| 9c17163b55 | |||
| e11c835bd3 | |||
| 5ecd832e81 | |||
| a95aa46fe5 | |||
| 1dd94ac0d0 | |||
| a6b0e18bde | |||
| 89a17ba84a | |||
| a87b475361 | |||
| b7c7d2747b | |||
| c0240e7249 | |||
| 6dd31299cf | |||
| 2846a2978b | |||
| 6df09f5ad6 | |||
| d9da6b77de | |||
| cd0381bab5 | |||
| f2f2f64161 | |||
| 2c09d7c8a7 | |||
| 389a99b2db | |||
| 07c8bf5064 | |||
| 7fd91a4b12 | |||
| ae4356265f | |||
| a0396620f2 | |||
| 7e73ed88f7 |
+8
-2
@@ -7,6 +7,7 @@
|
||||
/Makefile
|
||||
/config.log
|
||||
/config.status
|
||||
/configure
|
||||
/aclocal.m4
|
||||
/contrib/extract_translations/extract_translations.beam
|
||||
/*.cache
|
||||
@@ -24,11 +25,16 @@
|
||||
/doc/*.toc
|
||||
/doc/contributed_modules.tex
|
||||
/doc/version.tex
|
||||
/ebin/*.beam
|
||||
/ebin/ejabberd.app
|
||||
/ebin/
|
||||
/ejabberd.init
|
||||
/ejabberdctl.example
|
||||
/include/XmppAddr.hrl
|
||||
/rel/ejabberd/
|
||||
/src/XmppAddr.asn1db
|
||||
/src/XmppAddr.erl
|
||||
/src/ejabberd.app.src
|
||||
/src/eldap_filter_yecc.erl
|
||||
/vars.config
|
||||
/dialyzer/
|
||||
/test/*.beam
|
||||
/logs/
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
language: erlang
|
||||
|
||||
otp_release:
|
||||
- R16B03
|
||||
- R15B01
|
||||
|
||||
services:
|
||||
- riak
|
||||
|
||||
before_install:
|
||||
- sudo apt-get -qq update
|
||||
|
||||
install:
|
||||
- sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev
|
||||
|
||||
before_script:
|
||||
- mysql -u root -e "CREATE USER 'ejabberd_test'@'localhost' IDENTIFIED BY 'ejabberd_test';"
|
||||
- mysql -u root -e "CREATE DATABASE ejabberd_test;"
|
||||
- mysql -u root -e "GRANT ALL ON ejabberd_test.* TO 'ejabberd_test'@'localhost';"
|
||||
- psql -U postgres -c "CREATE USER ejabberd_test WITH PASSWORD 'ejabberd_test';"
|
||||
- psql -U postgres -c "CREATE DATABASE ejabberd_test;"
|
||||
- psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE ejabberd_test TO ejabberd_test;"
|
||||
|
||||
script:
|
||||
- ./autogen.sh
|
||||
- ./configure --enable-all --disable-odbc --disable-elixir
|
||||
- make xref
|
||||
- ERL_LIBS=$PWD make test
|
||||
- grep -q 'TEST COMPLETE, \([[:digit:]]*\) ok, .* of \1 ' logs/raw.log
|
||||
|
||||
after_script:
|
||||
- find logs -name suite.log -exec cat '{}' ';'
|
||||
|
||||
after_failure:
|
||||
- find logs -name ejabberd.log -exec cat '{}' ';'
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
@@ -4,8 +4,8 @@ with the OpenSSL library and distribute the resulting binary.
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@@ -306,9 +306,9 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
+29
-4
@@ -11,6 +11,9 @@ DESTDIR =
|
||||
# /etc/ejabberd/
|
||||
ETCDIR = $(DESTDIR)@sysconfdir@/ejabberd
|
||||
|
||||
# /bin/
|
||||
BINDIR = $(DESTDIR)@bindir@
|
||||
|
||||
# /sbin/
|
||||
SBINDIR = $(DESTDIR)@sbindir@
|
||||
|
||||
@@ -88,6 +91,10 @@ update:
|
||||
rm -rf deps/.built
|
||||
$(REBAR) update-deps && :> deps/.got
|
||||
|
||||
xref: all
|
||||
$(REBAR) skip_deps=true xref
|
||||
|
||||
|
||||
translations:
|
||||
contrib/extract_translations/prepare-translation.sh -updateall
|
||||
|
||||
@@ -114,6 +121,7 @@ install: all
|
||||
|| $(INSTALL) -b -m 640 $(G_USER) ejabberd.yml.example $(ETCDIR)/ejabberd.yml
|
||||
$(SED) -e "s*{{rootdir}}*@prefix@*" \
|
||||
-e "s*{{installuser}}*@INSTALLUSER@*" \
|
||||
-e "s*{{bindir}}*@bindir@*" \
|
||||
-e "s*{{libdir}}*@libdir@*" \
|
||||
-e "s*{{sysconfdir}}*@sysconfdir@*" \
|
||||
-e "s*{{localstatedir}}*@localstatedir@*" \
|
||||
@@ -128,6 +136,11 @@ install: all
|
||||
# Administration script
|
||||
[ -d $(SBINDIR) ] || $(INSTALL) -d -m 755 $(SBINDIR)
|
||||
$(INSTALL) -m 550 $(G_USER) ejabberdctl.example $(SBINDIR)/ejabberdctl
|
||||
# Elixir binaries
|
||||
[ -d $(BINDIR) ] || $(INSTALL) -d -m 755 $(BINDIR)
|
||||
-[ -f deps/elixir/bin/iex ] && $(INSTALL) -m 550 $(G_USER) deps/elixir/bin/iex $(BINDIR)/iex
|
||||
-[ -f deps/elixir/bin/elixir ] && $(INSTALL) -m 550 $(G_USER) deps/elixir/bin/elixir $(BINDIR)/elixir
|
||||
-[ -f deps/elixir/bin/mix ] && $(INSTALL) -m 550 $(G_USER) deps/elixir/bin/mix $(BINDIR)/mix
|
||||
#
|
||||
# Init script
|
||||
$(SED) -e "s*@ctlscriptpath@*$(SBINDIR)*" \
|
||||
@@ -141,6 +154,9 @@ install: all
|
||||
$(INSTALL) -m 644 ebin/*.beam $(BEAMDIR)
|
||||
$(INSTALL) -m 644 deps/*/ebin/*.app $(BEAMDIR)
|
||||
$(INSTALL) -m 644 deps/*/ebin/*.beam $(BEAMDIR)
|
||||
# Install Elixir and Elixir dependancies
|
||||
-$(INSTALL) -m 644 deps/*/lib/*/ebin/*.app $(BEAMDIR)
|
||||
-$(INSTALL) -m 644 deps/*/lib/*/ebin/*.beam $(BEAMDIR)
|
||||
rm -f $(BEAMDIR)/configure.beam
|
||||
#
|
||||
# ejabberd header files
|
||||
@@ -151,10 +167,13 @@ install: all
|
||||
# Binary C programs
|
||||
$(INSTALL) -d $(PBINDIR)
|
||||
$(INSTALL) -m 750 $(O_USER) tools/captcha.sh $(PBINDIR)
|
||||
-[ -f deps/p1_pam/priv/bin/epam ] \
|
||||
&& $(INSTALL) -m 750 $(O_USER) deps/p1_pam/priv/bin/epam $(PBINDIR)
|
||||
#
|
||||
# Binary system libraries
|
||||
$(INSTALL) -d $(SODIR)
|
||||
$(INSTALL) -m 644 $(DLLs) $(SODIR)
|
||||
-[ -f $(SODIR)/jiffy.so ] && (cd $(PRIVDIR); ln -s lib/jiffy.so; true)
|
||||
#
|
||||
# Translated strings
|
||||
$(INSTALL) -d $(MSGSDIR)
|
||||
@@ -178,19 +197,25 @@ install: all
|
||||
#
|
||||
# Documentation
|
||||
$(INSTALL) -d $(DOCDIR)
|
||||
$(INSTALL) -m 644 doc/dev.html $(DOCDIR)
|
||||
$(INSTALL) -m 644 doc/guide.html $(DOCDIR)
|
||||
$(INSTALL) -m 644 doc/*.png $(DOCDIR)
|
||||
$(INSTALL) -m 644 doc/*.txt $(DOCDIR)
|
||||
[ -f doc/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)
|
||||
$(INSTALL) -m 644 COPYING $(DOCDIR)
|
||||
|
||||
uninstall: uninstall-binary
|
||||
|
||||
uninstall-binary:
|
||||
rm -f $(SBINDIR)/ejabberdctl
|
||||
rm -f $(BINDIR)/iex
|
||||
rm -f $(BINDIR)/elixir
|
||||
rm -f $(BINDIR)/mix
|
||||
rm -fr $(DOCDIR)
|
||||
rm -f $(BEAMDIR)/*.beam
|
||||
rm -f $(BEAMDIR)/*.app
|
||||
|
||||
@@ -1,52 +1,161 @@
|
||||
ejabberd - High-Performance Enterprise Instant Messaging Server
|
||||
ejabberd Community Edition, by ProcessOne
|
||||
=========================================
|
||||
|
||||
ejabberd is a distributed, fault-tolerant technology that allows the creation
|
||||
of large-scale instant messaging applications. The server can reliably support
|
||||
thousands of simultaneous users on a single node and has been designed to
|
||||
provide exceptional standards of fault tolerance. As an open source
|
||||
technology, based on industry-standards, ejabberd can be used to build bespoke
|
||||
solutions very cost effectively.
|
||||
|
||||
|
||||
Key Features
|
||||
------------
|
||||
|
||||
- **Cross-platform**
|
||||
ejabberd runs under Microsoft Windows and Unix-derived systems such as
|
||||
Linux, FreeBSD and NetBSD.
|
||||
|
||||
- **Distributed**
|
||||
You can run ejabberd on a cluster of machines and all of them will serve the
|
||||
same XMPP 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.
|
||||
|
||||
- **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’.
|
||||
|
||||
- **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:
|
||||
- Comprehensive documentation.
|
||||
- Straightforward installers for Linux and Mac OS X.
|
||||
- Web administration.
|
||||
- Shared roster groups.
|
||||
- Command line administration tool.
|
||||
- Can integrate with existing authentication mechanisms.
|
||||
- Capability to send announce messages.
|
||||
|
||||
- **Internationalized**
|
||||
ejabberd leads in internationalization. Hence it is very well suited in a
|
||||
globalized world. Related features are:
|
||||
- Translated to 25 languages.
|
||||
- Support for IDNA.
|
||||
|
||||
- **Open Standards**
|
||||
ejabberd is the first Open Source Jabber server claiming to fully comply to
|
||||
the XMPP standard.
|
||||
- Fully XMPP-compliant.
|
||||
- XML-based protocol.
|
||||
- Many protocols supported.
|
||||
|
||||
|
||||
Additional Features
|
||||
-------------------
|
||||
|
||||
Moreover, ejabberd comes with a wide range of other state-of-the-art features:
|
||||
|
||||
- **Modularity**
|
||||
- Load only the modules you want.
|
||||
- Extend ejabberd with your own custom modules.
|
||||
|
||||
- **Security**
|
||||
- SASL and STARTTLS for c2s and s2s connections.
|
||||
- STARTTLS and Dialback s2s connections.
|
||||
- Web Admin accessible via HTTPS secure access.
|
||||
|
||||
- **Databases**
|
||||
- Internal database for fast deployment (Mnesia).
|
||||
- Native MySQL support.
|
||||
- Native PostgreSQL support.
|
||||
- ODBC data storage support.
|
||||
- Microsoft SQL Server support.
|
||||
|
||||
- **Authentication**
|
||||
- Internal authentication.
|
||||
- PAM, LDAP and ODBC.
|
||||
- External authentication script.
|
||||
|
||||
- **Others**
|
||||
- Support for virtual hosting.
|
||||
- Compressing XML streams with Stream Compression (XEP-0138).
|
||||
- Statistics via Statistics Gathering (XEP-0039).
|
||||
- IPv6 support both for c2s and s2s connections.
|
||||
- Multi-User Chat module with support for clustering and HTML logging.
|
||||
- Users Directory based on users vCards.
|
||||
- Publish-Subscribe component with support for Personal Eventing.
|
||||
- Support for web clients: HTTP Polling and HTTP Binding (BOSH).
|
||||
- IRC transport.
|
||||
- Component support: interface with networks such as AIM, ICQ and MSN.
|
||||
|
||||
|
||||
Quickstart guide
|
||||
----------------
|
||||
|
||||
|
||||
0. Requirements
|
||||
### 0. Requirements
|
||||
|
||||
To compile ejabberd you need:
|
||||
- GNU Make
|
||||
- GCC
|
||||
- Libexpat 1.95 or higher
|
||||
- Libyaml 1.4 or higher
|
||||
|
||||
- GNU Make.
|
||||
- GCC.
|
||||
- Libexpat 1.95 or higher.
|
||||
- Libyaml 0.1.4 or higher.
|
||||
- Erlang/OTP R15B or higher.
|
||||
- OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption.
|
||||
- Zlib 1.2.3 or higher, for Stream Compression support
|
||||
(XEP-0138). Optional.
|
||||
- Zlib 1.2.3 or higher, for Stream Compression support (XEP-0138). Optional.
|
||||
- PAM library. Optional. For Pluggable Authentication Modules (PAM).
|
||||
- GNU Iconv 1.8 or higher, for the IRC Transport
|
||||
(mod_irc). Optional. Not needed on systems with GNU Libc.
|
||||
- GNU Iconv 1.8 or higher, for the IRC Transport (mod_irc). Optional. Not
|
||||
needed on systems with GNU Libc.
|
||||
- ImageMagick's Convert program. Optional. For CAPTCHA challenges.
|
||||
- exmpp 0.9.6 or higher. Optional. For import/export XEP-0227 files.
|
||||
|
||||
|
||||
1. Compile and install on *nix systems
|
||||
### 1. Compile and install on *nix systems
|
||||
|
||||
To compile ejabberd execute the commands:
|
||||
./configure
|
||||
make
|
||||
To compile ejabberd, execute the following commands. The first one is only
|
||||
necessary if your source tree didn't come with a `configure` script.
|
||||
|
||||
To install ejabberd, run this command with system administrator rights
|
||||
(root user):
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
|
||||
sudo make install
|
||||
To install ejabberd, run this command with system administrator rights (root
|
||||
user):
|
||||
|
||||
sudo make install
|
||||
|
||||
These commands will:
|
||||
- Install the configuration files in /etc/ejabberd/
|
||||
- Install ejabberd binary, header and runtime files in /lib/ejabberd/
|
||||
- Install the administration script: /sbin/ejabberdctl
|
||||
- Install ejabberd documentation in /share/doc/ejabberd/
|
||||
- Create a spool directory: /var/lib/ejabberd/
|
||||
- Create a directory for log files: /var/log/ejabberd/
|
||||
|
||||
- Install the configuration files in `/etc/ejabberd/`
|
||||
- Install ejabberd binary, header and runtime files in `/lib/ejabberd/`
|
||||
- Install the administration script: `/sbin/ejabberdctl`
|
||||
- Install ejabberd documentation in `/share/doc/ejabberd/`
|
||||
- Create a spool directory: `/var/lib/ejabberd/`
|
||||
- Create a directory for log files: `/var/log/ejabberd/`
|
||||
|
||||
|
||||
2. Start ejabberd
|
||||
### 2. Start ejabberd
|
||||
|
||||
You can use the ejabberdctl command line administration script to
|
||||
You can use the `ejabberdctl` command line administration script to
|
||||
start and stop ejabberd. For example:
|
||||
ejabberdctl start
|
||||
|
||||
ejabberdctl start
|
||||
|
||||
|
||||
For detailed information please refer to the
|
||||
ejabberd Installation and Operation Guide
|
||||
For detailed information please refer to the ejabberd Installation and
|
||||
Operation Guide available online and in the `doc` directory of the source
|
||||
tarball.
|
||||
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
- Guide: https://www.process-one.net/docs/ejabberd/guide_en.html
|
||||
- Official site: https://www.process-one.net/en/ejabberd
|
||||
- Community site: https://www.ejabberd.im
|
||||
- Forum: https://www.process-one.net/en/forum
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
# generate a new autoconf
|
||||
aclocal -I m4
|
||||
autoconf
|
||||
autoconf -f
|
||||
|
||||
+22
-47
@@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.53)
|
||||
AC_INIT(ejabberd, community m4_esyscmd([git describe --tags | tr -d '\n']), [ejabberd@process-one.net], [ejabberd])
|
||||
AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 0.0` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd])
|
||||
REQUIRE_ERLANG_MIN="5.9.1 (Erlang/OTP R15B01)"
|
||||
REQUIRE_ERLANG_MAX="9.0.0 (No Max)"
|
||||
|
||||
@@ -82,12 +82,12 @@ AC_ARG_ENABLE(roster_gateway_workaround,
|
||||
esac],[roster_gateway_workaround=false])
|
||||
|
||||
AC_ARG_ENABLE(transient_supervisors,
|
||||
[AC_HELP_STRING([--enable-transient_supervisors], [use Erlang supervision for transient process (default: no)])],
|
||||
[AC_HELP_STRING([--disable-transient-supervisors], [disable Erlang supervision for transient processes (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) transient_supervisors=true ;;
|
||||
no) transient_supervisors=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-transient_supervisors) ;;
|
||||
esac],[transient_supervisors=false])
|
||||
esac],[transient_supervisors=true])
|
||||
|
||||
AC_ARG_ENABLE(full_xml,
|
||||
[AC_HELP_STRING([--enable-full-xml], [use XML features in XMPP stream (ex: CDATA) (default: no, requires XML compliant clients)])],
|
||||
@@ -106,10 +106,10 @@ AC_ARG_ENABLE(mssql,
|
||||
esac],[db_type=generic])
|
||||
|
||||
AC_ARG_ENABLE(all,
|
||||
[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-pam --enable-zlib --enable-stun --enable-riak --enable-json --enable-iconv --enable-debug --enable-http --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])],
|
||||
[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-pam --enable-zlib --enable-riak --enable-json --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) nif=true odbc=true mysql=true pgsql=true pam=true zlib=true stun=true riak=true json=true iconv=true debug=true http=true lager=true tools=true ;;
|
||||
no) nif=false odbc=false mysql=false pgsql=false pam=false zlib=false stun=false riak=false json=false iconv=false debug=false http=false lager=false tools=false ;;
|
||||
yes) nif=true odbc=true mysql=true pgsql=true pam=true zlib=true riak=true json=true elixir=true iconv=true debug=true lager=true tools=true ;;
|
||||
no) nif=false odbc=false mysql=false pgsql=false pam=false zlib=false riak=false json=false elixir=false iconv=false debug=false lager=false tools=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;;
|
||||
esac],[])
|
||||
|
||||
@@ -169,13 +169,13 @@ AC_ARG_ENABLE(zlib,
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-zlib) ;;
|
||||
esac],[if test "x$zlib" = "x"; then zlib=true; fi])
|
||||
|
||||
AC_ARG_ENABLE(stun,
|
||||
[AC_HELP_STRING([--enable-stun], [enable STUN support (default: no)])],
|
||||
AC_ARG_ENABLE(riak,
|
||||
[AC_HELP_STRING([--enable-riak], [enable Riak support (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) stun=true ;;
|
||||
no) stun=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-stun) ;;
|
||||
esac],[if test "x$stun" = "x"; then stun=false; fi])
|
||||
yes) riak=true ;;
|
||||
no) riak=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-riak) ;;
|
||||
esac],[if test "x$riak" = "x"; then riak=false; fi])
|
||||
|
||||
AC_ARG_ENABLE(json,
|
||||
[AC_HELP_STRING([--enable-json], [enable JSON support for mod_bosh (default: no)])],
|
||||
@@ -185,6 +185,14 @@ AC_ARG_ENABLE(json,
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-json) ;;
|
||||
esac],[if test "x$json" = "x"; then json=false; fi])
|
||||
|
||||
AC_ARG_ENABLE(elixir,
|
||||
[AC_HELP_STRING([--enable-elixir], [enable Elixir support (default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) elixir=true ;;
|
||||
no) elixir=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-elixir) ;;
|
||||
esac],[if test "x$elixir" = "x"; then elixir=false; fi])
|
||||
|
||||
AC_ARG_ENABLE(iconv,
|
||||
[AC_HELP_STRING([--enable-iconv], [enable iconv support (default: yes)])],
|
||||
[case "${enableval}" in
|
||||
@@ -201,14 +209,6 @@ AC_ARG_ENABLE(debug,
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
|
||||
esac],[if test "x$debug" = "x"; then debug=true; fi])
|
||||
|
||||
AC_ARG_ENABLE(http,
|
||||
[AC_HELP_STRING([--enable-http], [build external HTTP libraries ('ibrowse' and 'lhttpc', default: no)])],
|
||||
[case "${enableval}" in
|
||||
yes) http=true ;;
|
||||
no) http=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-http) ;;
|
||||
esac],[if test "x$http" = "x"; then http=false; fi])
|
||||
|
||||
AC_ARG_ENABLE(lager,
|
||||
[AC_HELP_STRING([--enable-lager], [enable lager support (default: yes)])],
|
||||
[case "${enableval}" in
|
||||
@@ -235,31 +235,6 @@ if test "$ENABLEUSER" != ""; then
|
||||
AC_SUBST([INSTALLUSER], [$ENABLEUSER])
|
||||
fi
|
||||
|
||||
AC_ERLANG_CHECK_LIB([sasl], [],
|
||||
[AC_MSG_ERROR([Erlang application 'sasl' was not found])])
|
||||
AC_ERLANG_CHECK_LIB([crypto], [],
|
||||
[AC_MSG_ERROR([Erlang application 'crypto' was not found])])
|
||||
AC_ERLANG_CHECK_LIB([public_key], [],
|
||||
[AC_MSG_ERROR([Erlang application 'public_key' was not found])])
|
||||
AC_ERLANG_CHECK_LIB([ssl], [],
|
||||
[AC_MSG_ERROR([Erlang application 'ssl' was not found])])
|
||||
AC_ERLANG_CHECK_LIB([mnesia], [],
|
||||
[AC_MSG_ERROR([Erlang application 'mnesia' was not found])])
|
||||
AC_ERLANG_CHECK_LIB([inets], [],
|
||||
[AC_MSG_ERROR([Erlang application 'inets' was not found])])
|
||||
AC_ERLANG_CHECK_LIB([compiler], [],
|
||||
[AC_MSG_ERROR([Erlang application 'compiler' was not found])])
|
||||
if test "x$odbc" = "xtrue"; then
|
||||
AC_ERLANG_CHECK_LIB([odbc], [],
|
||||
[AC_MSG_ERROR([Erlang application 'odbc' was not found])])
|
||||
fi
|
||||
if test "x$tools" = "xtrue"; then
|
||||
AC_ERLANG_CHECK_LIB([tools], [],
|
||||
[AC_MSG_ERROR([Erlang application 'tools' was not found])])
|
||||
AC_ERLANG_CHECK_LIB([runtime_tools], [],
|
||||
[AC_MSG_ERROR([Erlang application 'runtime_tools' was not found])])
|
||||
fi
|
||||
|
||||
AC_SUBST(hipe)
|
||||
AC_SUBST(roster_gateway_workaround)
|
||||
AC_SUBST(transient_supervisors)
|
||||
@@ -271,11 +246,11 @@ AC_SUBST(mysql)
|
||||
AC_SUBST(pgsql)
|
||||
AC_SUBST(pam)
|
||||
AC_SUBST(zlib)
|
||||
AC_SUBST(stun)
|
||||
AC_SUBST(riak)
|
||||
AC_SUBST(json)
|
||||
AC_SUBST(elixir)
|
||||
AC_SUBST(iconv)
|
||||
AC_SUBST(debug)
|
||||
AC_SUBST(http)
|
||||
AC_SUBST(lager)
|
||||
AC_SUBST(tools)
|
||||
|
||||
|
||||
@@ -230,7 +230,8 @@ extract_lang_po2msg ()
|
||||
msgattrib $PO_PATH --translated --no-fuzzy --no-obsolete --no-location --no-wrap | grep "^msg" | tail --lines=+3 >$MS_PATH
|
||||
grep "^msgid" $PO_PATH.ms | sed 's/^msgid //g' >$MSGID_PATH
|
||||
grep "^msgstr" $PO_PATH.ms | sed 's/^msgstr //g' >$MSGSTR_PATH
|
||||
paste $MSGID_PATH $MSGSTR_PATH --delimiter=, | awk '{print "{" $0 "}."}' | sort -g >$MSGS_PATH
|
||||
echo "%% -*- coding: latin-1 -*-" >$MSGS_PATH
|
||||
paste $MSGID_PATH $MSGSTR_PATH --delimiter=, | awk '{print "{" $0 "}."}' | sort -g >>$MSGS_PATH
|
||||
|
||||
rm $MS_PATH
|
||||
rm $MSGID_PATH
|
||||
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
# $Id$
|
||||
|
||||
SHELL = /bin/bash
|
||||
SHELL = /bin/sh
|
||||
|
||||
CONTRIBUTED_MODULES = ""
|
||||
#ifeq ($(shell ls mod_http_bind.tex),mod_http_bind.tex)
|
||||
@@ -11,16 +11,16 @@ CONTRIBUTED_MODULES = ""
|
||||
all: release pdf html
|
||||
|
||||
release:
|
||||
@echo "Notes for the releaser:"
|
||||
@echo "* Do not forget to add a link to the release notes in guide.tex"
|
||||
@echo "* Do not forget to update the version number in ebin/ejabberd.app!"
|
||||
@echo "* Do not forget to update the features in introduction.tex (including \new{} and \improved{} tags)."
|
||||
@echo "Press any key to continue"
|
||||
@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
|
||||
@echo "% ejabberd version (automatically generated)." > version.tex
|
||||
@echo "\newcommand{\version}{"`sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../ebin/ejabberd.app`"}" >> version.tex
|
||||
@echo -n "% Contributed modules (automatically generated)." > contributed_modules.tex
|
||||
@echo -e "$(CONTRIBUTED_MODULES)" >> contributed_modules.tex
|
||||
@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
|
||||
|
||||
|
||||
+236
-212
@@ -1,40 +1,45 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Ejabberd 2.1.12 Developers Guide
|
||||
</TITLE>
|
||||
|
||||
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<META name="GENERATOR" content="hevea 1.10">
|
||||
<STYLE type="text/css">
|
||||
<!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;}
|
||||
PRE{text-align:left;margin-left:0ex;margin-right:auto;}
|
||||
BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;}
|
||||
TD P{margin:0px;}
|
||||
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;width:auto; border:2px solid green;}
|
||||
.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;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;}
|
||||
@@ -43,169 +48,182 @@ TD P{margin:0px;}
|
||||
.marginparright{float:right; margin-left:1ex; margin-right:0ex;}
|
||||
.theorem{text-align:left;margin:1ex auto 1ex 0ex;}
|
||||
.part{margin:2ex auto;text-align:center}
|
||||
</STYLE>
|
||||
</HEAD>
|
||||
<BODY >
|
||||
</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 DEF section 1 --><P><A NAME="titlepage"></A>
|
||||
<!--CUT STYLE article--><!--CUT DEF section 1 --><p><a id="titlepage"></a>
|
||||
|
||||
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.1.12 Developers Guide</H1><H3 CLASS="titlerest">Alexey Shchepin<BR>
|
||||
<A HREF="mailto:alexey@sevcom.net"><TT>mailto:alexey@sevcom.net</TT></A><BR>
|
||||
<A HREF="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT></A></H3></TD></TR>
|
||||
</TABLE><DIV CLASS="center">
|
||||
</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">
|
||||
<img src="logo.png" alt="logo.png">
|
||||
|
||||
|
||||
</DIV><BLOCKQUOTE CLASS="quotation"><I>I can thoroughly recommend ejabberd for ease of setup –
|
||||
Kevin Smith, Current maintainer of the Psi project</I></BLOCKQUOTE><!--TOC section Contents-->
|
||||
<H2 CLASS="section"><!--SEC ANCHOR -->Contents</H2><!--SEC END --><UL CLASS="toc"><LI CLASS="li-toc">
|
||||
<A HREF="#htoc1">1  Key Features</A>
|
||||
</LI><LI CLASS="li-toc"><A HREF="#htoc2">2  Additional Features</A>
|
||||
</LI><LI CLASS="li-toc"><A HREF="#htoc3">3  How it Works</A>
|
||||
<UL CLASS="toc"><LI CLASS="li-toc">
|
||||
<A HREF="#htoc4">3.1  Router</A>
|
||||
</LI><LI CLASS="li-toc"><A HREF="#htoc5">3.2  Local Router</A>
|
||||
</LI><LI CLASS="li-toc"><A HREF="#htoc6">3.3  Session Manager</A>
|
||||
</LI><LI CLASS="li-toc"><A HREF="#htoc7">3.4  S2S Manager</A>
|
||||
</LI></UL>
|
||||
</LI><LI CLASS="li-toc"><A HREF="#htoc8">4  Authentication</A>
|
||||
<UL CLASS="toc">
|
||||
<UL CLASS="toc"><LI CLASS="li-toc">
|
||||
<A HREF="#htoc9">4.0.1  External</A>
|
||||
</LI></UL>
|
||||
</UL>
|
||||
</LI><LI CLASS="li-toc"><A HREF="#htoc10">5  XML Representation</A>
|
||||
</LI><LI CLASS="li-toc"><A HREF="#htoc11">6  Module <TT>xml</TT></A>
|
||||
</LI><LI CLASS="li-toc"><A HREF="#htoc12">7  Module <TT>xml_stream</TT></A>
|
||||
</LI><LI CLASS="li-toc"><A HREF="#htoc13">8  Modules</A>
|
||||
<UL CLASS="toc"><LI CLASS="li-toc">
|
||||
<A HREF="#htoc14">8.1  Module gen_iq_handler</A>
|
||||
</LI><LI CLASS="li-toc"><A HREF="#htoc15">8.2  Services</A>
|
||||
</LI></UL>
|
||||
</LI></UL><P>Introduction
|
||||
<A NAME="intro"></A></P><P><TT>ejabberd</TT> is a free and open source instant messaging server written in <A HREF="http://www.erlang.org/">Erlang/OTP</A>.</P><P><TT>ejabberd</TT> is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication.</P><P><TT>ejabberd</TT> is designed to be a rock-solid and feature rich XMPP server.</P><P><TT>ejabberd</TT> is suitable for small deployments, whether they need to be scalable or not, as well as extremely big deployments.</P><!--TOC section Key Features-->
|
||||
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc1">1</A>  Key Features</H2><!--SEC END --><P>
|
||||
<A NAME="keyfeatures"></A>
|
||||
</P><P><TT>ejabberd</TT> is:
|
||||
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
Cross-platform: <TT>ejabberd</TT> runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.</LI><LI CLASS="li-itemize">Distributed: You can run <TT>ejabberd</TT> on a cluster of machines and all of them will serve the same Jabber domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.</LI><LI CLASS="li-itemize">Fault-tolerant: You can deploy an <TT>ejabberd</TT> cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced ‘on the fly’.</LI><LI CLASS="li-itemize">Administrator Friendly: <TT>ejabberd</TT> is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</div><blockquote class="quotation"><span style="font-style:italic">I can thoroughly recommend ejabberd for ease of setup –
|
||||
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  Key Features</a>
|
||||
</li><li class="li-toc"><a href="#sec3">2  Additional Features</a>
|
||||
</li><li class="li-toc"><a href="#sec4">3  How it Works</a>
|
||||
<ul class="toc"><li class="li-toc">
|
||||
<a href="#sec5">3.1  Router</a>
|
||||
</li><li class="li-toc"><a href="#sec6">3.2  Local Router</a>
|
||||
</li><li class="li-toc"><a href="#sec7">3.3  Session Manager</a>
|
||||
</li><li class="li-toc"><a href="#sec8">3.4  S2S Manager</a>
|
||||
</li></ul>
|
||||
</li><li class="li-toc"><a href="#sec9">4  Authentication</a>
|
||||
<ul class="toc">
|
||||
<ul class="toc"><li class="li-toc">
|
||||
<a href="#sec10">4.0.1  External</a>
|
||||
</li></ul>
|
||||
</ul>
|
||||
</li><li class="li-toc"><a href="#sec11">5  XML Representation</a>
|
||||
</li><li class="li-toc"><a href="#sec12">6  Module <span style="font-family:monospace">xml</span></a>
|
||||
</li><li class="li-toc"><a href="#sec13">7  Module <span style="font-family:monospace">xml_stream</span></a>
|
||||
</li><li class="li-toc"><a href="#sec14">8  Modules</a>
|
||||
<ul class="toc"><li class="li-toc">
|
||||
<a href="#sec15">8.1  Module gen_iq_handler</a>
|
||||
</li><li class="li-toc"><a href="#sec16">8.2  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  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 ‘on the fly’.</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: <TT>ejabberd</TT> leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
Translated to 25 languages. </LI><LI CLASS="li-itemize">Support for <A HREF="http://www.ietf.org/rfc/rfc3490.txt">IDNA</A>.
|
||||
</LI></UL></LI><LI CLASS="li-itemize">Open Standards: <TT>ejabberd</TT> is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</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 Additional Features-->
|
||||
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc2">2</A>  Additional Features</H2><!--SEC END --><P>
|
||||
<A NAME="addfeatures"></A>
|
||||
</P><P>Moreover, <TT>ejabberd</TT> comes with a wide range of other state-of-the-art features:
|
||||
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</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  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">
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Load only the modules you want.
|
||||
</LI><LI CLASS="li-itemize">Extend <TT>ejabberd</TT> with your own custom modules.
|
||||
</LI></UL>
|
||||
</LI><LI CLASS="li-itemize">Security
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</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">
|
||||
</li><li class="li-itemize">STARTTLS and Dialback s2s connections.
|
||||
</li><li class="li-itemize">Web Admin accessible via HTTPS secure access.
|
||||
</li></ul>
|
||||
</li><li class="li-itemize">Databases
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Internal database for fast deployment (Mnesia).
|
||||
</LI><LI CLASS="li-itemize">Native MySQL support.
|
||||
</LI><LI CLASS="li-itemize">Native PostgreSQL support.
|
||||
</LI><LI CLASS="li-itemize">ODBC data storage support.
|
||||
</LI><LI CLASS="li-itemize">Microsoft SQL Server support. </LI></UL>
|
||||
</LI><LI CLASS="li-itemize">Authentication
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</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 and ODBC. </LI><LI CLASS="li-itemize">External Authentication script.
|
||||
</LI></UL>
|
||||
</LI><LI CLASS="li-itemize">Others
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</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">Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
|
||||
</LI></UL>
|
||||
</LI></UL><!--TOC section How it Works-->
|
||||
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc3">3</A>  How it Works</H2><!--SEC END --><P>
|
||||
<A NAME="howitworks"></A></P><P>A XMPP domain is served by one or more <TT>ejabberd</TT> nodes. These nodes can
|
||||
</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  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
|
||||
<TT>~ejabberd/.erlang.cookie</TT> must be the same on all nodes). This is
|
||||
<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…</P><P>Each <TT>ejabberd</TT> node have following modules:
|
||||
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
connections, registered services, etc…</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 Router-->
|
||||
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc4">3.1</A>  Router</H3><!--SEC END --><P>This module is the main router of XMPP packets on each node. It routes
|
||||
</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  Router</h3><!--SEC END --><p>This module is the main router of XMPP packets on each node. It routes
|
||||
them based on their destinations domains. It has two tables: local and global
|
||||
routes. First, domain of packet destination searched in local table, and if it
|
||||
found, then the packet is routed to appropriate process. If no, then it
|
||||
searches in global table, and is routed to the appropriate <TT>ejabberd</TT> node or
|
||||
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 Local Router-->
|
||||
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc5">3.2</A>  Local Router</H3><!--SEC END --><P>This module routes packets which have a destination domain equal to this server
|
||||
manager.</p>
|
||||
<!--TOC subsection id="sec6" Local Router-->
|
||||
<h3 id="sec6" class="subsection">3.2  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’s content.</P><!--TOC subsection Session Manager-->
|
||||
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc6">3.3</A>  Session Manager</H3><!--SEC END --><P>This module routes packets to local users. It searches for what user resource
|
||||
session manager, else it is processed depending on it’s content.</p>
|
||||
<!--TOC subsection id="sec7" Session Manager-->
|
||||
<h3 id="sec7" class="subsection">3.3  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 S2S Manager-->
|
||||
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc7">3.4</A>  S2S Manager</H3><!--SEC END --><P>This module routes packets to other XMPP servers. First, it checks if an
|
||||
the packet is sent to session manager on that node.</p>
|
||||
<!--TOC subsection id="sec8" S2S Manager-->
|
||||
<h3 id="sec8" class="subsection">3.4  S2S Manager</h3><!--SEC END --><p>This module routes packets to other XMPP servers. First, it checks if an
|
||||
open S2S connection from the domain of the packet source to the domain of
|
||||
packet destination already exists. If it is open on another node, then it
|
||||
routes the packet to S2S manager on that node, if it is open on this node, then
|
||||
it is routed to the process that serves this connection, and if a connection
|
||||
does not exist, then it is opened and registered.</P><!--TOC section Authentication-->
|
||||
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc8">4</A>  Authentication</H2><!--SEC END --><!--TOC subsubsection External-->
|
||||
<H4 CLASS="subsubsection"><!--SEC ANCHOR --><A NAME="htoc9">4.0.1</A>  External</H4><!--SEC END --><P>
|
||||
<A NAME="externalauth"></A>
|
||||
</P><P>The external authentication script follows
|
||||
<A HREF="http://www.erlang.org/doc/tutorial/c_portdriver.html">the erlang port driver API</A>.</P><P>That script is supposed to do theses actions, in an infinite loop:
|
||||
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
does not exist, then it is opened and registered.</p>
|
||||
<!--TOC section id="sec9" Authentication-->
|
||||
<h2 id="sec9" class="section">4  Authentication</h2><!--SEC END -->
|
||||
<!--TOC subsubsection id="sec10" External-->
|
||||
<h4 id="sec10" class="subsubsection">4.0.1  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">
|
||||
<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
|
||||
</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">
|
||||
<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’s a valid user)
|
||||
</LI><LI CLASS="li-itemize">setpass:User:Server:Password (set user’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">
|
||||
</li><li class="li-itemize">isuser:User:Server (check if it’s a valid user)
|
||||
</li><li class="li-itemize">setpass:User:Server:Password (set user’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
|
||||
</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 *
|
||||
@@ -242,10 +260,11 @@ while True:
|
||||
elif data[0] == "setpass":
|
||||
success = setpass(data[1], data[2], data[3])
|
||||
to_ejabberd(success)
|
||||
</PRE><!--TOC section XML Representation-->
|
||||
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc10">5</A>  XML Representation</H2><!--SEC END --><P>
|
||||
<A NAME="xmlrepr"></A></P><P>Each XML stanza is represented as the following tuple:
|
||||
</P><PRE CLASS="verbatim">XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
|
||||
</pre>
|
||||
<!--TOC section id="sec11" XML Representation-->
|
||||
<h2 id="sec11" class="section">5  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}
|
||||
@@ -253,30 +272,31 @@ while True:
|
||||
Val = string()
|
||||
ElementOrCDATA = XMLElement | CDATA
|
||||
CDATA = {xmlcdata, string()}
|
||||
</PRE><P>E. g. this stanza:
|
||||
</P><PRE CLASS="verbatim"><message to='test@conference.example.org' type='groupchat'>
|
||||
</pre><p>E. g. this stanza:
|
||||
</p><pre class="verbatim"><message to='test@conference.example.org' type='groupchat'>
|
||||
<body>test</body>
|
||||
</message>
|
||||
</PRE><P>is represented as the following structure:
|
||||
</P><PRE CLASS="verbatim">{xmlelement, "message",
|
||||
</pre><p>is represented as the following structure:
|
||||
</p><pre class="verbatim">{xmlelement, "message",
|
||||
[{"to", "test@conference.example.org"},
|
||||
{"type", "groupchat"}],
|
||||
[{xmlelement, "body",
|
||||
[],
|
||||
[{xmlcdata, "test"}]}]}}
|
||||
</PRE><!--TOC section Module <TT>xml</TT>-->
|
||||
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc11">6</A>  Module <TT>xml</TT></H2><!--SEC END --><P>
|
||||
<A NAME="xmlmod"></A></P><DL CLASS="description"><DT CLASS="dt-description">
|
||||
</DT><DD CLASS="dd-description"><CODE>element_to_string(El) -> string()</CODE>
|
||||
<PRE CLASS="verbatim">El = XMLElement
|
||||
</PRE>Returns string representation of XML stanza <TT>El</TT>.</DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description"><CODE>crypt(S) -> string()</CODE>
|
||||
<PRE CLASS="verbatim">S = string()
|
||||
</PRE>Returns string which correspond to <TT>S</TT> with encoded XML special
|
||||
characters.</DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description"><CODE>remove_cdata(ECList) -> EList</CODE>
|
||||
<PRE CLASS="verbatim">ECList = [ElementOrCDATA]
|
||||
</pre>
|
||||
<!--TOC section id="sec12" Module <span style="font-family:monospace">xml</span>-->
|
||||
<h2 id="sec12" class="section">6  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) -> 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) -> 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) -> EList</code>
|
||||
<pre class="verbatim">ECList = [ElementOrCDATA]
|
||||
EList = [XMLElement]
|
||||
</PRE><TT>EList</TT> is a list of all non-CDATA elements of ECList.</DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description"><CODE>get_path_s(El, Path) -> Res</CODE>
|
||||
<PRE CLASS="verbatim">El = 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) -> Res</code>
|
||||
<pre class="verbatim">El = XMLElement
|
||||
Path = [PathItem]
|
||||
PathItem = PathElem | PathAttr | PathCDATA
|
||||
PathElem = {elem, Name}
|
||||
@@ -284,57 +304,60 @@ PathAttr = {attr, Name}
|
||||
PathCDATA = cdata
|
||||
Name = string()
|
||||
Res = string() | XMLElement
|
||||
</PRE>If <TT>Path</TT> is empty, then returns <TT>El</TT>. Else sequentially
|
||||
consider elements of <TT>Path</TT>. Each element is one of:
|
||||
<DL CLASS="description"><DT CLASS="dt-description">
|
||||
</DT><DD CLASS="dd-description"><CODE>{elem, Name}</CODE> <TT>Name</TT> is name of subelement of
|
||||
<TT>El</TT>, if such element exists, then this element considered in
|
||||
</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 <TT>El</TT> have attribute <TT>Name</TT>, then
|
||||
</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 <TT>El</TT>.
|
||||
</DD></DL></DD><DT CLASS="dt-description"></DT><DD CLASS="dd-description">TODO:
|
||||
<PRE CLASS="verbatim"> get_cdata/1, get_tag_cdata/1
|
||||
</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 Module <TT>xml_stream</TT>-->
|
||||
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc12">7</A>  Module <TT>xml_stream</TT></H2><!--SEC END --><P>
|
||||
<A NAME="xmlstreammod"></A></P><DL CLASS="description"><DT CLASS="dt-description">
|
||||
</DT><DD CLASS="dd-description"><CODE>parse_element(Str) -> XMLElement | {error, Err}</CODE>
|
||||
<PRE CLASS="verbatim">Str = string()
|
||||
</pre></dd></dl>
|
||||
<!--TOC section id="sec13" Module <span style="font-family:monospace">xml_stream</span>-->
|
||||
<h2 id="sec13" class="section">7  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) -> XMLElement | {error, Err}</code>
|
||||
<pre class="verbatim">Str = string()
|
||||
Err = term()
|
||||
</PRE>Parses <TT>Str</TT> using XML parser, returns either parsed element or error
|
||||
</pre>Parses <span style="font-family:monospace">Str</span> using XML parser, returns either parsed element or error
|
||||
tuple.
|
||||
</DD></DL><!--TOC section Modules-->
|
||||
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc13">8</A>  Modules</H2><!--SEC END --><P>
|
||||
<A NAME="emods"></A></P><!--TOC subsection Module gen_iq_handler-->
|
||||
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc14">8.1</A>  Module gen_iq_handler</H3><!--SEC END --><P>
|
||||
<A NAME="geniqhandl"></A></P><P>The module <CODE>gen_iq_handler</CODE> allows to easily write handlers for IQ packets
|
||||
of particular XML namespaces that addressed to server or to users bare JIDs.</P><P>In this module the following functions are defined:
|
||||
</P><DL CLASS="description"><DT CLASS="dt-description">
|
||||
</DT><DD CLASS="dd-description"><CODE>add_iq_handler(Component, Host, NS, Module, Function, Type)</CODE>
|
||||
<PRE CLASS="verbatim">Component = Module = Function = atom()
|
||||
</dd></dl>
|
||||
<!--TOC section id="sec14" Modules-->
|
||||
<h2 id="sec14" class="section">8  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  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
|
||||
</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()
|
||||
<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).
|
||||
</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).
|
||||
|
||||
@@ -368,9 +391,10 @@ process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
|
||||
[{"xmlns", ?NS_CPUTIME}],
|
||||
[{xmlelement, "cputime", [], [{xmlcdata, SCPUTime}]}]}]}
|
||||
end.
|
||||
</PRE><!--TOC subsection Services-->
|
||||
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc15">8.2</A>  Services</H3><!--SEC END --><P>
|
||||
<A NAME="services"></A></P><PRE CLASS="verbatim">-module(mod_echo).
|
||||
</pre>
|
||||
<!--TOC subsection id="sec16" Services-->
|
||||
<h3 id="sec16" class="subsection">8.2  Services</h3><!--SEC END --><p>
|
||||
<a id="services"></a></p><pre class="verbatim">-module(mod_echo).
|
||||
|
||||
-behaviour(gen_mod).
|
||||
|
||||
@@ -404,10 +428,10 @@ stop(Host) ->
|
||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||
Proc ! stop,
|
||||
{wait, Proc}.
|
||||
</PRE><!--CUT END -->
|
||||
</pre><!--CUT END -->
|
||||
<!--HTMLFOOT-->
|
||||
<!--ENDHTML-->
|
||||
<!--FOOTER-->
|
||||
<HR SIZE=2><BLOCKQUOTE CLASS="quote"><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
|
||||
</EM><A HREF="http://hevea.inria.fr/index.html"><EM>H</EM><EM><FONT SIZE=2><sup>E</sup></FONT></EM><EM>V</EM><EM><FONT SIZE=2><sup>E</sup></FONT></EM><EM>A</EM></A><EM>.</EM></BLOCKQUOTE></BODY>
|
||||
</HTML>
|
||||
<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>
|
||||
|
||||
+97
-86
@@ -1,40 +1,45 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Ejabberd 2.1.12 Feature Sheet
|
||||
</TITLE>
|
||||
|
||||
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<META name="GENERATOR" content="hevea 1.10">
|
||||
<STYLE type="text/css">
|
||||
<!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;}
|
||||
PRE{text-align:left;margin-left:0ex;margin-right:auto;}
|
||||
BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;}
|
||||
TD P{margin:0px;}
|
||||
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;width:auto; border:2px solid green;}
|
||||
.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;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;}
|
||||
@@ -44,89 +49,95 @@ TD P{margin:0px;}
|
||||
.theorem{text-align:left;margin:1ex auto 1ex 0ex;}
|
||||
.part{margin:2ex auto;text-align:center}
|
||||
SPAN{width:20%; float:right; text-align:left; margin-left:auto;}
|
||||
</STYLE>
|
||||
</HEAD>
|
||||
<BODY >
|
||||
</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 DEF section 1 --><P><A NAME="titlepage"></A>
|
||||
<!--CUT STYLE article--><!--CUT DEF section 1 --><p><a id="titlepage"></a>
|
||||
|
||||
</P><TABLE CLASS="title"><TR><TD><H1 CLASS="titlemain">Ejabberd 2.1.12 Feature Sheet</H1><H3 CLASS="titlerest">Sander Devrieze<BR>
|
||||
<A HREF="mailto:s.devrieze@pandora.be"><TT>mailto:s.devrieze@pandora.be</TT></A><BR>
|
||||
<A HREF="xmpp:sander@devrieze.dyndns.org"><TT>xmpp:sander@devrieze.dyndns.org</TT></A></H3></TD></TR>
|
||||
</TABLE><DIV CLASS="center">
|
||||
</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">
|
||||
<img src="logo.png" alt="logo.png">
|
||||
|
||||
|
||||
</DIV><BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>I can thoroughly recommend ejabberd for ease of setup –
|
||||
Kevin Smith, Current maintainer of the Psi project</I></FONT></BLOCKQUOTE><P>Introduction
|
||||
<A NAME="intro"></A></P><BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. —
|
||||
Joeri</I></FONT></BLOCKQUOTE><P><TT>ejabberd</TT> is a <B><FONT SIZE=4><FONT COLOR="#001376">free and open source</FONT></FONT></B> instant messaging server written in <A HREF="http://www.erlang.org/">Erlang/OTP</A>.</P><P><TT>ejabberd</TT> is <B><FONT SIZE=4><FONT COLOR="#001376">cross-platform</FONT></FONT></B>, distributed, fault-tolerant, and based on open standards to achieve real-time communication.</P><P><TT>ejabberd</TT> is designed to be a <B><FONT SIZE=4><FONT COLOR="#001376">rock-solid and feature rich</FONT></FONT></B> XMPP server.</P><P><TT>ejabberd</TT> is suitable for small deployments, whether they need to be <B><FONT SIZE=4><FONT COLOR="#001376">scalable</FONT></FONT></B> or not, as well as extremely big deployments.</P><!--TOC section Key Features-->
|
||||
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc1"></A>Key Features</H2><!--SEC END --><P>
|
||||
<A NAME="keyfeatures"></A>
|
||||
</P><BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>Erlang seems to be tailor-made for writing stable, robust servers. —
|
||||
Peter Saint-André, Executive Director of the Jabber Software Foundation</I></FONT></BLOCKQUOTE><P><TT>ejabberd</TT> is:
|
||||
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
<B><FONT SIZE=4><FONT COLOR="#001376">Cross-platform:</FONT></FONT></B> <TT>ejabberd</TT> runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.</LI><LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Distributed:</FONT></FONT></B> You can run <TT>ejabberd</TT> on a cluster of machines and all of them will serve the same Jabber domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.</LI><LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Fault-tolerant:</FONT></FONT></B> You can deploy an <TT>ejabberd</TT> cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced ‘on the fly’.</LI><LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Administrator Friendly:</FONT></FONT></B> <TT>ejabberd</TT> is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</div><blockquote class="quotation"><span style="color:#921700"><span style="font-style:italic">I can thoroughly recommend ejabberd for ease of setup –
|
||||
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. —
|
||||
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. —
|
||||
Peter Saint-André, 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 ‘on the fly’.</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"><B><FONT SIZE=4><FONT COLOR="#001376">Internationalized:</FONT></FONT></B> <TT>ejabberd</TT> leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
Translated to 25 languages. </LI><LI CLASS="li-itemize">Support for <A HREF="http://www.ietf.org/rfc/rfc3490.txt">IDNA</A>.
|
||||
</LI></UL></LI><LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Open Standards:</FONT></FONT></B> <TT>ejabberd</TT> is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</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 Additional Features-->
|
||||
<H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc2"></A>Additional Features</H2><!--SEC END --><P>
|
||||
<A NAME="addfeatures"></A>
|
||||
</P><BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>ejabberd is making inroads to solving the "buggy incomplete server" problem —
|
||||
Justin Karneges, Founder of the Psi and the Delta projects</I></FONT></BLOCKQUOTE><P>Moreover, <TT>ejabberd</TT> comes with a wide range of other state-of-the-art features:
|
||||
</P><UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</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 —
|
||||
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">
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Load only the modules you want.
|
||||
</LI><LI CLASS="li-itemize">Extend <TT>ejabberd</TT> with your own custom modules.
|
||||
</LI></UL>
|
||||
</LI><LI CLASS="li-itemize">Security
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</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">
|
||||
</li><li class="li-itemize">STARTTLS and Dialback s2s connections.
|
||||
</li><li class="li-itemize">Web Admin accessible via HTTPS secure access.
|
||||
</li></ul>
|
||||
</li><li class="li-itemize">Databases
|
||||
<ul class="itemize"><li class="li-itemize">
|
||||
Internal database for fast deployment (Mnesia).
|
||||
</LI><LI CLASS="li-itemize">Native MySQL support.
|
||||
</LI><LI CLASS="li-itemize">Native PostgreSQL support.
|
||||
</LI><LI CLASS="li-itemize">ODBC data storage support.
|
||||
</LI><LI CLASS="li-itemize">Microsoft SQL Server support. </LI></UL>
|
||||
</LI><LI CLASS="li-itemize">Authentication
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</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 and ODBC. </LI><LI CLASS="li-itemize">External Authentication script.
|
||||
</LI></UL>
|
||||
</LI><LI CLASS="li-itemize">Others
|
||||
<UL CLASS="itemize"><LI CLASS="li-itemize">
|
||||
</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">Component support: interface with networks such as AIM, ICQ and MSN installing special tranports.
|
||||
</LI></UL>
|
||||
</LI></UL><!--CUT END -->
|
||||
</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 SIZE=2><BLOCKQUOTE CLASS="quote"><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
|
||||
</EM><A HREF="http://hevea.inria.fr/index.html"><EM>H</EM><EM><FONT SIZE=2><sup>E</sup></FONT></EM><EM>V</EM><EM><FONT SIZE=2><sup>E</sup></FONT></EM><EM>A</EM></A><EM>.</EM></BLOCKQUOTE></BODY>
|
||||
</HTML>
|
||||
<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>
|
||||
|
||||
-4660
File diff suppressed because it is too large
Load Diff
+600
-63
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,7 @@ Peter Saint-Andr\'e, Executive Director of the Jabber Software Foundation}
|
||||
\item \marking{Internationalized:} \ejabberd{} leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
|
||||
\begin{itemize}
|
||||
\item Translated to 25 languages. %%\improved{}
|
||||
\item Support for \footahref{http://www.ietf.org/rfc/rfc3490.txt}{IDNA}.
|
||||
\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.
|
||||
@@ -110,11 +110,12 @@ Moreover, \ejabberd{} comes with a wide range of other state-of-the-art features
|
||||
\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 and ODBC. %%\improved{}
|
||||
\item PAM, LDAP, ODBC and Riak. %%\improved{}
|
||||
\item External Authentication script.
|
||||
\end{itemize}
|
||||
\item Others
|
||||
@@ -128,6 +129,7 @@ Moreover, \ejabberd{} comes with a wide range of other state-of-the-art features
|
||||
\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}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
% ejabberd version (automatically generated).
|
||||
\newcommand{\version}{13.09}
|
||||
@@ -24,7 +24,7 @@ test -x "$CTL" || {
|
||||
echo "ERROR: ejabberd not found: $DIR"
|
||||
exit 1
|
||||
}
|
||||
grep ^"$USER": /etc/passwd >/dev/null || {
|
||||
getent passwd "$USER" >/dev/null || {
|
||||
echo "ERROR: System user not found: $USER"
|
||||
exit 2
|
||||
}
|
||||
|
||||
+55
-9
@@ -24,8 +24,8 @@
|
||||
### > Art thou not Romeo,
|
||||
### and a Montague?
|
||||
|
||||
### =========
|
||||
### DEBUGGING
|
||||
### =======
|
||||
### LOGGING
|
||||
|
||||
##
|
||||
## loglevel: Verbosity of log files generated by ejabberd.
|
||||
@@ -38,6 +38,32 @@
|
||||
##
|
||||
loglevel: 4
|
||||
|
||||
##
|
||||
## rotation: Describe how to rotate logs. Either size and/or date can trigger
|
||||
## log rotation. Setting count to N keeps N rotated logs. Setting count to 0
|
||||
## does not disable rotation, it instead rotates the file and keeps no previous
|
||||
## versions around. Setting size to X rotate log when it reaches X bytes.
|
||||
## To disable rotation set the size to 0 and the date to ""
|
||||
## Date syntax is taken from the syntax newsyslog uses in newsyslog.conf.
|
||||
## Some examples:
|
||||
## $D0 rotate every night at midnight
|
||||
## $D23 rotate every day at 23:00 hr
|
||||
## $W0D23 rotate every week on Sunday at 23:00 hr
|
||||
## $W5D16 rotate every week on Friday at 16:00 hr
|
||||
## $M1D0 rotate on the first day of every month at midnight
|
||||
## $M5D6 rotate on every 5th day of the month at 6:00 hr
|
||||
##
|
||||
log_rotate_size: 10485760
|
||||
log_rotate_date: ""
|
||||
log_rotate_count: 1
|
||||
|
||||
##
|
||||
## overload protection: If you want to limit the number of messages per second
|
||||
## allowed from error_logger, which is a good idea if you want to avoid a flood
|
||||
## of messages when system is overloaded, you can set a limit.
|
||||
## 100 is ejabberd's default.
|
||||
log_rate_limit: 100
|
||||
|
||||
##
|
||||
## watchdog_admins: Only useful for developers: if an ejabberd process
|
||||
## consumes a lot of memory, send live notifications to these XMPP
|
||||
@@ -82,10 +108,21 @@ listen:
|
||||
##
|
||||
## If TLS is compiled in and you installed a SSL
|
||||
## certificate, specify the full path to the
|
||||
## file and uncomment this line:
|
||||
## file and uncomment these lines:
|
||||
##
|
||||
## certfile: "/path/to/ssl.pem"
|
||||
## starttls: true
|
||||
##
|
||||
## To enforce TLS encryption for client connections,
|
||||
## use this instead of the "starttls" option:
|
||||
##
|
||||
## starttls_required: true
|
||||
##
|
||||
## Custom OpenSSL options
|
||||
##
|
||||
## protocol_options:
|
||||
## - "no_sslv3"
|
||||
## - "no_tlsv1"
|
||||
max_stanza_size: 65536
|
||||
shaper: c2s_shaper
|
||||
access: c2s
|
||||
@@ -144,6 +181,12 @@ listen:
|
||||
##
|
||||
## s2s_certfile: "/path/to/ssl.pem"
|
||||
|
||||
## Custom OpenSSL options
|
||||
##
|
||||
## s2s_protocol_options:
|
||||
## - "no_sslv3"
|
||||
## - "no_tlsv1"
|
||||
|
||||
##
|
||||
## domain_certfile: Specify a different certificate for each served hostname.
|
||||
##
|
||||
@@ -158,7 +201,7 @@ listen:
|
||||
##
|
||||
## Default s2s policy for undefined hosts.
|
||||
##
|
||||
## s2s_policy: s2s_access
|
||||
## s2s_access: s2s
|
||||
|
||||
##
|
||||
## Outgoing S2S options
|
||||
@@ -449,7 +492,7 @@ access:
|
||||
trusted_network:
|
||||
loopback: allow
|
||||
## Do not establish S2S connections with bad servers
|
||||
## s2s_access:
|
||||
## s2s:
|
||||
## bad_servers: deny
|
||||
## all: allow
|
||||
|
||||
@@ -514,6 +557,10 @@ modules:
|
||||
access: announce
|
||||
mod_blocking: {} # requires mod_privacy
|
||||
mod_caps: {}
|
||||
mod_carboncopy: {}
|
||||
mod_client_state:
|
||||
drop_chat_states: true
|
||||
queue_presence: false
|
||||
mod_configure: {} # requires mod_adhoc
|
||||
mod_disco: {}
|
||||
## mod_echo: {}
|
||||
@@ -601,10 +648,9 @@ modules:
|
||||
##
|
||||
## host_config:
|
||||
## "localhost":
|
||||
## add:
|
||||
## modules:
|
||||
## mod_echo:
|
||||
## host: "mirror.localhost"
|
||||
## modules:
|
||||
## mod_echo:
|
||||
## host: "mirror.localhost"
|
||||
|
||||
### Local Variables:
|
||||
### mode: yaml
|
||||
|
||||
+12
-1
@@ -56,7 +56,7 @@
|
||||
# This communication is used by ejabberdctl command line tool,
|
||||
# and in a cluster of several ejabberd nodes.
|
||||
#
|
||||
# Default: 127.0.0.1
|
||||
# Default: 0.0.0.0
|
||||
#
|
||||
#INET_DIST_INTERFACE=127.0.0.1
|
||||
|
||||
@@ -148,6 +148,17 @@
|
||||
#
|
||||
#EJABBERD_PID_PATH=/var/run/ejabberd/ejabberd.pid
|
||||
|
||||
#.
|
||||
#' EJABBERD_CONFIG_PATH: ejabberd configuration file
|
||||
#
|
||||
# Specify the full path to the ejabberd configuration file. If the file name has
|
||||
# a ".yml" extension, it is parsed as a YAML file; otherwise, Erlang syntax is
|
||||
# expected.
|
||||
#
|
||||
# Default: $ETC_DIR/ejabberd.yml
|
||||
#
|
||||
#EJABBERD_CONFIG_PATH=/etc/ejabberd/ejabberd.yml
|
||||
|
||||
#.
|
||||
#'
|
||||
# vim: foldmarker=#',#. foldmethod=marker:
|
||||
|
||||
+132
-69
@@ -7,12 +7,12 @@ ERL_MAX_PORTS=32000
|
||||
ERL_PROCESSES=250000
|
||||
ERL_MAX_ETS_TABLES=1400
|
||||
FIREWALL_WINDOW=""
|
||||
INET_DIST_INTERFACE="127.0.0.1"
|
||||
ERLANG_NODE=ejabberd@localhost
|
||||
|
||||
# define default environment variables
|
||||
SCRIPT_DIR=`cd ${0%/*} && pwd`
|
||||
ERL={{erl}}
|
||||
IEX={{bindir}}/iex
|
||||
INSTALLUSER={{installuser}}
|
||||
|
||||
# Compatibility in ZSH
|
||||
@@ -23,7 +23,12 @@ if [ "$INSTALLUSER" != "" ] ; then
|
||||
EXEC_CMD="false"
|
||||
for GID in `id -G`; do
|
||||
if [ $GID -eq 0 ] ; then
|
||||
EXEC_CMD="su $INSTALLUSER -p -c"
|
||||
INSTALLUSER_HOME=$(getent passwd "$INSTALLUSER" | cut -d: -f6)
|
||||
if [ -n "$INSTALLUSER_HOME" ] && [ ! -d "$INSTALLUSER_HOME" ] ; then
|
||||
mkdir -p "$INSTALLUSER_HOME"
|
||||
chown "$INSTALLUSER" "$INSTALLUSER_HOME"
|
||||
fi
|
||||
EXEC_CMD="su $INSTALLUSER -c"
|
||||
fi
|
||||
done
|
||||
if [ `id -g` -eq `id -g $INSTALLUSER` ] ; then
|
||||
@@ -45,33 +50,33 @@ while [ $# -ne 0 ] ; do
|
||||
case $PARAM in
|
||||
--) break ;;
|
||||
--node) ERLANG_NODE_ARG=$1 ; shift ;;
|
||||
--config-dir) ETCDIR=$1 ; shift ;;
|
||||
--config) EJABBERD_CONFIG_PATH=$1 ; shift ;;
|
||||
--ctl-config) EJABBERDCTL_CONFIG_PATH=$1 ; shift ;;
|
||||
--logs) LOGS_DIR=$1 ; shift ;;
|
||||
--spool) SPOOLDIR=$1 ; shift ;;
|
||||
--config-dir) ETC_DIR="$1" ; shift ;;
|
||||
--config) EJABBERD_CONFIG_PATH="$1" ; shift ;;
|
||||
--ctl-config) EJABBERDCTL_CONFIG_PATH="$1" ; shift ;;
|
||||
--logs) LOGS_DIR="$1" ; shift ;;
|
||||
--spool) SPOOL_DIR="$1" ; shift ;;
|
||||
*) ARGS="$ARGS $PARAM" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Define ejabberd variable if they have not been defined from the command line
|
||||
if [ "$ETCDIR" = "" ] ; then
|
||||
ETCDIR={{sysconfdir}}/ejabberd
|
||||
if [ "$ETC_DIR" = "" ] ; then
|
||||
ETC_DIR={{sysconfdir}}/ejabberd
|
||||
fi
|
||||
if [ "$EJABBERDCTL_CONFIG_PATH" = "" ] ; then
|
||||
EJABBERDCTL_CONFIG_PATH=$ETCDIR/ejabberdctl.cfg
|
||||
EJABBERDCTL_CONFIG_PATH=$ETC_DIR/ejabberdctl.cfg
|
||||
fi
|
||||
if [ -f "$EJABBERDCTL_CONFIG_PATH" ] ; then
|
||||
. "$EJABBERDCTL_CONFIG_PATH"
|
||||
fi
|
||||
if [ "$EJABBERD_CONFIG_PATH" = "" ] ; then
|
||||
EJABBERD_CONFIG_PATH=$ETCDIR/ejabberd.yml
|
||||
EJABBERD_CONFIG_PATH=$ETC_DIR/ejabberd.yml
|
||||
fi
|
||||
if [ "$LOGS_DIR" = "" ] ; then
|
||||
LOGS_DIR={{localstatedir}}/log/ejabberd
|
||||
fi
|
||||
if [ "$SPOOLDIR" = "" ] ; then
|
||||
SPOOLDIR={{localstatedir}}/lib/ejabberd
|
||||
if [ "$SPOOL_DIR" = "" ] ; then
|
||||
SPOOL_DIR={{localstatedir}}/lib/ejabberd
|
||||
fi
|
||||
if [ "$EJABBERD_DOC_PATH" = "" ] ; then
|
||||
EJABBERD_DOC_PATH={{docdir}}
|
||||
@@ -104,8 +109,7 @@ EJABBERD_LOG_PATH=$LOGS_DIR/ejabberd.log
|
||||
SASL_LOG_PATH=$LOGS_DIR/erlang.log
|
||||
DATETIME=`date "+%Y%m%d-%H%M%S"`
|
||||
ERL_CRASH_DUMP=$LOGS_DIR/erl_crash_$DATETIME.dump
|
||||
ERL_INETRC=$ETCDIR/inetrc
|
||||
HOME=$SPOOLDIR
|
||||
ERL_INETRC=$ETC_DIR/inetrc
|
||||
|
||||
# define erl parameters
|
||||
ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS"
|
||||
@@ -125,12 +129,28 @@ if [ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] ; then
|
||||
else
|
||||
NAME="-name"
|
||||
fi
|
||||
IEXNAME="-$NAME"
|
||||
|
||||
# create the ejabberd home dir with the proper user if doesn't exist
|
||||
# then change to that directory readable by INSTALLUSER to
|
||||
# prevent "File operation error: eacces." messages
|
||||
[ -d $HOME ] || $EXEC_CMD "mkdir -p $HOME"
|
||||
cd $HOME
|
||||
# define ejabberd environment parameters
|
||||
if [ "$EJABBERD_CONFIG_PATH" != "${EJABBERD_CONFIG_PATH%.yml}" ] ; then
|
||||
rate=$(sed '/^[ ]*log_rate_limit/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH)
|
||||
rotate=$(sed '/^[ ]*log_rotate_size/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH)
|
||||
count=$(sed '/^[ ]*log_rotate_count/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH)
|
||||
date=$(sed '/^[ ]*log_rotate_date/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH)
|
||||
else
|
||||
rate=$(sed '/^[ ]*log_rate_limit/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH)
|
||||
rotate=$(sed '/^[ ]*log_rotate_size/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH)
|
||||
count=$(sed '/^[ ]*log_rotate_count/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH)
|
||||
date=$(sed '/^[ ]*log_rotate_date/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH)
|
||||
fi
|
||||
[ -z "$rate" ] || EJABBERD_OPTS="log_rate_limit $rate"
|
||||
[ -z "$rotate" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_size $rotate"
|
||||
[ -z "$count" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_count $count"
|
||||
[ -z "$date" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_date '$date'"
|
||||
[ -z "$EJABBERD_OPTS" ] || EJABBERD_OPTS="-ejabberd ${EJABBERD_OPTS}"
|
||||
|
||||
[ -d $SPOOL_DIR ] || $EXEC_CMD "mkdir -p $SPOOL_DIR"
|
||||
cd $SPOOL_DIR
|
||||
|
||||
# export global variables
|
||||
export EJABBERD_CONFIG_PATH
|
||||
@@ -145,8 +165,6 @@ export ERL_EPMD_ADDRESS
|
||||
export ERL_INETRC
|
||||
export ERL_MAX_PORTS
|
||||
export ERL_MAX_ETS_TABLES
|
||||
export HOME
|
||||
export EXEC_CMD
|
||||
|
||||
# start server
|
||||
start()
|
||||
@@ -156,8 +174,9 @@ start()
|
||||
$NAME $ERLANG_NODE \
|
||||
-noinput -detached \
|
||||
-pa $EJABBERD_EBIN_PATH \
|
||||
-mnesia dir \"\\\"$SPOOLDIR\\\"\" \
|
||||
-mnesia dir \"\\\"$SPOOL_DIR\\\"\" \
|
||||
$KERNEL_OPTS \
|
||||
$EJABBERD_OPTS \
|
||||
-s ejabberd \
|
||||
-sasl sasl_error_logger \\{file,\\\"$SASL_LOG_PATH\\\"\\} \
|
||||
$ERLANG_OPTS $ARGS \"$@\""
|
||||
@@ -166,26 +185,7 @@ start()
|
||||
# attach to server
|
||||
debug()
|
||||
{
|
||||
echo "--------------------------------------------------------------------"
|
||||
echo ""
|
||||
echo "IMPORTANT: we will attempt to attach an INTERACTIVE shell"
|
||||
echo "to an already running ejabberd node."
|
||||
echo "If an ERROR is printed, it means the connection was not successful."
|
||||
echo "You can interact with the ejabberd node if you know how to use it."
|
||||
echo "Please be extremely cautious with your actions,"
|
||||
echo "and exit immediately if you are not completely sure."
|
||||
echo ""
|
||||
echo "To detach this shell from ejabberd, press:"
|
||||
echo " control+c, control+c"
|
||||
echo ""
|
||||
echo "--------------------------------------------------------------------"
|
||||
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
|
||||
echo " EJABBERD_BYPASS_WARNINGS=true"
|
||||
echo "Press any key to continue"
|
||||
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
|
||||
read foo
|
||||
fi
|
||||
echo ""
|
||||
debugwarning
|
||||
TTY=`tty | sed -e 's/.*\///g'`
|
||||
$EXEC_CMD "$ERL \
|
||||
$NAME debug-${TTY}-${ERLANG_NODE} \
|
||||
@@ -195,38 +195,47 @@ debug()
|
||||
$ERLANG_OPTS $ARGS \"$@\""
|
||||
}
|
||||
|
||||
# attach to server using Elixir
|
||||
iexdebug()
|
||||
{
|
||||
debugwarning
|
||||
TTY=`tty | sed -e 's/.*\///g'`
|
||||
# Elixir shell is hidden as default
|
||||
$EXEC_CMD "$IEX \
|
||||
$IEXNAME debug-${TTY}-${ERLANG_NODE} \
|
||||
--remsh $ERLANG_NODE \
|
||||
--erl \"$KERNEL_OPTS\" \
|
||||
--erl \"$ERLANG_OPTS\" --erl \"$ARGS\" --erl \"$@\""
|
||||
}
|
||||
|
||||
# start interactive server
|
||||
live()
|
||||
{
|
||||
check_start
|
||||
echo "--------------------------------------------------------------------"
|
||||
echo ""
|
||||
echo "IMPORTANT: ejabberd is going to start in LIVE (interactive) mode."
|
||||
echo "All log messages will be shown in the command shell."
|
||||
echo "You can interact with the ejabberd node if you know how to use it."
|
||||
echo "Please be extremely cautious with your actions,"
|
||||
echo "and exit immediately if you are not completely sure."
|
||||
echo ""
|
||||
echo "To exit this LIVE mode and stop ejabberd, press:"
|
||||
echo " q(). and press the Enter key"
|
||||
echo ""
|
||||
echo "--------------------------------------------------------------------"
|
||||
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
|
||||
echo " EJABBERD_BYPASS_WARNINGS=true"
|
||||
echo "Press any key to continue"
|
||||
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
|
||||
read foo
|
||||
fi
|
||||
echo ""
|
||||
livewarning
|
||||
$EXEC_CMD "$ERL \
|
||||
$NAME $ERLANG_NODE \
|
||||
-pa $EJABBERD_EBIN_PATH \
|
||||
-mnesia dir \"\\\"$SPOOLDIR\\\"\" \
|
||||
-mnesia dir \"\\\"$SPOOL_DIR\\\"\" \
|
||||
$KERNEL_OPTS \
|
||||
$EJABBERD_OPTS \
|
||||
-s ejabberd \
|
||||
$ERLANG_OPTS $ARGS \"$@\""
|
||||
}
|
||||
|
||||
# start interactive server with Elixir
|
||||
iexlive()
|
||||
{
|
||||
livewarning
|
||||
$EXEC_CMD "$IEX \
|
||||
$IEXNAME $ERLANG_NODE \
|
||||
-pa $EJABBERD_EBIN_PATH \
|
||||
--erl \"-mnesia dir \\\"$SPOOL_DIR\\\"\" \
|
||||
--erl \"$KERNEL_OPTS\" \
|
||||
--erl \"$EJABBERD_OPTS\" \
|
||||
--app ejabberd \
|
||||
--erl \"$ERLANG_OPTS\" --erl $ARGS --erl \"$@\""
|
||||
}
|
||||
|
||||
etop()
|
||||
{
|
||||
$EXEC_CMD "$ERL \
|
||||
@@ -234,20 +243,72 @@ etop()
|
||||
-hidden -s etop -s erlang halt -output text -node $ERLANG_NODE"
|
||||
}
|
||||
|
||||
# TODO: refactor debug warning and livewarning
|
||||
debugwarning()
|
||||
{
|
||||
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
|
||||
echo "--------------------------------------------------------------------"
|
||||
echo ""
|
||||
echo "IMPORTANT: we will attempt to attach an INTERACTIVE shell"
|
||||
echo "to an already running ejabberd node."
|
||||
echo "If an ERROR is printed, it means the connection was not successful."
|
||||
echo "You can interact with the ejabberd node if you know how to use it."
|
||||
echo "Please be extremely cautious with your actions,"
|
||||
echo "and exit immediately if you are not completely sure."
|
||||
echo ""
|
||||
echo "To detach this shell from ejabberd, press:"
|
||||
echo " control+c, control+c"
|
||||
echo ""
|
||||
echo "--------------------------------------------------------------------"
|
||||
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
|
||||
echo " EJABBERD_BYPASS_WARNINGS=true"
|
||||
echo "Press return to continue"
|
||||
read foo
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
livewarning()
|
||||
{
|
||||
check_start
|
||||
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
|
||||
echo "--------------------------------------------------------------------"
|
||||
echo ""
|
||||
echo "IMPORTANT: ejabberd is going to start in LIVE (interactive) mode."
|
||||
echo "All log messages will be shown in the command shell."
|
||||
echo "You can interact with the ejabberd node if you know how to use it."
|
||||
echo "Please be extremely cautious with your actions,"
|
||||
echo "and exit immediately if you are not completely sure."
|
||||
echo ""
|
||||
echo "To exit this LIVE mode and stop ejabberd, press:"
|
||||
echo " q(). and press the Enter key"
|
||||
echo ""
|
||||
echo "--------------------------------------------------------------------"
|
||||
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
|
||||
echo " EJABBERD_BYPASS_WARNINGS=true"
|
||||
echo "Press return to continue"
|
||||
read foo
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
# TODO: Make iex command display only if ejabberd Elixir support has been enabled
|
||||
help()
|
||||
{
|
||||
echo ""
|
||||
echo "Commands to start an ejabberd node:"
|
||||
echo " start Start an ejabberd node in server mode"
|
||||
echo " debug Attach an interactive Erlang shell to a running ejabberd node"
|
||||
echo " live Start an ejabberd node in live (interactive) mode"
|
||||
echo " start Start an ejabberd node in server mode"
|
||||
echo " debug Attach an interactive Erlang shell to a running ejabberd node"
|
||||
echo " iexdebug Attach an interactive Elixir shell to a running ejabberd node"
|
||||
echo " live Start an ejabberd node in live (interactive) mode"
|
||||
echo " iexlive Start an ejabberd node in live (interactive) mode, within an Elixir shell"
|
||||
echo ""
|
||||
echo "Optional parameters when starting an ejabberd node:"
|
||||
echo " --config-dir dir Config ejabberd: $ETCDIR"
|
||||
echo " --config-dir dir Config ejabberd: $ETC_DIR"
|
||||
echo " --config file Config ejabberd: $EJABBERD_CONFIG_PATH"
|
||||
echo " --ctl-config file Config ejabberdctl: $EJABBERDCTL_CONFIG_PATH"
|
||||
echo " --logs dir Directory for logs: $LOGS_DIR"
|
||||
echo " --spool dir Database spool dir: $SPOOLDIR"
|
||||
echo " --spool dir Database spool dir: $SPOOL_DIR"
|
||||
echo " --node nodename ejabberd node name: $ERLANG_NODE"
|
||||
echo ""
|
||||
}
|
||||
@@ -391,7 +452,9 @@ wait_for_status()
|
||||
case $ARGS in
|
||||
' start') start;;
|
||||
' debug') debug;;
|
||||
' iexdebug') iexdebug;;
|
||||
' live') live;;
|
||||
' iexlive') iexlive;;
|
||||
' 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
|
||||
|
||||
+4
-5
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -32,5 +31,6 @@
|
||||
host = <<"">> :: binary(),
|
||||
port = 5280 :: inet:port_number(),
|
||||
tp = http, % :: protocol(),
|
||||
opts = [] :: list(),
|
||||
headers = [] :: [{atom() | binary(), binary()}]}).
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
+4
-5
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
+5
-6
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,15 +12,14 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-include("ns.hrl").
|
||||
-include("xml.hrl").
|
||||
-include_lib("p1_xml/include/xml.hrl").
|
||||
|
||||
-define(STANZA_ERROR(Code, Type, Condition),
|
||||
#xmlel{name = <<"error">>,
|
||||
|
||||
+4
-5
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
-define(PRINT(Format, Args), io:format(Format, Args)).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -59,6 +58,7 @@
|
||||
voice_request_min_interval = 1800 :: non_neg_integer(),
|
||||
max_users = ?MAX_USERS_DEFAULT :: non_neg_integer() | none,
|
||||
logging = false :: boolean(),
|
||||
vcard = <<"">> :: boolean(),
|
||||
captcha_whitelist = (?SETS):empty() :: gb_set()
|
||||
}).
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
%%% RFC 1928 constants.
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -14,10 +14,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
+11
-5
@@ -1,6 +1,6 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -12,10 +12,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -43,6 +42,7 @@
|
||||
-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">>).
|
||||
-define(NS_EVENT, <<"jabber:x:event">>).
|
||||
-define(NS_CHATSTATES,
|
||||
@@ -144,3 +144,9 @@
|
||||
-define(NS_MEDIA, <<"urn:xmpp:media-element">>).
|
||||
-define(NS_BOB, <<"urn:xmpp:bob">>).
|
||||
-define(NS_PING, <<"urn:xmpp:ping">>).
|
||||
-define(NS_CARBONS_2, <<"urn:xmpp:carbons:2">>).
|
||||
-define(NS_CARBONS_1, <<"urn:xmpp:carbons:1">>).
|
||||
-define(NS_FORWARD, <<"urn:xmpp:forward:0">>).
|
||||
-define(NS_CLIENT_STATE, <<"urn:xmpp:csi:0">>).
|
||||
-define(NS_STREAM_MGMT_2, <<"urn:xmpp:sm:2">>).
|
||||
-define(NS_STREAM_MGMT_3, <<"urn:xmpp:sm:3">>).
|
||||
|
||||
+3
-3
@@ -13,12 +13,12 @@
|
||||
%%%
|
||||
%%%
|
||||
%%% The Initial Developer of the Original Code is ProcessOne.
|
||||
%%% Portions created by ProcessOne are Copyright 2006-2013, ProcessOne
|
||||
%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne
|
||||
%%% All Rights Reserved.''
|
||||
%%% This software is copyright 2006-2013, ProcessOne.
|
||||
%%% This software is copyright 2006-2015, ProcessOne.
|
||||
%%%
|
||||
%%%
|
||||
%%% copyright 2006-2013 ProcessOne
|
||||
%%% copyright 2006-2015 ProcessOne
|
||||
%%%
|
||||
%%% This file contains pubsub types definition.
|
||||
%%% ====================================================================
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
defmodule Ejabberd.Hooks do
|
||||
|
||||
# Generic hook setting features
|
||||
def add(hook_name, host, module, function, priority) do
|
||||
:ejabberd_hooks.add(hook_name, host, module, function, priority)
|
||||
end
|
||||
|
||||
# Should be named 'removed'
|
||||
def delete(hook_name, host, module, function, priority) do
|
||||
:ejabberd_hooks.delete(hook_name, host, module, function, priority)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
defmodule Ejabberd.Logger do
|
||||
|
||||
def critical(message, args \\ []), do: :lager.log(:critical, [], message, args)
|
||||
def error(message, args \\ []), do: :lager.log(:error, [], message, args)
|
||||
def warning(message, args \\ []), do: :lager.log(:warning, [], message, args)
|
||||
def info(message, args \\ []), do: :lager.log(:info, [], message, args)
|
||||
def debug(message, args \\ []), do: :lager.log(:debug, [], message, args)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,2 @@
|
||||
defmodule Ejabberd do
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
defmodule ModPresenceDemo do
|
||||
import Ejabberd.Logger # this allow using info, error, etc for logging
|
||||
@behaviour :gen_mod
|
||||
|
||||
def start(host, _opts) do
|
||||
info('Starting ejabberd module Presence Demo')
|
||||
Ejabberd.Hooks.add(:set_presence_hook, host, __ENV__.module, :on_presence, 50)
|
||||
:ok
|
||||
end
|
||||
|
||||
def stop(host) do
|
||||
info('Stopping ejabberd module Presence Demo')
|
||||
Ejabberd.Hooks.delete(:set_presence_hook, host, __ENV__.module, :on_presence, 50)
|
||||
:ok
|
||||
end
|
||||
|
||||
def on_presence(user, _server, _resource, _packet) do
|
||||
info('Receive presence for #{user}')
|
||||
:none
|
||||
end
|
||||
end
|
||||
+354
-328
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -120,7 +120,7 @@
|
||||
{"has been kicked because of a system shutdown","telah dikick karena sistem shutdown"}.
|
||||
{"has been kicked because the room has been changed to members-only","telah dikick karena ruangan telah diubah menjadi hanya untuk member"}.
|
||||
{"has been kicked","telah dikick"}.
|
||||
{" has set the subject to: ","telah menetapkan topik yaitu:"}.
|
||||
{" has set the subject to: "," telah menetapkan topik yaitu: "}.
|
||||
{"Host","Host"}.
|
||||
{"If you don't see the CAPTCHA image here, visit the web page.","Jika Anda tidak melihat gambar CAPTCHA disini, silahkan kunjungi halaman web."}.
|
||||
{"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.","Jika Anda ingin menentukan port yang berbeda, sandi, pengkodean untuk layanan IRC, isi daftar ini dengan nilai-nilai dalam format '{\"server irc \", \"encoding \", port, \"sandi \"}'. Secara default ini menggunakan layanan \"~s \" pengkodean, port ~p, kata sandi kosong."}.
|
||||
|
||||
+56
-14
@@ -16,7 +16,7 @@ Cfg = case file:consult("vars.config") of
|
||||
Macros = lists:flatmap(
|
||||
fun({roster_gateway_workaround, true}) ->
|
||||
[{d, 'ROSTER_GATEWAY_WORKAROUND'}];
|
||||
({transient_supervisors, true}) ->
|
||||
({transient_supervisors, false}) ->
|
||||
[{d, 'NO_TRANSIENT_SUPERVISORS'}];
|
||||
({nif, true}) ->
|
||||
[{d, 'NIF'}];
|
||||
@@ -42,9 +42,6 @@ HiPE = case lists:keysearch(hipe, 1, Cfg) of
|
||||
[]
|
||||
end,
|
||||
|
||||
Includes = [{i, "include"},
|
||||
{i, filename:join(["deps", "p1_xml", "include"])}],
|
||||
|
||||
SrcDirs = lists:foldl(
|
||||
fun({tools, true}, Acc) ->
|
||||
[tools|Acc];
|
||||
@@ -56,8 +53,11 @@ 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"}},
|
||||
{xmlrpc, ".*", {git, "git://github.com/rds13/xmlrpc"}}],
|
||||
{ehyperloglog, ".*", {git, "https://github.com/vaxelfel/eHyperLogLog.git"}},
|
||||
{p1_utils, ".*", {git, "git://github.com/processone/p1_utils"}}],
|
||||
|
||||
ConfigureCmd = fun(Pkg, Flags) ->
|
||||
{'get-deps',
|
||||
@@ -76,6 +76,8 @@ XMLFlags = lists:foldl(
|
||||
|
||||
PostHooks = [ConfigureCmd("p1_tls", ""),
|
||||
ConfigureCmd("p1_stringprep", ""),
|
||||
ConfigureCmd("p1_yaml", ""),
|
||||
ConfigureCmd("esip", ""),
|
||||
ConfigureCmd("p1_xml", XMLFlags)],
|
||||
|
||||
CfgDeps = lists:flatmap(
|
||||
@@ -87,15 +89,17 @@ CfgDeps = lists:flatmap(
|
||||
[{p1_pam, ".*", {git, "git://github.com/processone/epam"}}];
|
||||
({zlib, true}) ->
|
||||
[{p1_zlib, ".*", {git, "git://github.com/processone/zlib"}}];
|
||||
({stun, true}) ->
|
||||
[{p1_stun, ".*", {git, "git://github.com/processone/stun"}}];
|
||||
({riak, true}) ->
|
||||
[{riakc, ".*",
|
||||
{git, "git://github.com/basho/riak-erlang-client",
|
||||
{tag, "1.4.2"}}}];
|
||||
({json, true}) ->
|
||||
[{jiffy, ".*", {git, "git://github.com/davisp/jiffy"}}];
|
||||
({elixir, true}) ->
|
||||
[{rebar_elixir_plugin, ".*", {git, "git://github.com/yrashk/rebar_elixir_plugin"}},
|
||||
{elixir, "1.1.*", {git, "git://github.com/elixir-lang/elixir"}}];
|
||||
({iconv, true}) ->
|
||||
[{p1_iconv, ".*", {git, "git://github.com/processone/eiconv"}}];
|
||||
({http, true}) ->
|
||||
[{ibrowse, ".*", {git, "git://github.com/cmullaparthi/ibrowse"}},
|
||||
{lhttpc, ".*", {git, "git://github.com/esl/lhttpc"}}];
|
||||
({lager, true}) ->
|
||||
[{lager, ".*", {git, "git://github.com/basho/lager"}}];
|
||||
({lager, false}) ->
|
||||
@@ -115,17 +119,55 @@ CfgPostHooks = lists:flatmap(
|
||||
[]
|
||||
end, Cfg),
|
||||
|
||||
CfgXrefs = lists:flatmap(
|
||||
fun({mysql, false}) ->
|
||||
["(\".*mysql.*\":_/_)"];
|
||||
({pgsql, false}) ->
|
||||
["(\".*pgsql.*\":_/_)"];
|
||||
({pam, false}) ->
|
||||
["(\"epam\":_/_)"];
|
||||
({riak, false}) ->
|
||||
["(\"riak.*\":_/_)"];
|
||||
({riak, true}) ->
|
||||
% used in map-reduce function called from riak vm
|
||||
["(\"riak_object\":_/_)"];
|
||||
({json, false}) ->
|
||||
["(\"jiffy\":_/_)"];
|
||||
({zlib, false}) ->
|
||||
["(\"ezlib\":_/_)"];
|
||||
({http, false}) ->
|
||||
["(\"lhttpc\":_/_)"];
|
||||
({iconv, false}) ->
|
||||
["(\"iconv\":_/_)"];
|
||||
({odbc, false}) ->
|
||||
["(\"odbc\":_/_)"];
|
||||
(_) ->
|
||||
[]
|
||||
end, Cfg),
|
||||
|
||||
ElixirConfig = case lists:keysearch(elixir, 1, Cfg) of
|
||||
{value, {elixir, true}} ->
|
||||
[{plugins, [rebar_elixir_compiler, rebar_exunit] },
|
||||
{lib_dirs, ["deps/elixir/lib"]}];
|
||||
_ ->
|
||||
[]
|
||||
end,
|
||||
|
||||
{ok, Cwd} = file:get_cwd(),
|
||||
|
||||
Config = [{erl_opts, Includes ++ Macros ++ HiPE ++ DebugInfo ++
|
||||
Config = [{erl_opts, Macros ++ HiPE ++ DebugInfo ++
|
||||
[{src_dirs, [asn1, src | SrcDirs]}]},
|
||||
{sub_dirs, ["rel"]},
|
||||
{keep_build_info, true},
|
||||
{ct_extra_params, "-include "
|
||||
++ filename:join([Cwd, "tools"]) ++ " "
|
||||
++ filename:join([Cwd, "deps", "p1_xml", "include"])},
|
||||
++ filename:join([Cwd, "tools"])},
|
||||
{xref_warnings, false},
|
||||
{xref_checks, []},
|
||||
{xref_queries,
|
||||
[{"(XC - UC) || (XU - X - B - "
|
||||
++ string:join(CfgXrefs, " - ") ++ ")", []}]},
|
||||
{post_hooks, PostHooks ++ CfgPostHooks},
|
||||
{deps, Deps ++ CfgDeps}],
|
||||
{deps, Deps ++ CfgDeps}] ++ ElixirConfig,
|
||||
%%io:format("ejabberd configuration:~n ~p~n", [Config]),
|
||||
Config.
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ ConfiguredOTPApps = lists:flatmap(
|
||||
|
||||
OTPApps = RequiredOTPApps ++ ConfiguredOTPApps,
|
||||
|
||||
DepRequiredApps = [p1_cache_tab, p1_tls, p1_stringprep, p1_xml, p1_yaml, xmlrpc],
|
||||
DepRequiredApps = [p1_cache_tab, p1_tls, p1_stringprep, p1_xml, p1_yaml, p1_utils],
|
||||
|
||||
DepConfiguredApps = lists:flatmap(
|
||||
fun({mysql, true}) -> [p1_mysql];
|
||||
@@ -38,7 +38,6 @@ DepConfiguredApps = lists:flatmap(
|
||||
({stun, true}) -> [p1_stun];
|
||||
({json, true}) -> [jiffy];
|
||||
({iconv, true}) -> [p1_iconv];
|
||||
({http, true}) -> [ibrowse, lhttpc];
|
||||
({lager, true}) -> [lager, goldrush];
|
||||
({lager, false}) -> [p1_logger];
|
||||
(_) -> []
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
* 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
|
||||
@@ -11,10 +11,9 @@
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
* 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
|
||||
@@ -11,10 +11,9 @@
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+1782
File diff suppressed because it is too large
Load Diff
+30
-34
@@ -1,5 +1,5 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
-- 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
|
||||
@@ -11,27 +11,23 @@
|
||||
-- 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
|
||||
-- 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.
|
||||
--
|
||||
|
||||
-- Needs MySQL (at least 4.0.x) with innodb back-end
|
||||
SET table_type=InnoDB;
|
||||
|
||||
CREATE TABLE users (
|
||||
username varchar(250) PRIMARY KEY,
|
||||
password text NOT NULL,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
|
||||
CREATE TABLE last (
|
||||
username varchar(250) PRIMARY KEY,
|
||||
seconds text NOT NULL,
|
||||
state text NOT NULl
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
|
||||
CREATE TABLE rosterusers (
|
||||
@@ -45,7 +41,7 @@ CREATE TABLE rosterusers (
|
||||
subscribe text NOT NULL,
|
||||
type text,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE UNIQUE INDEX i_rosteru_user_jid ON rosterusers(username(75), jid(75));
|
||||
CREATE INDEX i_rosteru_username ON rosterusers(username);
|
||||
@@ -55,7 +51,7 @@ CREATE TABLE rostergroups (
|
||||
username varchar(250) NOT NULL,
|
||||
jid varchar(250) NOT NULL,
|
||||
grp text NOT NULL
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE INDEX pk_rosterg_user_jid ON rostergroups(username(75), jid(75));
|
||||
|
||||
@@ -63,13 +59,13 @@ CREATE TABLE sr_group (
|
||||
name varchar(250) NOT NULL,
|
||||
opts text NOT NULL,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE TABLE sr_user (
|
||||
jid varchar(250) NOT NULL,
|
||||
grp varchar(250) NOT NULL,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE UNIQUE INDEX i_sr_user_jid_group ON sr_user(jid(75), grp(75));
|
||||
CREATE INDEX i_sr_user_jid ON sr_user(jid);
|
||||
@@ -80,22 +76,21 @@ CREATE TABLE spool (
|
||||
xml text NOT NULL,
|
||||
seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE INDEX i_despool USING BTREE ON spool(username);
|
||||
|
||||
|
||||
CREATE TABLE vcard (
|
||||
username varchar(250) PRIMARY KEY,
|
||||
vcard mediumtext NOT NULL,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE TABLE vcard_xupdate (
|
||||
username varchar(250) PRIMARY KEY,
|
||||
hash text NOT NULL,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE TABLE vcard_search (
|
||||
username varchar(250) NOT NULL,
|
||||
@@ -122,7 +117,7 @@ CREATE TABLE vcard_search (
|
||||
lorgname varchar(250) NOT NULL,
|
||||
orgunit text NOT NULL,
|
||||
lorgunit varchar(250) NOT NULL
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn);
|
||||
CREATE INDEX i_vcard_search_lfamily ON vcard_search(lfamily);
|
||||
@@ -139,14 +134,14 @@ CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
|
||||
CREATE TABLE privacy_default_list (
|
||||
username varchar(250) PRIMARY KEY,
|
||||
name varchar(250) NOT NULL
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE TABLE privacy_list (
|
||||
username varchar(250) NOT NULL,
|
||||
name varchar(250) NOT NULL,
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE INDEX i_privacy_list_username USING BTREE ON privacy_list(username);
|
||||
CREATE UNIQUE INDEX i_privacy_list_username_name USING BTREE ON privacy_list (username(75), name(75));
|
||||
@@ -162,14 +157,15 @@ CREATE TABLE privacy_list_data (
|
||||
match_message boolean NOT NULL,
|
||||
match_presence_in boolean NOT NULL,
|
||||
match_presence_out boolean NOT NULL
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
CREATE INDEX i_privacy_list_data_id ON privacy_list_data(id);
|
||||
|
||||
CREATE TABLE private_storage (
|
||||
username varchar(250) NOT NULL,
|
||||
namespace varchar(250) NOT NULL,
|
||||
data text NOT NULL,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE INDEX i_private_storage_username USING BTREE ON private_storage(username);
|
||||
CREATE UNIQUE INDEX i_private_storage_username_namespace USING BTREE ON private_storage(username(75), namespace(75));
|
||||
@@ -178,7 +174,7 @@ CREATE UNIQUE INDEX i_private_storage_username_namespace USING BTREE ON private_
|
||||
CREATE TABLE roster_version (
|
||||
username varchar(250) PRIMARY KEY,
|
||||
version text NOT NULL
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
-- To update from 1.x:
|
||||
-- ALTER TABLE rosterusers ADD COLUMN askmessage text AFTER ask;
|
||||
@@ -191,7 +187,7 @@ CREATE TABLE pubsub_node (
|
||||
parent text,
|
||||
type text,
|
||||
nodeid bigint auto_increment primary key
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
CREATE INDEX i_pubsub_node_parent ON pubsub_node(parent(120));
|
||||
CREATE UNIQUE INDEX i_pubsub_node_tuple ON pubsub_node(host(20), node(120));
|
||||
|
||||
@@ -199,14 +195,14 @@ CREATE TABLE pubsub_node_option (
|
||||
nodeid bigint,
|
||||
name text,
|
||||
val text
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
CREATE INDEX i_pubsub_node_option_nodeid ON pubsub_node_option(nodeid);
|
||||
ALTER TABLE `pubsub_node_option` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE;
|
||||
|
||||
CREATE TABLE pubsub_node_owner (
|
||||
nodeid bigint,
|
||||
owner text
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
CREATE INDEX i_pubsub_node_owner_nodeid ON pubsub_node_owner(nodeid);
|
||||
ALTER TABLE `pubsub_node_owner` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE;
|
||||
|
||||
@@ -216,7 +212,7 @@ CREATE TABLE pubsub_state (
|
||||
affiliation character(1),
|
||||
subscriptions text,
|
||||
stateid bigint auto_increment primary key
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
CREATE INDEX i_pubsub_state_jid ON pubsub_state(jid(60));
|
||||
CREATE UNIQUE INDEX i_pubsub_state_tuple ON pubsub_state(nodeid, jid(60));
|
||||
ALTER TABLE `pubsub_state` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE;
|
||||
@@ -228,7 +224,7 @@ CREATE TABLE pubsub_item (
|
||||
creation text,
|
||||
modification text,
|
||||
payload text
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
CREATE INDEX i_pubsub_item_itemid ON pubsub_item(itemid(36));
|
||||
CREATE UNIQUE INDEX i_pubsub_item_tuple ON pubsub_item(nodeid, itemid(36));
|
||||
ALTER TABLE `pubsub_item` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE;
|
||||
@@ -245,7 +241,7 @@ CREATE TABLE muc_room (
|
||||
host text NOT NULL,
|
||||
opts text NOT NULL,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE UNIQUE INDEX i_muc_room_name_host USING BTREE ON muc_room(name(75), host(75));
|
||||
|
||||
@@ -254,7 +250,7 @@ CREATE TABLE muc_registered (
|
||||
host text NOT NULL,
|
||||
nick text NOT NULL,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE INDEX i_muc_registered_nick USING BTREE ON muc_registered(nick(75));
|
||||
CREATE UNIQUE INDEX i_muc_registered_jid_host USING BTREE ON muc_registered(jid(75), host(75));
|
||||
@@ -264,7 +260,7 @@ CREATE TABLE irc_custom (
|
||||
host text NOT NULL,
|
||||
data text NOT NULL,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE UNIQUE INDEX i_irc_custom_jid_host USING BTREE ON irc_custom(jid(75), host(75));
|
||||
|
||||
@@ -272,13 +268,13 @@ CREATE TABLE motd (
|
||||
username varchar(250) PRIMARY KEY,
|
||||
xml text,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE TABLE caps_features (
|
||||
node varchar(250) NOT NULL,
|
||||
subnode varchar(250) NOT NULL,
|
||||
feature text,
|
||||
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) CHARACTER SET utf8;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8;
|
||||
|
||||
CREATE INDEX i_caps_features_node_subnode ON caps_features(node(75), subnode(75));
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
--
|
||||
-- ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
-- 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
|
||||
@@ -11,10 +11,9 @@
|
||||
-- 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
|
||||
-- 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.
|
||||
--
|
||||
|
||||
CREATE TABLE users (
|
||||
|
||||
+23
-25
@@ -5,7 +5,7 @@
|
||||
%%% Created : 18 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -37,7 +36,7 @@
|
||||
-include("jlib.hrl").
|
||||
|
||||
-record(acl, {aclname, aclspec}).
|
||||
-record(access, {name :: access_name(),
|
||||
-record(access, {name :: aclname(),
|
||||
rules = [] :: [access_rule()]}).
|
||||
|
||||
-type regexp() :: binary().
|
||||
@@ -237,6 +236,8 @@ normalize_spec(Spec) ->
|
||||
{server_regexp, SR} -> {server_regexp, b(SR)};
|
||||
{server_glob, S} -> {server_glob, b(S)};
|
||||
{resource_glob, R} -> {resource_glob, b(R)};
|
||||
{ip, {Net, Mask}} ->
|
||||
{ip, {Net, Mask}};
|
||||
{ip, S} ->
|
||||
case parse_ip_netmask(b(S)) of
|
||||
{ok, Net, Mask} ->
|
||||
@@ -263,9 +264,6 @@ match_rule(Host, Access, JID) ->
|
||||
end,
|
||||
case GAccess ++ LAccess of
|
||||
[] ->
|
||||
?WARNING_MSG("Attempt to match against unspecified "
|
||||
"access rule '~s' (scope: ~s)",
|
||||
[Access, Host]),
|
||||
deny;
|
||||
AccessList ->
|
||||
Rules = lists:flatmap(
|
||||
@@ -455,22 +453,22 @@ transform_options({acl, Name, Type}, Opts) ->
|
||||
T = case Type of
|
||||
all -> all;
|
||||
none -> none;
|
||||
{user, U} -> {user, [U]};
|
||||
{user, U, S} -> {user, [[{U, S}]]};
|
||||
{shared_group, G} -> {shared_group, [G]};
|
||||
{shared_group, G, H} -> {shared_group, [[{G, H}]]};
|
||||
{user_regexp, UR} -> {user_regexp, [UR]};
|
||||
{user_regexp, UR, S} -> {user_regexp, [[{UR, S}]]};
|
||||
{node_regexp, UR, SR} -> {node_regexp, [[{UR, SR}]]};
|
||||
{user_glob, UR} -> {user_glob, [UR]};
|
||||
{user_glob, UR, S} -> {user_glob, [[{UR, S}]]};
|
||||
{node_glob, UR, SR} -> {node_glob, [[{UR, SR}]]};
|
||||
{server, S} -> {server, [S]};
|
||||
{resource, R} -> {resource, [R]};
|
||||
{server_regexp, SR} -> {server_regexp, [SR]};
|
||||
{server_glob, S} -> {server_glob, [S]};
|
||||
{ip, S} -> {ip, [S]};
|
||||
{resource_glob, R} -> {resource_glob, [R]}
|
||||
{user, U} -> {user, [b(U)]};
|
||||
{user, U, S} -> {user, [[{b(U), b(S)}]]};
|
||||
{shared_group, G} -> {shared_group, [b(G)]};
|
||||
{shared_group, G, H} -> {shared_group, [[{b(G), b(H)}]]};
|
||||
{user_regexp, UR} -> {user_regexp, [b(UR)]};
|
||||
{user_regexp, UR, S} -> {user_regexp, [[{b(UR), b(S)}]]};
|
||||
{node_regexp, UR, SR} -> {node_regexp, [[{b(UR), b(SR)}]]};
|
||||
{user_glob, UR} -> {user_glob, [b(UR)]};
|
||||
{user_glob, UR, S} -> {user_glob, [[{b(UR), b(S)}]]};
|
||||
{node_glob, UR, SR} -> {node_glob, [[{b(UR), b(SR)}]]};
|
||||
{server, S} -> {server, [b(S)]};
|
||||
{resource, R} -> {resource, [b(R)]};
|
||||
{server_regexp, SR} -> {server_regexp, [b(SR)]};
|
||||
{server_glob, S} -> {server_glob, [b(S)]};
|
||||
{ip, S} -> {ip, [b(S)]};
|
||||
{resource_glob, R} -> {resource_glob, [b(R)]}
|
||||
end,
|
||||
[{acl, [{Name, [T]}]}|Opts];
|
||||
transform_options({access, Name, Rules}, Opts) ->
|
||||
|
||||
+4
-5
@@ -5,7 +5,7 @@
|
||||
%%% Created : 31 Oct 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
+29
-8
@@ -5,7 +5,7 @@
|
||||
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -94,9 +93,15 @@ start() ->
|
||||
).
|
||||
|
||||
register_mechanism(Mechanism, Module, PasswordType) ->
|
||||
ets:insert(sasl_mechanism,
|
||||
#sasl_mechanism{mechanism = Mechanism, module = Module,
|
||||
password_type = PasswordType}).
|
||||
case is_disabled(Mechanism) of
|
||||
false ->
|
||||
ets:insert(sasl_mechanism,
|
||||
#sasl_mechanism{mechanism = Mechanism, module = Module,
|
||||
password_type = PasswordType});
|
||||
true ->
|
||||
?DEBUG("SASL mechanism ~p is disabled", [Mechanism]),
|
||||
true
|
||||
end.
|
||||
|
||||
%%% TODO: use callbacks
|
||||
%%-include("ejabberd.hrl").
|
||||
@@ -216,3 +221,19 @@ filter_anonymous(Host, Mechs) ->
|
||||
true -> Mechs;
|
||||
false -> Mechs -- [<<"ANONYMOUS">>]
|
||||
end.
|
||||
|
||||
-spec(is_disabled/1 ::
|
||||
(
|
||||
Mechanism :: mechanism())
|
||||
-> boolean()
|
||||
).
|
||||
|
||||
is_disabled(Mechanism) ->
|
||||
Disabled = ejabberd_config:get_option(
|
||||
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, []),
|
||||
lists:member(Mechanism, Disabled).
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%%% Created : 23 Aug 2005 by Magnus Henoch <henoch@dtek.chalmers.se>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -18,10 +18,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 11 Mar 2003 by Alexey Shchepin <alexey@sevcom.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -237,7 +236,7 @@ response(KeyVals, User, Passwd, Nonce, AuthzId,
|
||||
DigestURI = proplists_get_bin_value(<<"digest-uri">>, KeyVals, <<>>),
|
||||
NC = proplists_get_bin_value(<<"nc">>, KeyVals, <<>>),
|
||||
QOP = proplists_get_bin_value(<<"qop">>, KeyVals, <<>>),
|
||||
MD5Hash = crypto:md5(<<User/binary, ":", Realm/binary, ":",
|
||||
MD5Hash = erlang:md5(<<User/binary, ":", Realm/binary, ":",
|
||||
Passwd/binary>>),
|
||||
A1 = case AuthzId of
|
||||
<<"">> ->
|
||||
@@ -253,7 +252,7 @@ response(KeyVals, User, Passwd, Nonce, AuthzId,
|
||||
<<A2Prefix/binary, ":", DigestURI/binary,
|
||||
":00000000000000000000000000000000">>
|
||||
end,
|
||||
T = <<(hex((crypto:md5(A1))))/binary, ":", Nonce/binary,
|
||||
T = <<(hex((erlang:md5(A1))))/binary, ":", Nonce/binary,
|
||||
":", NC/binary, ":", CNonce/binary, ":", QOP/binary,
|
||||
":", (hex((crypto:md5(A2))))/binary>>,
|
||||
hex((crypto:md5(T))).
|
||||
":", (hex((erlang:md5(A2))))/binary>>,
|
||||
hex((erlang:md5(T))).
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 8 Mar 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 7 Aug 2011 by Stephen Röttger <stephen.roettger@googlemail.com>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -77,9 +76,11 @@ mech_step(#state{step = 2} = State, ClientIn) ->
|
||||
UserName ->
|
||||
case parse_attribute(ClientNonceAttribute) of
|
||||
{$r, ClientNonce} ->
|
||||
case (State#state.get_password)(UserName) of
|
||||
{Ret, _AuthModule} = (State#state.get_password)(UserName),
|
||||
case {Ret, jlib:resourceprep(Ret)} of
|
||||
{false, _} -> {error, <<"not-authorized">>, UserName};
|
||||
{Ret, _AuthModule} ->
|
||||
{_, error} when is_binary(Ret) -> ?WARNING_MSG("invalid plain password", []), {error, <<"not-authorized">>, UserName};
|
||||
{Ret, _} ->
|
||||
{StoredKey, ServerKey, Salt, IterationCount} =
|
||||
if is_tuple(Ret) -> Ret;
|
||||
true ->
|
||||
|
||||
+4
-5
@@ -5,7 +5,7 @@
|
||||
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
+19
-8
@@ -5,7 +5,7 @@
|
||||
%%% Created : 7 May 2006 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
@@ -32,6 +31,7 @@
|
||||
status/0, reopen_log/0,
|
||||
stop_kindly/2, send_service_message_all_mucs/2,
|
||||
registered_vhosts/0,
|
||||
reload_config/0,
|
||||
%% Erlang
|
||||
update_list/0, update/1,
|
||||
%% Accounts
|
||||
@@ -135,6 +135,11 @@ commands() ->
|
||||
module = ?MODULE, function = registered_vhosts,
|
||||
args = [],
|
||||
result = {vhosts, {list, {vhost, string}}}},
|
||||
#ejabberd_commands{name = reload_config, tags = [server],
|
||||
desc = "Reload ejabberd configuration file into memory",
|
||||
module = ?MODULE, function = reload_config,
|
||||
args = [],
|
||||
result = {res, rescode}},
|
||||
|
||||
#ejabberd_commands{name = import_file, tags = [mnesia],
|
||||
desc = "Import user data from jabberd14 spool file",
|
||||
@@ -253,9 +258,10 @@ reopen_log() ->
|
||||
%%% Stop Kindly
|
||||
%%%
|
||||
|
||||
stop_kindly(DelaySeconds, AnnouncementText) ->
|
||||
Subject = io_lib:format("Server stop in ~p seconds!", [DelaySeconds]),
|
||||
WaitingDesc = io_lib:format("Waiting ~p seconds", [DelaySeconds]),
|
||||
stop_kindly(DelaySeconds, AnnouncementTextString) ->
|
||||
Subject = list_to_binary(io_lib:format("Server stop in ~p seconds!", [DelaySeconds])),
|
||||
WaitingDesc = list_to_binary(io_lib:format("Waiting ~p seconds", [DelaySeconds])),
|
||||
AnnouncementText = list_to_binary(AnnouncementTextString),
|
||||
Steps = [
|
||||
{"Stopping ejabberd port listeners",
|
||||
ejabberd_listener, stop_listeners, []},
|
||||
@@ -352,6 +358,11 @@ registered_users(Host) ->
|
||||
registered_vhosts() ->
|
||||
?MYHOSTS.
|
||||
|
||||
reload_config() ->
|
||||
ejabberd_config:reload_file(),
|
||||
acl:start(),
|
||||
shaper:start().
|
||||
|
||||
%%%
|
||||
%%% Migration management
|
||||
%%%
|
||||
|
||||
+22
-8
@@ -5,7 +5,7 @@
|
||||
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -58,6 +57,7 @@ start(normal, _Args) ->
|
||||
connect_nodes(),
|
||||
Sup = ejabberd_sup:start_link(),
|
||||
ejabberd_rdbms:start(),
|
||||
ejabberd_riak_sup:start(),
|
||||
ejabberd_auth:start(),
|
||||
cyrsasl:start(),
|
||||
% Profiling
|
||||
@@ -108,6 +108,18 @@ loop() ->
|
||||
end.
|
||||
|
||||
db_init() ->
|
||||
MyNode = node(),
|
||||
DbNodes = mnesia:system_info(db_nodes),
|
||||
case lists:member(MyNode, DbNodes) of
|
||||
true ->
|
||||
ok;
|
||||
false ->
|
||||
?CRITICAL_MSG("Node name mismatch: I'm [~s], "
|
||||
"the database is owned by ~p", [MyNode, DbNodes]),
|
||||
?CRITICAL_MSG("Either set ERLANG_NODE in ejabberdctl.cfg "
|
||||
"or change node name in Mnesia", []),
|
||||
erlang:error(node_name_mismatch)
|
||||
end,
|
||||
case mnesia:system_info(extra_db_nodes) of
|
||||
[] ->
|
||||
mnesia:create_schema([node()]);
|
||||
@@ -178,10 +190,12 @@ add_windows_nameservers() ->
|
||||
|
||||
|
||||
broadcast_c2s_shutdown() ->
|
||||
Children = supervisor:which_children(ejabberd_c2s_sup),
|
||||
Children = ejabberd_sm:get_all_pids(),
|
||||
lists:foreach(
|
||||
fun({_, C2SPid, _, _}) ->
|
||||
C2SPid ! system_shutdown
|
||||
fun(C2SPid) when node(C2SPid) == node() ->
|
||||
C2SPid ! system_shutdown;
|
||||
(_) ->
|
||||
ok
|
||||
end, Children).
|
||||
|
||||
%%%
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 23 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -301,6 +300,9 @@ get_password_with_authmodule(User, Server) ->
|
||||
|
||||
-spec is_user_exists(binary(), binary()) -> boolean().
|
||||
|
||||
is_user_exists(_User, <<"">>) ->
|
||||
false;
|
||||
|
||||
is_user_exists(User, Server) ->
|
||||
%% Check if the user exists in all authentications module except the module
|
||||
%% passed as parameter
|
||||
@@ -443,5 +445,7 @@ import(Server) ->
|
||||
|
||||
import(Server, mnesia, Passwd) ->
|
||||
ejabberd_auth_internal:import(Server, mnesia, Passwd);
|
||||
import(Server, riak, Passwd) ->
|
||||
ejabberd_auth_riak:import(Server, riak, Passwd);
|
||||
import(_, _, _) ->
|
||||
pass.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 17 Feb 2006 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -55,10 +54,8 @@ start(Host) ->
|
||||
end,
|
||||
"extauth"),
|
||||
extauth:start(Host, Cmd),
|
||||
case check_cache_last_options(Host) of
|
||||
cache -> ok = ejabberd_auth_internal:start(Host);
|
||||
no_cache -> ok
|
||||
end.
|
||||
check_cache_last_options(Host),
|
||||
ejabberd_auth_internal:start(Host).
|
||||
|
||||
check_cache_last_options(Server) ->
|
||||
case get_cache_option(Server) of
|
||||
@@ -173,7 +170,9 @@ remove_user(User, Server, Password) ->
|
||||
get_cache_option(Host) ->
|
||||
case ejabberd_config:get_option(
|
||||
{extauth_cache, Host},
|
||||
fun(I) when is_integer(I), I > 0 -> I end) of
|
||||
fun(false) -> undefined;
|
||||
(I) when is_integer(I), I >= 0 -> I
|
||||
end) of
|
||||
undefined -> false;
|
||||
CacheTime -> {true, CacheTime}
|
||||
end.
|
||||
@@ -187,6 +186,8 @@ check_password_extauth(User, Server, Password) ->
|
||||
try_register_extauth(User, Server, Password) ->
|
||||
extauth:try_register(User, Server, Password).
|
||||
|
||||
check_password_cache(User, Server, Password, 0) ->
|
||||
check_password_external_cache(User, Server, Password);
|
||||
check_password_cache(User, Server, Password,
|
||||
CacheTime) ->
|
||||
case get_last_access(User, Server) of
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -78,10 +77,7 @@ update_reg_users_counter_table(Server) ->
|
||||
mnesia:sync_dirty(F).
|
||||
|
||||
plain_password_required() ->
|
||||
case is_scrammed() of
|
||||
false -> false;
|
||||
true -> true
|
||||
end.
|
||||
is_scrammed().
|
||||
|
||||
store_type() ->
|
||||
case is_scrammed() of
|
||||
@@ -151,7 +147,7 @@ set_password(User, Server, Password) ->
|
||||
ok
|
||||
end.
|
||||
|
||||
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid} | {aborted, Reason}
|
||||
%% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid} | {error, not_allowed} | {error, Reason}
|
||||
try_register(User, Server, PasswordList) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -388,7 +387,7 @@ parse_options(Host) ->
|
||||
[{<<"%u">>, <<"*">>}]),
|
||||
{DNFilter, DNFilterAttrs} =
|
||||
eldap_utils:get_opt({ldap_dn_filter, Host}, [],
|
||||
fun({DNF, DNFA}) ->
|
||||
fun([{DNF, DNFA}]) ->
|
||||
NewDNFA = case DNFA of
|
||||
undefined ->
|
||||
[];
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 12 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 5 Jul 2007 by Evgeniy Khramtsov <xram@jabber.ru>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(ejabberd_auth_pam).
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% File : ejabberd_auth_riak.erl
|
||||
%%% Author : Evgeniy Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% Purpose : Authentification via Riak
|
||||
%%% Created : 12 Nov 2012 by Evgeniy Khramtsov <ekhramtsov@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
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(ejabberd_auth_riak).
|
||||
|
||||
-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,
|
||||
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, export/1, import/3,
|
||||
plain_password_required/0]).
|
||||
-export([passwd_schema/0]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
|
||||
-record(passwd, {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$1',
|
||||
password = <<"">> :: binary() | scram() | '_'}).
|
||||
|
||||
-define(SALT_LENGTH, 16).
|
||||
|
||||
start(_Host) ->
|
||||
ok.
|
||||
|
||||
plain_password_required() ->
|
||||
case is_scrammed() of
|
||||
false -> false;
|
||||
true -> true
|
||||
end.
|
||||
|
||||
store_type() ->
|
||||
case is_scrammed() of
|
||||
false -> plain; %% allows: PLAIN DIGEST-MD5 SCRAM
|
||||
true -> scram %% allows: PLAIN SCRAM
|
||||
end.
|
||||
|
||||
passwd_schema() ->
|
||||
{record_info(fields, passwd), #passwd{}}.
|
||||
|
||||
check_password(User, Server, Password) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
|
||||
{ok, #passwd{password = Password}} when is_binary(Password) ->
|
||||
Password /= <<"">>;
|
||||
{ok, #passwd{password = Scram}} when is_record(Scram, scram) ->
|
||||
is_password_scram_valid(Password, Scram);
|
||||
_ ->
|
||||
false
|
||||
end.
|
||||
|
||||
check_password(User, Server, Password, Digest,
|
||||
DigestGen) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
|
||||
{ok, #passwd{password = Passwd}} when is_binary(Passwd) ->
|
||||
DigRes = if Digest /= <<"">> ->
|
||||
Digest == DigestGen(Passwd);
|
||||
true -> false
|
||||
end,
|
||||
if DigRes -> true;
|
||||
true -> (Passwd == Password) and (Password /= <<"">>)
|
||||
end;
|
||||
{ok, #passwd{password = Scram}}
|
||||
when is_record(Scram, scram) ->
|
||||
Passwd = jlib:decode_base64(Scram#scram.storedkey),
|
||||
DigRes = if Digest /= <<"">> ->
|
||||
Digest == DigestGen(Passwd);
|
||||
true -> false
|
||||
end,
|
||||
if DigRes -> true;
|
||||
true -> (Passwd == Password) and (Password /= <<"">>)
|
||||
end;
|
||||
_ -> false
|
||||
end.
|
||||
|
||||
set_password(User, Server, Password) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
US = {LUser, LServer},
|
||||
if (LUser == error) or (LServer == error) ->
|
||||
{error, invalid_jid};
|
||||
true ->
|
||||
Password2 = case is_scrammed() and is_binary(Password)
|
||||
of
|
||||
true -> password_to_scram(Password);
|
||||
false -> Password
|
||||
end,
|
||||
ok = ejabberd_riak:put(#passwd{us = US, password = Password2},
|
||||
passwd_schema(),
|
||||
[{'2i', [{<<"host">>, LServer}]}])
|
||||
end.
|
||||
|
||||
try_register(User, Server, PasswordList) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
Password = iolist_to_binary(PasswordList),
|
||||
US = {LUser, LServer},
|
||||
if (LUser == error) or (LServer == error) ->
|
||||
{error, invalid_jid};
|
||||
true ->
|
||||
case ejabberd_riak:get(passwd, passwd_schema(), US) of
|
||||
{error, notfound} ->
|
||||
Password2 = case is_scrammed() and
|
||||
is_binary(Password)
|
||||
of
|
||||
true -> password_to_scram(Password);
|
||||
false -> Password
|
||||
end,
|
||||
{atomic, ejabberd_riak:put(
|
||||
#passwd{us = US,
|
||||
password = Password2},
|
||||
passwd_schema(),
|
||||
[{'2i', [{<<"host">>, LServer}]}])};
|
||||
{ok, _} ->
|
||||
exists;
|
||||
Err ->
|
||||
{atomic, Err}
|
||||
end
|
||||
end.
|
||||
|
||||
dirty_get_registered_users() ->
|
||||
lists:flatmap(
|
||||
fun(Server) ->
|
||||
get_vh_registered_users(Server)
|
||||
end, ejabberd_config:get_vh_by_auth_method(riak)).
|
||||
|
||||
get_vh_registered_users(Server) ->
|
||||
LServer = jlib:nameprep(Server),
|
||||
case ejabberd_riak:get_keys_by_index(passwd, <<"host">>, LServer) of
|
||||
{ok, Users} ->
|
||||
Users;
|
||||
_ ->
|
||||
[]
|
||||
end.
|
||||
|
||||
get_vh_registered_users(Server, _) ->
|
||||
get_vh_registered_users(Server).
|
||||
|
||||
get_vh_registered_users_number(Server) ->
|
||||
LServer = jlib:nameprep(Server),
|
||||
case ejabberd_riak:count_by_index(passwd, <<"host">>, LServer) of
|
||||
{ok, N} ->
|
||||
N;
|
||||
_ ->
|
||||
0
|
||||
end.
|
||||
|
||||
get_vh_registered_users_number(Server, _) ->
|
||||
get_vh_registered_users_number(Server).
|
||||
|
||||
get_password(User, Server) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
|
||||
{ok, #passwd{password = Password}}
|
||||
when is_binary(Password) ->
|
||||
Password;
|
||||
{ok, #passwd{password = Scram}}
|
||||
when is_record(Scram, scram) ->
|
||||
{jlib:decode_base64(Scram#scram.storedkey),
|
||||
jlib:decode_base64(Scram#scram.serverkey),
|
||||
jlib:decode_base64(Scram#scram.salt),
|
||||
Scram#scram.iterationcount};
|
||||
_ -> false
|
||||
end.
|
||||
|
||||
get_password_s(User, Server) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
|
||||
{ok, #passwd{password = Password}}
|
||||
when is_binary(Password) ->
|
||||
Password;
|
||||
{ok, #passwd{password = Scram}}
|
||||
when is_record(Scram, scram) ->
|
||||
<<"">>;
|
||||
_ -> <<"">>
|
||||
end.
|
||||
|
||||
is_user_exists(User, Server) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
|
||||
{error, notfound} -> false;
|
||||
{ok, _} -> true;
|
||||
Err -> Err
|
||||
end.
|
||||
|
||||
remove_user(User, Server) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
ejabberd_riak:delete(passwd, {LUser, LServer}),
|
||||
ok.
|
||||
|
||||
remove_user(User, Server, Password) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
LServer = jlib:nameprep(Server),
|
||||
case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of
|
||||
{ok, #passwd{password = Password}}
|
||||
when is_binary(Password) ->
|
||||
ejabberd_riak:delete(passwd, {LUser, LServer}),
|
||||
ok;
|
||||
{ok, #passwd{password = Scram}}
|
||||
when is_record(Scram, scram) ->
|
||||
case is_password_scram_valid(Password, Scram) of
|
||||
true ->
|
||||
ejabberd_riak:delete(passwd, {LUser, LServer}),
|
||||
ok;
|
||||
false -> not_allowed
|
||||
end;
|
||||
_ -> not_exists
|
||||
end.
|
||||
|
||||
%%%
|
||||
%%% SCRAM
|
||||
%%%
|
||||
|
||||
is_scrammed() ->
|
||||
scram ==
|
||||
ejabberd_config:get_local_option({auth_password_format, ?MYNAME},
|
||||
fun(V) -> V end).
|
||||
|
||||
password_to_scram(Password) ->
|
||||
password_to_scram(Password,
|
||||
?SCRAM_DEFAULT_ITERATION_COUNT).
|
||||
|
||||
password_to_scram(Password, IterationCount) ->
|
||||
Salt = crypto:rand_bytes(?SALT_LENGTH),
|
||||
SaltedPassword = scram:salted_password(Password, Salt,
|
||||
IterationCount),
|
||||
StoredKey =
|
||||
scram:stored_key(scram:client_key(SaltedPassword)),
|
||||
ServerKey = scram:server_key(SaltedPassword),
|
||||
#scram{storedkey = jlib:encode_base64(StoredKey),
|
||||
serverkey = jlib:encode_base64(ServerKey),
|
||||
salt = jlib:encode_base64(Salt),
|
||||
iterationcount = IterationCount}.
|
||||
|
||||
is_password_scram_valid(Password, Scram) ->
|
||||
IterationCount = Scram#scram.iterationcount,
|
||||
Salt = jlib:decode_base64(Scram#scram.salt),
|
||||
SaltedPassword = scram:salted_password(Password, Salt,
|
||||
IterationCount),
|
||||
StoredKey =
|
||||
scram:stored_key(scram:client_key(SaltedPassword)),
|
||||
jlib:decode_base64(Scram#scram.storedkey) == StoredKey.
|
||||
|
||||
export(_Server) ->
|
||||
[{passwd,
|
||||
fun(Host, #passwd{us = {LUser, LServer}, password = Password})
|
||||
when LServer == Host ->
|
||||
Username = ejabberd_odbc:escape(LUser),
|
||||
Pass = ejabberd_odbc:escape(Password),
|
||||
[[<<"delete from users where username='">>, Username, <<"';">>],
|
||||
[<<"insert into users(username, password) "
|
||||
"values ('">>, Username, <<"', '">>, Pass, <<"');">>]];
|
||||
(_Host, _R) ->
|
||||
[]
|
||||
end}].
|
||||
|
||||
import(LServer, riak, #passwd{} = Passwd) ->
|
||||
ejabberd_riak:put(Passwd, passwd_schema(), [{'2i', [{<<"host">>, LServer}]}]);
|
||||
import(_, _, _) ->
|
||||
pass.
|
||||
+1109
-348
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
||||
%%% Created : 2 Nov 2007 by Mickael Remond <mremond@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -18,10 +18,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
+13
-14
@@ -5,7 +5,7 @@
|
||||
%%% Created : 26 Apr 2008 by Evgeniy Khramtsov <xramtsov@gmail.com>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
@@ -550,10 +549,11 @@ get_transfer_protocol(PortString) ->
|
||||
|
||||
get_port_listeners(PortNumber) ->
|
||||
AllListeners = ejabberd_config:get_option(listen, fun(V) -> V end),
|
||||
lists:filter(fun ({{Port, _Ip, _Netp}, _Module1,
|
||||
_Opts1})
|
||||
when Port == PortNumber ->
|
||||
true;
|
||||
lists:filter(fun (Listener) when is_list(Listener) ->
|
||||
case proplists:get_value(port, Listener) of
|
||||
PortNumber -> true;
|
||||
_ -> false
|
||||
end;
|
||||
(_) -> false
|
||||
end,
|
||||
AllListeners).
|
||||
@@ -563,12 +563,11 @@ get_captcha_transfer_protocol([]) ->
|
||||
"is not a ejabberd_http listener with "
|
||||
"'captcha' option. Change the port number "
|
||||
"or specify http:// in that option.">>);
|
||||
get_captcha_transfer_protocol([{{_Port, _Ip, tcp},
|
||||
ejabberd_http, Opts}
|
||||
| Listeners]) ->
|
||||
case lists:member(captcha, Opts) of
|
||||
get_captcha_transfer_protocol([Listener | Listeners]) when is_list(Listener) ->
|
||||
case proplists:get_value(module, Listener) == ejabberd_http andalso
|
||||
proplists:get_bool(captcha, Listener) of
|
||||
true ->
|
||||
case lists:member(tls, Opts) of
|
||||
case proplists:get_bool(tls, Listener) of
|
||||
true -> https;
|
||||
false -> http
|
||||
end;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 20 May 2008 by Badlop <badlop@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -400,7 +399,14 @@ check_auth({User, Server, Password}) ->
|
||||
check_access(all, _) ->
|
||||
true;
|
||||
check_access(Access, Auth) ->
|
||||
{ok, User, Server} = check_auth(Auth),
|
||||
case check_auth(Auth) of
|
||||
{ok, User, Server} ->
|
||||
check_access(Access, User, Server);
|
||||
_ ->
|
||||
false
|
||||
end.
|
||||
|
||||
check_access(Access, User, Server) ->
|
||||
%% Check this user has access permission
|
||||
case acl:match_rule(Server, Access, jlib:make_jid(User, Server, <<"">>)) of
|
||||
allow -> true;
|
||||
|
||||
+77
-34
@@ -5,7 +5,7 @@
|
||||
%%% Created : 14 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,17 +17,16 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(ejabberd_config).
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-export([start/0, load_file/1, read_file/1,
|
||||
-export([start/0, load_file/1, reload_file/0, read_file/1,
|
||||
add_global_option/2, add_local_option/2,
|
||||
get_global_option/2, get_local_option/2,
|
||||
get_global_option/3, get_local_option/3,
|
||||
@@ -69,8 +68,15 @@ start() ->
|
||||
%% This start time is used by mod_last:
|
||||
{MegaSecs, Secs, _} = now(),
|
||||
UnixTime = MegaSecs*1000000 + Secs,
|
||||
SharedKey = case erlang:get_cookie() of
|
||||
nocookie ->
|
||||
p1_sha:sha(randoms:get_string());
|
||||
Cookie ->
|
||||
p1_sha:sha(jlib:atom_to_binary(Cookie))
|
||||
end,
|
||||
State1 = set_option({node_start, global}, UnixTime, State),
|
||||
set_opts(State1).
|
||||
State2 = set_option({shared_key, global}, SharedKey, State1),
|
||||
set_opts(State2).
|
||||
|
||||
%% @doc Get the filename of the ejabberd configuration file.
|
||||
%% The filename can be specified with: erl -config "/path/to/ejabberd.yml".
|
||||
@@ -119,6 +125,12 @@ load_file(File) ->
|
||||
State = read_file(File),
|
||||
set_opts(State).
|
||||
|
||||
-spec reload_file() -> ok.
|
||||
|
||||
reload_file() ->
|
||||
Config = get_ejabberd_config_path(),
|
||||
load_file(Config).
|
||||
|
||||
-spec convert_to_yaml(file:filename()) -> ok | {error, any()}.
|
||||
|
||||
convert_to_yaml(File) ->
|
||||
@@ -178,9 +190,11 @@ consult(File) ->
|
||||
{ok, []} ->
|
||||
{ok, []};
|
||||
{ok, [Document|_]} ->
|
||||
{ok, Document};
|
||||
{ok, parserl(Document)};
|
||||
{error, Err} ->
|
||||
{error, p1_yaml:format_error(Err)}
|
||||
Msg1 = "Cannot load " ++ File ++ ": ",
|
||||
Msg2 = p1_yaml:format_error(Err),
|
||||
{error, Msg1 ++ Msg2}
|
||||
end;
|
||||
_ ->
|
||||
case file:consult(File) of
|
||||
@@ -193,6 +207,17 @@ consult(File) ->
|
||||
end
|
||||
end.
|
||||
|
||||
parserl(<<"> ", Term/binary>>) ->
|
||||
{ok, A2, _} = erl_scan:string(binary_to_list(Term)),
|
||||
{ok, A3} = erl_parse:parse_term(A2),
|
||||
A3;
|
||||
parserl({A, B}) ->
|
||||
{parserl(A), parserl(B)};
|
||||
parserl([El|Tail]) ->
|
||||
[parserl(El) | parserl(Tail)];
|
||||
parserl(Other) ->
|
||||
Other.
|
||||
|
||||
%% @doc Convert configuration filename to absolute path.
|
||||
%% Input is an absolute or relative path to an ejabberd configuration file.
|
||||
%% And returns an absolute path to the configuration file.
|
||||
@@ -202,9 +227,8 @@ get_absolute_path(File) ->
|
||||
absolute ->
|
||||
File;
|
||||
relative ->
|
||||
Config_path = get_ejabberd_config_path(),
|
||||
Config_dir = filename:dirname(Config_path),
|
||||
filename:absname_join(Config_dir, File)
|
||||
{ok, Dir} = file:get_cwd(),
|
||||
filename:absname_join(Dir, File)
|
||||
end.
|
||||
|
||||
|
||||
@@ -683,26 +707,40 @@ replace_module(mod_roster_odbc) -> {mod_roster, odbc};
|
||||
replace_module(mod_shared_roster_odbc) -> {mod_shared_roster, odbc};
|
||||
replace_module(mod_vcard_odbc) -> {mod_vcard, odbc};
|
||||
replace_module(mod_vcard_xupdate_odbc) -> {mod_vcard_xupdate, odbc};
|
||||
replace_module(Module) -> Module.
|
||||
replace_module(Module) ->
|
||||
case is_elixir_module(Module) of
|
||||
true -> expand_elixir_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
|
||||
%% ====================
|
||||
|
||||
%% If module name start with uppercase letter, this is an Elixir module:
|
||||
is_elixir_module(Module) ->
|
||||
case atom_to_list(Module) of
|
||||
[H|_] when H >= 65, H =< 90 -> true;
|
||||
_ ->false
|
||||
end.
|
||||
|
||||
%% We assume we know this is an elixir module
|
||||
expand_elixir_module(Module) ->
|
||||
case atom_to_list(Module) of
|
||||
%% Module name already specified as an Elixir from Erlang module name
|
||||
"Elixir." ++ _ -> Module;
|
||||
%% if start with uppercase letter, this is an Elixir module: Append 'Elixir.' to module name.
|
||||
ModuleString ->
|
||||
list_to_atom("Elixir." ++ ModuleString)
|
||||
end.
|
||||
|
||||
strings_to_binary([]) ->
|
||||
[];
|
||||
@@ -981,9 +1019,14 @@ report_and_stop(Tab, Err) ->
|
||||
halt(string:substr(ErrTxt, 1, 199)).
|
||||
|
||||
emit_deprecation_warning(Module, NewModule, DBType) ->
|
||||
?WARNING_MSG("Module ~s is deprecated, use {~s, [{db_type, ~s}, ...]}"
|
||||
?WARNING_MSG("Module ~s is deprecated, use ~s with 'db_type: ~s'"
|
||||
" instead", [Module, NewModule, DBType]).
|
||||
|
||||
emit_deprecation_warning(Module, NewModule) ->
|
||||
?WARNING_MSG("Module ~s is deprecated, use ~s instead",
|
||||
[Module, NewModule]).
|
||||
case is_elixir_module(NewModule) of
|
||||
%% Do not emit deprecation warning for Elixir
|
||||
true -> ok;
|
||||
false ->
|
||||
?WARNING_MSG("Module ~s is deprecated, use ~s instead",
|
||||
[Module, NewModule])
|
||||
end.
|
||||
|
||||
+29
-27
@@ -5,7 +5,7 @@
|
||||
%%% Created : 11 Jan 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -84,7 +83,7 @@ start() ->
|
||||
Node = list_to_atom(SNode1),
|
||||
Status = case rpc:call(Node, ?MODULE, process, [Args]) of
|
||||
{badrpc, Reason} ->
|
||||
?PRINT("Failed RPC connection to the node ~p: ~p~n",
|
||||
print("Failed RPC connection to the node ~p: ~p~n",
|
||||
[Node, Reason]),
|
||||
%% TODO: show minimal start help
|
||||
?STATUS_BADRPC;
|
||||
@@ -131,17 +130,17 @@ unregister_commands(CmdDescs, Module, Function) ->
|
||||
%% they are usable even if ejabberd is completely stopped.
|
||||
process(["status"]) ->
|
||||
{InternalStatus, ProvidedStatus} = init:get_status(),
|
||||
?PRINT("The node ~p is ~p with status: ~p~n",
|
||||
print("The node ~p is ~p with status: ~p~n",
|
||||
[node(), InternalStatus, ProvidedStatus]),
|
||||
case lists:keysearch(ejabberd, 1, application:which_applications()) of
|
||||
false ->
|
||||
EjabberdLogPath = ejabberd_logger:get_log_path(),
|
||||
?PRINT("ejabberd is not running in that node~n"
|
||||
print("ejabberd is not running in that node~n"
|
||||
"Check for error messages: ~s~n"
|
||||
"or other files in that directory.~n", [EjabberdLogPath]),
|
||||
?STATUS_ERROR;
|
||||
{value, {_, _, Version}} ->
|
||||
?PRINT("ejabberd ~s is running in that node~n", [Version]),
|
||||
print("ejabberd ~s is running in that node~n", [Version]),
|
||||
?STATUS_SUCCESS
|
||||
end;
|
||||
|
||||
@@ -155,7 +154,7 @@ process(["restart"]) ->
|
||||
?STATUS_SUCCESS;
|
||||
|
||||
process(["mnesia"]) ->
|
||||
?PRINT("~p~n", [mnesia:system_info(all)]),
|
||||
print("~p~n", [mnesia:system_info(all)]),
|
||||
?STATUS_SUCCESS;
|
||||
|
||||
process(["mnesia", "info"]) ->
|
||||
@@ -164,8 +163,8 @@ process(["mnesia", "info"]) ->
|
||||
|
||||
process(["mnesia", Arg]) ->
|
||||
case catch mnesia:system_info(list_to_atom(Arg)) of
|
||||
{'EXIT', Error} -> ?PRINT("Error: ~p~n", [Error]);
|
||||
Return -> ?PRINT("~p~n", [Return])
|
||||
{'EXIT', Error} -> print("Error: ~p~n", [Error]);
|
||||
Return -> print("~p~n", [Return])
|
||||
end,
|
||||
?STATUS_SUCCESS;
|
||||
|
||||
@@ -211,7 +210,7 @@ process(Args) ->
|
||||
|
||||
%% @spec (Args::[string()], AccessCommands) -> {String::string(), Code::integer()}
|
||||
process2(["--auth", User, Server, Pass | Args], AccessCommands) ->
|
||||
process2(Args, {User, Server, Pass}, AccessCommands);
|
||||
process2(Args, {list_to_binary(User), list_to_binary(Server), list_to_binary(Pass)}, AccessCommands);
|
||||
process2(Args, AccessCommands) ->
|
||||
process2(Args, noauth, AccessCommands).
|
||||
|
||||
@@ -261,7 +260,7 @@ try_run_ctp(Args, Auth, AccessCommands) ->
|
||||
Error:Why ->
|
||||
%% In this case probably ejabberd is not started, so let's show Status
|
||||
process(["status"]),
|
||||
?PRINT("~n", []),
|
||||
print("~n", []),
|
||||
{io_lib:format("Error in ejabberd ctl process: '~p' ~p", [Error, Why]), ?STATUS_USAGE}
|
||||
end.
|
||||
|
||||
@@ -419,6 +418,7 @@ is_supported_args(Args) ->
|
||||
fun({_Name, Format}) ->
|
||||
(Format == integer)
|
||||
or (Format == string)
|
||||
or (Format == binary)
|
||||
end,
|
||||
Args).
|
||||
|
||||
@@ -457,14 +457,14 @@ print_usage(HelpMode, MaxC, ShCode) ->
|
||||
get_list_commands() ++
|
||||
get_list_ctls(),
|
||||
|
||||
?PRINT(
|
||||
print(
|
||||
["Usage: ", ?B("ejabberdctl"), " [--node ", ?U("nodename"), "] [--auth ",
|
||||
?U("user"), " ", ?U("host"), " ", ?U("password"), "] ",
|
||||
?U("command"), " [", ?U("options"), "]\n"
|
||||
"\n"
|
||||
"Available commands in this ejabberd node:\n"], []),
|
||||
print_usage_commands(HelpMode, MaxC, ShCode, AllCommands),
|
||||
?PRINT(
|
||||
print(
|
||||
["\n"
|
||||
"Examples:\n"
|
||||
" ejabberdctl restart\n"
|
||||
@@ -498,7 +498,7 @@ print_usage_commands(HelpMode, MaxC, ShCode, Commands) ->
|
||||
%% Convert its definition to a line
|
||||
FmtCmdDescs = format_command_lines(CmdArgsLenDescsSorted, MaxCmdLen, MaxC, ShCode, HelpMode),
|
||||
|
||||
?PRINT([FmtCmdDescs], []).
|
||||
print([FmtCmdDescs], []).
|
||||
|
||||
|
||||
%% Get some info about the shell:
|
||||
@@ -565,7 +565,7 @@ format_command_lines(CALD, MaxCmdLen, MaxC, ShCode, dual) ->
|
||||
lists:map(
|
||||
fun({Cmd, Args, CmdArgsL, Desc}) ->
|
||||
DescFmt = prepare_description(MaxCmdLen+4, MaxC, Desc),
|
||||
[" ", ?B(Cmd), " ", [[?U(Arg), " "] || Arg <- Args],
|
||||
[" ", ?B(Cmd), " ", [[?U(Arg), " "] || Arg <- Args],
|
||||
string:chars($\s, MaxCmdLen - CmdArgsL + 1),
|
||||
DescFmt, "\n"]
|
||||
end, CALD);
|
||||
@@ -574,7 +574,7 @@ format_command_lines(CALD, _MaxCmdLen, MaxC, ShCode, long) ->
|
||||
lists:map(
|
||||
fun({Cmd, Args, _CmdArgsL, Desc}) ->
|
||||
DescFmt = prepare_description(8, MaxC, Desc),
|
||||
["\n ", ?B(Cmd), " ", [[?U(Arg), " "] || Arg <- Args], "\n", " ",
|
||||
["\n ", ?B(Cmd), " ", [[?U(Arg), " "] || Arg <- Args], "\n", " ",
|
||||
DescFmt, "\n"]
|
||||
end, CALD).
|
||||
|
||||
@@ -584,20 +584,20 @@ format_command_lines(CALD, _MaxCmdLen, MaxC, ShCode, long) ->
|
||||
%%-----------------------------
|
||||
|
||||
print_usage_tags(MaxC, ShCode) ->
|
||||
?PRINT("Available tags and commands:", []),
|
||||
print("Available tags and commands:", []),
|
||||
TagsCommands = ejabberd_commands:get_tags_commands(),
|
||||
lists:foreach(
|
||||
fun({Tag, Commands} = _TagCommands) ->
|
||||
?PRINT(["\n\n ", ?B(Tag), "\n "], []),
|
||||
print(["\n\n ", ?B(Tag), "\n "], []),
|
||||
Words = lists:sort(Commands),
|
||||
Desc = prepare_long_line(5, MaxC, Words),
|
||||
?PRINT(Desc, [])
|
||||
print(Desc, [])
|
||||
end,
|
||||
TagsCommands),
|
||||
?PRINT("\n\n", []).
|
||||
print("\n\n", []).
|
||||
|
||||
print_usage_tags(Tag, MaxC, ShCode) ->
|
||||
?PRINT(["Available commands with tag ", ?B(Tag), ":", "\n"], []),
|
||||
print(["Available commands with tag ", ?B(Tag), ":", "\n"], []),
|
||||
HelpMode = long,
|
||||
TagsCommands = ejabberd_commands:get_tags_commands(),
|
||||
CommandsNames = case lists:keysearch(Tag, 1, TagsCommands) of
|
||||
@@ -615,7 +615,7 @@ print_usage_tags(Tag, MaxC, ShCode) ->
|
||||
end,
|
||||
CommandsNames),
|
||||
print_usage_commands(HelpMode, MaxC, ShCode, CommandsList),
|
||||
?PRINT("\n", []).
|
||||
print("\n", []).
|
||||
|
||||
|
||||
%%-----------------------------
|
||||
@@ -673,7 +673,7 @@ print_usage_commands2(Cmds, MaxC, ShCode) ->
|
||||
fun(Cmd, Remaining) ->
|
||||
print_usage_command(Cmd, MaxC, ShCode),
|
||||
case Remaining > 1 of
|
||||
true -> ?PRINT([" ", lists:duplicate(MaxC, 126), " \n"], []);
|
||||
true -> print([" ", lists:duplicate(MaxC, 126), " \n"], []);
|
||||
false -> ok
|
||||
end,
|
||||
{ok, Remaining-1}
|
||||
@@ -749,7 +749,7 @@ print_usage_command(Cmd, C, MaxC, ShCode) ->
|
||||
false -> [" ", ?B("Note:"), " This command cannot be executed using ejabberdctl. Try ejabberd_xmlrpc.\n\n"]
|
||||
end,
|
||||
|
||||
?PRINT(["\n", NameFmt, "\n", ArgsFmt, "\n", ReturnsFmt, "\n\n", XmlrpcFmt, TagsFmt, "\n\n", DescFmt, "\n\n", LongDescFmt, NoteEjabberdctl], []).
|
||||
print(["\n", NameFmt, "\n", ArgsFmt, "\n", ReturnsFmt, "\n\n", XmlrpcFmt, TagsFmt, "\n\n", DescFmt, "\n\n", LongDescFmt, NoteEjabberdctl], []).
|
||||
|
||||
format_usage_ctype(Type, _Indentation)
|
||||
when (Type==atom) or (Type==integer) or (Type==string) or (Type==binary) or (Type==rescode) or (Type==restuple)->
|
||||
@@ -780,6 +780,8 @@ format_usage_tuple([ElementDef | ElementsDef], Indentation) ->
|
||||
MarginString = lists:duplicate(Indentation, $\s), % Put spaces
|
||||
[ElementFmt, ",\n", MarginString, format_usage_tuple(ElementsDef, Indentation)].
|
||||
|
||||
print(Format, Args) ->
|
||||
io:format(lists:flatten(Format), Args).
|
||||
|
||||
%%-----------------------------
|
||||
%% Command managment
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 23 Aug 2006 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 8 Aug 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -152,7 +151,7 @@ run(Hook, Host, Args) ->
|
||||
%% The arguments passed to the function are: [Val | Args].
|
||||
%% The result of a call is used as Val for the next call.
|
||||
%% If a call returns 'stop', no more calls are performed and 'stopped' is returned.
|
||||
%% If a call returns {stopped, NewVal}, no more calls are performed and NewVal is returned.
|
||||
%% If a call returns {stop, NewVal}, no more calls are performed and NewVal is returned.
|
||||
run_fold(Hook, Val, Args) ->
|
||||
run_fold(Hook, global, Val, Args).
|
||||
|
||||
|
||||
+27
-17
@@ -5,7 +5,7 @@
|
||||
%%% Created : 27 Feb 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -51,7 +50,7 @@
|
||||
request_auth,
|
||||
request_keepalive,
|
||||
request_content_length,
|
||||
request_lang = "en",
|
||||
request_lang = <<"en">>,
|
||||
%% XXX bard: request handlers are configured in
|
||||
%% ejabberd.cfg under the HTTP service. For example,
|
||||
%% to have the module test_web handle requests with
|
||||
@@ -66,6 +65,7 @@
|
||||
request_tp,
|
||||
request_headers = [],
|
||||
end_of_request = false,
|
||||
options = [],
|
||||
default_host,
|
||||
trail = <<>>
|
||||
}).
|
||||
@@ -114,26 +114,30 @@ init({SockMod, Socket}, Opts) ->
|
||||
inet:setopts(Socket1, [{packet, http_bin}, {recbuf, 8192}]);
|
||||
_ -> ok
|
||||
end,
|
||||
Captcha = case lists:member(captcha, Opts) of
|
||||
Captcha = case proplists:get_bool(captcha, Opts) of
|
||||
true -> [{[<<"captcha">>], ejabberd_captcha}];
|
||||
false -> []
|
||||
end,
|
||||
Register = case lists:member(register, Opts) of
|
||||
Register = case proplists:get_bool(register, Opts) of
|
||||
true -> [{[<<"register">>], mod_register_web}];
|
||||
false -> []
|
||||
end,
|
||||
Admin = case lists:member(web_admin, Opts) of
|
||||
Admin = case proplists:get_bool(web_admin, Opts) of
|
||||
true -> [{[<<"admin">>], ejabberd_web_admin}];
|
||||
false -> []
|
||||
end,
|
||||
Bind = case lists:member(http_bind, Opts) of
|
||||
Bind = case proplists:get_bool(http_bind, Opts) of
|
||||
true -> [{[<<"http-bind">>], mod_http_bind}];
|
||||
false -> []
|
||||
end,
|
||||
Poll = case lists:member(http_poll, Opts) of
|
||||
Poll = case proplists:get_bool(http_poll, Opts) of
|
||||
true -> [{[<<"http-poll">>], ejabberd_http_poll}];
|
||||
false -> []
|
||||
end,
|
||||
XMLRPC = case proplists:get_bool(xmlrpc, Opts) of
|
||||
true -> [{[], ejabberd_xmlrpc}];
|
||||
false -> []
|
||||
end,
|
||||
DefinedHandlers = gen_mod:get_opt(
|
||||
request_handlers, Opts,
|
||||
fun(Hs) ->
|
||||
@@ -142,7 +146,7 @@ init({SockMod, Socket}, Opts) ->
|
||||
Mod} || {Path, Mod} <- Hs]
|
||||
end, []),
|
||||
RequestHandlers = DefinedHandlers ++ Captcha ++ Register ++
|
||||
Admin ++ Bind ++ Poll,
|
||||
Admin ++ Bind ++ Poll ++ XMLRPC,
|
||||
?DEBUG("S: ~p~n", [RequestHandlers]),
|
||||
|
||||
DefaultHost = gen_mod:get_opt(default_host, Opts, fun(A) -> A end, undefined),
|
||||
@@ -151,6 +155,7 @@ init({SockMod, Socket}, Opts) ->
|
||||
State = #state{sockmod = SockMod1,
|
||||
socket = Socket1,
|
||||
default_host = DefaultHost,
|
||||
options = Opts,
|
||||
request_handlers = RequestHandlers},
|
||||
receive_headers(State).
|
||||
|
||||
@@ -201,8 +206,8 @@ parse_headers(#state{request_method = Method,
|
||||
trail = Data} =
|
||||
State) ->
|
||||
PktType = case Method of
|
||||
undefined -> http;
|
||||
_ -> httph
|
||||
undefined -> http_bin;
|
||||
_ -> httph_bin
|
||||
end,
|
||||
case erlang:decode_packet(PktType, Data, []) of
|
||||
{ok, Pkt, Rest} ->
|
||||
@@ -275,7 +280,7 @@ process_header(State, Data) ->
|
||||
[]),
|
||||
throw(http_request_no_host_header);
|
||||
{ok, http_eoh} ->
|
||||
?DEBUG("(~w) http query: ~w ~s~n",
|
||||
?DEBUG("(~w) http query: ~w ~p~n",
|
||||
[State#state.socket, State#state.request_method,
|
||||
element(2, State#state.request_path)]),
|
||||
{HostProvided, Port, TP} =
|
||||
@@ -294,13 +299,16 @@ process_header(State, Data) ->
|
||||
_ -> ok
|
||||
end,
|
||||
#state{sockmod = SockMod, socket = Socket,
|
||||
options = State#state.options,
|
||||
request_handlers = State#state.request_handlers};
|
||||
_ ->
|
||||
#state{end_of_request = true,
|
||||
options = State#state.options,
|
||||
request_handlers = State#state.request_handlers}
|
||||
end;
|
||||
_ ->
|
||||
#state{end_of_request = true,
|
||||
options = State#state.options,
|
||||
request_handlers = State#state.request_handlers}
|
||||
end.
|
||||
|
||||
@@ -360,7 +368,7 @@ process(Handlers, Request) ->
|
||||
false -> process(HandlersLeft, Request)
|
||||
end.
|
||||
|
||||
process_request(#state{request_method = Method,
|
||||
process_request(#state{request_method = Method, options = Options,
|
||||
request_path = {abs_path, Path}, request_auth = Auth,
|
||||
request_lang = Lang, request_handlers = RequestHandlers,
|
||||
request_host = Host, request_port = Port,
|
||||
@@ -390,6 +398,7 @@ process_request(#state{request_method = Method,
|
||||
IP = analyze_ip_xff(IPHere, XFF, Host),
|
||||
Request = #request{method = Method,
|
||||
path = LPath,
|
||||
opts = Options,
|
||||
q = LQuery,
|
||||
auth = Auth,
|
||||
lang = Lang,
|
||||
@@ -414,7 +423,7 @@ process_request(#state{request_method = Method,
|
||||
make_text_output(State, Status, Headers, Output)
|
||||
end
|
||||
end;
|
||||
process_request(#state{request_method = Method,
|
||||
process_request(#state{request_method = Method, options = Options,
|
||||
request_path = {abs_path, Path}, request_auth = Auth,
|
||||
request_content_length = Len, request_lang = Lang,
|
||||
sockmod = SockMod, socket = Socket, request_host = Host,
|
||||
@@ -451,6 +460,7 @@ process_request(#state{request_method = Method,
|
||||
Request = #request{method = Method,
|
||||
path = LPath,
|
||||
q = LQuery,
|
||||
opts = Options,
|
||||
auth = Auth,
|
||||
data = Data,
|
||||
lang = Lang,
|
||||
|
||||
+11
-15
@@ -5,7 +5,7 @@
|
||||
%%% Created : 4 Mar 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -49,7 +48,7 @@
|
||||
-export_type([poll_socket/0]).
|
||||
|
||||
-record(state,
|
||||
{id, key, socket, output = <<"">>, input = <<"">>,
|
||||
{id, key, socket, output = [], input = <<"">>,
|
||||
waiting_input = false, last_receiver, http_poll_timeout,
|
||||
timer}).
|
||||
|
||||
@@ -253,7 +252,7 @@ handle_event({activate, From}, StateName, StateData) ->
|
||||
Input ->
|
||||
Receiver = From,
|
||||
Receiver !
|
||||
{tcp, StateData#state.socket, iolist_to_binary(Input)},
|
||||
{tcp, StateData#state.socket, Input},
|
||||
{next_state, StateName,
|
||||
StateData#state{input = <<"">>, waiting_input = false,
|
||||
last_receiver = Receiver}}
|
||||
@@ -272,11 +271,8 @@ handle_event(_Event, StateName, StateData) ->
|
||||
%%----------------------------------------------------------------------
|
||||
handle_sync_event({send, Packet}, _From, StateName,
|
||||
StateData) ->
|
||||
Packet2 = if is_binary(Packet) -> (Packet);
|
||||
true -> Packet
|
||||
end,
|
||||
Output = StateData#state.output ++
|
||||
[lists:flatten(Packet2)],
|
||||
Packet2 = iolist_to_binary(Packet),
|
||||
Output = StateData#state.output ++ [Packet2],
|
||||
Reply = ok,
|
||||
{reply, Reply, StateName,
|
||||
StateData#state{output = Output}};
|
||||
@@ -287,7 +283,7 @@ handle_sync_event({http_put, Key, NewKey, Packet},
|
||||
Allow = case StateData#state.key of
|
||||
<<"">> -> true;
|
||||
OldKey ->
|
||||
NextKey = jlib:encode_base64((crypto:sha(Key))),
|
||||
NextKey = jlib:encode_base64((p1_sha:sha1(Key))),
|
||||
if OldKey == NextKey -> true;
|
||||
true -> false
|
||||
end
|
||||
@@ -295,7 +291,7 @@ handle_sync_event({http_put, Key, NewKey, Packet},
|
||||
if Allow ->
|
||||
case StateData#state.waiting_input of
|
||||
false ->
|
||||
Input = [StateData#state.input | Packet],
|
||||
Input = <<(StateData#state.input)/binary, Packet/binary>>,
|
||||
Reply = ok,
|
||||
{reply, Reply, StateName,
|
||||
StateData#state{input = Input, key = NewKey}};
|
||||
@@ -320,7 +316,7 @@ handle_sync_event(http_get, _From, StateName,
|
||||
StateData) ->
|
||||
Reply = {ok, StateData#state.output},
|
||||
{reply, Reply, StateName,
|
||||
StateData#state{output = <<"">>}};
|
||||
StateData#state{output = []}};
|
||||
handle_sync_event(_Event, _From, StateName,
|
||||
StateData) ->
|
||||
Reply = ok, {reply, Reply, StateName, StateData}.
|
||||
|
||||
+52
-27
@@ -5,7 +5,7 @@
|
||||
%%% Created : 16 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -152,7 +151,20 @@ init_udp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
|
||||
{ok, Socket} ->
|
||||
%% Inform my parent that this port was opened succesfully
|
||||
proc_lib:init_ack({ok, self()}),
|
||||
udp_recv(Socket, Module, Opts);
|
||||
case erlang:function_exported(Module, udp_init, 2) of
|
||||
false ->
|
||||
udp_recv(Socket, Module, Opts);
|
||||
true ->
|
||||
case catch Module:udp_init(Socket, Opts) of
|
||||
{'EXIT', _} = Err ->
|
||||
?ERROR_MSG("failed to process callback function "
|
||||
"~p:~s(~p, ~p): ~p",
|
||||
[Module, udp_init, Socket, Opts, Err]),
|
||||
udp_recv(Socket, Module, Opts);
|
||||
NewOpts ->
|
||||
udp_recv(Socket, Module, NewOpts)
|
||||
end
|
||||
end;
|
||||
{error, Reason} ->
|
||||
socket_error(Reason, PortIP, Module, SockOpts, Port, IPS)
|
||||
end.
|
||||
@@ -161,8 +173,20 @@ init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
|
||||
ListenSocket = listen_tcp(PortIP, Module, SockOpts, Port, IPS),
|
||||
%% Inform my parent that this port was opened succesfully
|
||||
proc_lib:init_ack({ok, self()}),
|
||||
%% And now start accepting connection attempts
|
||||
accept(ListenSocket, Module, Opts).
|
||||
case erlang:function_exported(Module, tcp_init, 2) of
|
||||
false ->
|
||||
accept(ListenSocket, Module, Opts);
|
||||
true ->
|
||||
case catch Module:tcp_init(ListenSocket, Opts) of
|
||||
{'EXIT', _} = Err ->
|
||||
?ERROR_MSG("failed to process callback function "
|
||||
"~p:~s(~p, ~p): ~p",
|
||||
[Module, tcp_init, ListenSocket, Opts, Err]),
|
||||
accept(ListenSocket, Module, Opts);
|
||||
NewOpts ->
|
||||
accept(ListenSocket, Module, NewOpts)
|
||||
end
|
||||
end.
|
||||
|
||||
listen_tcp(PortIP, Module, SockOpts, Port, IPS) ->
|
||||
case ets:lookup(listen_sockets, PortIP) of
|
||||
@@ -177,11 +201,7 @@ listen_tcp(PortIP, Module, SockOpts, Port, IPS) ->
|
||||
catch
|
||||
_:_ -> []
|
||||
end,
|
||||
DeliverAs = case Module of
|
||||
ejabberd_xmlrpc -> list;
|
||||
_ -> binary
|
||||
end,
|
||||
Res = gen_tcp:listen(Port, [DeliverAs,
|
||||
Res = gen_tcp:listen(Port, [binary,
|
||||
{packet, 0},
|
||||
{active, false},
|
||||
{reuseaddr, true},
|
||||
@@ -285,9 +305,10 @@ accept(ListenSocket, Module, Opts) ->
|
||||
case gen_tcp:accept(ListenSocket) of
|
||||
{ok, Socket} ->
|
||||
case {inet:sockname(Socket), inet:peername(Socket)} of
|
||||
{{ok, Addr}, {ok, PAddr}} ->
|
||||
?INFO_MSG("(~w) Accepted connection ~w -> ~w",
|
||||
[Socket, PAddr, Addr]);
|
||||
{{ok, {Addr, Port}}, {ok, {PAddr, PPort}}} ->
|
||||
?INFO_MSG("(~w) Accepted connection ~s:~p -> ~s:~p",
|
||||
[Socket, inet_parse:ntoa(PAddr), PPort,
|
||||
inet_parse:ntoa(Addr), Port]);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
@@ -311,11 +332,11 @@ udp_recv(Socket, Module, Opts) ->
|
||||
?ERROR_MSG("failed to process UDP packet:~n"
|
||||
"** Source: {~p, ~p}~n"
|
||||
"** Reason: ~p~n** Packet: ~p",
|
||||
[Addr, Port, Reason, Packet]);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
udp_recv(Socket, Module, Opts);
|
||||
[Addr, Port, Reason, Packet]),
|
||||
udp_recv(Socket, Module, Opts);
|
||||
NewOpts ->
|
||||
udp_recv(Socket, Module, NewOpts)
|
||||
end;
|
||||
{error, Reason} ->
|
||||
?ERROR_MSG("unexpected UDP error: ~s", [format_error(Reason)]),
|
||||
throw({error, Reason})
|
||||
@@ -341,6 +362,7 @@ start_listener2(Port, Module, Opts) ->
|
||||
%% It is only required to start the supervisor in some cases.
|
||||
%% But it doesn't hurt to attempt to start it for any listener.
|
||||
%% So, it's normal (and harmless) that in most cases this call returns: {error, {already_started, pid()}}
|
||||
maybe_start_sip(Module),
|
||||
start_module_sup(Port, Module),
|
||||
start_listener_sup(Port, Module, Opts).
|
||||
|
||||
@@ -455,6 +477,10 @@ is_frontend(_) -> false.
|
||||
strip_frontend({frontend, Module}) -> Module;
|
||||
strip_frontend(Module) when is_atom(Module) -> Module.
|
||||
|
||||
maybe_start_sip(esip_socket) ->
|
||||
ejabberd:start_app(esip);
|
||||
maybe_start_sip(_) ->
|
||||
ok.
|
||||
|
||||
%%%
|
||||
%%% Check options
|
||||
@@ -565,7 +591,7 @@ transform_option({{Port, IP, Transport}, Mod, Opts}) ->
|
||||
try
|
||||
Mod:transform_listen_option(Opt, Acc)
|
||||
catch error:undef ->
|
||||
Acc
|
||||
[Opt|Acc]
|
||||
end
|
||||
end, [], Opts1),
|
||||
TransportOpt = if Transport == tcp -> [];
|
||||
@@ -633,10 +659,9 @@ prepare_ip(IP) when is_list(IP) ->
|
||||
prepare_ip(IP) when is_binary(IP) ->
|
||||
prepare_ip(binary_to_list(IP)).
|
||||
|
||||
prepare_mod(ejabberd_stun) ->
|
||||
prepare_mod(stun);
|
||||
prepare_mod(stun) ->
|
||||
ejabberd:start_app(p1_stun),
|
||||
stun;
|
||||
prepare_mod(ejabberd_sip) ->
|
||||
prepare_mod(sip);
|
||||
prepare_mod(sip) ->
|
||||
esip_socket;
|
||||
prepare_mod(Mod) when is_atom(Mod) ->
|
||||
Mod.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 30 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
+47
-11
@@ -6,7 +6,7 @@
|
||||
%%% @end
|
||||
%%% Created : 12 May 2013 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2013 ProcessOne
|
||||
%%% ejabberd, Copyright (C) 2013-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
|
||||
@@ -18,10 +18,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(ejabberd_logger).
|
||||
@@ -62,29 +61,66 @@ get_log_path() ->
|
||||
|
||||
-ifdef(LAGER).
|
||||
|
||||
get_integer_env(Name, Default) ->
|
||||
case application:get_env(ejabberd, Name) of
|
||||
{ok, I} when is_integer(I), I>=0 ->
|
||||
I;
|
||||
undefined ->
|
||||
Default;
|
||||
{ok, Junk} ->
|
||||
error_logger:error_msg("wrong value for ~s: ~p; "
|
||||
"using ~p as a fallback~n",
|
||||
[Name, Junk, Default]),
|
||||
Default
|
||||
end.
|
||||
get_string_env(Name, Default) ->
|
||||
case application:get_env(ejabberd, Name) of
|
||||
{ok, L} when is_list(L) ->
|
||||
L;
|
||||
undefined ->
|
||||
Default;
|
||||
{ok, Junk} ->
|
||||
error_logger:error_msg("wrong value for ~s: ~p; "
|
||||
"using ~p as a fallback~n",
|
||||
[Name, Junk, Default]),
|
||||
Default
|
||||
end.
|
||||
|
||||
start() ->
|
||||
application:load(sasl),
|
||||
application:set_env(sasl, sasl_error_logger, false),
|
||||
application:load(lager),
|
||||
ConsoleLog = get_log_path(),
|
||||
Dir = filename:dirname(ConsoleLog),
|
||||
ErrorLog = filename:join([Dir, "error.log"]),
|
||||
CrashLog = filename:join([Dir, "crash.log"]),
|
||||
LogRotateDate = get_string_env(log_rotate_date, ""),
|
||||
LogRotateSize = get_integer_env(log_rotate_size, 10*1024*1024),
|
||||
LogRotateCount = get_integer_env(log_rotate_count, 1),
|
||||
LogRateLimit = get_integer_env(log_rate_limit, 100),
|
||||
application:set_env(lager, error_logger_hwm, LogRateLimit),
|
||||
application:set_env(
|
||||
lager, handlers,
|
||||
[{lager_console_backend, info},
|
||||
{lager_file_backend, [{file, ConsoleLog}, {level, info}, {count, 1}]},
|
||||
{lager_file_backend, [{file, ErrorLog}, {level, error}, {count, 1}]}]),
|
||||
{lager_file_backend, [{file, ConsoleLog}, {level, info}, {date, LogRotateDate},
|
||||
{count, LogRotateCount}, {size, LogRotateSize}]},
|
||||
{lager_file_backend, [{file, ErrorLog}, {level, error}, {date, LogRotateDate},
|
||||
{count, LogRotateCount}, {size, LogRotateSize}]}]),
|
||||
application:set_env(lager, crash_log, CrashLog),
|
||||
application:set_env(lager, crash_log_date, LogRotateDate),
|
||||
application:set_env(lager, crash_log_size, LogRotateSize),
|
||||
application:set_env(lager, crash_log_count, LogRotateCount),
|
||||
ejabberd:start_app(lager),
|
||||
ok.
|
||||
|
||||
reopen_log() ->
|
||||
lager_crash_log ! rotate,
|
||||
lists:foreach(
|
||||
fun({lager_file_backend, File}) ->
|
||||
whereis(lager_event) ! {rotate, File};
|
||||
(_) ->
|
||||
ok
|
||||
end, gen_event:which_handlers(lager_event)),
|
||||
reopen_sasl_log().
|
||||
end, gen_event:which_handlers(lager_event)).
|
||||
|
||||
get() ->
|
||||
case lager:get_loglevel(lager_console_backend) of
|
||||
@@ -146,8 +182,6 @@ get() ->
|
||||
set(LogLevel) ->
|
||||
p1_loglevel:set(LogLevel).
|
||||
|
||||
-endif.
|
||||
|
||||
%%%===================================================================
|
||||
%%% Internal functions
|
||||
%%%===================================================================
|
||||
@@ -180,3 +214,5 @@ get_sasl_error_logger_type () ->
|
||||
{ok, Bad} -> exit ({bad_config, {sasl, {errlog_type, Bad}}});
|
||||
_ -> all
|
||||
end.
|
||||
|
||||
-endif.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 1 Nov 2006 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
+30
-22
@@ -5,7 +5,7 @@
|
||||
%%% Created : 8 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -141,9 +140,12 @@ sql_bloc(Host, F) -> sql_call(Host, {sql_bloc, F}).
|
||||
sql_call(Host, Msg) ->
|
||||
case get(?STATE_KEY) of
|
||||
undefined ->
|
||||
(?GEN_FSM):sync_send_event(ejabberd_odbc_sup:get_random_pid(Host),
|
||||
{sql_cmd, Msg, now()},
|
||||
?TRANSACTION_TIMEOUT);
|
||||
case ejabberd_odbc_sup:get_random_pid(Host) of
|
||||
none -> {error, <<"Unknown Host">>};
|
||||
Pid ->
|
||||
(?GEN_FSM):sync_send_event(Pid,{sql_cmd, Msg, now()},
|
||||
?TRANSACTION_TIMEOUT)
|
||||
end;
|
||||
_State -> nested_op(Msg)
|
||||
end.
|
||||
|
||||
@@ -202,7 +204,7 @@ decode_term(Bin) ->
|
||||
%%%----------------------------------------------------------------------
|
||||
init([Host, StartInterval]) ->
|
||||
case ejabberd_config:get_option(
|
||||
{keepalive_interval, Host},
|
||||
{odbc_keepalive_interval, Host},
|
||||
fun(I) when is_integer(I), I>0 -> I end) of
|
||||
undefined ->
|
||||
ok;
|
||||
@@ -325,7 +327,7 @@ handle_info(Info, StateName, State) ->
|
||||
terminate(_Reason, _StateName, State) ->
|
||||
ejabberd_odbc_sup:remove_pid(State#state.host, self()),
|
||||
case State#state.db_type of
|
||||
mysql -> catch mysql_conn:stop(State#state.db_ref);
|
||||
mysql -> catch p1_mysql_conn:stop(State#state.db_ref);
|
||||
_ -> ok
|
||||
end,
|
||||
ok.
|
||||
@@ -447,9 +449,9 @@ sql_query_internal(Query) ->
|
||||
mysql ->
|
||||
?DEBUG("MySQL, Send query~n~p~n", [Query]),
|
||||
%%squery to be able to specify result_type = binary
|
||||
%%[Query] because mysql_conn expect query to be a list (elements can be binaries, or iolist)
|
||||
%% but doesn't accept just a binary
|
||||
R = mysql_to_odbc(mysql_conn:squery(State#state.db_ref,
|
||||
%%[Query] because p1_mysql_conn expect query to be a list (elements can be binaries, or iolist)
|
||||
%% but doesn't accept just a binary
|
||||
R = mysql_to_odbc(p1_mysql_conn:squery(State#state.db_ref,
|
||||
[Query], self(),
|
||||
[{timeout, (?TRANSACTION_TIMEOUT) - 1000},
|
||||
{result_type, binary}])),
|
||||
@@ -484,7 +486,7 @@ abort_on_driver_error(Reply, From) ->
|
||||
%% Open an ODBC database connection
|
||||
odbc_connect(SQLServer) ->
|
||||
ejabberd:start_app(odbc),
|
||||
odbc:connect(SQLServer, [{scrollable_cursors, off}]).
|
||||
odbc:connect(binary_to_list(SQLServer), [{scrollable_cursors, off}]).
|
||||
|
||||
%% == Native PostgreSQL code
|
||||
|
||||
@@ -533,12 +535,12 @@ pgsql_item_to_odbc(_) -> {updated, undefined}.
|
||||
%% part of init/1
|
||||
%% Open a database connection to MySQL
|
||||
mysql_connect(Server, Port, DB, Username, Password) ->
|
||||
case mysql_conn:start(binary_to_list(Server), Port,
|
||||
case p1_mysql_conn:start(binary_to_list(Server), Port,
|
||||
binary_to_list(Username), binary_to_list(Password),
|
||||
binary_to_list(DB), fun log/3)
|
||||
of
|
||||
{ok, Ref} ->
|
||||
mysql_conn:fetch(Ref, [<<"set names 'utf8';">>],
|
||||
p1_mysql_conn:fetch(Ref, [<<"set names 'utf8';">>],
|
||||
self()),
|
||||
{ok, Ref};
|
||||
Err -> Err
|
||||
@@ -546,15 +548,21 @@ mysql_connect(Server, Port, DB, Username, Password) ->
|
||||
|
||||
%% Convert MySQL query result to Erlang ODBC result formalism
|
||||
mysql_to_odbc({updated, MySQLRes}) ->
|
||||
{updated, mysql:get_result_affected_rows(MySQLRes)};
|
||||
{updated, p1_mysql:get_result_affected_rows(MySQLRes)};
|
||||
mysql_to_odbc({data, MySQLRes}) ->
|
||||
mysql_item_to_odbc(mysql:get_result_field_info(MySQLRes),
|
||||
mysql:get_result_rows(MySQLRes));
|
||||
mysql_item_to_odbc(p1_mysql:get_result_field_info(MySQLRes),
|
||||
p1_mysql:get_result_rows(MySQLRes));
|
||||
mysql_to_odbc({error, MySQLRes})
|
||||
when is_binary(MySQLRes) ->
|
||||
when is_binary(MySQLRes) ->
|
||||
{error, MySQLRes};
|
||||
mysql_to_odbc({error, MySQLRes})
|
||||
when is_list(MySQLRes) ->
|
||||
{error, list_to_binary(MySQLRes)};
|
||||
mysql_to_odbc({error, MySQLRes}) ->
|
||||
{error, mysql:get_result_reason(MySQLRes)}.
|
||||
{error, p1_mysql:get_result_reason(MySQLRes)};
|
||||
mysql_to_odbc(ok) ->
|
||||
ok.
|
||||
|
||||
|
||||
%% When tabular data is returned, convert it to the ODBC formalism
|
||||
mysql_item_to_odbc(Columns, Recs) ->
|
||||
@@ -586,7 +594,7 @@ db_opts(Host) ->
|
||||
[odbc, Server];
|
||||
_ ->
|
||||
Port = ejabberd_config:get_option(
|
||||
{port, Host},
|
||||
{odbc_port, Host},
|
||||
fun(P) when is_integer(P), P > 0, P < 65536 -> P end,
|
||||
case Type of
|
||||
mysql -> ?MYSQL_PORT;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 22 Dec 2004 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -83,8 +82,10 @@ get_pids(Host) ->
|
||||
[R#sql_pool.pid || R <- Rs].
|
||||
|
||||
get_random_pid(Host) ->
|
||||
Pids = get_pids(Host),
|
||||
lists:nth(erlang:phash(now(), length(Pids)), Pids).
|
||||
case get_pids(Host) of
|
||||
[] -> none;
|
||||
Pids -> lists:nth(erlang:phash(now(), length(Pids)), Pids)
|
||||
end.
|
||||
|
||||
add_pid(Host, Pid) ->
|
||||
F = fun () ->
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
%%% @doc
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -21,10 +21,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 31 Jan 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 10 Nov 2003 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 8 Dec 2011 by Badlop
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,554 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Alexey Shchepin <alexey@process-one.net>
|
||||
%%% @doc
|
||||
%%% Interface for Riak database
|
||||
%%% @end
|
||||
%%% Created : 29 Dec 2011 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%% @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
|
||||
%%%
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(ejabberd_riak).
|
||||
|
||||
-behaviour(gen_server).
|
||||
|
||||
%% API
|
||||
-export([start_link/4, get_proc/1, make_bucket/1, put/2, put/3,
|
||||
get/2, get/3, get_by_index/4, delete/1, delete/2,
|
||||
count_by_index/3, get_by_index_range/5,
|
||||
get_keys/1, get_keys_by_index/3, is_connected/0,
|
||||
count/1, delete_by_index/3]).
|
||||
%% For debugging
|
||||
-export([get_tables/0]).
|
||||
%% map/reduce exports
|
||||
-export([map_key/3]).
|
||||
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
|
||||
-record(state, {pid = self() :: pid()}).
|
||||
|
||||
-type index() :: {binary(), any()}.
|
||||
|
||||
-type index_info() :: [{i, any()} | {'2i', [index()]}].
|
||||
|
||||
%% The `record_schema()' is just a tuple:
|
||||
%% {record_info(fields, some_record), #some_record{}}
|
||||
|
||||
-type record_schema() :: {[atom()], tuple()}.
|
||||
|
||||
%% The `index_info()' is used in put/delete functions:
|
||||
%% `i' defines a primary index, `` '2i' '' defines secondary indexes.
|
||||
%% There must be only one primary index. If `i' is not specified,
|
||||
%% the first element of the record is assumed as a primary index,
|
||||
%% i.e. `i' = element(2, Record).
|
||||
|
||||
-export_types([index_info/0]).
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
%% @private
|
||||
start_link(Num, Server, Port, _StartInterval) ->
|
||||
gen_server:start_link({local, get_proc(Num)}, ?MODULE, [Server, Port], []).
|
||||
|
||||
%% @private
|
||||
is_connected() ->
|
||||
catch riakc_pb_socket:is_connected(get_random_pid()).
|
||||
|
||||
%% @private
|
||||
get_proc(I) ->
|
||||
jlib:binary_to_atom(
|
||||
iolist_to_binary(
|
||||
[atom_to_list(?MODULE), $_, integer_to_list(I)])).
|
||||
|
||||
-spec make_bucket(atom()) -> binary().
|
||||
%% @doc Makes a bucket from a table name
|
||||
%% @private
|
||||
make_bucket(Table) ->
|
||||
erlang:atom_to_binary(Table, utf8).
|
||||
|
||||
-spec put(tuple(), record_schema()) -> ok | {error, any()}.
|
||||
%% @equiv put(Record, [])
|
||||
put(Record, RecFields) ->
|
||||
?MODULE:put(Record, RecFields, []).
|
||||
|
||||
-spec put(tuple(), record_schema(), index_info()) -> ok | {error, any()}.
|
||||
%% @doc Stores a record `Rec' with indexes described in ``IndexInfo''
|
||||
put(Rec, RecSchema, IndexInfo) ->
|
||||
Key = encode_key(proplists:get_value(i, IndexInfo, element(2, Rec))),
|
||||
SecIdxs = [encode_index_key(K, V) ||
|
||||
{K, V} <- proplists:get_value('2i', IndexInfo, [])],
|
||||
Table = element(1, Rec),
|
||||
Value = encode_record(Rec, RecSchema),
|
||||
case put_raw(Table, Key, Value, SecIdxs) of
|
||||
ok ->
|
||||
ok;
|
||||
{error, _} = Error ->
|
||||
log_error(Error, put, [{record, Rec},
|
||||
{index_info, IndexInfo}]),
|
||||
Error
|
||||
end.
|
||||
|
||||
put_raw(Table, Key, Value, Indexes) ->
|
||||
Bucket = make_bucket(Table),
|
||||
Obj = riakc_obj:new(Bucket, Key, Value, "application/x-erlang-term"),
|
||||
Obj1 = if Indexes /= [] ->
|
||||
MetaData = dict:store(<<"index">>, Indexes, dict:new()),
|
||||
riakc_obj:update_metadata(Obj, MetaData);
|
||||
true ->
|
||||
Obj
|
||||
end,
|
||||
catch riakc_pb_socket:put(get_random_pid(), Obj1).
|
||||
|
||||
get_object_raw(Table, Key) ->
|
||||
Bucket = make_bucket(Table),
|
||||
catch riakc_pb_socket:get(get_random_pid(), Bucket, Key).
|
||||
|
||||
-spec get(atom(), record_schema()) -> {ok, [any()]} | {error, any()}.
|
||||
%% @doc Returns all objects from table `Table'
|
||||
get(Table, RecSchema) ->
|
||||
Bucket = make_bucket(Table),
|
||||
case catch riakc_pb_socket:mapred(
|
||||
get_random_pid(),
|
||||
Bucket,
|
||||
[{map, {modfun, riak_kv_mapreduce, map_object_value},
|
||||
none, true}]) of
|
||||
{ok, [{_, Objs}]} ->
|
||||
{ok, lists:flatmap(
|
||||
fun(Obj) ->
|
||||
case catch decode_record(Obj, RecSchema) of
|
||||
{'EXIT', _} ->
|
||||
Error = {error, make_invalid_object(Obj)},
|
||||
log_error(Error, get,
|
||||
[{table, Table}]),
|
||||
[];
|
||||
Term ->
|
||||
[Term]
|
||||
end
|
||||
end, Objs)};
|
||||
{ok, []} ->
|
||||
{ok, []};
|
||||
{error, notfound} ->
|
||||
{ok, []};
|
||||
{error, _} = Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
-spec get(atom(), record_schema(), any()) -> {ok, any()} | {error, any()}.
|
||||
%% @doc Reads record by `Key' from table `Table'
|
||||
get(Table, RecSchema, Key) ->
|
||||
case get_raw(Table, encode_key(Key)) of
|
||||
{ok, Val} ->
|
||||
case catch decode_record(Val, RecSchema) of
|
||||
{'EXIT', _} ->
|
||||
Error = {error, make_invalid_object(Val)},
|
||||
log_error(Error, get, [{table, Table}, {key, Key}]),
|
||||
{error, notfound};
|
||||
Term ->
|
||||
{ok, Term}
|
||||
end;
|
||||
{error, _} = Error ->
|
||||
log_error(Error, get, [{table, Table},
|
||||
{key, Key}]),
|
||||
Error
|
||||
end.
|
||||
|
||||
-spec get_by_index(atom(), record_schema(), binary(), any()) ->
|
||||
{ok, [any()]} | {error, any()}.
|
||||
%% @doc Reads records by `Index' and value `Key' from `Table'
|
||||
get_by_index(Table, RecSchema, Index, Key) ->
|
||||
{NewIndex, NewKey} = encode_index_key(Index, Key),
|
||||
case get_by_index_raw(Table, NewIndex, NewKey) of
|
||||
{ok, Vals} ->
|
||||
{ok, lists:flatmap(
|
||||
fun(Val) ->
|
||||
case catch decode_record(Val, RecSchema) of
|
||||
{'EXIT', _} ->
|
||||
Error = {error, make_invalid_object(Val)},
|
||||
log_error(Error, get_by_index,
|
||||
[{table, Table},
|
||||
{index, Index},
|
||||
{key, Key}]),
|
||||
[];
|
||||
Term ->
|
||||
[Term]
|
||||
end
|
||||
end, Vals)};
|
||||
{error, notfound} ->
|
||||
{ok, []};
|
||||
{error, _} = Error ->
|
||||
log_error(Error, get_by_index,
|
||||
[{table, Table},
|
||||
{index, Index},
|
||||
{key, Key}]),
|
||||
Error
|
||||
end.
|
||||
|
||||
-spec get_by_index_range(atom(), record_schema(), binary(), any(), any()) ->
|
||||
{ok, [any()]} | {error, any()}.
|
||||
%% @doc Reads records by `Index' in the range `FromKey'..`ToKey' from `Table'
|
||||
get_by_index_range(Table, RecSchema, Index, FromKey, ToKey) ->
|
||||
{NewIndex, NewFromKey} = encode_index_key(Index, FromKey),
|
||||
{NewIndex, NewToKey} = encode_index_key(Index, ToKey),
|
||||
case get_by_index_range_raw(Table, NewIndex, NewFromKey, NewToKey) of
|
||||
{ok, Vals} ->
|
||||
{ok, lists:flatmap(
|
||||
fun(Val) ->
|
||||
case catch decode_record(Val, RecSchema) of
|
||||
{'EXIT', _} ->
|
||||
Error = {error, make_invalid_object(Val)},
|
||||
log_error(Error, get_by_index_range,
|
||||
[{table, Table},
|
||||
{index, Index},
|
||||
{start_key, FromKey},
|
||||
{end_key, ToKey}]),
|
||||
[];
|
||||
Term ->
|
||||
[Term]
|
||||
end
|
||||
end, Vals)};
|
||||
{error, notfound} ->
|
||||
{ok, []};
|
||||
{error, _} = Error ->
|
||||
log_error(Error, get_by_index_range,
|
||||
[{table, Table}, {index, Index},
|
||||
{start_key, FromKey}, {end_key, ToKey}]),
|
||||
Error
|
||||
end.
|
||||
|
||||
get_raw(Table, Key) ->
|
||||
case get_object_raw(Table, Key) of
|
||||
{ok, Obj} ->
|
||||
{ok, riakc_obj:get_value(Obj)};
|
||||
{error, _} = Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
-spec get_keys(atom()) -> {ok, [any()]} | {error, any()}.
|
||||
%% @doc Returns a list of index values
|
||||
get_keys(Table) ->
|
||||
Bucket = make_bucket(Table),
|
||||
case catch riakc_pb_socket:mapred(
|
||||
get_random_pid(),
|
||||
Bucket,
|
||||
[{map, {modfun, ?MODULE, map_key}, none, true}]) of
|
||||
{ok, [{_, Keys}]} ->
|
||||
{ok, Keys};
|
||||
{ok, []} ->
|
||||
{ok, []};
|
||||
{error, _} = Error ->
|
||||
log_error(Error, get_keys, [{table, Table}]),
|
||||
Error
|
||||
end.
|
||||
|
||||
-spec get_keys_by_index(atom(), binary(),
|
||||
any()) -> {ok, [any()]} | {error, any()}.
|
||||
%% @doc Returns a list of primary keys of objects indexed by `Key'.
|
||||
get_keys_by_index(Table, Index, Key) ->
|
||||
{NewIndex, NewKey} = encode_index_key(Index, Key),
|
||||
Bucket = make_bucket(Table),
|
||||
case catch riakc_pb_socket:mapred(
|
||||
get_random_pid(),
|
||||
{index, Bucket, NewIndex, NewKey},
|
||||
[{map, {modfun, ?MODULE, map_key}, none, true}]) of
|
||||
{ok, [{_, Keys}]} ->
|
||||
{ok, Keys};
|
||||
{ok, []} ->
|
||||
{ok, []};
|
||||
{error, _} = Error ->
|
||||
log_error(Error, get_keys_by_index, [{table, Table},
|
||||
{index, Index},
|
||||
{key, Key}]),
|
||||
Error
|
||||
end.
|
||||
|
||||
%% @hidden
|
||||
get_tables() ->
|
||||
catch riakc_pb_socket:list_buckets(get_random_pid()).
|
||||
|
||||
get_by_index_raw(Table, Index, Key) ->
|
||||
Bucket = make_bucket(Table),
|
||||
case riakc_pb_socket:mapred(
|
||||
get_random_pid(),
|
||||
{index, Bucket, Index, Key},
|
||||
[{map, {modfun, riak_kv_mapreduce, map_object_value},
|
||||
none, true}]) of
|
||||
{ok, [{_, Objs}]} ->
|
||||
{ok, Objs};
|
||||
{ok, []} ->
|
||||
{ok, []};
|
||||
{error, _} = Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
get_by_index_range_raw(Table, Index, FromKey, ToKey) ->
|
||||
Bucket = make_bucket(Table),
|
||||
case catch riakc_pb_socket:mapred(
|
||||
get_random_pid(),
|
||||
{index, Bucket, Index, FromKey, ToKey},
|
||||
[{map, {modfun, riak_kv_mapreduce, map_object_value},
|
||||
none, true}]) of
|
||||
{ok, [{_, Objs}]} ->
|
||||
{ok, Objs};
|
||||
{ok, []} ->
|
||||
{ok, []};
|
||||
{error, _} = Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
-spec count(atom()) -> {ok, non_neg_integer()} | {error, any()}.
|
||||
%% @doc Returns the number of objects in the `Table'
|
||||
count(Table) ->
|
||||
Bucket = make_bucket(Table),
|
||||
case catch riakc_pb_socket:mapred(
|
||||
get_random_pid(),
|
||||
Bucket,
|
||||
[{reduce, {modfun, riak_kv_mapreduce, reduce_count_inputs},
|
||||
none, true}]) of
|
||||
{ok, [{_, [Cnt]}]} ->
|
||||
{ok, Cnt};
|
||||
{error, _} = Error ->
|
||||
log_error(Error, count, [{table, Table}]),
|
||||
Error
|
||||
end.
|
||||
|
||||
-spec count_by_index(atom(), binary(), any()) ->
|
||||
{ok, non_neg_integer()} | {error, any()}.
|
||||
%% @doc Returns the number of objects in the `Table' by index
|
||||
count_by_index(Tab, Index, Key) ->
|
||||
{NewIndex, NewKey} = encode_index_key(Index, Key),
|
||||
case count_by_index_raw(Tab, NewIndex, NewKey) of
|
||||
{ok, Cnt} ->
|
||||
{ok, Cnt};
|
||||
{error, notfound} ->
|
||||
{ok, 0};
|
||||
{error, _} = Error ->
|
||||
log_error(Error, count_by_index,
|
||||
[{table, Tab},
|
||||
{index, Index},
|
||||
{key, Key}]),
|
||||
Error
|
||||
end.
|
||||
|
||||
count_by_index_raw(Table, Index, Key) ->
|
||||
Bucket = make_bucket(Table),
|
||||
case catch riakc_pb_socket:mapred(
|
||||
get_random_pid(),
|
||||
{index, Bucket, Index, Key},
|
||||
[{reduce, {modfun, riak_kv_mapreduce, reduce_count_inputs},
|
||||
none, true}]) of
|
||||
{ok, [{_, [Cnt]}]} ->
|
||||
{ok, Cnt};
|
||||
{error, _} = Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
-spec delete(tuple() | atom()) -> ok | {error, any()}.
|
||||
%% @doc Same as delete(T, []) when T is record.
|
||||
%% Or deletes all elements from table if T is atom.
|
||||
delete(Rec) when is_tuple(Rec) ->
|
||||
delete(Rec, []);
|
||||
delete(Table) when is_atom(Table) ->
|
||||
try
|
||||
{ok, Keys} = ?MODULE:get_keys(Table),
|
||||
lists:foreach(
|
||||
fun(K) ->
|
||||
ok = delete(Table, K)
|
||||
end, Keys)
|
||||
catch _:{badmatch, Err} ->
|
||||
Err
|
||||
end.
|
||||
|
||||
-spec delete(tuple() | atom(), index_info() | any()) -> ok | {error, any()}.
|
||||
%% @doc Delete an object
|
||||
delete(Rec, Opts) when is_tuple(Rec) ->
|
||||
Table = element(1, Rec),
|
||||
Key = proplists:get_value(i, Opts, element(2, Rec)),
|
||||
delete(Table, Key);
|
||||
delete(Table, Key) when is_atom(Table) ->
|
||||
case delete_raw(Table, encode_key(Key)) of
|
||||
ok ->
|
||||
ok;
|
||||
Err ->
|
||||
log_error(Err, delete, [{table, Table}, {key, Key}]),
|
||||
Err
|
||||
end.
|
||||
|
||||
delete_raw(Table, Key) ->
|
||||
Bucket = make_bucket(Table),
|
||||
catch riakc_pb_socket:delete(get_random_pid(), Bucket, Key).
|
||||
|
||||
-spec delete_by_index(atom(), binary(), any()) -> ok | {error, any()}.
|
||||
%% @doc Deletes objects by index
|
||||
delete_by_index(Table, Index, Key) ->
|
||||
try
|
||||
{ok, Keys} = get_keys_by_index(Table, Index, Key),
|
||||
lists:foreach(
|
||||
fun(K) ->
|
||||
ok = delete(Table, K)
|
||||
end, Keys)
|
||||
catch _:{badmatch, Err} ->
|
||||
Err
|
||||
end.
|
||||
|
||||
%%%===================================================================
|
||||
%%% map/reduce functions
|
||||
%%%===================================================================
|
||||
%% @private
|
||||
map_key(Obj, _, _) ->
|
||||
[case riak_object:key(Obj) of
|
||||
<<"b_", B/binary>> ->
|
||||
B;
|
||||
<<"i_", B/binary>> ->
|
||||
list_to_integer(binary_to_list(B));
|
||||
B ->
|
||||
erlang:binary_to_term(B)
|
||||
end].
|
||||
|
||||
%%%===================================================================
|
||||
%%% gen_server API
|
||||
%%%===================================================================
|
||||
%% @private
|
||||
init([Server, Port]) ->
|
||||
case riakc_pb_socket:start(
|
||||
Server, Port,
|
||||
[auto_reconnect]) of
|
||||
{ok, Pid} ->
|
||||
erlang:monitor(process, Pid),
|
||||
{ok, #state{pid = Pid}};
|
||||
Err ->
|
||||
{stop, Err}
|
||||
end.
|
||||
|
||||
%% @private
|
||||
handle_call(get_pid, _From, #state{pid = Pid} = State) ->
|
||||
{reply, {ok, Pid}, State};
|
||||
handle_call(_Request, _From, State) ->
|
||||
Reply = ok,
|
||||
{reply, Reply, State}.
|
||||
|
||||
%% @private
|
||||
handle_cast(_Msg, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
%% @private
|
||||
handle_info({'DOWN', _MonitorRef, _Type, _Object, _Info}, State) ->
|
||||
{stop, normal, State};
|
||||
handle_info(_Info, State) ->
|
||||
?ERROR_MSG("unexpected info: ~p", [_Info]),
|
||||
{noreply, State}.
|
||||
|
||||
%% @private
|
||||
terminate(_Reason, _State) ->
|
||||
ok.
|
||||
|
||||
%% @private
|
||||
code_change(_OldVsn, State, _Extra) ->
|
||||
{ok, State}.
|
||||
|
||||
%%%===================================================================
|
||||
%%% Internal functions
|
||||
%%%===================================================================
|
||||
encode_index_key(Idx, Key) when is_integer(Key) ->
|
||||
{<<Idx/binary, "_int">>, Key};
|
||||
encode_index_key(Idx, Key) ->
|
||||
{<<Idx/binary, "_bin">>, encode_key(Key)}.
|
||||
|
||||
encode_key(Bin) when is_binary(Bin) ->
|
||||
<<"b_", Bin/binary>>;
|
||||
encode_key(Int) when is_integer(Int) ->
|
||||
<<"i_", (list_to_binary(integer_to_list(Int)))/binary>>;
|
||||
encode_key(Term) ->
|
||||
erlang:term_to_binary(Term).
|
||||
|
||||
log_error({error, notfound}, _, _) ->
|
||||
ok;
|
||||
log_error({error, Why} = Err, Function, Opts) ->
|
||||
Txt = lists:map(
|
||||
fun({table, Table}) ->
|
||||
io_lib:fwrite("** Table: ~p~n", [Table]);
|
||||
({key, Key}) ->
|
||||
io_lib:fwrite("** Key: ~p~n", [Key]);
|
||||
({index, Index}) ->
|
||||
io_lib:fwrite("** Index = ~p~n", [Index]);
|
||||
({start_key, Key}) ->
|
||||
io_lib:fwrite("** Start Key: ~p~n", [Key]);
|
||||
({end_key, Key}) ->
|
||||
io_lib:fwrite("** End Key: ~p~n", [Key]);
|
||||
({record, Rec}) ->
|
||||
io_lib:fwrite("** Record = ~p~n", [Rec]);
|
||||
({index_info, IdxInfo}) ->
|
||||
io_lib:fwrite("** Index info = ~p~n", [IdxInfo]);
|
||||
(_) ->
|
||||
""
|
||||
end, Opts),
|
||||
ErrTxt = if is_binary(Why) ->
|
||||
io_lib:fwrite("** Error: ~s", [Why]);
|
||||
true ->
|
||||
io_lib:fwrite("** Error: ~p", [Err])
|
||||
end,
|
||||
?ERROR_MSG("database error:~n** Function: ~p~n~s~s",
|
||||
[Function, Txt, ErrTxt]);
|
||||
log_error(_, _, _) ->
|
||||
ok.
|
||||
|
||||
make_invalid_object(Val) ->
|
||||
list_to_binary(io_lib:fwrite("Invalid object: ~p", [Val])).
|
||||
|
||||
get_random_pid() ->
|
||||
PoolPid = ejabberd_riak_sup:get_random_pid(),
|
||||
case catch gen_server:call(PoolPid, get_pid) of
|
||||
{ok, Pid} ->
|
||||
Pid;
|
||||
{'EXIT', {timeout, _}} ->
|
||||
throw({error, timeout});
|
||||
{'EXIT', Err} ->
|
||||
throw({error, Err})
|
||||
end.
|
||||
|
||||
encode_record(Rec, {Fields, DefRec}) ->
|
||||
term_to_binary(encode_record(Rec, Fields, DefRec, 2)).
|
||||
|
||||
encode_record(Rec, [FieldName|Fields], DefRec, Pos) ->
|
||||
Value = element(Pos, Rec),
|
||||
DefValue = element(Pos, DefRec),
|
||||
if Value == DefValue ->
|
||||
encode_record(Rec, Fields, DefRec, Pos+1);
|
||||
true ->
|
||||
[{FieldName, Value}|encode_record(Rec, Fields, DefRec, Pos+1)]
|
||||
end;
|
||||
encode_record(_, [], _, _) ->
|
||||
[].
|
||||
|
||||
decode_record(Bin, {Fields, DefRec}) ->
|
||||
decode_record(binary_to_term(Bin), Fields, DefRec, 2).
|
||||
|
||||
decode_record(KeyVals, [FieldName|Fields], Rec, Pos) ->
|
||||
case lists:keyfind(FieldName, 1, KeyVals) of
|
||||
{_, Value} ->
|
||||
NewRec = setelement(Pos, Rec, Value),
|
||||
decode_record(KeyVals, Fields, NewRec, Pos+1);
|
||||
false ->
|
||||
decode_record(KeyVals, Fields, Rec, Pos+1)
|
||||
end;
|
||||
decode_record(_, [], Rec, _) ->
|
||||
Rec.
|
||||
@@ -0,0 +1,161 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% File : ejabberd_riak_sup.erl
|
||||
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
||||
%%% Purpose : Riak connections supervisor
|
||||
%%% Created : 29 Dec 2011 by Alexey Shchepin <alexey@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
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
-module(ejabberd_riak_sup).
|
||||
-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
|
||||
]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
|
||||
-define(DEFAULT_POOL_SIZE, 10).
|
||||
-define(DEFAULT_RIAK_START_INTERVAL, 30). % 30 seconds
|
||||
-define(DEFAULT_RIAK_HOST, "127.0.0.1").
|
||||
-define(DEFAULT_RIAK_PORT, 8087).
|
||||
|
||||
% time to wait for the supervisor to start its child before returning
|
||||
% a timeout error to the request
|
||||
-define(CONNECT_TIMEOUT, 500). % milliseconds
|
||||
|
||||
start() ->
|
||||
case lists:any(
|
||||
fun(Host) ->
|
||||
is_riak_configured(Host)
|
||||
end, ?MYHOSTS) of
|
||||
true ->
|
||||
ejabberd:start_app(riakc),
|
||||
do_start();
|
||||
false ->
|
||||
ok
|
||||
end.
|
||||
|
||||
is_riak_configured(Host) ->
|
||||
ServerConfigured = ejabberd_config:get_option(
|
||||
{riak_server, Host},
|
||||
fun(_) -> true end, false),
|
||||
PortConfigured = ejabberd_config:get_option(
|
||||
{riak_port, Host},
|
||||
fun(_) -> true end, false),
|
||||
AuthConfigured = lists:member(
|
||||
ejabberd_auth_riak,
|
||||
ejabberd_auth:auth_modules(Host)),
|
||||
Modules = ejabberd_config:get_option(
|
||||
{modules, Host},
|
||||
fun(L) when is_list(L) -> L end, []),
|
||||
ModuleWithRiakDBConfigured = lists:any(
|
||||
fun({_Module, Opts}) ->
|
||||
gen_mod:db_type(Opts) == riak
|
||||
end, Modules),
|
||||
ServerConfigured or PortConfigured
|
||||
or AuthConfigured or ModuleWithRiakDBConfigured.
|
||||
|
||||
do_start() ->
|
||||
SupervisorName = ?MODULE,
|
||||
ChildSpec =
|
||||
{SupervisorName,
|
||||
{?MODULE, start_link, []},
|
||||
transient,
|
||||
infinity,
|
||||
supervisor,
|
||||
[?MODULE]},
|
||||
case supervisor:start_child(ejabberd_sup, ChildSpec) of
|
||||
{ok, _PID} ->
|
||||
ok;
|
||||
_Error ->
|
||||
?ERROR_MSG("Start of supervisor ~p failed:~n~p~nRetrying...~n",
|
||||
[SupervisorName, _Error]),
|
||||
timer:sleep(5000),
|
||||
start()
|
||||
end.
|
||||
|
||||
start_link() ->
|
||||
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
||||
|
||||
init([]) ->
|
||||
PoolSize = get_pool_size(),
|
||||
StartInterval = get_start_interval(),
|
||||
Server = get_riak_server(),
|
||||
Port = get_riak_port(),
|
||||
{ok, {{one_for_one, PoolSize*10, 1},
|
||||
lists:map(
|
||||
fun(I) ->
|
||||
{ejabberd_riak:get_proc(I),
|
||||
{ejabberd_riak, start_link,
|
||||
[I, Server, Port, StartInterval*1000]},
|
||||
transient, 2000, worker, [?MODULE]}
|
||||
end, lists:seq(1, PoolSize))}}.
|
||||
|
||||
get_start_interval() ->
|
||||
ejabberd_config:get_option(
|
||||
riak_start_interval,
|
||||
fun(N) when is_integer(N), N >= 1 -> N end,
|
||||
?DEFAULT_RIAK_START_INTERVAL).
|
||||
|
||||
get_pool_size() ->
|
||||
ejabberd_config:get_option(
|
||||
riak_pool_size,
|
||||
fun(N) when is_integer(N), N >= 1 -> N end,
|
||||
?DEFAULT_POOL_SIZE).
|
||||
|
||||
get_riak_server() ->
|
||||
ejabberd_config:get_option(
|
||||
riak_server,
|
||||
fun(S) ->
|
||||
binary_to_list(iolist_to_binary(S))
|
||||
end, ?DEFAULT_RIAK_HOST).
|
||||
|
||||
get_riak_port() ->
|
||||
ejabberd_config:get_option(
|
||||
riak_port,
|
||||
fun(P) when is_integer(P), P > 0, P < 65536 -> P end,
|
||||
?DEFAULT_RIAK_PORT).
|
||||
|
||||
get_pids() ->
|
||||
[ejabberd_riak:get_proc(I) || I <- lists:seq(1, get_pool_size())].
|
||||
|
||||
get_random_pid() ->
|
||||
get_random_pid(now()).
|
||||
|
||||
get_random_pid(Term) ->
|
||||
I = erlang:phash2(Term, get_pool_size()) + 1,
|
||||
ejabberd_riak:get_proc(I).
|
||||
|
||||
transform_options(Opts) ->
|
||||
lists:foldl(fun transform_options/2, [], Opts).
|
||||
|
||||
transform_options({riak_server, {S, P}}, Opts) ->
|
||||
[{riak_server, S}, {riak_port, P}|Opts];
|
||||
transform_options(Opt, Opts) ->
|
||||
[Opt|Opts].
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 27 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -397,6 +396,7 @@ update_tables() ->
|
||||
[domain, node, pid] -> mnesia:delete_table(route);
|
||||
[domain, pid] -> mnesia:delete_table(route);
|
||||
[domain, pid, local_hint] -> ok;
|
||||
[domain, pid, local_hint|_] -> mnesia:delete_table(route);
|
||||
{'EXIT', _} -> ok
|
||||
end,
|
||||
case lists:member(local_route,
|
||||
|
||||
+157
-6
@@ -5,7 +5,7 @@
|
||||
%%% Created : 7 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -38,7 +37,8 @@
|
||||
incoming_s2s_number/0, outgoing_s2s_number/0,
|
||||
clean_temporarily_blocked_table/0,
|
||||
list_temporarily_blocked_hosts/0,
|
||||
external_host_overloaded/1, is_temporarly_blocked/1]).
|
||||
external_host_overloaded/1, is_temporarly_blocked/1,
|
||||
check_peer_certificate/3]).
|
||||
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2,
|
||||
@@ -54,6 +54,14 @@
|
||||
|
||||
-include("ejabberd_commands.hrl").
|
||||
|
||||
-include_lib("public_key/include/public_key.hrl").
|
||||
|
||||
-define(PKIXEXPLICIT, 'OTP-PUB-KEY').
|
||||
|
||||
-define(PKIXIMPLICIT, 'OTP-PUB-KEY').
|
||||
|
||||
-include("XmppAddr.hrl").
|
||||
|
||||
-define(DEFAULT_MAX_S2S_CONNECTIONS_NUMBER, 1).
|
||||
|
||||
-define(DEFAULT_MAX_S2S_CONNECTIONS_NUMBER_PER_NODE, 1).
|
||||
@@ -208,6 +216,31 @@ try_register(FromTo) ->
|
||||
dirty_get_connections() ->
|
||||
mnesia:dirty_all_keys(s2s).
|
||||
|
||||
check_peer_certificate(SockMod, Sock, Peer) ->
|
||||
case SockMod:get_peer_certificate(Sock) of
|
||||
{ok, Cert} ->
|
||||
case SockMod:get_verify_result(Sock) of
|
||||
0 ->
|
||||
case idna:domain_utf8_to_ascii(Peer) of
|
||||
false ->
|
||||
{error, <<"Cannot decode remote server name">>};
|
||||
AsciiPeer ->
|
||||
case
|
||||
lists:any(fun(D) -> match_domain(AsciiPeer, D) end,
|
||||
get_cert_domains(Cert)) of
|
||||
true ->
|
||||
{ok, <<"Verification successful">>};
|
||||
false ->
|
||||
{error, <<"Certificate host name mismatch">>}
|
||||
end
|
||||
end;
|
||||
VerifyRes ->
|
||||
{error, p1_tls:get_cert_verify_string(VerifyRes, Cert)}
|
||||
end;
|
||||
error ->
|
||||
{error, <<"Cannot get peer certificate">>}
|
||||
end.
|
||||
|
||||
%%====================================================================
|
||||
%% gen_server callbacks
|
||||
%%====================================================================
|
||||
@@ -620,3 +653,121 @@ get_s2s_state(S2sPid) ->
|
||||
{badrpc, _} -> [{status, error}]
|
||||
end,
|
||||
[{s2s_pid, S2sPid} | Infos].
|
||||
|
||||
get_cert_domains(Cert) ->
|
||||
{rdnSequence, Subject} =
|
||||
(Cert#'Certificate'.tbsCertificate)#'TBSCertificate'.subject,
|
||||
Extensions =
|
||||
(Cert#'Certificate'.tbsCertificate)#'TBSCertificate'.extensions,
|
||||
lists:flatmap(fun (#'AttributeTypeAndValue'{type =
|
||||
?'id-at-commonName',
|
||||
value = Val}) ->
|
||||
case 'OTP-PUB-KEY':decode('X520CommonName', Val) of
|
||||
{ok, {_, D1}} ->
|
||||
D = if is_binary(D1) -> D1;
|
||||
is_list(D1) -> list_to_binary(D1);
|
||||
true -> error
|
||||
end,
|
||||
if D /= error ->
|
||||
case jlib:string_to_jid(D) of
|
||||
#jid{luser = <<"">>, lserver = LD,
|
||||
lresource = <<"">>} ->
|
||||
[LD];
|
||||
_ -> []
|
||||
end;
|
||||
true -> []
|
||||
end;
|
||||
_ -> []
|
||||
end;
|
||||
(_) -> []
|
||||
end,
|
||||
lists:flatten(Subject))
|
||||
++
|
||||
lists:flatmap(fun (#'Extension'{extnID =
|
||||
?'id-ce-subjectAltName',
|
||||
extnValue = Val}) ->
|
||||
BVal = if is_list(Val) -> list_to_binary(Val);
|
||||
true -> Val
|
||||
end,
|
||||
case 'OTP-PUB-KEY':decode('SubjectAltName', BVal)
|
||||
of
|
||||
{ok, SANs} ->
|
||||
lists:flatmap(fun ({otherName,
|
||||
#'AnotherName'{'type-id' =
|
||||
?'id-on-xmppAddr',
|
||||
value =
|
||||
XmppAddr}}) ->
|
||||
case
|
||||
'XmppAddr':decode('XmppAddr',
|
||||
XmppAddr)
|
||||
of
|
||||
{ok, D}
|
||||
when
|
||||
is_binary(D) ->
|
||||
case
|
||||
jlib:string_to_jid((D))
|
||||
of
|
||||
#jid{luser =
|
||||
<<"">>,
|
||||
lserver =
|
||||
LD,
|
||||
lresource =
|
||||
<<"">>} ->
|
||||
case
|
||||
idna:domain_utf8_to_ascii(LD)
|
||||
of
|
||||
false ->
|
||||
[];
|
||||
PCLD ->
|
||||
[PCLD]
|
||||
end;
|
||||
_ -> []
|
||||
end;
|
||||
_ -> []
|
||||
end;
|
||||
({dNSName, D})
|
||||
when is_list(D) ->
|
||||
case
|
||||
jlib:string_to_jid(list_to_binary(D))
|
||||
of
|
||||
#jid{luser = <<"">>,
|
||||
lserver = LD,
|
||||
lresource =
|
||||
<<"">>} ->
|
||||
[LD];
|
||||
_ -> []
|
||||
end;
|
||||
(_) -> []
|
||||
end,
|
||||
SANs);
|
||||
_ -> []
|
||||
end;
|
||||
(_) -> []
|
||||
end,
|
||||
Extensions).
|
||||
|
||||
match_domain(Domain, Domain) -> true;
|
||||
match_domain(Domain, Pattern) ->
|
||||
DLabels = str:tokens(Domain, <<".">>),
|
||||
PLabels = str:tokens(Pattern, <<".">>),
|
||||
match_labels(DLabels, PLabels).
|
||||
|
||||
match_labels([], []) -> true;
|
||||
match_labels([], [_ | _]) -> false;
|
||||
match_labels([_ | _], []) -> false;
|
||||
match_labels([DL | DLabels], [PL | PLabels]) ->
|
||||
case lists:all(fun (C) ->
|
||||
$a =< C andalso C =< $z orelse
|
||||
$0 =< C andalso C =< $9 orelse
|
||||
C == $- orelse C == $*
|
||||
end,
|
||||
binary_to_list(PL))
|
||||
of
|
||||
true ->
|
||||
Regexp = ejabberd_regexp:sh_to_awk(PL),
|
||||
case ejabberd_regexp:run(DL, Regexp) of
|
||||
match -> match_labels(DLabels, PLabels);
|
||||
nomatch -> false
|
||||
end;
|
||||
false -> false
|
||||
end.
|
||||
|
||||
+78
-218
@@ -5,7 +5,7 @@
|
||||
%%% Created : 6 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -31,8 +30,7 @@
|
||||
-behaviour(p1_fsm).
|
||||
|
||||
%% External exports
|
||||
-export([start/2, start_link/2, match_domain/2,
|
||||
socket_type/0]).
|
||||
-export([start/2, start_link/2, socket_type/0]).
|
||||
|
||||
%% gen_fsm callbacks
|
||||
-export([init/1, wait_for_stream/2,
|
||||
@@ -45,14 +43,6 @@
|
||||
|
||||
-include("jlib.hrl").
|
||||
|
||||
-include_lib("public_key/include/public_key.hrl").
|
||||
|
||||
-define(PKIXEXPLICIT, 'OTP-PUB-KEY').
|
||||
|
||||
-define(PKIXIMPLICIT, 'OTP-PUB-KEY').
|
||||
|
||||
-include("XmppAddr.hrl").
|
||||
|
||||
-define(DICT, dict).
|
||||
|
||||
-record(state,
|
||||
@@ -88,7 +78,7 @@
|
||||
|
||||
-define(SUPERVISOR_START,
|
||||
p1_fsm:start(ejabberd_s2s_in, [SockData, Opts],
|
||||
?FSMOPTS ++ fsm_limit_opts(Opts)).
|
||||
?FSMOPTS ++ fsm_limit_opts(Opts))).
|
||||
|
||||
-else.
|
||||
|
||||
@@ -177,9 +167,26 @@ init([{SockMod, Socket}, Opts]) ->
|
||||
undefined -> [];
|
||||
CertFile -> [{certfile, CertFile}]
|
||||
end,
|
||||
TLSOpts2 = case ejabberd_config:get_option(
|
||||
s2s_ciphers, fun iolist_to_binary/1) of
|
||||
undefined -> TLSOpts1;
|
||||
Ciphers -> [{ciphers, Ciphers} | TLSOpts1]
|
||||
end,
|
||||
TLSOpts3 = case ejabberd_config:get_option(
|
||||
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) of
|
||||
undefined -> TLSOpts2;
|
||||
ProtocolOpts -> [{protocol_options, ProtocolOpts} | TLSOpts2]
|
||||
end,
|
||||
TLSOpts = case proplists:get_bool(tls_compression, Opts) of
|
||||
false -> [compression_none | TLSOpts1];
|
||||
true -> TLSOpts1
|
||||
false -> [compression_none | TLSOpts3];
|
||||
true -> TLSOpts3
|
||||
end,
|
||||
Timer = erlang:start_timer(?S2STIMEOUT, self(), []),
|
||||
{ok, wait_for_stream,
|
||||
@@ -208,34 +215,21 @@ wait_for_stream({xmlstreamstart, _Name, Attrs},
|
||||
not StateData#state.authenticated ->
|
||||
send_text(StateData,
|
||||
?STREAM_HEADER(<<" version='1.0'">>)),
|
||||
SASL = if StateData#state.tls_enabled ->
|
||||
case
|
||||
(StateData#state.sockmod):get_peer_certificate(StateData#state.socket)
|
||||
of
|
||||
{ok, Cert} ->
|
||||
case
|
||||
(StateData#state.sockmod):get_verify_result(StateData#state.socket)
|
||||
of
|
||||
0 ->
|
||||
[#xmlel{name = <<"mechanisms">>,
|
||||
attrs = [{<<"xmlns">>, ?NS_SASL}],
|
||||
children =
|
||||
[#xmlel{name = <<"mechanism">>,
|
||||
attrs = [],
|
||||
children =
|
||||
[{xmlcdata,
|
||||
<<"EXTERNAL">>}]}]}];
|
||||
CertVerifyRes ->
|
||||
case StateData#state.tls_certverify of
|
||||
true ->
|
||||
{error_cert_verif, CertVerifyRes,
|
||||
Cert};
|
||||
false -> []
|
||||
end
|
||||
end;
|
||||
error -> []
|
||||
Auth = if StateData#state.tls_enabled ->
|
||||
case jlib:nameprep(xml:get_attr_s(<<"from">>, Attrs)) of
|
||||
From when From /= <<"">>, From /= error ->
|
||||
{Result, Message} =
|
||||
ejabberd_s2s:check_peer_certificate(StateData#state.sockmod,
|
||||
StateData#state.socket,
|
||||
From),
|
||||
{Result, From, Message};
|
||||
_ ->
|
||||
{error, <<"(unknown)">>,
|
||||
<<"Got no valid 'from' attribute">>}
|
||||
end;
|
||||
true -> []
|
||||
true ->
|
||||
{no_verify, <<"(unknown)">>,
|
||||
<<"TLS not (yet) enabled">>}
|
||||
end,
|
||||
StartTLS = if StateData#state.tls_enabled -> [];
|
||||
not StateData#state.tls_enabled and
|
||||
@@ -251,26 +245,36 @@ wait_for_stream({xmlstreamstart, _Name, Attrs},
|
||||
[#xmlel{name = <<"required">>,
|
||||
attrs = [], children = []}]}]
|
||||
end,
|
||||
case SASL of
|
||||
{error_cert_verif, CertVerifyResult, Certificate} ->
|
||||
CertError = p1_tls:get_cert_verify_string(CertVerifyResult,
|
||||
Certificate),
|
||||
RemoteServer = xml:get_attr_s(<<"from">>, Attrs),
|
||||
case Auth of
|
||||
{error, RemoteServer, CertError}
|
||||
when StateData#state.tls_certverify ->
|
||||
?INFO_MSG("Closing s2s connection: ~s <--> ~s (~s)",
|
||||
[StateData#state.server, RemoteServer, CertError]),
|
||||
send_text(StateData,
|
||||
xml:element_to_binary(?SERRT_POLICY_VIOLATION(<<"en">>,
|
||||
CertError))),
|
||||
{atomic, Pid} =
|
||||
ejabberd_s2s:find_connection(jlib:make_jid(<<"">>,
|
||||
Server, <<"">>),
|
||||
jlib:make_jid(<<"">>,
|
||||
RemoteServer,
|
||||
<<"">>)),
|
||||
ejabberd_s2s_out:stop_connection(Pid),
|
||||
<<(xml:element_to_binary(?SERRT_POLICY_VIOLATION(<<"en">>,
|
||||
CertError)))/binary,
|
||||
(?STREAM_TRAILER)/binary>>),
|
||||
{stop, normal, StateData};
|
||||
_ ->
|
||||
send_element(StateData,
|
||||
{VerifyResult, RemoteServer, Msg} ->
|
||||
{SASL, NewStateData} = case VerifyResult of
|
||||
ok ->
|
||||
{[#xmlel{name = <<"mechanisms">>,
|
||||
attrs = [{<<"xmlns">>, ?NS_SASL}],
|
||||
children =
|
||||
[#xmlel{name = <<"mechanism">>,
|
||||
attrs = [],
|
||||
children =
|
||||
[{xmlcdata,
|
||||
<<"EXTERNAL">>}]}]}],
|
||||
StateData#state{auth_domain = RemoteServer}};
|
||||
error ->
|
||||
?DEBUG("Won't accept certificate of ~s: ~s",
|
||||
[RemoteServer, Msg]),
|
||||
{[], StateData};
|
||||
no_verify ->
|
||||
{[], StateData}
|
||||
end,
|
||||
send_element(NewStateData,
|
||||
#xmlel{name = <<"stream:features">>, attrs = [],
|
||||
children =
|
||||
SASL ++
|
||||
@@ -279,7 +283,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs},
|
||||
Server, [],
|
||||
[Server])}),
|
||||
{next_state, wait_for_feature_request,
|
||||
StateData#state{server = Server}}
|
||||
NewStateData#state{server = Server}}
|
||||
end;
|
||||
{<<"jabber:server">>, _, Server, true}
|
||||
when StateData#state.authenticated ->
|
||||
@@ -293,7 +297,9 @@ wait_for_stream({xmlstreamstart, _Name, Attrs},
|
||||
[Server])}),
|
||||
{next_state, stream_established, StateData};
|
||||
{<<"jabber:server">>, <<"jabber:server:dialback">>,
|
||||
_Server, _} ->
|
||||
_Server, _} when
|
||||
(StateData#state.tls_required and StateData#state.tls_enabled)
|
||||
or (not StateData#state.tls_required) ->
|
||||
send_text(StateData, ?STREAM_HEADER(<<"">>)),
|
||||
{next_state, stream_established, StateData};
|
||||
_ ->
|
||||
@@ -312,7 +318,7 @@ wait_for_stream(closed, StateData) ->
|
||||
|
||||
wait_for_feature_request({xmlstreamelement, El},
|
||||
StateData) ->
|
||||
#xmlel{name = Name, attrs = Attrs, children = Els} = El,
|
||||
#xmlel{name = Name, attrs = Attrs} = El,
|
||||
TLS = StateData#state.tls,
|
||||
TLSEnabled = StateData#state.tls_enabled,
|
||||
SockMod =
|
||||
@@ -358,52 +364,23 @@ wait_for_feature_request({xmlstreamelement, El},
|
||||
{?NS_SASL, <<"auth">>} when TLSEnabled ->
|
||||
Mech = xml:get_attr_s(<<"mechanism">>, Attrs),
|
||||
case Mech of
|
||||
<<"EXTERNAL">> ->
|
||||
Auth = jlib:decode_base64(xml:get_cdata(Els)),
|
||||
AuthDomain = jlib:nameprep(Auth),
|
||||
AuthRes = case
|
||||
(StateData#state.sockmod):get_peer_certificate(StateData#state.socket)
|
||||
of
|
||||
{ok, Cert} ->
|
||||
case
|
||||
(StateData#state.sockmod):get_verify_result(StateData#state.socket)
|
||||
of
|
||||
0 ->
|
||||
case AuthDomain of
|
||||
error -> false;
|
||||
_ ->
|
||||
case
|
||||
idna:domain_utf8_to_ascii(AuthDomain)
|
||||
of
|
||||
false -> false;
|
||||
PCAuthDomain ->
|
||||
lists:any(fun (D) ->
|
||||
match_domain(PCAuthDomain,
|
||||
D)
|
||||
end,
|
||||
get_cert_domains(Cert))
|
||||
end
|
||||
end;
|
||||
_ -> false
|
||||
end;
|
||||
error -> false
|
||||
end,
|
||||
<<"EXTERNAL">> when StateData#state.auth_domain /= <<"">> ->
|
||||
AuthDomain = StateData#state.auth_domain,
|
||||
AllowRemoteHost = ejabberd_s2s:allow_host(<<"">>,
|
||||
AuthDomain),
|
||||
if AuthRes andalso AllowRemoteHost ->
|
||||
if AllowRemoteHost ->
|
||||
(StateData#state.sockmod):reset_stream(StateData#state.socket),
|
||||
send_element(StateData,
|
||||
#xmlel{name = <<"success">>,
|
||||
attrs = [{<<"xmlns">>, ?NS_SASL}],
|
||||
children = []}),
|
||||
?DEBUG("(~w) Accepted s2s authentication for ~s",
|
||||
[StateData#state.socket, AuthDomain]),
|
||||
?INFO_MSG("Accepted s2s EXTERNAL authentication for ~s (TLS=~p)",
|
||||
[AuthDomain, StateData#state.tls_enabled]),
|
||||
change_shaper(StateData, <<"">>,
|
||||
jlib:make_jid(<<"">>, AuthDomain, <<"">>)),
|
||||
{next_state, wait_for_stream,
|
||||
StateData#state{streamid = new_id(),
|
||||
authenticated = true,
|
||||
auth_domain = AuthDomain}};
|
||||
authenticated = true}};
|
||||
true ->
|
||||
send_element(StateData,
|
||||
#xmlel{name = <<"failure">>,
|
||||
@@ -538,6 +515,8 @@ stream_established({valid, From, To}, StateData) ->
|
||||
[{<<"from">>, To}, {<<"to">>, From},
|
||||
{<<"type">>, <<"valid">>}],
|
||||
children = []}),
|
||||
?INFO_MSG("Accepted s2s dialback authentication for ~s (TLS=~p)",
|
||||
[From, StateData#state.tls_enabled]),
|
||||
LFrom = jlib:nameprep(From),
|
||||
LTo = jlib:nameprep(To),
|
||||
NSD = StateData#state{connections =
|
||||
@@ -720,125 +699,6 @@ is_key_packet(#xmlel{name = Name, attrs = Attrs,
|
||||
xml:get_attr_s(<<"id">>, Attrs), xml:get_cdata(Els)};
|
||||
is_key_packet(_) -> false.
|
||||
|
||||
get_cert_domains(Cert) ->
|
||||
{rdnSequence, Subject} =
|
||||
(Cert#'Certificate'.tbsCertificate)#'TBSCertificate'.subject,
|
||||
Extensions =
|
||||
(Cert#'Certificate'.tbsCertificate)#'TBSCertificate'.extensions,
|
||||
lists:flatmap(fun (#'AttributeTypeAndValue'{type =
|
||||
?'id-at-commonName',
|
||||
value = Val}) ->
|
||||
case 'OTP-PUB-KEY':decode('X520CommonName', Val) of
|
||||
{ok, {_, D1}} ->
|
||||
D = if is_binary(D1) -> D1;
|
||||
is_binary(D1) -> (D1);
|
||||
true -> error
|
||||
end,
|
||||
if D /= error ->
|
||||
case jlib:string_to_jid(D) of
|
||||
#jid{luser = <<"">>, lserver = LD,
|
||||
lresource = <<"">>} ->
|
||||
[LD];
|
||||
_ -> []
|
||||
end;
|
||||
true -> []
|
||||
end;
|
||||
_ -> []
|
||||
end;
|
||||
(_) -> []
|
||||
end,
|
||||
lists:flatten(Subject))
|
||||
++
|
||||
lists:flatmap(fun (#'Extension'{extnID =
|
||||
?'id-ce-subjectAltName',
|
||||
extnValue = Val}) ->
|
||||
BVal = if is_binary(Val) -> iolist_to_binary(Val);
|
||||
is_binary(Val) -> Val;
|
||||
true -> Val
|
||||
end,
|
||||
case 'OTP-PUB-KEY':decode('SubjectAltName', BVal)
|
||||
of
|
||||
{ok, SANs} ->
|
||||
lists:flatmap(fun ({otherName,
|
||||
#'AnotherName'{'type-id' =
|
||||
?'id-on-xmppAddr',
|
||||
value =
|
||||
XmppAddr}}) ->
|
||||
case
|
||||
'XmppAddr':decode('XmppAddr',
|
||||
XmppAddr)
|
||||
of
|
||||
{ok, D}
|
||||
when
|
||||
is_binary(D) ->
|
||||
case
|
||||
jlib:string_to_jid((D))
|
||||
of
|
||||
#jid{luser =
|
||||
<<"">>,
|
||||
lserver =
|
||||
LD,
|
||||
lresource =
|
||||
<<"">>} ->
|
||||
case
|
||||
idna:domain_utf8_to_ascii(LD)
|
||||
of
|
||||
false ->
|
||||
[];
|
||||
PCLD ->
|
||||
[PCLD]
|
||||
end;
|
||||
_ -> []
|
||||
end;
|
||||
_ -> []
|
||||
end;
|
||||
({dNSName, D})
|
||||
when is_binary(D) ->
|
||||
case
|
||||
jlib:string_to_jid(D)
|
||||
of
|
||||
#jid{luser = <<"">>,
|
||||
lserver = LD,
|
||||
lresource =
|
||||
<<"">>} ->
|
||||
[LD];
|
||||
_ -> []
|
||||
end;
|
||||
(_) -> []
|
||||
end,
|
||||
SANs);
|
||||
_ -> []
|
||||
end;
|
||||
(_) -> []
|
||||
end,
|
||||
Extensions).
|
||||
|
||||
match_domain(Domain, Domain) -> true;
|
||||
match_domain(Domain, Pattern) ->
|
||||
DLabels = str:tokens(Domain, <<".">>),
|
||||
PLabels = str:tokens(Pattern, <<".">>),
|
||||
match_labels(DLabels, PLabels).
|
||||
|
||||
match_labels([], []) -> true;
|
||||
match_labels([], [_ | _]) -> false;
|
||||
match_labels([_ | _], []) -> false;
|
||||
match_labels([DL | DLabels], [PL | PLabels]) ->
|
||||
case lists:all(fun (C) ->
|
||||
$a =< C andalso C =< $z orelse
|
||||
$0 =< C andalso C =< $9 orelse
|
||||
C == $- orelse C == $*
|
||||
end,
|
||||
binary_to_list(PL))
|
||||
of
|
||||
true ->
|
||||
Regexp = ejabberd_regexp:sh_to_awk(PL),
|
||||
case ejabberd_regexp:run(DL, Regexp) of
|
||||
match -> match_labels(DLabels, PLabels);
|
||||
nomatch -> false
|
||||
end;
|
||||
false -> false
|
||||
end.
|
||||
|
||||
fsm_limit_opts(Opts) ->
|
||||
case lists:keysearch(max_fsm_queue, 1, Opts) of
|
||||
{value, {_, N}} when is_integer(N) -> [{max_queue, N}];
|
||||
|
||||
+89
-47
@@ -5,7 +5,7 @@
|
||||
%%% Created : 6 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -70,6 +69,7 @@
|
||||
use_v10 = true :: boolean(),
|
||||
tls = false :: boolean(),
|
||||
tls_required = false :: boolean(),
|
||||
tls_certverify = false :: boolean(),
|
||||
tls_enabled = false :: boolean(),
|
||||
tls_options = [connect] :: list(),
|
||||
authenticated = false :: boolean(),
|
||||
@@ -161,28 +161,27 @@ stop_connection(Pid) -> p1_fsm:send_event(Pid, closed).
|
||||
init([From, Server, Type]) ->
|
||||
process_flag(trap_exit, true),
|
||||
?DEBUG("started: ~p", [{From, Server, Type}]),
|
||||
{TLS, TLSRequired} = case
|
||||
ejabberd_config:get_option(
|
||||
s2s_use_starttls,
|
||||
fun(true) -> true;
|
||||
(false) -> false;
|
||||
(optional) -> optional;
|
||||
(required) -> required;
|
||||
(required_trusted) -> required_trusted
|
||||
end)
|
||||
of
|
||||
UseTls
|
||||
when (UseTls == undefined) or
|
||||
(UseTls == false) ->
|
||||
{false, false};
|
||||
UseTls
|
||||
when (UseTls == true) or (UseTls == optional) ->
|
||||
{true, false};
|
||||
UseTls
|
||||
when (UseTls == required) or
|
||||
(UseTls == required_trusted) ->
|
||||
{true, true}
|
||||
end,
|
||||
{TLS, TLSRequired, TLSCertverify} =
|
||||
case ejabberd_config:get_option(
|
||||
s2s_use_starttls,
|
||||
fun(true) -> true;
|
||||
(false) -> false;
|
||||
(optional) -> optional;
|
||||
(required) -> required;
|
||||
(required_trusted) -> required_trusted
|
||||
end)
|
||||
of
|
||||
UseTls
|
||||
when (UseTls == undefined) or (UseTls == false) ->
|
||||
{false, false, false};
|
||||
UseTls
|
||||
when (UseTls == true) or (UseTls == optional) ->
|
||||
{true, false, false};
|
||||
required ->
|
||||
{true, true, false};
|
||||
required_trusted ->
|
||||
{true, true, true}
|
||||
end,
|
||||
UseV10 = TLS,
|
||||
TLSOpts1 = case
|
||||
ejabberd_config:get_option(
|
||||
@@ -191,13 +190,30 @@ init([From, Server, Type]) ->
|
||||
undefined -> [connect];
|
||||
CertFile -> [{certfile, CertFile}, connect]
|
||||
end,
|
||||
TLSOpts2 = case ejabberd_config:get_option(
|
||||
s2s_ciphers, fun iolist_to_binary/1) of
|
||||
undefined -> TLSOpts1;
|
||||
Ciphers -> [{ciphers, Ciphers} | TLSOpts1]
|
||||
end,
|
||||
TLSOpts3 = case ejabberd_config:get_option(
|
||||
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) of
|
||||
undefined -> TLSOpts2;
|
||||
ProtocolOpts -> [{protocol_options, ProtocolOpts} | TLSOpts2]
|
||||
end,
|
||||
TLSOpts = case ejabberd_config:get_option(
|
||||
{s2s_tls_compression, From},
|
||||
fun(true) -> true;
|
||||
(false) -> false
|
||||
end, true) of
|
||||
false -> [compression_none | TLSOpts1];
|
||||
true -> TLSOpts1
|
||||
false -> [compression_none | TLSOpts3];
|
||||
true -> TLSOpts3
|
||||
end,
|
||||
{New, Verify} = case Type of
|
||||
{new, Key} -> {Key, false};
|
||||
@@ -207,9 +223,9 @@ init([From, Server, Type]) ->
|
||||
Timer = erlang:start_timer(?S2STIMEOUT, self(), []),
|
||||
{ok, open_socket,
|
||||
#state{use_v10 = UseV10, tls = TLS,
|
||||
tls_required = TLSRequired, tls_options = TLSOpts,
|
||||
queue = queue:new(), myname = From, server = Server,
|
||||
new = New, verify = Verify, timer = Timer}}.
|
||||
tls_required = TLSRequired, tls_certverify = TLSCertverify,
|
||||
tls_options = TLSOpts, queue = queue:new(), myname = From,
|
||||
server = Server, new = New, verify = Verify, timer = Timer}}.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
%% Func: StateName/2
|
||||
@@ -329,35 +345,57 @@ open_socket2(Type, Addr, Port) ->
|
||||
|
||||
wait_for_stream({xmlstreamstart, _Name, Attrs},
|
||||
StateData) ->
|
||||
{CertCheckRes, CertCheckMsg, NewStateData} =
|
||||
if StateData#state.tls_certverify, StateData#state.tls_enabled ->
|
||||
{Res, Msg} =
|
||||
ejabberd_s2s:check_peer_certificate(ejabberd_socket,
|
||||
StateData#state.socket,
|
||||
StateData#state.server),
|
||||
?DEBUG("Certificate verification result for ~s: ~s",
|
||||
[StateData#state.server, Msg]),
|
||||
{Res, Msg, StateData#state{tls_certverify = false}};
|
||||
true ->
|
||||
{no_verify, <<"Not verified">>, StateData}
|
||||
end,
|
||||
case {xml:get_attr_s(<<"xmlns">>, Attrs),
|
||||
xml:get_attr_s(<<"xmlns:db">>, Attrs),
|
||||
xml:get_attr_s(<<"version">>, Attrs) == <<"1.0">>}
|
||||
of
|
||||
_ when CertCheckRes == error ->
|
||||
send_text(NewStateData,
|
||||
<<(xml:element_to_binary(?SERRT_POLICY_VIOLATION(<<"en">>,
|
||||
CertCheckMsg)))/binary,
|
||||
(?STREAM_TRAILER)/binary>>),
|
||||
?INFO_MSG("Closing s2s connection: ~s -> ~s (~s)",
|
||||
[NewStateData#state.myname,
|
||||
NewStateData#state.server,
|
||||
CertCheckMsg]),
|
||||
{stop, normal, NewStateData};
|
||||
{<<"jabber:server">>, <<"jabber:server:dialback">>,
|
||||
false} ->
|
||||
send_db_request(StateData);
|
||||
send_db_request(NewStateData);
|
||||
{<<"jabber:server">>, <<"jabber:server:dialback">>,
|
||||
true}
|
||||
when StateData#state.use_v10 ->
|
||||
{next_state, wait_for_features, StateData, ?FSMTIMEOUT};
|
||||
when NewStateData#state.use_v10 ->
|
||||
{next_state, wait_for_features, NewStateData, ?FSMTIMEOUT};
|
||||
%% Clause added to handle Tigase's workaround for an old ejabberd bug:
|
||||
{<<"jabber:server">>, <<"jabber:server:dialback">>,
|
||||
true}
|
||||
when not StateData#state.use_v10 ->
|
||||
send_db_request(StateData);
|
||||
when not NewStateData#state.use_v10 ->
|
||||
send_db_request(NewStateData);
|
||||
{<<"jabber:server">>, <<"">>, true}
|
||||
when StateData#state.use_v10 ->
|
||||
when NewStateData#state.use_v10 ->
|
||||
{next_state, wait_for_features,
|
||||
StateData#state{db_enabled = false}, ?FSMTIMEOUT};
|
||||
NewStateData#state{db_enabled = false}, ?FSMTIMEOUT};
|
||||
{NSProvided, DB, _} ->
|
||||
send_text(StateData, ?INVALID_NAMESPACE_ERR),
|
||||
send_text(NewStateData, ?INVALID_NAMESPACE_ERR),
|
||||
?INFO_MSG("Closing s2s connection: ~s -> ~s (invalid "
|
||||
"namespace).~nNamespace provided: ~p~nNamespac"
|
||||
"e expected: \"jabber:server\"~nxmlns:db "
|
||||
"provided: ~p~nAll attributes: ~p",
|
||||
[StateData#state.myname, StateData#state.server,
|
||||
[NewStateData#state.myname, NewStateData#state.server,
|
||||
NSProvided, DB, Attrs]),
|
||||
{stop, normal, StateData}
|
||||
{stop, normal, NewStateData}
|
||||
end;
|
||||
wait_for_stream({xmlstreamerror, _}, StateData) ->
|
||||
send_text(StateData,
|
||||
@@ -554,15 +592,19 @@ wait_for_features({xmlstreamelement, El}, StateData) ->
|
||||
if not SASLEXT and not StartTLS and
|
||||
StateData#state.authenticated ->
|
||||
send_queue(StateData, StateData#state.queue),
|
||||
?INFO_MSG("Connection established: ~s -> ~s",
|
||||
[StateData#state.myname, StateData#state.server]),
|
||||
?INFO_MSG("Connection established: ~s -> ~s with "
|
||||
"SASL EXTERNAL and TLS=~p",
|
||||
[StateData#state.myname, StateData#state.server,
|
||||
StateData#state.tls_enabled]),
|
||||
ejabberd_hooks:run(s2s_connect_hook,
|
||||
[StateData#state.myname,
|
||||
StateData#state.server]),
|
||||
{next_state, stream_established,
|
||||
StateData#state{queue = queue:new()}};
|
||||
SASLEXT and StateData#state.try_auth and
|
||||
(StateData#state.new /= false) ->
|
||||
(StateData#state.new /= false) and
|
||||
(StateData#state.tls_enabled or
|
||||
not StateData#state.tls_required) ->
|
||||
send_element(StateData,
|
||||
#xmlel{name = <<"auth">>,
|
||||
attrs =
|
||||
@@ -720,8 +762,8 @@ wait_for_starttls_proceed({xmlstreamelement, El},
|
||||
tls_options = TLSOpts},
|
||||
send_text(NewStateData,
|
||||
io_lib:format(?STREAM_HEADER,
|
||||
[StateData#state.myname,
|
||||
StateData#state.server,
|
||||
[NewStateData#state.myname,
|
||||
NewStateData#state.server,
|
||||
<<" version='1.0'">>])),
|
||||
{next_state, wait_for_stream, NewStateData,
|
||||
?FSMTIMEOUT};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 6 Dec 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
+63
-28
@@ -5,7 +5,7 @@
|
||||
%%% Created : 24 Nov 2002 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
@@ -33,11 +32,14 @@
|
||||
%% API
|
||||
-export([start_link/0,
|
||||
route/3,
|
||||
open_session/5, close_session/4,
|
||||
open_session/5,
|
||||
open_session/6,
|
||||
close_session/4,
|
||||
check_in_subscription/6,
|
||||
bounce_offline_message/3,
|
||||
disconnect_removed_user/2,
|
||||
get_user_resources/2,
|
||||
get_user_present_resources/2,
|
||||
set_presence/7,
|
||||
unset_presence/6,
|
||||
close_session_unset_presence/5,
|
||||
@@ -52,9 +54,12 @@
|
||||
connected_users/0,
|
||||
connected_users_number/0,
|
||||
user_resources/2,
|
||||
kick_user/2,
|
||||
get_session_pid/3,
|
||||
get_user_info/3,
|
||||
get_user_ip/3,
|
||||
get_max_user_sessions/2,
|
||||
get_all_pids/0,
|
||||
is_existing_resource/3
|
||||
]).
|
||||
|
||||
@@ -68,7 +73,7 @@
|
||||
-include("jlib.hrl").
|
||||
|
||||
-include("ejabberd_commands.hrl").
|
||||
|
||||
-include_lib("stdlib/include/ms_transform.hrl").
|
||||
-include("mod_privacy.hrl").
|
||||
|
||||
-record(session, {sid, usr, us, priority, info}).
|
||||
@@ -107,10 +112,10 @@ route(From, To, Packet) ->
|
||||
_ -> ok
|
||||
end.
|
||||
|
||||
-spec open_session(sid(), binary(), binary(), binary(), info()) -> ok.
|
||||
-spec open_session(sid(), binary(), binary(), binary(), prio(), info()) -> ok.
|
||||
|
||||
open_session(SID, User, Server, Resource, Info) ->
|
||||
set_session(SID, User, Server, Resource, undefined, Info),
|
||||
open_session(SID, User, Server, Resource, Priority, Info) ->
|
||||
set_session(SID, User, Server, Resource, Priority, Info),
|
||||
mnesia:dirty_update_counter(session_counter,
|
||||
jlib:nameprep(Server), 1),
|
||||
check_for_sessions_to_replace(User, Server, Resource),
|
||||
@@ -118,6 +123,11 @@ open_session(SID, User, Server, Resource, Info) ->
|
||||
ejabberd_hooks:run(sm_register_connection_hook,
|
||||
JID#jid.lserver, [SID, JID, Info]).
|
||||
|
||||
-spec open_session(sid(), binary(), binary(), binary(), info()) -> ok.
|
||||
|
||||
open_session(SID, User, Server, Resource, Info) ->
|
||||
open_session(SID, User, Server, Resource, undefined, Info).
|
||||
|
||||
-spec close_session(sid(), binary(), binary(), binary()) -> ok.
|
||||
|
||||
close_session(SID, User, Server, Resource) ->
|
||||
@@ -167,6 +177,20 @@ get_user_resources(User, Server) ->
|
||||
[element(3, S#session.usr) || S <- clean_session_list(Ss)]
|
||||
end.
|
||||
|
||||
-spec get_user_present_resources(binary(), binary()) -> [tuple()].
|
||||
|
||||
get_user_present_resources(LUser, LServer) ->
|
||||
US = {LUser, LServer},
|
||||
case catch mnesia:dirty_index_read(session, US,
|
||||
#session.us)
|
||||
of
|
||||
{'EXIT', _Reason} -> [];
|
||||
Ss ->
|
||||
[{S#session.priority, element(3, S#session.usr)}
|
||||
|| S <- clean_session_list(Ss),
|
||||
is_integer(S#session.priority)]
|
||||
end.
|
||||
|
||||
-spec get_user_ip(binary(), binary(), binary()) -> ip().
|
||||
|
||||
get_user_ip(User, Server, Resource) ->
|
||||
@@ -260,13 +284,23 @@ dirty_get_my_sessions_list() ->
|
||||
[{'==', {node, '$1'}, node()}],
|
||||
['$_']}]).
|
||||
|
||||
-spec get_vh_session_list(binary()) -> [ljid()].
|
||||
|
||||
get_vh_session_list(Server) ->
|
||||
LServer = jlib:nameprep(Server),
|
||||
mnesia:dirty_select(session,
|
||||
[{#session{usr = '$1', _ = '_'},
|
||||
[{'==', {element, 2, '$1'}, LServer}], ['$1']}]).
|
||||
|
||||
-spec get_vh_session_list(binary()) -> [ljid()].
|
||||
-spec get_all_pids() -> [pid()].
|
||||
|
||||
get_all_pids() ->
|
||||
mnesia:dirty_select(
|
||||
session,
|
||||
ets:fun2ms(
|
||||
fun(#session{sid = {_, Pid}}) ->
|
||||
Pid
|
||||
end)).
|
||||
|
||||
get_vh_session_number(Server) ->
|
||||
LServer = jlib:nameprep(Server),
|
||||
@@ -570,7 +604,7 @@ do_route(From, To, #xmlel{} = Packet) ->
|
||||
?ERR_SERVICE_UNAVAILABLE),
|
||||
ejabberd_router:route(To, From, Err)
|
||||
end;
|
||||
_ -> ?DEBUG("packet droped~n", [])
|
||||
_ -> ?DEBUG("packet dropped~n", [])
|
||||
end;
|
||||
Ss ->
|
||||
Session = lists:max(Ss),
|
||||
@@ -670,20 +704,6 @@ clean_session_list([S1, S2 | Rest], Res) ->
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
get_user_present_resources(LUser, LServer) ->
|
||||
US = {LUser, LServer},
|
||||
case catch mnesia:dirty_index_read(session, US,
|
||||
#session.us)
|
||||
of
|
||||
{'EXIT', _Reason} -> [];
|
||||
Ss ->
|
||||
[{S#session.priority, element(3, S#session.usr)}
|
||||
|| S <- clean_session_list(Ss),
|
||||
is_integer(S#session.priority)]
|
||||
end.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
%% On new session, check if some existing connections need to be replace
|
||||
check_for_sessions_to_replace(User, Server, Resource) ->
|
||||
LUser = jlib:nodeprep(User),
|
||||
@@ -800,8 +820,14 @@ commands() ->
|
||||
tags = [session],
|
||||
desc = "List user's connected resources",
|
||||
module = ?MODULE, function = user_resources,
|
||||
args = [{user, string}, {host, string}],
|
||||
result = {resources, {list, {resource, string}}}}].
|
||||
args = [{user, binary}, {host, binary}],
|
||||
result = {resources, {list, {resource, string}}}},
|
||||
#ejabberd_commands{name = kick_user,
|
||||
tags = [session],
|
||||
desc = "Disconnect user's active sessions",
|
||||
module = ?MODULE, function = kick_user,
|
||||
args = [{user, binary}, {host, binary}],
|
||||
result = {num_resources, integer}}].
|
||||
|
||||
-spec connected_users() -> [binary()].
|
||||
|
||||
@@ -818,6 +844,14 @@ user_resources(User, Server) ->
|
||||
Resources = get_user_resources(User, Server),
|
||||
lists:sort(Resources).
|
||||
|
||||
kick_user(User, Server) ->
|
||||
Resources = get_user_resources(User, Server),
|
||||
lists:foreach(
|
||||
fun(Resource) ->
|
||||
PID = get_session_pid(User, Server, Resource),
|
||||
PID ! kick
|
||||
end, Resources),
|
||||
length(Resources).
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% Update Mnesia tables
|
||||
@@ -827,6 +861,7 @@ update_tables() ->
|
||||
[ur, user, node] -> mnesia:delete_table(session);
|
||||
[ur, user, pid] -> mnesia:delete_table(session);
|
||||
[usr, us, pid] -> mnesia:delete_table(session);
|
||||
[usr, us, sid, priority, info] -> mnesia:delete_table(session);
|
||||
[sid, usr, us, priority] ->
|
||||
mnesia:delete_table(session);
|
||||
[sid, usr, us, priority, info] -> ok;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%%% Created : 23 Aug 2006 by Alexey Shchepin <alexey@process-one.net>
|
||||
%%%
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2002-2013 ProcessOne
|
||||
%%% 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
|
||||
@@ -17,10 +17,9 @@
|
||||
%%% 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
|
||||
%%% 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.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%% @copyright (C) 2014, Evgeny Khramtsov
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 8 May 2014 by Evgeny Khramtsov <ekhramtsov@process-one.net>
|
||||
%%%
|
||||
%%% ejabberd, Copyright (C) 2013-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.,
|
||||
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(ejabberd_stun).
|
||||
|
||||
%% API
|
||||
-export([tcp_init/2, udp_init/2, udp_recv/5, start/2, socket_type/0]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
tcp_init(Socket, Opts) ->
|
||||
ejabberd:start_app(p1_stun),
|
||||
stun:tcp_init(Socket, prepare_turn_opts(Opts)).
|
||||
|
||||
udp_init(Socket, Opts) ->
|
||||
ejabberd:start_app(p1_stun),
|
||||
stun:udp_init(Socket, prepare_turn_opts(Opts)).
|
||||
|
||||
udp_recv(Socket, Addr, Port, Packet, Opts) ->
|
||||
stun:udp_recv(Socket, Addr, Port, Packet, Opts).
|
||||
|
||||
start(Opaque, Opts) ->
|
||||
stun:start(Opaque, Opts).
|
||||
|
||||
socket_type() ->
|
||||
raw.
|
||||
|
||||
%%%===================================================================
|
||||
%%% Internal functions
|
||||
%%%===================================================================
|
||||
prepare_turn_opts(Opts) ->
|
||||
UseTurn = proplists:get_bool(use_turn, Opts),
|
||||
prepare_turn_opts(Opts, UseTurn).
|
||||
|
||||
prepare_turn_opts(Opts, _UseTurn = false) ->
|
||||
Opts;
|
||||
prepare_turn_opts(Opts, _UseTurn = true) ->
|
||||
NumberOfMyHosts = length(?MYHOSTS),
|
||||
case proplists:get_value(turn_ip, Opts) of
|
||||
undefined ->
|
||||
?WARNING_MSG("option 'turn_ip' is undefined, "
|
||||
"more likely the TURN relay won't be working "
|
||||
"properly", []);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
AuthFun = fun ejabberd_auth:get_password_s/2,
|
||||
Shaper = gen_mod:get_opt(shaper, Opts,
|
||||
fun(S) when is_atom(S) -> S end,
|
||||
none),
|
||||
AuthType = gen_mod:get_opt(auth_type, Opts,
|
||||
fun(anonymous) -> anonymous;
|
||||
(user) -> user
|
||||
end, user),
|
||||
Realm = case gen_mod:get_opt(auth_realm, Opts, fun iolist_to_binary/1) of
|
||||
undefined when AuthType == user ->
|
||||
if NumberOfMyHosts > 1 ->
|
||||
?WARNING_MSG("you have several virtual "
|
||||
"hosts configured, but option "
|
||||
"'auth_realm' is undefined and "
|
||||
"'auth_type' is set to 'user', "
|
||||
"more likely the TURN relay won't "
|
||||
"be working properly. Using ~s as "
|
||||
"a fallback", [?MYNAME]);
|
||||
true ->
|
||||
ok
|
||||
end,
|
||||
[{auth_realm, ?MYNAME}];
|
||||
_ ->
|
||||
[]
|
||||
end,
|
||||
MaxRate = shaper:get_max_rate(Shaper),
|
||||
Realm ++ [{auth_fun, AuthFun},{shaper, MaxRate} |
|
||||
lists:keydelete(shaper, 1, Opts)].
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user