Hanno Böck commited on 2007-09-13 03:07:31
Zeige 28 geänderte Dateien mit 0 Einfügungen und 4973 Löschungen.
... | ... |
@@ -1,42 +0,0 @@ |
1 |
-# ChangeLog for net-im/ejabberd |
|
2 |
-# Copyright 2005-2006 BreakMyGentoo.net; Distributed under the GPL v2 |
|
3 |
-# $Header: $ |
|
4 |
- |
|
5 |
-*ejabberd-1.1.2-r5.ebuild (21 Nov 2006) |
|
6 |
- 21 Nov 2006; Lars Strojny <lars@strojny.net> ejabberd-1.1.2-r5.ebuild: |
|
7 |
- Bumping |
|
8 |
- |
|
9 |
-*ejabberd-1.1.1.ebuild (07 May 2006) |
|
10 |
- 02 Sep 2006; Lars Strojny <lars@strojny.net> ejabberd-1.1.1.ebuild, |
|
11 |
- files/ejabberd-1.1.1-http_binding.patch, files/ejabberd-1.1.1-proxy65.patch: |
|
12 |
- Added USE-flag httpbind and proxy for HTTP-binding (JEP-0124) implementation |
|
13 |
- by Stefan Strigler <zeank@jwchat.org> in order of Mabber (http://mabber.com) |
|
14 |
- and a Socks bytestream-implementation (JEP-0065) which is currently |
|
15 |
- experimental and supplied via bugtracker |
|
16 |
- (http://www.jabber.ru/bugzilla/show_bug.cgi?id=25) by Sander Devrieze |
|
17 |
- <s.devrieze@pandora.be>. |
|
18 |
- |
|
19 |
- 08 May 2006; Lars Strojny <lars@strojny.net> ejabberd-1.1.1.ebuild: |
|
20 |
- Used --enable-odbc instead of the custom make |
|
21 |
- |
|
22 |
- 07 May 2006; Lars Strojny <lars@strojny.net> ejabberd-1.1.1.ebuild: |
|
23 |
- Fixed buggy myconf |
|
24 |
- |
|
25 |
- 07 May 2006; Lars Strojny <lars@strojny.net> ejabberd-1.1.1.ebuild: |
|
26 |
- Added fix by Max Loparyev <max@city.veganet.ru> for "SET NAMES |
|
27 |
- 'utf8'" during MySQL-connect. Did some cleaning. |
|
28 |
- |
|
29 |
- 07 May 2006; Lars Strojny <lars@strojny.net> ejabberd-1.1.1.ebuild: |
|
30 |
- Version bump |
|
31 |
- |
|
32 |
-*ejabberd-1.0-r1.ebuild |
|
33 |
- 02 Mar 2006; Hendrik Brandt <heb@gnome-de.org> ChangeLog: |
|
34 |
- add missing digest file |
|
35 |
- |
|
36 |
- 26 Feb 2006; Lars Strojny <lars@breakmygentoo.net> ejabberd-1.0.0-r1.ebuild: |
|
37 |
- Added fix for DNS-SRV connections |
|
38 |
- |
|
39 |
- 16 Feb 2006; Lars Strojny <lars@breakmygentoo.net> ChangeLog: |
|
40 |
- Initial commit. This is a typical "just works" ebuild. Needs some love to |
|
41 |
- become more elegant. |
|
42 |
- |
... | ... |
@@ -1,104 +0,0 @@ |
1 |
-AUX ejabberd-1.1.1-http_binding.patch 27120 RMD160 33a486a0070317755217d2513f38e1fc51436cd8 SHA1 9b5079ed7134c9ec6b101e79921f9978de820475 SHA256 9edbe0257b9e3fb547bcdb4f4325627e279199adfd6753622665b762eb675ed0 |
|
2 |
-MD5 98f2370cd26723c02ae57ae780221663 files/ejabberd-1.1.1-http_binding.patch 27120 |
|
3 |
-RMD160 33a486a0070317755217d2513f38e1fc51436cd8 files/ejabberd-1.1.1-http_binding.patch 27120 |
|
4 |
-SHA256 9edbe0257b9e3fb547bcdb4f4325627e279199adfd6753622665b762eb675ed0 files/ejabberd-1.1.1-http_binding.patch 27120 |
|
5 |
-AUX ejabberd-1.1.1-mysql-connect-utf8.patch 622 RMD160 36bf34ba4a584ed19a4f93f709df0cfeb7d0ad7b SHA1 3fd01b6d6782bea7feeb3f784f393c04a7b7022c SHA256 747fbd494d6ebb75d5b73d407be10b0dba10f59a4a46561509c788d72a30ff08 |
|
6 |
-MD5 2b686065c6f72505ae252cdb5c7bebe8 files/ejabberd-1.1.1-mysql-connect-utf8.patch 622 |
|
7 |
-RMD160 36bf34ba4a584ed19a4f93f709df0cfeb7d0ad7b files/ejabberd-1.1.1-mysql-connect-utf8.patch 622 |
|
8 |
-SHA256 747fbd494d6ebb75d5b73d407be10b0dba10f59a4a46561509c788d72a30ff08 files/ejabberd-1.1.1-mysql-connect-utf8.patch 622 |
|
9 |
-AUX ejabberd-1.1.1-proxy65.patch 13293 RMD160 cdd06d4ca07773349ad4d97d854cff8b5547c8e2 SHA1 a6d9000a8b751efb1045830544a9e9a89e8122da SHA256 ade6a713cdb57c74ee29063104e4cf44476bb7fb5e63b3ea9f1353c20e9813aa |
|
10 |
-MD5 6284b9ed2a52690a62fbdca052c5a571 files/ejabberd-1.1.1-proxy65.patch 13293 |
|
11 |
-RMD160 cdd06d4ca07773349ad4d97d854cff8b5547c8e2 files/ejabberd-1.1.1-proxy65.patch 13293 |
|
12 |
-SHA256 ade6a713cdb57c74ee29063104e4cf44476bb7fb5e63b3ea9f1353c20e9813aa files/ejabberd-1.1.1-proxy65.patch 13293 |
|
13 |
-AUX ejabberd-1.1.1.confd 671 RMD160 e727a01c6e0418468bd785447b85d349a536f3ea SHA1 e40c4e24ed1976a781b9557d8ba186fb0fd5cda2 SHA256 fb8f66daaa4bf9063867b80ac6e677be7f6739d3c245bf389467df2ea687887d |
|
14 |
-MD5 03cdfdbfb294de6eccffda248d349040 files/ejabberd-1.1.1.confd 671 |
|
15 |
-RMD160 e727a01c6e0418468bd785447b85d349a536f3ea files/ejabberd-1.1.1.confd 671 |
|
16 |
-SHA256 fb8f66daaa4bf9063867b80ac6e677be7f6739d3c245bf389467df2ea687887d files/ejabberd-1.1.1.confd 671 |
|
17 |
-AUX ejabberd-1.1.1.initd 1260 RMD160 0565503966512228f21079213a8587d7ada7a823 SHA1 09d2ca4ab1a371fe2a987f649c6761742531c658 SHA256 cd06a6efdefda36993eb82fb6617a9a7e65228941f4deac42d583e96b1d6dfc9 |
|
18 |
-MD5 608e482a70b1cd9a1a78d721edc8d42d files/ejabberd-1.1.1.initd 1260 |
|
19 |
-RMD160 0565503966512228f21079213a8587d7ada7a823 files/ejabberd-1.1.1.initd 1260 |
|
20 |
-SHA256 cd06a6efdefda36993eb82fb6617a9a7e65228941f4deac42d583e96b1d6dfc9 files/ejabberd-1.1.1.initd 1260 |
|
21 |
-AUX ejabberd-1.1.2-http_binding.patch 29551 RMD160 6c1c9bc7516a5d4a13220be5d7508348aca1128a SHA1 d65a1fdf14c74154b25778e495568aeec6dcad77 SHA256 c55992c2b6e9ca36d9687237b990c27c47511bbe025d746d2380f122fecbda32 |
|
22 |
-MD5 8e25a0686567a645914aa51440e7d521 files/ejabberd-1.1.2-http_binding.patch 29551 |
|
23 |
-RMD160 6c1c9bc7516a5d4a13220be5d7508348aca1128a files/ejabberd-1.1.2-http_binding.patch 29551 |
|
24 |
-SHA256 c55992c2b6e9ca36d9687237b990c27c47511bbe025d746d2380f122fecbda32 files/ejabberd-1.1.2-http_binding.patch 29551 |
|
25 |
-AUX ejabberd-1.1.2-mod_irc-utf-8.patch 369 RMD160 11b3a06b4f8af77c6c368aeacfe8943eace50da5 SHA1 123a95c4535102aaa076435c464025e40f9fb889 SHA256 a3884a97f9e4239df643ac327c48baf78f77c9cffbd5d67f39f018a811dcdc9f |
|
26 |
-MD5 3ca38149e85443cac4dfc58ca8bf1c08 files/ejabberd-1.1.2-mod_irc-utf-8.patch 369 |
|
27 |
-RMD160 11b3a06b4f8af77c6c368aeacfe8943eace50da5 files/ejabberd-1.1.2-mod_irc-utf-8.patch 369 |
|
28 |
-SHA256 a3884a97f9e4239df643ac327c48baf78f77c9cffbd5d67f39f018a811dcdc9f files/ejabberd-1.1.2-mod_irc-utf-8.patch 369 |
|
29 |
-AUX ejabberd-1.1.2-mysql-connect-utf8.patch 622 RMD160 36bf34ba4a584ed19a4f93f709df0cfeb7d0ad7b SHA1 3fd01b6d6782bea7feeb3f784f393c04a7b7022c SHA256 747fbd494d6ebb75d5b73d407be10b0dba10f59a4a46561509c788d72a30ff08 |
|
30 |
-MD5 2b686065c6f72505ae252cdb5c7bebe8 files/ejabberd-1.1.2-mysql-connect-utf8.patch 622 |
|
31 |
-RMD160 36bf34ba4a584ed19a4f93f709df0cfeb7d0ad7b files/ejabberd-1.1.2-mysql-connect-utf8.patch 622 |
|
32 |
-SHA256 747fbd494d6ebb75d5b73d407be10b0dba10f59a4a46561509c788d72a30ff08 files/ejabberd-1.1.2-mysql-connect-utf8.patch 622 |
|
33 |
-AUX ejabberd-1.1.2-proxy65.patch 13293 RMD160 cdd06d4ca07773349ad4d97d854cff8b5547c8e2 SHA1 a6d9000a8b751efb1045830544a9e9a89e8122da SHA256 ade6a713cdb57c74ee29063104e4cf44476bb7fb5e63b3ea9f1353c20e9813aa |
|
34 |
-MD5 6284b9ed2a52690a62fbdca052c5a571 files/ejabberd-1.1.2-proxy65.patch 13293 |
|
35 |
-RMD160 cdd06d4ca07773349ad4d97d854cff8b5547c8e2 files/ejabberd-1.1.2-proxy65.patch 13293 |
|
36 |
-SHA256 ade6a713cdb57c74ee29063104e4cf44476bb7fb5e63b3ea9f1353c20e9813aa files/ejabberd-1.1.2-proxy65.patch 13293 |
|
37 |
-AUX ejabberd-1.1.2.confd 671 RMD160 e727a01c6e0418468bd785447b85d349a536f3ea SHA1 e40c4e24ed1976a781b9557d8ba186fb0fd5cda2 SHA256 fb8f66daaa4bf9063867b80ac6e677be7f6739d3c245bf389467df2ea687887d |
|
38 |
-MD5 03cdfdbfb294de6eccffda248d349040 files/ejabberd-1.1.2.confd 671 |
|
39 |
-RMD160 e727a01c6e0418468bd785447b85d349a536f3ea files/ejabberd-1.1.2.confd 671 |
|
40 |
-SHA256 fb8f66daaa4bf9063867b80ac6e677be7f6739d3c245bf389467df2ea687887d files/ejabberd-1.1.2.confd 671 |
|
41 |
-AUX ejabberd-1.1.2.initd 1260 RMD160 0565503966512228f21079213a8587d7ada7a823 SHA1 09d2ca4ab1a371fe2a987f649c6761742531c658 SHA256 cd06a6efdefda36993eb82fb6617a9a7e65228941f4deac42d583e96b1d6dfc9 |
|
42 |
-MD5 608e482a70b1cd9a1a78d721edc8d42d files/ejabberd-1.1.2.initd 1260 |
|
43 |
-RMD160 0565503966512228f21079213a8587d7ada7a823 files/ejabberd-1.1.2.initd 1260 |
|
44 |
-SHA256 cd06a6efdefda36993eb82fb6617a9a7e65228941f4deac42d583e96b1d6dfc9 files/ejabberd-1.1.2.initd 1260 |
|
45 |
-AUX ejabberd-1.1.3-http_binding.patch 29551 RMD160 6c1c9bc7516a5d4a13220be5d7508348aca1128a SHA1 d65a1fdf14c74154b25778e495568aeec6dcad77 SHA256 c55992c2b6e9ca36d9687237b990c27c47511bbe025d746d2380f122fecbda32 |
|
46 |
-MD5 8e25a0686567a645914aa51440e7d521 files/ejabberd-1.1.3-http_binding.patch 29551 |
|
47 |
-RMD160 6c1c9bc7516a5d4a13220be5d7508348aca1128a files/ejabberd-1.1.3-http_binding.patch 29551 |
|
48 |
-SHA256 c55992c2b6e9ca36d9687237b990c27c47511bbe025d746d2380f122fecbda32 files/ejabberd-1.1.3-http_binding.patch 29551 |
|
49 |
-AUX ejabberd-1.1.3-mod_irc-utf-8.patch 369 RMD160 11b3a06b4f8af77c6c368aeacfe8943eace50da5 SHA1 123a95c4535102aaa076435c464025e40f9fb889 SHA256 a3884a97f9e4239df643ac327c48baf78f77c9cffbd5d67f39f018a811dcdc9f |
|
50 |
-MD5 3ca38149e85443cac4dfc58ca8bf1c08 files/ejabberd-1.1.3-mod_irc-utf-8.patch 369 |
|
51 |
-RMD160 11b3a06b4f8af77c6c368aeacfe8943eace50da5 files/ejabberd-1.1.3-mod_irc-utf-8.patch 369 |
|
52 |
-SHA256 a3884a97f9e4239df643ac327c48baf78f77c9cffbd5d67f39f018a811dcdc9f files/ejabberd-1.1.3-mod_irc-utf-8.patch 369 |
|
53 |
-AUX ejabberd-1.1.3-mysql-connect-utf8.patch 659 RMD160 5d72e94d9634447eb07b03d8229e99a5d7e7a43f SHA1 7a7e5ccc60dfeb197567c6097f190ee241fcb95a SHA256 371c5de9be1c366f7a5ee0008621bce761acbab0b92e279e31326b6bdf8a6c52 |
|
54 |
-MD5 d014130a19d11bfa159b998a0f44796c files/ejabberd-1.1.3-mysql-connect-utf8.patch 659 |
|
55 |
-RMD160 5d72e94d9634447eb07b03d8229e99a5d7e7a43f files/ejabberd-1.1.3-mysql-connect-utf8.patch 659 |
|
56 |
-SHA256 371c5de9be1c366f7a5ee0008621bce761acbab0b92e279e31326b6bdf8a6c52 files/ejabberd-1.1.3-mysql-connect-utf8.patch 659 |
|
57 |
-AUX ejabberd-1.1.3-proxy65.patch 13293 RMD160 cdd06d4ca07773349ad4d97d854cff8b5547c8e2 SHA1 a6d9000a8b751efb1045830544a9e9a89e8122da SHA256 ade6a713cdb57c74ee29063104e4cf44476bb7fb5e63b3ea9f1353c20e9813aa |
|
58 |
-MD5 6284b9ed2a52690a62fbdca052c5a571 files/ejabberd-1.1.3-proxy65.patch 13293 |
|
59 |
-RMD160 cdd06d4ca07773349ad4d97d854cff8b5547c8e2 files/ejabberd-1.1.3-proxy65.patch 13293 |
|
60 |
-SHA256 ade6a713cdb57c74ee29063104e4cf44476bb7fb5e63b3ea9f1353c20e9813aa files/ejabberd-1.1.3-proxy65.patch 13293 |
|
61 |
-AUX ejabberd-1.1.3.confd 671 RMD160 e727a01c6e0418468bd785447b85d349a536f3ea SHA1 e40c4e24ed1976a781b9557d8ba186fb0fd5cda2 SHA256 fb8f66daaa4bf9063867b80ac6e677be7f6739d3c245bf389467df2ea687887d |
|
62 |
-MD5 03cdfdbfb294de6eccffda248d349040 files/ejabberd-1.1.3.confd 671 |
|
63 |
-RMD160 e727a01c6e0418468bd785447b85d349a536f3ea files/ejabberd-1.1.3.confd 671 |
|
64 |
-SHA256 fb8f66daaa4bf9063867b80ac6e677be7f6739d3c245bf389467df2ea687887d files/ejabberd-1.1.3.confd 671 |
|
65 |
-AUX ejabberd-1.1.3.initd 1260 RMD160 0565503966512228f21079213a8587d7ada7a823 SHA1 09d2ca4ab1a371fe2a987f649c6761742531c658 SHA256 cd06a6efdefda36993eb82fb6617a9a7e65228941f4deac42d583e96b1d6dfc9 |
|
66 |
-MD5 608e482a70b1cd9a1a78d721edc8d42d files/ejabberd-1.1.3.initd 1260 |
|
67 |
-RMD160 0565503966512228f21079213a8587d7ada7a823 files/ejabberd-1.1.3.initd 1260 |
|
68 |
-SHA256 cd06a6efdefda36993eb82fb6617a9a7e65228941f4deac42d583e96b1d6dfc9 files/ejabberd-1.1.3.initd 1260 |
|
69 |
-AUX inetrc 36 RMD160 4b79020864689ede547969610fde18fe490f5810 SHA1 1e0bae0f7251e2ae3b62ba9d3e5cc86bb5dd271e SHA256 0f383befc4c46134d88ce14d3bd06c404ef6575391f4ac0b5e8c28ba383b28fc |
|
70 |
-MD5 e088cd52d4316efddc54195dc939cd24 files/inetrc 36 |
|
71 |
-RMD160 4b79020864689ede547969610fde18fe490f5810 files/inetrc 36 |
|
72 |
-SHA256 0f383befc4c46134d88ce14d3bd06c404ef6575391f4ac0b5e8c28ba383b28fc files/inetrc 36 |
|
73 |
-DIST ejabberd-1.1.1.tar.gz 803278 RMD160 b9c0b7ab3fe1f1b2dce52e1460bba04b313ea534 SHA1 4f23d787afe75c7c866decdff6f539195449776e SHA256 52a97275537073066bd352f5718954f6994b272d1efa51187e17edf0c9b11082 |
|
74 |
-DIST ejabberd-1.1.2.tar.gz 836240 RMD160 e763752e6c5fb46c51b71e265ab2ceda6d043a0d SHA1 9e94bdbc10fee5b781405daf43a0b4abc4dee6c1 SHA256 029129a6bcb5d15dbccc5aa756f61c52692eb6882ec7aad0193aa940b6a20bb6 |
|
75 |
-DIST ejabberd-1.1.3.tar.gz 826057 RMD160 99b4c73ae29ef9814f5c572f8e3b3a82d960f5ee SHA1 66b00ca52fa4f4f4e097b0e897c3b5a2e4526603 SHA256 3b8ac67673fa6c08bc25382d3e99171ebc71d4759899eb5a730e65117256e703 |
|
76 |
-EBUILD ejabberd-1.1.1.ebuild 5044 RMD160 3c0213f2cd39fdb54505cc0b394b70477b10fbb4 SHA1 491cbd3d3ab8dde27a5280fdbf2783131da4fa7b SHA256 9346b48122eb7812e6beba93e223d0c1d027719877ef7307415edac56b1a1d06 |
|
77 |
-MD5 2d16ab0045996aa62fdc6867e8c62edb ejabberd-1.1.1.ebuild 5044 |
|
78 |
-RMD160 3c0213f2cd39fdb54505cc0b394b70477b10fbb4 ejabberd-1.1.1.ebuild 5044 |
|
79 |
-SHA256 9346b48122eb7812e6beba93e223d0c1d027719877ef7307415edac56b1a1d06 ejabberd-1.1.1.ebuild 5044 |
|
80 |
-EBUILD ejabberd-1.1.2-r5.ebuild 5072 RMD160 d1ad865d489b7856ea9b252ac0fc9444fa812cd7 SHA1 695f4b8715050907072e347ea846b59fe673c181 SHA256 ada01971d7d7b5362ad8b9a839a990eb1b2d8013f7c66fdbba502486b02cbbfb |
|
81 |
-MD5 27ae991ce72e44d8838c5e7c9f3a5331 ejabberd-1.1.2-r5.ebuild 5072 |
|
82 |
-RMD160 d1ad865d489b7856ea9b252ac0fc9444fa812cd7 ejabberd-1.1.2-r5.ebuild 5072 |
|
83 |
-SHA256 ada01971d7d7b5362ad8b9a839a990eb1b2d8013f7c66fdbba502486b02cbbfb ejabberd-1.1.2-r5.ebuild 5072 |
|
84 |
-EBUILD ejabberd-1.1.3-r1.ebuild 4312 RMD160 fd19cc00f401ca16d17ca31f7a891444ed9edd25 SHA1 a1983e32f9289d93313af6f9fd08bc1e37fbc605 SHA256 cdaa01e626f0d032c0ed780be0fc964b314fed492a88d96832c317026bb550d9 |
|
85 |
-MD5 2b495ac9aaca0c91f75e67f53e2ea96a ejabberd-1.1.3-r1.ebuild 4312 |
|
86 |
-RMD160 fd19cc00f401ca16d17ca31f7a891444ed9edd25 ejabberd-1.1.3-r1.ebuild 4312 |
|
87 |
-SHA256 cdaa01e626f0d032c0ed780be0fc964b314fed492a88d96832c317026bb550d9 ejabberd-1.1.3-r1.ebuild 4312 |
|
88 |
-MISC ChangeLog 1674 RMD160 a7cde836a8d747863d148edef3a9d1b7cf781af2 SHA1 529722882cfb1e1135eda10c99d0aa8e753704a3 SHA256 c37aa58a182a91857395f0c53c3299d19cfe4960d5240673c7606f18199d3681 |
|
89 |
-MD5 678fcb919ef8ac4a080934c500537f8d ChangeLog 1674 |
|
90 |
-RMD160 a7cde836a8d747863d148edef3a9d1b7cf781af2 ChangeLog 1674 |
|
91 |
-SHA256 c37aa58a182a91857395f0c53c3299d19cfe4960d5240673c7606f18199d3681 ChangeLog 1674 |
|
92 |
-MISC metadata.xml 386 RMD160 6851cac865de77f0052aa55b91845f98ba984bf2 SHA1 f3a72217775da32822787455f53a6168b4ce2acb SHA256 8fdc368bc07695d9ee0b988f09ef41799619a86f33faf839360c046f46ce8aa5 |
|
93 |
-MD5 de765f4e50f58226d0035d84531cf752 metadata.xml 386 |
|
94 |
-RMD160 6851cac865de77f0052aa55b91845f98ba984bf2 metadata.xml 386 |
|
95 |
-SHA256 8fdc368bc07695d9ee0b988f09ef41799619a86f33faf839360c046f46ce8aa5 metadata.xml 386 |
|
96 |
-MD5 87c80474a3cbcdf51830a748a411f0f4 files/digest-ejabberd-1.1.1 244 |
|
97 |
-RMD160 bdb61a1e0dd65fa91775a5f3b7c7516dc65bd8ff files/digest-ejabberd-1.1.1 244 |
|
98 |
-SHA256 d3659c3dbc43cf807fb7309da84ba62393e9257a7a16a3305621ee60f97378a6 files/digest-ejabberd-1.1.1 244 |
|
99 |
-MD5 a38033cd51c7bb84bc09310952063222 files/digest-ejabberd-1.1.2-r5 244 |
|
100 |
-RMD160 d8117ebc19953eb40137b4ebca37d7577ff9e5b6 files/digest-ejabberd-1.1.2-r5 244 |
|
101 |
-SHA256 e1ff34ed81425e1b009e60d29d7f6b9bdeff7cdba4407372cfdb8e40ca00efcb files/digest-ejabberd-1.1.2-r5 244 |
|
102 |
-MD5 9b247a2a345b5d2c9cdf1a1678f4edf9 files/digest-ejabberd-1.1.3-r1 244 |
|
103 |
-RMD160 59a1985b119be6cf343af1ea13929c233e59f0b4 files/digest-ejabberd-1.1.3-r1 244 |
|
104 |
-SHA256 5dad3cfcf7b609862a65b6d09c18ed318563573f866e6c19010c7b9ee7836998 files/digest-ejabberd-1.1.3-r1 244 |
... | ... |
@@ -1,197 +0,0 @@ |
1 |
-# Copyright 2005-2006 BreakMyGentoo.net |
|
2 |
-# Distributed under the terms of the GNU General Public License v2 |
|
3 |
-# $Header: $ |
|
4 |
- |
|
5 |
-inherit eutils multilib ssl-cert versionator |
|
6 |
- |
|
7 |
-JABBER_ETC="/etc/jabber" |
|
8 |
-JABBER_RUN="/var/run/jabber" |
|
9 |
-JABBER_SPOOL="/var/spool/jabber" |
|
10 |
-JABBER_LOG="/var/log/jabber" |
|
11 |
- |
|
12 |
-E_MYSQL_V="5" |
|
13 |
-E_MYSQL_N="mysql" |
|
14 |
-E_MYSQL=${E_MYSQL_N}-${E_MYSQL_V} |
|
15 |
- |
|
16 |
-E_PGSQL_V="0.0.1" |
|
17 |
-E_PGSQL_N="pgsql-cvs" |
|
18 |
-E_PGSQL=${E_PGSQL_N}-${E_PGSQL_V} |
|
19 |
- |
|
20 |
-DESCRIPTION="The Erlang Jabber Daemon" |
|
21 |
-HOMEPAGE="http://ejabberd.jabber.ru/" |
|
22 |
-SRC_URI="http://process-one.net/en/projects/ejabberd/download/${PV}/${P}.tar.gz" |
|
23 |
-LICENSE="GPL-2" |
|
24 |
-SLOT="0" |
|
25 |
-KEYWORDS="~x86 ~amd64" |
|
26 |
-IUSE="${IUSE} irc ldap muc odbc postgres pubsub web mysql httpbind proxy" |
|
27 |
- |
|
28 |
-DEPEND="${RDEPEND} |
|
29 |
- >=net-im/jabber-base-0.00 |
|
30 |
- >=dev-libs/expat-1.95 |
|
31 |
- >=dev-lang/erlang-10.2.0 |
|
32 |
- odbc? ( dev-db/unixODBC ) |
|
33 |
- ldap? ( =net-nds/openldap-2* ) |
|
34 |
- postgres? ( =dev-erl/${E_PGSQL} ) |
|
35 |
- mysql? ( =dev-erl/${E_MYSQL} )" |
|
36 |
- |
|
37 |
-RDEPEND="postgres? ( dev-db/postgresql ) |
|
38 |
- mysql? ( dev-db/mysql )" |
|
39 |
- |
|
40 |
-PROVIDE="virtual/jabber-server" |
|
41 |
-S=${WORKDIR}/${P}/src |
|
42 |
- |
|
43 |
-src_unpack() { |
|
44 |
- unpack ${A} |
|
45 |
- MYSQL_P=$(best_version dev-db/mysql) |
|
46 |
- MYSQL_PV=${MYSQL_P/dev-db\/mysql-/} |
|
47 |
- |
|
48 |
- # |
|
49 |
- # If we have to work with MySQL 4.1 or greater, ejabberd's native |
|
50 |
- # MySQL-driver has to be patched to query "SET NAMES 'utf8'" on connecting |
|
51 |
- # the database. |
|
52 |
- # |
|
53 |
- if use mysql && \ |
|
54 |
- (( \ |
|
55 |
- [ $(get_major_version ${MYSQL_PV}) -eq 4 ] && \ |
|
56 |
- [ $(get_major_version $(get_after_major_version ${MYSQL_PV})) -ge 1] \ |
|
57 |
- ) \ |
|
58 |
- || \ |
|
59 |
- [ $(get_major_version ${MYSQL_PV}) -ge 5 ] \ |
|
60 |
- ); then |
|
61 |
- epatch ${FILESDIR}/${P}-mysql-connect-utf8.patch |
|
62 |
- fi |
|
63 |
- |
|
64 |
- cd ${S} |
|
65 |
- if use httpbind; then |
|
66 |
- epatch ${FILESDIR}/${P}-http_binding.patch |
|
67 |
- fi |
|
68 |
- |
|
69 |
- if use proxy; then |
|
70 |
- epatch ${FILESDIR}/${P}-proxy65.patch |
|
71 |
- fi |
|
72 |
- |
|
73 |
- epatch ${FILESDIR}/${P}-mod_irc-charset.patch |
|
74 |
-} |
|
75 |
- |
|
76 |
- |
|
77 |
-src_compile() { |
|
78 |
- local myconf |
|
79 |
- |
|
80 |
- if ! use mysql && ! use postgres && ! use odbc; then |
|
81 |
- myconf="--disable-odbc" |
|
82 |
- else |
|
83 |
- myconf="--enable-odbc" |
|
84 |
- fi |
|
85 |
- |
|
86 |
- # |
|
87 |
- # configure ejabberd |
|
88 |
- # |
|
89 |
- econf ${myconf} \ |
|
90 |
- --enable-roster-gateway-workaround \ |
|
91 |
- $(use_enable irc mod_irc) \ |
|
92 |
- $(use_enable ldap eldap) \ |
|
93 |
- $(use_enable muc mod_muc) \ |
|
94 |
- $(use_enable pubsub mod_pubsub) \ |
|
95 |
- $(use_enable ssl tls) \ |
|
96 |
- $(use_enable web web) \ |
|
97 |
- || die "econf failed" |
|
98 |
- |
|
99 |
- # |
|
100 |
- # Build ejabberd core |
|
101 |
- # |
|
102 |
- emake || die "compiling ejabberd core failed" |
|
103 |
-} |
|
104 |
- |
|
105 |
-src_install() { |
|
106 |
- # |
|
107 |
- # Install ejabberd |
|
108 |
- # |
|
109 |
- make \ |
|
110 |
- DESTDIR=${D} \ |
|
111 |
- EJABBERDDIR=${D}/usr/$(get_libdir)/erlang/lib/${P} \ |
|
112 |
- ETCDIR=${D}${JABBER_ETC} \ |
|
113 |
- LOGDIR=${D}${JABBER_LOG} \ |
|
114 |
- install \ |
|
115 |
- || die "install failed" |
|
116 |
- |
|
117 |
- |
|
118 |
- insinto /usr/share/doc/${PF} |
|
119 |
- use postgres && doins odbc/pg.sql |
|
120 |
- use mysql && doins odbc/mysql.sql |
|
121 |
- dodoc doc/release_notes_${PV}.txt |
|
122 |
- dohtml doc/*.{html,png} |
|
123 |
- |
|
124 |
- |
|
125 |
- use postgres && { |
|
126 |
- pa="-pa /usr/$(get_libdir)/erlang/lib/${E_PGSQL}/ebin" |
|
127 |
- } |
|
128 |
- |
|
129 |
- use mysql && { |
|
130 |
- pa=${pa}" -pa /usr/$(get_libdir)/erlang/lib/${E_MYSQL}/ebin" |
|
131 |
- } |
|
132 |
- |
|
133 |
- # |
|
134 |
- # Create /usr/bin/ejabberd |
|
135 |
- # |
|
136 |
- cat <<EOF > ${T}/ejabberd |
|
137 |
-#!/bin/bash |
|
138 |
- |
|
139 |
-erl -pa /usr/$(get_libdir)/erlang/lib/${P}/ebin \\ |
|
140 |
- ${pa} \\ |
|
141 |
- -sname ejabberd \\ |
|
142 |
- -s ejabberd \\ |
|
143 |
- -ejabberd config \"${JABBER_ETC}/ejabberd.cfg\" \\ |
|
144 |
- log_path \"${JABBER_LOG}/ejabberd.log\" \\ |
|
145 |
- -kernel inetrc \"${JABBER_ETC}/inetrc\" \\ |
|
146 |
- -sasl sasl_error_logger \{file,\"${JABBER_LOG}/sasl.log\"\} \\ |
|
147 |
- -mnesia dir \"${JABBER_SPOOL}\" \\ |
|
148 |
- \$@ |
|
149 |
-EOF |
|
150 |
- |
|
151 |
- # |
|
152 |
- # Create /usr/bin/ejabberdctl |
|
153 |
- # |
|
154 |
- cat <<EOF > ${T}/ejabberdctl |
|
155 |
-#!/bin/sh |
|
156 |
- |
|
157 |
-exec env HOME=${JABBER_RUN} \\ |
|
158 |
- erl -pa /usr/$(get_libdir)/erlang/lib/${P}/ebin \\ |
|
159 |
- ${pa} \\ |
|
160 |
- -noinput \\ |
|
161 |
- -sname ejabberdctl \\ |
|
162 |
- -s ejabberd_ctl \\ |
|
163 |
- -extra \$@ |
|
164 |
-EOF |
|
165 |
- |
|
166 |
- dobin ${T}/ejabberdctl |
|
167 |
- dobin ${T}/ejabberd |
|
168 |
- |
|
169 |
- newinitd ${FILESDIR}/${P}.initd ${PN} |
|
170 |
- newconfd ${FILESDIR}/${P}.confd ${PN} |
|
171 |
- |
|
172 |
- insinto ${JABBER_ETC} |
|
173 |
- if use ssl; then |
|
174 |
- docert ssl |
|
175 |
- rm -f ${D}${JABBER_ETC}/ssl.{crt,csr,key} |
|
176 |
- fowners jabber:jabber ${JABBER_ETC}/ssl.pem |
|
177 |
- fi |
|
178 |
- doins ${FILESDIR}/inetrc |
|
179 |
-} |
|
180 |
- |
|
181 |
-pkg_postinst() { |
|
182 |
- if [ ! -e ${JABBER_ETC}/ejabberd.cfg ] |
|
183 |
- then |
|
184 |
- einfo "Configuration file has been installed in ${JABBER_ETC}/ejabberd.cfg." |
|
185 |
- einfo "Edit it according to your needs. For configuration instructions," |
|
186 |
- einfo "please see /usr/share/doc/${PF}/html/guide.html" |
|
187 |
- fi |
|
188 |
- if use ssl ; then |
|
189 |
- einfo "A script to generate a ssl key has been installed in" |
|
190 |
- einfo "${JABBER_ETC}/self-cert.sh . Use it and change the config file to" |
|
191 |
- einfo "point to the full path" |
|
192 |
- fi |
|
193 |
- if ! use web ; then |
|
194 |
- einfo "The web USE flag is off, this will disable the web admin interface," |
|
195 |
- einfo "if this was not the intention then add web to your USE flags." |
|
196 |
- fi |
|
197 |
-} |
... | ... |
@@ -1,197 +0,0 @@ |
1 |
-# Copyright 2005-2006 BreakMyGentoo.net |
|
2 |
-# Distributed under the terms of the GNU General Public License v2 |
|
3 |
-# $Header: $ |
|
4 |
- |
|
5 |
-inherit eutils multilib ssl-cert versionator |
|
6 |
- |
|
7 |
-JABBER_ETC="/etc/jabber" |
|
8 |
-JABBER_RUN="/var/run/jabber" |
|
9 |
-JABBER_SPOOL="/var/spool/jabber" |
|
10 |
-JABBER_LOG="/var/log/jabber" |
|
11 |
- |
|
12 |
-E_MYSQL_V="0.1" |
|
13 |
-E_MYSQL_N="mysql" |
|
14 |
-E_MYSQL=${E_MYSQL_N}-${E_MYSQL_V} |
|
15 |
- |
|
16 |
-E_PGSQL_V="0.0.1" |
|
17 |
-E_PGSQL_N="pgsql-cvs" |
|
18 |
-E_PGSQL=${E_PGSQL_N}-${E_PGSQL_V} |
|
19 |
- |
|
20 |
-DESCRIPTION="The Erlang Jabber Daemon" |
|
21 |
-HOMEPAGE="http://ejabberd.jabber.ru/" |
|
22 |
-SRC_URI="http://process-one.net/en/projects/ejabberd/download/${PV}/${P}.tar.gz" |
|
23 |
-LICENSE="GPL-2" |
|
24 |
-SLOT="0" |
|
25 |
-KEYWORDS="~x86 amd64" |
|
26 |
-IUSE="${IUSE} irc ldap muc odbc postgres pubsub web mysql httpbind proxy" |
|
27 |
- |
|
28 |
-DEPEND="${RDEPEND} |
|
29 |
- >=net-im/jabber-base-0.00 |
|
30 |
- >=dev-libs/expat-1.95 |
|
31 |
- >=dev-lang/erlang-10.2.0 |
|
32 |
- odbc? ( dev-db/unixODBC ) |
|
33 |
- ldap? ( =net-nds/openldap-2* ) |
|
34 |
- postgres? ( =dev-erl/${E_PGSQL} ) |
|
35 |
- mysql? ( =dev-erl/${E_MYSQL} )" |
|
36 |
- |
|
37 |
-RDEPEND="postgres? ( dev-db/postgresql ) |
|
38 |
- mysql? ( dev-db/mysql )" |
|
39 |
- |
|
40 |
-PROVIDE="virtual/jabber-server" |
|
41 |
-S=${WORKDIR}/${P}/src |
|
42 |
- |
|
43 |
-src_unpack() { |
|
44 |
- unpack ${A} |
|
45 |
- MYSQL_P=$(best_version dev-db/mysql) |
|
46 |
- MYSQL_PV=${MYSQL_P/dev-db\/mysql-/} |
|
47 |
- |
|
48 |
- # |
|
49 |
- # If we have to work with MySQL 4.1 or greater, ejabberd's native |
|
50 |
- # MySQL-driver has to be patched to query "SET NAMES 'utf8'" on connecting |
|
51 |
- # the database. |
|
52 |
- # |
|
53 |
- if use mysql && \ |
|
54 |
- (( \ |
|
55 |
- [ $(get_major_version ${MYSQL_PV}) -eq 4 ] && \ |
|
56 |
- [ $(get_major_version $(get_after_major_version ${MYSQL_PV})) -ge 1] \ |
|
57 |
- ) \ |
|
58 |
- || \ |
|
59 |
- [ $(get_major_version ${MYSQL_PV}) -ge 5 ] \ |
|
60 |
- ); then |
|
61 |
- epatch ${FILESDIR}/${P}-mysql-connect-utf8.patch || die |
|
62 |
- fi |
|
63 |
- |
|
64 |
- cd ${S} |
|
65 |
- if use httpbind; then |
|
66 |
- epatch ${FILESDIR}/${P}-http_binding.patch || die |
|
67 |
- fi |
|
68 |
- |
|
69 |
- if use proxy; then |
|
70 |
- epatch ${FILESDIR}/${P}-proxy65.patch || die |
|
71 |
- fi |
|
72 |
- |
|
73 |
- epatch ${FILESDIR}/${P}-mod_irc-utf-8.patch || die |
|
74 |
-} |
|
75 |
- |
|
76 |
- |
|
77 |
-src_compile() { |
|
78 |
- local myconf |
|
79 |
- |
|
80 |
- if ! use mysql && ! use postgres && ! use odbc; then |
|
81 |
- myconf="--disable-odbc" |
|
82 |
- else |
|
83 |
- myconf="--enable-odbc" |
|
84 |
- fi |
|
85 |
- |
|
86 |
- # |
|
87 |
- # configure ejabberd |
|
88 |
- # |
|
89 |
- econf ${myconf} \ |
|
90 |
- --enable-roster-gateway-workaround \ |
|
91 |
- $(use_enable irc mod_irc) \ |
|
92 |
- $(use_enable ldap eldap) \ |
|
93 |
- $(use_enable muc mod_muc) \ |
|
94 |
- $(use_enable pubsub mod_pubsub) \ |
|
95 |
- $(use_enable ssl tls) \ |
|
96 |
- $(use_enable web web) \ |
|
97 |
- || die "econf failed" |
|
98 |
- |
|
99 |
- # |
|
100 |
- # Build ejabberd core |
|
101 |
- # |
|
102 |
- emake || die "compiling ejabberd core failed" |
|
103 |
-} |
|
104 |
- |
|
105 |
-src_install() { |
|
106 |
- # |
|
107 |
- # Install ejabberd |
|
108 |
- # |
|
109 |
- make \ |
|
110 |
- DESTDIR=${D} \ |
|
111 |
- EJABBERDDIR=${D}/usr/$(get_libdir)/erlang/lib/${P} \ |
|
112 |
- ETCDIR=${D}${JABBER_ETC} \ |
|
113 |
- LOGDIR=${D}${JABBER_LOG} \ |
|
114 |
- install \ |
|
115 |
- || die "install failed" |
|
116 |
- |
|
117 |
- |
|
118 |
- insinto /usr/share/doc/${PF} |
|
119 |
- use postgres && doins odbc/pg.sql |
|
120 |
- use mysql && doins odbc/mysql.sql |
|
121 |
- dodoc doc/release_notes_${PV}.txt |
|
122 |
- dohtml doc/*.{html,png} |
|
123 |
- |
|
124 |
- |
|
125 |
- use postgres && { |
|
126 |
- pa="-pa /usr/$(get_libdir)/erlang/lib/${E_PGSQL}/ebin" |
|
127 |
- } |
|
128 |
- |
|
129 |
- use mysql && { |
|
130 |
- pa=${pa}" -pa /usr/$(get_libdir)/erlang/lib/${E_MYSQL}/ebin" |
|
131 |
- } |
|
132 |
- |
|
133 |
- # |
|
134 |
- # Create /usr/bin/ejabberd |
|
135 |
- # |
|
136 |
- cat <<EOF > ${T}/ejabberd |
|
137 |
-#!/bin/bash |
|
138 |
- |
|
139 |
-erl -pa /usr/$(get_libdir)/erlang/lib/${P}/ebin \\ |
|
140 |
- ${pa} \\ |
|
141 |
- -sname ejabberd \\ |
|
142 |
- -s ejabberd \\ |
|
143 |
- -ejabberd config \"${JABBER_ETC}/ejabberd.cfg\" \\ |
|
144 |
- log_path \"${JABBER_LOG}/ejabberd.log\" \\ |
|
145 |
- -kernel inetrc \"${JABBER_ETC}/inetrc\" \\ |
|
146 |
- -sasl sasl_error_logger \{file,\"${JABBER_LOG}/sasl.log\"\} \\ |
|
147 |
- -mnesia dir \"${JABBER_SPOOL}\" \\ |
|
148 |
- \$@ |
|
149 |
-EOF |
|
150 |
- |
|
151 |
- # |
|
152 |
- # Create /usr/bin/ejabberdctl |
|
153 |
- # |
|
154 |
- cat <<EOF > ${T}/ejabberdctl |
|
155 |
-#!/bin/sh |
|
156 |
- |
|
157 |
-exec env HOME=${JABBER_RUN} \\ |
|
158 |
- erl -pa /usr/$(get_libdir)/erlang/lib/${P}/ebin \\ |
|
159 |
- ${pa} \\ |
|
160 |
- -noinput \\ |
|
161 |
- -sname ejabberdctl \\ |
|
162 |
- -s ejabberd_ctl \\ |
|
163 |
- -extra \$@ |
|
164 |
-EOF |
|
165 |
- |
|
166 |
- dobin ${T}/ejabberdctl |
|
167 |
- dobin ${T}/ejabberd |
|
168 |
- |
|
169 |
- newinitd ${FILESDIR}/${P}.initd ${PN} |
|
170 |
- newconfd ${FILESDIR}/${P}.confd ${PN} |
|
171 |
- |
|
172 |
- insinto ${JABBER_ETC} |
|
173 |
- if use ssl; then |
|
174 |
- docert ssl |
|
175 |
- rm -f ${D}${JABBER_ETC}/ssl.{crt,csr,key} |
|
176 |
- fowners jabber:jabber ${JABBER_ETC}/ssl.pem |
|
177 |
- fi |
|
178 |
- doins ${FILESDIR}/inetrc |
|
179 |
-} |
|
180 |
- |
|
181 |
-pkg_postinst() { |
|
182 |
- if [ ! -e ${JABBER_ETC}/ejabberd.cfg ] |
|
183 |
- then |
|
184 |
- einfo "Configuration file has been installed in ${JABBER_ETC}/ejabberd.cfg." |
|
185 |
- einfo "Edit it according to your needs. For configuration instructions," |
|
186 |
- einfo "please see /usr/share/doc/${PF}/html/guide.html" |
|
187 |
- fi |
|
188 |
- if use ssl ; then |
|
189 |
- einfo "A script to generate a ssl key has been installed in" |
|
190 |
- einfo "${JABBER_ETC}/self-cert.sh . Use it and change the config file to" |
|
191 |
- einfo "point to the full path" |
|
192 |
- fi |
|
193 |
- if ! use web ; then |
|
194 |
- einfo "The web USE flag is off, this will disable the web admin interface," |
|
195 |
- einfo "if this was not the intention then add web to your USE flags." |
|
196 |
- fi |
|
197 |
-} |
... | ... |
@@ -1,182 +0,0 @@ |
1 |
-# Copyright 2005-2006 BreakMyGentoo.net |
|
2 |
-# Distributed under the terms of the GNU General Public License v2 |
|
3 |
-# $Header: $ |
|
4 |
- |
|
5 |
-inherit eutils multilib ssl-cert versionator |
|
6 |
- |
|
7 |
-JABBER_ETC="/etc/jabber" |
|
8 |
-JABBER_RUN="/var/run/jabber" |
|
9 |
-JABBER_SPOOL="/var/spool/jabber" |
|
10 |
-JABBER_LOG="/var/log/jabber" |
|
11 |
- |
|
12 |
-E_MYSQL_V="0.1" |
|
13 |
-E_MYSQL_N="mysql" |
|
14 |
-E_MYSQL=${E_MYSQL_N}-${E_MYSQL_V} |
|
15 |
- |
|
16 |
-E_PGSQL_V="0.0.1" |
|
17 |
-E_PGSQL_N="pgsql-cvs" |
|
18 |
-E_PGSQL=${E_PGSQL_N}-${E_PGSQL_V} |
|
19 |
- |
|
20 |
-DESCRIPTION="The Erlang Jabber Daemon" |
|
21 |
-HOMEPAGE="http://ejabberd.jabber.ru/" |
|
22 |
-SRC_URI="http://process-one.net/en/projects/ejabberd/download/${PV}/${P}.tar.gz" |
|
23 |
-LICENSE="GPL-2" |
|
24 |
-SLOT="0" |
|
25 |
-KEYWORDS="~x86 amd64" |
|
26 |
-IUSE="${IUSE} irc ldap muc odbc postgres pubsub web mysql httpbind proxy" |
|
27 |
- |
|
28 |
-DEPEND="${RDEPEND} |
|
29 |
- >=net-im/jabber-base-0.00 |
|
30 |
- >=dev-libs/expat-1.95 |
|
31 |
- >=dev-lang/erlang-10.2.0 |
|
32 |
- odbc? ( dev-db/unixODBC ) |
|
33 |
- ldap? ( =net-nds/openldap-2* ) |
|
34 |
- postgres? ( =dev-erl/${E_PGSQL} ) |
|
35 |
- mysql? ( =dev-erl/${E_MYSQL} )" |
|
36 |
- |
|
37 |
-RDEPEND="postgres? ( dev-db/postgresql ) |
|
38 |
- mysql? ( dev-db/mysql )" |
|
39 |
- |
|
40 |
-PROVIDE="virtual/jabber-server" |
|
41 |
-S=${WORKDIR}/${P}/src |
|
42 |
- |
|
43 |
-src_unpack() { |
|
44 |
- unpack ${A} |
|
45 |
- MYSQL_P=$(best_version dev-db/mysql) |
|
46 |
- MYSQL_PV=${MYSQL_P/dev-db\/mysql-/} |
|
47 |
- |
|
48 |
- |
|
49 |
- cd ${S} |
|
50 |
- if use httpbind; then |
|
51 |
- epatch ${FILESDIR}/${P}-http_binding.patch || die |
|
52 |
- fi |
|
53 |
- |
|
54 |
- if use proxy; then |
|
55 |
- epatch ${FILESDIR}/${P}-proxy65.patch || die |
|
56 |
- fi |
|
57 |
- |
|
58 |
- epatch ${FILESDIR}/${P}-mod_irc-utf-8.patch || die |
|
59 |
-} |
|
60 |
- |
|
61 |
- |
|
62 |
-src_compile() { |
|
63 |
- local myconf |
|
64 |
- |
|
65 |
- if ! use mysql && ! use postgres && ! use odbc; then |
|
66 |
- myconf="--disable-odbc" |
|
67 |
- else |
|
68 |
- myconf="--enable-odbc" |
|
69 |
- fi |
|
70 |
- |
|
71 |
- # |
|
72 |
- # configure ejabberd |
|
73 |
- # |
|
74 |
- econf ${myconf} \ |
|
75 |
- --enable-roster-gateway-workaround \ |
|
76 |
- $(use_enable irc mod_irc) \ |
|
77 |
- $(use_enable ldap eldap) \ |
|
78 |
- $(use_enable muc mod_muc) \ |
|
79 |
- $(use_enable pubsub mod_pubsub) \ |
|
80 |
- $(use_enable ssl tls) \ |
|
81 |
- $(use_enable web web) \ |
|
82 |
- || die "econf failed" |
|
83 |
- |
|
84 |
- # |
|
85 |
- # Build ejabberd core |
|
86 |
- # |
|
87 |
- emake || die "compiling ejabberd core failed" |
|
88 |
-} |
|
89 |
- |
|
90 |
-src_install() { |
|
91 |
- # |
|
92 |
- # Install ejabberd |
|
93 |
- # |
|
94 |
- make \ |
|
95 |
- DESTDIR=${D} \ |
|
96 |
- EJABBERDDIR=${D}/usr/$(get_libdir)/erlang/lib/${P} \ |
|
97 |
- ETCDIR=${D}${JABBER_ETC} \ |
|
98 |
- LOGDIR=${D}${JABBER_LOG} \ |
|
99 |
- install \ |
|
100 |
- || die "install failed" |
|
101 |
- |
|
102 |
- |
|
103 |
- insinto /usr/share/doc/${PF} |
|
104 |
- use postgres && doins odbc/pg.sql |
|
105 |
- use mysql && doins odbc/mysql.sql |
|
106 |
- dodoc doc/release_notes_${PV}.txt |
|
107 |
- dohtml doc/*.{html,png} |
|
108 |
- |
|
109 |
- |
|
110 |
- use postgres && { |
|
111 |
- pa="-pa /usr/$(get_libdir)/erlang/lib/${E_PGSQL}/ebin" |
|
112 |
- } |
|
113 |
- |
|
114 |
- use mysql && { |
|
115 |
- pa=${pa}" -pa /usr/$(get_libdir)/erlang/lib/${E_MYSQL}/ebin" |
|
116 |
- } |
|
117 |
- |
|
118 |
- # |
|
119 |
- # Create /usr/bin/ejabberd |
|
120 |
- # |
|
121 |
- cat <<EOF > ${T}/ejabberd |
|
122 |
-#!/bin/bash |
|
123 |
- |
|
124 |
-erl -pa /usr/$(get_libdir)/erlang/lib/${P}/ebin \\ |
|
125 |
- ${pa} \\ |
|
126 |
- -sname ejabberd \\ |
|
127 |
- -s ejabberd \\ |
|
128 |
- -ejabberd config \"${JABBER_ETC}/ejabberd.cfg\" \\ |
|
129 |
- log_path \"${JABBER_LOG}/ejabberd.log\" \\ |
|
130 |
- -kernel inetrc \"${JABBER_ETC}/inetrc\" \\ |
|
131 |
- -sasl sasl_error_logger \{file,\"${JABBER_LOG}/sasl.log\"\} \\ |
|
132 |
- -mnesia dir \"${JABBER_SPOOL}\" \\ |
|
133 |
- \$@ |
|
134 |
-EOF |
|
135 |
- |
|
136 |
- # |
|
137 |
- # Create /usr/bin/ejabberdctl |
|
138 |
- # |
|
139 |
- cat <<EOF > ${T}/ejabberdctl |
|
140 |
-#!/bin/sh |
|
141 |
- |
|
142 |
-exec env HOME=${JABBER_RUN} \\ |
|
143 |
- erl -pa /usr/$(get_libdir)/erlang/lib/${P}/ebin \\ |
|
144 |
- ${pa} \\ |
|
145 |
- -noinput \\ |
|
146 |
- -sname ejabberdctl \\ |
|
147 |
- -s ejabberd_ctl \\ |
|
148 |
- -extra \$@ |
|
149 |
-EOF |
|
150 |
- |
|
151 |
- dobin ${T}/ejabberdctl |
|
152 |
- dobin ${T}/ejabberd |
|
153 |
- |
|
154 |
- newinitd ${FILESDIR}/${P}.initd ${PN} |
|
155 |
- newconfd ${FILESDIR}/${P}.confd ${PN} |
|
156 |
- |
|
157 |
- insinto ${JABBER_ETC} |
|
158 |
- if use ssl; then |
|
159 |
- docert ssl |
|
160 |
- rm -f ${D}${JABBER_ETC}/ssl.{crt,csr,key} |
|
161 |
- fowners jabber:jabber ${JABBER_ETC}/ssl.pem |
|
162 |
- fi |
|
163 |
- doins ${FILESDIR}/inetrc |
|
164 |
-} |
|
165 |
- |
|
166 |
-pkg_postinst() { |
|
167 |
- if [ ! -e ${JABBER_ETC}/ejabberd.cfg ] |
|
168 |
- then |
|
169 |
- einfo "Configuration file has been installed in ${JABBER_ETC}/ejabberd.cfg." |
|
170 |
- einfo "Edit it according to your needs. For configuration instructions," |
|
171 |
- einfo "please see /usr/share/doc/${PF}/html/guide.html" |
|
172 |
- fi |
|
173 |
- if use ssl ; then |
|
174 |
- einfo "A script to generate a ssl key has been installed in" |
|
175 |
- einfo "${JABBER_ETC}/self-cert.sh . Use it and change the config file to" |
|
176 |
- einfo "point to the full path" |
|
177 |
- fi |
|
178 |
- if ! use web ; then |
|
179 |
- einfo "The web USE flag is off, this will disable the web admin interface," |
|
180 |
- einfo "if this was not the intention then add web to your USE flags." |
|
181 |
- fi |
|
182 |
-} |
... | ... |
@@ -1,855 +0,0 @@ |
1 |
-Index: src/ejabberd.cfg.example |
|
2 |
-=================================================================== |
|
3 |
---- src/ejabberd.cfg.example (Revision 565) |
|
4 |
-+++ src/ejabberd.cfg.example (Arbeitskopie) |
|
5 |
-@@ -124,7 +124,7 @@ |
|
6 |
- {5269, ejabberd_s2s_in, [{shaper, s2s_shaper}, |
|
7 |
- {max_stanza_size, 131072} |
|
8 |
- ]}, |
|
9 |
-- {5280, ejabberd_http, [http_poll, web_admin]}, |
|
10 |
-+ {5280, ejabberd_http, [http_poll, http_bind, web_admin]}, |
|
11 |
- {8888, ejabberd_service, [{access, all}, |
|
12 |
- {hosts, ["icq.localhost", "sms.localhost"], |
|
13 |
- [{password, "secret"}]}]} |
|
14 |
-Index: src/web/Makefile.in |
|
15 |
-=================================================================== |
|
16 |
---- src/web/Makefile.in (Revision 565) |
|
17 |
-+++ src/web/Makefile.in (Arbeitskopie) |
|
18 |
-@@ -15,7 +15,8 @@ |
|
19 |
- $(OUTDIR)/ejabberd_http.beam \ |
|
20 |
- $(OUTDIR)/ejabberd_web.beam \ |
|
21 |
- $(OUTDIR)/ejabberd_web_admin.beam \ |
|
22 |
-- $(OUTDIR)/ejabberd_http_poll.beam |
|
23 |
-+ $(OUTDIR)/ejabberd_http_poll.beam \ |
|
24 |
-+ $(OUTDIR)/ejabberd_http_bind.beam |
|
25 |
- |
|
26 |
- all: $(OBJS) |
|
27 |
- |
|
28 |
-Index: src/web/ejabberd_http_bind.erl |
|
29 |
-=================================================================== |
|
30 |
---- src/web/ejabberd_http_bind.erl (Revision 0) |
|
31 |
-+++ src/web/ejabberd_http_bind.erl (Revision 0) |
|
32 |
-@@ -0,0 +1,654 @@ |
|
33 |
-+%%%---------------------------------------------------------------------- |
|
34 |
-+%%% File : ejabberd_http_bind.erl |
|
35 |
-+%%% Author : Stefan Strigler <steve@zeank.in-berlin.de> |
|
36 |
-+%%% Purpose : HTTP Binding support (JEP-0124) |
|
37 |
-+%%% Created : 21 Sep 2005 by Stefan Strigler <steve@zeank.in-berlin.de> |
|
38 |
-+%%% Id : $Id: ejabberd_http_bind.erl,v 1.2 2006/01/16 10:47:50 zeank Exp $ |
|
39 |
-+%%%---------------------------------------------------------------------- |
|
40 |
-+ |
|
41 |
-+-module(ejabberd_http_bind). |
|
42 |
-+-author('steve@zeank.in-berlin.de'). |
|
43 |
-+-vsn('$Revision: 1.2 $ '). |
|
44 |
-+ |
|
45 |
-+-behaviour(gen_fsm). |
|
46 |
-+ |
|
47 |
-+%% External exports |
|
48 |
-+-export([start_link/2, |
|
49 |
-+ init/1, |
|
50 |
-+ handle_event/3, |
|
51 |
-+ handle_sync_event/4, |
|
52 |
-+ code_change/4, |
|
53 |
-+ handle_info/3, |
|
54 |
-+ terminate/3, |
|
55 |
-+ send/2, |
|
56 |
-+ setopts/2, |
|
57 |
-+ controlling_process/2, |
|
58 |
-+ close/1, |
|
59 |
-+ process_request/1]). |
|
60 |
-+ |
|
61 |
-+%-define(ejabberd_debug, true). |
|
62 |
-+ |
|
63 |
-+-include("ejabberd.hrl"). |
|
64 |
-+-include("jlib.hrl"). |
|
65 |
-+-include("ejabberd_http.hrl"). |
|
66 |
-+ |
|
67 |
-+-record(http_bind, {id, pid, hold, wait}). |
|
68 |
-+ |
|
69 |
-+%% http binding request |
|
70 |
-+-record(hbr, {rid, |
|
71 |
-+ key, |
|
72 |
-+ in, |
|
73 |
-+ out}). |
|
74 |
-+ |
|
75 |
-+-record(state, {id, |
|
76 |
-+ rid = error, |
|
77 |
-+ key, |
|
78 |
-+ output = "", |
|
79 |
-+ input = "", |
|
80 |
-+ waiting_input = false, |
|
81 |
-+ last_receiver, |
|
82 |
-+ last_poll, |
|
83 |
-+ ctime = 0, |
|
84 |
-+ timer, |
|
85 |
-+ req_list = [] % list of requests |
|
86 |
-+ }). |
|
87 |
-+ |
|
88 |
-+ |
|
89 |
-+%-define(DBGFSM, true). |
|
90 |
-+ |
|
91 |
-+-ifdef(DBGFSM). |
|
92 |
-+-define(FSMOPTS, [{debug, [trace]}]). |
|
93 |
-+-else. |
|
94 |
-+-define(FSMOPTS, []). |
|
95 |
-+-endif. |
|
96 |
-+ |
|
97 |
-+-define(MAX_REQUESTS, 2). % number of simultaneous requests |
|
98 |
-+-define(MIN_POLLING, "2"). % don't poll faster than that or we will shoot you |
|
99 |
-+-define(MAX_WAIT, 60). % max num of secs to keep a request on hold |
|
100 |
-+-define(MAX_INACTIVITY, 30000). % msecs to wait before terminating idle sessions |
|
101 |
-+-define(CT, {"Content-Type", "text/xml; charset=utf-8"}). |
|
102 |
-+-define(BAD_REQUEST, ?CT). |
|
103 |
-+ |
|
104 |
-+ |
|
105 |
-+%%%---------------------------------------------------------------------- |
|
106 |
-+%%% API |
|
107 |
-+%%%---------------------------------------------------------------------- |
|
108 |
-+start(ID, Key) -> |
|
109 |
-+ mnesia:create_table(http_bind, |
|
110 |
-+ [{ram_copies, [node()]}, |
|
111 |
-+ {attributes, record_info(fields, http_bind)}]), |
|
112 |
-+ supervisor:start_child(ejabberd_http_bind_sup, [ID, Key]). |
|
113 |
-+ |
|
114 |
-+start_link(ID, Key) -> |
|
115 |
-+ gen_fsm:start_link(?MODULE, [ID, Key], ?FSMOPTS). |
|
116 |
-+ |
|
117 |
-+send({http_bind, FsmRef}, Packet) -> |
|
118 |
-+ gen_fsm:sync_send_all_state_event(FsmRef, {send, Packet}). |
|
119 |
-+ |
|
120 |
-+setopts({http_bind, FsmRef}, Opts) -> |
|
121 |
-+ case lists:member({active, once}, Opts) of |
|
122 |
-+ true -> |
|
123 |
-+ gen_fsm:sync_send_all_state_event(FsmRef, activate); |
|
124 |
-+ _ -> |
|
125 |
-+ ok |
|
126 |
-+ end. |
|
127 |
-+ |
|
128 |
-+controlling_process(_Socket, _Pid) -> |
|
129 |
-+ ok. |
|
130 |
-+ |
|
131 |
-+close({http_bind, FsmRef}) -> |
|
132 |
-+ catch gen_fsm:sync_send_all_state_event(FsmRef, close). |
|
133 |
-+ |
|
134 |
-+ |
|
135 |
-+process_request(#request{path = [], |
|
136 |
-+ data = Data}) -> |
|
137 |
-+ case catch parse_request(Data) of |
|
138 |
-+ {ok, ID1, RID, Key, NewKey, Attrs, Packet} -> |
|
139 |
-+ XmppDomain = xml:get_attr_s("to",Attrs), |
|
140 |
-+ if |
|
141 |
-+ (ID1 == "") and (XmppDomain == "") -> |
|
142 |
-+ {200, [?CT], "<body type='terminate' condition='improper-addressing' xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
143 |
-+ true -> |
|
144 |
-+ ID = if |
|
145 |
-+ (ID1 == "") -> |
|
146 |
-+ %% create new session |
|
147 |
-+ NewID = sha:sha(term_to_binary({now(), make_ref()})), |
|
148 |
-+ {ok, Pid} = start(NewID, Key), |
|
149 |
-+ Wait = case |
|
150 |
-+ string:to_integer(xml:get_attr_s("wait",Attrs)) |
|
151 |
-+ of |
|
152 |
-+ {error, _} -> |
|
153 |
-+ ?MAX_WAIT; |
|
154 |
-+ {CWait, _} -> |
|
155 |
-+ if |
|
156 |
-+ (CWait > ?MAX_WAIT) -> |
|
157 |
-+ ?MAX_WAIT; |
|
158 |
-+ true -> |
|
159 |
-+ CWait |
|
160 |
-+ end |
|
161 |
-+ end, |
|
162 |
-+ Hold = case |
|
163 |
-+ string:to_integer(xml:get_attr_s("hold",Attrs)) |
|
164 |
-+ of |
|
165 |
-+ {error, _} -> |
|
166 |
-+ (?MAX_REQUESTS - 1); |
|
167 |
-+ {CHold, _} -> |
|
168 |
-+ if |
|
169 |
-+ (CHold > (?MAX_REQUESTS - 1)) -> |
|
170 |
-+ (?MAX_REQUESTS - 1); |
|
171 |
-+ true -> |
|
172 |
-+ CHold |
|
173 |
-+ end |
|
174 |
-+ end, |
|
175 |
-+ mnesia:transaction( |
|
176 |
-+ fun() -> |
|
177 |
-+ mnesia:write(#http_bind{id = NewID, |
|
178 |
-+ pid = Pid, |
|
179 |
-+ wait = Wait, |
|
180 |
-+ hold = Hold}) |
|
181 |
-+ end), |
|
182 |
-+ InPacket = if |
|
183 |
-+ (XmppDomain /= "") -> |
|
184 |
-+ ["<stream:stream to='", |
|
185 |
-+ XmppDomain, |
|
186 |
-+ "' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>"]; |
|
187 |
-+ true -> |
|
188 |
-+ "" |
|
189 |
-+ end, |
|
190 |
-+ NewID; |
|
191 |
-+ true -> |
|
192 |
-+ %% old session |
|
193 |
-+ Type = xml:get_attr_s("type",Attrs), |
|
194 |
-+ Wait = ?MAX_WAIT, |
|
195 |
-+ Hold = (?MAX_REQUESTS - 1), |
|
196 |
-+ if |
|
197 |
-+ (Type == "terminate") -> |
|
198 |
-+ %% terminate session |
|
199 |
-+ InPacket = Packet ++ "</stream:stream>"; |
|
200 |
-+ true -> |
|
201 |
-+ InPacket = Packet |
|
202 |
-+ end, |
|
203 |
-+ ID1 |
|
204 |
-+ end, |
|
205 |
-+ ?DEBUG("~n InPacket: ~s ~n", [InPacket]), |
|
206 |
-+ case http_put(ID, RID, Key, NewKey, Hold, InPacket) of |
|
207 |
-+ {error, not_exists} -> |
|
208 |
-+ {404, [?BAD_REQUEST], ""}; |
|
209 |
-+ {error, bad_key} -> |
|
210 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
211 |
-+ [] -> |
|
212 |
-+ {404, [?BAD_REQUEST], ""}; |
|
213 |
-+ [#http_bind{pid = FsmRef}] -> |
|
214 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop), |
|
215 |
-+ {404, [?BAD_REQUEST], ""} |
|
216 |
-+ end; |
|
217 |
-+ {error, polling_too_frequently} -> |
|
218 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
219 |
-+ [] -> %% unlikely! (?) |
|
220 |
-+ {404, [?BAD_REQUEST], ""}; |
|
221 |
-+ [#http_bind{pid = FsmRef}] -> |
|
222 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop), |
|
223 |
-+ {403, [?BAD_REQUEST], ""} |
|
224 |
-+ end; |
|
225 |
-+ {repeat, OutPacket} -> |
|
226 |
-+ ?DEBUG("http_put said 'repeat!' ...", []), |
|
227 |
-+ send_outpacket(ID, OutPacket); |
|
228 |
-+ ok -> |
|
229 |
-+ receive_loop(ID,ID1,RID,Wait,Hold,Attrs) |
|
230 |
-+ end |
|
231 |
-+ end; |
|
232 |
-+ _ -> |
|
233 |
-+ {400, [?BAD_REQUEST], ""} |
|
234 |
-+ end; |
|
235 |
-+process_request(_Request) -> |
|
236 |
-+ {400, [], {xmlelement, "h1", [], |
|
237 |
-+ [{xmlcdata, "400 Bad Request"}]}}. |
|
238 |
-+ |
|
239 |
-+receive_loop(ID,ID1,RID,Wait,Hold,Attrs) -> |
|
240 |
-+ receive |
|
241 |
-+ after 100 -> ok |
|
242 |
-+ end, |
|
243 |
-+ prepare_response(ID,ID1,RID,Wait,Hold,Attrs). |
|
244 |
-+ |
|
245 |
-+prepare_response(ID,ID1,RID,Wait,Hold,Attrs) -> |
|
246 |
-+ case http_get(ID,RID) of |
|
247 |
-+ {error, not_exists} -> |
|
248 |
-+ {404, [?BAD_REQUEST], ""}; |
|
249 |
-+ {ok, keep_on_hold} -> |
|
250 |
-+ receive_loop(ID,ID1,RID,Wait,Hold,Attrs); |
|
251 |
-+ {ok, OutPacket} -> |
|
252 |
-+ if |
|
253 |
-+ ID == ID1 -> |
|
254 |
-+ send_outpacket(ID, OutPacket); |
|
255 |
-+ true -> |
|
256 |
-+ To = xml:get_attr_s("to",Attrs), |
|
257 |
-+ case xml_stream:parse_element(OutPacket++"</stream:stream>") of |
|
258 |
-+ El when element(1, El) == xmlelement -> |
|
259 |
-+ {xmlelement, _, OutAttrs, _} = El, |
|
260 |
-+ AuthID = xml:get_attr_s("id", OutAttrs), |
|
261 |
-+ StreamError = false; |
|
262 |
-+ {error, _} -> |
|
263 |
-+ AuthID = "", |
|
264 |
-+ StreamError = true |
|
265 |
-+ end, |
|
266 |
-+ if |
|
267 |
-+ To == "" -> |
|
268 |
-+ {200, [?CT], "<body type='terminate' condition='improper-addressing' xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
269 |
-+ StreamError == true -> |
|
270 |
-+ {200, [?CT], "<body type='terminate' condition='host-unknown' xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
271 |
-+ true -> |
|
272 |
-+ {200, [?CT], |
|
273 |
-+ xml:element_to_string( |
|
274 |
-+ {xmlelement,"body", |
|
275 |
-+ [{"xmlns", |
|
276 |
-+ "http://jabber.org/protocol/httpbind"}, |
|
277 |
-+ {"sid",ID}, |
|
278 |
-+ {"wait", integer_to_list(Wait)}, |
|
279 |
-+ {"requests", integer_to_list(Hold+1)}, |
|
280 |
-+ {"inactivity", integer_to_list(trunc(?MAX_INACTIVITY/1000))}, |
|
281 |
-+ {"polling", ?MIN_POLLING}, |
|
282 |
-+ {"authid", AuthID} |
|
283 |
-+ ],[]})} |
|
284 |
-+ end |
|
285 |
-+ end |
|
286 |
-+ end. |
|
287 |
-+ |
|
288 |
-+send_outpacket(ID, OutPacket) -> |
|
289 |
-+ case OutPacket of |
|
290 |
-+ "" -> |
|
291 |
-+ {200, [?CT], "<body xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
292 |
-+ "</stream:stream>" -> |
|
293 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
294 |
-+ [#http_bind{pid = FsmRef}] -> |
|
295 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop) |
|
296 |
-+ end, |
|
297 |
-+ {200, [?CT], "<body xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
298 |
-+ _ -> |
|
299 |
-+ case xml_stream:parse_element("<body>" |
|
300 |
-+ ++ OutPacket |
|
301 |
-+ ++ "</body>") |
|
302 |
-+ of |
|
303 |
-+ El when element(1, El) == xmlelement -> |
|
304 |
-+ {xmlelement, _, _, OEls} = El, |
|
305 |
-+ TypedEls = [xml:replace_tag_attr("xmlns","jabber:client",OEl) || |
|
306 |
-+ OEl <- OEls], |
|
307 |
-+ ?DEBUG(" --- outgoing data --- ~n~s~n --- outgoing data END --- ~n", |
|
308 |
-+ [xml:element_to_string( |
|
309 |
-+ {xmlelement,"body", |
|
310 |
-+ [{"xmlns", |
|
311 |
-+ "http://jabber.org/protocol/httpbind"}], |
|
312 |
-+ TypedEls})] |
|
313 |
-+ ), |
|
314 |
-+ {200, [?CT], |
|
315 |
-+ xml:element_to_string( |
|
316 |
-+ {xmlelement,"body", |
|
317 |
-+ [{"xmlns", |
|
318 |
-+ "http://jabber.org/protocol/httpbind"}], |
|
319 |
-+ TypedEls})}; |
|
320 |
-+ {error, _} -> |
|
321 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
322 |
-+ [#http_bind{pid = FsmRef}] -> |
|
323 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop) |
|
324 |
-+ end, |
|
325 |
-+ {200, [?CT], |
|
326 |
-+ "<body type='terminate' condition='internal-server-error' xmlns='http://jabber.org/protocol/httpbind'/>"} |
|
327 |
-+ end |
|
328 |
-+ end. |
|
329 |
-+ |
|
330 |
-+%%%---------------------------------------------------------------------- |
|
331 |
-+%%% Callback functions from gen_fsm |
|
332 |
-+%%%---------------------------------------------------------------------- |
|
333 |
-+ |
|
334 |
-+%%---------------------------------------------------------------------- |
|
335 |
-+%% Func: init/1 |
|
336 |
-+%% Returns: {ok, StateName, StateData} | |
|
337 |
-+%% {ok, StateName, StateData, Timeout} | |
|
338 |
-+%% ignore | |
|
339 |
-+%% {stop, StopReason} |
|
340 |
-+%%---------------------------------------------------------------------- |
|
341 |
-+init([ID, Key]) -> |
|
342 |
-+ ?INFO_MSG("started: ~p", [{ID, Key}]), |
|
343 |
-+ Opts = [], % TODO |
|
344 |
-+ {ok, C2SPid} = ejabberd_c2s:start({?MODULE, {http_bind, self()}}, Opts), |
|
345 |
-+ ejabberd_c2s:become_controller(C2SPid), |
|
346 |
-+ Timer = erlang:start_timer(?MAX_INACTIVITY, self(), []), |
|
347 |
-+ {ok, loop, #state{id = ID, |
|
348 |
-+ key = Key, |
|
349 |
-+ timer = Timer}}. |
|
350 |
-+ |
|
351 |
-+%%---------------------------------------------------------------------- |
|
352 |
-+%% Func: StateName/2 |
|
353 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
354 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
355 |
-+%% {stop, Reason, NewStateData} |
|
356 |
-+%%---------------------------------------------------------------------- |
|
357 |
-+ |
|
358 |
-+ |
|
359 |
-+%%---------------------------------------------------------------------- |
|
360 |
-+%% Func: StateName/3 |
|
361 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
362 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
363 |
-+%% {reply, Reply, NextStateName, NextStateData} | |
|
364 |
-+%% {reply, Reply, NextStateName, NextStateData, Timeout} | |
|
365 |
-+%% {stop, Reason, NewStateData} | |
|
366 |
-+%% {stop, Reason, Reply, NewStateData} |
|
367 |
-+%%---------------------------------------------------------------------- |
|
368 |
-+%state_name(Event, From, StateData) -> |
|
369 |
-+% Reply = ok, |
|
370 |
-+% {reply, Reply, state_name, StateData}. |
|
371 |
-+ |
|
372 |
-+%%---------------------------------------------------------------------- |
|
373 |
-+%% Func: handle_event/3 |
|
374 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
375 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
376 |
-+%% {stop, Reason, NewStateData} |
|
377 |
-+%%---------------------------------------------------------------------- |
|
378 |
-+handle_event(_Event, StateName, StateData) -> |
|
379 |
-+ {next_state, StateName, StateData}. |
|
380 |
-+ |
|
381 |
-+%%---------------------------------------------------------------------- |
|
382 |
-+%% Func: handle_sync_event/4 |
|
383 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
384 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
385 |
-+%% {reply, Reply, NextStateName, NextStateData} | |
|
386 |
-+%% {reply, Reply, NextStateName, NextStateData, Timeout} | |
|
387 |
-+%% {stop, Reason, NewStateData} | |
|
388 |
-+%% {stop, Reason, Reply, NewStateData} |
|
389 |
-+%%---------------------------------------------------------------------- |
|
390 |
-+handle_sync_event({send, Packet}, _From, StateName, StateData) -> |
|
391 |
-+ Output = [StateData#state.output | Packet], |
|
392 |
-+ Reply = ok, |
|
393 |
-+ {reply, Reply, StateName, StateData#state{output = Output}}; |
|
394 |
-+ |
|
395 |
-+handle_sync_event(activate, From, StateName, StateData) -> |
|
396 |
-+ case StateData#state.input of |
|
397 |
-+ "" -> |
|
398 |
-+ {reply, ok, StateName, StateData#state{waiting_input = From}}; |
|
399 |
-+ Input -> |
|
400 |
-+ From ! {tcp, {http_bind, self()}, list_to_binary(Input)}, |
|
401 |
-+ {reply, ok, StateName, StateData#state{input = "", |
|
402 |
-+ waiting_input = false, |
|
403 |
-+ last_receiver = From}} |
|
404 |
-+ end; |
|
405 |
-+ |
|
406 |
-+handle_sync_event(stop, _From, _StateName, StateData) -> |
|
407 |
-+ Reply = ok, |
|
408 |
-+ {stop, normal, Reply, StateData}; |
|
409 |
-+ |
|
410 |
-+handle_sync_event({http_put, RID, Key, NewKey, Hold, Packet}, |
|
411 |
-+ _From, StateName, StateData) -> |
|
412 |
-+ %% check if RID valid |
|
413 |
-+ RidAllow = case RID of |
|
414 |
-+ error -> |
|
415 |
-+ false; |
|
416 |
-+ _ -> |
|
417 |
-+ case StateData#state.rid of |
|
418 |
-+ error -> |
|
419 |
-+ %% first request - nothing saved so far |
|
420 |
-+ true; |
|
421 |
-+ OldRID -> |
|
422 |
-+ ?DEBUG("state.rid/cur rid: ~p/~p", [OldRID, RID]), |
|
423 |
-+ if |
|
424 |
-+ (OldRID < RID) and (RID =< (OldRID + Hold + 1)) -> |
|
425 |
-+ true; |
|
426 |
-+ (RID =< OldRID) and (RID > OldRID - Hold - 1) -> |
|
427 |
-+ repeat; |
|
428 |
-+ true -> |
|
429 |
-+ false |
|
430 |
-+ end |
|
431 |
-+ end |
|
432 |
-+ end, |
|
433 |
-+ %% check if key valid |
|
434 |
-+ KeyAllow = case RidAllow of |
|
435 |
-+ repeat -> |
|
436 |
-+ true; |
|
437 |
-+ false -> |
|
438 |
-+ false; |
|
439 |
-+ true -> |
|
440 |
-+ case StateData#state.key of |
|
441 |
-+ "" -> |
|
442 |
-+ true; |
|
443 |
-+ OldKey -> |
|
444 |
-+ NextKey = httpd_util:to_lower(hex( |
|
445 |
-+ binary_to_list(crypto:sha(Key)))), |
|
446 |
-+ ?DEBUG("Key/OldKey/NextKey: ~s/~s/~s", [Key, OldKey, NextKey]), |
|
447 |
-+ if |
|
448 |
-+ OldKey == NextKey -> |
|
449 |
-+ true; |
|
450 |
-+ true -> |
|
451 |
-+ ?DEBUG("wrong key: ~s",[Key]), |
|
452 |
-+ false |
|
453 |
-+ end |
|
454 |
-+ end |
|
455 |
-+ end, |
|
456 |
-+ {_,TSec,TMSec} = now(), |
|
457 |
-+ TNow = TSec*1000*1000 + TMSec, |
|
458 |
-+ LastPoll = if |
|
459 |
-+ Packet == "" -> |
|
460 |
-+ TNow; |
|
461 |
-+ true -> |
|
462 |
-+ StateData#state.last_poll |
|
463 |
-+ end, |
|
464 |
-+ {MinPoll, _} = string:to_integer(?MIN_POLLING), |
|
465 |
-+ if |
|
466 |
-+ (Packet == "") and (TNow - StateData#state.last_poll < MinPoll*1000*1000) -> |
|
467 |
-+ Reply = {error, polling_too_frequently}, |
|
468 |
-+ {reply, Reply, StateName, StateData}; |
|
469 |
-+ KeyAllow -> |
|
470 |
-+ case RidAllow of |
|
471 |
-+ false -> |
|
472 |
-+ Reply = {error, not_exists}, |
|
473 |
-+ {reply, Reply, StateName, StateData}; |
|
474 |
-+ repeat -> |
|
475 |
-+ ?DEBUG("repeating ~p", [RID]), |
|
476 |
-+ [Out | _XS] = [El#hbr.out || El <- StateData#state.req_list, El#hbr.rid == RID], |
|
477 |
-+ case Out of |
|
478 |
-+ [[] | OutPacket] -> |
|
479 |
-+ Reply = {repeat, OutPacket}; |
|
480 |
-+ _ -> |
|
481 |
-+ Reply = {repeat, Out} |
|
482 |
-+ end, |
|
483 |
-+ {reply, Reply, StateName, StateData#state{last_poll = LastPoll}}; |
|
484 |
-+ true -> |
|
485 |
-+ SaveKey = if |
|
486 |
-+ NewKey == "" -> |
|
487 |
-+ Key; |
|
488 |
-+ true -> |
|
489 |
-+ NewKey |
|
490 |
-+ end, |
|
491 |
-+ ?DEBUG(" -- SaveKey: ~s~n", [SaveKey]), |
|
492 |
-+ |
|
493 |
-+ %% save request |
|
494 |
-+ ReqList = [#hbr{rid=RID, |
|
495 |
-+ key=StateData#state.key, |
|
496 |
-+ in=StateData#state.input, |
|
497 |
-+ out=StateData#state.output |
|
498 |
-+ } | |
|
499 |
-+ [El || El <- StateData#state.req_list, |
|
500 |
-+ El#hbr.rid < RID, El#hbr.rid > (RID - 1 - Hold) ] |
|
501 |
-+ ], |
|
502 |
-+ |
|
503 |
-+ ?DEBUG("reqlist: ~p", [ReqList]), |
|
504 |
-+ |
|
505 |
-+ case StateData#state.waiting_input of |
|
506 |
-+ false -> |
|
507 |
-+ cancel_timer(StateData#state.timer), |
|
508 |
-+ Timer = erlang:start_timer(?MAX_INACTIVITY, self(), []), |
|
509 |
-+ Input = Packet ++ [StateData#state.input], |
|
510 |
-+ Reply = ok, |
|
511 |
-+ {reply, Reply, StateName, |
|
512 |
-+ StateData#state{input = Input, |
|
513 |
-+ rid = RID, |
|
514 |
-+ key = SaveKey, |
|
515 |
-+ ctime = TNow, |
|
516 |
-+ timer = Timer, |
|
517 |
-+ last_poll = LastPoll, |
|
518 |
-+ req_list = ReqList |
|
519 |
-+ }}; |
|
520 |
-+ {Receiver, _Tag} -> |
|
521 |
-+ Receiver ! {tcp, {http_bind, self()}, |
|
522 |
-+ list_to_binary(Packet)}, |
|
523 |
-+ cancel_timer(StateData#state.timer), |
|
524 |
-+ Timer = erlang:start_timer(?MAX_INACTIVITY, self(), []), |
|
525 |
-+ Reply = ok, |
|
526 |
-+ {reply, Reply, StateName, |
|
527 |
-+ StateData#state{waiting_input = false, |
|
528 |
-+ last_receiver = Receiver, |
|
529 |
-+ input = "", |
|
530 |
-+ rid = RID, |
|
531 |
-+ key = SaveKey, |
|
532 |
-+ ctime = TNow, |
|
533 |
-+ timer = Timer, |
|
534 |
-+ last_poll = LastPoll, |
|
535 |
-+ req_list = ReqList |
|
536 |
-+ }} |
|
537 |
-+ end |
|
538 |
-+ end; |
|
539 |
-+ true -> |
|
540 |
-+ Reply = {error, bad_key}, |
|
541 |
-+ {reply, Reply, StateName, StateData} |
|
542 |
-+ end; |
|
543 |
-+ |
|
544 |
-+handle_sync_event({http_get, RID, Wait, Hold}, _From, StateName, StateData) -> |
|
545 |
-+ {_,TSec,TMSec} = now(), |
|
546 |
-+ TNow = TSec*1000*1000 + TMSec, |
|
547 |
-+%% ?DEBUG("Wait/Hold/cTime/Now: ~p/~p/~p/~p", [Wait, Hold, StateData#state.ctime,TNow]), |
|
548 |
-+ cancel_timer(StateData#state.timer), |
|
549 |
-+ Timer = erlang:start_timer(?MAX_INACTIVITY, self(), []), |
|
550 |
-+ if |
|
551 |
-+ (Hold > 0) and |
|
552 |
-+ (StateData#state.output == "") and |
|
553 |
-+ ((TNow - StateData#state.ctime) < (Wait*1000*1000)) and |
|
554 |
-+ (StateData#state.rid == RID) -> |
|
555 |
-+ Output = StateData#state.output, |
|
556 |
-+ ReqList = StateData#state.req_list, |
|
557 |
-+ Reply = {ok, keep_on_hold}; |
|
558 |
-+ true -> |
|
559 |
-+ case StateData#state.output of |
|
560 |
-+ [[]| OutPacket] -> |
|
561 |
-+ Reply = {ok, OutPacket}; |
|
562 |
-+ _ -> |
|
563 |
-+ Reply = {ok, StateData#state.output} |
|
564 |
-+ end, |
|
565 |
-+ %% save request |
|
566 |
-+ ReqList = [#hbr{rid=RID, |
|
567 |
-+ key=StateData#state.key, |
|
568 |
-+ in=StateData#state.input, |
|
569 |
-+ out=StateData#state.output |
|
570 |
-+ } | |
|
571 |
-+ [El || El <- StateData#state.req_list, |
|
572 |
-+ El#hbr.rid /= RID ] |
|
573 |
-+ ], |
|
574 |
-+ Output = "" |
|
575 |
-+ end, |
|
576 |
-+ {reply, Reply, StateName, StateData#state{output = Output, |
|
577 |
-+ timer = Timer, |
|
578 |
-+ req_list = ReqList}}; |
|
579 |
-+ |
|
580 |
-+handle_sync_event(_Event, _From, StateName, StateData) -> |
|
581 |
-+ Reply = ok, |
|
582 |
-+ {reply, Reply, StateName, StateData}. |
|
583 |
-+ |
|
584 |
-+code_change(_OldVsn, StateName, StateData, _Extra) -> |
|
585 |
-+ {ok, StateName, StateData}. |
|
586 |
-+ |
|
587 |
-+%%---------------------------------------------------------------------- |
|
588 |
-+%% Func: handle_info/3 |
|
589 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
590 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
591 |
-+%% {stop, Reason, NewStateData} |
|
592 |
-+%%---------------------------------------------------------------------- |
|
593 |
-+handle_info({timeout, Timer, _}, _StateName, |
|
594 |
-+ #state{timer = Timer} = StateData) -> |
|
595 |
-+ ?DEBUG("ding dong", []), |
|
596 |
-+ {stop, normal, StateData}; |
|
597 |
-+ |
|
598 |
-+handle_info(_, StateName, StateData) -> |
|
599 |
-+ {next_state, StateName, StateData}. |
|
600 |
-+ |
|
601 |
-+%%---------------------------------------------------------------------- |
|
602 |
-+%% Func: terminate/3 |
|
603 |
-+%% Purpose: Shutdown the fsm |
|
604 |
-+%% Returns: any |
|
605 |
-+%%---------------------------------------------------------------------- |
|
606 |
-+terminate(_Reason, _StateName, StateData) -> |
|
607 |
-+ ?DEBUG("terminate: deleting session ~s", [StateData#state.id]), |
|
608 |
-+ mnesia:transaction( |
|
609 |
-+ fun() -> |
|
610 |
-+ mnesia:delete({http_bind, StateData#state.id}) |
|
611 |
-+ end), |
|
612 |
-+ case StateData#state.waiting_input of |
|
613 |
-+ false -> |
|
614 |
-+ case StateData#state.last_receiver of |
|
615 |
-+ undefined -> ok; |
|
616 |
-+ Receiver -> Receiver ! {tcp_closed, {http_bind, self()}} |
|
617 |
-+ end; |
|
618 |
-+ {Receiver, _Tag} -> Receiver ! {tcp_closed, {http_bind, self()}} |
|
619 |
-+ end, |
|
620 |
-+ ok. |
|
621 |
-+ |
|
622 |
-+%%%---------------------------------------------------------------------- |
|
623 |
-+%%% Internal functions |
|
624 |
-+%%%---------------------------------------------------------------------- |
|
625 |
-+ |
|
626 |
-+ |
|
627 |
-+http_put(ID, RID, Key, NewKey, Hold, Packet) -> |
|
628 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
629 |
-+ [] -> |
|
630 |
-+ {error, not_exists}; |
|
631 |
-+ [#http_bind{pid = FsmRef}] -> |
|
632 |
-+ gen_fsm:sync_send_all_state_event( |
|
633 |
-+ FsmRef, {http_put, RID, Key, NewKey, Hold, Packet}) |
|
634 |
-+ end. |
|
635 |
-+ |
|
636 |
-+http_get(ID,RID) -> |
|
637 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
638 |
-+ [] -> |
|
639 |
-+ {error, not_exists}; |
|
640 |
-+ [#http_bind{pid = FsmRef, wait = Wait, hold = Hold}] -> |
|
641 |
-+ gen_fsm:sync_send_all_state_event(FsmRef, {http_get, RID, Wait, Hold}) |
|
642 |
-+ end. |
|
643 |
-+ |
|
644 |
-+ |
|
645 |
-+parse_request(Data) -> |
|
646 |
-+ ?DEBUG("--- incoming data --- ~n~s~n --- END incoming data END --- ",[Data]), |
|
647 |
-+ case xml_stream:parse_element(Data) of |
|
648 |
-+ El when element(1, El) == xmlelement -> |
|
649 |
-+ {xmlelement, Name, Attrs, Els} = El, |
|
650 |
-+ ID = xml:get_attr_s("sid",Attrs), |
|
651 |
-+ {RID,_X} = string:to_integer(xml:get_attr_s("rid",Attrs)), |
|
652 |
-+ Key = xml:get_attr_s("key",Attrs), |
|
653 |
-+ NewKey = xml:get_attr_s("newkey",Attrs), |
|
654 |
-+ Xmlns = xml:get_attr_s("xmlns",Attrs), |
|
655 |
-+ Packet = [xml:element_to_string(xml:remove_tag_attr("xmlns",E)) || E <- Els], |
|
656 |
-+ ?DEBUG(" --- incoming packet --- ~n~s~n --- END incoming packet END --- ", [Packet]), |
|
657 |
-+ if |
|
658 |
-+ Name /= "body" -> |
|
659 |
-+ {error, bad_request}; |
|
660 |
-+ Xmlns /= "http://jabber.org/protocol/httpbind" -> |
|
661 |
-+ {error, bad_request}; |
|
662 |
-+ true -> |
|
663 |
-+ {ok, ID, RID, Key, NewKey, Attrs, Packet} |
|
664 |
-+ end; |
|
665 |
-+ {error, _Reason} -> |
|
666 |
-+ {error, bad_request} |
|
667 |
-+ end. |
|
668 |
-+ |
|
669 |
-+cancel_timer(Timer) -> |
|
670 |
-+ erlang:cancel_timer(Timer), |
|
671 |
-+ receive |
|
672 |
-+ {timeout, Timer, _} -> |
|
673 |
-+ ok |
|
674 |
-+ after 0 -> |
|
675 |
-+ ok |
|
676 |
-+ end. |
|
677 |
-+ |
|
678 |
-+hex(Bin) when binary(Bin) -> hex(binary_to_list(Bin)); |
|
679 |
-+hex([]) -> ""; |
|
680 |
-+hex([H|T]) -> |
|
681 |
-+ [A,B] = if |
|
682 |
-+ H == 0 -> "00"; |
|
683 |
-+ H < 16 -> [$0,element(H,{$1,$2,$3,$4,$5,$6,$7,$8,$9,$a,$b,$c,$d,$e,$f})]; |
|
684 |
-+ true -> erlang:integer_to_list(H,16) |
|
685 |
-+ end, |
|
686 |
-+ [A,B|hex(T)]. |
|
687 |
-Index: src/web/ejabberd_web.erl |
|
688 |
-=================================================================== |
|
689 |
---- src/web/ejabberd_web.erl (Revision 565) |
|
690 |
-+++ src/web/ejabberd_web.erl (Arbeitskopie) |
|
691 |
-@@ -49,7 +49,7 @@ |
|
692 |
- {"value", Value}])). |
|
693 |
- |
|
694 |
- |
|
695 |
--process_get({_, true}, |
|
696 |
-+process_get({_, _, true}, |
|
697 |
- #request{auth = Auth, |
|
698 |
- path = ["admin", "server", SHost | RPath], |
|
699 |
- q = Query, |
|
700 |
-@@ -94,7 +94,7 @@ |
|
701 |
- {404, [], make_xhtml([?XC("h1", "Not found")])} |
|
702 |
- end; |
|
703 |
- |
|
704 |
--process_get({_, true}, |
|
705 |
-+process_get({_, _, true}, |
|
706 |
- #request{auth = Auth, |
|
707 |
- path = ["admin" | RPath], |
|
708 |
- q = Query, |
|
709 |
-@@ -133,12 +133,19 @@ |
|
710 |
- [{xmlcdata, "401 Unauthorized"}]}])} |
|
711 |
- end; |
|
712 |
- |
|
713 |
--process_get({true, _}, |
|
714 |
-+process_get({true, _, _}, |
|
715 |
- #request{path = ["http-poll" | RPath], |
|
716 |
- q = _Query, |
|
717 |
- lang = _Lang} = Request) -> |
|
718 |
- ejabberd_http_poll:process_request(Request#request{path = RPath}); |
|
719 |
- |
|
720 |
-+process_get({_, true, _}, |
|
721 |
-+ #request{us = _US, |
|
722 |
-+ path = ["http-bind" | RPath], |
|
723 |
-+ q = _Query, |
|
724 |
-+ lang = _Lang} = Request) -> |
|
725 |
-+ ejabberd_http_bind:process_request(Request#request{path = RPath}); |
|
726 |
-+ |
|
727 |
- process_get(_, _Request) -> |
|
728 |
- {404, [], make_xhtml([?XC("h1", "Not found")])}. |
|
729 |
- |
|
730 |
-Index: src/web/ejabberd_http.erl |
|
731 |
-=================================================================== |
|
732 |
---- src/web/ejabberd_http.erl (Revision 565) |
|
733 |
-+++ src/web/ejabberd_http.erl (Arbeitskopie) |
|
734 |
-@@ -30,6 +30,7 @@ |
|
735 |
- request_keepalive, |
|
736 |
- request_content_length, |
|
737 |
- request_lang = "en", |
|
738 |
-+ use_http_bind = false, |
|
739 |
- use_http_poll = false, |
|
740 |
- use_web_admin = false, |
|
741 |
- end_of_request = false, |
|
742 |
-@@ -70,15 +71,17 @@ |
|
743 |
- _ -> |
|
744 |
- ok |
|
745 |
- end, |
|
746 |
-+ UseHTTPBind = lists:member(http_bind, Opts), |
|
747 |
- UseHTTPPoll = lists:member(http_poll, Opts), |
|
748 |
- UseWebAdmin = lists:member(web_admin, Opts), |
|
749 |
-- ?DEBUG("S: ~p~n", [{UseHTTPPoll, UseWebAdmin}]), |
|
750 |
-+ ?DEBUG("S: ~p~n", [{UseHTTPPoll, UseHTTPBind, UseWebAdmin}]), |
|
751 |
- ?INFO_MSG("started: ~p", [{SockMod1, Socket1}]), |
|
752 |
- {ok, proc_lib:spawn_link(ejabberd_http, |
|
753 |
- receive_headers, |
|
754 |
- [#state{sockmod = SockMod1, |
|
755 |
- socket = Socket1, |
|
756 |
- use_http_poll = UseHTTPPoll, |
|
757 |
-+ use_http_bind = UseHTTPBind, |
|
758 |
- use_web_admin = UseWebAdmin}])}. |
|
759 |
- |
|
760 |
- |
|
761 |
-@@ -185,6 +188,7 @@ |
|
762 |
- #state{sockmod = SockMod, |
|
763 |
- socket = Socket, |
|
764 |
- use_http_poll = State#state.use_http_poll, |
|
765 |
-+ use_http_bind = State#state.use_http_bind, |
|
766 |
- use_web_admin = State#state.use_web_admin}; |
|
767 |
- _ -> |
|
768 |
- #state{end_of_request = true} |
|
769 |
-@@ -200,6 +204,7 @@ |
|
770 |
- request_auth = Auth, |
|
771 |
- request_lang = Lang, |
|
772 |
- use_http_poll = UseHTTPPoll, |
|
773 |
-+ use_http_bind = UseHTTPBind, |
|
774 |
- use_web_admin = UseWebAdmin} = State) -> |
|
775 |
- case (catch url_decode_q_split(Path)) of |
|
776 |
- {'EXIT', _} -> |
|
777 |
-@@ -217,7 +222,7 @@ |
|
778 |
- q = LQuery, |
|
779 |
- auth = Auth, |
|
780 |
- lang = Lang}, |
|
781 |
-- case ejabberd_web:process_get({UseHTTPPoll, UseWebAdmin}, |
|
782 |
-+ case ejabberd_web:process_get({UseHTTPPoll, UseHTTPBind, UseWebAdmin}, |
|
783 |
- Request) of |
|
784 |
- El when element(1, El) == xmlelement -> |
|
785 |
- make_xhtml_output(State, 200, [], El); |
|
786 |
-@@ -240,6 +245,7 @@ |
|
787 |
- sockmod = SockMod, |
|
788 |
- socket = Socket, |
|
789 |
- use_http_poll = UseHTTPPoll, |
|
790 |
-+ use_http_bind = UseHTTPBind, |
|
791 |
- use_web_admin = UseWebAdmin} = State) |
|
792 |
- when is_integer(Len) -> |
|
793 |
- case SockMod of |
|
794 |
-@@ -267,7 +273,7 @@ |
|
795 |
- auth = Auth, |
|
796 |
- data = Data, |
|
797 |
- lang = Lang}, |
|
798 |
-- case ejabberd_web:process_get({UseHTTPPoll, UseWebAdmin}, |
|
799 |
-+ case ejabberd_web:process_get({UseHTTPPoll, UseHTTPBind, UseWebAdmin}, |
|
800 |
- Request) of |
|
801 |
- El when element(1, El) == xmlelement -> |
|
802 |
- make_xhtml_output(State, 200, [], El); |
|
803 |
-Index: src/xml.erl |
|
804 |
-=================================================================== |
|
805 |
---- src/xml.erl (Revision 565) |
|
806 |
-+++ src/xml.erl (Arbeitskopie) |
|
807 |
-@@ -18,6 +18,7 @@ |
|
808 |
- get_tag_attr/2, get_tag_attr_s/2, |
|
809 |
- get_subtag/2, |
|
810 |
- get_path_s/2, |
|
811 |
-+ remove_tag_attr/2, |
|
812 |
- replace_tag_attr/3]). |
|
813 |
- |
|
814 |
- %element_to_string(El) -> |
|
815 |
-@@ -224,6 +225,14 @@ |
|
816 |
- get_path_s(El, [cdata]) -> |
|
817 |
- get_tag_cdata(El). |
|
818 |
- |
|
819 |
-+remove_tag_attr(Attr, El) -> |
|
820 |
-+ case El of |
|
821 |
-+ {xmlelement, Name, Attrs, Els} -> |
|
822 |
-+ Attrs1 = lists:keydelete(Attr, 1, Attrs), |
|
823 |
-+ {xmlelement, Name, Attrs1, Els}; |
|
824 |
-+ _ -> |
|
825 |
-+ El |
|
826 |
-+ end. |
|
827 |
- |
|
828 |
- replace_tag_attr(Attr, Value, {xmlelement, Name, Attrs, Els}) -> |
|
829 |
- Attrs1 = lists:keydelete(Attr, 1, Attrs), |
|
830 |
-Index: src/ejabberd_sup.erl |
|
831 |
-=================================================================== |
|
832 |
---- src/ejabberd_sup.erl (Revision 565) |
|
833 |
-+++ src/ejabberd_sup.erl (Arbeitskopie) |
|
834 |
-@@ -123,6 +123,14 @@ |
|
835 |
- infinity, |
|
836 |
- supervisor, |
|
837 |
- [ejabberd_tmp_sup]}, |
|
838 |
-+ HTTPBindSupervisor = |
|
839 |
-+ {ejabberd_http_bind_sup, |
|
840 |
-+ {ejabberd_tmp_sup, start_link, |
|
841 |
-+ [ejabberd_http_bind_sup, ejabberd_http_bind]}, |
|
842 |
-+ permanent, |
|
843 |
-+ infinity, |
|
844 |
-+ supervisor, |
|
845 |
-+ [ejabberd_tmp_sup]}, |
|
846 |
- IQSupervisor = |
|
847 |
- {ejabberd_iq_sup, |
|
848 |
- {ejabberd_tmp_sup, start_link, |
|
849 |
-@@ -145,6 +153,7 @@ |
|
850 |
- ServiceSupervisor, |
|
851 |
- HTTPSupervisor, |
|
852 |
- HTTPPollSupervisor, |
|
853 |
-+ HTTPBindSupervisor, |
|
854 |
- IQSupervisor, |
|
855 |
- Listener]}}. |
... | ... |
@@ -1,11 +0,0 @@ |
1 |
-diff -Naur ejabberd-1.1.1.orig/src/odbc/ejabberd_odbc.erl ejabberd-1.1.1/src/odbc/ejabberd_odbc.erl |
|
2 |
---- ejabberd-1.1.1.orig/src/odbc/ejabberd_odbc.erl 2006-05-07 19:05:12.549917750 +0400 |
|
3 |
-+++ ejabberd-1.1.1/src/odbc/ejabberd_odbc.erl 2006-05-07 19:06:11.337591750 +0400 |
|
4 |
-@@ -281,6 +281,7 @@ |
|
5 |
- case mysql_conn:start(Server, ?MYSQL_PORT, Username, Password, DB, NoLogFun) of |
|
6 |
- {ok, Ref} -> |
|
7 |
- erlang:monitor(process, Ref), |
|
8 |
-+ catch mysql_conn:fetch(Ref, "SET NAMES 'utf8';", self()), |
|
9 |
- {ok, #state{db_ref = Ref, db_type = mysql}}; |
|
10 |
- {error, Reason} -> |
|
11 |
- ?ERROR_MSG("MySQL connection failed: ~p~n", [Reason]), |
... | ... |
@@ -1,406 +0,0 @@ |
1 |
-* modified files |
|
2 |
- |
|
3 |
- |
|
4 |
---- jlib.hrl |
|
5 |
-+++ jlib.hrl |
|
6 |
-@@ -34,6 +34,7 @@ |
|
7 |
- -define(NS_PUBSUB_OWNER, "http://jabber.org/protocol/pubsub#owner"). |
|
8 |
- -define(NS_PUBSUB_NMI, "http://jabber.org/protocol/pubsub#node-meta-info"). |
|
9 |
- -define(NS_COMMANDS, "http://jabber.org/protocol/commands"). |
|
10 |
-+-define(NS_BYTESTREAMS, "http://jabber.org/protocol/bytestreams"). |
|
11 |
- |
|
12 |
- -define(NS_EJABBERD_CONFIG, "ejabberd:config"). |
|
13 |
- |
|
14 |
- |
|
15 |
- |
|
16 |
- |
|
17 |
-* added files |
|
18 |
- |
|
19 |
---- /dev/null |
|
20 |
-+++ mod_proxy65.erl |
|
21 |
-@@ -0,0 +1,189 @@ |
|
22 |
-+%%%---------------------------------------------------------------------- |
|
23 |
-+%%% File : mod_proxy65.erl |
|
24 |
-+%%% Author : Magnus Henoch <henoch@dtek.chalmers.se> |
|
25 |
-+%%% Purpose : Handle Jabber communications for JEP-0065 proxy |
|
26 |
-+%%% Created : 27 Dec 2005 by Magnus Henoch <henoch@dtek.chalmers.se> |
|
27 |
-+%%% Id : $Id: ejabberd_c2s.erl 440 2005-11-22 18:00:56Z alexey $ |
|
28 |
-+%%%---------------------------------------------------------------------- |
|
29 |
-+ |
|
30 |
-+-module(mod_proxy65). |
|
31 |
-+-author('henoch@dtek.chalmers.se'). |
|
32 |
-+-vsn('$Revision$ '). |
|
33 |
-+ |
|
34 |
-+-behaviour(gen_mod). |
|
35 |
-+ |
|
36 |
-+-export([start/2, |
|
37 |
-+ init/1, |
|
38 |
-+ stop/1]). |
|
39 |
-+ |
|
40 |
-+-include("ejabberd.hrl"). |
|
41 |
-+-include("jlib.hrl"). |
|
42 |
-+ |
|
43 |
-+-record(proxy65_connection, {cookie, firstpid = none, secondpid = none}). |
|
44 |
-+ |
|
45 |
-+-record(proxy65_options, {host, access, streamhosts}). |
|
46 |
-+ |
|
47 |
-+-define(PROCNAME, ejabberd_mod_proxy65). |
|
48 |
-+ |
|
49 |
-+start(Host, Opts) -> |
|
50 |
-+ mnesia:create_table(proxy65_connection, |
|
51 |
-+ [{ram_copies, [node()]}, |
|
52 |
-+ {attributes, record_info(fields, proxy65_connection)}]), |
|
53 |
-+ MyHost = gen_mod:get_opt(host, Opts, "proxy." ++ Host), |
|
54 |
-+ Access = gen_mod:get_opt(access, Opts, all), |
|
55 |
-+ Streamhosts = gen_mod:get_opt(streamhosts, Opts, [{Host, 7777}]), |
|
56 |
-+ |
|
57 |
-+ register(gen_mod:get_module_proc(Host, ?PROCNAME), |
|
58 |
-+ spawn(?MODULE, init, [#proxy65_options{host = MyHost, access = Access, |
|
59 |
-+ streamhosts = Streamhosts}])). |
|
60 |
-+ |
|
61 |
-+ |
|
62 |
-+stop(Host) -> |
|
63 |
-+ Proc = gen_mod:get_module_proc(Host, ?PROCNAME), |
|
64 |
-+ Proc ! stop, |
|
65 |
-+ {wait, Proc}. |
|
66 |
-+ |
|
67 |
-+init(#proxy65_options{host = Host} = Opts) -> |
|
68 |
-+ ejabberd_router:register_route(Host), |
|
69 |
-+ loop(Opts). |
|
70 |
-+ |
|
71 |
-+loop(#proxy65_options{host = Host} = Opts) -> |
|
72 |
-+ receive |
|
73 |
-+ {route, From, To, Packet} -> |
|
74 |
-+ case catch do_route(Opts, From, To, Packet) of |
|
75 |
-+ {'EXIT', Reason} -> |
|
76 |
-+ ?ERROR_MSG("~p", [Reason]); |
|
77 |
-+ _ -> |
|
78 |
-+ ok |
|
79 |
-+ end, |
|
80 |
-+ loop(Opts); |
|
81 |
-+ stop -> |
|
82 |
-+ ejabberd_router:unregister_route(Host), |
|
83 |
-+ ok; |
|
84 |
-+ _ -> |
|
85 |
-+ loop(Opts) |
|
86 |
-+ end. |
|
87 |
-+ |
|
88 |
-+do_route(#proxy65_options{host = Host, access = Access} = Opts, |
|
89 |
-+ From, To, Packet) -> |
|
90 |
-+ case acl:match_rule(Host, Access, From) of |
|
91 |
-+ allow -> |
|
92 |
-+ do_route1(Opts, From, To, Packet); |
|
93 |
-+ _ -> |
|
94 |
-+ {xmlelement, _Name, Attrs, _Els} = Packet, |
|
95 |
-+ Lang = xml:get_attr_s("xml:lang", Attrs), |
|
96 |
-+ ErrText = "Access denied by service policy", |
|
97 |
-+ Err = jlib:make_error_reply(Packet, |
|
98 |
-+ ?ERRT_FORBIDDEN(Lang, ErrText)), |
|
99 |
-+ ejabberd_router:route(To, From, Err) |
|
100 |
-+ end. |
|
101 |
-+ |
|
102 |
-+do_route1(#proxy65_options{host = Host, streamhosts = Streamhosts}, From, To, Packet) -> |
|
103 |
-+ {xmlelement, Name, _Attrs, _Els} = Packet, |
|
104 |
-+ case Name of |
|
105 |
-+ "iq" -> |
|
106 |
-+ case jlib:iq_query_info(Packet) of |
|
107 |
-+ #iq{type = get, xmlns = ?NS_DISCO_INFO = XMLNS, |
|
108 |
-+ lang = Lang, sub_el = SubEl} = IQ -> |
|
109 |
-+ Node = xml:get_tag_attr_s("node", SubEl), |
|
110 |
-+ if Node == [] -> |
|
111 |
-+ Res = IQ#iq{type = result, |
|
112 |
-+ sub_el = [{xmlelement, "query", |
|
113 |
-+ [{"xmlns", XMLNS}], |
|
114 |
-+ [{xmlelement, "identity", |
|
115 |
-+ [{"category", "proxy"}, |
|
116 |
-+ {"type", "bytestreams"}, |
|
117 |
-+ {"name", translate:translate(Lang, "SOCKS5 bytestreams proxy")}], |
|
118 |
-+ []}, |
|
119 |
-+ {xmlelement, "feature", |
|
120 |
-+ [{"var", ?NS_BYTESTREAMS}], []}]}]}; |
|
121 |
-+ true -> |
|
122 |
-+ Res = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND) |
|
123 |
-+ end; |
|
124 |
-+ #iq{type = get, xmlns = ?NS_DISCO_ITEMS = XMLNS} = IQ -> |
|
125 |
-+ Res = IQ#iq{type = result, |
|
126 |
-+ sub_el = [{xmlelement, "query", |
|
127 |
-+ [{"xmlns", XMLNS}], []}]}; |
|
128 |
-+ #iq{type = get, xmlns = ?NS_VERSION} = IQ -> |
|
129 |
-+ OSType = case os:type() of |
|
130 |
-+ {Osfamily, Osname} -> |
|
131 |
-+ atom_to_list(Osfamily) ++ "/" ++ |
|
132 |
-+ atom_to_list(Osname); |
|
133 |
-+ Osfamily -> |
|
134 |
-+ atom_to_list(Osfamily) |
|
135 |
-+ end, |
|
136 |
-+ OSVersion = case os:version() of |
|
137 |
-+ {Major, Minor, Release} -> |
|
138 |
-+ lists:flatten( |
|
139 |
-+ io_lib:format("~w.~w.~w", |
|
140 |
-+ [Major, Minor, Release])); |
|
141 |
-+ VersionString -> |
|
142 |
-+ VersionString |
|
143 |
-+ end, |
|
144 |
-+ OS = OSType ++ " " ++ OSVersion, |
|
145 |
-+ Res = IQ#iq{type = result, |
|
146 |
-+ sub_el = [{xmlelement, "query", |
|
147 |
-+ [{"xmlns", ?NS_VERSION}], |
|
148 |
-+ [{xmlelement, "name", [], |
|
149 |
-+ [{xmlcdata, "ejabberd mod_proxy65 (unofficial)"}]}, |
|
150 |
-+ {xmlelement, "version", [], |
|
151 |
-+ [{xmlcdata, "0.1"}]}, |
|
152 |
-+ {xmlelement, "os", [], |
|
153 |
-+ [{xmlcdata, OS}]} |
|
154 |
-+ ]}]}; |
|
155 |
-+ #iq{type = get, xmlns = ?NS_BYTESTREAMS = XMLNS} = IQ -> |
|
156 |
-+ Res = IQ#iq{type = result, |
|
157 |
-+ sub_el = [{xmlelement, "query", |
|
158 |
-+ [{"xmlns", XMLNS}], |
|
159 |
-+ return_streamhosts(Host, Streamhosts)}]}; |
|
160 |
-+ #iq{type = set, xmlns = ?NS_BYTESTREAMS} = IQ -> |
|
161 |
-+ Res = activate(Packet, From, To, IQ); |
|
162 |
-+ _ -> |
|
163 |
-+ Res = jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED) |
|
164 |
-+ end, |
|
165 |
-+ case Res of |
|
166 |
-+ #iq{} -> |
|
167 |
-+ ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); |
|
168 |
-+ _ -> |
|
169 |
-+ ejabberd_router:route(To, From, Res) |
|
170 |
-+ end; |
|
171 |
-+ _ -> |
|
172 |
-+ ejabberd_router:route(To, From, jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED)) |
|
173 |
-+ end. |
|
174 |
-+ |
|
175 |
-+return_streamhosts(_JID, []) -> |
|
176 |
-+ []; |
|
177 |
-+return_streamhosts(JID, [{Host, Port} | Streamhosts]) -> |
|
178 |
-+ %% This is not tail-recursive, but it doesn't matter. |
|
179 |
-+ [{xmlelement, "streamhost", |
|
180 |
-+ [{"jid", JID}, |
|
181 |
-+ {"host", Host}, |
|
182 |
-+ {"port", integer_to_list(Port)}], |
|
183 |
-+ []} | return_streamhosts(JID, Streamhosts)]. |
|
184 |
-+ |
|
185 |
-+activate(Packet, From, _To, #iq{sub_el = SubEl} = IQ) -> |
|
186 |
-+ case SubEl of |
|
187 |
-+ {xmlelement, "query", Attrs, _SubEls} -> |
|
188 |
-+ Sid = xml:get_attr_s("sid", Attrs), |
|
189 |
-+ ActivateTag = xml:get_subtag(SubEl, "activate"), |
|
190 |
-+ if ActivateTag /= false -> |
|
191 |
-+ TargetJID = jlib:string_to_jid(xml:get_tag_cdata(ActivateTag)); |
|
192 |
-+ true -> |
|
193 |
-+ TargetJID = false |
|
194 |
-+ end, |
|
195 |
-+ |
|
196 |
-+ if Sid /= [], TargetJID /= false, TargetJID /= error -> |
|
197 |
-+ case proxy65_listener:activate(From, TargetJID, Sid) of |
|
198 |
-+ ok -> |
|
199 |
-+ ?INFO_MSG("Activated connection between ~s and ~s", |
|
200 |
-+ [jlib:jid_to_string(From), TargetJID]), |
|
201 |
-+ IQ#iq{type = result, sub_el = []}; |
|
202 |
-+ _ -> |
|
203 |
-+ jlib:make_error_reply(Packet, ?ERR_INTERNAL_SERVER_ERROR) |
|
204 |
-+ end; |
|
205 |
-+ true -> |
|
206 |
-+ jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST) |
|
207 |
-+ end; |
|
208 |
-+ _ -> |
|
209 |
-+ jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST) |
|
210 |
-+ end. |
|
211 |
---- /dev/null |
|
212 |
-+++ proxy65_listener.erl |
|
213 |
-@@ -0,0 +1,192 @@ |
|
214 |
-+%%%---------------------------------------------------------------------- |
|
215 |
-+%%% File : proxy65_listener.erl |
|
216 |
-+%%% Author : Magnus Henoch <henoch@dtek.chalmers.se> |
|
217 |
-+%%% Purpose : Handle SOCKS5 connections for JEP-0065 proxy |
|
218 |
-+%%% Created : 27 Dec 2005 by Magnus Henoch <henoch@dtek.chalmers.se> |
|
219 |
-+%%% Id : $Id: ejabberd_c2s.erl 440 2005-11-22 18:00:56Z alexey $ |
|
220 |
-+%%%---------------------------------------------------------------------- |
|
221 |
-+ |
|
222 |
-+-module(proxy65_listener). |
|
223 |
-+-author('henoch@dtek.chalmers.se'). |
|
224 |
-+-vsn('$Revision$ '). |
|
225 |
-+ |
|
226 |
-+-export([start/2, handle_connection/2, activate/3]). |
|
227 |
-+ |
|
228 |
-+-include("ejabberd.hrl"). |
|
229 |
-+-include("jlib.hrl"). |
|
230 |
-+ |
|
231 |
-+-record(proxy65_connection, {cookie, firstpid = none, secondpid = none}). |
|
232 |
-+ |
|
233 |
-+start({SockMod, Socket}, Opts) -> |
|
234 |
-+ {ok, proc_lib:spawn(?MODULE, handle_connection, [{SockMod, Socket}, Opts])}. |
|
235 |
-+ |
|
236 |
-+read_bytes(_SockOpts, 0, Data) -> |
|
237 |
-+ lists:flatten(Data); |
|
238 |
-+read_bytes({SockMod, Socket} = SockOpts, N, Data) -> |
|
239 |
-+ Timeout = 1000, |
|
240 |
-+ case SockMod:recv(Socket, N, Timeout) of |
|
241 |
-+ {error, closed} -> |
|
242 |
-+ %% On closed connection, return everything we have, |
|
243 |
-+ %% but not if we have nothing. |
|
244 |
-+ if Data == [] -> |
|
245 |
-+ erlang:error(closed); |
|
246 |
-+ true -> |
|
247 |
-+ lists:flatten(Data) |
|
248 |
-+ end; |
|
249 |
-+ {ok, MoreData} -> |
|
250 |
-+ ?DEBUG("read ~p", [MoreData]), |
|
251 |
-+ DataList = binary_to_list(MoreData), |
|
252 |
-+ read_bytes(SockOpts, N - length(DataList), [Data, DataList]) |
|
253 |
-+ end. |
|
254 |
-+ |
|
255 |
-+handle_connection({SockMod, Socket}, Opts) -> |
|
256 |
-+ ?DEBUG("in handle_connection", []), |
|
257 |
-+ case catch handle_auth({SockMod, Socket}, Opts) of |
|
258 |
-+ {'EXIT', Reason} -> |
|
259 |
-+ ?ERROR_MSG("~p abnormal termination:~n\t~p~n", |
|
260 |
-+ [?MODULE, Reason]), |
|
261 |
-+ SockMod:close(Socket); |
|
262 |
-+ _ -> |
|
263 |
-+ ok |
|
264 |
-+ end. |
|
265 |
-+ |
|
266 |
-+handle_auth({SockMod, Socket} = SockOpts, Opts) -> |
|
267 |
-+ ?DEBUG("in handle_auth", []), |
|
268 |
-+ %% SOCKS protocol stuff... |
|
269 |
-+ [5, NAuthMethods] = read_bytes(SockOpts, 2, []), |
|
270 |
-+ AuthMethods = read_bytes(SockOpts, NAuthMethods, []), |
|
271 |
-+ SupportsNoAuth = lists:member(0, AuthMethods), |
|
272 |
-+ |
|
273 |
-+ %% Must support no authentication, otherwise crash |
|
274 |
-+ true = SupportsNoAuth, |
|
275 |
-+ |
|
276 |
-+ SockMod:send(Socket, [5, 0]), |
|
277 |
-+ |
|
278 |
-+ %% And done. |
|
279 |
-+ handle_connect(SockOpts, Opts). |
|
280 |
-+ |
|
281 |
-+handle_connect({SockMod, Socket} = SockOpts, Opts) -> |
|
282 |
-+ ?DEBUG("in handle_connect", []), |
|
283 |
-+ %% Expect a CONNECT command and nothing else |
|
284 |
-+ [5, 1, _, 3, AddressLength] = read_bytes(SockOpts, 5, []), |
|
285 |
-+ Cookie = read_bytes(SockOpts, AddressLength, []), |
|
286 |
-+ [0, 0] = read_bytes(SockOpts, 2, []), |
|
287 |
-+ |
|
288 |
-+ %% Make sure no more than two connections claim the same cookie. |
|
289 |
-+ F = fun() -> |
|
290 |
-+ case mnesia:read({proxy65_connection, Cookie}) of |
|
291 |
-+ [] -> |
|
292 |
-+ mnesia:write(#proxy65_connection{cookie = Cookie, |
|
293 |
-+ firstpid = self()}), |
|
294 |
-+ ok; |
|
295 |
-+ [#proxy65_connection{secondpid = none} = C] -> |
|
296 |
-+ mnesia:write(C#proxy65_connection{secondpid = self()}), |
|
297 |
-+ ok |
|
298 |
-+ end |
|
299 |
-+ end, |
|
300 |
-+ |
|
301 |
-+ case mnesia:transaction(F) of |
|
302 |
-+ {atomic, ok} -> |
|
303 |
-+ SockMod:send(Socket, [5, 0, 0, 3, AddressLength, Cookie, 0, 0]), |
|
304 |
-+ wait_for_activation(SockOpts, Opts); |
|
305 |
-+ Error -> |
|
306 |
-+ %% conflict. send "general SOCKS server failure". |
|
307 |
-+ SockMod:send(Socket, [5, 1, 0, 3, AddressLength, Cookie, 0, 0]), |
|
308 |
-+ erlang:error({badconnect, Error}) |
|
309 |
-+ end. |
|
310 |
-+ |
|
311 |
-+wait_for_activation(SockOpts, Opts) -> |
|
312 |
-+ ?DEBUG("in wait_for_activation", []), |
|
313 |
-+ receive |
|
314 |
-+ {get_socket, ReplyTo} -> |
|
315 |
-+ ReplyTo ! SockOpts, |
|
316 |
-+ wait_for_activation(SockOpts, Opts); |
|
317 |
-+ {activate, TargetSocket, Initiator, Target} -> |
|
318 |
-+ ?DEBUG("activated", []), |
|
319 |
-+ |
|
320 |
-+ %% We have no way of knowing which connection belongs to |
|
321 |
-+ %% which participant, so give both the maximum traffic |
|
322 |
-+ %% allowed to either. |
|
323 |
-+ Shapers = case lists:keysearch(shaper, 1, Opts) of |
|
324 |
-+ {value, {_, S}} -> S; |
|
325 |
-+ _ -> none |
|
326 |
-+ end, |
|
327 |
-+ ?DEBUG("we have shapers: ~p", [Shapers]), |
|
328 |
-+ Shaper1 = acl:match_rule(global, Shapers, jlib:string_to_jid(Initiator)), |
|
329 |
-+ Shaper2 = acl:match_rule(global, Shapers, jlib:string_to_jid(Target)), |
|
330 |
-+ if Shaper1 == none; Shaper2 == none -> |
|
331 |
-+ MaxShaper = none; |
|
332 |
-+ true -> |
|
333 |
-+ ShaperValue1 = ejabberd_config:get_global_option({shaper, Shaper1}), |
|
334 |
-+ ShaperValue2 = ejabberd_config:get_global_option({shaper, Shaper2}), |
|
335 |
-+ |
|
336 |
-+ if ShaperValue1 > ShaperValue2 -> |
|
337 |
-+ MaxShaper = Shaper1; |
|
338 |
-+ true -> |
|
339 |
-+ MaxShaper = Shaper2 |
|
340 |
-+ end, |
|
341 |
-+ ?DEBUG("shapers have values ~p and ~p~nusing ~p", [ShaperValue1, ShaperValue2, MaxShaper]), |
|
342 |
-+ ok |
|
343 |
-+ end, |
|
344 |
-+ |
|
345 |
-+ transfer_data(SockOpts, TargetSocket, shaper:new(MaxShaper)) |
|
346 |
-+ end. |
|
347 |
-+ |
|
348 |
-+transfer_data({SockMod, Socket} = SockOpts, {TargetSockMod, TargetSocket} = TargetSockOpts, |
|
349 |
-+ Shaper) -> |
|
350 |
-+ case SockMod:recv(Socket, 0, infinity) of |
|
351 |
-+ {ok, Data} -> |
|
352 |
-+ if Data /= <<>> -> |
|
353 |
-+ NewShaper = case Shaper of |
|
354 |
-+ none -> none; |
|
355 |
-+ _ -> |
|
356 |
-+ shaper:update(Shaper, size(Data)) |
|
357 |
-+ end, |
|
358 |
-+ ok = TargetSockMod:send(TargetSocket, Data); |
|
359 |
-+ true -> |
|
360 |
-+ NewShaper = Shaper |
|
361 |
-+ end, |
|
362 |
-+ transfer_data(SockOpts, TargetSockOpts, NewShaper); |
|
363 |
-+ {error, _} -> |
|
364 |
-+ TargetSockMod:shutdown(TargetSocket, read_write) |
|
365 |
-+ end. |
|
366 |
-+ |
|
367 |
-+get_socket(PID) -> |
|
368 |
-+ PID ! {get_socket, self()}, |
|
369 |
-+ receive |
|
370 |
-+ {_SockMod, _Socket} = SockOpts -> |
|
371 |
-+ SockOpts |
|
372 |
-+ end. |
|
373 |
-+ |
|
374 |
-+%% If any argument is a jid record, convert it to normalized string form... |
|
375 |
-+activate(#jid{} = Initiator, Target, SessionID) -> |
|
376 |
-+ NormalizedInitiator = jlib:jid_to_string(jlib:make_jid(jlib:jid_tolower(Initiator))), |
|
377 |
-+ activate(NormalizedInitiator, Target, SessionID); |
|
378 |
-+activate(Initiator, #jid{} = Target, SessionID) -> |
|
379 |
-+ NormalizedTarget = jlib:jid_to_string(jlib:make_jid(jlib:jid_tolower(Target))), |
|
380 |
-+ activate(Initiator, NormalizedTarget, SessionID); |
|
381 |
-+%% ...and get on with the activation. |
|
382 |
-+activate(Initiator, Target, SessionID) -> |
|
383 |
-+ Cookie = sha:sha(SessionID ++ Initiator ++ Target), |
|
384 |
-+ F = fun() -> |
|
385 |
-+ case mnesia:read({proxy65_connection, Cookie}) of |
|
386 |
-+ [#proxy65_connection{firstpid = FirstPID, |
|
387 |
-+ secondpid = SecondPID}] |
|
388 |
-+ when is_pid(FirstPID), is_pid(SecondPID) -> |
|
389 |
-+ mnesia:delete({proxy65_connection, Cookie}), |
|
390 |
-+ {FirstPID, SecondPID}; |
|
391 |
-+ _ -> |
|
392 |
-+ error |
|
393 |
-+ end |
|
394 |
-+ end, |
|
395 |
-+ case mnesia:transaction(F) of |
|
396 |
-+ {atomic, {FirstPID, SecondPID}} -> |
|
397 |
-+ FirstSocket = get_socket(FirstPID), |
|
398 |
-+ SecondSocket = get_socket(SecondPID), |
|
399 |
-+ FirstPID ! {activate, SecondSocket, Initiator, Target}, |
|
400 |
-+ SecondPID ! {activate, FirstSocket, Initiator, Target}, |
|
401 |
-+ ok; |
|
402 |
-+ Error -> |
|
403 |
-+ ?ERROR_MSG("Proxy activation failed: ~p", [Error]), |
|
404 |
-+ error |
|
405 |
-+ end. |
|
406 |
- |
... | ... |
@@ -1,17 +0,0 @@ |
1 |
-# Copyright 1999-2005 Gentoo Foundation |
|
2 |
-# Distributed under the terms of the GNU General Public License v2 |
|
3 |
-# $Header: $ |
|
4 |
- |
|
5 |
-# Name of your ejabberd node. Used by ejabberdctl to determine which |
|
6 |
-# node to communicate with. Default is "ejabberd@`hostname -s`". |
|
7 |
-#EJABBERD_NODE="ejabberd@`hostname -s`" |
|
8 |
- |
|
9 |
-# Max number of open network connections. Default is 1024. Increasing |
|
10 |
-# this will slightly increase memory usage. |
|
11 |
-#ERL_MAX_PORTS=1024 |
|
12 |
- |
|
13 |
-# Return memory to the system after using it, instead of keeping it |
|
14 |
-# allocated for future use. Decreases the memory required by ejabberd, |
|
15 |
-# but makes it run slower. Default is unset, set to any value to |
|
16 |
-# activate. |
|
17 |
-#ERL_FULLSWEEP_AFTER=0 |
... | ... |
@@ -1,60 +0,0 @@ |
1 |
-#!/sbin/runscript |
|
2 |
-# Copyright 1999-2005 Gentoo Foundation |
|
3 |
-# Distributed under the terms of the GNU General Public License v2 |
|
4 |
-# $Header: $ |
|
5 |
- |
|
6 |
-opts="${opts} reload" |
|
7 |
- |
|
8 |
-depend() { |
|
9 |
- use dns |
|
10 |
- need net |
|
11 |
- provide jabber-server |
|
12 |
-} |
|
13 |
- |
|
14 |
-checkconfig() { |
|
15 |
- if [ ! -e /etc/jabber/ejabberd.cfg ] ; then |
|
16 |
- eerror "You need an /etc/jabber/ejabberd.cfg file to run ejabberd" |
|
17 |
- return 1 |
|
18 |
- fi |
|
19 |
-} |
|
20 |
- |
|
21 |
-start() { |
|
22 |
- checkconfig || return 1 |
|
23 |
- ebegin "Starting eJabberd" |
|
24 |
- start-stop-daemon --start --quiet --chuid jabber:jabber \ |
|
25 |
- --exec /usr/bin/env HOME=/var/run/jabber /usr/bin/ejabberd -- -noshell -detached |
|
26 |
- eend $? |
|
27 |
-} |
|
28 |
- |
|
29 |
-stop() { |
|
30 |
- ebegin "Stopping eJabberd" |
|
31 |
- if [ -z "$EJABBERD_NODE" ]; |
|
32 |
- then |
|
33 |
- EJABBERD_NODE="ejabberd@`hostname -s`" |
|
34 |
- fi |
|
35 |
- /usr/bin/ejabberdctl $EJABBERD_NODE stop |
|
36 |
- eend $? |
|
37 |
-} |
|
38 |
- |
|
39 |
-# Work around a bug in /sbin/runscript.sh - it won't run our custom |
|
40 |
-# restart() unless it finds these two strings in the file. |
|
41 |
-# svc_start svc_stop |
|
42 |
-restart() { |
|
43 |
- ebegin "Restarting eJabberd" |
|
44 |
- if [ -z "$EJABBERD_NODE" ]; |
|
45 |
- then |
|
46 |
- EJABBERD_NODE="ejabberd@`hostname -s`" |
|
47 |
- fi |
|
48 |
- /usr/bin/ejabberdctl $EJABBERD_NODE restart |
|
49 |
- eend $? |
|
50 |
-} |
|
51 |
- |
|
52 |
-reload() { |
|
53 |
- ebegin "Reloading eJabberd" |
|
54 |
- if [ -z "$EJABBERD_NODE" ]; |
|
55 |
- then |
|
56 |
- EJABBERD_NODE="ejabberd@`hostname -s`" |
|
57 |
- fi |
|
58 |
- /usr/bin/ejabberdctl $EJABBERD_NODE reopen-log |
|
59 |
- eend $? |
|
60 |
-} |
... | ... |
@@ -1,934 +0,0 @@ |
1 |
-Index: src/ejabberd.cfg.example |
|
2 |
-=================================================================== |
|
3 |
---- src/ejabberd.cfg.example (Revision 565) |
|
4 |
-+++ src/ejabberd.cfg.example (Arbeitskopie) |
|
5 |
-@@ -124,7 +124,7 @@ |
|
6 |
- {5269, ejabberd_s2s_in, [{shaper, s2s_shaper}, |
|
7 |
- {max_stanza_size, 131072} |
|
8 |
- ]}, |
|
9 |
-- {5280, ejabberd_http, [http_poll, web_admin]}, |
|
10 |
-+ {5280, ejabberd_http, [http_poll, http_bind, web_admin]}, |
|
11 |
- {8888, ejabberd_service, [{access, all}, |
|
12 |
- {hosts, ["icq.localhost", "sms.localhost"], |
|
13 |
- [{password, "secret"}]}]} |
|
14 |
-Index: src/web/Makefile.in |
|
15 |
-=================================================================== |
|
16 |
---- src/web/Makefile.in (Revision 565) |
|
17 |
-+++ src/web/Makefile.in (Arbeitskopie) |
|
18 |
-@@ -15,7 +15,8 @@ |
|
19 |
- $(OUTDIR)/ejabberd_http.beam \ |
|
20 |
- $(OUTDIR)/ejabberd_web.beam \ |
|
21 |
- $(OUTDIR)/ejabberd_web_admin.beam \ |
|
22 |
-- $(OUTDIR)/ejabberd_http_poll.beam |
|
23 |
-+ $(OUTDIR)/ejabberd_http_poll.beam \ |
|
24 |
-+ $(OUTDIR)/ejabberd_http_bind.beam |
|
25 |
- |
|
26 |
- all: $(OBJS) |
|
27 |
- |
|
28 |
-Index: src/web/ejabberd_http_bind.erl |
|
29 |
-=================================================================== |
|
30 |
---- src/web/ejabberd_http_bind.erl (Revision 0) |
|
31 |
-+++ src/web/ejabberd_http_bind.erl (Revision 0) |
|
32 |
-@@ -0,0 +1,731 @@ |
|
33 |
-+%%%---------------------------------------------------------------------- |
|
34 |
-+%%% File : ejabberd_http_bind.erl |
|
35 |
-+%%% Author : Stefan Strigler <steve@zeank.in-berlin.de> |
|
36 |
-+%%% Purpose : HTTP Binding support (JEP-0124) |
|
37 |
-+%%% Created : 21 Sep 2005 by Stefan Strigler <steve@zeank.in-berlin.de> |
|
38 |
-+%%% Id : $Id: ejabberd_http_bind.erl,v 1.2 2006/01/16 10:47:50 zeank Exp $ |
|
39 |
-+%%%---------------------------------------------------------------------- |
|
40 |
-+ |
|
41 |
-+-module(ejabberd_http_bind). |
|
42 |
-+-author('steve@zeank.in-berlin.de'). |
|
43 |
-+-vsn('Revision: 1.3'). |
|
44 |
-+ |
|
45 |
-+-behaviour(gen_fsm). |
|
46 |
-+ |
|
47 |
-+%% External exports |
|
48 |
-+-export([start_link/2, |
|
49 |
-+ init/1, |
|
50 |
-+ handle_event/3, |
|
51 |
-+ handle_sync_event/4, |
|
52 |
-+ code_change/4, |
|
53 |
-+ handle_info/3, |
|
54 |
-+ terminate/3, |
|
55 |
-+ send/2, |
|
56 |
-+ setopts/2, |
|
57 |
-+ controlling_process/2, |
|
58 |
-+ close/1, |
|
59 |
-+ process_request/1]). |
|
60 |
-+ |
|
61 |
-+%%-define(ejabberd_debug, true). |
|
62 |
-+ |
|
63 |
-+-include("ejabberd.hrl"). |
|
64 |
-+-include("jlib.hrl"). |
|
65 |
-+-include("ejabberd_http.hrl"). |
|
66 |
-+ |
|
67 |
-+-record(http_bind, {id, pid, hold, wait}). |
|
68 |
-+ |
|
69 |
-+%% http binding request |
|
70 |
-+-record(hbr, {rid, |
|
71 |
-+ key, |
|
72 |
-+ in, |
|
73 |
-+ out}). |
|
74 |
-+ |
|
75 |
-+-record(state, {id, |
|
76 |
-+ rid = error, |
|
77 |
-+ key, |
|
78 |
-+ output = "", |
|
79 |
-+ input = "", |
|
80 |
-+ waiting_input = false, |
|
81 |
-+ last_receiver, |
|
82 |
-+ last_poll, |
|
83 |
-+ ctime = 0, |
|
84 |
-+ timer, |
|
85 |
-+ req_list = [] % list of requests |
|
86 |
-+ }). |
|
87 |
-+ |
|
88 |
-+ |
|
89 |
-+%-define(DBGFSM, true). |
|
90 |
-+ |
|
91 |
-+-ifdef(DBGFSM). |
|
92 |
-+-define(FSMOPTS, [{debug, [trace]}]). |
|
93 |
-+-else. |
|
94 |
-+-define(FSMOPTS, []). |
|
95 |
-+-endif. |
|
96 |
-+ |
|
97 |
-+-define(MAX_REQUESTS, 2). % number of simultaneous requests |
|
98 |
-+-define(MIN_POLLING, "2"). % don't poll faster than that or we will shoot you |
|
99 |
-+-define(MAX_WAIT, 60). % max num of secs to keep a request on hold |
|
100 |
-+-define(MAX_INACTIVITY, 30000). % msecs to wait before terminating idle sessions |
|
101 |
-+-define(CT, {"Content-Type", "text/xml; charset=utf-8"}). |
|
102 |
-+-define(BAD_REQUEST, ?CT). |
|
103 |
-+ |
|
104 |
-+ |
|
105 |
-+%%%---------------------------------------------------------------------- |
|
106 |
-+%%% API |
|
107 |
-+%%%---------------------------------------------------------------------- |
|
108 |
-+start(ID, Key) -> |
|
109 |
-+ mnesia:create_table(http_bind, |
|
110 |
-+ [{ram_copies, [node()]}, |
|
111 |
-+ {attributes, record_info(fields, http_bind)}]), |
|
112 |
-+ supervisor:start_child(ejabberd_http_bind_sup, [ID, Key]). |
|
113 |
-+ |
|
114 |
-+start_link(ID, Key) -> |
|
115 |
-+ gen_fsm:start_link(?MODULE, [ID, Key], ?FSMOPTS). |
|
116 |
-+ |
|
117 |
-+send({http_bind, FsmRef}, Packet) -> |
|
118 |
-+ gen_fsm:sync_send_all_state_event(FsmRef, {send, Packet}). |
|
119 |
-+ |
|
120 |
-+setopts({http_bind, FsmRef}, Opts) -> |
|
121 |
-+ case lists:member({active, once}, Opts) of |
|
122 |
-+ true -> |
|
123 |
-+ gen_fsm:sync_send_all_state_event(FsmRef, activate); |
|
124 |
-+ _ -> |
|
125 |
-+ ok |
|
126 |
-+ end. |
|
127 |
-+ |
|
128 |
-+controlling_process(_Socket, _Pid) -> |
|
129 |
-+ ok. |
|
130 |
-+ |
|
131 |
-+close({http_bind, FsmRef}) -> |
|
132 |
-+ catch gen_fsm:sync_send_all_state_event(FsmRef, close). |
|
133 |
-+ |
|
134 |
-+ |
|
135 |
-+process_request(#request{path = [], |
|
136 |
-+ data = Data}) -> |
|
137 |
-+ case catch parse_request(Data) of |
|
138 |
-+ {ok, ID1, RID, Key, NewKey, Attrs, Packet} -> |
|
139 |
-+ XmppDomain = xml:get_attr_s("to",Attrs), |
|
140 |
-+ if |
|
141 |
-+ (ID1 == "") and (XmppDomain == "") -> |
|
142 |
-+ {200, [?CT], "<body type='terminate' " |
|
143 |
-+ "condition='improper-addressing' " |
|
144 |
-+ "xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
145 |
-+ true -> |
|
146 |
-+ ID = if |
|
147 |
-+ (ID1 == "") -> |
|
148 |
-+ %% create new session |
|
149 |
-+ NewID = sha:sha(term_to_binary({now(), make_ref()})), |
|
150 |
-+ {ok, Pid} = start(NewID, Key), |
|
151 |
-+ Wait = case |
|
152 |
-+ string:to_integer(xml:get_attr_s("wait",Attrs)) |
|
153 |
-+ of |
|
154 |
-+ {error, _} -> |
|
155 |
-+ ?MAX_WAIT; |
|
156 |
-+ {CWait, _} -> |
|
157 |
-+ if |
|
158 |
-+ (CWait > ?MAX_WAIT) -> |
|
159 |
-+ ?MAX_WAIT; |
|
160 |
-+ true -> |
|
161 |
-+ CWait |
|
162 |
-+ end |
|
163 |
-+ end, |
|
164 |
-+ Hold = case |
|
165 |
-+ string:to_integer( |
|
166 |
-+ xml:get_attr_s("hold",Attrs)) |
|
167 |
-+ of |
|
168 |
-+ {error, _} -> |
|
169 |
-+ (?MAX_REQUESTS - 1); |
|
170 |
-+ {CHold, _} -> |
|
171 |
-+ if |
|
172 |
-+ (CHold > (?MAX_REQUESTS - 1)) -> |
|
173 |
-+ (?MAX_REQUESTS - 1); |
|
174 |
-+ true -> |
|
175 |
-+ CHold |
|
176 |
-+ end |
|
177 |
-+ end, |
|
178 |
-+ mnesia:transaction( |
|
179 |
-+ fun() -> |
|
180 |
-+ mnesia:write(#http_bind{id = NewID, |
|
181 |
-+ pid = Pid, |
|
182 |
-+ wait = Wait, |
|
183 |
-+ hold = Hold}) |
|
184 |
-+ end), |
|
185 |
-+ InPacket = if |
|
186 |
-+ (XmppDomain /= "") -> |
|
187 |
-+ ["<stream:stream to='", |
|
188 |
-+ XmppDomain, |
|
189 |
-+ "' xmlns='jabber:client' " |
|
190 |
-+ "xmlns:stream='http://etherx.jabber.org/streams'>"]; |
|
191 |
-+ true -> |
|
192 |
-+ "" |
|
193 |
-+ end, |
|
194 |
-+ NewID; |
|
195 |
-+ true -> |
|
196 |
-+ %% old session |
|
197 |
-+ Type = xml:get_attr_s("type",Attrs), |
|
198 |
-+ Wait = ?MAX_WAIT, |
|
199 |
-+ Hold = (?MAX_REQUESTS - 1), |
|
200 |
-+ if |
|
201 |
-+ (Type == "terminate") -> |
|
202 |
-+ %% terminate session |
|
203 |
-+ InPacket = Packet ++ "</stream:stream>"; |
|
204 |
-+ true -> |
|
205 |
-+ InPacket = Packet |
|
206 |
-+ end, |
|
207 |
-+ ID1 |
|
208 |
-+ end, |
|
209 |
-+%% ?DEBUG("~n InPacket: ~s ~n", [InPacket]), |
|
210 |
-+ case http_put(ID, RID, Key, NewKey, Hold, InPacket) of |
|
211 |
-+ {error, not_exists} -> |
|
212 |
-+ ?DEBUG("no session associated with sid: ~p", [ID]), |
|
213 |
-+ {404, [?BAD_REQUEST], ""}; |
|
214 |
-+ {error, bad_key} -> |
|
215 |
-+ ?DEBUG("bad key: ~s", Key), |
|
216 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
217 |
-+ [] -> |
|
218 |
-+ {404, [?BAD_REQUEST], ""}; |
|
219 |
-+ [#http_bind{pid = FsmRef}] -> |
|
220 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop), |
|
221 |
-+ {404, [?BAD_REQUEST], ""} |
|
222 |
-+ end; |
|
223 |
-+ {error, polling_too_frequently} -> |
|
224 |
-+ ?DEBUG("polling too frequently: ~p", [ID]), |
|
225 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
226 |
-+ [] -> %% unlikely! (?) |
|
227 |
-+ {404, [?BAD_REQUEST], ""}; |
|
228 |
-+ [#http_bind{pid = FsmRef}] -> |
|
229 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop), |
|
230 |
-+ {403, [?BAD_REQUEST], ""} |
|
231 |
-+ end; |
|
232 |
-+ {repeat, OutPacket} -> |
|
233 |
-+ ?DEBUG("http_put said 'repeat!' ...~nOutPacket: ~p", |
|
234 |
-+ [OutPacket]), |
|
235 |
-+ send_outpacket(ID, OutPacket); |
|
236 |
-+ ok -> |
|
237 |
-+ receive_loop(ID,ID1,RID,Wait,Hold,Attrs) |
|
238 |
-+ end |
|
239 |
-+ end; |
|
240 |
-+ _ -> |
|
241 |
-+ {400, [?BAD_REQUEST], ""} |
|
242 |
-+ end; |
|
243 |
-+process_request(_Request) -> |
|
244 |
-+ {400, [], {xmlelement, "h1", [], |
|
245 |
-+ [{xmlcdata, "400 Bad Request"}]}}. |
|
246 |
-+ |
|
247 |
-+receive_loop(ID,ID1,RID,Wait,Hold,Attrs) -> |
|
248 |
-+ receive |
|
249 |
-+ after 100 -> ok |
|
250 |
-+ end, |
|
251 |
-+ prepare_response(ID,ID1,RID,Wait,Hold,Attrs). |
|
252 |
-+ |
|
253 |
-+prepare_response(ID,ID1,RID,Wait,Hold,Attrs) -> |
|
254 |
-+ case http_get(ID,RID) of |
|
255 |
-+ {error, not_exists} -> |
|
256 |
-+ ?DEBUG("no session associated with sid: ~s", ID), |
|
257 |
-+ {404, [?BAD_REQUEST], ""}; |
|
258 |
-+ {ok, keep_on_hold} -> |
|
259 |
-+ receive_loop(ID,ID1,RID,Wait,Hold,Attrs); |
|
260 |
-+ {ok, cancel} -> |
|
261 |
-+ %% actually it would be better if we could completely |
|
262 |
-+ %% cancel this request, but then we would have to hack |
|
263 |
-+ %% ejabberd_http and I'm too lazy now |
|
264 |
-+ {404, [?BAD_REQUEST], ""}; |
|
265 |
-+ {ok, OutPacket} -> |
|
266 |
-+ ?DEBUG("OutPacket: ~s", [OutPacket]), |
|
267 |
-+ if |
|
268 |
-+ ID == ID1 -> |
|
269 |
-+ send_outpacket(ID, OutPacket); |
|
270 |
-+ true -> |
|
271 |
-+ To = xml:get_attr_s("to",Attrs), |
|
272 |
-+ case xml_stream:parse_element( |
|
273 |
-+ OutPacket++"</stream:stream>") of |
|
274 |
-+ El when element(1, El) == xmlelement -> |
|
275 |
-+ {xmlelement, _, OutAttrs, _} = El, |
|
276 |
-+ AuthID = xml:get_attr_s("id", OutAttrs), |
|
277 |
-+ StreamError = false; |
|
278 |
-+ {error, _} -> |
|
279 |
-+ AuthID = "", |
|
280 |
-+ StreamError = true |
|
281 |
-+ end, |
|
282 |
-+ if |
|
283 |
-+ To == "" -> |
|
284 |
-+ {200, [?CT], "<body type='terminate' " |
|
285 |
-+ "condition='improper-addressing' " |
|
286 |
-+ "xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
287 |
-+ StreamError == true -> |
|
288 |
-+ {200, [?CT], "<body type='terminate' " |
|
289 |
-+ "condition='host-unknown' " |
|
290 |
-+ "xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
291 |
-+ true -> |
|
292 |
-+ {200, [?CT], |
|
293 |
-+ xml:element_to_string( |
|
294 |
-+ {xmlelement,"body", |
|
295 |
-+ [{"xmlns", |
|
296 |
-+ "http://jabber.org/protocol/httpbind"}, |
|
297 |
-+ {"sid",ID}, |
|
298 |
-+ {"wait", integer_to_list(Wait)}, |
|
299 |
-+ {"requests", integer_to_list(Hold+1)}, |
|
300 |
-+ {"inactivity", |
|
301 |
-+ integer_to_list(trunc(?MAX_INACTIVITY/1000))}, |
|
302 |
-+ {"polling", ?MIN_POLLING}, |
|
303 |
-+ {"authid", AuthID} |
|
304 |
-+ ],[]})} |
|
305 |
-+ end |
|
306 |
-+ end |
|
307 |
-+ end. |
|
308 |
-+ |
|
309 |
-+send_outpacket(ID, OutPacket) -> |
|
310 |
-+ case OutPacket of |
|
311 |
-+ "" -> |
|
312 |
-+ {200, [?CT], "<body xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
313 |
-+ "</stream:stream>" -> |
|
314 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
315 |
-+ [#http_bind{pid = FsmRef}] -> |
|
316 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop) |
|
317 |
-+ end, |
|
318 |
-+ {200, [?CT], "<body xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
319 |
-+ _ -> |
|
320 |
-+ case xml_stream:parse_element("<body>" |
|
321 |
-+ ++ OutPacket |
|
322 |
-+ ++ "</body>") |
|
323 |
-+ of |
|
324 |
-+ El when element(1, El) == xmlelement -> |
|
325 |
-+ {xmlelement, _, _, OEls} = El, |
|
326 |
-+ TypedEls = [xml:replace_tag_attr("xmlns", |
|
327 |
-+ "jabber:client",OEl) || |
|
328 |
-+ OEl <- OEls], |
|
329 |
-+ ?DEBUG(" --- outgoing data --- ~n~s~n --- END --- ~n", |
|
330 |
-+ [xml:element_to_string( |
|
331 |
-+ {xmlelement,"body", |
|
332 |
-+ [{"xmlns", |
|
333 |
-+ "http://jabber.org/protocol/httpbind"}], |
|
334 |
-+ TypedEls})] |
|
335 |
-+ ), |
|
336 |
-+ {200, [?CT], |
|
337 |
-+ xml:element_to_string( |
|
338 |
-+ {xmlelement,"body", |
|
339 |
-+ [{"xmlns", |
|
340 |
-+ "http://jabber.org/protocol/httpbind"}], |
|
341 |
-+ TypedEls})}; |
|
342 |
-+ {error, _E} -> |
|
343 |
-+ ?DEBUG("parse error: ~p", [_E]), |
|
344 |
-+ StreamErrCond = case xml_stream:parse_element( |
|
345 |
-+ "<stream:stream>"++OutPacket) of |
|
346 |
-+ El when element(1, El) == xmlelement -> |
|
347 |
-+ {xmlelement, _Tag, _Attr, Els} = El, |
|
348 |
-+ [{xmlelement, SE, _, Cond} | _] = Els, |
|
349 |
-+ if |
|
350 |
-+ SE == "stream:error" -> |
|
351 |
-+ Cond; |
|
352 |
-+ true -> |
|
353 |
-+ null |
|
354 |
-+ end; |
|
355 |
-+ {error, _E} -> |
|
356 |
-+ null |
|
357 |
-+ end, |
|
358 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
359 |
-+ [#http_bind{pid = FsmRef}] -> |
|
360 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop); |
|
361 |
-+ _ -> |
|
362 |
-+ err %% hu? |
|
363 |
-+ end, |
|
364 |
-+ case StreamErrCond of |
|
365 |
-+ null -> |
|
366 |
-+ {200, [?CT], |
|
367 |
-+ "<body type='terminate' " |
|
368 |
-+ "condition='internal-server-error' " |
|
369 |
-+ "xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
370 |
-+ _ -> |
|
371 |
-+ {200, [?CT], |
|
372 |
-+ "<body type='terminate' " |
|
373 |
-+ "condition='remote-stream-error' " |
|
374 |
-+ "xmlns='http://jabber.org/protocol/httpbind'>" ++ |
|
375 |
-+ elements_to_string(StreamErrCond) ++ |
|
376 |
-+ "</body>"} |
|
377 |
-+ end |
|
378 |
-+ end |
|
379 |
-+ end. |
|
380 |
-+ |
|
381 |
-+%%%---------------------------------------------------------------------- |
|
382 |
-+%%% Callback functions from gen_fsm |
|
383 |
-+%%%---------------------------------------------------------------------- |
|
384 |
-+ |
|
385 |
-+%%---------------------------------------------------------------------- |
|
386 |
-+%% Func: init/1 |
|
387 |
-+%% Returns: {ok, StateName, StateData} | |
|
388 |
-+%% {ok, StateName, StateData, Timeout} | |
|
389 |
-+%% ignore | |
|
390 |
-+%% {stop, StopReason} |
|
391 |
-+%%---------------------------------------------------------------------- |
|
392 |
-+init([ID, Key]) -> |
|
393 |
-+ ?INFO_MSG("started: ~p", [{ID, Key}]), |
|
394 |
-+ Opts = [], % TODO |
|
395 |
-+ {ok, C2SPid} = ejabberd_c2s:start({?MODULE, {http_bind, self()}}, Opts), |
|
396 |
-+ ejabberd_c2s:become_controller(C2SPid), |
|
397 |
-+ Timer = erlang:start_timer(?MAX_INACTIVITY, self(), []), |
|
398 |
-+ {ok, loop, #state{id = ID, |
|
399 |
-+ key = Key, |
|
400 |
-+ timer = Timer}}. |
|
401 |
-+ |
|
402 |
-+%%---------------------------------------------------------------------- |
|
403 |
-+%% Func: StateName/2 |
|
404 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
405 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
406 |
-+%% {stop, Reason, NewStateData} |
|
407 |
-+%%---------------------------------------------------------------------- |
|
408 |
-+ |
|
409 |
-+ |
|
410 |
-+%%---------------------------------------------------------------------- |
|
411 |
-+%% Func: StateName/3 |
|
412 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
413 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
414 |
-+%% {reply, Reply, NextStateName, NextStateData} | |
|
415 |
-+%% {reply, Reply, NextStateName, NextStateData, Timeout} | |
|
416 |
-+%% {stop, Reason, NewStateData} | |
|
417 |
-+%% {stop, Reason, Reply, NewStateData} |
|
418 |
-+%%---------------------------------------------------------------------- |
|
419 |
-+%state_name(Event, From, StateData) -> |
|
420 |
-+% Reply = ok, |
|
421 |
-+% {reply, Reply, state_name, StateData}. |
|
422 |
-+ |
|
423 |
-+%%---------------------------------------------------------------------- |
|
424 |
-+%% Func: handle_event/3 |
|
425 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
426 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
427 |
-+%% {stop, Reason, NewStateData} |
|
428 |
-+%%---------------------------------------------------------------------- |
|
429 |
-+handle_event(_Event, StateName, StateData) -> |
|
430 |
-+ {next_state, StateName, StateData}. |
|
431 |
-+ |
|
432 |
-+%%---------------------------------------------------------------------- |
|
433 |
-+%% Func: handle_sync_event/4 |
|
434 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
435 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
436 |
-+%% {reply, Reply, NextStateName, NextStateData} | |
|
437 |
-+%% {reply, Reply, NextStateName, NextStateData, Timeout} | |
|
438 |
-+%% {stop, Reason, NewStateData} | |
|
439 |
-+%% {stop, Reason, Reply, NewStateData} |
|
440 |
-+%%---------------------------------------------------------------------- |
|
441 |
-+handle_sync_event({send, Packet}, _From, StateName, StateData) -> |
|
442 |
-+ Output = [StateData#state.output | Packet], |
|
443 |
-+ Reply = ok, |
|
444 |
-+ {reply, Reply, StateName, StateData#state{output = Output}}; |
|
445 |
-+ |
|
446 |
-+handle_sync_event(activate, From, StateName, StateData) -> |
|
447 |
-+ case StateData#state.input of |
|
448 |
-+ "" -> |
|
449 |
-+ {reply, ok, StateName, StateData#state{ |
|
450 |
-+ waiting_input = From}}; |
|
451 |
-+ Input -> |
|
452 |
-+ From ! {tcp, {http_bind, self()}, list_to_binary(Input)}, |
|
453 |
-+ {reply, ok, StateName, StateData#state{ |
|
454 |
-+ input = "", |
|
455 |
-+ waiting_input = false, |
|
456 |
-+ last_receiver = From}} |
|
457 |
-+ end; |
|
458 |
-+ |
|
459 |
-+handle_sync_event(stop, _From, _StateName, StateData) -> |
|
460 |
-+ Reply = ok, |
|
461 |
-+ {stop, normal, Reply, StateData}; |
|
462 |
-+ |
|
463 |
-+handle_sync_event({http_put, RID, Key, NewKey, Hold, Packet}, |
|
464 |
-+ _From, StateName, StateData) -> |
|
465 |
-+ %% check if RID valid |
|
466 |
-+ RidAllow = case RID of |
|
467 |
-+ error -> |
|
468 |
-+ false; |
|
469 |
-+ _ -> |
|
470 |
-+ case StateData#state.rid of |
|
471 |
-+ error -> |
|
472 |
-+ %% first request - nothing saved so far |
|
473 |
-+ true; |
|
474 |
-+ OldRID -> |
|
475 |
-+ ?DEBUG("state.rid/cur rid: ~p/~p", |
|
476 |
-+ [OldRID, RID]), |
|
477 |
-+ if |
|
478 |
-+ (OldRID < RID) and |
|
479 |
-+ (RID =< (OldRID + Hold + 1)) -> |
|
480 |
-+ true; |
|
481 |
-+ (RID =< OldRID) and |
|
482 |
-+ (RID > OldRID - Hold - 1) -> |
|
483 |
-+ repeat; |
|
484 |
-+ true -> |
|
485 |
-+ false |
|
486 |
-+ end |
|
487 |
-+ end |
|
488 |
-+ end, |
|
489 |
-+ %% check if key valid |
|
490 |
-+ KeyAllow = case RidAllow of |
|
491 |
-+ repeat -> |
|
492 |
-+ true; |
|
493 |
-+ false -> |
|
494 |
-+ false; |
|
495 |
-+ true -> |
|
496 |
-+ case StateData#state.key of |
|
497 |
-+ "" -> |
|
498 |
-+ true; |
|
499 |
-+ OldKey -> |
|
500 |
-+ NextKey = httpd_util:to_lower( |
|
501 |
-+ hex(binary_to_list( |
|
502 |
-+ crypto:sha(Key)))), |
|
503 |
-+ ?DEBUG("Key/OldKey/NextKey: ~s/~s/~s", |
|
504 |
-+ [Key, OldKey, NextKey]), |
|
505 |
-+ if |
|
506 |
-+ OldKey == NextKey -> |
|
507 |
-+ true; |
|
508 |
-+ true -> |
|
509 |
-+ ?DEBUG("wrong key: ~s",[Key]), |
|
510 |
-+ false |
|
511 |
-+ end |
|
512 |
-+ end |
|
513 |
-+ end, |
|
514 |
-+ {_,TSec,TMSec} = now(), |
|
515 |
-+ TNow = TSec*1000*1000 + TMSec, |
|
516 |
-+ LastPoll = if |
|
517 |
-+ Packet == "" -> |
|
518 |
-+ TNow; |
|
519 |
-+ true -> |
|
520 |
-+ 0 |
|
521 |
-+ end, |
|
522 |
-+ {MinPoll, _} = string:to_integer(?MIN_POLLING), |
|
523 |
-+ if |
|
524 |
-+ (Packet == "") and |
|
525 |
-+ (TNow - StateData#state.last_poll < MinPoll*1000*1000) -> |
|
526 |
-+ Reply = {error, polling_too_frequently}, |
|
527 |
-+ {reply, Reply, StateName, StateData}; |
|
528 |
-+ KeyAllow -> |
|
529 |
-+ case RidAllow of |
|
530 |
-+ false -> |
|
531 |
-+ Reply = {error, not_exists}, |
|
532 |
-+ {reply, Reply, StateName, StateData}; |
|
533 |
-+ repeat -> |
|
534 |
-+ ?DEBUG("REPEATING ~p", [RID]), |
|
535 |
-+ [Out | _XS] = [El#hbr.out || |
|
536 |
-+ El <- StateData#state.req_list, |
|
537 |
-+ El#hbr.rid == RID], |
|
538 |
-+ case Out of |
|
539 |
-+ [[] | OutPacket] -> |
|
540 |
-+ Reply = {repeat, OutPacket}; |
|
541 |
-+ _ -> |
|
542 |
-+ Reply = {repeat, Out} |
|
543 |
-+ end, |
|
544 |
-+ {reply, Reply, StateName, |
|
545 |
-+ StateData#state{input = "cancel", last_poll = LastPoll}}; |
|
546 |
-+ true -> |
|
547 |
-+ SaveKey = if |
|
548 |
-+ NewKey == "" -> |
|
549 |
-+ Key; |
|
550 |
-+ true -> |
|
551 |
-+ NewKey |
|
552 |
-+ end, |
|
553 |
-+ ?DEBUG(" -- SaveKey: ~s~n", [SaveKey]), |
|
554 |
-+ |
|
555 |
-+ %% save request |
|
556 |
-+ ReqList = [#hbr{rid=RID, |
|
557 |
-+ key=StateData#state.key, |
|
558 |
-+ in=StateData#state.input, |
|
559 |
-+ out=StateData#state.output |
|
560 |
-+ } | |
|
561 |
-+ [El || El <- StateData#state.req_list, |
|
562 |
-+ El#hbr.rid < RID, |
|
563 |
-+ El#hbr.rid > (RID - 1 - Hold)] |
|
564 |
-+ ], |
|
565 |
-+%% ?DEBUG("reqlist: ~p", [ReqList]), |
|
566 |
-+ case StateData#state.waiting_input of |
|
567 |
-+ false -> |
|
568 |
-+ cancel_timer(StateData#state.timer), |
|
569 |
-+ Timer = erlang:start_timer( |
|
570 |
-+ ?MAX_INACTIVITY, self(), []), |
|
571 |
-+ Input = Packet ++ [StateData#state.input], |
|
572 |
-+ Reply = ok, |
|
573 |
-+ {reply, Reply, StateName, |
|
574 |
-+ StateData#state{input = Input, |
|
575 |
-+ rid = RID, |
|
576 |
-+ key = SaveKey, |
|
577 |
-+ ctime = TNow, |
|
578 |
-+ timer = Timer, |
|
579 |
-+ last_poll = LastPoll, |
|
580 |
-+ req_list = ReqList |
|
581 |
-+ }}; |
|
582 |
-+ {Receiver, _Tag} -> |
|
583 |
-+ Receiver ! {tcp, {http_bind, self()}, |
|
584 |
-+ list_to_binary(Packet)}, |
|
585 |
-+ cancel_timer(StateData#state.timer), |
|
586 |
-+ Timer = erlang:start_timer( |
|
587 |
-+ ?MAX_INACTIVITY, self(), []), |
|
588 |
-+ Reply = ok, |
|
589 |
-+ {reply, Reply, StateName, |
|
590 |
-+ StateData#state{waiting_input = false, |
|
591 |
-+ last_receiver = Receiver, |
|
592 |
-+ input = "", |
|
593 |
-+ rid = RID, |
|
594 |
-+ key = SaveKey, |
|
595 |
-+ ctime = TNow, |
|
596 |
-+ timer = Timer, |
|
597 |
-+ last_poll = LastPoll, |
|
598 |
-+ req_list = ReqList |
|
599 |
-+ }} |
|
600 |
-+ end |
|
601 |
-+ end; |
|
602 |
-+ true -> |
|
603 |
-+ Reply = {error, bad_key}, |
|
604 |
-+ {reply, Reply, StateName, StateData} |
|
605 |
-+ end; |
|
606 |
-+ |
|
607 |
-+handle_sync_event({http_get, RID, Wait, Hold}, _From, StateName, StateData) -> |
|
608 |
-+ {_,TSec,TMSec} = now(), |
|
609 |
-+ TNow = TSec*1000*1000 + TMSec, |
|
610 |
-+ cancel_timer(StateData#state.timer), |
|
611 |
-+ Timer = erlang:start_timer(?MAX_INACTIVITY, self(), []), |
|
612 |
-+ if |
|
613 |
-+ (Hold > 0) and |
|
614 |
-+ (StateData#state.output == "") and |
|
615 |
-+ ((TNow - StateData#state.ctime) < (Wait*1000*1000)) and |
|
616 |
-+ (StateData#state.rid == RID) and |
|
617 |
-+ (StateData#state.input /= "cancel") -> |
|
618 |
-+ Output = StateData#state.output, |
|
619 |
-+ ReqList = StateData#state.req_list, |
|
620 |
-+ Reply = {ok, keep_on_hold}; |
|
621 |
-+ (StateData#state.input == "cancel") -> |
|
622 |
-+ Output = StateData#state.output, |
|
623 |
-+ ReqList = StateData#state.req_list, |
|
624 |
-+ Reply = {ok, cancel}; |
|
625 |
-+ true -> |
|
626 |
-+ case StateData#state.output of |
|
627 |
-+ [[]| OutPacket] -> |
|
628 |
-+ Reply = {ok, OutPacket}; |
|
629 |
-+ _ -> |
|
630 |
-+ Reply = {ok, StateData#state.output} |
|
631 |
-+ end, |
|
632 |
-+ %% save request |
|
633 |
-+ ReqList = [#hbr{rid=RID, |
|
634 |
-+ key=StateData#state.key, |
|
635 |
-+ in=StateData#state.input, |
|
636 |
-+ out=StateData#state.output |
|
637 |
-+ } | |
|
638 |
-+ [El || El <- StateData#state.req_list, |
|
639 |
-+ El#hbr.rid /= RID ] |
|
640 |
-+ ], |
|
641 |
-+ Output = "" |
|
642 |
-+ end, |
|
643 |
-+ {reply, Reply, StateName, StateData#state{ |
|
644 |
-+ input = "", |
|
645 |
-+ output = Output, |
|
646 |
-+ timer = Timer, |
|
647 |
-+ req_list = ReqList}}; |
|
648 |
-+ |
|
649 |
-+handle_sync_event(_Event, _From, StateName, StateData) -> |
|
650 |
-+ Reply = ok, |
|
651 |
-+ {reply, Reply, StateName, StateData}. |
|
652 |
-+ |
|
653 |
-+code_change(_OldVsn, StateName, StateData, _Extra) -> |
|
654 |
-+ {ok, StateName, StateData}. |
|
655 |
-+ |
|
656 |
-+%%---------------------------------------------------------------------- |
|
657 |
-+%% Func: handle_info/3 |
|
658 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
659 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
660 |
-+%% {stop, Reason, NewStateData} |
|
661 |
-+%%---------------------------------------------------------------------- |
|
662 |
-+handle_info({timeout, Timer, _}, _StateName, |
|
663 |
-+ #state{timer = Timer} = StateData) -> |
|
664 |
-+ ?DEBUG("ding dong", []), |
|
665 |
-+ {stop, normal, StateData}; |
|
666 |
-+ |
|
667 |
-+handle_info(_, StateName, StateData) -> |
|
668 |
-+ {next_state, StateName, StateData}. |
|
669 |
-+ |
|
670 |
-+%%---------------------------------------------------------------------- |
|
671 |
-+%% Func: terminate/3 |
|
672 |
-+%% Purpose: Shutdown the fsm |
|
673 |
-+%% Returns: any |
|
674 |
-+%%---------------------------------------------------------------------- |
|
675 |
-+terminate(_Reason, _StateName, StateData) -> |
|
676 |
-+ ?DEBUG("terminate: deleting session ~s", [StateData#state.id]), |
|
677 |
-+ mnesia:transaction( |
|
678 |
-+ fun() -> |
|
679 |
-+ mnesia:delete({http_bind, StateData#state.id}) |
|
680 |
-+ end), |
|
681 |
-+ case StateData#state.waiting_input of |
|
682 |
-+ false -> |
|
683 |
-+ case StateData#state.last_receiver of |
|
684 |
-+ undefined -> ok; |
|
685 |
-+ Receiver -> Receiver ! {tcp_closed, {http_bind, self()}} |
|
686 |
-+ end; |
|
687 |
-+ {Receiver, _Tag} -> Receiver ! {tcp_closed, {http_bind, self()}} |
|
688 |
-+ end, |
|
689 |
-+ ok. |
|
690 |
-+ |
|
691 |
-+%%%---------------------------------------------------------------------- |
|
692 |
-+%%% Internal functions |
|
693 |
-+%%%---------------------------------------------------------------------- |
|
694 |
-+ |
|
695 |
-+ |
|
696 |
-+http_put(ID, RID, Key, NewKey, Hold, Packet) -> |
|
697 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
698 |
-+ [] -> |
|
699 |
-+ {error, not_exists}; |
|
700 |
-+ [#http_bind{pid = FsmRef}] -> |
|
701 |
-+ gen_fsm:sync_send_all_state_event( |
|
702 |
-+ FsmRef, {http_put, RID, Key, NewKey, Hold, Packet}) |
|
703 |
-+ end. |
|
704 |
-+ |
|
705 |
-+http_get(ID,RID) -> |
|
706 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
707 |
-+ [] -> |
|
708 |
-+ {error, not_exists}; |
|
709 |
-+ [#http_bind{pid = FsmRef, wait = Wait, hold = Hold}] -> |
|
710 |
-+ gen_fsm:sync_send_all_state_event(FsmRef, |
|
711 |
-+ {http_get, RID, Wait, Hold}) |
|
712 |
-+ end. |
|
713 |
-+ |
|
714 |
-+ |
|
715 |
-+parse_request(Data) -> |
|
716 |
-+ ?DEBUG("--- incoming data --- ~n~s~n --- END --- ", |
|
717 |
-+ [Data]), |
|
718 |
-+ case xml_stream:parse_element(Data) of |
|
719 |
-+ El when element(1, El) == xmlelement -> |
|
720 |
-+ {xmlelement, Name, Attrs, Els} = El, |
|
721 |
-+ ID = xml:get_attr_s("sid",Attrs), |
|
722 |
-+ {RID,_X} = string:to_integer(xml:get_attr_s("rid",Attrs)), |
|
723 |
-+ Key = xml:get_attr_s("key",Attrs), |
|
724 |
-+ NewKey = xml:get_attr_s("newkey",Attrs), |
|
725 |
-+ Xmlns = xml:get_attr_s("xmlns",Attrs), |
|
726 |
-+ Packet = [xml:element_to_string( |
|
727 |
-+ xml:remove_tag_attr("xmlns",E)) || |
|
728 |
-+ E <- Els], |
|
729 |
-+ if |
|
730 |
-+ Name /= "body" -> |
|
731 |
-+ {error, bad_request}; |
|
732 |
-+ Xmlns /= "http://jabber.org/protocol/httpbind" -> |
|
733 |
-+ {error, bad_request}; |
|
734 |
-+ true -> |
|
735 |
-+ {ok, ID, RID, Key, NewKey, Attrs, Packet} |
|
736 |
-+ end; |
|
737 |
-+ {error, _Reason} -> |
|
738 |
-+ {error, bad_request} |
|
739 |
-+ end. |
|
740 |
-+ |
|
741 |
-+cancel_timer(Timer) -> |
|
742 |
-+ erlang:cancel_timer(Timer), |
|
743 |
-+ receive |
|
744 |
-+ {timeout, Timer, _} -> |
|
745 |
-+ ok |
|
746 |
-+ after 0 -> |
|
747 |
-+ ok |
|
748 |
-+ end. |
|
749 |
-+ |
|
750 |
-+hex(Bin) when binary(Bin) -> hex(binary_to_list(Bin)); |
|
751 |
-+hex([]) -> ""; |
|
752 |
-+hex([H|T]) -> |
|
753 |
-+ [A,B] = if |
|
754 |
-+ H == 0 -> "00"; |
|
755 |
-+ H < 16 -> [$0,element(H,{$1,$2,$3,$4,$5,$6,$7,$8,$9,$a,$b,$c,$d,$e,$f})]; |
|
756 |
-+ true -> erlang:integer_to_list(H,16) |
|
757 |
-+ end, |
|
758 |
-+ [A,B|hex(T)]. |
|
759 |
-+ |
|
760 |
-+elements_to_string([]) -> |
|
761 |
-+ []; |
|
762 |
-+elements_to_string([El | Els]) -> |
|
763 |
-+ xml:element_to_string(El) ++ elements_to_string(Els). |
|
764 |
-Index: src/web/ejabberd_web.erl |
|
765 |
-=================================================================== |
|
766 |
---- src/web/ejabberd_web.erl (Revision 565) |
|
767 |
-+++ src/web/ejabberd_web.erl (Arbeitskopie) |
|
768 |
-@@ -49,7 +49,7 @@ |
|
769 |
- {"value", Value}])). |
|
770 |
- |
|
771 |
- |
|
772 |
--process_get({_, true}, |
|
773 |
-+process_get({_, _, true}, |
|
774 |
- #request{auth = Auth, |
|
775 |
- path = ["admin", "server", SHost | RPath], |
|
776 |
- q = Query, |
|
777 |
-@@ -94,7 +94,7 @@ |
|
778 |
- {404, [], make_xhtml([?XC("h1", "Not found")])} |
|
779 |
- end; |
|
780 |
- |
|
781 |
--process_get({_, true}, |
|
782 |
-+process_get({_, _, true}, |
|
783 |
- #request{auth = Auth, |
|
784 |
- path = ["admin" | RPath], |
|
785 |
- q = Query, |
|
786 |
-@@ -133,12 +133,19 @@ |
|
787 |
- [{xmlcdata, "401 Unauthorized"}]}])} |
|
788 |
- end; |
|
789 |
- |
|
790 |
--process_get({true, _}, |
|
791 |
-+process_get({true, _, _}, |
|
792 |
- #request{path = ["http-poll" | RPath], |
|
793 |
- q = _Query, |
|
794 |
- lang = _Lang} = Request) -> |
|
795 |
- ejabberd_http_poll:process_request(Request#request{path = RPath}); |
|
796 |
- |
|
797 |
-+process_get({_, true, _}, |
|
798 |
-+ #request{us = _US, |
|
799 |
-+ path = ["http-bind" | RPath], |
|
800 |
-+ q = _Query, |
|
801 |
-+ lang = _Lang} = Request) -> |
|
802 |
-+ ejabberd_http_bind:process_request(Request#request{path = RPath}); |
|
803 |
-+ |
|
804 |
- process_get(_, _Request) -> |
|
805 |
- {404, [], make_xhtml([?XC("h1", "Not found")])}. |
|
806 |
- |
|
807 |
-Index: src/web/ejabberd_http.erl |
|
808 |
-=================================================================== |
|
809 |
---- src/web/ejabberd_http.erl (Revision 565) |
|
810 |
-+++ src/web/ejabberd_http.erl (Arbeitskopie) |
|
811 |
-@@ -30,6 +30,7 @@ |
|
812 |
- request_keepalive, |
|
813 |
- request_content_length, |
|
814 |
- request_lang = "en", |
|
815 |
-+ use_http_bind = false, |
|
816 |
- use_http_poll = false, |
|
817 |
- use_web_admin = false, |
|
818 |
- end_of_request = false, |
|
819 |
-@@ -70,15 +71,17 @@ |
|
820 |
- _ -> |
|
821 |
- ok |
|
822 |
- end, |
|
823 |
-+ UseHTTPBind = lists:member(http_bind, Opts), |
|
824 |
- UseHTTPPoll = lists:member(http_poll, Opts), |
|
825 |
- UseWebAdmin = lists:member(web_admin, Opts), |
|
826 |
-- ?DEBUG("S: ~p~n", [{UseHTTPPoll, UseWebAdmin}]), |
|
827 |
-+ ?DEBUG("S: ~p~n", [{UseHTTPPoll, UseHTTPBind, UseWebAdmin}]), |
|
828 |
- ?INFO_MSG("started: ~p", [{SockMod1, Socket1}]), |
|
829 |
- {ok, proc_lib:spawn_link(ejabberd_http, |
|
830 |
- receive_headers, |
|
831 |
- [#state{sockmod = SockMod1, |
|
832 |
- socket = Socket1, |
|
833 |
- use_http_poll = UseHTTPPoll, |
|
834 |
-+ use_http_bind = UseHTTPBind, |
|
835 |
- use_web_admin = UseWebAdmin}])}. |
|
836 |
- |
|
837 |
- |
|
838 |
-@@ -185,6 +188,7 @@ |
|
839 |
- #state{sockmod = SockMod, |
|
840 |
- socket = Socket, |
|
841 |
- use_http_poll = State#state.use_http_poll, |
|
842 |
-+ use_http_bind = State#state.use_http_bind, |
|
843 |
- use_web_admin = State#state.use_web_admin}; |
|
844 |
- _ -> |
|
845 |
- #state{end_of_request = true} |
|
846 |
-@@ -200,6 +204,7 @@ |
|
847 |
- request_auth = Auth, |
|
848 |
- request_lang = Lang, |
|
849 |
- use_http_poll = UseHTTPPoll, |
|
850 |
-+ use_http_bind = UseHTTPBind, |
|
851 |
- use_web_admin = UseWebAdmin} = State) -> |
|
852 |
- case (catch url_decode_q_split(Path)) of |
|
853 |
- {'EXIT', _} -> |
|
854 |
-@@ -217,7 +222,7 @@ |
|
855 |
- q = LQuery, |
|
856 |
- auth = Auth, |
|
857 |
- lang = Lang}, |
|
858 |
-- case ejabberd_web:process_get({UseHTTPPoll, UseWebAdmin}, |
|
859 |
-+ case ejabberd_web:process_get({UseHTTPPoll, UseHTTPBind, UseWebAdmin}, |
|
860 |
- Request) of |
|
861 |
- El when element(1, El) == xmlelement -> |
|
862 |
- make_xhtml_output(State, 200, [], El); |
|
863 |
-@@ -240,6 +245,7 @@ |
|
864 |
- sockmod = SockMod, |
|
865 |
- socket = Socket, |
|
866 |
- use_http_poll = UseHTTPPoll, |
|
867 |
-+ use_http_bind = UseHTTPBind, |
|
868 |
- use_web_admin = UseWebAdmin} = State) |
|
869 |
- when is_integer(Len) -> |
|
870 |
- case SockMod of |
|
871 |
-@@ -267,7 +273,7 @@ |
|
872 |
- auth = Auth, |
|
873 |
- data = Data, |
|
874 |
- lang = Lang}, |
|
875 |
-- case ejabberd_web:process_get({UseHTTPPoll, UseWebAdmin}, |
|
876 |
-+ case ejabberd_web:process_get({UseHTTPPoll, UseHTTPBind, UseWebAdmin}, |
|
877 |
- Request) of |
|
878 |
- El when element(1, El) == xmlelement -> |
|
879 |
- make_xhtml_output(State, 200, [], El); |
|
880 |
-Index: src/xml.erl |
|
881 |
-=================================================================== |
|
882 |
---- src/xml.erl (Revision 565) |
|
883 |
-+++ src/xml.erl (Arbeitskopie) |
|
884 |
-@@ -18,6 +18,7 @@ |
|
885 |
- get_tag_attr/2, get_tag_attr_s/2, |
|
886 |
- get_subtag/2, |
|
887 |
- get_path_s/2, |
|
888 |
-+ remove_tag_attr/2, |
|
889 |
- replace_tag_attr/3]). |
|
890 |
- |
|
891 |
- %element_to_string(El) -> |
|
892 |
-@@ -224,6 +225,14 @@ |
|
893 |
- get_path_s(El, [cdata]) -> |
|
894 |
- get_tag_cdata(El). |
|
895 |
- |
|
896 |
-+remove_tag_attr(Attr, El) -> |
|
897 |
-+ case El of |
|
898 |
-+ {xmlelement, Name, Attrs, Els} -> |
|
899 |
-+ Attrs1 = lists:keydelete(Attr, 1, Attrs), |
|
900 |
-+ {xmlelement, Name, Attrs1, Els}; |
|
901 |
-+ _ -> |
|
902 |
-+ El |
|
903 |
-+ end. |
|
904 |
- |
|
905 |
- replace_tag_attr(Attr, Value, {xmlelement, Name, Attrs, Els}) -> |
|
906 |
- Attrs1 = lists:keydelete(Attr, 1, Attrs), |
|
907 |
- |
|
908 |
-Index: src/ejabberd_sup.erl |
|
909 |
-=================================================================== |
|
910 |
---- src/ejabberd_sup.erl (Revision 565) |
|
911 |
-+++ src/ejabberd_sup.erl (Arbeitskopie) |
|
912 |
-@@ -123,6 +123,14 @@ |
|
913 |
- infinity, |
|
914 |
- supervisor, |
|
915 |
- [ejabberd_tmp_sup]}, |
|
916 |
-+ HTTPBindSupervisor = |
|
917 |
-+ {ejabberd_http_bind_sup, |
|
918 |
-+ {ejabberd_tmp_sup, start_link, |
|
919 |
-+ [ejabberd_http_bind_sup, ejabberd_http_bind]}, |
|
920 |
-+ permanent, |
|
921 |
-+ infinity, |
|
922 |
-+ supervisor, |
|
923 |
-+ [ejabberd_tmp_sup]}, |
|
924 |
- IQSupervisor = |
|
925 |
- {ejabberd_iq_sup, |
|
926 |
- {ejabberd_tmp_sup, start_link, |
|
927 |
-@@ -145,6 +153,7 @@ |
|
928 |
- ServiceSupervisor, |
|
929 |
- HTTPSupervisor, |
|
930 |
- HTTPPollSupervisor, |
|
931 |
-+ HTTPBindSupervisor, |
|
932 |
- IQSupervisor, |
|
933 |
- Listener]}}. |
|
934 |
- |
... | ... |
@@ -1,11 +0,0 @@ |
1 |
---- mod_irc/mod_irc.erl.orig 2006-11-19 14:40:02.463429250 +0100 |
|
2 |
-+++ mod_irc/mod_irc.erl 2006-11-19 14:40:25.888893250 +0100 |
|
3 |
-@@ -27,7 +27,7 @@ |
|
4 |
- -include("ejabberd.hrl"). |
|
5 |
- -include("jlib.hrl"). |
|
6 |
- |
|
7 |
---define(DEFAULT_IRC_ENCODING, "koi8-r"). |
|
8 |
-+-define(DEFAULT_IRC_ENCODING, "utf-8"). |
|
9 |
- |
|
10 |
- -record(irc_connection, {jid_server_host, pid}). |
|
11 |
- -record(irc_custom, {us_host, data}). |
... | ... |
@@ -1,11 +0,0 @@ |
1 |
-diff -Naur ejabberd-1.1.1.orig/src/odbc/ejabberd_odbc.erl ejabberd-1.1.1/src/odbc/ejabberd_odbc.erl |
|
2 |
---- ejabberd-1.1.1.orig/src/odbc/ejabberd_odbc.erl 2006-05-07 19:05:12.549917750 +0400 |
|
3 |
-+++ ejabberd-1.1.1/src/odbc/ejabberd_odbc.erl 2006-05-07 19:06:11.337591750 +0400 |
|
4 |
-@@ -281,6 +281,7 @@ |
|
5 |
- case mysql_conn:start(Server, ?MYSQL_PORT, Username, Password, DB, NoLogFun) of |
|
6 |
- {ok, Ref} -> |
|
7 |
- erlang:monitor(process, Ref), |
|
8 |
-+ catch mysql_conn:fetch(Ref, "SET NAMES 'utf8';", self()), |
|
9 |
- {ok, #state{db_ref = Ref, db_type = mysql}}; |
|
10 |
- {error, Reason} -> |
|
11 |
- ?ERROR_MSG("MySQL connection failed: ~p~n", [Reason]), |
... | ... |
@@ -1,406 +0,0 @@ |
1 |
-* modified files |
|
2 |
- |
|
3 |
- |
|
4 |
---- jlib.hrl |
|
5 |
-+++ jlib.hrl |
|
6 |
-@@ -34,6 +34,7 @@ |
|
7 |
- -define(NS_PUBSUB_OWNER, "http://jabber.org/protocol/pubsub#owner"). |
|
8 |
- -define(NS_PUBSUB_NMI, "http://jabber.org/protocol/pubsub#node-meta-info"). |
|
9 |
- -define(NS_COMMANDS, "http://jabber.org/protocol/commands"). |
|
10 |
-+-define(NS_BYTESTREAMS, "http://jabber.org/protocol/bytestreams"). |
|
11 |
- |
|
12 |
- -define(NS_EJABBERD_CONFIG, "ejabberd:config"). |
|
13 |
- |
|
14 |
- |
|
15 |
- |
|
16 |
- |
|
17 |
-* added files |
|
18 |
- |
|
19 |
---- /dev/null |
|
20 |
-+++ mod_proxy65.erl |
|
21 |
-@@ -0,0 +1,189 @@ |
|
22 |
-+%%%---------------------------------------------------------------------- |
|
23 |
-+%%% File : mod_proxy65.erl |
|
24 |
-+%%% Author : Magnus Henoch <henoch@dtek.chalmers.se> |
|
25 |
-+%%% Purpose : Handle Jabber communications for JEP-0065 proxy |
|
26 |
-+%%% Created : 27 Dec 2005 by Magnus Henoch <henoch@dtek.chalmers.se> |
|
27 |
-+%%% Id : $Id: ejabberd_c2s.erl 440 2005-11-22 18:00:56Z alexey $ |
|
28 |
-+%%%---------------------------------------------------------------------- |
|
29 |
-+ |
|
30 |
-+-module(mod_proxy65). |
|
31 |
-+-author('henoch@dtek.chalmers.se'). |
|
32 |
-+-vsn('$Revision$ '). |
|
33 |
-+ |
|
34 |
-+-behaviour(gen_mod). |
|
35 |
-+ |
|
36 |
-+-export([start/2, |
|
37 |
-+ init/1, |
|
38 |
-+ stop/1]). |
|
39 |
-+ |
|
40 |
-+-include("ejabberd.hrl"). |
|
41 |
-+-include("jlib.hrl"). |
|
42 |
-+ |
|
43 |
-+-record(proxy65_connection, {cookie, firstpid = none, secondpid = none}). |
|
44 |
-+ |
|
45 |
-+-record(proxy65_options, {host, access, streamhosts}). |
|
46 |
-+ |
|
47 |
-+-define(PROCNAME, ejabberd_mod_proxy65). |
|
48 |
-+ |
|
49 |
-+start(Host, Opts) -> |
|
50 |
-+ mnesia:create_table(proxy65_connection, |
|
51 |
-+ [{ram_copies, [node()]}, |
|
52 |
-+ {attributes, record_info(fields, proxy65_connection)}]), |
|
53 |
-+ MyHost = gen_mod:get_opt(host, Opts, "proxy." ++ Host), |
|
54 |
-+ Access = gen_mod:get_opt(access, Opts, all), |
|
55 |
-+ Streamhosts = gen_mod:get_opt(streamhosts, Opts, [{Host, 7777}]), |
|
56 |
-+ |
|
57 |
-+ register(gen_mod:get_module_proc(Host, ?PROCNAME), |
|
58 |
-+ spawn(?MODULE, init, [#proxy65_options{host = MyHost, access = Access, |
|
59 |
-+ streamhosts = Streamhosts}])). |
|
60 |
-+ |
|
61 |
-+ |
|
62 |
-+stop(Host) -> |
|
63 |
-+ Proc = gen_mod:get_module_proc(Host, ?PROCNAME), |
|
64 |
-+ Proc ! stop, |
|
65 |
-+ {wait, Proc}. |
|
66 |
-+ |
|
67 |
-+init(#proxy65_options{host = Host} = Opts) -> |
|
68 |
-+ ejabberd_router:register_route(Host), |
|
69 |
-+ loop(Opts). |
|
70 |
-+ |
|
71 |
-+loop(#proxy65_options{host = Host} = Opts) -> |
|
72 |
-+ receive |
|
73 |
-+ {route, From, To, Packet} -> |
|
74 |
-+ case catch do_route(Opts, From, To, Packet) of |
|
75 |
-+ {'EXIT', Reason} -> |
|
76 |
-+ ?ERROR_MSG("~p", [Reason]); |
|
77 |
-+ _ -> |
|
78 |
-+ ok |
|
79 |
-+ end, |
|
80 |
-+ loop(Opts); |
|
81 |
-+ stop -> |
|
82 |
-+ ejabberd_router:unregister_route(Host), |
|
83 |
-+ ok; |
|
84 |
-+ _ -> |
|
85 |
-+ loop(Opts) |
|
86 |
-+ end. |
|
87 |
-+ |
|
88 |
-+do_route(#proxy65_options{host = Host, access = Access} = Opts, |
|
89 |
-+ From, To, Packet) -> |
|
90 |
-+ case acl:match_rule(Host, Access, From) of |
|
91 |
-+ allow -> |
|
92 |
-+ do_route1(Opts, From, To, Packet); |
|
93 |
-+ _ -> |
|
94 |
-+ {xmlelement, _Name, Attrs, _Els} = Packet, |
|
95 |
-+ Lang = xml:get_attr_s("xml:lang", Attrs), |
|
96 |
-+ ErrText = "Access denied by service policy", |
|
97 |
-+ Err = jlib:make_error_reply(Packet, |
|
98 |
-+ ?ERRT_FORBIDDEN(Lang, ErrText)), |
|
99 |
-+ ejabberd_router:route(To, From, Err) |
|
100 |
-+ end. |
|
101 |
-+ |
|
102 |
-+do_route1(#proxy65_options{host = Host, streamhosts = Streamhosts}, From, To, Packet) -> |
|
103 |
-+ {xmlelement, Name, _Attrs, _Els} = Packet, |
|
104 |
-+ case Name of |
|
105 |
-+ "iq" -> |
|
106 |
-+ case jlib:iq_query_info(Packet) of |
|
107 |
-+ #iq{type = get, xmlns = ?NS_DISCO_INFO = XMLNS, |
|
108 |
-+ lang = Lang, sub_el = SubEl} = IQ -> |
|
109 |
-+ Node = xml:get_tag_attr_s("node", SubEl), |
|
110 |
-+ if Node == [] -> |
|
111 |
-+ Res = IQ#iq{type = result, |
|
112 |
-+ sub_el = [{xmlelement, "query", |
|
113 |
-+ [{"xmlns", XMLNS}], |
|
114 |
-+ [{xmlelement, "identity", |
|
115 |
-+ [{"category", "proxy"}, |
|
116 |
-+ {"type", "bytestreams"}, |
|
117 |
-+ {"name", translate:translate(Lang, "SOCKS5 bytestreams proxy")}], |
|
118 |
-+ []}, |
|
119 |
-+ {xmlelement, "feature", |
|
120 |
-+ [{"var", ?NS_BYTESTREAMS}], []}]}]}; |
|
121 |
-+ true -> |
|
122 |
-+ Res = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND) |
|
123 |
-+ end; |
|
124 |
-+ #iq{type = get, xmlns = ?NS_DISCO_ITEMS = XMLNS} = IQ -> |
|
125 |
-+ Res = IQ#iq{type = result, |
|
126 |
-+ sub_el = [{xmlelement, "query", |
|
127 |
-+ [{"xmlns", XMLNS}], []}]}; |
|
128 |
-+ #iq{type = get, xmlns = ?NS_VERSION} = IQ -> |
|
129 |
-+ OSType = case os:type() of |
|
130 |
-+ {Osfamily, Osname} -> |
|
131 |
-+ atom_to_list(Osfamily) ++ "/" ++ |
|
132 |
-+ atom_to_list(Osname); |
|
133 |
-+ Osfamily -> |
|
134 |
-+ atom_to_list(Osfamily) |
|
135 |
-+ end, |
|
136 |
-+ OSVersion = case os:version() of |
|
137 |
-+ {Major, Minor, Release} -> |
|
138 |
-+ lists:flatten( |
|
139 |
-+ io_lib:format("~w.~w.~w", |
|
140 |
-+ [Major, Minor, Release])); |
|
141 |
-+ VersionString -> |
|
142 |
-+ VersionString |
|
143 |
-+ end, |
|
144 |
-+ OS = OSType ++ " " ++ OSVersion, |
|
145 |
-+ Res = IQ#iq{type = result, |
|
146 |
-+ sub_el = [{xmlelement, "query", |
|
147 |
-+ [{"xmlns", ?NS_VERSION}], |
|
148 |
-+ [{xmlelement, "name", [], |
|
149 |
-+ [{xmlcdata, "ejabberd mod_proxy65 (unofficial)"}]}, |
|
150 |
-+ {xmlelement, "version", [], |
|
151 |
-+ [{xmlcdata, "0.1"}]}, |
|
152 |
-+ {xmlelement, "os", [], |
|
153 |
-+ [{xmlcdata, OS}]} |
|
154 |
-+ ]}]}; |
|
155 |
-+ #iq{type = get, xmlns = ?NS_BYTESTREAMS = XMLNS} = IQ -> |
|
156 |
-+ Res = IQ#iq{type = result, |
|
157 |
-+ sub_el = [{xmlelement, "query", |
|
158 |
-+ [{"xmlns", XMLNS}], |
|
159 |
-+ return_streamhosts(Host, Streamhosts)}]}; |
|
160 |
-+ #iq{type = set, xmlns = ?NS_BYTESTREAMS} = IQ -> |
|
161 |
-+ Res = activate(Packet, From, To, IQ); |
|
162 |
-+ _ -> |
|
163 |
-+ Res = jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED) |
|
164 |
-+ end, |
|
165 |
-+ case Res of |
|
166 |
-+ #iq{} -> |
|
167 |
-+ ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); |
|
168 |
-+ _ -> |
|
169 |
-+ ejabberd_router:route(To, From, Res) |
|
170 |
-+ end; |
|
171 |
-+ _ -> |
|
172 |
-+ ejabberd_router:route(To, From, jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED)) |
|
173 |
-+ end. |
|
174 |
-+ |
|
175 |
-+return_streamhosts(_JID, []) -> |
|
176 |
-+ []; |
|
177 |
-+return_streamhosts(JID, [{Host, Port} | Streamhosts]) -> |
|
178 |
-+ %% This is not tail-recursive, but it doesn't matter. |
|
179 |
-+ [{xmlelement, "streamhost", |
|
180 |
-+ [{"jid", JID}, |
|
181 |
-+ {"host", Host}, |
|
182 |
-+ {"port", integer_to_list(Port)}], |
|
183 |
-+ []} | return_streamhosts(JID, Streamhosts)]. |
|
184 |
-+ |
|
185 |
-+activate(Packet, From, _To, #iq{sub_el = SubEl} = IQ) -> |
|
186 |
-+ case SubEl of |
|
187 |
-+ {xmlelement, "query", Attrs, _SubEls} -> |
|
188 |
-+ Sid = xml:get_attr_s("sid", Attrs), |
|
189 |
-+ ActivateTag = xml:get_subtag(SubEl, "activate"), |
|
190 |
-+ if ActivateTag /= false -> |
|
191 |
-+ TargetJID = jlib:string_to_jid(xml:get_tag_cdata(ActivateTag)); |
|
192 |
-+ true -> |
|
193 |
-+ TargetJID = false |
|
194 |
-+ end, |
|
195 |
-+ |
|
196 |
-+ if Sid /= [], TargetJID /= false, TargetJID /= error -> |
|
197 |
-+ case proxy65_listener:activate(From, TargetJID, Sid) of |
|
198 |
-+ ok -> |
|
199 |
-+ ?INFO_MSG("Activated connection between ~s and ~s", |
|
200 |
-+ [jlib:jid_to_string(From), TargetJID]), |
|
201 |
-+ IQ#iq{type = result, sub_el = []}; |
|
202 |
-+ _ -> |
|
203 |
-+ jlib:make_error_reply(Packet, ?ERR_INTERNAL_SERVER_ERROR) |
|
204 |
-+ end; |
|
205 |
-+ true -> |
|
206 |
-+ jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST) |
|
207 |
-+ end; |
|
208 |
-+ _ -> |
|
209 |
-+ jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST) |
|
210 |
-+ end. |
|
211 |
---- /dev/null |
|
212 |
-+++ proxy65_listener.erl |
|
213 |
-@@ -0,0 +1,192 @@ |
|
214 |
-+%%%---------------------------------------------------------------------- |
|
215 |
-+%%% File : proxy65_listener.erl |
|
216 |
-+%%% Author : Magnus Henoch <henoch@dtek.chalmers.se> |
|
217 |
-+%%% Purpose : Handle SOCKS5 connections for JEP-0065 proxy |
|
218 |
-+%%% Created : 27 Dec 2005 by Magnus Henoch <henoch@dtek.chalmers.se> |
|
219 |
-+%%% Id : $Id: ejabberd_c2s.erl 440 2005-11-22 18:00:56Z alexey $ |
|
220 |
-+%%%---------------------------------------------------------------------- |
|
221 |
-+ |
|
222 |
-+-module(proxy65_listener). |
|
223 |
-+-author('henoch@dtek.chalmers.se'). |
|
224 |
-+-vsn('$Revision$ '). |
|
225 |
-+ |
|
226 |
-+-export([start/2, handle_connection/2, activate/3]). |
|
227 |
-+ |
|
228 |
-+-include("ejabberd.hrl"). |
|
229 |
-+-include("jlib.hrl"). |
|
230 |
-+ |
|
231 |
-+-record(proxy65_connection, {cookie, firstpid = none, secondpid = none}). |
|
232 |
-+ |
|
233 |
-+start({SockMod, Socket}, Opts) -> |
|
234 |
-+ {ok, proc_lib:spawn(?MODULE, handle_connection, [{SockMod, Socket}, Opts])}. |
|
235 |
-+ |
|
236 |
-+read_bytes(_SockOpts, 0, Data) -> |
|
237 |
-+ lists:flatten(Data); |
|
238 |
-+read_bytes({SockMod, Socket} = SockOpts, N, Data) -> |
|
239 |
-+ Timeout = 1000, |
|
240 |
-+ case SockMod:recv(Socket, N, Timeout) of |
|
241 |
-+ {error, closed} -> |
|
242 |
-+ %% On closed connection, return everything we have, |
|
243 |
-+ %% but not if we have nothing. |
|
244 |
-+ if Data == [] -> |
|
245 |
-+ erlang:error(closed); |
|
246 |
-+ true -> |
|
247 |
-+ lists:flatten(Data) |
|
248 |
-+ end; |
|
249 |
-+ {ok, MoreData} -> |
|
250 |
-+ ?DEBUG("read ~p", [MoreData]), |
|
251 |
-+ DataList = binary_to_list(MoreData), |
|
252 |
-+ read_bytes(SockOpts, N - length(DataList), [Data, DataList]) |
|
253 |
-+ end. |
|
254 |
-+ |
|
255 |
-+handle_connection({SockMod, Socket}, Opts) -> |
|
256 |
-+ ?DEBUG("in handle_connection", []), |
|
257 |
-+ case catch handle_auth({SockMod, Socket}, Opts) of |
|
258 |
-+ {'EXIT', Reason} -> |
|
259 |
-+ ?ERROR_MSG("~p abnormal termination:~n\t~p~n", |
|
260 |
-+ [?MODULE, Reason]), |
|
261 |
-+ SockMod:close(Socket); |
|
262 |
-+ _ -> |
|
263 |
-+ ok |
|
264 |
-+ end. |
|
265 |
-+ |
|
266 |
-+handle_auth({SockMod, Socket} = SockOpts, Opts) -> |
|
267 |
-+ ?DEBUG("in handle_auth", []), |
|
268 |
-+ %% SOCKS protocol stuff... |
|
269 |
-+ [5, NAuthMethods] = read_bytes(SockOpts, 2, []), |
|
270 |
-+ AuthMethods = read_bytes(SockOpts, NAuthMethods, []), |
|
271 |
-+ SupportsNoAuth = lists:member(0, AuthMethods), |
|
272 |
-+ |
|
273 |
-+ %% Must support no authentication, otherwise crash |
|
274 |
-+ true = SupportsNoAuth, |
|
275 |
-+ |
|
276 |
-+ SockMod:send(Socket, [5, 0]), |
|
277 |
-+ |
|
278 |
-+ %% And done. |
|
279 |
-+ handle_connect(SockOpts, Opts). |
|
280 |
-+ |
|
281 |
-+handle_connect({SockMod, Socket} = SockOpts, Opts) -> |
|
282 |
-+ ?DEBUG("in handle_connect", []), |
|
283 |
-+ %% Expect a CONNECT command and nothing else |
|
284 |
-+ [5, 1, _, 3, AddressLength] = read_bytes(SockOpts, 5, []), |
|
285 |
-+ Cookie = read_bytes(SockOpts, AddressLength, []), |
|
286 |
-+ [0, 0] = read_bytes(SockOpts, 2, []), |
|
287 |
-+ |
|
288 |
-+ %% Make sure no more than two connections claim the same cookie. |
|
289 |
-+ F = fun() -> |
|
290 |
-+ case mnesia:read({proxy65_connection, Cookie}) of |
|
291 |
-+ [] -> |
|
292 |
-+ mnesia:write(#proxy65_connection{cookie = Cookie, |
|
293 |
-+ firstpid = self()}), |
|
294 |
-+ ok; |
|
295 |
-+ [#proxy65_connection{secondpid = none} = C] -> |
|
296 |
-+ mnesia:write(C#proxy65_connection{secondpid = self()}), |
|
297 |
-+ ok |
|
298 |
-+ end |
|
299 |
-+ end, |
|
300 |
-+ |
|
301 |
-+ case mnesia:transaction(F) of |
|
302 |
-+ {atomic, ok} -> |
|
303 |
-+ SockMod:send(Socket, [5, 0, 0, 3, AddressLength, Cookie, 0, 0]), |
|
304 |
-+ wait_for_activation(SockOpts, Opts); |
|
305 |
-+ Error -> |
|
306 |
-+ %% conflict. send "general SOCKS server failure". |
|
307 |
-+ SockMod:send(Socket, [5, 1, 0, 3, AddressLength, Cookie, 0, 0]), |
|
308 |
-+ erlang:error({badconnect, Error}) |
|
309 |
-+ end. |
|
310 |
-+ |
|
311 |
-+wait_for_activation(SockOpts, Opts) -> |
|
312 |
-+ ?DEBUG("in wait_for_activation", []), |
|
313 |
-+ receive |
|
314 |
-+ {get_socket, ReplyTo} -> |
|
315 |
-+ ReplyTo ! SockOpts, |
|
316 |
-+ wait_for_activation(SockOpts, Opts); |
|
317 |
-+ {activate, TargetSocket, Initiator, Target} -> |
|
318 |
-+ ?DEBUG("activated", []), |
|
319 |
-+ |
|
320 |
-+ %% We have no way of knowing which connection belongs to |
|
321 |
-+ %% which participant, so give both the maximum traffic |
|
322 |
-+ %% allowed to either. |
|
323 |
-+ Shapers = case lists:keysearch(shaper, 1, Opts) of |
|
324 |
-+ {value, {_, S}} -> S; |
|
325 |
-+ _ -> none |
|
326 |
-+ end, |
|
327 |
-+ ?DEBUG("we have shapers: ~p", [Shapers]), |
|
328 |
-+ Shaper1 = acl:match_rule(global, Shapers, jlib:string_to_jid(Initiator)), |
|
329 |
-+ Shaper2 = acl:match_rule(global, Shapers, jlib:string_to_jid(Target)), |
|
330 |
-+ if Shaper1 == none; Shaper2 == none -> |
|
331 |
-+ MaxShaper = none; |
|
332 |
-+ true -> |
|
333 |
-+ ShaperValue1 = ejabberd_config:get_global_option({shaper, Shaper1}), |
|
334 |
-+ ShaperValue2 = ejabberd_config:get_global_option({shaper, Shaper2}), |
|
335 |
-+ |
|
336 |
-+ if ShaperValue1 > ShaperValue2 -> |
|
337 |
-+ MaxShaper = Shaper1; |
|
338 |
-+ true -> |
|
339 |
-+ MaxShaper = Shaper2 |
|
340 |
-+ end, |
|
341 |
-+ ?DEBUG("shapers have values ~p and ~p~nusing ~p", [ShaperValue1, ShaperValue2, MaxShaper]), |
|
342 |
-+ ok |
|
343 |
-+ end, |
|
344 |
-+ |
|
345 |
-+ transfer_data(SockOpts, TargetSocket, shaper:new(MaxShaper)) |
|
346 |
-+ end. |
|
347 |
-+ |
|
348 |
-+transfer_data({SockMod, Socket} = SockOpts, {TargetSockMod, TargetSocket} = TargetSockOpts, |
|
349 |
-+ Shaper) -> |
|
350 |
-+ case SockMod:recv(Socket, 0, infinity) of |
|
351 |
-+ {ok, Data} -> |
|
352 |
-+ if Data /= <<>> -> |
|
353 |
-+ NewShaper = case Shaper of |
|
354 |
-+ none -> none; |
|
355 |
-+ _ -> |
|
356 |
-+ shaper:update(Shaper, size(Data)) |
|
357 |
-+ end, |
|
358 |
-+ ok = TargetSockMod:send(TargetSocket, Data); |
|
359 |
-+ true -> |
|
360 |
-+ NewShaper = Shaper |
|
361 |
-+ end, |
|
362 |
-+ transfer_data(SockOpts, TargetSockOpts, NewShaper); |
|
363 |
-+ {error, _} -> |
|
364 |
-+ TargetSockMod:shutdown(TargetSocket, read_write) |
|
365 |
-+ end. |
|
366 |
-+ |
|
367 |
-+get_socket(PID) -> |
|
368 |
-+ PID ! {get_socket, self()}, |
|
369 |
-+ receive |
|
370 |
-+ {_SockMod, _Socket} = SockOpts -> |
|
371 |
-+ SockOpts |
|
372 |
-+ end. |
|
373 |
-+ |
|
374 |
-+%% If any argument is a jid record, convert it to normalized string form... |
|
375 |
-+activate(#jid{} = Initiator, Target, SessionID) -> |
|
376 |
-+ NormalizedInitiator = jlib:jid_to_string(jlib:make_jid(jlib:jid_tolower(Initiator))), |
|
377 |
-+ activate(NormalizedInitiator, Target, SessionID); |
|
378 |
-+activate(Initiator, #jid{} = Target, SessionID) -> |
|
379 |
-+ NormalizedTarget = jlib:jid_to_string(jlib:make_jid(jlib:jid_tolower(Target))), |
|
380 |
-+ activate(Initiator, NormalizedTarget, SessionID); |
|
381 |
-+%% ...and get on with the activation. |
|
382 |
-+activate(Initiator, Target, SessionID) -> |
|
383 |
-+ Cookie = sha:sha(SessionID ++ Initiator ++ Target), |
|
384 |
-+ F = fun() -> |
|
385 |
-+ case mnesia:read({proxy65_connection, Cookie}) of |
|
386 |
-+ [#proxy65_connection{firstpid = FirstPID, |
|
387 |
-+ secondpid = SecondPID}] |
|
388 |
-+ when is_pid(FirstPID), is_pid(SecondPID) -> |
|
389 |
-+ mnesia:delete({proxy65_connection, Cookie}), |
|
390 |
-+ {FirstPID, SecondPID}; |
|
391 |
-+ _ -> |
|
392 |
-+ error |
|
393 |
-+ end |
|
394 |
-+ end, |
|
395 |
-+ case mnesia:transaction(F) of |
|
396 |
-+ {atomic, {FirstPID, SecondPID}} -> |
|
397 |
-+ FirstSocket = get_socket(FirstPID), |
|
398 |
-+ SecondSocket = get_socket(SecondPID), |
|
399 |
-+ FirstPID ! {activate, SecondSocket, Initiator, Target}, |
|
400 |
-+ SecondPID ! {activate, FirstSocket, Initiator, Target}, |
|
401 |
-+ ok; |
|
402 |
-+ Error -> |
|
403 |
-+ ?ERROR_MSG("Proxy activation failed: ~p", [Error]), |
|
404 |
-+ error |
|
405 |
-+ end. |
|
406 |
- |
... | ... |
@@ -1,17 +0,0 @@ |
1 |
-# Copyright 1999-2005 Gentoo Foundation |
|
2 |
-# Distributed under the terms of the GNU General Public License v2 |
|
3 |
-# $Header: $ |
|
4 |
- |
|
5 |
-# Name of your ejabberd node. Used by ejabberdctl to determine which |
|
6 |
-# node to communicate with. Default is "ejabberd@`hostname -s`". |
|
7 |
-#EJABBERD_NODE="ejabberd@`hostname -s`" |
|
8 |
- |
|
9 |
-# Max number of open network connections. Default is 1024. Increasing |
|
10 |
-# this will slightly increase memory usage. |
|
11 |
-#ERL_MAX_PORTS=1024 |
|
12 |
- |
|
13 |
-# Return memory to the system after using it, instead of keeping it |
|
14 |
-# allocated for future use. Decreases the memory required by ejabberd, |
|
15 |
-# but makes it run slower. Default is unset, set to any value to |
|
16 |
-# activate. |
|
17 |
-#ERL_FULLSWEEP_AFTER=0 |
... | ... |
@@ -1,60 +0,0 @@ |
1 |
-#!/sbin/runscript |
|
2 |
-# Copyright 1999-2005 Gentoo Foundation |
|
3 |
-# Distributed under the terms of the GNU General Public License v2 |
|
4 |
-# $Header: $ |
|
5 |
- |
|
6 |
-opts="${opts} reload" |
|
7 |
- |
|
8 |
-depend() { |
|
9 |
- use dns |
|
10 |
- need net |
|
11 |
- provide jabber-server |
|
12 |
-} |
|
13 |
- |
|
14 |
-checkconfig() { |
|
15 |
- if [ ! -e /etc/jabber/ejabberd.cfg ] ; then |
|
16 |
- eerror "You need an /etc/jabber/ejabberd.cfg file to run ejabberd" |
|
17 |
- return 1 |
|
18 |
- fi |
|
19 |
-} |
|
20 |
- |
|
21 |
-start() { |
|
22 |
- checkconfig || return 1 |
|
23 |
- ebegin "Starting eJabberd" |
|
24 |
- start-stop-daemon --start --quiet --chuid jabber:jabber \ |
|
25 |
- --exec /usr/bin/env HOME=/var/run/jabber /usr/bin/ejabberd -- -noshell -detached |
|
26 |
- eend $? |
|
27 |
-} |
|
28 |
- |
|
29 |
-stop() { |
|
30 |
- ebegin "Stopping eJabberd" |
|
31 |
- if [ -z "$EJABBERD_NODE" ]; |
|
32 |
- then |
|
33 |
- EJABBERD_NODE="ejabberd@`hostname -s`" |
|
34 |
- fi |
|
35 |
- /usr/bin/ejabberdctl $EJABBERD_NODE stop |
|
36 |
- eend $? |
|
37 |
-} |
|
38 |
- |
|
39 |
-# Work around a bug in /sbin/runscript.sh - it won't run our custom |
|
40 |
-# restart() unless it finds these two strings in the file. |
|
41 |
-# svc_start svc_stop |
|
42 |
-restart() { |
|
43 |
- ebegin "Restarting eJabberd" |
|
44 |
- if [ -z "$EJABBERD_NODE" ]; |
|
45 |
- then |
|
46 |
- EJABBERD_NODE="ejabberd@`hostname -s`" |
|
47 |
- fi |
|
48 |
- /usr/bin/ejabberdctl $EJABBERD_NODE restart |
|
49 |
- eend $? |
|
50 |
-} |
|
51 |
- |
|
52 |
-reload() { |
|
53 |
- ebegin "Reloading eJabberd" |
|
54 |
- if [ -z "$EJABBERD_NODE" ]; |
|
55 |
- then |
|
56 |
- EJABBERD_NODE="ejabberd@`hostname -s`" |
|
57 |
- fi |
|
58 |
- /usr/bin/ejabberdctl $EJABBERD_NODE reopen-log |
|
59 |
- eend $? |
|
60 |
-} |
... | ... |
@@ -1,934 +0,0 @@ |
1 |
-Index: src/ejabberd.cfg.example |
|
2 |
-=================================================================== |
|
3 |
---- src/ejabberd.cfg.example (Revision 565) |
|
4 |
-+++ src/ejabberd.cfg.example (Arbeitskopie) |
|
5 |
-@@ -124,7 +124,7 @@ |
|
6 |
- {5269, ejabberd_s2s_in, [{shaper, s2s_shaper}, |
|
7 |
- {max_stanza_size, 131072} |
|
8 |
- ]}, |
|
9 |
-- {5280, ejabberd_http, [http_poll, web_admin]}, |
|
10 |
-+ {5280, ejabberd_http, [http_poll, http_bind, web_admin]}, |
|
11 |
- {8888, ejabberd_service, [{access, all}, |
|
12 |
- {hosts, ["icq.localhost", "sms.localhost"], |
|
13 |
- [{password, "secret"}]}]} |
|
14 |
-Index: src/web/Makefile.in |
|
15 |
-=================================================================== |
|
16 |
---- src/web/Makefile.in (Revision 565) |
|
17 |
-+++ src/web/Makefile.in (Arbeitskopie) |
|
18 |
-@@ -15,7 +15,8 @@ |
|
19 |
- $(OUTDIR)/ejabberd_http.beam \ |
|
20 |
- $(OUTDIR)/ejabberd_web.beam \ |
|
21 |
- $(OUTDIR)/ejabberd_web_admin.beam \ |
|
22 |
-- $(OUTDIR)/ejabberd_http_poll.beam |
|
23 |
-+ $(OUTDIR)/ejabberd_http_poll.beam \ |
|
24 |
-+ $(OUTDIR)/ejabberd_http_bind.beam |
|
25 |
- |
|
26 |
- all: $(OBJS) |
|
27 |
- |
|
28 |
-Index: src/web/ejabberd_http_bind.erl |
|
29 |
-=================================================================== |
|
30 |
---- src/web/ejabberd_http_bind.erl (Revision 0) |
|
31 |
-+++ src/web/ejabberd_http_bind.erl (Revision 0) |
|
32 |
-@@ -0,0 +1,731 @@ |
|
33 |
-+%%%---------------------------------------------------------------------- |
|
34 |
-+%%% File : ejabberd_http_bind.erl |
|
35 |
-+%%% Author : Stefan Strigler <steve@zeank.in-berlin.de> |
|
36 |
-+%%% Purpose : HTTP Binding support (JEP-0124) |
|
37 |
-+%%% Created : 21 Sep 2005 by Stefan Strigler <steve@zeank.in-berlin.de> |
|
38 |
-+%%% Id : $Id: ejabberd_http_bind.erl,v 1.2 2006/01/16 10:47:50 zeank Exp $ |
|
39 |
-+%%%---------------------------------------------------------------------- |
|
40 |
-+ |
|
41 |
-+-module(ejabberd_http_bind). |
|
42 |
-+-author('steve@zeank.in-berlin.de'). |
|
43 |
-+-vsn('Revision: 1.3'). |
|
44 |
-+ |
|
45 |
-+-behaviour(gen_fsm). |
|
46 |
-+ |
|
47 |
-+%% External exports |
|
48 |
-+-export([start_link/2, |
|
49 |
-+ init/1, |
|
50 |
-+ handle_event/3, |
|
51 |
-+ handle_sync_event/4, |
|
52 |
-+ code_change/4, |
|
53 |
-+ handle_info/3, |
|
54 |
-+ terminate/3, |
|
55 |
-+ send/2, |
|
56 |
-+ setopts/2, |
|
57 |
-+ controlling_process/2, |
|
58 |
-+ close/1, |
|
59 |
-+ process_request/1]). |
|
60 |
-+ |
|
61 |
-+%%-define(ejabberd_debug, true). |
|
62 |
-+ |
|
63 |
-+-include("ejabberd.hrl"). |
|
64 |
-+-include("jlib.hrl"). |
|
65 |
-+-include("ejabberd_http.hrl"). |
|
66 |
-+ |
|
67 |
-+-record(http_bind, {id, pid, hold, wait}). |
|
68 |
-+ |
|
69 |
-+%% http binding request |
|
70 |
-+-record(hbr, {rid, |
|
71 |
-+ key, |
|
72 |
-+ in, |
|
73 |
-+ out}). |
|
74 |
-+ |
|
75 |
-+-record(state, {id, |
|
76 |
-+ rid = error, |
|
77 |
-+ key, |
|
78 |
-+ output = "", |
|
79 |
-+ input = "", |
|
80 |
-+ waiting_input = false, |
|
81 |
-+ last_receiver, |
|
82 |
-+ last_poll, |
|
83 |
-+ ctime = 0, |
|
84 |
-+ timer, |
|
85 |
-+ req_list = [] % list of requests |
|
86 |
-+ }). |
|
87 |
-+ |
|
88 |
-+ |
|
89 |
-+%-define(DBGFSM, true). |
|
90 |
-+ |
|
91 |
-+-ifdef(DBGFSM). |
|
92 |
-+-define(FSMOPTS, [{debug, [trace]}]). |
|
93 |
-+-else. |
|
94 |
-+-define(FSMOPTS, []). |
|
95 |
-+-endif. |
|
96 |
-+ |
|
97 |
-+-define(MAX_REQUESTS, 2). % number of simultaneous requests |
|
98 |
-+-define(MIN_POLLING, "2"). % don't poll faster than that or we will shoot you |
|
99 |
-+-define(MAX_WAIT, 60). % max num of secs to keep a request on hold |
|
100 |
-+-define(MAX_INACTIVITY, 30000). % msecs to wait before terminating idle sessions |
|
101 |
-+-define(CT, {"Content-Type", "text/xml; charset=utf-8"}). |
|
102 |
-+-define(BAD_REQUEST, ?CT). |
|
103 |
-+ |
|
104 |
-+ |
|
105 |
-+%%%---------------------------------------------------------------------- |
|
106 |
-+%%% API |
|
107 |
-+%%%---------------------------------------------------------------------- |
|
108 |
-+start(ID, Key) -> |
|
109 |
-+ mnesia:create_table(http_bind, |
|
110 |
-+ [{ram_copies, [node()]}, |
|
111 |
-+ {attributes, record_info(fields, http_bind)}]), |
|
112 |
-+ supervisor:start_child(ejabberd_http_bind_sup, [ID, Key]). |
|
113 |
-+ |
|
114 |
-+start_link(ID, Key) -> |
|
115 |
-+ gen_fsm:start_link(?MODULE, [ID, Key], ?FSMOPTS). |
|
116 |
-+ |
|
117 |
-+send({http_bind, FsmRef}, Packet) -> |
|
118 |
-+ gen_fsm:sync_send_all_state_event(FsmRef, {send, Packet}). |
|
119 |
-+ |
|
120 |
-+setopts({http_bind, FsmRef}, Opts) -> |
|
121 |
-+ case lists:member({active, once}, Opts) of |
|
122 |
-+ true -> |
|
123 |
-+ gen_fsm:sync_send_all_state_event(FsmRef, activate); |
|
124 |
-+ _ -> |
|
125 |
-+ ok |
|
126 |
-+ end. |
|
127 |
-+ |
|
128 |
-+controlling_process(_Socket, _Pid) -> |
|
129 |
-+ ok. |
|
130 |
-+ |
|
131 |
-+close({http_bind, FsmRef}) -> |
|
132 |
-+ catch gen_fsm:sync_send_all_state_event(FsmRef, close). |
|
133 |
-+ |
|
134 |
-+ |
|
135 |
-+process_request(#request{path = [], |
|
136 |
-+ data = Data}) -> |
|
137 |
-+ case catch parse_request(Data) of |
|
138 |
-+ {ok, ID1, RID, Key, NewKey, Attrs, Packet} -> |
|
139 |
-+ XmppDomain = xml:get_attr_s("to",Attrs), |
|
140 |
-+ if |
|
141 |
-+ (ID1 == "") and (XmppDomain == "") -> |
|
142 |
-+ {200, [?CT], "<body type='terminate' " |
|
143 |
-+ "condition='improper-addressing' " |
|
144 |
-+ "xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
145 |
-+ true -> |
|
146 |
-+ ID = if |
|
147 |
-+ (ID1 == "") -> |
|
148 |
-+ %% create new session |
|
149 |
-+ NewID = sha:sha(term_to_binary({now(), make_ref()})), |
|
150 |
-+ {ok, Pid} = start(NewID, Key), |
|
151 |
-+ Wait = case |
|
152 |
-+ string:to_integer(xml:get_attr_s("wait",Attrs)) |
|
153 |
-+ of |
|
154 |
-+ {error, _} -> |
|
155 |
-+ ?MAX_WAIT; |
|
156 |
-+ {CWait, _} -> |
|
157 |
-+ if |
|
158 |
-+ (CWait > ?MAX_WAIT) -> |
|
159 |
-+ ?MAX_WAIT; |
|
160 |
-+ true -> |
|
161 |
-+ CWait |
|
162 |
-+ end |
|
163 |
-+ end, |
|
164 |
-+ Hold = case |
|
165 |
-+ string:to_integer( |
|
166 |
-+ xml:get_attr_s("hold",Attrs)) |
|
167 |
-+ of |
|
168 |
-+ {error, _} -> |
|
169 |
-+ (?MAX_REQUESTS - 1); |
|
170 |
-+ {CHold, _} -> |
|
171 |
-+ if |
|
172 |
-+ (CHold > (?MAX_REQUESTS - 1)) -> |
|
173 |
-+ (?MAX_REQUESTS - 1); |
|
174 |
-+ true -> |
|
175 |
-+ CHold |
|
176 |
-+ end |
|
177 |
-+ end, |
|
178 |
-+ mnesia:transaction( |
|
179 |
-+ fun() -> |
|
180 |
-+ mnesia:write(#http_bind{id = NewID, |
|
181 |
-+ pid = Pid, |
|
182 |
-+ wait = Wait, |
|
183 |
-+ hold = Hold}) |
|
184 |
-+ end), |
|
185 |
-+ InPacket = if |
|
186 |
-+ (XmppDomain /= "") -> |
|
187 |
-+ ["<stream:stream to='", |
|
188 |
-+ XmppDomain, |
|
189 |
-+ "' xmlns='jabber:client' " |
|
190 |
-+ "xmlns:stream='http://etherx.jabber.org/streams'>"]; |
|
191 |
-+ true -> |
|
192 |
-+ "" |
|
193 |
-+ end, |
|
194 |
-+ NewID; |
|
195 |
-+ true -> |
|
196 |
-+ %% old session |
|
197 |
-+ Type = xml:get_attr_s("type",Attrs), |
|
198 |
-+ Wait = ?MAX_WAIT, |
|
199 |
-+ Hold = (?MAX_REQUESTS - 1), |
|
200 |
-+ if |
|
201 |
-+ (Type == "terminate") -> |
|
202 |
-+ %% terminate session |
|
203 |
-+ InPacket = Packet ++ "</stream:stream>"; |
|
204 |
-+ true -> |
|
205 |
-+ InPacket = Packet |
|
206 |
-+ end, |
|
207 |
-+ ID1 |
|
208 |
-+ end, |
|
209 |
-+%% ?DEBUG("~n InPacket: ~s ~n", [InPacket]), |
|
210 |
-+ case http_put(ID, RID, Key, NewKey, Hold, InPacket) of |
|
211 |
-+ {error, not_exists} -> |
|
212 |
-+ ?DEBUG("no session associated with sid: ~p", [ID]), |
|
213 |
-+ {404, [?BAD_REQUEST], ""}; |
|
214 |
-+ {error, bad_key} -> |
|
215 |
-+ ?DEBUG("bad key: ~s", Key), |
|
216 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
217 |
-+ [] -> |
|
218 |
-+ {404, [?BAD_REQUEST], ""}; |
|
219 |
-+ [#http_bind{pid = FsmRef}] -> |
|
220 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop), |
|
221 |
-+ {404, [?BAD_REQUEST], ""} |
|
222 |
-+ end; |
|
223 |
-+ {error, polling_too_frequently} -> |
|
224 |
-+ ?DEBUG("polling too frequently: ~p", [ID]), |
|
225 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
226 |
-+ [] -> %% unlikely! (?) |
|
227 |
-+ {404, [?BAD_REQUEST], ""}; |
|
228 |
-+ [#http_bind{pid = FsmRef}] -> |
|
229 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop), |
|
230 |
-+ {403, [?BAD_REQUEST], ""} |
|
231 |
-+ end; |
|
232 |
-+ {repeat, OutPacket} -> |
|
233 |
-+ ?DEBUG("http_put said 'repeat!' ...~nOutPacket: ~p", |
|
234 |
-+ [OutPacket]), |
|
235 |
-+ send_outpacket(ID, OutPacket); |
|
236 |
-+ ok -> |
|
237 |
-+ receive_loop(ID,ID1,RID,Wait,Hold,Attrs) |
|
238 |
-+ end |
|
239 |
-+ end; |
|
240 |
-+ _ -> |
|
241 |
-+ {400, [?BAD_REQUEST], ""} |
|
242 |
-+ end; |
|
243 |
-+process_request(_Request) -> |
|
244 |
-+ {400, [], {xmlelement, "h1", [], |
|
245 |
-+ [{xmlcdata, "400 Bad Request"}]}}. |
|
246 |
-+ |
|
247 |
-+receive_loop(ID,ID1,RID,Wait,Hold,Attrs) -> |
|
248 |
-+ receive |
|
249 |
-+ after 100 -> ok |
|
250 |
-+ end, |
|
251 |
-+ prepare_response(ID,ID1,RID,Wait,Hold,Attrs). |
|
252 |
-+ |
|
253 |
-+prepare_response(ID,ID1,RID,Wait,Hold,Attrs) -> |
|
254 |
-+ case http_get(ID,RID) of |
|
255 |
-+ {error, not_exists} -> |
|
256 |
-+ ?DEBUG("no session associated with sid: ~s", ID), |
|
257 |
-+ {404, [?BAD_REQUEST], ""}; |
|
258 |
-+ {ok, keep_on_hold} -> |
|
259 |
-+ receive_loop(ID,ID1,RID,Wait,Hold,Attrs); |
|
260 |
-+ {ok, cancel} -> |
|
261 |
-+ %% actually it would be better if we could completely |
|
262 |
-+ %% cancel this request, but then we would have to hack |
|
263 |
-+ %% ejabberd_http and I'm too lazy now |
|
264 |
-+ {404, [?BAD_REQUEST], ""}; |
|
265 |
-+ {ok, OutPacket} -> |
|
266 |
-+ ?DEBUG("OutPacket: ~s", [OutPacket]), |
|
267 |
-+ if |
|
268 |
-+ ID == ID1 -> |
|
269 |
-+ send_outpacket(ID, OutPacket); |
|
270 |
-+ true -> |
|
271 |
-+ To = xml:get_attr_s("to",Attrs), |
|
272 |
-+ case xml_stream:parse_element( |
|
273 |
-+ OutPacket++"</stream:stream>") of |
|
274 |
-+ El when element(1, El) == xmlelement -> |
|
275 |
-+ {xmlelement, _, OutAttrs, _} = El, |
|
276 |
-+ AuthID = xml:get_attr_s("id", OutAttrs), |
|
277 |
-+ StreamError = false; |
|
278 |
-+ {error, _} -> |
|
279 |
-+ AuthID = "", |
|
280 |
-+ StreamError = true |
|
281 |
-+ end, |
|
282 |
-+ if |
|
283 |
-+ To == "" -> |
|
284 |
-+ {200, [?CT], "<body type='terminate' " |
|
285 |
-+ "condition='improper-addressing' " |
|
286 |
-+ "xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
287 |
-+ StreamError == true -> |
|
288 |
-+ {200, [?CT], "<body type='terminate' " |
|
289 |
-+ "condition='host-unknown' " |
|
290 |
-+ "xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
291 |
-+ true -> |
|
292 |
-+ {200, [?CT], |
|
293 |
-+ xml:element_to_string( |
|
294 |
-+ {xmlelement,"body", |
|
295 |
-+ [{"xmlns", |
|
296 |
-+ "http://jabber.org/protocol/httpbind"}, |
|
297 |
-+ {"sid",ID}, |
|
298 |
-+ {"wait", integer_to_list(Wait)}, |
|
299 |
-+ {"requests", integer_to_list(Hold+1)}, |
|
300 |
-+ {"inactivity", |
|
301 |
-+ integer_to_list(trunc(?MAX_INACTIVITY/1000))}, |
|
302 |
-+ {"polling", ?MIN_POLLING}, |
|
303 |
-+ {"authid", AuthID} |
|
304 |
-+ ],[]})} |
|
305 |
-+ end |
|
306 |
-+ end |
|
307 |
-+ end. |
|
308 |
-+ |
|
309 |
-+send_outpacket(ID, OutPacket) -> |
|
310 |
-+ case OutPacket of |
|
311 |
-+ "" -> |
|
312 |
-+ {200, [?CT], "<body xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
313 |
-+ "</stream:stream>" -> |
|
314 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
315 |
-+ [#http_bind{pid = FsmRef}] -> |
|
316 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop) |
|
317 |
-+ end, |
|
318 |
-+ {200, [?CT], "<body xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
319 |
-+ _ -> |
|
320 |
-+ case xml_stream:parse_element("<body>" |
|
321 |
-+ ++ OutPacket |
|
322 |
-+ ++ "</body>") |
|
323 |
-+ of |
|
324 |
-+ El when element(1, El) == xmlelement -> |
|
325 |
-+ {xmlelement, _, _, OEls} = El, |
|
326 |
-+ TypedEls = [xml:replace_tag_attr("xmlns", |
|
327 |
-+ "jabber:client",OEl) || |
|
328 |
-+ OEl <- OEls], |
|
329 |
-+ ?DEBUG(" --- outgoing data --- ~n~s~n --- END --- ~n", |
|
330 |
-+ [xml:element_to_string( |
|
331 |
-+ {xmlelement,"body", |
|
332 |
-+ [{"xmlns", |
|
333 |
-+ "http://jabber.org/protocol/httpbind"}], |
|
334 |
-+ TypedEls})] |
|
335 |
-+ ), |
|
336 |
-+ {200, [?CT], |
|
337 |
-+ xml:element_to_string( |
|
338 |
-+ {xmlelement,"body", |
|
339 |
-+ [{"xmlns", |
|
340 |
-+ "http://jabber.org/protocol/httpbind"}], |
|
341 |
-+ TypedEls})}; |
|
342 |
-+ {error, _E} -> |
|
343 |
-+ ?DEBUG("parse error: ~p", [_E]), |
|
344 |
-+ StreamErrCond = case xml_stream:parse_element( |
|
345 |
-+ "<stream:stream>"++OutPacket) of |
|
346 |
-+ El when element(1, El) == xmlelement -> |
|
347 |
-+ {xmlelement, _Tag, _Attr, Els} = El, |
|
348 |
-+ [{xmlelement, SE, _, Cond} | _] = Els, |
|
349 |
-+ if |
|
350 |
-+ SE == "stream:error" -> |
|
351 |
-+ Cond; |
|
352 |
-+ true -> |
|
353 |
-+ null |
|
354 |
-+ end; |
|
355 |
-+ {error, _E} -> |
|
356 |
-+ null |
|
357 |
-+ end, |
|
358 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
359 |
-+ [#http_bind{pid = FsmRef}] -> |
|
360 |
-+ gen_fsm:sync_send_all_state_event(FsmRef,stop); |
|
361 |
-+ _ -> |
|
362 |
-+ err %% hu? |
|
363 |
-+ end, |
|
364 |
-+ case StreamErrCond of |
|
365 |
-+ null -> |
|
366 |
-+ {200, [?CT], |
|
367 |
-+ "<body type='terminate' " |
|
368 |
-+ "condition='internal-server-error' " |
|
369 |
-+ "xmlns='http://jabber.org/protocol/httpbind'/>"}; |
|
370 |
-+ _ -> |
|
371 |
-+ {200, [?CT], |
|
372 |
-+ "<body type='terminate' " |
|
373 |
-+ "condition='remote-stream-error' " |
|
374 |
-+ "xmlns='http://jabber.org/protocol/httpbind'>" ++ |
|
375 |
-+ elements_to_string(StreamErrCond) ++ |
|
376 |
-+ "</body>"} |
|
377 |
-+ end |
|
378 |
-+ end |
|
379 |
-+ end. |
|
380 |
-+ |
|
381 |
-+%%%---------------------------------------------------------------------- |
|
382 |
-+%%% Callback functions from gen_fsm |
|
383 |
-+%%%---------------------------------------------------------------------- |
|
384 |
-+ |
|
385 |
-+%%---------------------------------------------------------------------- |
|
386 |
-+%% Func: init/1 |
|
387 |
-+%% Returns: {ok, StateName, StateData} | |
|
388 |
-+%% {ok, StateName, StateData, Timeout} | |
|
389 |
-+%% ignore | |
|
390 |
-+%% {stop, StopReason} |
|
391 |
-+%%---------------------------------------------------------------------- |
|
392 |
-+init([ID, Key]) -> |
|
393 |
-+ ?INFO_MSG("started: ~p", [{ID, Key}]), |
|
394 |
-+ Opts = [], % TODO |
|
395 |
-+ {ok, C2SPid} = ejabberd_c2s:start({?MODULE, {http_bind, self()}}, Opts), |
|
396 |
-+ ejabberd_c2s:become_controller(C2SPid), |
|
397 |
-+ Timer = erlang:start_timer(?MAX_INACTIVITY, self(), []), |
|
398 |
-+ {ok, loop, #state{id = ID, |
|
399 |
-+ key = Key, |
|
400 |
-+ timer = Timer}}. |
|
401 |
-+ |
|
402 |
-+%%---------------------------------------------------------------------- |
|
403 |
-+%% Func: StateName/2 |
|
404 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
405 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
406 |
-+%% {stop, Reason, NewStateData} |
|
407 |
-+%%---------------------------------------------------------------------- |
|
408 |
-+ |
|
409 |
-+ |
|
410 |
-+%%---------------------------------------------------------------------- |
|
411 |
-+%% Func: StateName/3 |
|
412 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
413 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
414 |
-+%% {reply, Reply, NextStateName, NextStateData} | |
|
415 |
-+%% {reply, Reply, NextStateName, NextStateData, Timeout} | |
|
416 |
-+%% {stop, Reason, NewStateData} | |
|
417 |
-+%% {stop, Reason, Reply, NewStateData} |
|
418 |
-+%%---------------------------------------------------------------------- |
|
419 |
-+%state_name(Event, From, StateData) -> |
|
420 |
-+% Reply = ok, |
|
421 |
-+% {reply, Reply, state_name, StateData}. |
|
422 |
-+ |
|
423 |
-+%%---------------------------------------------------------------------- |
|
424 |
-+%% Func: handle_event/3 |
|
425 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
426 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
427 |
-+%% {stop, Reason, NewStateData} |
|
428 |
-+%%---------------------------------------------------------------------- |
|
429 |
-+handle_event(_Event, StateName, StateData) -> |
|
430 |
-+ {next_state, StateName, StateData}. |
|
431 |
-+ |
|
432 |
-+%%---------------------------------------------------------------------- |
|
433 |
-+%% Func: handle_sync_event/4 |
|
434 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
435 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
436 |
-+%% {reply, Reply, NextStateName, NextStateData} | |
|
437 |
-+%% {reply, Reply, NextStateName, NextStateData, Timeout} | |
|
438 |
-+%% {stop, Reason, NewStateData} | |
|
439 |
-+%% {stop, Reason, Reply, NewStateData} |
|
440 |
-+%%---------------------------------------------------------------------- |
|
441 |
-+handle_sync_event({send, Packet}, _From, StateName, StateData) -> |
|
442 |
-+ Output = [StateData#state.output | Packet], |
|
443 |
-+ Reply = ok, |
|
444 |
-+ {reply, Reply, StateName, StateData#state{output = Output}}; |
|
445 |
-+ |
|
446 |
-+handle_sync_event(activate, From, StateName, StateData) -> |
|
447 |
-+ case StateData#state.input of |
|
448 |
-+ "" -> |
|
449 |
-+ {reply, ok, StateName, StateData#state{ |
|
450 |
-+ waiting_input = From}}; |
|
451 |
-+ Input -> |
|
452 |
-+ From ! {tcp, {http_bind, self()}, list_to_binary(Input)}, |
|
453 |
-+ {reply, ok, StateName, StateData#state{ |
|
454 |
-+ input = "", |
|
455 |
-+ waiting_input = false, |
|
456 |
-+ last_receiver = From}} |
|
457 |
-+ end; |
|
458 |
-+ |
|
459 |
-+handle_sync_event(stop, _From, _StateName, StateData) -> |
|
460 |
-+ Reply = ok, |
|
461 |
-+ {stop, normal, Reply, StateData}; |
|
462 |
-+ |
|
463 |
-+handle_sync_event({http_put, RID, Key, NewKey, Hold, Packet}, |
|
464 |
-+ _From, StateName, StateData) -> |
|
465 |
-+ %% check if RID valid |
|
466 |
-+ RidAllow = case RID of |
|
467 |
-+ error -> |
|
468 |
-+ false; |
|
469 |
-+ _ -> |
|
470 |
-+ case StateData#state.rid of |
|
471 |
-+ error -> |
|
472 |
-+ %% first request - nothing saved so far |
|
473 |
-+ true; |
|
474 |
-+ OldRID -> |
|
475 |
-+ ?DEBUG("state.rid/cur rid: ~p/~p", |
|
476 |
-+ [OldRID, RID]), |
|
477 |
-+ if |
|
478 |
-+ (OldRID < RID) and |
|
479 |
-+ (RID =< (OldRID + Hold + 1)) -> |
|
480 |
-+ true; |
|
481 |
-+ (RID =< OldRID) and |
|
482 |
-+ (RID > OldRID - Hold - 1) -> |
|
483 |
-+ repeat; |
|
484 |
-+ true -> |
|
485 |
-+ false |
|
486 |
-+ end |
|
487 |
-+ end |
|
488 |
-+ end, |
|
489 |
-+ %% check if key valid |
|
490 |
-+ KeyAllow = case RidAllow of |
|
491 |
-+ repeat -> |
|
492 |
-+ true; |
|
493 |
-+ false -> |
|
494 |
-+ false; |
|
495 |
-+ true -> |
|
496 |
-+ case StateData#state.key of |
|
497 |
-+ "" -> |
|
498 |
-+ true; |
|
499 |
-+ OldKey -> |
|
500 |
-+ NextKey = httpd_util:to_lower( |
|
501 |
-+ hex(binary_to_list( |
|
502 |
-+ crypto:sha(Key)))), |
|
503 |
-+ ?DEBUG("Key/OldKey/NextKey: ~s/~s/~s", |
|
504 |
-+ [Key, OldKey, NextKey]), |
|
505 |
-+ if |
|
506 |
-+ OldKey == NextKey -> |
|
507 |
-+ true; |
|
508 |
-+ true -> |
|
509 |
-+ ?DEBUG("wrong key: ~s",[Key]), |
|
510 |
-+ false |
|
511 |
-+ end |
|
512 |
-+ end |
|
513 |
-+ end, |
|
514 |
-+ {_,TSec,TMSec} = now(), |
|
515 |
-+ TNow = TSec*1000*1000 + TMSec, |
|
516 |
-+ LastPoll = if |
|
517 |
-+ Packet == "" -> |
|
518 |
-+ TNow; |
|
519 |
-+ true -> |
|
520 |
-+ 0 |
|
521 |
-+ end, |
|
522 |
-+ {MinPoll, _} = string:to_integer(?MIN_POLLING), |
|
523 |
-+ if |
|
524 |
-+ (Packet == "") and |
|
525 |
-+ (TNow - StateData#state.last_poll < MinPoll*1000*1000) -> |
|
526 |
-+ Reply = {error, polling_too_frequently}, |
|
527 |
-+ {reply, Reply, StateName, StateData}; |
|
528 |
-+ KeyAllow -> |
|
529 |
-+ case RidAllow of |
|
530 |
-+ false -> |
|
531 |
-+ Reply = {error, not_exists}, |
|
532 |
-+ {reply, Reply, StateName, StateData}; |
|
533 |
-+ repeat -> |
|
534 |
-+ ?DEBUG("REPEATING ~p", [RID]), |
|
535 |
-+ [Out | _XS] = [El#hbr.out || |
|
536 |
-+ El <- StateData#state.req_list, |
|
537 |
-+ El#hbr.rid == RID], |
|
538 |
-+ case Out of |
|
539 |
-+ [[] | OutPacket] -> |
|
540 |
-+ Reply = {repeat, OutPacket}; |
|
541 |
-+ _ -> |
|
542 |
-+ Reply = {repeat, Out} |
|
543 |
-+ end, |
|
544 |
-+ {reply, Reply, StateName, |
|
545 |
-+ StateData#state{input = "cancel", last_poll = LastPoll}}; |
|
546 |
-+ true -> |
|
547 |
-+ SaveKey = if |
|
548 |
-+ NewKey == "" -> |
|
549 |
-+ Key; |
|
550 |
-+ true -> |
|
551 |
-+ NewKey |
|
552 |
-+ end, |
|
553 |
-+ ?DEBUG(" -- SaveKey: ~s~n", [SaveKey]), |
|
554 |
-+ |
|
555 |
-+ %% save request |
|
556 |
-+ ReqList = [#hbr{rid=RID, |
|
557 |
-+ key=StateData#state.key, |
|
558 |
-+ in=StateData#state.input, |
|
559 |
-+ out=StateData#state.output |
|
560 |
-+ } | |
|
561 |
-+ [El || El <- StateData#state.req_list, |
|
562 |
-+ El#hbr.rid < RID, |
|
563 |
-+ El#hbr.rid > (RID - 1 - Hold)] |
|
564 |
-+ ], |
|
565 |
-+%% ?DEBUG("reqlist: ~p", [ReqList]), |
|
566 |
-+ case StateData#state.waiting_input of |
|
567 |
-+ false -> |
|
568 |
-+ cancel_timer(StateData#state.timer), |
|
569 |
-+ Timer = erlang:start_timer( |
|
570 |
-+ ?MAX_INACTIVITY, self(), []), |
|
571 |
-+ Input = Packet ++ [StateData#state.input], |
|
572 |
-+ Reply = ok, |
|
573 |
-+ {reply, Reply, StateName, |
|
574 |
-+ StateData#state{input = Input, |
|
575 |
-+ rid = RID, |
|
576 |
-+ key = SaveKey, |
|
577 |
-+ ctime = TNow, |
|
578 |
-+ timer = Timer, |
|
579 |
-+ last_poll = LastPoll, |
|
580 |
-+ req_list = ReqList |
|
581 |
-+ }}; |
|
582 |
-+ {Receiver, _Tag} -> |
|
583 |
-+ Receiver ! {tcp, {http_bind, self()}, |
|
584 |
-+ list_to_binary(Packet)}, |
|
585 |
-+ cancel_timer(StateData#state.timer), |
|
586 |
-+ Timer = erlang:start_timer( |
|
587 |
-+ ?MAX_INACTIVITY, self(), []), |
|
588 |
-+ Reply = ok, |
|
589 |
-+ {reply, Reply, StateName, |
|
590 |
-+ StateData#state{waiting_input = false, |
|
591 |
-+ last_receiver = Receiver, |
|
592 |
-+ input = "", |
|
593 |
-+ rid = RID, |
|
594 |
-+ key = SaveKey, |
|
595 |
-+ ctime = TNow, |
|
596 |
-+ timer = Timer, |
|
597 |
-+ last_poll = LastPoll, |
|
598 |
-+ req_list = ReqList |
|
599 |
-+ }} |
|
600 |
-+ end |
|
601 |
-+ end; |
|
602 |
-+ true -> |
|
603 |
-+ Reply = {error, bad_key}, |
|
604 |
-+ {reply, Reply, StateName, StateData} |
|
605 |
-+ end; |
|
606 |
-+ |
|
607 |
-+handle_sync_event({http_get, RID, Wait, Hold}, _From, StateName, StateData) -> |
|
608 |
-+ {_,TSec,TMSec} = now(), |
|
609 |
-+ TNow = TSec*1000*1000 + TMSec, |
|
610 |
-+ cancel_timer(StateData#state.timer), |
|
611 |
-+ Timer = erlang:start_timer(?MAX_INACTIVITY, self(), []), |
|
612 |
-+ if |
|
613 |
-+ (Hold > 0) and |
|
614 |
-+ (StateData#state.output == "") and |
|
615 |
-+ ((TNow - StateData#state.ctime) < (Wait*1000*1000)) and |
|
616 |
-+ (StateData#state.rid == RID) and |
|
617 |
-+ (StateData#state.input /= "cancel") -> |
|
618 |
-+ Output = StateData#state.output, |
|
619 |
-+ ReqList = StateData#state.req_list, |
|
620 |
-+ Reply = {ok, keep_on_hold}; |
|
621 |
-+ (StateData#state.input == "cancel") -> |
|
622 |
-+ Output = StateData#state.output, |
|
623 |
-+ ReqList = StateData#state.req_list, |
|
624 |
-+ Reply = {ok, cancel}; |
|
625 |
-+ true -> |
|
626 |
-+ case StateData#state.output of |
|
627 |
-+ [[]| OutPacket] -> |
|
628 |
-+ Reply = {ok, OutPacket}; |
|
629 |
-+ _ -> |
|
630 |
-+ Reply = {ok, StateData#state.output} |
|
631 |
-+ end, |
|
632 |
-+ %% save request |
|
633 |
-+ ReqList = [#hbr{rid=RID, |
|
634 |
-+ key=StateData#state.key, |
|
635 |
-+ in=StateData#state.input, |
|
636 |
-+ out=StateData#state.output |
|
637 |
-+ } | |
|
638 |
-+ [El || El <- StateData#state.req_list, |
|
639 |
-+ El#hbr.rid /= RID ] |
|
640 |
-+ ], |
|
641 |
-+ Output = "" |
|
642 |
-+ end, |
|
643 |
-+ {reply, Reply, StateName, StateData#state{ |
|
644 |
-+ input = "", |
|
645 |
-+ output = Output, |
|
646 |
-+ timer = Timer, |
|
647 |
-+ req_list = ReqList}}; |
|
648 |
-+ |
|
649 |
-+handle_sync_event(_Event, _From, StateName, StateData) -> |
|
650 |
-+ Reply = ok, |
|
651 |
-+ {reply, Reply, StateName, StateData}. |
|
652 |
-+ |
|
653 |
-+code_change(_OldVsn, StateName, StateData, _Extra) -> |
|
654 |
-+ {ok, StateName, StateData}. |
|
655 |
-+ |
|
656 |
-+%%---------------------------------------------------------------------- |
|
657 |
-+%% Func: handle_info/3 |
|
658 |
-+%% Returns: {next_state, NextStateName, NextStateData} | |
|
659 |
-+%% {next_state, NextStateName, NextStateData, Timeout} | |
|
660 |
-+%% {stop, Reason, NewStateData} |
|
661 |
-+%%---------------------------------------------------------------------- |
|
662 |
-+handle_info({timeout, Timer, _}, _StateName, |
|
663 |
-+ #state{timer = Timer} = StateData) -> |
|
664 |
-+ ?DEBUG("ding dong", []), |
|
665 |
-+ {stop, normal, StateData}; |
|
666 |
-+ |
|
667 |
-+handle_info(_, StateName, StateData) -> |
|
668 |
-+ {next_state, StateName, StateData}. |
|
669 |
-+ |
|
670 |
-+%%---------------------------------------------------------------------- |
|
671 |
-+%% Func: terminate/3 |
|
672 |
-+%% Purpose: Shutdown the fsm |
|
673 |
-+%% Returns: any |
|
674 |
-+%%---------------------------------------------------------------------- |
|
675 |
-+terminate(_Reason, _StateName, StateData) -> |
|
676 |
-+ ?DEBUG("terminate: deleting session ~s", [StateData#state.id]), |
|
677 |
-+ mnesia:transaction( |
|
678 |
-+ fun() -> |
|
679 |
-+ mnesia:delete({http_bind, StateData#state.id}) |
|
680 |
-+ end), |
|
681 |
-+ case StateData#state.waiting_input of |
|
682 |
-+ false -> |
|
683 |
-+ case StateData#state.last_receiver of |
|
684 |
-+ undefined -> ok; |
|
685 |
-+ Receiver -> Receiver ! {tcp_closed, {http_bind, self()}} |
|
686 |
-+ end; |
|
687 |
-+ {Receiver, _Tag} -> Receiver ! {tcp_closed, {http_bind, self()}} |
|
688 |
-+ end, |
|
689 |
-+ ok. |
|
690 |
-+ |
|
691 |
-+%%%---------------------------------------------------------------------- |
|
692 |
-+%%% Internal functions |
|
693 |
-+%%%---------------------------------------------------------------------- |
|
694 |
-+ |
|
695 |
-+ |
|
696 |
-+http_put(ID, RID, Key, NewKey, Hold, Packet) -> |
|
697 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
698 |
-+ [] -> |
|
699 |
-+ {error, not_exists}; |
|
700 |
-+ [#http_bind{pid = FsmRef}] -> |
|
701 |
-+ gen_fsm:sync_send_all_state_event( |
|
702 |
-+ FsmRef, {http_put, RID, Key, NewKey, Hold, Packet}) |
|
703 |
-+ end. |
|
704 |
-+ |
|
705 |
-+http_get(ID,RID) -> |
|
706 |
-+ case mnesia:dirty_read({http_bind, ID}) of |
|
707 |
-+ [] -> |
|
708 |
-+ {error, not_exists}; |
|
709 |
-+ [#http_bind{pid = FsmRef, wait = Wait, hold = Hold}] -> |
|
710 |
-+ gen_fsm:sync_send_all_state_event(FsmRef, |
|
711 |
-+ {http_get, RID, Wait, Hold}) |
|
712 |
-+ end. |
|
713 |
-+ |
|
714 |
-+ |
|
715 |
-+parse_request(Data) -> |
|
716 |
-+ ?DEBUG("--- incoming data --- ~n~s~n --- END --- ", |
|
717 |
-+ [Data]), |
|
718 |
-+ case xml_stream:parse_element(Data) of |
|
719 |
-+ El when element(1, El) == xmlelement -> |
|
720 |
-+ {xmlelement, Name, Attrs, Els} = El, |
|
721 |
-+ ID = xml:get_attr_s("sid",Attrs), |
|
722 |
-+ {RID,_X} = string:to_integer(xml:get_attr_s("rid",Attrs)), |
|
723 |
-+ Key = xml:get_attr_s("key",Attrs), |
|
724 |
-+ NewKey = xml:get_attr_s("newkey",Attrs), |
|
725 |
-+ Xmlns = xml:get_attr_s("xmlns",Attrs), |
|
726 |
-+ Packet = [xml:element_to_string( |
|
727 |
-+ xml:remove_tag_attr("xmlns",E)) || |
|
728 |
-+ E <- Els], |
|
729 |
-+ if |
|
730 |
-+ Name /= "body" -> |
|
731 |
-+ {error, bad_request}; |
|
732 |
-+ Xmlns /= "http://jabber.org/protocol/httpbind" -> |
|
733 |
-+ {error, bad_request}; |
|
734 |
-+ true -> |
|
735 |
-+ {ok, ID, RID, Key, NewKey, Attrs, Packet} |
|
736 |
-+ end; |
|
737 |
-+ {error, _Reason} -> |
|
738 |
-+ {error, bad_request} |
|
739 |
-+ end. |
|
740 |
-+ |
|
741 |
-+cancel_timer(Timer) -> |
|
742 |
-+ erlang:cancel_timer(Timer), |
|
743 |
-+ receive |
|
744 |
-+ {timeout, Timer, _} -> |
|
745 |
-+ ok |
|
746 |
-+ after 0 -> |
|
747 |
-+ ok |
|
748 |
-+ end. |
|
749 |
-+ |
|
750 |
-+hex(Bin) when binary(Bin) -> hex(binary_to_list(Bin)); |
|
751 |
-+hex([]) -> ""; |
|
752 |
-+hex([H|T]) -> |
|
753 |
-+ [A,B] = if |
|
754 |
-+ H == 0 -> "00"; |
|
755 |
-+ H < 16 -> [$0,element(H,{$1,$2,$3,$4,$5,$6,$7,$8,$9,$a,$b,$c,$d,$e,$f})]; |
|
756 |
-+ true -> erlang:integer_to_list(H,16) |
|
757 |
-+ end, |
|
758 |
-+ [A,B|hex(T)]. |
|
759 |
-+ |
|
760 |
-+elements_to_string([]) -> |
|
761 |
-+ []; |
|
762 |
-+elements_to_string([El | Els]) -> |
|
763 |
-+ xml:element_to_string(El) ++ elements_to_string(Els). |
|
764 |
-Index: src/web/ejabberd_web.erl |
|
765 |
-=================================================================== |
|
766 |
---- src/web/ejabberd_web.erl (Revision 565) |
|
767 |
-+++ src/web/ejabberd_web.erl (Arbeitskopie) |
|
768 |
-@@ -49,7 +49,7 @@ |
|
769 |
- {"value", Value}])). |
|
770 |
- |
|
771 |
- |
|
772 |
--process_get({_, true}, |
|
773 |
-+process_get({_, _, true}, |
|
774 |
- #request{auth = Auth, |
|
775 |
- path = ["admin", "server", SHost | RPath], |
|
776 |
- q = Query, |
|
777 |
-@@ -94,7 +94,7 @@ |
|
778 |
- {404, [], make_xhtml([?XC("h1", "Not found")])} |
|
779 |
- end; |
|
780 |
- |
|
781 |
--process_get({_, true}, |
|
782 |
-+process_get({_, _, true}, |
|
783 |
- #request{auth = Auth, |
|
784 |
- path = ["admin" | RPath], |
|
785 |
- q = Query, |
|
786 |
-@@ -133,12 +133,19 @@ |
|
787 |
- [{xmlcdata, "401 Unauthorized"}]}])} |
|
788 |
- end; |
|
789 |
- |
|
790 |
--process_get({true, _}, |
|
791 |
-+process_get({true, _, _}, |
|
792 |
- #request{path = ["http-poll" | RPath], |
|
793 |
- q = _Query, |
|
794 |
- lang = _Lang} = Request) -> |
|
795 |
- ejabberd_http_poll:process_request(Request#request{path = RPath}); |
|
796 |
- |
|
797 |
-+process_get({_, true, _}, |
|
798 |
-+ #request{us = _US, |
|
799 |
-+ path = ["http-bind" | RPath], |
|
800 |
-+ q = _Query, |
|
801 |
-+ lang = _Lang} = Request) -> |
|
802 |
-+ ejabberd_http_bind:process_request(Request#request{path = RPath}); |
|
803 |
-+ |
|
804 |
- process_get(_, _Request) -> |
|
805 |
- {404, [], make_xhtml([?XC("h1", "Not found")])}. |
|
806 |
- |
|
807 |
-Index: src/web/ejabberd_http.erl |
|
808 |
-=================================================================== |
|
809 |
---- src/web/ejabberd_http.erl (Revision 565) |
|
810 |
-+++ src/web/ejabberd_http.erl (Arbeitskopie) |
|
811 |
-@@ -30,6 +30,7 @@ |
|
812 |
- request_keepalive, |
|
813 |
- request_content_length, |
|
814 |
- request_lang = "en", |
|
815 |
-+ use_http_bind = false, |
|
816 |
- use_http_poll = false, |
|
817 |
- use_web_admin = false, |
|
818 |
- end_of_request = false, |
|
819 |
-@@ -70,15 +71,17 @@ |
|
820 |
- _ -> |
|
821 |
- ok |
|
822 |
- end, |
|
823 |
-+ UseHTTPBind = lists:member(http_bind, Opts), |
|
824 |
- UseHTTPPoll = lists:member(http_poll, Opts), |
|
825 |
- UseWebAdmin = lists:member(web_admin, Opts), |
|
826 |
-- ?DEBUG("S: ~p~n", [{UseHTTPPoll, UseWebAdmin}]), |
|
827 |
-+ ?DEBUG("S: ~p~n", [{UseHTTPPoll, UseHTTPBind, UseWebAdmin}]), |
|
828 |
- ?INFO_MSG("started: ~p", [{SockMod1, Socket1}]), |
|
829 |
- {ok, proc_lib:spawn_link(ejabberd_http, |
|
830 |
- receive_headers, |
|
831 |
- [#state{sockmod = SockMod1, |
|
832 |
- socket = Socket1, |
|
833 |
- use_http_poll = UseHTTPPoll, |
|
834 |
-+ use_http_bind = UseHTTPBind, |
|
835 |
- use_web_admin = UseWebAdmin}])}. |
|
836 |
- |
|
837 |
- |
|
838 |
-@@ -185,6 +188,7 @@ |
|
839 |
- #state{sockmod = SockMod, |
|
840 |
- socket = Socket, |
|
841 |
- use_http_poll = State#state.use_http_poll, |
|
842 |
-+ use_http_bind = State#state.use_http_bind, |
|
843 |
- use_web_admin = State#state.use_web_admin}; |
|
844 |
- _ -> |
|
845 |
- #state{end_of_request = true} |
|
846 |
-@@ -200,6 +204,7 @@ |
|
847 |
- request_auth = Auth, |
|
848 |
- request_lang = Lang, |
|
849 |
- use_http_poll = UseHTTPPoll, |
|
850 |
-+ use_http_bind = UseHTTPBind, |
|
851 |
- use_web_admin = UseWebAdmin} = State) -> |
|
852 |
- case (catch url_decode_q_split(Path)) of |
|
853 |
- {'EXIT', _} -> |
|
854 |
-@@ -217,7 +222,7 @@ |
|
855 |
- q = LQuery, |
|
856 |
- auth = Auth, |
|
857 |
- lang = Lang}, |
|
858 |
-- case ejabberd_web:process_get({UseHTTPPoll, UseWebAdmin}, |
|
859 |
-+ case ejabberd_web:process_get({UseHTTPPoll, UseHTTPBind, UseWebAdmin}, |
|
860 |
- Request) of |
|
861 |
- El when element(1, El) == xmlelement -> |
|
862 |
- make_xhtml_output(State, 200, [], El); |
|
863 |
-@@ -240,6 +245,7 @@ |
|
864 |
- sockmod = SockMod, |
|
865 |
- socket = Socket, |
|
866 |
- use_http_poll = UseHTTPPoll, |
|
867 |
-+ use_http_bind = UseHTTPBind, |
|
868 |
- use_web_admin = UseWebAdmin} = State) |
|
869 |
- when is_integer(Len) -> |
|
870 |
- case SockMod of |
|
871 |
-@@ -267,7 +273,7 @@ |
|
872 |
- auth = Auth, |
|
873 |
- data = Data, |
|
874 |
- lang = Lang}, |
|
875 |
-- case ejabberd_web:process_get({UseHTTPPoll, UseWebAdmin}, |
|
876 |
-+ case ejabberd_web:process_get({UseHTTPPoll, UseHTTPBind, UseWebAdmin}, |
|
877 |
- Request) of |
|
878 |
- El when element(1, El) == xmlelement -> |
|
879 |
- make_xhtml_output(State, 200, [], El); |
|
880 |
-Index: src/xml.erl |
|
881 |
-=================================================================== |
|
882 |
---- src/xml.erl (Revision 565) |
|
883 |
-+++ src/xml.erl (Arbeitskopie) |
|
884 |
-@@ -18,6 +18,7 @@ |
|
885 |
- get_tag_attr/2, get_tag_attr_s/2, |
|
886 |
- get_subtag/2, |
|
887 |
- get_path_s/2, |
|
888 |
-+ remove_tag_attr/2, |
|
889 |
- replace_tag_attr/3]). |
|
890 |
- |
|
891 |
- %element_to_string(El) -> |
|
892 |
-@@ -224,6 +225,14 @@ |
|
893 |
- get_path_s(El, [cdata]) -> |
|
894 |
- get_tag_cdata(El). |
|
895 |
- |
|
896 |
-+remove_tag_attr(Attr, El) -> |
|
897 |
-+ case El of |
|
898 |
-+ {xmlelement, Name, Attrs, Els} -> |
|
899 |
-+ Attrs1 = lists:keydelete(Attr, 1, Attrs), |
|
900 |
-+ {xmlelement, Name, Attrs1, Els}; |
|
901 |
-+ _ -> |
|
902 |
-+ El |
|
903 |
-+ end. |
|
904 |
- |
|
905 |
- replace_tag_attr(Attr, Value, {xmlelement, Name, Attrs, Els}) -> |
|
906 |
- Attrs1 = lists:keydelete(Attr, 1, Attrs), |
|
907 |
- |
|
908 |
-Index: src/ejabberd_sup.erl |
|
909 |
-=================================================================== |
|
910 |
---- src/ejabberd_sup.erl (Revision 565) |
|
911 |
-+++ src/ejabberd_sup.erl (Arbeitskopie) |
|
912 |
-@@ -123,6 +123,14 @@ |
|
913 |
- infinity, |
|
914 |
- supervisor, |
|
915 |
- [ejabberd_tmp_sup]}, |
|
916 |
-+ HTTPBindSupervisor = |
|
917 |
-+ {ejabberd_http_bind_sup, |
|
918 |
-+ {ejabberd_tmp_sup, start_link, |
|
919 |
-+ [ejabberd_http_bind_sup, ejabberd_http_bind]}, |
|
920 |
-+ permanent, |
|
921 |
-+ infinity, |
|
922 |
-+ supervisor, |
|
923 |
-+ [ejabberd_tmp_sup]}, |
|
924 |
- IQSupervisor = |
|
925 |
- {ejabberd_iq_sup, |
|
926 |
- {ejabberd_tmp_sup, start_link, |
|
927 |
-@@ -145,6 +153,7 @@ |
|
928 |
- ServiceSupervisor, |
|
929 |
- HTTPSupervisor, |
|
930 |
- HTTPPollSupervisor, |
|
931 |
-+ HTTPBindSupervisor, |
|
932 |
- IQSupervisor, |
|
933 |
- Listener]}}. |
|
934 |
- |
... | ... |
@@ -1,11 +0,0 @@ |
1 |
---- mod_irc/mod_irc.erl.orig 2006-11-19 14:40:02.463429250 +0100 |
|
2 |
-+++ mod_irc/mod_irc.erl 2006-11-19 14:40:25.888893250 +0100 |
|
3 |
-@@ -27,7 +27,7 @@ |
|
4 |
- -include("ejabberd.hrl"). |
|
5 |
- -include("jlib.hrl"). |
|
6 |
- |
|
7 |
---define(DEFAULT_IRC_ENCODING, "koi8-r"). |
|
8 |
-+-define(DEFAULT_IRC_ENCODING, "utf-8"). |
|
9 |
- |
|
10 |
- -record(irc_connection, {jid_server_host, pid}). |
|
11 |
- -record(irc_custom, {us_host, data}). |
... | ... |
@@ -1,12 +0,0 @@ |
1 |
-diff -Naur ejabberd-1.1.1.orig/src/odbc/ejabberd_odbc.erl ejabberd-1.1.1/src/odbc/ejabberd_odbc.erl |
|
2 |
---- ejabberd-1.1.1.orig/src/odbc/ejabberd_odbc.erl 2006-05-07 19:05:12.549917750 +0400 |
|
3 |
-+++ ejabberd-1.1.1/src/odbc/ejabberd_odbc.erl 2006-05-07 19:06:11.337591750 +0400 |
|
4 |
-@@ -272,7 +272,6 @@ |
|
5 |
- case mysql_conn:start(Server, ?MYSQL_PORT, Username, Password, DB, NoLogFun) of |
|
6 |
- {ok, Ref} -> |
|
7 |
- erlang:monitor(process, Ref), |
|
8 |
-+ catch mysql_conn:fetch(Ref, "SET NAMES 'utf8';", self()), |
|
9 |
- {ok, #state{db_ref = Ref, db_type = mysql}}; |
|
10 |
- {error, Reason} -> |
|
11 |
- ?ERROR_MSG("MySQL connection failed: ~p~n", [Reason]), |
|
12 |
- |
... | ... |
@@ -1,406 +0,0 @@ |
1 |
-* modified files |
|
2 |
- |
|
3 |
- |
|
4 |
---- jlib.hrl |
|
5 |
-+++ jlib.hrl |
|
6 |
-@@ -34,6 +34,7 @@ |
|
7 |
- -define(NS_PUBSUB_OWNER, "http://jabber.org/protocol/pubsub#owner"). |
|
8 |
- -define(NS_PUBSUB_NMI, "http://jabber.org/protocol/pubsub#node-meta-info"). |
|
9 |
- -define(NS_COMMANDS, "http://jabber.org/protocol/commands"). |
|
10 |
-+-define(NS_BYTESTREAMS, "http://jabber.org/protocol/bytestreams"). |
|
11 |
- |
|
12 |
- -define(NS_EJABBERD_CONFIG, "ejabberd:config"). |
|
13 |
- |
|
14 |
- |
|
15 |
- |
|
16 |
- |
|
17 |
-* added files |
|
18 |
- |
|
19 |
---- /dev/null |
|
20 |
-+++ mod_proxy65.erl |
|
21 |
-@@ -0,0 +1,189 @@ |
|
22 |
-+%%%---------------------------------------------------------------------- |
|
23 |
-+%%% File : mod_proxy65.erl |
|
24 |
-+%%% Author : Magnus Henoch <henoch@dtek.chalmers.se> |
|
25 |
-+%%% Purpose : Handle Jabber communications for JEP-0065 proxy |
|
26 |
-+%%% Created : 27 Dec 2005 by Magnus Henoch <henoch@dtek.chalmers.se> |
|
27 |
-+%%% Id : $Id: ejabberd_c2s.erl 440 2005-11-22 18:00:56Z alexey $ |
|
28 |
-+%%%---------------------------------------------------------------------- |
|
29 |
-+ |
|
30 |
-+-module(mod_proxy65). |
|
31 |
-+-author('henoch@dtek.chalmers.se'). |
|
32 |
-+-vsn('$Revision$ '). |
|
33 |
-+ |
|
34 |
-+-behaviour(gen_mod). |
|
35 |
-+ |
|
36 |
-+-export([start/2, |
|
37 |
-+ init/1, |
|
38 |
-+ stop/1]). |
|
39 |
-+ |
|
40 |
-+-include("ejabberd.hrl"). |
|
41 |
-+-include("jlib.hrl"). |
|
42 |
-+ |
|
43 |
-+-record(proxy65_connection, {cookie, firstpid = none, secondpid = none}). |
|
44 |
-+ |
|
45 |
-+-record(proxy65_options, {host, access, streamhosts}). |
|
46 |
-+ |
|
47 |
-+-define(PROCNAME, ejabberd_mod_proxy65). |
|
48 |
-+ |
|
49 |
-+start(Host, Opts) -> |
|
50 |
-+ mnesia:create_table(proxy65_connection, |
|
51 |
-+ [{ram_copies, [node()]}, |
|
52 |
-+ {attributes, record_info(fields, proxy65_connection)}]), |
|
53 |
-+ MyHost = gen_mod:get_opt(host, Opts, "proxy." ++ Host), |
|
54 |
-+ Access = gen_mod:get_opt(access, Opts, all), |
|
55 |
-+ Streamhosts = gen_mod:get_opt(streamhosts, Opts, [{Host, 7777}]), |
|
56 |
-+ |
|
57 |
-+ register(gen_mod:get_module_proc(Host, ?PROCNAME), |
|
58 |
-+ spawn(?MODULE, init, [#proxy65_options{host = MyHost, access = Access, |
|
59 |
-+ streamhosts = Streamhosts}])). |
|
60 |
-+ |
|
61 |
-+ |
|
62 |
-+stop(Host) -> |
|
63 |
-+ Proc = gen_mod:get_module_proc(Host, ?PROCNAME), |
|
64 |
-+ Proc ! stop, |
|
65 |
-+ {wait, Proc}. |
|
66 |
-+ |
|
67 |
-+init(#proxy65_options{host = Host} = Opts) -> |
|
68 |
-+ ejabberd_router:register_route(Host), |
|
69 |
-+ loop(Opts). |
|
70 |
-+ |
|
71 |
-+loop(#proxy65_options{host = Host} = Opts) -> |
|
72 |
-+ receive |
|
73 |
-+ {route, From, To, Packet} -> |
|
74 |
-+ case catch do_route(Opts, From, To, Packet) of |
|
75 |
-+ {'EXIT', Reason} -> |
|
76 |
-+ ?ERROR_MSG("~p", [Reason]); |
|
77 |
-+ _ -> |
|
78 |
-+ ok |
|
79 |
-+ end, |
|
80 |
-+ loop(Opts); |
|
81 |
-+ stop -> |
|
82 |
-+ ejabberd_router:unregister_route(Host), |
|
83 |
-+ ok; |
|
84 |
-+ _ -> |
|
85 |
-+ loop(Opts) |
|
86 |
-+ end. |
|
87 |
-+ |
|
88 |
-+do_route(#proxy65_options{host = Host, access = Access} = Opts, |
|
89 |
-+ From, To, Packet) -> |
|
90 |
-+ case acl:match_rule(Host, Access, From) of |
|
91 |
-+ allow -> |
|
92 |
-+ do_route1(Opts, From, To, Packet); |
|
93 |
-+ _ -> |
|
94 |
-+ {xmlelement, _Name, Attrs, _Els} = Packet, |
|
95 |
-+ Lang = xml:get_attr_s("xml:lang", Attrs), |
|
96 |
-+ ErrText = "Access denied by service policy", |
|
97 |
-+ Err = jlib:make_error_reply(Packet, |
|
98 |
-+ ?ERRT_FORBIDDEN(Lang, ErrText)), |
|
99 |
-+ ejabberd_router:route(To, From, Err) |
|
100 |
-+ end. |
|
101 |
-+ |
|
102 |
-+do_route1(#proxy65_options{host = Host, streamhosts = Streamhosts}, From, To, Packet) -> |
|
103 |
-+ {xmlelement, Name, _Attrs, _Els} = Packet, |
|
104 |
-+ case Name of |
|
105 |
-+ "iq" -> |
|
106 |
-+ case jlib:iq_query_info(Packet) of |
|
107 |
-+ #iq{type = get, xmlns = ?NS_DISCO_INFO = XMLNS, |
|
108 |
-+ lang = Lang, sub_el = SubEl} = IQ -> |
|
109 |
-+ Node = xml:get_tag_attr_s("node", SubEl), |
|
110 |
-+ if Node == [] -> |
|
111 |
-+ Res = IQ#iq{type = result, |
|
112 |
-+ sub_el = [{xmlelement, "query", |
|
113 |
-+ [{"xmlns", XMLNS}], |
|
114 |
-+ [{xmlelement, "identity", |
|
115 |
-+ [{"category", "proxy"}, |
|
116 |
-+ {"type", "bytestreams"}, |
|
117 |
-+ {"name", translate:translate(Lang, "SOCKS5 bytestreams proxy")}], |
|
118 |
-+ []}, |
|
119 |
-+ {xmlelement, "feature", |
|
120 |
-+ [{"var", ?NS_BYTESTREAMS}], []}]}]}; |
|
121 |
-+ true -> |
|
122 |
-+ Res = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND) |
|
123 |
-+ end; |
|
124 |
-+ #iq{type = get, xmlns = ?NS_DISCO_ITEMS = XMLNS} = IQ -> |
|
125 |
-+ Res = IQ#iq{type = result, |
|
126 |
-+ sub_el = [{xmlelement, "query", |
|
127 |
-+ [{"xmlns", XMLNS}], []}]}; |
|
128 |
-+ #iq{type = get, xmlns = ?NS_VERSION} = IQ -> |
|
129 |
-+ OSType = case os:type() of |
|
130 |
-+ {Osfamily, Osname} -> |
|
131 |
-+ atom_to_list(Osfamily) ++ "/" ++ |
|
132 |
-+ atom_to_list(Osname); |
|
133 |
-+ Osfamily -> |
|
134 |
-+ atom_to_list(Osfamily) |
|
135 |
-+ end, |
|
136 |
-+ OSVersion = case os:version() of |
|
137 |
-+ {Major, Minor, Release} -> |
|
138 |
-+ lists:flatten( |
|
139 |
-+ io_lib:format("~w.~w.~w", |
|
140 |
-+ [Major, Minor, Release])); |
|
141 |
-+ VersionString -> |
|
142 |
-+ VersionString |
|
143 |
-+ end, |
|
144 |
-+ OS = OSType ++ " " ++ OSVersion, |
|
145 |
-+ Res = IQ#iq{type = result, |
|
146 |
-+ sub_el = [{xmlelement, "query", |
|
147 |
-+ [{"xmlns", ?NS_VERSION}], |
|
148 |
-+ [{xmlelement, "name", [], |
|
149 |
-+ [{xmlcdata, "ejabberd mod_proxy65 (unofficial)"}]}, |
|
150 |
-+ {xmlelement, "version", [], |
|
151 |
-+ [{xmlcdata, "0.1"}]}, |
|
152 |
-+ {xmlelement, "os", [], |
|
153 |
-+ [{xmlcdata, OS}]} |
|
154 |
-+ ]}]}; |
|
155 |
-+ #iq{type = get, xmlns = ?NS_BYTESTREAMS = XMLNS} = IQ -> |
|
156 |
-+ Res = IQ#iq{type = result, |
|
157 |
-+ sub_el = [{xmlelement, "query", |
|
158 |
-+ [{"xmlns", XMLNS}], |
|
159 |
-+ return_streamhosts(Host, Streamhosts)}]}; |
|
160 |
-+ #iq{type = set, xmlns = ?NS_BYTESTREAMS} = IQ -> |
|
161 |
-+ Res = activate(Packet, From, To, IQ); |
|
162 |
-+ _ -> |
|
163 |
-+ Res = jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED) |
|
164 |
-+ end, |
|
165 |
-+ case Res of |
|
166 |
-+ #iq{} -> |
|
167 |
-+ ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); |
|
168 |
-+ _ -> |
|
169 |
-+ ejabberd_router:route(To, From, Res) |
|
170 |
-+ end; |
|
171 |
-+ _ -> |
|
172 |
-+ ejabberd_router:route(To, From, jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED)) |
|
173 |
-+ end. |
|
174 |
-+ |
|
175 |
-+return_streamhosts(_JID, []) -> |
|
176 |
-+ []; |
|
177 |
-+return_streamhosts(JID, [{Host, Port} | Streamhosts]) -> |
|
178 |
-+ %% This is not tail-recursive, but it doesn't matter. |
|
179 |
-+ [{xmlelement, "streamhost", |
|
180 |
-+ [{"jid", JID}, |
|
181 |
-+ {"host", Host}, |
|
182 |
-+ {"port", integer_to_list(Port)}], |
|
183 |
-+ []} | return_streamhosts(JID, Streamhosts)]. |
|
184 |
-+ |
|
185 |
-+activate(Packet, From, _To, #iq{sub_el = SubEl} = IQ) -> |
|
186 |
-+ case SubEl of |
|
187 |
-+ {xmlelement, "query", Attrs, _SubEls} -> |
|
188 |
-+ Sid = xml:get_attr_s("sid", Attrs), |
|
189 |
-+ ActivateTag = xml:get_subtag(SubEl, "activate"), |
|
190 |
-+ if ActivateTag /= false -> |
|
191 |
-+ TargetJID = jlib:string_to_jid(xml:get_tag_cdata(ActivateTag)); |
|
192 |
-+ true -> |
|
193 |
-+ TargetJID = false |
|
194 |
-+ end, |
|
195 |
-+ |
|
196 |
-+ if Sid /= [], TargetJID /= false, TargetJID /= error -> |
|
197 |
-+ case proxy65_listener:activate(From, TargetJID, Sid) of |
|
198 |
-+ ok -> |
|
199 |
-+ ?INFO_MSG("Activated connection between ~s and ~s", |
|
200 |
-+ [jlib:jid_to_string(From), TargetJID]), |
|
201 |
-+ IQ#iq{type = result, sub_el = []}; |
|
202 |
-+ _ -> |
|
203 |
-+ jlib:make_error_reply(Packet, ?ERR_INTERNAL_SERVER_ERROR) |
|
204 |
-+ end; |
|
205 |
-+ true -> |
|
206 |
-+ jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST) |
|
207 |
-+ end; |
|
208 |
-+ _ -> |
|
209 |
-+ jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST) |
|
210 |
-+ end. |
|
211 |
---- /dev/null |
|
212 |
-+++ proxy65_listener.erl |
|
213 |
-@@ -0,0 +1,192 @@ |
|
214 |
-+%%%---------------------------------------------------------------------- |
|
215 |
-+%%% File : proxy65_listener.erl |
|
216 |
-+%%% Author : Magnus Henoch <henoch@dtek.chalmers.se> |
|
217 |
-+%%% Purpose : Handle SOCKS5 connections for JEP-0065 proxy |
|
218 |
-+%%% Created : 27 Dec 2005 by Magnus Henoch <henoch@dtek.chalmers.se> |
|
219 |
-+%%% Id : $Id: ejabberd_c2s.erl 440 2005-11-22 18:00:56Z alexey $ |
|
220 |
-+%%%---------------------------------------------------------------------- |
|
221 |
-+ |
|
222 |
-+-module(proxy65_listener). |
|
223 |
-+-author('henoch@dtek.chalmers.se'). |
|
224 |
-+-vsn('$Revision$ '). |
|
225 |
-+ |
|
226 |
-+-export([start/2, handle_connection/2, activate/3]). |
|
227 |
-+ |
|
228 |
-+-include("ejabberd.hrl"). |
|
229 |
-+-include("jlib.hrl"). |
|
230 |
-+ |
|
231 |
-+-record(proxy65_connection, {cookie, firstpid = none, secondpid = none}). |
|
232 |
-+ |
|
233 |
-+start({SockMod, Socket}, Opts) -> |
|
234 |
-+ {ok, proc_lib:spawn(?MODULE, handle_connection, [{SockMod, Socket}, Opts])}. |
|
235 |
-+ |
|
236 |
-+read_bytes(_SockOpts, 0, Data) -> |
|
237 |
-+ lists:flatten(Data); |
|
238 |
-+read_bytes({SockMod, Socket} = SockOpts, N, Data) -> |
|
239 |
-+ Timeout = 1000, |
|
240 |
-+ case SockMod:recv(Socket, N, Timeout) of |
|
241 |
-+ {error, closed} -> |
|
242 |
-+ %% On closed connection, return everything we have, |
|
243 |
-+ %% but not if we have nothing. |
|
244 |
-+ if Data == [] -> |
|
245 |
-+ erlang:error(closed); |
|
246 |
-+ true -> |
|
247 |
-+ lists:flatten(Data) |
|
248 |
-+ end; |
|
249 |
-+ {ok, MoreData} -> |
|
250 |
-+ ?DEBUG("read ~p", [MoreData]), |
|
251 |
-+ DataList = binary_to_list(MoreData), |
|
252 |
-+ read_bytes(SockOpts, N - length(DataList), [Data, DataList]) |
|
253 |
-+ end. |
|
254 |
-+ |
|
255 |
-+handle_connection({SockMod, Socket}, Opts) -> |
|
256 |
-+ ?DEBUG("in handle_connection", []), |
|
257 |
-+ case catch handle_auth({SockMod, Socket}, Opts) of |
|
258 |
-+ {'EXIT', Reason} -> |
|
259 |
-+ ?ERROR_MSG("~p abnormal termination:~n\t~p~n", |
|
260 |
-+ [?MODULE, Reason]), |
|
261 |
-+ SockMod:close(Socket); |
|
262 |
-+ _ -> |
|
263 |
-+ ok |
|
264 |
-+ end. |
|
265 |
-+ |
|
266 |
-+handle_auth({SockMod, Socket} = SockOpts, Opts) -> |
|
267 |
-+ ?DEBUG("in handle_auth", []), |
|
268 |
-+ %% SOCKS protocol stuff... |
|
269 |
-+ [5, NAuthMethods] = read_bytes(SockOpts, 2, []), |
|
270 |
-+ AuthMethods = read_bytes(SockOpts, NAuthMethods, []), |
|
271 |
-+ SupportsNoAuth = lists:member(0, AuthMethods), |
|
272 |
-+ |
|
273 |
-+ %% Must support no authentication, otherwise crash |
|
274 |
-+ true = SupportsNoAuth, |
|
275 |
-+ |
|
276 |
-+ SockMod:send(Socket, [5, 0]), |
|
277 |
-+ |
|
278 |
-+ %% And done. |
|
279 |
-+ handle_connect(SockOpts, Opts). |
|
280 |
-+ |
|
281 |
-+handle_connect({SockMod, Socket} = SockOpts, Opts) -> |
|
282 |
-+ ?DEBUG("in handle_connect", []), |
|
283 |
-+ %% Expect a CONNECT command and nothing else |
|
284 |
-+ [5, 1, _, 3, AddressLength] = read_bytes(SockOpts, 5, []), |
|
285 |
-+ Cookie = read_bytes(SockOpts, AddressLength, []), |
|
286 |
-+ [0, 0] = read_bytes(SockOpts, 2, []), |
|
287 |
-+ |
|
288 |
-+ %% Make sure no more than two connections claim the same cookie. |
|
289 |
-+ F = fun() -> |
|
290 |
-+ case mnesia:read({proxy65_connection, Cookie}) of |
|
291 |
-+ [] -> |
|
292 |
-+ mnesia:write(#proxy65_connection{cookie = Cookie, |
|
293 |
-+ firstpid = self()}), |
|
294 |
-+ ok; |
|
295 |
-+ [#proxy65_connection{secondpid = none} = C] -> |
|
296 |
-+ mnesia:write(C#proxy65_connection{secondpid = self()}), |
|
297 |
-+ ok |
|
298 |
-+ end |
|
299 |
-+ end, |
|
300 |
-+ |
|
301 |
-+ case mnesia:transaction(F) of |
|
302 |
-+ {atomic, ok} -> |
|
303 |
-+ SockMod:send(Socket, [5, 0, 0, 3, AddressLength, Cookie, 0, 0]), |
|
304 |
-+ wait_for_activation(SockOpts, Opts); |
|
305 |
-+ Error -> |
|
306 |
-+ %% conflict. send "general SOCKS server failure". |
|
307 |
-+ SockMod:send(Socket, [5, 1, 0, 3, AddressLength, Cookie, 0, 0]), |
|
308 |
-+ erlang:error({badconnect, Error}) |
|
309 |
-+ end. |
|
310 |
-+ |
|
311 |
-+wait_for_activation(SockOpts, Opts) -> |
|
312 |
-+ ?DEBUG("in wait_for_activation", []), |
|
313 |
-+ receive |
|
314 |
-+ {get_socket, ReplyTo} -> |
|
315 |
-+ ReplyTo ! SockOpts, |
|
316 |
-+ wait_for_activation(SockOpts, Opts); |
|
317 |
-+ {activate, TargetSocket, Initiator, Target} -> |
|
318 |
-+ ?DEBUG("activated", []), |
|
319 |
-+ |
|
320 |
-+ %% We have no way of knowing which connection belongs to |
|
321 |
-+ %% which participant, so give both the maximum traffic |
|
322 |
-+ %% allowed to either. |
|
323 |
-+ Shapers = case lists:keysearch(shaper, 1, Opts) of |
|
324 |
-+ {value, {_, S}} -> S; |
|
325 |
-+ _ -> none |
|
326 |
-+ end, |
|
327 |
-+ ?DEBUG("we have shapers: ~p", [Shapers]), |
|
328 |
-+ Shaper1 = acl:match_rule(global, Shapers, jlib:string_to_jid(Initiator)), |
|
329 |
-+ Shaper2 = acl:match_rule(global, Shapers, jlib:string_to_jid(Target)), |
|
330 |
-+ if Shaper1 == none; Shaper2 == none -> |
|
331 |
-+ MaxShaper = none; |
|
332 |
-+ true -> |
|
333 |
-+ ShaperValue1 = ejabberd_config:get_global_option({shaper, Shaper1}), |
|
334 |
-+ ShaperValue2 = ejabberd_config:get_global_option({shaper, Shaper2}), |
|
335 |
-+ |
|
336 |
-+ if ShaperValue1 > ShaperValue2 -> |
|
337 |
-+ MaxShaper = Shaper1; |
|
338 |
-+ true -> |
|
339 |
-+ MaxShaper = Shaper2 |
|
340 |
-+ end, |
|
341 |
-+ ?DEBUG("shapers have values ~p and ~p~nusing ~p", [ShaperValue1, ShaperValue2, MaxShaper]), |
|
342 |
-+ ok |
|
343 |
-+ end, |
|
344 |
-+ |
|
345 |
-+ transfer_data(SockOpts, TargetSocket, shaper:new(MaxShaper)) |
|
346 |
-+ end. |
|
347 |
-+ |
|
348 |
-+transfer_data({SockMod, Socket} = SockOpts, {TargetSockMod, TargetSocket} = TargetSockOpts, |
|
349 |
-+ Shaper) -> |
|
350 |
-+ case SockMod:recv(Socket, 0, infinity) of |
|
351 |
-+ {ok, Data} -> |
|
352 |
-+ if Data /= <<>> -> |
|
353 |
-+ NewShaper = case Shaper of |
|
354 |
-+ none -> none; |
|
355 |
-+ _ -> |
|
356 |
-+ shaper:update(Shaper, size(Data)) |
|
357 |
-+ end, |
|
358 |
-+ ok = TargetSockMod:send(TargetSocket, Data); |
|
359 |
-+ true -> |
|
360 |
-+ NewShaper = Shaper |
|
361 |
-+ end, |
|
362 |
-+ transfer_data(SockOpts, TargetSockOpts, NewShaper); |
|
363 |
-+ {error, _} -> |
|
364 |
-+ TargetSockMod:shutdown(TargetSocket, read_write) |
|
365 |
-+ end. |
|
366 |
-+ |
|
367 |
-+get_socket(PID) -> |
|
368 |
-+ PID ! {get_socket, self()}, |
|
369 |
-+ receive |
|
370 |
-+ {_SockMod, _Socket} = SockOpts -> |
|
371 |
-+ SockOpts |
|
372 |
-+ end. |
|
373 |
-+ |
|
374 |
-+%% If any argument is a jid record, convert it to normalized string form... |
|
375 |
-+activate(#jid{} = Initiator, Target, SessionID) -> |
|
376 |
-+ NormalizedInitiator = jlib:jid_to_string(jlib:make_jid(jlib:jid_tolower(Initiator))), |
|
377 |
-+ activate(NormalizedInitiator, Target, SessionID); |
|
378 |
-+activate(Initiator, #jid{} = Target, SessionID) -> |
|
379 |
-+ NormalizedTarget = jlib:jid_to_string(jlib:make_jid(jlib:jid_tolower(Target))), |
|
380 |
-+ activate(Initiator, NormalizedTarget, SessionID); |
|
381 |
-+%% ...and get on with the activation. |
|
382 |
-+activate(Initiator, Target, SessionID) -> |
|
383 |
-+ Cookie = sha:sha(SessionID ++ Initiator ++ Target), |
|
384 |
-+ F = fun() -> |
|
385 |
-+ case mnesia:read({proxy65_connection, Cookie}) of |
|
386 |
-+ [#proxy65_connection{firstpid = FirstPID, |
|
387 |
-+ secondpid = SecondPID}] |
|
388 |
-+ when is_pid(FirstPID), is_pid(SecondPID) -> |
|
389 |
-+ mnesia:delete({proxy65_connection, Cookie}), |
|
390 |
-+ {FirstPID, SecondPID}; |
|
391 |
-+ _ -> |
|
392 |
-+ error |
|
393 |
-+ end |
|
394 |
-+ end, |
|
395 |
-+ case mnesia:transaction(F) of |
|
396 |
-+ {atomic, {FirstPID, SecondPID}} -> |
|
397 |
-+ FirstSocket = get_socket(FirstPID), |
|
398 |
-+ SecondSocket = get_socket(SecondPID), |
|
399 |
-+ FirstPID ! {activate, SecondSocket, Initiator, Target}, |
|
400 |
-+ SecondPID ! {activate, FirstSocket, Initiator, Target}, |
|
401 |
-+ ok; |
|
402 |
-+ Error -> |
|
403 |
-+ ?ERROR_MSG("Proxy activation failed: ~p", [Error]), |
|
404 |
-+ error |
|
405 |
-+ end. |
|
406 |
- |
... | ... |
@@ -1,17 +0,0 @@ |
1 |
-# Copyright 1999-2005 Gentoo Foundation |
|
2 |
-# Distributed under the terms of the GNU General Public License v2 |
|
3 |
-# $Header: $ |
|
4 |
- |
|
5 |
-# Name of your ejabberd node. Used by ejabberdctl to determine which |
|
6 |
-# node to communicate with. Default is "ejabberd@`hostname -s`". |
|
7 |
-#EJABBERD_NODE="ejabberd@`hostname -s`" |
|
8 |
- |
|
9 |
-# Max number of open network connections. Default is 1024. Increasing |
|
10 |
-# this will slightly increase memory usage. |
|
11 |
-#ERL_MAX_PORTS=1024 |
|
12 |
- |
|
13 |
-# Return memory to the system after using it, instead of keeping it |
|
14 |
-# allocated for future use. Decreases the memory required by ejabberd, |
|
15 |
-# but makes it run slower. Default is unset, set to any value to |
|
16 |
-# activate. |
|
17 |
-#ERL_FULLSWEEP_AFTER=0 |
... | ... |
@@ -1,60 +0,0 @@ |
1 |
-#!/sbin/runscript |
|
2 |
-# Copyright 1999-2005 Gentoo Foundation |
|
3 |
-# Distributed under the terms of the GNU General Public License v2 |
|
4 |
-# $Header: $ |
|
5 |
- |
|
6 |
-opts="${opts} reload" |
|
7 |
- |
|
8 |
-depend() { |
|
9 |
- use dns |
|
10 |
- need net |
|
11 |
- provide jabber-server |
|
12 |
-} |
|
13 |
- |
|
14 |
-checkconfig() { |
|
15 |
- if [ ! -e /etc/jabber/ejabberd.cfg ] ; then |
|
16 |
- eerror "You need an /etc/jabber/ejabberd.cfg file to run ejabberd" |
|
17 |
- return 1 |
|
18 |
- fi |
|
19 |
-} |
|
20 |
- |
|
21 |
-start() { |
|
22 |
- checkconfig || return 1 |
|
23 |
- ebegin "Starting eJabberd" |
|
24 |
- start-stop-daemon --start --quiet --chuid jabber:jabber \ |
|
25 |
- --exec /usr/bin/env HOME=/var/run/jabber /usr/bin/ejabberd -- -noshell -detached |
|
26 |
- eend $? |
|
27 |
-} |
|
28 |
- |
|
29 |
-stop() { |
|
30 |
- ebegin "Stopping eJabberd" |
|
31 |
- if [ -z "$EJABBERD_NODE" ]; |
|
32 |
- then |
|
33 |
- EJABBERD_NODE="ejabberd@`hostname -s`" |
|
34 |
- fi |
|
35 |
- /usr/bin/ejabberdctl $EJABBERD_NODE stop |
|
36 |
- eend $? |
|
37 |
-} |
|
38 |
- |
|
39 |
-# Work around a bug in /sbin/runscript.sh - it won't run our custom |
|
40 |
-# restart() unless it finds these two strings in the file. |
|
41 |
-# svc_start svc_stop |
|
42 |
-restart() { |
|
43 |
- ebegin "Restarting eJabberd" |
|
44 |
- if [ -z "$EJABBERD_NODE" ]; |
|
45 |
- then |
|
46 |
- EJABBERD_NODE="ejabberd@`hostname -s`" |
|
47 |
- fi |
|
48 |
- /usr/bin/ejabberdctl $EJABBERD_NODE restart |
|
49 |
- eend $? |
|
50 |
-} |
|
51 |
- |
|
52 |
-reload() { |
|
53 |
- ebegin "Reloading eJabberd" |
|
54 |
- if [ -z "$EJABBERD_NODE" ]; |
|
55 |
- then |
|
56 |
- EJABBERD_NODE="ejabberd@`hostname -s`" |
|
57 |
- fi |
|
58 |
- /usr/bin/ejabberdctl $EJABBERD_NODE reopen-log |
|
59 |
- eend $? |
|
60 |
-} |
... | ... |
@@ -1 +0,0 @@ |
1 |
-{file, resolv, "/etc/resolv.conf"}. |
... | ... |
@@ -1,10 +0,0 @@ |
1 |
-<?xml version="1.0" encoding="UTF-8"?> |
|
2 |
-<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd"> |
|
3 |
- |
|
4 |
-<pkgmetadata> |
|
5 |
-<herd>net-im</herd> |
|
6 |
-<maintainer> |
|
7 |
- <email>lars@breakmygentoo.net</email> |
|
8 |
-</maintainer> |
|
9 |
-<longdescription> Free and Open Source distributed fault-tolerant Jabber server. It's mostly written in Erlang, and works on many platforms.</longdescription> |
|
10 |
-</pkgmetadata> |
|
11 | 0 |