Compare commits
963 Commits
resolver-f
...
develop
Author | SHA1 | Date |
---|---|---|
genofire | aa8b9f338f | |
genofire | 658c1c58d5 | |
genofire | 39792f0815 | |
Daniel Gultsch | db834a1f07 | |
Daniel Gultsch | f8a94161db | |
Daniel Gultsch | 5d526a77e3 | |
Daniel Gultsch | a508a81553 | |
Daniel Gultsch | 61fb38cd84 | |
Daniel Gultsch | 1bf2d5dd8f | |
Daniel Gultsch | 0a18c8613f | |
Daniel Gultsch | abb671616c | |
Daniel Gultsch | 297a843b9c | |
Daniel Gultsch | 0698fa0d8c | |
Daniel Gultsch | 70b5d8d81a | |
Daniel Gultsch | 0a3947b8e3 | |
Daniel Gultsch | 3f402b132b | |
Daniel Gultsch | 5b80c62a63 | |
Daniel Gultsch | 717c83753f | |
Daniel Gultsch | b6dee6da6a | |
Daniel Gultsch | 9c3f55bef2 | |
Daniel Gultsch | 9843b72f6f | |
Daniel Gultsch | 61851e5f84 | |
Daniel Gultsch | 4ec0996dff | |
genofire | fa1363cea0 | |
Daniel Gultsch | fda45a7c86 | |
Daniel Gultsch | b5786787f0 | |
Daniel Gultsch | d4cbf2e11e | |
Daniel Gultsch | 7d7e158fd7 | |
Daniel Gultsch | a8ff88398d | |
Daniel Gultsch | bae9fc45c2 | |
Daniel Gultsch | ba4a47204b | |
Daniel Gultsch | 226eb739bd | |
Daniel Gultsch | 869a135bab | |
Daniel Gultsch | 7ddd60d314 | |
Daniel Gultsch | 2ca00265db | |
Daniel Gultsch | e0c4964cc2 | |
Daniel Gultsch | 3706981645 | |
genofire | a124b3df9a | |
genofire | 5a7bae592d | |
Daniel Gultsch | 6d2e406ee5 | |
Daniel Gultsch | cc489ef7bf | |
Daniel Gultsch | 495537d087 | |
Daniel Gultsch | 20e4d108d4 | |
Daniel Gultsch | d0af5a002e | |
Daniel Gultsch | 86de21f6a8 | |
Daniel Gultsch | e664a27cd0 | |
Daniel Gultsch | 4a6df90f0c | |
Daniel Gultsch | fdaab1c27e | |
Daniel Gultsch | f8c59a7b75 | |
Daniel Gultsch | f182fe6697 | |
Daniel Gultsch | daf1bbfca5 | |
Daniel Gultsch | b8eec6ae5b | |
Daniel Gultsch | 3ede2d00bd | |
Daniel Gultsch | d2a387e82f | |
Daniel Gultsch | da14f83a42 | |
Daniel Gultsch | 586fff5485 | |
Daniel Gultsch | ea9b73c1fe | |
Daniel Gultsch | e791e19265 | |
Daniel Gultsch | 3de8147b41 | |
Daniel Gultsch | b9ceb67104 | |
Daniel Gultsch | 90a0d36362 | |
Daniel Gultsch | bd4d939a29 | |
Daniel Gultsch | 64a6edd3fb | |
Daniel Gultsch | 75c20a7a2b | |
Daniel Gultsch | d5994a8d65 | |
Daniel Gultsch | 572b9c2dc6 | |
Daniel Gultsch | f9f994c540 | |
Daniel Gultsch | ba9596b37d | |
Daniel Gultsch | b01bca74fd | |
Daniel Gultsch | bfc8668803 | |
Alexei Sorokin | 951d84f404 | |
Ashique Bava | 231d97ea81 | |
Daniel Gultsch | 73000962fe | |
Daniel Gultsch | 3075833ab3 | |
Geno | eba5dd8654 | |
Geno | abe3718353 | |
Daniel Gultsch | 3f315751a1 | |
Daniel Gultsch | 68d8e2b9cf | |
Daniel Gultsch | c195e8b3d2 | |
Daniel Gultsch | 25f137441b | |
Daniel Gultsch | d436c5f856 | |
Daniel Gultsch | 8d9c51d755 | |
Daniel Gultsch | 2957bccb33 | |
Daniel Gultsch | 3135550b83 | |
Millesimus | 4d36231fa5 | |
Millesimus | dfeeaff74c | |
Daniel Gultsch | 5a9777f7f1 | |
Daniel Gultsch | 63f5f8c89d | |
Millesimus | ca08c27eef | |
Millesimus | 4040d5f647 | |
Millesimus | 8d45cc5827 | |
Daniel Gultsch | 96f0a09a5d | |
Maximilian Weiler | 38a77dbba6 | |
Daniel Gultsch | 8b817b3bd8 | |
Alexei Sorokin | 754773be55 | |
Alexei Sorokin | 4f362aafac | |
Daniel Gultsch | ea0dc558cb | |
Daniel Gultsch | 80d8b6dd88 | |
Daniel Gultsch | 2819545a43 | |
Daniel Gultsch | 9526456d75 | |
Daniel Gultsch | f975b5ddac | |
Daniel Gultsch | 581eb511b9 | |
Daniel Gultsch | af42e34654 | |
Daniel Gultsch | 0495470ca8 | |
Daniel Gultsch | 6c88a4b4fa | |
Daniel Gultsch | 88d7ddf124 | |
Daniel Gultsch | e6d8bee035 | |
Daniel Gultsch | 208c9d91db | |
Licaon_Kter | bf3c1d573b | |
Daniel Gultsch | 4e90c0dbbb | |
Daniel Gultsch | caefec2fbf | |
Daniel Gultsch | 339ee8f6ea | |
Daniel Gultsch | b00b8996d5 | |
Maximilian Weiler | 06fbb06aee | |
Maximilian Weiler | ef8f10cc13 | |
Millesimus | b6fe1898e7 | |
Millesimus | 955a6f3fe1 | |
Millesimus | a0529a4e1e | |
Millesimus | 2db2ca95ce | |
Millesimus | a0bca08997 | |
Millesimus | 748443cd4e | |
Millesimus | 3921f3a940 | |
Millesimus | c81c8a62b3 | |
Millesimus | e850900b40 | |
Millesimus | 74d60d0131 | |
Millesimus | 65a72827bc | |
Millesimus | 309082a9b3 | |
Licaon_Kter | e528b9f5df | |
Daniel Gultsch | 1e1dad780b | |
Daniel Gultsch | 0e54cde4bf | |
Alexei Sorokin | b99f9d4f1c | |
Daniel Gultsch | 7466d12505 | |
Daniel Gultsch | 98ffadd87d | |
Daniel Gultsch | af33a57bf2 | |
Daniel Gultsch | 87f99d3570 | |
Daniel Gultsch | b025265f91 | |
Daniel Gultsch | 0f3181555a | |
Daniel Gultsch | 76fb0180d6 | |
Daniel Gultsch | e02aaed7d2 | |
Daniel Gultsch | c9f1bdc551 | |
Daniel Gultsch | 2b9862adea | |
Daniel Gultsch | d91cd3e9e8 | |
Geno | e21d49efc8 | |
Daniel Gultsch | 56535e07ff | |
Dheeraj Chintaluri | 60c5906fe9 | |
Daniel Gultsch | 67e5f839f1 | |
Daniel Gultsch | 89012b0f8b | |
Daniel Gultsch | 7476dccc0e | |
Daniel Gultsch | 9182a300c5 | |
Daniel Gultsch | faa4c87b5f | |
Daniel Gultsch | 8d391753d7 | |
Daniel Gultsch | 337aa4a110 | |
Daniel Gultsch | ddf597e0d3 | |
Daniel Gultsch | 9c16af25fb | |
Daniel Gultsch | e2324209ed | |
Daniel Gultsch | 9544b994dc | |
Daniel Gultsch | 3b25fb9038 | |
Daniel Gultsch | 48156dd27f | |
Daniel Gultsch | 905489e237 | |
Daniel Gultsch | a5ad2b7fc6 | |
Daniel Gultsch | 5d3ad6e36b | |
Daniel Gultsch | 6d91551f59 | |
Daniel Gultsch | 0717f9ba18 | |
Daniel Gultsch | ac7855a332 | |
Daniel Gultsch | a40b82b85b | |
Daniel Gultsch | c5e90199c3 | |
Daniel Gultsch | 53908dd56e | |
Daniel Gultsch | 9d9514a091 | |
Daniel Gultsch | bc58fb0fbd | |
Daniel Gultsch | ec061bedc1 | |
Geno | a7f4abbab5 | |
Daniel Gultsch | f9b292fd6a | |
Daniel Gultsch | 8aed588405 | |
Daniel Gultsch | ea2acc2963 | |
Daniel Gultsch | 2760f07307 | |
Daniel Gultsch | ec22a39538 | |
Daniel Gultsch | 331fd30699 | |
Daniel Gultsch | c469b2dc22 | |
Daniel Gultsch | 202bde46ed | |
Daniel Gultsch | 37ce311764 | |
Daniel Gultsch | 9fc04c4b1e | |
Daniel Gultsch | 5f020af2cc | |
Daniel Gultsch | 55b2f2656d | |
Daniel Gultsch | fb681dfd60 | |
Daniel Gultsch | 5e59f20685 | |
Daniel Gultsch | 0fc191d004 | |
Daniel Gultsch | 30c9e7399e | |
Geno | 35e6c476dd | |
Daniel Gultsch | f632c7bbc9 | |
Daniel Gultsch | 08f27ddcf8 | |
Daniel Gultsch | 1822a71c2a | |
Daniel Gultsch | 77f448692c | |
Daniel Gultsch | 9cc95d4cc2 | |
Daniel Gultsch | ff756647a9 | |
Daniel Gultsch | 9a7fc3d9b8 | |
Daniel Gultsch | d37140ebf0 | |
Daniel Gultsch | d288f5bff2 | |
Daniel Gultsch | aad34783ad | |
Daniel Gultsch | 914ea9c398 | |
Daniel Gultsch | 02b16063c6 | |
Daniel Gultsch | 45c5f9aa90 | |
Daniel Gultsch | 4ac64f3a3b | |
Daniel Gultsch | 8b90c1c498 | |
Daniel Gultsch | 70fc08314f | |
Daniel Gultsch | ce7f59a76c | |
Daniel Gultsch | 1cd95aefa6 | |
Daniel Gultsch | 739d20428a | |
Daniel Gultsch | 6ee2807027 | |
Daniel Gultsch | a6244d986a | |
Daniel Gultsch | 8ac97b0027 | |
Daniel Gultsch | 7a115cb967 | |
Daniel Gultsch | d1195d21ae | |
Daniel Gultsch | 72828c6c4e | |
Daniel Gultsch | 38ef69a926 | |
Daniel Gultsch | aaac8296b3 | |
Daniel Gultsch | e217551a82 | |
Daniel Gultsch | b09a1432a3 | |
Geno | f161a9c4bf | |
Geno | f8e69f9fc2 | |
Daniel Gultsch | 6f1b71970d | |
Daniel Gultsch | 3baacf8862 | |
Daniel Gultsch | 9c2da0a1b8 | |
Daniel Gultsch | 2681ad82e1 | |
Daniel Gultsch | 8764d11cce | |
Daniel Gultsch | 3c60de54cb | |
Daniel Gultsch | d30a08266a | |
Daniel Gultsch | 859f3b2a1d | |
Daniel Gultsch | bf25b24967 | |
Daniel Gultsch | 7c53dcc4f4 | |
Daniel Gultsch | bf9d1a5759 | |
Daniel Gultsch | ddb54bb222 | |
Daniel Gultsch | 813b07e18d | |
Daniel Gultsch | 0fa06d65b5 | |
Daniel Gultsch | e947a3f808 | |
Daniel Gultsch | b34f6e0720 | |
Daniel Gultsch | b8c61b795e | |
Daniel Gultsch | cf68c544aa | |
Christopher Vollick | ef24d2050b | |
Daniel Gultsch | 4a175f915d | |
Daniel Gultsch | 5848013a1e | |
Daniel Gultsch | c5f801c1fe | |
Daniel Gultsch | d52c46d582 | |
Daniel Gultsch | e81fb1b24e | |
Daniel Gultsch | 3ee70b1d48 | |
Daniel Gultsch | e4b2bb4a42 | |
Daniel Gultsch | 8a6430ae29 | |
Geno | a213b00091 | |
Geno | 64e88d946f | |
Daniel Gultsch | 47a904b4fc | |
Daniel Gultsch | 33e73a2b47 | |
Daniel Gultsch | d889c02a0a | |
Daniel Gultsch | 073b6a998a | |
Daniel Gultsch | 9450d49b0b | |
Daniel Gultsch | 5e0c158cde | |
Daniel Gultsch | 16b1c561d4 | |
Daniel Gultsch | 24f2f52512 | |
Daniel Gultsch | e98ec40b7f | |
Daniel Gultsch | f92ea5c70b | |
Daniel Gultsch | 81505c6202 | |
Daniel Gultsch | 638f30b902 | |
Daniel Gultsch | 0812bae1ab | |
Daniel Gultsch | 6bfe16f044 | |
Daniel Gultsch | 53da64b7e2 | |
Daniel Gultsch | ebb38d7d75 | |
Daniel Gultsch | 484f633180 | |
Daniel Gultsch | 78c89664c4 | |
Daniel Gultsch | 90270069da | |
Daniel Gultsch | 49992f300b | |
Daniel Gultsch | 72e268e6b1 | |
Daniel Gultsch | 78901e3339 | |
Daniel Gultsch | 149224a073 | |
Daniel Gultsch | db447f845e | |
Daniel Gultsch | 6cab0ad496 | |
Daniel Gultsch | 9f869d3895 | |
Daniel Gultsch | b808a03702 | |
Daniel Gultsch | 7330d8a7f0 | |
Daniel Gultsch | 6e3dc0eef6 | |
Geno | 696f791dca | |
Geno | e101bd8ba2 | |
Daniel Gultsch | 3847ab8465 | |
Daniel Gultsch | deee31e517 | |
mimi89999 | ab17f935c3 | |
mimi89999 | d51b4380d7 | |
Daniel Gultsch | b6d62c13ef | |
Daniel Gultsch | b76b60df5c | |
Daniel Gultsch | f82ae0a9b8 | |
Daniel Gultsch | 358c70828f | |
maxim432 | 156c4da2b3 | |
Daniel Gultsch | ca496fd39f | |
Daniel Gultsch | 53a038d90e | |
Daniel Gultsch | d77d89b356 | |
Daniel Gultsch | 2155a50875 | |
Daniel Gultsch | 4a9dfb9567 | |
Daniel Gultsch | 10382e83bf | |
Daniel Gultsch | c11ac40df4 | |
Geno | 3c8a5d138a | |
Daniel Gultsch | aee37c3e3e | |
Daniel Gultsch | 0a2c753620 | |
Daniel Gultsch | d907d590d9 | |
Daniel Gultsch | 8e57a7622c | |
Daniel Gultsch | 8abf861303 | |
Daniel Gultsch | 247998ff81 | |
Daniel Gultsch | 1068f16473 | |
Daniel Gultsch | 15a33adaae | |
Daniel Gultsch | 619af9c6c5 | |
Daniel Gultsch | bc97d0b0bb | |
Daniel Gultsch | 9c9a953281 | |
Daniel Gultsch | 6a89a472e1 | |
Daniel Gultsch | 8ce7bfb95e | |
Daniel Gultsch | 582aee4718 | |
Daniel Gultsch | 3b43cb0bda | |
Daniel Gultsch | e711b3d294 | |
Daniel Gultsch | e087b594ff | |
Daniel Gultsch | b37f25335c | |
Daniel Gultsch | 9c087b9dd4 | |
Molly Miller | ebbf1ff6b1 | |
Daniel Gultsch | 20d0206859 | |
Daniel Gultsch | 9db0808306 | |
Daniel Gultsch | eea484af01 | |
Daniel Gultsch | 47d619b28e | |
Daniel Gultsch | 60b23882fd | |
Daniel Gultsch | 47adf646c6 | |
Daniel Gultsch | 26a4598f3c | |
Daniel Gultsch | 624bb565a8 | |
Daniel Gultsch | 87e9b8037e | |
Daniel Gultsch | 49d0558da1 | |
Daniel Gultsch | 6e5240fe2e | |
Daniel Gultsch | 260b203ea3 | |
Daniel Gultsch | 864b0b3b3d | |
Daniel Gultsch | 91cc8f5011 | |
Ferdinand Pöll | 453ca7c0ed | |
Daniel Gultsch | 5fd0700daa | |
Daniel Gultsch | 55fd0b8504 | |
Geno | d2cd482a07 | |
Daniel Gultsch | bfccfba00e | |
Daniel Gultsch | 5b48b4027e | |
Daniel Gultsch | 41c045d779 | |
Daniel Gultsch | 07cc5c13ca | |
Daniel Gultsch | b0584137b4 | |
Daniel Gultsch | d0a2f1f45f | |
Daniel Gultsch | 372ddbfb49 | |
Emmanuel Gil Peyrot | 17c697eed9 | |
Daniel Gultsch | 69dca53bf3 | |
Daniel Gultsch | 6c2f0d29d8 | |
Daniel Gultsch | 2bec5459c5 | |
Daniel Gultsch | 8eb685a7eb | |
Daniel Gultsch | 6d13ee52f0 | |
Daniel Gultsch | adb5a2b2c2 | |
Daniel Gultsch | 0569febf67 | |
Daniel Gultsch | 0e54d8a2cf | |
Daniel Gultsch | 2a57c92f63 | |
Daniel Gultsch | 692ee6c9fb | |
Geno | 1257ad8509 | |
Geno | 1a0b4b441d | |
Daniel Gultsch | f23016c967 | |
Daniel Gultsch | b4db2e5284 | |
Daniel Gultsch | 39229c34f6 | |
Daniel Gultsch | 090b3b18d0 | |
Daniel Gultsch | d1490673bb | |
Daniel Gultsch | e38aa30a84 | |
Daniel Gultsch | 00bc7a4b06 | |
Daniel Gultsch | f584179f2f | |
Daniel Gultsch | 07e965f8f3 | |
Daniel Gultsch | 9c67e8fec2 | |
Daniel Gultsch | 849968107e | |
Daniel Gultsch | 7179d72f7e | |
Daniel Gultsch | 261207a4c0 | |
Daniel Gultsch | 303e205276 | |
Daniel Gultsch | 99cb23fe14 | |
Daniel Gultsch | 528f192f76 | |
Daniel Gultsch | 778cfa846b | |
Daniel Gultsch | 00e1a93014 | |
Daniel Gultsch | 1f392a688d | |
Daniel Gultsch | 92083fec83 | |
Daniel Gultsch | 35316ad93a | |
Daniel Gultsch | 3c7ac2524f | |
Daniel Gultsch | 600f243797 | |
Daniel Gultsch | 36f5f77c30 | |
Daniel Gultsch | c7ec6a9dae | |
eta | 0c563134da | |
Daniel Gultsch | fc53271212 | |
Daniel Gultsch | 6485c77e09 | |
Daniel Gultsch | 1fafe4287d | |
Daniel Gultsch | 16c4e3eec7 | |
Daniel Gultsch | afb2fb1326 | |
Daniel Gultsch | 952387cb5a | |
Christoph Scholz | 386b224123 | |
Alexei Sorokin | 501cdd5edf | |
Daniel Gultsch | b327548c85 | |
Daniel Gultsch | aaebb3a536 | |
Daniel Gultsch | 5ad054617b | |
Daniel Gultsch | ff13cc2766 | |
Daniel Gultsch | dc72bc5bc3 | |
nico | fdfac102e2 | |
eta | 364502d1a3 | |
eta | b4805ac2c5 | |
genofire | 571cb5dd44 | |
genofire | 06b2043b24 | |
Daniel Gultsch | afffe01868 | |
Daniel Gultsch | 0b4d12782b | |
Daniel Gultsch | ce1b707837 | |
Daniel Gultsch | 7fb617e39a | |
Daniel Gultsch | 9db0c85cda | |
Daniel Gultsch | 27c89e487a | |
Daniel Gultsch | 73dac680e5 | |
Daniel Gultsch | 23ed0ce2ad | |
Daniel Gultsch | aa792a3af6 | |
Daniel Gultsch | 8d64e101c9 | |
Daniel Gultsch | 3281a93dc3 | |
Daniel Gultsch | 81985ca7d7 | |
Daniel Gultsch | f76ef17494 | |
Daniel Gultsch | 4b12033bd3 | |
Daniel Gultsch | ce81123112 | |
Daniel Gultsch | 2de8f3d35b | |
Daniel Gultsch | 97fe9fa01f | |
Daniel Gultsch | 6590dc922f | |
Daniel Gultsch | c48499253b | |
Daniel Gultsch | 3c0773c6e7 | |
Daniel Gultsch | 064264c20b | |
Daniel Gultsch | 3dcb36a417 | |
Daniel Gultsch | 35af8894d2 | |
genofire | 2cd0993534 | |
genofire | 35e064949d | |
genofire | 8f5e3978e4 | |
genofire | 08449e34ec | |
Daniel Gultsch | d158eeaf72 | |
Daniel Gultsch | 91e94db747 | |
Daniel Gultsch | 15b323ee69 | |
Daniel Gultsch | f3362ebde5 | |
Daniel Gultsch | 70c10fd0de | |
Daniel Gultsch | 1958cded23 | |
Daniel Gultsch | 7d2a7d536d | |
genofire | ef7cbbadca | |
genofire | c9c37dfb04 | |
Daniel Gultsch | 59d7bb63e9 | |
Daniel Gultsch | 129f43a349 | |
Daniel Gultsch | 637c0cb15a | |
Daniel Gultsch | 1ae7d6be16 | |
Daniel Gultsch | f22e33e3ea | |
Daniel Gultsch | 47e3504a02 | |
Daniel Gultsch | 5ecd250565 | |
Daniel Gultsch | f5f9075da2 | |
Daniel Gultsch | e10b182d6b | |
Daniel Gultsch | 9cd4e1d581 | |
Daniel Gultsch | 6941d5edd1 | |
Daniel Gultsch | 1c66772202 | |
Daniel Gultsch | 9bec186292 | |
Daniel Gultsch | 8b26c60f00 | |
Daniel Gultsch | 16300727d1 | |
Daniel Gultsch | 28856aaf9f | |
Daniel Gultsch | 32d55346cc | |
genofire | 1b28ea9dda | |
Daniel Gultsch | 994fd9ecad | |
Daniel Gultsch | cb9623703d | |
Daniel Gultsch | fd68bfb8ca | |
Daniel Gultsch | 9e6f7237af | |
Daniel Gultsch | 7aeb2b2740 | |
Daniel Gultsch | 590deef8e9 | |
Daniel Gultsch | c9e6653e33 | |
Marcin Mielniczuk | e7e04837b6 | |
Daniel Gultsch | aa47e53584 | |
Daniel Gultsch | c3fa1d5d30 | |
Daniel Gultsch | fffa659881 | |
Daniel Gultsch | bab9dd4893 | |
Daniel Gultsch | 7ff56a5087 | |
Daniel Gultsch | bf85a55930 | |
Daniel Gultsch | 1107529f56 | |
Daniel Gultsch | 6a6c9fb3bf | |
Daniel Gultsch | 9ab0fbe48c | |
Daniel Gultsch | 71a56002fe | |
genofire | 1865177d74 | |
genofire | 0bca11bdeb | |
Martin | 14bb8b0cf1 | |
Daniel Gultsch | 8f439a9c37 | |
Daniel Gultsch | 2881a1b946 | |
Daniel Gultsch | 13d8eb1c7e | |
Daniel Gultsch | fada3a63c9 | |
Daniel Gultsch | a5430d5ce1 | |
Daniel Gultsch | 57135e1a59 | |
Daniel Gultsch | 15489547b7 | |
Daniel Gultsch | 68960398b2 | |
Andrey Tikhomirov | 203e248a14 | |
genofire | c57d5375e0 | |
Daniel Gultsch | d88f79e436 | |
Daniel Gultsch | dddb7ece25 | |
Daniel Gultsch | 169ee99afa | |
Daniel Gultsch | fe68aff23c | |
Daniel Gultsch | 7bcb29c482 | |
Daniel Gultsch | 47804205b6 | |
Dmitry Markin | 4493f6cc13 | |
Daniel Gultsch | 8356a1cfe1 | |
Daniel Gultsch | 8534175057 | |
Daniel Gultsch | 9649ba16b5 | |
Daniel Gultsch | 23c4a26404 | |
Daniel Gultsch | c8f23aef4e | |
Daniel Gultsch | 98e1044bdd | |
Daniel Gultsch | d823cefe47 | |
Daniel Gultsch | 38b2764c81 | |
Daniel Gultsch | 20286ea8d2 | |
Daniel Gultsch | 1f77d5e115 | |
Daniel Gultsch | 61aac78af0 | |
Daniel Gultsch | 16bc210211 | |
Daniel Gultsch | c3b9a4dabc | |
Daniel Gultsch | ccdc91a497 | |
Daniel Gultsch | 400c8461fc | |
Daniel Gultsch | fda9e7b51c | |
Daniel Gultsch | 0dba9f560c | |
Daniel Gultsch | 56ea9647cd | |
Daniel Gultsch | 971bb60f42 | |
Daniel Gultsch | 8059aa7b0d | |
Daniel Gultsch | 01bfb5fd56 | |
Daniel Gultsch | 0ba4892d3e | |
Daniel Gultsch | b7f3b4333e | |
Daniel Gultsch | 644ad99520 | |
Daniel Gultsch | adb3c77d31 | |
Daniel Gultsch | 2cd0cc50d0 | |
Daniel Gultsch | f39daf565a | |
Daniel Gultsch | 552e17e39a | |
Daniel Gultsch | 7e2d87f39c | |
Daniel Gultsch | 1853242c66 | |
Daniel Gultsch | b78d45c7cc | |
genofire | c44b948228 | |
Daniel Gultsch | c029382410 | |
Licaon_Kter | f879d87f04 | |
Daniel Gultsch | 4bc43af690 | |
Daniel Gultsch | 0391e78832 | |
Daniel Gultsch | 3343d2665a | |
Daniel Gultsch | 61f6ce317b | |
Daniel Gultsch | 637c208f55 | |
Daniel Gultsch | 8edfc61346 | |
Daniel Gultsch | 8603d24bcb | |
Daniel Gultsch | bc6446beb8 | |
Licaon_Kter | ecb9039547 | |
Daniel Gultsch | 59d1a2982e | |
Daniel Gultsch | 63ba21a512 | |
Daniel Gultsch | 5e3aab3abe | |
Daniel Gultsch | 575ada3b27 | |
genofire | 09c7d8298d | |
Daniel Gultsch | 8f7ff2c3dd | |
Daniel Gultsch | dc53976aec | |
Daniel Gultsch | cdcc34ff91 | |
Daniel Gultsch | 1c625e55a0 | |
Daniel Gultsch | 8475a28dc5 | |
Daniel Gultsch | 7ca543e42f | |
Daniel Gultsch | 88cc097732 | |
Daniel Gultsch | ed4d7bff92 | |
Daniel Gultsch | 550fbc6d2c | |
Daniel Gultsch | 685e01e83f | |
genofire | 2731b7b690 | |
genofire | c3f392445f | |
Daniel Gultsch | a2a7256682 | |
Daniel Gultsch | de941f6036 | |
Daniel Gultsch | 574bccfc59 | |
Daniel Gultsch | aa1e69d277 | |
Daniel Gultsch | 304411fc09 | |
Daniel Gultsch | bfeebc141f | |
Daniel Gultsch | dd0f354b62 | |
Licaon_Kter | 24fb42c5f4 | |
Daniel Gultsch | f8fedf0059 | |
Daniel Gultsch | d17f4acd3e | |
Daniel Gultsch | 4e886ebbcc | |
Daniel Gultsch | fa752b596d | |
Daniel Gultsch | 89c022f0cb | |
Daniel Gultsch | 22f3aac465 | |
Daniel Gultsch | 3ca10b8fa9 | |
Daniel Gultsch | df3273a6fc | |
Daniel Gultsch | a0920b83e2 | |
Daniel Gultsch | b347d57848 | |
Daniel Gultsch | 351790b0c3 | |
Daniel Gultsch | 7abd37498e | |
Daniel Gultsch | 1da490f77a | |
Daniel Gultsch | 4dd3b0c2aa | |
Daniel Gultsch | 7a21b2c5ed | |
Daniel Gultsch | 0aee863123 | |
Daniel Gultsch | 2195bce303 | |
Daniel Gultsch | 78a82a74bc | |
Daniel Gultsch | dc29cf27a3 | |
Daniel Gultsch | 198a7db954 | |
Daniel Gultsch | ef7d4fca86 | |
Daniel Gultsch | b6703dbe38 | |
Daniel Gultsch | 3510f10e25 | |
genofire | dfee543df0 | |
genofire | fca5e15aad | |
Daniel Gultsch | 1b4f9cc8ab | |
Daniel Gultsch | 36d2ecfcfa | |
Licaon_Kter | 7c4566e561 | |
Daniel Gultsch | 2c4788b7c7 | |
Daniel Gultsch | b845c601d0 | |
Daniel Gultsch | 90526efbd4 | |
Daniel Gultsch | 11de70312c | |
Daniel Gultsch | 907b4d2b8a | |
Daniel Gultsch | 46579550e4 | |
Daniel Gultsch | 4d3d3a7038 | |
Daniel Gultsch | 2c5bed61a1 | |
Daniel Gultsch | 9b8b4f1791 | |
Daniel Gultsch | 526e9eab61 | |
Daniel Gultsch | f4247379bd | |
Daniel Gultsch | 1d9b9e3bf0 | |
Daniel Gultsch | 04764eb989 | |
Daniel Gultsch | 92fc22b313 | |
Daniel Gultsch | 6daaca496b | |
Daniel Gultsch | 072edc5a62 | |
Daniel Gultsch | bd0234ba4d | |
Daniel Gultsch | abfa4eae08 | |
Daniel Gultsch | 285c750e69 | |
Daniel Gultsch | 350fc57d87 | |
Daniel Gultsch | 5af4c865a7 | |
Daniel Gultsch | 1ece8e077e | |
Daniel Gultsch | 1b237e4ea0 | |
genofire | 99bb2b4698 | |
genofire | 34241828ab | |
genofire | 99a5c71b0b | |
Daniel Gultsch | 42563e6c29 | |
Daniel Gultsch | 5d28ae9f38 | |
Daniel Gultsch | fb57ef47bc | |
Daniel Gultsch | c159bbfc81 | |
Daniel Gultsch | 2018ae8ba0 | |
Daniel Gultsch | 8a1bdd97e8 | |
Daniel Gultsch | a3b3b14bf1 | |
Daniel Gultsch | 8fb8656e34 | |
Licaon_Kter | dcb02ee5e2 | |
Daniel Gultsch | b6d38f8e8b | |
Daniel Gultsch | 476fb23656 | |
Daniel Gultsch | 3c3f5d8e6f | |
Daniel Gultsch | 6888f57191 | |
Daniel Gultsch | cacd3b8ed8 | |
Daniel Gultsch | 0ee9dbcea7 | |
Daniel Gultsch | 3577afea4e | |
Daniel Gultsch | e70b6eec98 | |
Daniel Gultsch | 5a5f887229 | |
Licaon_Kter | 4f8715a349 | |
Daniel Gultsch | abb33b048a | |
Daniel Gultsch | 63ddd97b6b | |
Allan Nordhøy | f739752f76 | |
Daniel Gultsch | e4b906ebeb | |
Daniel Gultsch | 48163a5604 | |
Daniel Gultsch | f7a0d2031a | |
Daniel Gultsch | 58429c42ee | |
Daniel Gultsch | 7ac5e8e828 | |
genofire | 21da82885e | |
Daniel Gultsch | f8866d1bef | |
Daniel Gultsch | 5aa42cda6c | |
Daniel Gultsch | eab4ac017f | |
Daniel Gultsch | 86b2631449 | |
Daniel Gultsch | ea1c2f27d1 | |
Daniel Gultsch | b6d3b49702 | |
Daniel Gultsch | 00229d7d6d | |
Daniel Gultsch | 419d2c91bc | |
Licaon_Kter | eea0f8579e | |
Daniel Gultsch | 8374df84aa | |
Daniel Gultsch | f106cbccf5 | |
Daniel Gultsch | deae2b109f | |
Daniel Gultsch | 8a586527c4 | |
Daniel Gultsch | 52d416c6e6 | |
Daniel Gultsch | a49d69c878 | |
Daniel Gultsch | 54ca3fb020 | |
Daniel Gultsch | 333f509e53 | |
Daniel Gultsch | 0d4b175760 | |
Daniel Gultsch | daf234191b | |
Daniel Gultsch | f93bac6d73 | |
Daniel Gultsch | faf1ff365d | |
Daniel Gultsch | 8183c54ba0 | |
Daniel Gultsch | 27bf871472 | |
Daniel Gultsch | 418cecad11 | |
Daniel Gultsch | fc4397e5b9 | |
Daniel Gultsch | 07911b2094 | |
Daniel Gultsch | 9fbf73d1ea | |
Daniel Gultsch | 006d7447a3 | |
Daniel Gultsch | c41033e83c | |
genofire | 749ff88ed0 | |
Daniel Gultsch | 45bb86c0f6 | |
Daniel Gultsch | a5beaaed9d | |
Daniel Gultsch | 07ba70aef7 | |
Daniel Gultsch | 32ab7775d7 | |
Daniel Gultsch | 99d2b6a268 | |
Daniel Gultsch | cacd85b4f1 | |
Daniel Gultsch | 4f5415ecba | |
Daniel Gultsch | c0036b4ca6 | |
genofire | c52121e6dc | |
Daniel Gultsch | 02a74b10a1 | |
Daniel Gultsch | 96f6ae2b49 | |
Daniel Gultsch | 80cac3bd69 | |
Daniel Gultsch | adad683b20 | |
Daniel Gultsch | c88d736cee | |
Daniel Gultsch | d7a8519ad6 | |
genofire | dfa22954e5 | |
Daniel Gultsch | cfb9368edb | |
Daniel Gultsch | 60cea03dce | |
Daniel Gultsch | a008993d06 | |
Daniel Gultsch | 22e93e4169 | |
Daniel Gultsch | fc7ecca1b3 | |
Daniel Gultsch | 892d913e2c | |
Daniel Gultsch | 9fa9ca9cbc | |
Daniel Gultsch | fa45422fa8 | |
Daniel Gultsch | 1fc98c0c11 | |
Daniel Gultsch | 9afac21b0b | |
Daniel Gultsch | 04a7b9da1c | |
Daniel Gultsch | 876b1149d5 | |
Daniel Gultsch | e0cb127005 | |
Daniel Gultsch | e5282b846f | |
Daniel Gultsch | 995856ffe0 | |
Daniel Gultsch | 62c50d0089 | |
Daniel Gultsch | 3c0b3f4b94 | |
Daniel Gultsch | 442b952700 | |
Daniel Gultsch | 5b12e23382 | |
Daniel Gultsch | eb911b8196 | |
Daniel Gultsch | d5e3d13158 | |
Daniel Gultsch | 8b79808f02 | |
Daniel Gultsch | 7898ba65cd | |
Daniel Gultsch | f858412d72 | |
Daniel Gultsch | 23d1ee5e41 | |
Daniel Gultsch | 187dff3df9 | |
Daniel Gultsch | df2ef0eeb0 | |
Daniel Gultsch | e661d5b7ad | |
Daniel Gultsch | 1016e8d018 | |
Daniel Gultsch | 1cc0dfad84 | |
Daniel Gultsch | c64779329b | |
Daniel Gultsch | 7f45f3ab54 | |
Daniel Gultsch | 5a0979b41e | |
Daniel Gultsch | f7f0dc99a7 | |
Daniel Gultsch | c7269bc0aa | |
Daniel Gultsch | 31dfb0c704 | |
Daniel Gultsch | 72c551d128 | |
Daniel Gultsch | a12760300c | |
Daniel Gultsch | c20c40a807 | |
Daniel Gultsch | 7dfd47a5c4 | |
Daniel Gultsch | 934b98d199 | |
Daniel Gultsch | ebda472c22 | |
Daniel Gultsch | 48f752366b | |
Daniel Gultsch | 644e5aa856 | |
Daniel Gultsch | 16d34c2ba0 | |
Daniel Gultsch | ab2681640a | |
Daniel Gultsch | 2f437ea845 | |
Daniel Gultsch | fa3ef07580 | |
Daniel Gultsch | 0a18ab35c0 | |
Daniel Gultsch | 8472712b3e | |
Daniel Gultsch | e545e95d39 | |
Daniel Gultsch | ea2ed85ed7 | |
Daniel Gultsch | 21e412ef6f | |
Daniel Gultsch | 0c4f0c074d | |
Daniel Gultsch | 4558b9a7b0 | |
Daniel Gultsch | 45d5d1f635 | |
Daniel Gultsch | b95d406e61 | |
Daniel Gultsch | ec6bcec849 | |
Daniel Gultsch | 36e117979a | |
Daniel Gultsch | d7e93e18e5 | |
Daniel Gultsch | f995965dea | |
Daniel Gultsch | 01a9a52990 | |
Daniel Gultsch | 445009c558 | |
Daniel Gultsch | 5a20faaf0f | |
Daniel Gultsch | d4788fc1f4 | |
Daniel Gultsch | b4df19177f | |
Daniel Gultsch | 17d9b02f41 | |
Daniel Gultsch | d057ae3439 | |
Daniel Gultsch | 8c273e7eee | |
Daniel Gultsch | 1489dba44f | |
Daniel Gultsch | b20b00e77f | |
Daniel Gultsch | 339bdaea06 | |
Daniel Gultsch | bfb9a6267a | |
Daniel Gultsch | dd42a6b850 | |
Daniel Gultsch | 65b43661dd | |
Daniel Gultsch | 172d2c693f | |
Daniel Gultsch | e16e0d895e | |
Daniel Gultsch | 493ca68464 | |
Daniel Gultsch | ef22071bd1 | |
Daniel Gultsch | 9bc264bd73 | |
Daniel Gultsch | 981aeaf264 | |
Daniel Gultsch | b924a63d01 | |
Daniel Gultsch | 5b98107e9a | |
Daniel Gultsch | 9a41d11aed | |
Daniel Gultsch | 4be2309202 | |
Daniel Gultsch | 3439f40411 | |
Daniel Gultsch | 1dc88f38ca | |
Daniel Gultsch | 82f9a77777 | |
Daniel Gultsch | deaa76b5ca | |
Daniel Gultsch | 609120c0d8 | |
Daniel Gultsch | c9f7e174f7 | |
Daniel Gultsch | c6db651322 | |
Daniel Gultsch | 5eea961155 | |
Daniel Gultsch | 7b382d2ba5 | |
Daniel Gultsch | 07e671d7c3 | |
Daniel Gultsch | 9d83981f2c | |
Daniel Gultsch | d19b5e0634 | |
Daniel Gultsch | 2e8b91665b | |
Daniel Gultsch | 14d008d89d | |
Daniel Gultsch | 0302eacac1 | |
Daniel Gultsch | f5c4de8770 | |
Daniel Gultsch | 2ba84bd32e | |
Daniel Gultsch | 6884e427ef | |
Daniel Gultsch | 0661c1bd37 | |
Daniel Gultsch | 39e3791345 | |
Daniel Gultsch | 6a1df0538e | |
Daniel Gultsch | 7749a7ce22 | |
Daniel Gultsch | 268eedad89 | |
Daniel Gultsch | 15a2491d7b | |
Daniel Gultsch | 845b3d8a0e | |
Daniel Gultsch | 3e5e4e813b | |
Daniel Gultsch | 0bf991d95c | |
Daniel Gultsch | ca9b95fc9c | |
Daniel Gultsch | 859bc0bef3 | |
Daniel Gultsch | 00f273b0c0 | |
Daniel Gultsch | f7d1e02d4b | |
Daniel Gultsch | 9edadc9835 | |
Daniel Gultsch | a11d506bf0 | |
Daniel Gultsch | 7909a72d43 | |
Daniel Gultsch | e2f1cec2e5 | |
Daniel Gultsch | ccfc55e9b6 | |
Daniel Gultsch | 4c6ee9693a | |
Daniel Gultsch | 0e88b56eb4 | |
Daniel Gultsch | a9a35fb74b | |
Daniel Gultsch | f8c0328416 | |
Daniel Gultsch | 22c755c5ce | |
Daniel Gultsch | 9dfa9df790 | |
Daniel Gultsch | ac9a1a773e | |
Daniel Gultsch | 885ec0febe | |
Daniel Gultsch | f264ef9f8b | |
Daniel Gultsch | b1c0e93b34 | |
Daniel Gultsch | 2591a96945 | |
Daniel Gultsch | 4d70855b4c | |
Daniel Gultsch | b44a3aeac6 | |
Daniel Gultsch | ef51ec2c1d | |
Daniel Gultsch | 28ead10ca4 | |
Daniel Gultsch | 18059345c8 | |
Daniel Gultsch | 5b1d86d67e | |
Daniel Gultsch | 3b857e6894 | |
Daniel Gultsch | e2e4390d51 | |
Daniel Gultsch | 766d1d603e | |
Daniel Gultsch | 4e13893662 | |
Daniel Gultsch | 43cf1783a4 | |
Daniel Gultsch | b2aa0e3352 | |
Daniel Gultsch | 5b15348f13 | |
Daniel Gultsch | 385692ea28 | |
Daniel Gultsch | a4acfb2a19 | |
Daniel Gultsch | f9650b95d8 | |
Daniel Gultsch | 963ddd11c2 | |
Daniel Gultsch | eb22bd0499 | |
Daniel Gultsch | 7538e387ec | |
Daniel Gultsch | 34f42c73bc | |
Daniel Gultsch | 23ebb6ae80 | |
Daniel Gultsch | 75f753e957 | |
Daniel Gultsch | b40a65652f | |
Daniel Gultsch | e964bb78ef | |
Daniel Gultsch | 1d62cb0024 | |
Daniel Gultsch | c5da699afe | |
Daniel Gultsch | 62934e6487 | |
Daniel Gultsch | ff18ea452d | |
Daniel Gultsch | 3d0138506d | |
Daniel Gultsch | 972e537ea1 | |
Daniel Gultsch | 7c13c8a4e5 | |
Daniel Gultsch | 4e33ebb308 | |
Daniel Gultsch | 3cf469a43b | |
Daniel Gultsch | e49ad3d573 | |
Daniel Gultsch | 0718c70f6b | |
Daniel Gultsch | 41ada3480c | |
genofire | 147a10a271 | |
genofire | 35b9745fc9 | |
Daniel Gultsch | 36de53cdec | |
Daniel Gultsch | 00191e2b60 | |
Daniel Gultsch | 257de4b51e | |
Daniel Gultsch | 7851174b77 | |
Daniel Gultsch | aecb771ab5 | |
Daniel Gultsch | 3be7c3bca2 | |
Daniel Gultsch | 788b0f7f2d | |
Daniel Gultsch | b2e9a954ab | |
Daniel Gultsch | 7b5d0e034e | |
Daniel Gultsch | 08bc3ca0d5 | |
genofire | d353372768 | |
genofire | fed1dfa141 | |
genofire | 944779ba78 | |
Daniel Gultsch | 0f40e7e73b | |
genofire | 5dd666257d | |
Daniel Gultsch | 17e8aa43fb | |
Daniel Gultsch | 12907a52e3 | |
Daniel Gultsch | d781bc9cb9 | |
genofire | c3bcaaa76b | |
genofire | b28b1dd154 | |
genofire | 89ecc47897 | |
genofire | 0ec4088626 | |
Daniel Gultsch | d73cb08ec6 | |
Daniel Gultsch | d6ae9d8d14 | |
Daniel Gultsch | 27ca031f93 | |
Daniel Gultsch | e4685ad47a | |
Daniel Gultsch | d37aeef182 | |
Daniel Gultsch | 9b55d90705 | |
Daniel Gultsch | d64bc1776b | |
Daniel Gultsch | c34d40ebff | |
Hugo Trentesaux | 62021aae59 | |
genofire | 80dd53c3f0 | |
genofire | e3b5be777c | |
Daniel Gultsch | a06eb10ed8 | |
Daniel Gultsch | fc2b27c3b4 | |
Daniel Gultsch | 2aee26c49a | |
Daniel Gultsch | 6acb15dd15 | |
genofire | 9247b8dc18 | |
genofire | 3e29c21f80 | |
genofire | 109d38e1b1 | |
genofire | a1ab687f6e | |
genofire | e54a2cc04e | |
genofire | 3df33228a8 | |
genofire | 5e0856ee69 | |
Licaon_Kter | a520e93b1b | |
James Lee | ba2cca08e9 | |
Daniel Gultsch | 69680134c9 | |
Daniel Gultsch | 18a90fde8c | |
Daniel Gultsch | 09dff6310d | |
Licaon_Kter | 37907e6d97 | |
genofire | 3cc75939bc | |
genofire | cf6323cc00 | |
genofire | ea2adcc4f5 | |
genofire | f80eac3a38 | |
genofire | 2077bf739b | |
genofire | 8e93f2423c | |
genofire | 7fa520e2fd | |
genofire | d4f7c2b34a | |
genofire | 76ad8f1389 | |
genofire | 8d996f390a | |
genofire | 50456e3cac | |
genofire | c437fb067b | |
genofire | 1c0c6a6fba | |
genofire | ec92294e41 | |
Martin/Geno | f33c486263 | |
Martin/Geno | 72be751568 | |
Martin/Geno | 9c5de8b13f | |
Martin/Geno | 875d71e9be | |
Martin/Geno | c3cb5f2838 | |
Martin/Geno | 82e244b96b | |
Martin/Geno | 4745ab65a1 | |
Martin/Geno | 68ee3d9994 | |
Martin/Geno | fa0452761f | |
Martin/Geno | 38c5ab7428 | |
Martin/Geno | 13b55fde20 | |
Martin/Geno | 88179fb66e | |
Martin/Geno | e304b6b152 | |
Martin/Geno | 30280289b8 | |
Martin/Geno | 936c5011f5 | |
Martin/Geno | 3d81b4ea9d | |
Martin/Geno | 0f4d8439f5 | |
Martin/Geno | c04494f42a | |
Martin/Geno | 6c8f57912e | |
Martin/Geno | b459a4c6e3 | |
Martin/Geno | 415a105b41 | |
Martin/Geno | b65e14072e | |
Martin/Geno | fe124e4789 | |
Martin/Geno | d0fd1f0e30 | |
Martin/Geno | 9a49c7c3c6 | |
Martin/Geno | 14d4e6aec8 | |
Martin/Geno | cc478f744b | |
Martin/Geno | 28c01aea8e | |
Martin/Geno | 7ac752fac3 | |
Martin/Geno | 66d4c49fd3 | |
Martin/Geno | 35b32a2f65 | |
Martin/Geno | 0754d6d01a | |
Martin/Geno | 9f3cbc28c4 | |
Martin/Geno | 69b92f264a | |
Martin/Geno | 27bc0ce08d | |
Martin/Geno | a8b433ed6a | |
Martin/Geno | a15756d4ff | |
Martin/Geno | 25c2ed38d8 | |
Martin/Geno | db8160e681 | |
Martin/Geno | e140ab713e | |
Martin/Geno | db12bae1a2 | |
Martin/Geno | 089f76f43c | |
Martin/Geno | 4e659b35d7 |
|
@ -1,11 +0,0 @@
|
|||
### Reporting Bugs and getting help
|
||||
|
||||
The issue tracker on Github is for bug reports only. It is not a general support forum.
|
||||
|
||||
**A bug is everything you can reproduce. ie *if I do this that happens but something else should happen instead*.**
|
||||
|
||||
Please search the issue tracker (including closed issues). Your bug might be a server bug that has already been addressed.
|
||||
|
||||
Please fill in the template when creating new issues and provide information about your device and your server. The [adb logcat](https://wiki.cyanogenmod.org/w/Doc:_debugging_with_logcat) can be omitted if you can reproduce the bug under every condition. (ie *click button X and the application crashes*) But the adb logcat is required if the bug happens only under certain conditions or involves network problem (Server not found, messages not arriving)
|
||||
|
||||
**If you are seeking help or are unable to reproduce the exact problem please join our MUC at conversations@conference.siacs.eu**
|
|
@ -1,3 +0,0 @@
|
|||
github: inputmice
|
||||
liberapay: inputmice
|
||||
custom: https://paypal.me/ConversationsIM
|
|
@ -1,35 +0,0 @@
|
|||
#### General information
|
||||
|
||||
* **Version:** 2.6.0
|
||||
* **Device:** Xiaomi Mi A1
|
||||
* **Android Version:** Android 9 (stock)
|
||||
* **Server name:** conversations.im, jabber.at or self hosted
|
||||
* **Server software:** ejabberd 19.09.1 or prosody 0.11.3 (if known)
|
||||
* **Installed server modules:** Stream Managment, CSI, MAM
|
||||
* **Conversations source:** PlayStore, PlayStore Beta Channel, F-Droid, self build (latest HEAD)
|
||||
|
||||
|
||||
#### Steps to reproduce
|
||||
|
||||
1. …
|
||||
2. …
|
||||
|
||||
|
||||
#### Expected result
|
||||
|
||||
What is the expected output?
|
||||
|
||||
|
||||
#### Actual result
|
||||
|
||||
What do you see instead?
|
||||
|
||||
|
||||
#### Debug output
|
||||
|
||||
Please post the output of adb logcat. The log should begin with the start of Conversations and include all the
|
||||
steps it takes to reproduce the problem.
|
||||
|
||||
````
|
||||
adb logcat -s conversations
|
||||
````
|
|
@ -0,0 +1,38 @@
|
|||
name: Android CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK 11
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '11'
|
||||
distribution: 'adopt'
|
||||
- name: Download WebRTC
|
||||
run: mkdir libs && wget -O libs/libwebrtc-m92.aar https://gultsch.de/files/libwebrtc-m92.aar
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Build Quicksy (Compat)
|
||||
run: ./gradlew assembleQuicksyFreeCompatDebug
|
||||
- name: Build Quicksy (System)
|
||||
run: ./gradlew assembleQuicksyFreeSystemDebug
|
||||
- name: Build Conversations (Compat)
|
||||
run: ./gradlew assembleConversationsFreeCompatDebug
|
||||
- name: Build Conversations (System)
|
||||
run: ./gradlew assembleConversationsFreeSystemDebug
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Conversations all-flavors (debug)
|
||||
path: ./build/outputs/apk/**/debug/Conversations-*.apk
|
||||
|
||||
|
|
@ -9,12 +9,13 @@ src/quicksyPlaystore/res/values/push.xml
|
|||
# https://github.com/github/gitignore/blob/master/Gradle.gitignore
|
||||
.gradle/
|
||||
build/
|
||||
gradle.properties
|
||||
captures/
|
||||
signing.properties
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
libs/*.aar
|
||||
|
||||
# https://github.com/github/gitignore/blob/master/Android.gitignore
|
||||
# Built application files
|
||||
*.apk
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
image: registry.gitlab.com/fdroid/ci-images-client:latest
|
||||
|
||||
cache:
|
||||
paths:
|
||||
- .gradle/wrapper
|
||||
- .gradle/caches
|
||||
|
||||
stages:
|
||||
- build
|
||||
|
||||
before_script:
|
||||
- export GRADLE_USER_HOME=$PWD/.gradle
|
||||
- export ANDROID_COMPILE_SDK=`sed -n 's,.*compileSdkVersion\s*\([0-9][0-9]*\).*,\1,p' build.gradle`
|
||||
- echo y | sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" > /dev/null
|
||||
|
||||
build:
|
||||
stage: build
|
||||
except:
|
||||
- develop
|
||||
script:
|
||||
- ./gradlew assembleConversationsFreeCompatDebug
|
||||
artifacts:
|
||||
paths:
|
||||
- build/outputs/
|
||||
|
||||
publish:
|
||||
stage: build
|
||||
only:
|
||||
- develop
|
||||
script:
|
||||
- find -type d -name "siacs" -print0 | xargs --null -I{} bash -c 'x="{}"; mv "$x" "${x/siacs/sum7}" '
|
||||
- find -type f -name "*.java" -exec sed -i "/eu.siacs.conversations.axolotl/! s/eu.siacs./eu.sum7./" "{}" \;
|
||||
- find -type f -name "*.xml" -exec sed -i "/eu.siacs.conversations.axolotl/! s/eu.siacs./eu.sum7./" "{}" \;
|
||||
# workaround for bug in fdroid nightly
|
||||
- sed -i "s/-debug.apk/-unsigned.apk/" /usr/lib/python3/dist-packages/fdroidserver/nightly.py
|
||||
- sed -i "s/servergitmirror = 'git@' +/servergitmirror = 'gitlab@' +/" /usr/lib/python3/dist-packages/fdroidserver/nightly.py
|
||||
- sed -i "s/git@/gitlab@/" /usr/lib/python3/dist-packages/fdroidserver/index.py
|
||||
# generate new version
|
||||
- export versionCode="$CI_JOB_ID"
|
||||
- export versionName="$(git describe --tag --abbrev=0)-${CI_JOB_ID}_${CI_COMMIT_REF_NAME}"
|
||||
- echo "set VersionCode '${versionCode}' and VersonName '${versionName}'"
|
||||
- sed -i "s/^\(\s*versionCode\s*\).*$/\1$versionCode/" build.gradle
|
||||
- sed -i "0,/versionName/s/^\(\s*versionName\).*/\1 \"$versionName\"/" build.gradle
|
||||
- cat -n build.gradle
|
||||
# build free version
|
||||
- ./gradlew assembleConversationsFreeCompatRelease
|
||||
- ls build/outputs/apk/conversationsFreeCompat/*
|
||||
# publish on nightly fdroid repo
|
||||
- fdroid nightly -v
|
||||
|
||||
after_script:
|
||||
# this file changes every time but should not be cached
|
||||
- rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock
|
||||
- rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/
|
17
.travis.yml
|
@ -1,17 +0,0 @@
|
|||
language: android
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
android:
|
||||
components:
|
||||
- platform-tools
|
||||
- tools
|
||||
- build-tools-28.0.3
|
||||
- extra-google-google_play_services
|
||||
licenses:
|
||||
- '.+'
|
||||
script:
|
||||
- ./gradlew assembleConversationsFreeSystemRelease
|
||||
- ./gradlew assembleQuicksyFreeCompatRelease
|
||||
|
||||
before_install:
|
||||
- yes | sdkmanager "platforms;android-28"
|
|
@ -2,7 +2,7 @@
|
|||
host = https://www.transifex.com
|
||||
lang_map = af_ZA: af-rZA, am_ET: am-rET, ar_AE: ar-rAE, ar_BH: ar-rBH, ar_DZ: ar-rDZ, ar_EG: ar-rEG, ar_IQ: ar-rIQ, ar_JO: ar-rJO, ar_KW: ar-rKW, ar_LB: ar-rLB, ar_LY: ar-rLY, ar_MA: ar-rMA, ar_OM: ar-rOM, ar_QA: ar-rQA, ar_SA: ar-rSA, ar_SY: ar-rSY, ar_TN: ar-rTN, ar_YE: ar-rYE, arn_CL: arn-rCL, as_IN: as-rIN, az_AZ: az-rAZ, ba_RU: ba-rRU, be_BY: be-rBY, bg_BG: bg-rBG, bn_BD: bn-rBD, bn_IN: bn-rIN, bo_CN: bo-rCN, br_FR: br-rFR, bs_BA: bs-rBA, ca_ES: ca-rES, co_FR: co-rFR, cs_CZ: cs-rCZ, cy_GB: cy-rGB, da_DK: da-rDK, de_AT: de-rAT, de_CH: de-rCH, de_DE: de-rDE, de_LI: de-rLI, de_LU: de-rLU, dsb_DE: dsb-rDE, dv_MV: dv-rMV, el_GR: el-rGR, en_AU: en-rAU, en_BZ: en-rBZ, en_CA: en-rCA, en_GB: en-rGB, en_IE: en-rIE, en_IN: en-rIN, en_JM: en-rJM, en_MY: en-rMY, en_NZ: en-rNZ, en_PH: en-rPH, en_SG: en-rSG, en_TT: en-rTT, en_US: en-rUS, en_ZA: en-rZA, en_ZW: en-rZW, es_AR: es-rAR, es_BO: es-rBO, es_CL: es-rCL, es_CO: es-rCO, es_CR: es-rCR, es_DO: es-rDO, es_EC: es-rEC, es_ES: es-rES, es_GT: es-rGT, es_HN: es-rHN, es_MX: es-rMX, es_NI: es-rNI, es_PA: es-rPA, es_PE: es-rPE, es_PR: es-rPR, es_PY: es-rPY, es_SV: es-rSV, es_US: es-rUS, es_UY: es-rUY, es_VE: es-rVE, et_EE: et-rEE, eu_ES: eu-rES, fa_IR: fa-rIR, fi_FI: fi-rFI, fil_PH: fil-rPH, fo_FO: fo-rFO, fr_BE: fr-rBE, fr_CA: fr-rCA, fr_CH: fr-rCH, fr_FR: fr-rFR, fr_LU: fr-rLU, fr_MC: fr-rMC, fy_NL: fy-rNL, ga_IE: ga-rIE, gd_GB: gd-rGB, gl_ES: gl-rES, gsw_FR: gsw-rFR, gu_IN: gu-rIN, ha_NG: ha-rNG, hi_IN: hi-rIN, hr_BA: hr-rBA, hr_HR: hr-rHR, hsb_DE: hsb-rDE, hu_HU: hu-rHU, hy_AM: hy-rAM, id_ID: id-rID, ig_NG: ig-rNG, ii_CN: ii-rCN, is_IS: is-rIS, it_CH: it-rCH, it_IT: it-rIT, iu_CA: iu-rCA, ja_JP: ja-rJP, ka_GE: ka-rGE, kk_KZ: kk-rKZ, kl_GL: kl-rGL, km_KH: km-rKH, kn_IN: kn-rIN, ko_KR: ko-rKR, kok_IN: kok-rIN, ky_KG: ky-rKG, lb_LU: lb-rLU, lo_LA: lo-rLA, lt_LT: lt-rLT, lv_LV: lv-rLV, mi_NZ: mi-rNZ, mk_MK: mk-rMK, ml_IN: ml-rIN, mn_CN: mn-rCN, mn_MN: mn-rMN, moh_CA: moh-rCA, mr_IN: mr-rIN, ms_BN: ms-rBN, ms_MY: ms-rMY, mt_MT: mt-rMT, nb_NO: nb-rNO, ne_NP: ne-rNP, nl_BE: nl-rBE, nl_NL: nl-rNL, nn_NO: nn-rNO, nso_ZA: nso-rZA, oc_FR: oc-rFR, or_IN: or-rIN, pa_IN: pa-rIN, pl_PL: pl-rPL, prs_AF: prs-rAF, ps_AF: ps-rAF, pt_BR: pt-rBR, pt_PT: pt-rPT, qut_GT: qut-rGT, quz_BO: quz-rBO, quz_EC: quz-rEC, quz_PE: quz-rPE, rm_CH: rm-rCH, ro_RO: ro-rRO, ru_RU: ru-rRU, rw_RW: rw-rRW, sa_IN: sa-rIN, sah_RU: sah-rRU, se_FI: se-rFI, se_NO: se-rNO, se_SE: se-rSE, si_LK: si-rLK, sk_SK: sk-rSK, sl_SI: sl-rSI, sma_NO: sma-rNO, sma_SE: sma-rSE, smj_NO: smj-rNO, smj_SE: smj-rSE, smn_FI: smn-rFI, sms_FI: sms-rFI, sq_AL: sq-rAL, sr_BA: sr-rBA, sr_CS: sr-rCS, sr_ME: sr-rME, sr_RS: sr-rRS, sv_FI: sv-rFI, sv_SE: sv-rSE, sw_KE: sw-rKE, syr_SY: syr-rSY, ta_IN: ta-rIN, te_IN: te-rIN, tg_TJ: tg-rTJ, th_TH: th-rTH, tk_TM: tk-rTM, tn_ZA: tn-rZA, tr_TR: tr-rTR, tt_RU: tt-rRU, tzm_DZ: tzm-rDZ, ug_CN: ug-rCN, uk_UA: uk-rUA, ur_PK: ur-rPK, uz_UZ: uz-rUZ, vi_VN: vi-rVN, wo_SN: wo-rSN, xh_ZA: xh-rZA, yo_NG: yo-rNG, zh_CN: zh-rCN, zh_HK: zh-rHK, zh_MO: zh-rMO, zh_SG: zh-rSG, zh_TW: zh-rTW, zu_ZA: zu-rZA, no_NO: no-rNO, he_IL: iw-rIL, he: iw
|
||||
|
||||
[conversations.strings]
|
||||
[conversations.main-strings]
|
||||
file_filter = src/main/res/values-<lang>/strings.xml
|
||||
source_file = src/main/res/values/strings.xml
|
||||
source_lang = en
|
||||
|
|
169
CHANGELOG.md
|
@ -1,5 +1,161 @@
|
|||
# Changelog
|
||||
|
||||
### Version 2.10.2
|
||||
|
||||
* Fix crash when rendering some quotes
|
||||
* Fix crash in welcome screen
|
||||
|
||||
### Version 2.10.1
|
||||
|
||||
* Fix issue with some videos not being compressed
|
||||
* Fix rare crash when opening notification
|
||||
|
||||
### Version 2.10.0
|
||||
|
||||
* Show black bars when remote video does not match aspect ratio of screen
|
||||
* Improve search performance
|
||||
* Add setting to prevent screenshots
|
||||
|
||||
### Version 2.9.13
|
||||
|
||||
* minor A/V improvements
|
||||
|
||||
### Version 2.9.12
|
||||
|
||||
* Always verify domain name. No user overwrite
|
||||
* Support roster pre authentication
|
||||
|
||||
### Version 2.9.11
|
||||
|
||||
* Fixed 'No Connectivity' issues on Android 7.1
|
||||
|
||||
### Version 2.9.10
|
||||
* fix HTTP up/download for users that don’t trust system CAs
|
||||
|
||||
### Version 2.9.9
|
||||
|
||||
* Various bug fixes around Tor support
|
||||
* Improve call compatibility with Dino
|
||||
|
||||
### Version 2.9.8
|
||||
|
||||
* Verify A/V calls with preexisting OMEMO sessions
|
||||
* Improve compatibility with non libwebrtc WebRTC implementations
|
||||
|
||||
### Version 2.9.7
|
||||
|
||||
* Ability to select incoming call ringtone
|
||||
* Fix OpenPGP key id discovery for OpenKeychain 5.6+
|
||||
* Properly verify punycode TLS certificates
|
||||
* Improve stability of RTP session establishment (calling)
|
||||
|
||||
### Version 2.9.6
|
||||
|
||||
* Show call button for offline contacts if they previously announced support
|
||||
* Back button no longer ends call when call is connected
|
||||
* bug fixes
|
||||
|
||||
### Version 2.9.5
|
||||
|
||||
* Quicksy: Automatically receive verification SMS
|
||||
|
||||
### Version 2.9.4
|
||||
* minor stability improvements for A/V calls
|
||||
* Conversations releases from here on forward require Android 5
|
||||
|
||||
### Version 2.9.3
|
||||
|
||||
* Fixed connectivity issues when different accounts used different SCRAM mechanisms
|
||||
* Add support for SCRAM-SHA-512
|
||||
* Allow P2P (Jingle) file transfer with self contact
|
||||
|
||||
### Version 2.9.2
|
||||
|
||||
* Offer Easy Invite generation on supporting servers
|
||||
* Display GIFs send from Movim
|
||||
* store avatars in cache
|
||||
|
||||
### Version 2.9.1
|
||||
|
||||
* fixed search on Android <= 5
|
||||
* optimize memory consumption
|
||||
|
||||
### Version 2.9.0
|
||||
|
||||
* Search individual conversations
|
||||
* Notify user if message delivery fails
|
||||
* Remember display names (nicks) from Quicksy users across restarts
|
||||
* Add button to start Orbot (Tor) from notification if necessary
|
||||
|
||||
### Version 2.8.10
|
||||
|
||||
* Handle GPX files
|
||||
* Improve performance for backup restore
|
||||
* bug fixes
|
||||
|
||||
### Version 2.8.9
|
||||
|
||||
* add 'Return to chat' to audio call screen
|
||||
* Improve keyboard shortcuts
|
||||
* bug fixes
|
||||
|
||||
### Version 2.8.8
|
||||
|
||||
* Fixed notifications not showing up under certain conditions
|
||||
* Fixed compatibility issues and crashes related to A/V calls
|
||||
|
||||
### Version 2.8.7
|
||||
|
||||
* Show help button if A/V call fails
|
||||
* Fixed some annoying crashes
|
||||
* Fixed Jingle connections (file transfer + calls) with bare JIDs
|
||||
|
||||
### Version 2.8.6
|
||||
|
||||
* Offer to record voice message when callee is busy
|
||||
|
||||
### Version 2.8.5
|
||||
|
||||
* Reduce echo during calls on some devices
|
||||
* Fix login when passwords contains special characters
|
||||
* Play dial and busy tones on speaker during video calls
|
||||
|
||||
### Version 2.8.4
|
||||
|
||||
* Rework Login with certificate UI
|
||||
* Add ability to pin chats on top (add to favorites)
|
||||
|
||||
### Version 2.8.3
|
||||
|
||||
* Move call icon to the left in order to keep other toolbar icons in a consistent place
|
||||
* Show call duration during audio calls
|
||||
* Tie breaking for A/V calls (the same two people calling each other at the same time)
|
||||
|
||||
### Version 2.8.2
|
||||
|
||||
* Add button to switch camera during video call
|
||||
* Fixed voice calls on tablets
|
||||
|
||||
### Version 2.8.1
|
||||
|
||||
* Audible feedback (dialing, call started, call ended) for voice calls.
|
||||
* Fixed issue with retrying failed video call
|
||||
|
||||
### Version 2.8.0
|
||||
|
||||
* Audio/Video calls (Requires server support in form of STUN and TURN servers discoverable via XEP-0215)
|
||||
|
||||
|
||||
### Version 2.7.1
|
||||
|
||||
* Fix avatar selection on some Android 10 devices
|
||||
* Fix file transfer for larger files
|
||||
|
||||
### Version 2.7.0
|
||||
|
||||
* Provide PDF preview on Android 5+
|
||||
* Use 12 byte IVs for OMEMO
|
||||
|
||||
### Version 2.6.4
|
||||
|
||||
* Support automatic theme switching on Android 10
|
||||
|
@ -343,10 +499,9 @@
|
|||
* Icons for attach menu
|
||||
|
||||
### Version 1.16.2
|
||||
* change mam catchup strategie. support mam:1
|
||||
* change mam catchup strategy. support mam:1
|
||||
* bug fixes
|
||||
|
||||
|
||||
### Version 1.16.1
|
||||
* UI performance fixes
|
||||
* bug fixes
|
||||
|
@ -396,7 +551,7 @@
|
|||
* bug fixes
|
||||
|
||||
### Version 1.14.6
|
||||
* make error notification dismissable
|
||||
* make error notification dismissible
|
||||
* bug fixes
|
||||
|
||||
|
||||
|
@ -420,7 +575,7 @@
|
|||
* bug fixes
|
||||
|
||||
### Version 1.14.0
|
||||
* Improvments for N
|
||||
* Improvements for N
|
||||
* Quick Reply to Notifications on N
|
||||
* Don't download avatars and files when data saver is on
|
||||
* bug fixes
|
||||
|
@ -598,7 +753,7 @@
|
|||
|
||||
### Version 1.7.0
|
||||
* CAPTCHA support
|
||||
* SASL EXTERNAL (client certifiates)
|
||||
* SASL EXTERNAL (client certificates)
|
||||
* fetching MUC history via MAM
|
||||
* redownload deleted files from HTTP hosts
|
||||
* Expert setting to automatically set presence
|
||||
|
@ -706,7 +861,7 @@
|
|||
* accept more ciphers
|
||||
|
||||
### Version 1.0
|
||||
* MUC controls (Affiliaton changes)
|
||||
* MUC controls (Affiliation changes)
|
||||
* Added download button to notification
|
||||
* Added check box to hide offline contacts
|
||||
* Use Material theme and icons on Android L
|
||||
|
@ -812,7 +967,7 @@
|
|||
* XEP-0333. Mark whether the other party has read your messages
|
||||
* Delayed messages are now tagged properly
|
||||
* Share images from the Gallery
|
||||
* Infinit history scrolling
|
||||
* Infinite history scrolling
|
||||
* Mark the last used presence in presence selection dialog
|
||||
|
||||
### Version 0.3
|
||||
|
|
150
README.md
|
@ -1,28 +1,36 @@
|
|||
<h1 align="center">Conversations</h1>
|
||||
<h1 align="center">Conv6ations for Sum7 is a fork of <a href="https://f-droid.org/packages/eu.siacs.conversations/">Conversations</a></h1>
|
||||
|
||||
<p align="center">Conversations: the very last word in instant messaging</p>
|
||||
<p align="center">A Jabber/XMPP chat client which is fair to IPv6</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://conversations.im/j/conversations@conference.siacs.eu">
|
||||
<img src="https://inverse.chat/badge.svg?room=conversations@conference.siacs.eu"
|
||||
alt="chat on our conference room">
|
||||
</a>
|
||||
<a href="https://travis-ci.org/siacs/Conversations">
|
||||
<img src="https://travis-ci.org/siacs/Conversations.svg?branch=master"
|
||||
alt="build status">
|
||||
</a>
|
||||
<a href="https://bountysource.com/teams/siacs">
|
||||
<img src="https://api.bountysource.com/badge/tracker?tracker_id=519483" alt="Bountysource">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<a href="https://conversations.im/j/support@conference.chat.sum7.eu">
|
||||
<img src="https://inverse.chat/badge.svg?room=support@conference.chat.sum7.eu"
|
||||
alt="chat on our conference room">
|
||||
</a>
|
||||
<a href="https://dev.sum7.eu/sum7/Conversations/pipelines">
|
||||
<img src="https://dev.sum7.eu/sum7/Conversations/badges/develop/pipeline.svg"
|
||||
alt="build status">
|
||||
</a>
|
||||
</a>
|
||||
<p align="center">
|
||||
<a href="https://play.google.com/store/apps/details?id=eu.siacs.conversations&referrer=utm_source%3Dgithub">
|
||||
<img src="https://conversations.im/images/en-play-badge.png" alt="Google Play">
|
||||
</a>
|
||||
<img src="metadata/en-US/phoneScreenshots/1.jpg" width="19%" alt="screenshot 1"/>
|
||||
<img src="metadata/en-US/phoneScreenshots/2.jpg" width="19%" alt="screenshot 2"/>
|
||||
<img src="metadata/en-US/phoneScreenshots/3.jpg" width="19%" alt="screenshot 3"/>
|
||||
<img src="metadata/en-US/phoneScreenshots/4.jpg" width="19%" alt="screenshot 4"/>
|
||||
<img src="metadata/en-US/phoneScreenshots/5.jpg" width="19%" alt="screenshot 5"/>
|
||||
</p>
|
||||
|
||||
![screenshots](https://raw.githubusercontent.com/siacs/Conversations/master/screenshots.png)
|
||||
[<img src="https://f-droid.org/badge/get-it-on.png"
|
||||
alt="Get it on F-Droid"
|
||||
height="80">](https://f-droid.org/en/packages/eu.sum7.conversations)
|
||||
|
||||
### Nightly:
|
||||
[![https://dev.sum7.eu/sum7/Conversations-nightly/raw/master/fdroid/repo](https://dev.sum7.eu/sum7/Conversations-nightly/raw/master/icon.png)](https://dev.sum7.eu/sum7/Conversations-nightly/raw/master/fdroid/repo)
|
||||
|
||||
## Changes to origin:
|
||||
* replace the hardcoded IPv4 preference to easy Happy Eyeball, for faster connection and fair to both IP version.
|
||||
* rebrands it as chat.sum7.eu (to run both version together)
|
||||
|
||||
|
||||
## Design principles
|
||||
|
||||
|
@ -35,6 +43,7 @@
|
|||
|
||||
* End-to-end encryption with [OMEMO](http://conversations.im/omemo/) or [OpenPGP](http://openpgp.org/about/)
|
||||
* Send and receive images as well as other kind of files
|
||||
* [Encrypted audio and video calls (DTLS-SRTP)](https://help.conversations.im)
|
||||
* Share your location
|
||||
* Send voice messages
|
||||
* Indication when your contact has read your message
|
||||
|
@ -87,37 +96,8 @@ Conversations is entirely open source and licensed under GPLv3. So if you are a
|
|||
software developer you can check out the sources from GitHub and use Gradle to
|
||||
build your apk file.
|
||||
|
||||
The more convenient way — which not only gives you automatic updates but also
|
||||
supports the further development of Conversations — is to buy the App in the
|
||||
Google [Play Store](https://play.google.com/store/apps/details?id=eu.siacs.conversations&referrer=utm_source%3Dgithub).
|
||||
|
||||
Buying the App from the Play Store will also give you access to our [beta test](#beta).
|
||||
|
||||
#### I don't have a Google Account but I would still like to make a contribution
|
||||
|
||||
I accept donations over PayPal, bank transfer and various crypto currencies. For donations via PayPal use the button below:
|
||||
|
||||
[![Donate with PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.me/ConversationsIM)
|
||||
|
||||
**Disclaimer:** I'm not a huge fan of PayPal and their business policies. For
|
||||
larger contributions please get in touch with me beforehand and we can talk
|
||||
about bank transfer (SEPA).
|
||||
|
||||
##### Crypto currencies
|
||||
|
||||
Bitcoin: `3KAD8vew6tPZDjiUJNnZ3YUoUxrCEVNwFL`
|
||||
|
||||
Bitcoin Cash: `16ABkXzYAwWz8Y5DcWFfbBRqL63g3hzEaU`
|
||||
|
||||
Ether: `0x5c4e5239cd9c6f4a909e4e8361526e2e3c8ba9fa`
|
||||
|
||||
#### How do I create an account?
|
||||
XMPP, like email, is a federated protocol, which means that there is not one company you can create an *official XMPP account* with. Instead there are hundreds, or even thousands, of providers out there. One of those providers is our very own [conversations.im](https://account.conversations.im). If you don’t like to use *conversations.im* use a web search engine of your choice to find another provider. Or maybe your university has one. Or you can run your own. Or ask a friend to run one. Once you've found one, you can use Conversations to create an account. Just select *register new account* on server within the create account dialog.
|
||||
|
||||
##### Domain hosting
|
||||
Using your own domain not only gives you a more recognizable Jabber ID, it also gives you the flexibility to migrate your account between different XMPP providers. This is a good compromise between the responsibilities of having to operate your own server and the downsides of being dependent on a single provider.
|
||||
|
||||
Learn more about [conversations.im Jabber/XMPP domain hosting](https://account.conversations.im/domain/).
|
||||
XMPP, like email, is a federated protocol, which means that there is not one company you can create an *official XMPP account* with. Instead there are hundreds, or even thousands, of providers out there. One of those providers is our very own [chat.sum7.eu](https://chat.sum7.eu). If you don’t like to use *chat.sum7.eu* use a web search engine of your choice to find another provider. Or maybe your university has one. Or you can run your own. Or ask a friend to run one. Once you've found one, you can use Conversations to create an account. Just select *register new account* on server within the create account dialog.
|
||||
|
||||
##### Running your own
|
||||
If you already have a server somewhere and are willing and able to put the necessary work in you can run your own XMPP server.
|
||||
|
@ -153,15 +133,15 @@ SCRAM-SHA1, PLAIN, EXTERNAL (client certs) and DIGEST-MD5.
|
|||
Some Bind failures are transient and resolve themselves after a reconnect.
|
||||
|
||||
When trying to connect to OpenFire the bind failure can be a permanent problem when the domain part of the Jabber ID entered in Conversations doesn’t match the domain the OpenFire server feels responsible for. For example OpenFire is configured to use the domain `a.tld` but the Jabber ID entered is `user@b.tld` where `b.tld` also points to the same host. During bind OpenFire tries to reassign the Jabber to `user@a.tld`. Conversations doesn’t like that.
|
||||
This can be fixed by creating a new account in Conversations that uses the Jabber ID `user@a.tld`.
|
||||
This can be fixed by creating a new account in Conversations that uses the Jabber ID `user@a.tld`.
|
||||
|
||||
Note: This is kind of a weird quirk in OpenFire. Most other servers would just throw a 'Server not responsible for domain' error instead of attempting to reassign the Jabber ID.
|
||||
|
||||
Maybe you attempted to use the Jabber ID `test@b.tld` because `a.tld` doesn’t point to the correct host. In that case you might have to enable the extended connection settings in the expert settings of Conversations and set a host name.
|
||||
|
||||
### I get 'Stream opening error'. What does that mean?
|
||||
#### I get 'Stream opening error'. What does that mean?
|
||||
|
||||
In most cases this error is caused by ejabberd advertising support for TLSv1.3 but not properly supporting it. This can happen if the openssl version on the server already supports TLSv1.3 but the fast\_tls wrapper library used by ejabberd not (properly) support it. Upgrading fast\_tls and ejabberd or - theoretically - downgrading openssl should fix the issue. A work around is to explicity disable TLSv1.3 support in the ejabberd configuration. More information can be found on [this issue on the ejabberd issue tracker](https://github.com/processone/ejabberd/issues/2614).
|
||||
In most cases this error is caused by ejabberd advertising support for TLSv1.3 but not properly supporting it. This can happen if the OpenSSL version on the server already supports TLSv1.3 but the fast\_tls wrapper library used by ejabberd not (properly) support it. Upgrading fast\_tls and ejabberd or - theoretically - downgrading OpenSSL should fix the issue. A work around is to explicitly disable TLSv1.3 support in the ejabberd configuration. More information can be found on [this issue on the ejabberd issue tracker](https://github.com/processone/ejabberd/issues/2614).
|
||||
|
||||
|
||||
#### I’m getting this annoying permanent notification
|
||||
|
@ -169,16 +149,16 @@ Starting with Conversations 2.3.6 Conversations releases distributed over the Go
|
|||
|
||||
However you can disable the notification via settings of the operating system. (Not settings in Conversations.)
|
||||
|
||||
**The battery consumption and the entire behaviour of Conversations will remain the same (as good or as bad as it was before). Why is Google doing this to you? We have no idea.**
|
||||
**The battery consumption and the entire behavior of Conversations will remain the same (as good or as bad as it was before). Why is Google doing this to you? We have no idea.**
|
||||
|
||||
##### Android <= 7.1
|
||||
##### Android <= 7.1 or Conversations from F-Droid (all Android versions)
|
||||
The foreground notification is still controlled over the expert settings within Conversations as it always has been. Whether or not you need to enable it depends on how aggressive the non-standard 'power saving' features are that your phone vendor has built into the operating system.
|
||||
|
||||
##### Android 8.x
|
||||
Long press the permanent notification and disable that particular type of notification by moving the slider to the left. This will make the notification disappear but create another notification (this time created by the operating system itself.) that will complain about Conversations (and other apps) using battery. Starting with Android 8.1 you can disable that notification again with the same method described above.
|
||||
|
||||
##### Android 9.0+
|
||||
Long press the permanent notification and press the info `(i)` button to get into the App info screen. In that screen touch the 'Notification' entry. In the next screen remove the checkbox for the 'Foreground service' entry.
|
||||
Long press the permanent notification and press the info `(i)` button to get into the App info screen. In that screen touch the 'Notification' entry. In the next screen remove the checkbox for the 'Foreground service' entry.
|
||||
|
||||
#### How do XEP-0357: Push Notifications work?
|
||||
You need to be running the Play Store version of Conversations and your server needs to support push notifications.¹ Because *Google’s Firebase Cloud Messaging (FCM)* are tied with an API key to a specific app your server can not initiate the push message directly. Instead your server will send the push notification to the [Conversations App server](https://github.com/iNPUTmice/p2) (operated by us) which then acts as a proxy and initiates the push message for you. The push message sent from our App server through FCM doesn’t contain any personal information. It is just an empty message which will wake up your device and tell Conversations to reconnect to your server. The information sent from your server to our App server depends on the configuration of your server but can be limited to your account name. (In any case the Conversations App server won't redirect any information through FCM even if your server sends this information.)
|
||||
|
@ -189,24 +169,20 @@ If you don’t want this simply pick a server which does not offer Push Notifica
|
|||
|
||||
You can find a detailed description of how your server, the app server and FCM are interacting with each other in the [README](https://github.com/iNPUTmice/p2/blob/master/README.md) of the Conversations App Server.
|
||||
|
||||
¹ Your server only needs to support the server side of [XEP-0357: Push Notifications](http://xmpp.org/extensions/xep-0357.html). If you use the Play Store version you do **not** need to run your own app server. The server modules are called *mod_cloud_notify* on Prosody and *mod_push* on ejabberd.
|
||||
¹ If you use the Play Store version you do **not** need to run your own app server. Your server only needs to support the server side of [XEP-0357: Push Notifications](http://xmpp.org/extensions/xep-0357.html) and [XEP-0198: Stream Management](https://xmpp.org/extensions/xep-0198.html). The prosody server modules are called *mod_cloud_notify* and *mod_smacks*. The ejabberd server modules are called *mod_push* and *mod_stream_mgmt*.
|
||||
|
||||
|
||||
#### But why do I need a permanent notification if I use Google Push?
|
||||
FCM (Google Push) allows an app to wake up from *Doze* which is (as the name suggests) a hibernation feature of the Android operating system that cuts the network connection and also reduces the number of times the app is allowed to wake up (to ping the server for example). The app can ask to be excluded from doze. Non push variants of the app (from F-Droid or if the server doesn’t support it) will do this on first start up. So if you get exemption from *Doze*, or if you get regular push events sent to you, Doze should not pose a threat to Conversatons working properly. But even with *Doze* the app is still open in the background (kept in memory); it is just limited in the actions it can do. Conversations needs to stay in memory to hold certain session state (online status of contacts, join status of group chats, …). However with Android 8 Google changed all of this again and now an App that wants to stay in memory needs to have a foreground service which is visible to the user via the annoying notification. But why does Conversations need to hold that state? XMPP is a stateful protocol that has a lot of per-session information; packets need to be counted, presence information needs to be held, some features like Message Carbons get activated once per session, MAM catchup happens once, service discovery happens only once; the list goes on. When Conversations was created in early 2014 none of this was a problem because apps were just allowed to stay in memory. Basically every XMPP client out there holds that information in memory because it would be a lot more complicated trying to persist it to disk. An entire rewrite of Conversations in the year 2019 would attempt to do that and would probably succeed however it would require exactly that; a complete rewrite which is not feasible right now. That’s by the way also the reason why it is difficult to write an XMPP client on iOS. Or more broadly put this is also the reason why other protocols are designed as or migrated to stateless protocols (often based on HTTP); take for example the migration of IMAP to [JMAP](https://jmap.io/).
|
||||
FCM (Google Push) allows an app to wake up from *Doze* which is (as the name suggests) a hibernation feature of the Android operating system that cuts the network connection and also reduces the number of times the app is allowed to wake up (to ping the server for example). The app can ask to be excluded from doze. Non push variants of the app (from F-Droid or if the server doesn’t support it) will do this on first start up. So if you get exemption from *Doze*, or if you get regular push events sent to you, Doze should not pose a threat to Conversatons working properly. But even with *Doze* the app is still open in the background (kept in memory); it is just limited in the actions it can do. Conversations needs to stay in memory to hold certain session state (online status of contacts, join status of group chats, …). However with Android 8 Google changed all of this again and now an App that wants to stay in memory needs to have a foreground service which is visible to the user via the annoying notification. But why does Conversations need to hold that state? XMPP is a statefull protocol that has a lot of per-session information; packets need to be counted, presence information needs to be held, some features like Message Carbons get activated once per session, MAM catch-up happens once, service discovery happens only once; the list goes on. When Conversations was created in early 2014 none of this was a problem because apps were just allowed to stay in memory. Basically every XMPP client out there holds that information in memory because it would be a lot more complicated trying to persist it to disk. An entire rewrite of Conversations in the year 2019 would attempt to do that and would probably succeed however it would require exactly that; a complete rewrite which is not feasible right now. That’s by the way also the reason why it is difficult to write an XMPP client on iOS. Or more broadly put this is also the reason why other protocols are designed as or migrated to stateless protocols (often based on HTTP); take for example the migration of IMAP to [JMAP](https://jmap.io/).
|
||||
|
||||
#### Conversations doesn’t work for me. Where can I get help?
|
||||
|
||||
You can join our conference room on `conversations@conference.siacs.eu`.
|
||||
You can join our conference room on [`support@conference.chat.sum7.eu`](https://conversations.im/j/support@conference.chat.sum7.eu).
|
||||
A lot of people in there are able to answer basic questions about the usage of
|
||||
Conversations or can provide you with tips on running your own XMPP server. If
|
||||
you found a bug or your app crashes please read the Developer / Report Bugs
|
||||
section of this document.
|
||||
|
||||
#### I need professional support with Conversations or setting up my server
|
||||
|
||||
I'm available for hire. Contact information can be found on [my website](https://gultsch.de).
|
||||
|
||||
#### How does the address book integration work?
|
||||
|
||||
The address book integration was designed to protect your privacy. Conversations
|
||||
|
@ -291,11 +267,11 @@ and introduce yourself to `iNPUTmice` so he can approve your join request.
|
|||
#### How do I backup / move Conversations to a new device?
|
||||
On the one hand Conversations supports Message Archive Management to keep a server side history of your messages so when migrating to a new device that device can display your entire history. However that does not work if you enable OMEMO due to its forward secrecy. (Read [The State of Mobile XMPP in 2016](https://gultsch.de/xmpp_2016.html) especially the section on encryption.)
|
||||
|
||||
As of version 2.4.0 an integrated Backup & Restore function will help with this, go to Settings → Expert settings → Create backup. A notification will pop-up during the creation process that will announce you when it's ready. After the files, one for each account, are created, you can move the **Conversations** folder *(if you want your old media files too)* or only the **Conversations/Backup** folder *(for OMEMO keys and history only)* to your new device (or to a storage place) where a freshly installed Conversations can restore each account. Don't forget to enable the accounts after a succesful restore.
|
||||
As of version 2.4.0 an integrated Backup & Restore function will help with this, go to Settings and you’ll find a setting called Create backup. A notification will pop-up during the creation process that will announce you when it's ready. After the files, one for each account, are created, you can move the **Conversations** folder *(if you want your old media files too)* or only the **Conversations/Backup** folder *(for OMEMO keys and history only)* to your new device (or to a storage place) where a freshly installed Conversations can restore each account. Don't forget to enable the accounts after a successfull restore.
|
||||
|
||||
This backup method will include your OMEMO keys. Due to forward secrecy you will not be able to recover messages sent and received between creating the backup and restoring it. If you have a server side archive (MAM) those messages will be retrieved but displayed as *unable to decrypt*. For technical reasons you might also lose the first message you either sent or receive after the restore; for each conversation you have. This message will then also show up as *unable to decrypt*, but this will automatically recover itself as long as both participants are on Conversations 2.3.11+. Note that this doesn’t happen if you just transfer to a new phone and no messages have been exchanged between backup and restore.
|
||||
|
||||
In the vast, vast majority of cases you won’t have to manually delete OMEMO keys or do anything like that. Conversations only introduced the offical backup feature in 2.4.0 after making sure the *OMEMO self healing* mechanism introduced in 2.3.11 works fine.
|
||||
In the vast, vast majority of cases you won’t have to manually delete OMEMO keys or do anything like that. Conversations only introduced the official backup feature in 2.4.0 after making sure the *OMEMO self healing* mechanism introduced in 2.3.11 works fine.
|
||||
|
||||
**WARNING**: Be sure to know your accounts passwords or find ways to reset them **before** doing the backup as the files are encrypted using those passwords and the Restore process will ask for them.
|
||||
**WARNING**: Do not use the restore backup feature in an attempt to clone (run simultaneously) an installation. Restoring a backup is only meant for migrations or in case you’ve lost the original device.
|
||||
|
@ -316,10 +292,6 @@ will it accelerate the development.
|
|||
Just write it yourself and send me a pull request. If I like it I will happily
|
||||
merge it if I don't at least you and like minded people get to enjoy it.
|
||||
|
||||
#### I need a feature and I need it now!
|
||||
|
||||
I am available for hire. Contact me via XMPP: `inputmice@siacs.eu`
|
||||
|
||||
### Security
|
||||
|
||||
#### Why are there two end-to-end encryption methods and which one should I choose?
|
||||
|
@ -355,7 +327,7 @@ OMEMO has two requirements: Your server and the server of your contact need to s
|
|||
OMEMO encryption works only in private (members only) conferences that are non-anonymous. Non-anonymous (being able to discover the real JID of other participants) is a technical requirement to discover the key material. Members only is a sort of arbitrary requirement imposed by Conversations. (see 'OMEMO is grayed out')
|
||||
|
||||
The server of all participants need to pass the OMEMO [Compliance Test](https://conversations.im/compliance/).
|
||||
In other words they either need to run Ejabberd 18.01+ or Prosody 0.11+.
|
||||
In other words they either need to run ejabberd 18.01+ or Prosody 0.11+.
|
||||
|
||||
(Alternatively it would also work if all participants had each other in their contact list; But that rarely is the case in larger group chats.)
|
||||
|
||||
|
@ -389,47 +361,29 @@ There are XMPP Clients available for all major platforms.
|
|||
#### Windows / Linux
|
||||
For your desktop computer we recommend that you use [Gajim](https://gajim.org). You need to install the plugins `OMEMO`, `HTTP Upload` and `URL image preview` to get the best compatibility with Conversations. Plugins can be installed from within the app.
|
||||
#### iOS
|
||||
Unfortunately we don‘t have a recommendation for iPhones right now. There are two clients available [ChatSecure](https://chatsecure.org/) and [Monal](https://monal.im/). Both with their own pros and cons.
|
||||
Unfortunately we don‘t have a recommendation for iPhones right now. There are three clients available [Siskin](https://siskin.im/), [ChatSecure](https://chatsecure.org/) and [Monal](https://monal.im/). Each with their own pros and cons.
|
||||
|
||||
|
||||
### Development
|
||||
|
||||
<a name="beta"></a>
|
||||
#### Beta testing
|
||||
If you bought the App on [Google Play](https://play.google.com/store/apps/details?id=eu.siacs.conversations)
|
||||
you can get access to the the latest beta version by signing up using [this link](https://play.google.com/apps/testing/eu.siacs.conversations).
|
||||
|
||||
#### How do I build Conversations
|
||||
|
||||
**Note:** Starting with version 2.8.0 you will need to compile libwebrtc.
|
||||
[Instructions](https://webrtc.github.io/webrtc-org/native-code/android/) can be found on the WebRTC
|
||||
website. Place the resulting libwebrtc.aar in the `libs/` directory. The PlayStore release currently
|
||||
uses the stable M90 release and renamed the file name to `libwebrtc-m90.aar` put potentially you can
|
||||
reference any file name by modifying `build.gradle`.
|
||||
|
||||
Make sure to have ANDROID_HOME point to your Android SDK. Use the Android SDK Manager to install missing dependencies.
|
||||
|
||||
git clone https://github.com/siacs/Conversations.git
|
||||
git clone https://github.com/inputmice/Conversations.git
|
||||
cd Conversations
|
||||
./gradlew assembleConversationsFreeSystemDebug
|
||||
|
||||
There are two build flavors available. *free* and *playstore*. Unless you know what you are doing you only need *free*.
|
||||
|
||||
|
||||
[![Build Status](https://travis-ci.org/siacs/Conversations.svg?branch=development)](https://travis-ci.org/siacs/Conversations)
|
||||
|
||||
#### How do I update/add external libraries?
|
||||
|
||||
If the library you want to update is in Maven Central or JCenter (or has its own
|
||||
Maven repo), add it or update its version in `build.gradle`. If the library is
|
||||
in the `libs/` directory, you can update it using a subtree merge by doing the
|
||||
following (using `minidns` as an example):
|
||||
|
||||
git remote add minidns https://github.com/rtreffer/minidns.git
|
||||
git fetch minidns
|
||||
git merge -s subtree minidns master
|
||||
|
||||
To add a new dependency to the `libs/` directory (replacing "name", "branch" and
|
||||
"url" as necessary):
|
||||
|
||||
git remote add name url
|
||||
git merge -s ours --no-commit name/branch
|
||||
git read-tree --prefix=libs/name -u name/branch
|
||||
git commit -m "Subtree merged in name"
|
||||
[![Build Status](https://dev.sum7.eu/sum7/Conversations/badges/develop/build.svg)](https://dev.sum7.eu/sum7/Conversations/pipelines)
|
||||
|
||||
#### How do I debug Conversations
|
||||
|
||||
|
@ -446,7 +400,7 @@ Debian/Ubuntu for example it is called `android-tools-adb`.
|
|||
Furthermore you might have to enable 'USB debugging' in the Developer options of your
|
||||
phone. After that you can just execute the following on your computer:
|
||||
|
||||
adb -d logcat -v time -s conversations
|
||||
adb -d logcat -v time -s conver6ations
|
||||
|
||||
If need be there are also some Apps on the PlayStore that can be used to show the logcat
|
||||
directly on your rooted phone. (Search for logcat). However in regards to further processing
|
||||
|
@ -461,4 +415,4 @@ Play Store version or the current HEAD. If you are having problems connecting to
|
|||
your XMPP server your file transfer doesn’t work as expected please always
|
||||
include a logcat debug output with your issue (see above).
|
||||
|
||||
[issues]: https://github.com/siacs/Conversations/issues
|
||||
[issues]: https://dev.sum7.eu/sum7/Conversations/issues
|
||||
|
|
|
@ -155,9 +155,9 @@
|
|||
inkscape:connector-curvature="0"
|
||||
id="path3805"
|
||||
d="m 8,8 c 2,2 4,6 4,10 L 16,8 Z"
|
||||
style="display:none;fill:#424242;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3811)" />
|
||||
style="display:none;fill:#282828;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3811)" />
|
||||
<rect
|
||||
style="fill:#424242;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3811)"
|
||||
style="fill:#282828;fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3811)"
|
||||
id="rect2987"
|
||||
width="20"
|
||||
height="20"
|
||||
|
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24" fill="black" width="24px" height="24px"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M9,12c0,1.66,1.34,3,3,3s3-1.34,3-3s-1.34-3-3-3S9,10.34,9,12z"/><path d="M8,10V8H5.09C6.47,5.61,9.05,4,12,4c3.72,0,6.85,2.56,7.74,6h2.06c-0.93-4.56-4.96-8-9.8-8C8.73,2,5.82,3.58,4,6.01V4H2v6 H8z"/><path d="M16,14v2h2.91c-1.38,2.39-3.96,4-6.91,4c-3.72,0-6.85-2.56-7.74-6H2.2c0.93,4.56,4.96,8,9.8,8c3.27,0,6.18-1.58,8-4.01V20 h2v-6H16z"/></g></g></svg>
|
After Width: | Height: | Size: 547 B |
|
@ -147,15 +147,15 @@
|
|||
inkscape:export-xdpi="100"
|
||||
transform="matrix(0.3835576,0,0,0.3835576,-246.60108,-156.11013)"
|
||||
id="g5317"
|
||||
style="display:inline;fill:#00a000;fill-opacity:1">
|
||||
style="display:inline;fill:#EF6C00;fill-opacity:1">
|
||||
<path
|
||||
style="display:inline;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="display:inline;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 1120.8042,772.36056 -118.0025,103.66316 118.5792,46.01918 c 8.4859,3.29325 19.6524,7.94481 27.2622,0.71376 7.3868,-7.01907 5.6502,-14.13839 3.0935,-24.54095 z"
|
||||
id="path5319"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccsssc" />
|
||||
<circle
|
||||
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
style="display:inline;opacity:1;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="circle5321"
|
||||
cx="883.16943"
|
||||
cy="677.19611"
|
||||
|
@ -171,7 +171,7 @@
|
|||
inkscape:connector-curvature="0"
|
||||
id="path6884"
|
||||
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
|
||||
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
style="display:inline;opacity:1;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
|
@ -180,7 +180,7 @@
|
|||
inkscape:connector-curvature="0"
|
||||
id="path6888"
|
||||
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
|
||||
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
style="display:inline;opacity:1;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
|
@ -189,7 +189,7 @@
|
|||
inkscape:connector-curvature="0"
|
||||
id="path6892"
|
||||
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
|
||||
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
style="display:inline;opacity:1;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
|
@ -198,7 +198,7 @@
|
|||
inkscape:connector-curvature="0"
|
||||
id="path6896"
|
||||
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
|
||||
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
style="display:inline;opacity:1;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
|
@ -207,7 +207,7 @@
|
|||
inkscape:connector-curvature="0"
|
||||
id="path6900"
|
||||
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
|
||||
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
style="display:inline;opacity:1;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
|
@ -216,7 +216,7 @@
|
|||
inkscape:connector-curvature="0"
|
||||
id="path6904"
|
||||
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
|
||||
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
style="display:inline;opacity:1;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
|
@ -225,7 +225,7 @@
|
|||
inkscape:connector-curvature="0"
|
||||
id="path6908"
|
||||
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
|
||||
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
style="display:inline;opacity:1;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
|
@ -234,7 +234,7 @@
|
|||
inkscape:connector-curvature="0"
|
||||
id="path6912"
|
||||
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
|
||||
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
style="display:inline;opacity:1;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</clipPath>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
|
@ -256,7 +256,7 @@
|
|||
inkscape:connector-curvature="0"
|
||||
id="path5747"
|
||||
d="M 99.908581,-2.3831968e-4 A 95.889392,95.889392 0 0 0 4.0199102,95.888436 95.889392,95.889392 0 0 0 99.908581,191.77906 95.889392,95.889392 0 0 0 142.61366,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 L 183.8285,142.24002 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.79921,95.888466 95.889392,95.889392 0 0 0 99.908581,-2.0831968e-4 Z"
|
||||
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
style="display:inline;opacity:1;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<metadata
|
||||
|
@ -290,7 +290,7 @@
|
|||
inkscape:groupmode="layer"
|
||||
transform="translate(-4,2.6816348)">
|
||||
<path
|
||||
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
style="display:inline;opacity:1;fill:#EF6C00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="M 104.88867,-1.9377566 A 95.889392,95.889392 0 0 0 8.9999996,93.950918 95.889392,95.889392 0 0 0 104.88867,189.84154 95.889392,95.889392 0 0 0 147.59375,179.76341 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 L 188.80859,140.3025 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 200.7793,93.950948 95.889392,95.889392 0 0 0 104.88867,-1.9377266 Z"
|
||||
id="circle6661"
|
||||
inkscape:connector-curvature="0" />
|
||||
|
@ -313,7 +313,7 @@
|
|||
style="display:inline"
|
||||
transform="translate(-4,2.6816164)">
|
||||
<path
|
||||
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="opacity:1;fill:#FF9800;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
clip-path="url(#clipPath6910)"
|
||||
d="m 145.16406,11.183594 -5.13232,9.649402 c -0.77924,1.465076 -0.65974,2.41396 0.66876,3.18097 9.66686,5.488467 18.12303,12.874168 24.86104,21.711122 1.05534,1.616079 2.08054,1.713076 3.67763,0.571565 L 178.04883,40 C 169.45271,27.990203 158.19857,18.128379 145.16406,11.183594 Z"
|
||||
id="path7364"
|
||||
|
@ -321,7 +321,7 @@
|
|||
sodipodi:nodetypes="csccscc"
|
||||
transform="translate(4.9999996,-1.9374999)" />
|
||||
<path
|
||||
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="opacity:1;fill:#FF9800;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
clip-path="url(#clipPath6906)"
|
||||
d="m 193.80469,75.615234 -9.62713,2.062751 c -2.66266,0.570512 -3.40763,1.172953 -2.90593,3.917433 0.85823,4.714633 1.30424,9.497137 1.33189,14.293254 -0.028,5.578758 -0.62194,11.137108 -1.77093,16.589918 -0.86591,3.23162 0.13682,3.77092 3.16149,4.58138 l 8.98639,2.30136 c 1.98177,-7.66828 3.00584,-15.55255 3.04883,-23.472658 -0.0187,-6.817681 -0.76446,-13.613926 -2.22461,-20.273438 z"
|
||||
id="path7366"
|
||||
|
@ -329,7 +329,7 @@
|
|||
sodipodi:nodetypes="csccccccc"
|
||||
transform="translate(4.9999996,-1.9374999)" />
|
||||
<path
|
||||
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="opacity:1;fill:#FF9800;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
clip-path="url(#clipPath6902)"
|
||||
d="m 14.264281,102.76512 -10.2076406,0.87943 c 1.2093798,14.83154 5.8540346,29.17808 13.5664056,41.90429 l 8.544301,-5.23239 c 2.394983,-1.46665 1.895406,-3.37834 0.986202,-5.04513 -5.118253,-9.40257 -8.359018,-19.71635 -9.536202,-30.36553 0,-2.09418 -1.881577,-2.26744 -3.353066,-2.14067 z"
|
||||
id="path7372"
|
||||
|
@ -337,7 +337,7 @@
|
|||
sodipodi:nodetypes="sccsccs"
|
||||
transform="translate(4.9999996,-1.9374999)" />
|
||||
<path
|
||||
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="opacity:1;fill:#FF9800;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
clip-path="url(#clipPath6898)"
|
||||
d="m 51.504371,166.60235 -5.82273,8.50898 c 12.710503,8.71282 27.333669,14.23394 42.630859,16.0957 l 1.220329,-9.90843 c 0.355066,-2.88295 -1.085712,-3.52946 -3.332252,-3.90256 -10.402329,-1.73697 -20.373956,-5.45322 -29.373754,-10.94516 -1.647505,-1.06744 -3.639993,-2.30718 -5.322452,0.15147 z"
|
||||
id="path7370"
|
||||
|
@ -345,7 +345,7 @@
|
|||
sodipodi:nodetypes="sccsccs"
|
||||
transform="translate(4.9999996,-1.9374999)" />
|
||||
<path
|
||||
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="opacity:1;fill:#FF9800;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
clip-path="url(#clipPath6894)"
|
||||
d="M 32.208984,27.683594 C 21.779177,38.079001 13.883707,50.736882 9.1347656,64.675781 L 19.33617,68.090365 c 1.658147,0.55501 2.832564,-0.120955 3.374272,-1.591979 3.777598,-10.021698 9.470788,-19.210103 16.759132,-27.052307 1.561136,-1.561136 1.567283,-2.960058 0.447507,-4.076606 z"
|
||||
id="path7374"
|
||||
|
@ -353,7 +353,7 @@
|
|||
sodipodi:nodetypes="ccsccsc"
|
||||
transform="translate(4.9999996,-1.9374999)" />
|
||||
<path
|
||||
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="opacity:1;fill:#FF9800;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
clip-path="url(#clipPath6890)"
|
||||
d="M 99.888672,-0.25 C 87.701045,-0.2239408 75.630114,2.1252837 64.322266,6.671875 l 3.530435,8.74898 c 1.063314,2.635062 1.616754,3.526314 4.973913,2.352259 8.692057,-3.031338 17.839027,-4.588849 27.062058,-4.599286 5.555828,0 6.486278,0.350026 6.780788,-3.4460223 l 0.74851,-9.64772758 C 104.9135,-0.12857239 102.40179,-0.23868346 99.888672,-0.25 Z"
|
||||
id="path7376"
|
||||
|
@ -361,7 +361,7 @@
|
|||
sodipodi:nodetypes="ccsccscc"
|
||||
transform="translate(4.9999996,-1.9374999)" />
|
||||
<path
|
||||
style="display:inline;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="display:inline;fill:#FF9800;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
clip-path="url(#clipPath6886)"
|
||||
d="m 138.72416,168.48439 c -4.17634,2.25458 -8.55959,4.09055 -13.0504,5.63418 -1.00363,0.34498 -1.20742,1.18222 -0.8682,2.27372 l 3.44056,11.0706 c 4.92985,-1.53124 9.72799,-3.45808 14.34766,-5.76172 l 0.12695,0.0137 14.0293,5.44532 4.12174,-10.20577 c 0.7548,-1.86894 -0.0184,-2.7016 -1.59462,-3.31324 l -14.72114,-5.71251 c -1.86679,-0.7244 -3.68834,-0.60144 -5.83185,0.55572 z"
|
||||
id="path5005"
|
||||
|
@ -369,7 +369,7 @@
|
|||
sodipodi:nodetypes="cssccccsssc"
|
||||
transform="translate(4.9999996,-1.9374999)" />
|
||||
<path
|
||||
style="display:inline;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
style="display:inline;fill:#FF9800;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
clip-path="url(#clipPath6882)"
|
||||
d="m 186.53125,152.80469 -10.6386,2.70888 c -0.78879,0.20085 -1.67397,1.02386 -1.35494,2.33801 l 9.75918,40.15428 c 8.56713,5.97538 15.30408,3.06731 11.01563,-9.47266 z"
|
||||
id="path5071"
|
||||
|
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
@ -1,76 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.0"
|
||||
width="95"
|
||||
height="95"
|
||||
id="Yes_check"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="ic_received_indicator.svg">
|
||||
<metadata
|
||||
id="metadata10">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="956"
|
||||
inkscape:window-height="1156"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:zoom="5.04"
|
||||
inkscape:cx="-4.3215257"
|
||||
inkscape:cy="37.489149"
|
||||
inkscape:window-x="2880"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="Yes_check"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<defs
|
||||
id="defs1373">
|
||||
<linearGradient
|
||||
id="linearGradient2250">
|
||||
<stop
|
||||
style="stop-color:#008700;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop2252" />
|
||||
<stop
|
||||
style="stop-color:#006f00;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop2254" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path
|
||||
d="m 2.3894499,61.412131 c 0,0 16.7473651,20.271938 22.3528491,26.154483 3.648598,3.026816 12.878061,3.83429 14.880462,0 1.64903,-2.636163 2.380404,-5.8348 2.991819,-7.931771 C 49.920898,54.575958 72.297563,22.337321 92.321082,10.50894 96.814837,5.2377522 86.327596,3.5063483 77.217442,6.9958109 63.487006,12.254946 34.107717,59.529917 29.270873,69.192545 22.40265,70.841418 12.518762,52.447046 12.518762,52.447046 7.3805037,52.552428 1.8841059,52.071763 2.3894499,61.412131 z"
|
||||
style="fill:#259b24;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.29981154;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="check"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccscsccc" />
|
||||
</svg>
|
Before Width: | Height: | Size: 2.7 KiB |
BIN
art/logo.png
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 12 B |
|
@ -0,0 +1 @@
|
|||
new_logo.png
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 12 B |
|
@ -94,7 +94,7 @@
|
|||
<path
|
||||
d="M24 4c-7.73 0-14 6.27-14 14 0 10.5 14 26 14 26s14-15.5 14-26c0-7.73-6.27-14-14-14zm0 19c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"
|
||||
id="path4"
|
||||
style="fill:#00a000;fill-opacity:1;stroke:none;stroke-opacity:0.53333336;stroke-width:1.70000002;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
style="fill:#EF6C00;fill-opacity:1;stroke:none;stroke-opacity:0.53333336;stroke-width:1.70000002;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
style="display:inline;opacity:0.19211821;fill:url(#radialGradient3883);fill-opacity:1;stroke:none"
|
||||
d="m 53.884912,1.7373006 c -18.322492,0 -33.173092,14.5823714 -33.173092,32.5686504 0,3.794038 0.661899,7.436601 1.877335,10.821463 1.505391,0.209531 3.044508,0.317391 4.607513,0.317391 5.584539,0 9.890238,-1.147853 14.805425,-2.934259 l 15.611481,6.295152 a 2.0568126,2.0577227 0 0 0 2.766588,-2.403594 l -4.227888,-17.09591 c 2.717518,-4.771967 3.645449,-10.205846 3.645449,-15.810885 0,-4.0761111 -0.781533,-7.9714274 -2.20495,-11.5551094 -1.217366,-0.132888 -2.454715,-0.202899 -3.707861,-0.202899 z"
|
||||
|
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
|
@ -140,7 +140,7 @@
|
|||
transform="translate(0,-2)">
|
||||
<g
|
||||
id="g3759"
|
||||
style="fill:#4d8e50;fill-opacity:1;stroke:none;fill-rule:nonzero;filter:url(#filter3811)">
|
||||
style="fill:#FF9800;fill-opacity:1;stroke:none;fill-rule:nonzero;filter:url(#filter3811)">
|
||||
<path
|
||||
style="display:none"
|
||||
d="m 8,6 c 2,2 4,6 4,10 L 16,6 z"
|
||||
|
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
@ -140,7 +140,7 @@
|
|||
transform="translate(0,-2)">
|
||||
<g
|
||||
id="g3759"
|
||||
style="fill:#295e2d;fill-opacity:1;stroke:none;fill-rule:nonzero;filter:url(#filter3811)">
|
||||
style="fill:#BF360C;fill-opacity:1;stroke:none;fill-rule:nonzero;filter:url(#filter3811)">
|
||||
<path
|
||||
style="display:none"
|
||||
d="m 8,6 c 2,2 4,6 4,10 L 16,6 z"
|
||||
|
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
@ -140,9 +140,9 @@
|
|||
transform="translate(0,-2)">
|
||||
<g
|
||||
id="g3759"
|
||||
style="fill:#424242;fill-opacity:1;stroke:none;fill-rule:nonzero;filter:url(#filter3811)">
|
||||
style="fill:#282828;fill-opacity:1;stroke:none;fill-rule:nonzero;filter:url(#filter3811)">
|
||||
<path
|
||||
style="display:none;fill:#424242;fill-opacity:1"
|
||||
style="display:none;fill:#282828;fill-opacity:1"
|
||||
d="m 8,6 c 2,2 4,6 4,10 L 16,6 z"
|
||||
id="path3805"
|
||||
inkscape:connector-curvature="0"
|
||||
|
@ -153,7 +153,7 @@
|
|||
id="path2989"
|
||||
d="M 4,4 16,16 16,4 z"
|
||||
sodipodi:nodetypes="cccc"
|
||||
style="fill:#424242;fill-opacity:1" />
|
||||
style="fill:#282828;fill-opacity:1" />
|
||||
<rect
|
||||
ry="2"
|
||||
y="4"
|
||||
|
@ -161,7 +161,7 @@
|
|||
height="20"
|
||||
width="20"
|
||||
id="rect2987"
|
||||
style="fill:#424242;fill-opacity:1" />
|
||||
style="fill:#282828;fill-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
@ -140,9 +140,9 @@
|
|||
transform="translate(0,-2)">
|
||||
<g
|
||||
id="g3759"
|
||||
style="fill:#424242;fill-opacity:1;stroke:none;fill-rule:nonzero;filter:url(#filter3811)">
|
||||
style="fill:#282828;fill-opacity:1;stroke:none;fill-rule:nonzero;filter:url(#filter3811)">
|
||||
<path
|
||||
style="display:none;fill:#424242;fill-opacity:1"
|
||||
style="display:none;fill:#282828;fill-opacity:1"
|
||||
d="M 28,18 C 26,16 24,12 24,8 l -4,10 z"
|
||||
id="path3809"
|
||||
inkscape:connector-curvature="0"
|
||||
|
@ -153,7 +153,7 @@
|
|||
id="path2989"
|
||||
d="m 20,12 0,12 12,0 z"
|
||||
sodipodi:nodetypes="cccc"
|
||||
style="fill:#424242;fill-opacity:1" />
|
||||
style="fill:#282828;fill-opacity:1" />
|
||||
<rect
|
||||
ry="2"
|
||||
y="4"
|
||||
|
@ -161,7 +161,7 @@
|
|||
height="20"
|
||||
width="20"
|
||||
id="rect2987"
|
||||
style="fill:#424242;fill-opacity:1" />
|
||||
style="fill:#282828;fill-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 24 KiB |
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
id="svg4"
|
||||
sodipodi:docname="open_pdf_black.svg"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14">
|
||||
<metadata
|
||||
id="metadata10">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="956"
|
||||
inkscape:window-height="1560"
|
||||
id="namedview6"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:cx="-6.1016949"
|
||||
inkscape:cy="12"
|
||||
inkscape:window-x="4800"
|
||||
inkscape:window-y="18"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
d="M12,10.5H13V13.5H12V10.5M7,11.5H8V10.5H7V11.5M20,6V18A2,2 0 0,1 18,20H6A2,2 0 0,1 4,18V6A2,2 0 0,1 6,4H18A2,2 0 0,1 20,6M9.5,10.5A1.5,1.5 0 0,0 8,9H5.5V15H7V13H8A1.5,1.5 0 0,0 9.5,11.5V10.5M14.5,10.5A1.5,1.5 0 0,0 13,9H10.5V15H13A1.5,1.5 0 0,0 14.5,13.5V10.5M18.5,9H15.5V15H17V13H18.5V11.5H17V10.5H18.5V9Z"
|
||||
id="path2"
|
||||
style="fill:#000000;fill-opacity:0.5411765" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
id="svg4"
|
||||
sodipodi:docname="open_pdf_white.svg"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14">
|
||||
<metadata
|
||||
id="metadata10">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="1600"
|
||||
id="namedview6"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:cx="-23.084746"
|
||||
inkscape:cy="11.084746"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
d="M12,10.5H13V13.5H12V10.5M7,11.5H8V10.5H7V11.5M20,6V18A2,2 0 0,1 18,20H6A2,2 0 0,1 4,18V6A2,2 0 0,1 6,4H18A2,2 0 0,1 20,6M9.5,10.5A1.5,1.5 0 0,0 8,9H5.5V15H7V13H8A1.5,1.5 0 0,0 9.5,11.5V10.5M14.5,10.5A1.5,1.5 0 0,0 13,9H10.5V15H13A1.5,1.5 0 0,0 14.5,13.5V10.5M18.5,9H15.5V15H17V13H18.5V11.5H17V10.5H18.5V9Z"
|
||||
id="path2"
|
||||
style="fill:#ffffff;fill-opacity:0.69803923" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -23,9 +23,11 @@ images = {
|
|||
'play_gif_white.svg' => ['play_gif_white', 128],
|
||||
'play_video_black.svg' => ['play_video_black', 128],
|
||||
'play_gif_black.svg' => ['play_gif_black', 128],
|
||||
'open_pdf_black.svg' => ['open_pdf_black', 128],
|
||||
'open_pdf_white.svg' => ['open_pdf_white', 128],
|
||||
'conversations_mono.svg' => ['conversations/ic_notification', 24],
|
||||
'quicksy_mono.svg' => ['quicksy/ic_notification', 24],
|
||||
'ic_received_indicator.svg' => ['ic_received_indicator', 12],
|
||||
'flip_camera_android-black-24dp.svg' => ['ic_flip_camera_android_black_24dp', 24],
|
||||
'ic_send_text_offline.svg' => ['ic_send_text_offline', 36],
|
||||
'ic_send_text_offline_white.svg' => ['ic_send_text_offline_white', 36],
|
||||
'ic_send_text_online.svg' => ['ic_send_text_online', 36],
|
||||
|
@ -117,7 +119,7 @@ images.each do |source_filename, settings|
|
|||
else
|
||||
path = "../src/#{output_parts[0]}/res/drawable-#{resolution}/#{output_parts[1]}.png"
|
||||
end
|
||||
execute_cmd "#{inkscape} -f #{source_filename} -z -C -w #{width} -h #{height} -e #{path}"
|
||||
execute_cmd "#{inkscape} #{source_filename} -C -w #{width} -h #{height} -o #{path}"
|
||||
|
||||
top = []
|
||||
right = []
|
||||
|
|
126
build.gradle
|
@ -3,10 +3,10 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
classpath 'com.android.tools.build:gradle:7.0.3'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,8 @@ apply plugin: 'com.android.application'
|
|||
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
configurations {
|
||||
|
@ -24,37 +24,36 @@ configurations {
|
|||
conversationsFreeCompatImplementation
|
||||
conversationsPlaystoreCompatImplementation
|
||||
conversationsPlaystoreSystemImplementation
|
||||
quicksyPlaystoreCompatImplementation
|
||||
quicksyPlaystoreSystemImplementation
|
||||
quicksyFreeCompatImplementation
|
||||
quicksyImplementation
|
||||
}
|
||||
|
||||
ext {
|
||||
supportLibVersion = '28.0.0'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
playstoreImplementation('com.google.firebase:firebase-messaging:17.3.4') {
|
||||
implementation 'androidx.viewpager:viewpager:1.0.0'
|
||||
|
||||
playstoreImplementation('com.google.firebase:firebase-messaging:22.0.0') {
|
||||
exclude group: 'com.google.firebase', module: 'firebase-core'
|
||||
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
||||
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
||||
}
|
||||
conversationsPlaystoreCompatImplementation("com.android.installreferrer:installreferrer:1.1")
|
||||
conversationsPlaystoreSystemImplementation("com.android.installreferrer:installreferrer:1.1")
|
||||
conversationsPlaystoreCompatImplementation("com.android.installreferrer:installreferrer:2.2")
|
||||
conversationsPlaystoreSystemImplementation("com.android.installreferrer:installreferrer:2.2")
|
||||
quicksyPlaystoreCompatImplementation 'com.google.android.gms:play-services-auth-api-phone:17.5.1'
|
||||
quicksyPlaystoreSystemImplementation 'com.google.android.gms:play-services-auth-api-phone:17.5.1'
|
||||
implementation 'org.sufficientlysecure:openpgp-api:10.0'
|
||||
implementation('com.theartofdev.edmodo:android-image-cropper:2.7.+') {
|
||||
exclude group: 'com.android.support', module: 'appcompat-v7'
|
||||
exclude group: 'com.android.support', module: 'exifinterface'
|
||||
}
|
||||
implementation "com.android.support:support-v13:$supportLibVersion"
|
||||
implementation "com.android.support:appcompat-v7:$supportLibVersion"
|
||||
implementation "com.android.support:exifinterface:$supportLibVersion"
|
||||
implementation "com.android.support:cardview-v7:$supportLibVersion"
|
||||
implementation "com.android.support:support-emoji:$supportLibVersion"
|
||||
implementation "com.android.support:design:$supportLibVersion"
|
||||
compatImplementation "com.android.support:support-emoji-appcompat:$supportLibVersion"
|
||||
conversationsFreeCompatImplementation "com.android.support:support-emoji-bundled:$supportLibVersion"
|
||||
quicksyFreeCompatImplementation "com.android.support:support-emoji-bundled:$supportLibVersion"
|
||||
implementation 'org.bouncycastle:bcmail-jdk15on:1.58'
|
||||
implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.3'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
implementation 'androidx.emoji:emoji:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
compatImplementation 'androidx.emoji:emoji-appcompat:1.1.0'
|
||||
conversationsFreeCompatImplementation 'androidx.emoji:emoji-bundled:1.1.0'
|
||||
quicksyFreeCompatImplementation 'androidx.emoji:emoji-bundled:1.1.0'
|
||||
implementation 'org.bouncycastle:bcmail-jdk15on:1.64'
|
||||
//zxing stopped supporting Java 7 so we have to stick with 3.3.3
|
||||
//https://github.com/zxing/zxing/issues/1170
|
||||
implementation 'com.google.zxing:core:3.3.3'
|
||||
|
@ -63,52 +62,56 @@ dependencies {
|
|||
implementation 'org.whispersystems:signal-protocol-java:2.6.2'
|
||||
implementation 'com.makeramen:roundedimageview:2.3.0'
|
||||
implementation "com.wefika:flowlayout:0.4.1"
|
||||
implementation 'net.ypresto.androidtranscoder:android-transcoder:0.3.0'
|
||||
implementation project(':libs:xmpp-addr')
|
||||
implementation 'org.osmdroid:osmdroid-android:6.1.5'
|
||||
implementation 'com.otaliastudios:transcoder:0.10.4'
|
||||
|
||||
implementation 'org.jxmpp:jxmpp-jid:1.0.2'
|
||||
implementation 'org.osmdroid:osmdroid-android:6.1.10'
|
||||
implementation 'org.hsluv:hsluv:0.2'
|
||||
implementation 'org.conscrypt:conscrypt-android:2.2.1'
|
||||
implementation 'org.conscrypt:conscrypt-android:2.5.2'
|
||||
implementation 'me.drakeet.support:toastcompat:1.1.0'
|
||||
implementation "com.leinardi.android:speed-dial:2.0.1"
|
||||
//retrofit needs to stick with 2.6.x (https://github.com/square/retrofit/blob/master/CHANGELOG.md)
|
||||
implementation "com.squareup.retrofit2:retrofit:2.6.4"
|
||||
implementation "com.squareup.retrofit2:converter-gson:2.6.4"
|
||||
//okhttp needs to stick with 3.12.x
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.12.7'
|
||||
implementation 'com.google.guava:guava:27.1-android'
|
||||
quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.11.1'
|
||||
implementation "com.leinardi.android:speed-dial:3.2.0"
|
||||
|
||||
implementation "com.squareup.retrofit2:retrofit:2.9.0"
|
||||
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
|
||||
implementation "com.squareup.okhttp3:okhttp:4.9.2"
|
||||
|
||||
implementation 'com.google.guava:guava:30.1.1-android'
|
||||
quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.12.36'
|
||||
// implementation fileTree(include: ['libwebrtc-m92.aar'], dir: 'libs')
|
||||
implementation 'org.webrtc:google-webrtc:1.0.32006'
|
||||
}
|
||||
|
||||
ext {
|
||||
travisBuild = System.getenv("TRAVIS") == "true"
|
||||
preDexEnabled = System.getProperty("pre-dex", "true")
|
||||
abiCodes = ['armeabi-v7a': 1, 'x86': 2, 'x86_64': 3, 'arm64-v8a': 4]
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 28
|
||||
versionCode 362
|
||||
versionName "2.6.4"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 4202301
|
||||
versionName "2.10.2"
|
||||
archivesBaseName += "-$versionName"
|
||||
applicationId "eu.siacs.conversations"
|
||||
applicationId "eu.sum7.conversations"
|
||||
resValue "string", "applicationId", applicationId
|
||||
resValue "string", "app_name", "Conversations"
|
||||
buildConfigField "String", "LOGTAG", "\"conversations\""
|
||||
def appName = "Conv6ations"
|
||||
resValue "string", "app_name", appName
|
||||
buildConfigField "String", "APP_NAME", "\"$appName\"";
|
||||
}
|
||||
|
||||
|
||||
configurations {
|
||||
implementation.exclude group: 'org.jetbrains' , module:'annotations'
|
||||
}
|
||||
|
||||
dataBinding {
|
||||
enabled true
|
||||
}
|
||||
|
||||
dexOptions {
|
||||
// Skip pre-dexing when running on Travis CI or when disabled via -Dpre-dex=false.
|
||||
preDexLibraries = preDexEnabled && !travisBuild
|
||||
jumboMode true
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
|
@ -121,9 +124,11 @@ android {
|
|||
quicksy {
|
||||
dimension "mode"
|
||||
applicationId = "im.quicksy.client"
|
||||
resValue "string", "app_name", "Quicksy"
|
||||
resValue "string", "applicationId", applicationId
|
||||
buildConfigField "String", "LOGTAG", "\"quicksy\""
|
||||
|
||||
def appName = "Quicksy"
|
||||
resValue "string", "app_name", appName
|
||||
buildConfigField "String", "APP_NAME", "\"$appName\"";
|
||||
}
|
||||
|
||||
conversations {
|
||||
|
@ -132,31 +137,34 @@ android {
|
|||
|
||||
playstore {
|
||||
dimension "distribution"
|
||||
versionNameSuffix "+p"
|
||||
}
|
||||
free {
|
||||
dimension "distribution"
|
||||
versionNameSuffix "+f"
|
||||
}
|
||||
system {
|
||||
dimension "emoji"
|
||||
versionNameSuffix "s"
|
||||
}
|
||||
compat {
|
||||
dimension "emoji"
|
||||
versionNameSuffix "c"
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
quicksyFreeSystem {
|
||||
java {
|
||||
srcDir 'src/quicksyFree/java'
|
||||
}
|
||||
}
|
||||
quicksyFreeCompat {
|
||||
java {
|
||||
srcDir 'src/freeCompat/java'
|
||||
srcDir 'src/quicksyFree/java'
|
||||
}
|
||||
}
|
||||
quicksyPlaystoreCompat {
|
||||
java {
|
||||
srcDir 'src/playstoreCompat/java'
|
||||
srcDir 'src/quicksyPlaystore/java'
|
||||
}
|
||||
res {
|
||||
srcDir 'src/playstoreCompat/res'
|
||||
|
@ -164,6 +172,9 @@ android {
|
|||
}
|
||||
}
|
||||
quicksyPlaystoreSystem {
|
||||
java {
|
||||
srcDir 'src/quicksyPlaystore/java'
|
||||
}
|
||||
res {
|
||||
srcDir 'src/quicksyPlaystore/res'
|
||||
}
|
||||
|
@ -204,13 +215,11 @@ android {
|
|||
shrinkResources true
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
versionNameSuffix "r"
|
||||
}
|
||||
debug {
|
||||
shrinkResources true
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
versionNameSuffix "d"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,7 +240,8 @@ android {
|
|||
}
|
||||
|
||||
lintOptions {
|
||||
disable 'ExtraTranslation', 'MissingTranslation', 'InvalidPackage', 'MissingQuantity', 'AppCompatResource'
|
||||
disable 'MissingTranslation', 'InvalidPackage', 'AppCompatResource'
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="../style.xsl" type="text/xsl"?>
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<Project xmlns="http://usefulinc.com/ns/doap#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:xmpp="https://linkmauve.fr/ns/xmpp-doap#">
|
||||
<Project xmlns="http://usefulinc.com/ns/doap#"
|
||||
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||
xmlns:xmpp="https://linkmauve.fr/ns/xmpp-doap#"
|
||||
xmlns:schema="https://schema.org/">
|
||||
<name>Conversations</name>
|
||||
|
||||
<created>2014-01-14</created>
|
||||
|
@ -12,23 +15,31 @@
|
|||
|
||||
<homepage rdf:resource="https://conversations.im/"/>
|
||||
<download-page rdf:resource="https://play.google.com/store/apps/details?id=eu.siacs.conversations"/>
|
||||
<bug-database rdf:resource="https://github.com/siacs/Conversations/issues"/>
|
||||
<bug-database rdf:resource="https://github.com/iNPUTmice/Conversations/issues"/>
|
||||
<!-- See https://github.com/ewilderj/doap/issues/53 -->
|
||||
<developer-forum rdf:resource="xmpp:conversations@siacs.conference.eu?join"/>
|
||||
<support-forum rdf:resource="xmpp:conversations@siacs.conference.eu?join"/>
|
||||
|
||||
<license rdf:resource="https://github.com/siacs/Conversations/blob/master/LICENSE"/>
|
||||
<license rdf:resource="https://github.com/iNPUTmice/Conversations/blob/master/LICENSE"/>
|
||||
|
||||
<!-- See https://github.com/ewilderj/doap/issues/49 -->
|
||||
<language>en</language>
|
||||
|
||||
<logo rdf:resource="https://raw.githubusercontent.com/siacs/Conversations/master/doap.rdf"/>
|
||||
<schema:logo rdf:resource="https://raw.githubusercontent.com/iNPUTmice/Conversations/master/art/ic_launcher.svg"/>
|
||||
<schema:screenshot rdf:resource='https://raw.githubusercontent.com/iNPUTmice/Conversations/master/fastlane/metadata/android/en-US/images/phoneScreenshots/01.png'/>
|
||||
<schema:screenshot rdf:resource='https://raw.githubusercontent.com/iNPUTmice/Conversations/master/fastlane/metadata/android/en-US/images/phoneScreenshots/02.png'/>
|
||||
<schema:screenshot rdf:resource='https://raw.githubusercontent.com/iNPUTmice/Conversations/master/fastlane/metadata/android/en-US/images/phoneScreenshots/03.png'/>
|
||||
<schema:screenshot rdf:resource='https://raw.githubusercontent.com/iNPUTmice/Conversations/master/fastlane/metadata/android/en-US/images/phoneScreenshots/04.png'/>
|
||||
<schema:screenshot rdf:resource='https://raw.githubusercontent.com/iNPUTmice/Conversations/master/fastlane/metadata/android/en-US/images/phoneScreenshots/05.png'/>
|
||||
<schema:screenshot rdf:resource='https://raw.githubusercontent.com/iNPUTmice/Conversations/master/fastlane/metadata/android/en-US/images/phoneScreenshots/06.png'/>
|
||||
<schema:screenshot rdf:resource='https://raw.githubusercontent.com/iNPUTmice/Conversations/master/fastlane/metadata/android/en-US/images/phoneScreenshots/07.png'/>
|
||||
<schema:screenshot rdf:resource='https://raw.githubusercontent.com/iNPUTmice/Conversations/master/fastlane/metadata/android/en-US/images/phoneScreenshots/08.png'/>
|
||||
<schema:screenshot rdf:resource='https://raw.githubusercontent.com/iNPUTmice/Conversations/master/fastlane/metadata/android/en-US/images/phoneScreenshots/09.png'/>
|
||||
|
||||
<programming-language>Java</programming-language>
|
||||
|
||||
<os>Android</os>
|
||||
|
||||
<!-- TODO: Categories are URIs, find a better location for them. -->
|
||||
<category rdf:resource="https://linkmauve.fr/ns/xmpp-doap#category-xmpp"/>
|
||||
<category rdf:resource="https://linkmauve.fr/ns/xmpp-doap#category-jabber"/>
|
||||
<category rdf:resource="https://linkmauve.fr/ns/xmpp-doap#category-client"/>
|
||||
|
@ -42,8 +53,8 @@
|
|||
|
||||
<repository>
|
||||
<GitRepository>
|
||||
<browse rdf:resource="https://github.com/siacs/Conversations"/>
|
||||
<location rdf:resource="https://github.com/siacs/Conversations.git"/>
|
||||
<browse rdf:resource="https://github.com/iNPUTmice/Conversations"/>
|
||||
<location rdf:resource="https://github.com/iNPUTmice/Conversations.git"/>
|
||||
</GitRepository>
|
||||
</repository>
|
||||
|
||||
|
@ -80,6 +91,28 @@
|
|||
<xmpp:version>1.1</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0048.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.1</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0049.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.2</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0054.html"/>
|
||||
<xmpp:status>partial</xmpp:status>
|
||||
<xmpp:version>1.2</xmpp:version>
|
||||
<xmpp:note xml:lang='en'>Avatars only</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0084.html"/>
|
||||
|
@ -108,6 +141,14 @@
|
|||
<xmpp:version>1.5.1</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0153.html"/>
|
||||
<xmpp:status>partial</xmpp:status>
|
||||
<xmpp:version>1.1</xmpp:version>
|
||||
<xmpp:note xml:lang='en'>Read only. Publication via XEP-0398</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0163.html"/>
|
||||
|
@ -121,7 +162,14 @@
|
|||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0166.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.1.2</xmpp:version>
|
||||
<xmpp:note>File transfer only</xmpp:note>
|
||||
<xmpp:note>File transfer + A/V calls</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0167.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.2.1</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
|
@ -132,6 +180,13 @@
|
|||
<xmpp:note>read only</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0176.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.1</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0184.html"/>
|
||||
|
@ -160,6 +215,27 @@
|
|||
<xmpp:version>2.0.1</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0199.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>2.0.1</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0215.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>0.7</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0223.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.1</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0234.html"/>
|
||||
|
@ -211,11 +287,25 @@
|
|||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0308.html"/>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0293.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.0.1</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0294.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.0</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0308.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.2.0</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0313.html"/>
|
||||
|
@ -231,6 +321,13 @@
|
|||
<xmpp:note>opt-in</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0320.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.0.0</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0333.html"/>
|
||||
|
@ -238,6 +335,20 @@
|
|||
<xmpp:version>0.3</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0338.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.0.0</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0339.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.0.0</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0352.html"/>
|
||||
|
@ -245,6 +356,13 @@
|
|||
<xmpp:version>0.3.0</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0353.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>0.3.0</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0357.html"/>
|
||||
|
@ -253,6 +371,13 @@
|
|||
<xmpp:note>Only available in the version distributed over Google Play</xmpp:note>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0363.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>1.0.0</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0368.html"/>
|
||||
|
@ -328,12 +453,19 @@
|
|||
<xmpp:version>0.2.0</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
<implements>
|
||||
<xmpp:SupportedXep>
|
||||
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0454.html"/>
|
||||
<xmpp:status>complete</xmpp:status>
|
||||
<xmpp:version>0.1.0</xmpp:version>
|
||||
</xmpp:SupportedXep>
|
||||
</implements>
|
||||
|
||||
<release>
|
||||
<Version>
|
||||
<revision>2.5.8</revision>
|
||||
<created>2019-09-12</created>
|
||||
<file-release rdf:resource="https://github.com/siacs/Conversations/archive/2.5.8.tar.gz"/>
|
||||
<revision>2.9.13</revision>
|
||||
<created>2021-05-03</created>
|
||||
<file-release rdf:resource="https://github.com/iNPUTmice/Conversations/archive/2.9.13.tar.gz"/>
|
||||
</Version>
|
||||
</release>
|
||||
</Project>
|
|
@ -1,25 +0,0 @@
|
|||
Conversations is a messenger for the next decade. Based on already established
|
||||
internet standards that have been around for over ten years Conversations isn’t
|
||||
trying to replace current commercial messengers. It will simply outlive them.
|
||||
Commercial, closed source products are coming and going. 15 years ago we had ICQ
|
||||
which was replaced by Skype. MySpace was replaced by Facebook. WhatsApp and
|
||||
Hangouts will disappear soon. Internet standards however stick around. People
|
||||
are still using IRC and e-mail even though these protocols have been around for
|
||||
decades. Utilizing proven standards doesn’t mean one can not evolve. GMail has
|
||||
revolutionized the way we look at e-mail. Firefox and Chrome have changed the
|
||||
way we use the Web. Conversations will change the way we look at instant
|
||||
messaging. Being less obtrusive than a telephone call instant messaging has
|
||||
always played an important role in modern society. Conversations will show that
|
||||
instant messaging can be fast, reliable and private. Conversations will not
|
||||
force its security and privacy aspects upon the user. For those willing to use
|
||||
encryption Conversations will make it as uncomplicated as possible. However
|
||||
Conversations is aware that end-to-end encryption by the very principle isn’t
|
||||
trivial. Instead of trying the impossible and making encryption easier than
|
||||
comparing a fingerprint Conversations will try to educate the willing user and
|
||||
explain the necessary steps and the reasons behind them. Those unwilling to
|
||||
learn about encryption will still be protected by the design principals of
|
||||
Conversations. Conversations will simply not share or generate certain
|
||||
information for example by encouraging the use of federated servers.
|
||||
Conversations will always utilize the best available standards for encryption
|
||||
and media encoding instead of reinventing the wheel. However it isn’t afraid to
|
||||
break with behavior patterns that have been proven ineffective.
|
32
docs/XEPs.md
|
@ -1,32 +0,0 @@
|
|||
* XEP-0027: Current Jabber OpenPGP Usage
|
||||
* XEP-0030: Service Discovery
|
||||
* XEP-0045: Multi-User Chat
|
||||
* XEP-0048: Bookmarks
|
||||
* XEP-0084: User Avatar
|
||||
* XEP-0085: Chat State Notifications
|
||||
* XEP-0092: Software Version
|
||||
* XEP-0115: Entity Capabilities
|
||||
* XEP-0163: Personal Eventing Protocol (avatars and nicks)
|
||||
* XEP-0166: Jingle (only used for file transfer)
|
||||
* XEP-0172: User Nickname
|
||||
* XEP-0184: Message Delivery Receipts (reply only)
|
||||
* XEP-0191: Blocking command
|
||||
* XEP-0198: Stream Management
|
||||
* XEP-0199: XMPP Ping
|
||||
* XEP-0234: Jingle File Transfer
|
||||
* XEP-0237: Roster Versioning
|
||||
* XEP-0245: The /me Command
|
||||
* XEP-0249: Direct MUC Invitations (receiving only)
|
||||
* XEP-0260: Jingle SOCKS5 Bytestreams Transport Method
|
||||
* XEP-0261: Jingle In-Band Bytestreams Transport Method
|
||||
* XEP-0280: Message Carbons
|
||||
* XEP-0308: Last Message Correction
|
||||
* XEP-0313: Message Archive Management
|
||||
* XEP-0319: Last User Interaction in Presence
|
||||
* XEP-0333: Chat Markers
|
||||
* XEP-0352: Client State Indication
|
||||
* XEP-0357: Push Notifications
|
||||
* XEP-0363: HTTP File Upload
|
||||
* XEP-0368: SRV records for XMPP over TLS
|
||||
* XEP-0377: Spam Reporting
|
||||
* XEP-0384: OMEMO Encryption
|
|
@ -1,97 +0,0 @@
|
|||
Observations on implementing XMPP
|
||||
=================================
|
||||
After spending the last two and a half month basically writing my own XMPP
|
||||
library from scratch I decided to share some of the observations I made in the
|
||||
process. In part this article can be seen as a response to a blog post made by
|
||||
Dr. Ing. Georg Lukas. The blog post introduces a couple of XEP (XMPP Extensions)
|
||||
which make the life on mobile devices a lot easier but states that they are
|
||||
currently very few implementations of those XEPs. So I went ahead and
|
||||
implemented all of them in my Android XMPP client.
|
||||
|
||||
### General observations
|
||||
The first thing I noticed is that XMPP is actually okish designed. If you were
|
||||
to design a new chat protocol today you probably wouldn’t choose XML again
|
||||
however the protocol basically consists of only three different packages which
|
||||
are quickly hidden under some sort of abstraction layer within your library.
|
||||
Getting from zero to sending messages to other users actually was very simple
|
||||
and straight forward. But then came the XEPs.
|
||||
|
||||
### Multi-User Chat
|
||||
The first one was XEP-0045 Multi-User Chat. This is the one XEP of the XEPs I’m
|
||||
going to mention in my article which is actually wildly adopted. Most clients
|
||||
and servers I know of support MUC. However the level of completeness varies.
|
||||
MUC actually introduces access and permission roles which are far more complex
|
||||
than what some of us are used to from IRC but a lot of clients just don’t
|
||||
implement them. I’m not implementing them myself (at least for now) because I
|
||||
somewhat doubt that someone would actually use them (however this might be some
|
||||
sort of chicken or egg problem). I did find some strange bugs though which might
|
||||
be interesting for other library developers. In theory a MUC server
|
||||
implementation can allow a single user (same jid) to join a conference room
|
||||
multiple times with the same nick from different clients. This means if someone
|
||||
wants to participate in a conference from two different devices (mobile and
|
||||
desktop for example) one wouldn’t have to name oneself `userDesktop` and
|
||||
`userMobile` but just `user`. Both ejabberd and prosody support this but with
|
||||
strange side effects. Prosody for example doesn’t allow a user to change its
|
||||
name once two clients are “merged” by having the same nick.
|
||||
|
||||
### Carbons and Stream Management
|
||||
Two of the other XEPs Lukas mentions — Carbons (XEP-0280) and Stream Management
|
||||
(XEP-0198) — were actually fairly easy to implement. The only challenges were to
|
||||
find a server to support them (I ended up running my own Prosody server) and a
|
||||
desktop client to test them with. For carbons there is a patched Mcabber version
|
||||
and Gajim. After implementing stream management I had very good results on my
|
||||
mobile device. I had sessions running for up to 24 hours with a walking outside,
|
||||
loosing mobile coverage for a few minutes and so on. The only limitation was
|
||||
that I had to keep on developing and reinstalling my app.
|
||||
|
||||
### Off the record
|
||||
And then came OTR... This is were I spend the most time debugging stuff and
|
||||
trying to get things right and compatible with other clients. This is the part
|
||||
were I want to help other developers not to make the same mistakes and maybe
|
||||
come to some sort of consent among XMPP developers to ultimately increase the
|
||||
interoperability. OTR has some down sides which make it difficult or at times
|
||||
even dangerous to implement within XMPP. First of all it is a synchronous
|
||||
protocol which is tunneled through a different protocol (XMPP). Synchronous
|
||||
means — among other things — auto replies. (An OTR session begins with “hi I’m
|
||||
speaking otr give me your key” “ok cool here is my key”) And auto replies — we
|
||||
know that since the first time an out of office auto responder went postal — are
|
||||
dangerous. Things really start to get messy when you use one of the best
|
||||
features of XMPP — multiple clients. The way XMPP works is that clients are
|
||||
encouraged to send their messages to the raw jid and let the server decide what
|
||||
full jid the messages are routed to. If in doubt even all of them. So what
|
||||
happens when Alice sends a start-otr-message to Bobs raw jid? Bob receives the
|
||||
message on his notebook as well as his cell phone. Both of them answer. Alice
|
||||
gets two different replies. Shit explodes. Even if Alice sends the message to
|
||||
bob/notebook chances are that Bob has carbon messages enabled and still receives
|
||||
the messages on both devices. Now assuming that Bobs client is clever enough not
|
||||
to auto reply to carbonated messages Bob/cellphone will still end up with a lot
|
||||
of garbage messages. (Essentially the entire conversation between Alice and
|
||||
Bob/notebook but unreadable of course) Therefor it should be good practice to
|
||||
tag OTR messages as both private and no-copy (private is part of the carbons
|
||||
XEP, no-copy is a general hint). I found that prosody for some reasons doesn’t
|
||||
honor the private tag on outgoing messages. While this is easily fixed I presume
|
||||
that having both the private and the no-copy tag will make it more compatible
|
||||
with servers or clients I don’t know about yet.
|
||||
|
||||
#### Rules to follow when implementing OTR
|
||||
To summarize my observations on implementing OTR in XMPP let me make the
|
||||
following three statements.
|
||||
|
||||
1. While it is good practice for unencrypted messages to be send to the raw jid
|
||||
and have the receiving server or user decide how they should be routed OTR
|
||||
messages must be send to a specific resource. To make this work the user should
|
||||
be given the option to select the presence (which can be assisted with some
|
||||
educated guessing by the client based on previous messages). Furthermore a
|
||||
client should encourage a user to choose meaningful presences instead of the
|
||||
clients name or even random ones. Something like `/mobile`, `/notebook`,
|
||||
`/desktop` is a greater assist to any one who wants to start an otr session then
|
||||
`/Gajim`, `/mcabber` or `/pidgin`.
|
||||
|
||||
2. Messages should be tagged private and no-copy to avoid unnecessary traffic or
|
||||
otr error loops with faulty clients. This tagging should be done even if your
|
||||
own client doesn’t support carbons.
|
||||
|
||||
3. When dealing with “legacy clients” — meaning clients which don’t follow my
|
||||
advise — a client should be extra careful not to create message loops. This
|
||||
means to not respond with otr errors if a client is not 100% sure it is the only
|
||||
client which received the message
|
|
@ -1,4 +0,0 @@
|
|||
* Introduce expert setting to perform channel discovery on local server instead of search.jabber.network
|
||||
* Enable delivery check marks by default and remove setting
|
||||
* Enable ‘Send button indicates status’ by default and remove setting
|
||||
* Move Backup and Foreground Service settings to main screen
|
|
@ -1,3 +0,0 @@
|
|||
* fixes for Jingle IBB file transfer
|
||||
* fixes for repeated corrections filling up the database
|
||||
* switched to Last Message Correction v1.1
|
|
@ -1,4 +0,0 @@
|
|||
* let users set their own nick name
|
||||
* resume download of OMEMO encrypted files
|
||||
* Channels now use '#' as symbol in avatar
|
||||
* Quicksy uses 'always' as OMEMO encryption default (hides lock icon)
|
|
@ -1 +0,0 @@
|
|||
* Support for ?register and ?register;preauth XMPP uri parameters
|
|
@ -1,47 +0,0 @@
|
|||
Easy to use, reliable, battery friendly. With built-in support for images, group chats and e2e encryption.
|
||||
|
||||
Design principles:
|
||||
|
||||
* Be as beautiful and easy to use as possible without sacrificing security or privacy
|
||||
* Rely on existing, well established protocols
|
||||
* Do not require a Google Account or specifically Google Cloud Messaging (GCM)
|
||||
* Require as few permissions as possible
|
||||
|
||||
Features:
|
||||
|
||||
* End-to-end encryption with either <a href="http://conversations.im/omemo/">OMEMO</a> or <a href="http://openpgp.org/about/">OpenPGP</a>
|
||||
* Sending and receiving images
|
||||
* Intuitive UI that follows Android Design guidelines
|
||||
* Pictures / Avatars for your Contacts
|
||||
* Syncs with desktop client
|
||||
* Conferences (with support for bookmarks)
|
||||
* Address book integration
|
||||
* Multiple accounts / unified inbox
|
||||
* Very low impact on battery life
|
||||
|
||||
Conversations makes it very easy to create an account on the conversations.im
|
||||
server. Using that server comes with an annual fee of 8 Euro after a 6 month
|
||||
trial period. However Conversations will work with any other XMPP server as
|
||||
well. A lot of XMPP servers are run by volunteers and are free of charge.
|
||||
|
||||
XMPP Features:
|
||||
|
||||
Conversations works with every XMPP server out there. However XMPP is an
|
||||
extensible protocol. These extensions are standardized as well in so called
|
||||
XEP’s. Conversations supports a couple of those to make the overall user
|
||||
experience better. There is a chance that your current XMPP server does not
|
||||
support these extensions. Therefore to get the most out of Conversations you
|
||||
should consider either switching to an XMPP server that does or - even better -
|
||||
run your own XMPP server for you and your friends.
|
||||
|
||||
These XEPs are - as of now:
|
||||
|
||||
* XEP-0065: SOCKS5 Bytestreams (or mod_proxy65). Will be used to transfer files if both parties are behind a firewall (NAT).
|
||||
* XEP-0163: Personal Eventing Protocol for avatars
|
||||
* XEP-0191: Blocking command lets you blacklist spammers or block contacts without removing them from your roster.
|
||||
* XEP-0198: Stream Management allows XMPP to survive small network outages and changes of the underlying TCP connection.
|
||||
* XEP-0280: Message Carbons which automatically syncs the messages you send to your desktop client and thus allows you to switch seamlessly from your mobile client to your desktop client and back within one conversation.
|
||||
* XEP-0237: Roster Versioning mainly to save bandwidth on poor mobile connections
|
||||
* XEP-0313: Message Archive Management synchronize message history with the server. Catch up with messages that were sent while Conversations was offline.
|
||||
* XEP-0352: Client State Indication lets the server know whether or not Conversations is in the background. Allows the server to save bandwidth by withholding unimportant packages.
|
||||
* XEP-0363: HTTP File Upload allows you to share files in conferences and with offline contacts. Requires an additional component on your server.
|
Before Width: | Height: | Size: 414 KiB |
Before Width: | Height: | Size: 449 KiB |
Before Width: | Height: | Size: 475 KiB |
Before Width: | Height: | Size: 339 KiB |
Before Width: | Height: | Size: 284 KiB |
Before Width: | Height: | Size: 168 KiB |
Before Width: | Height: | Size: 418 KiB |
Before Width: | Height: | Size: 391 KiB |
Before Width: | Height: | Size: 382 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 372 KiB |
|
@ -1 +0,0 @@
|
|||
An encrypted, user friendly XMPP instant messaging client optimized for mobile
|
|
@ -0,0 +1,3 @@
|
|||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
org.gradle.jvmargs=-Xmx4096m
|
|
@ -1,6 +1,6 @@
|
|||
#Wed Apr 24 10:50:09 CEST 2019
|
||||
#Sat Nov 14 09:59:55 CET 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/build
|
|
@ -1,14 +0,0 @@
|
|||
apply plugin: 'java-library'
|
||||
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'rocks.xmpp:precis:1.0.0'
|
||||
}
|
||||
|
||||
sourceCompatibility = "8"
|
||||
targetCompatibility = "8"
|
|
@ -1,179 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2017 Christian Schudt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rocks.xmpp.addr;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Abstract Jid implementation for both full and bare JIDs.
|
||||
*
|
||||
* @author Christian Schudt
|
||||
*/
|
||||
abstract class AbstractJid implements Jid {
|
||||
|
||||
/**
|
||||
* Checks if the JID is a full JID.
|
||||
* <blockquote>
|
||||
* <p>The term "full JID" refers to an XMPP address of the form <localpart@domainpart/resourcepart> (for a particular authorized client or device associated with an account) or of the form <domainpart/resourcepart> (for a particular resource or script associated with a server).</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return True, if the JID is a full JID; otherwise false.
|
||||
*/
|
||||
@Override
|
||||
public final boolean isFullJid() {
|
||||
return getResource() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the JID is a bare JID.
|
||||
* <blockquote>
|
||||
* <p>The term "bare JID" refers to an XMPP address of the form <localpart@domainpart> (for an account at a server) or of the form <domainpart> (for a server).</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return True, if the JID is a bare JID; otherwise false.
|
||||
*/
|
||||
@Override
|
||||
public final boolean isBareJid() {
|
||||
return getResource() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isDomainJid() {
|
||||
return getLocal() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof Jid)) {
|
||||
return false;
|
||||
}
|
||||
Jid other = (Jid) o;
|
||||
|
||||
return (getLocal() == other.getLocal() || getLocal() != null && getLocal().equals(other.getLocal()))
|
||||
&& (getDomain() == other.getDomain() || getDomain() != null && getDomain().equals(other.getDomain()))
|
||||
&& (getResource() == other.getResource() || getResource() != null && getResource().equals(other.getResource()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return Arrays.hashCode(new String[]{getLocal(), getDomain(), getResource()});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this JID with another JID. First domain parts are compared. If these are equal, local parts are compared
|
||||
* and if these are equal, too, resource parts are compared.
|
||||
*
|
||||
* @param o The other JID.
|
||||
* @return The comparison result.
|
||||
*/
|
||||
@Override
|
||||
public final int compareTo(Jid o) {
|
||||
|
||||
if (this == o) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (o != null) {
|
||||
final Collator collator = Collator.getInstance();
|
||||
int result;
|
||||
// First compare domain parts.
|
||||
if (getDomain() != null) {
|
||||
result = o.getDomain() != null ? collator.compare(getDomain(), o.getDomain()) : -1;
|
||||
} else {
|
||||
result = o.getDomain() != null ? 1 : 0;
|
||||
}
|
||||
// If the domains are equal, compare local parts.
|
||||
if (result == 0) {
|
||||
if (getLocal() != null) {
|
||||
// If this local part is not null, but the other is null, move this down (1).
|
||||
result = o.getLocal() != null ? collator.compare(getLocal(), o.getLocal()) : 1;
|
||||
} else {
|
||||
// If this local part is null, but the other is not, move this up (-1).
|
||||
result = o.getLocal() != null ? -1 : 0;
|
||||
}
|
||||
}
|
||||
// If the local parts are equal, compare resource parts.
|
||||
if (result == 0) {
|
||||
if (getResource() != null) {
|
||||
// If this resource part is not null, but the other is null, move this down (1).
|
||||
return o.getResource() != null ? collator.compare(getResource(), o.getResource()) : 1;
|
||||
} else {
|
||||
// If this resource part is null, but the other is not, move this up (-1).
|
||||
return o.getResource() != null ? -1 : 0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int length() {
|
||||
return toString().length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final char charAt(int index) {
|
||||
return toString().charAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final CharSequence subSequence(int start, int end) {
|
||||
return toString().subSequence(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JID in its string representation, i.e. [ localpart "@" ] domainpart [ "/" resourcepart ].
|
||||
*
|
||||
* @return The JID.
|
||||
* @see #toEscapedString()
|
||||
*/
|
||||
@Override
|
||||
public final String toString() {
|
||||
return toString(getLocal(), getDomain(), getResource());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toEscapedString() {
|
||||
return toString(getEscapedLocal(), getDomain(), getResource());
|
||||
}
|
||||
|
||||
static String toString(String local, String domain, String resource) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (local != null) {
|
||||
sb.append(local).append('@');
|
||||
}
|
||||
sb.append(domain);
|
||||
if (resource != null) {
|
||||
sb.append('/').append(resource);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -1,498 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2017 Christian Schudt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rocks.xmpp.addr;
|
||||
|
||||
import rocks.xmpp.precis.PrecisProfile;
|
||||
import rocks.xmpp.precis.PrecisProfiles;
|
||||
import rocks.xmpp.util.cache.LruCache;
|
||||
|
||||
import java.net.IDN;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.Normalizer;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* The implementation of the JID as described in <a href="https://tools.ietf.org/html/rfc7622">Extensible Messaging and Presence Protocol (XMPP): Address Format</a>.
|
||||
* <p>
|
||||
* This class is thread-safe and immutable.
|
||||
*
|
||||
* @author Christian Schudt
|
||||
* @see <a href="https://tools.ietf.org/html/rfc7622">RFC 7622 - Extensible Messaging and Presence Protocol (XMPP): Address Format</a>
|
||||
*/
|
||||
final class FullJid extends AbstractJid {
|
||||
|
||||
/**
|
||||
* Escapes all disallowed characters and also backslash, when followed by a defined hex code for escaping. See 4. Business Rules.
|
||||
*/
|
||||
private static final Pattern ESCAPE_PATTERN = Pattern.compile("[ \"&'/:<>@]|\\\\(?=20|22|26|27|2f|3a|3c|3e|40|5c)");
|
||||
|
||||
private static final Pattern UNESCAPE_PATTERN = Pattern.compile("\\\\(20|22|26|27|2f|3a|3c|3e|40|5c)");
|
||||
|
||||
private static final Pattern JID = Pattern.compile("^((.*?)@)?([^/@]+)(/(.*))?$");
|
||||
|
||||
private static final IDNProfile IDN_PROFILE = new IDNProfile();
|
||||
|
||||
/**
|
||||
* Whenever dots are used as label separators, the following characters MUST be recognized as dots: U+002E (full stop), U+3002 (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61 (halfwidth ideographic full stop).
|
||||
*/
|
||||
private static final String DOTS = "[.\u3002\uFF0E\uFF61]";
|
||||
|
||||
/**
|
||||
* Label separators for domain labels, which should be mapped to "." (dot): IDEOGRAPHIC FULL STOP character (U+3002)
|
||||
*/
|
||||
private static final Pattern LABEL_SEPARATOR = Pattern.compile(DOTS);
|
||||
|
||||
private static final Pattern LABEL_SEPARATOR_FINAL = Pattern.compile(DOTS + "$");
|
||||
|
||||
/**
|
||||
* Caches the escaped JIDs.
|
||||
*/
|
||||
private static final Map<CharSequence, Jid> ESCAPED_CACHE = new LruCache<>(5000);
|
||||
|
||||
/**
|
||||
* Caches the unescaped JIDs.
|
||||
*/
|
||||
private static final Map<CharSequence, Jid> UNESCAPED_CACHE = new LruCache<>(5000);
|
||||
|
||||
private static final long serialVersionUID = -3824234106101731424L;
|
||||
|
||||
private final String escapedLocal;
|
||||
|
||||
private final String local;
|
||||
|
||||
private final String domain;
|
||||
|
||||
private final String resource;
|
||||
|
||||
private final Jid bareJid;
|
||||
|
||||
/**
|
||||
* Creates a full JID with local, domain and resource part.
|
||||
*
|
||||
* @param local The local part.
|
||||
* @param domain The domain part.
|
||||
* @param resource The resource part.
|
||||
*/
|
||||
FullJid(CharSequence local, CharSequence domain, CharSequence resource) {
|
||||
this(local, domain, resource, false, null);
|
||||
}
|
||||
|
||||
private FullJid(final CharSequence local, final CharSequence domain, final CharSequence resource, final boolean doUnescape, Jid bareJid) {
|
||||
final String enforcedLocalPart;
|
||||
final String enforcedDomainPart;
|
||||
final String enforcedResource;
|
||||
|
||||
final String unescapedLocalPart;
|
||||
|
||||
if (domain == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
if (doUnescape) {
|
||||
unescapedLocalPart = unescape(local);
|
||||
} else {
|
||||
unescapedLocalPart = local != null ? local.toString() : null;
|
||||
}
|
||||
|
||||
// Escape the local part, so that disallowed characters like the space characters pass the UsernameCaseMapped profile.
|
||||
final String escapedLocalPart = escape(unescapedLocalPart);
|
||||
|
||||
// If the domainpart includes a final character considered to be a label
|
||||
// separator (dot) by [RFC1034], this character MUST be stripped from
|
||||
// the domainpart before the JID of which it is a part is used for the
|
||||
// purpose of routing an XML stanza, comparing against another JID, or
|
||||
// constructing an XMPP URI or IRI [RFC5122]. In particular, such a
|
||||
// character MUST be stripped before any other canonicalization steps
|
||||
// are taken.
|
||||
// Also validate, that the domain name can be converted to ASCII, i.e. validate the domain name (e.g. must not start with "_").
|
||||
final String strDomain = IDN.toASCII(LABEL_SEPARATOR_FINAL.matcher(domain).replaceAll(""), IDN.USE_STD3_ASCII_RULES);
|
||||
enforcedLocalPart = escapedLocalPart != null ? PrecisProfiles.USERNAME_CASE_MAPPED.enforce(escapedLocalPart) : null;
|
||||
enforcedResource = resource != null ? PrecisProfiles.OPAQUE_STRING.enforce(resource) : null;
|
||||
// See https://tools.ietf.org/html/rfc5895#section-2
|
||||
enforcedDomainPart = IDN_PROFILE.enforce(strDomain);
|
||||
|
||||
validateLength(enforcedLocalPart, "local");
|
||||
validateLength(enforcedResource, "resource");
|
||||
validateDomain(strDomain);
|
||||
|
||||
this.local = unescape(enforcedLocalPart);
|
||||
this.escapedLocal = enforcedLocalPart;
|
||||
this.domain = enforcedDomainPart;
|
||||
this.resource = enforcedResource;
|
||||
if (bareJid != null) {
|
||||
this.bareJid = bareJid;
|
||||
} else {
|
||||
this.bareJid = isBareJid() ? this : new AbstractJid() {
|
||||
|
||||
@Override
|
||||
public Jid asBareJid() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jid withLocal(CharSequence local) {
|
||||
if (local == this.getLocal() || local != null && local.equals(this.getLocal())) {
|
||||
return this;
|
||||
}
|
||||
return new FullJid(local, getDomain(), getResource(), false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jid withResource(CharSequence resource) {
|
||||
if (resource == this.getResource() || resource != null && resource.equals(this.getResource())) {
|
||||
return this;
|
||||
}
|
||||
return new FullJid(getLocal(), getDomain(), resource, false, asBareJid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jid atSubdomain(CharSequence subdomain) {
|
||||
if (subdomain == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return new FullJid(getLocal(), subdomain + "." + getDomain(), getResource(), false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocal() {
|
||||
return FullJid.this.getLocal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEscapedLocal() {
|
||||
return FullJid.this.getEscapedLocal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDomain() {
|
||||
return FullJid.this.getDomain();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResource() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JID from a string. The format must be
|
||||
* <blockquote><p>[ localpart "@" ] domainpart [ "/" resourcepart ]</p></blockquote>
|
||||
*
|
||||
* @param jid The JID.
|
||||
* @param doUnescape If the jid parameter will be unescaped.
|
||||
* @return The JID.
|
||||
* @throws NullPointerException If the jid is null.
|
||||
* @throws IllegalArgumentException If the jid could not be parsed or is not valid.
|
||||
* @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
|
||||
*/
|
||||
static Jid of(String jid, final boolean doUnescape) {
|
||||
if (jid == null) {
|
||||
throw new NullPointerException("jid must not be null.");
|
||||
}
|
||||
|
||||
jid = jid.trim();
|
||||
|
||||
if (jid.isEmpty()) {
|
||||
throw new IllegalArgumentException("jid must not be empty.");
|
||||
}
|
||||
|
||||
Jid result;
|
||||
if (doUnescape) {
|
||||
result = UNESCAPED_CACHE.get(jid);
|
||||
} else {
|
||||
result = ESCAPED_CACHE.get(jid);
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Matcher matcher = JID.matcher(jid);
|
||||
if (matcher.matches()) {
|
||||
Jid jidValue = new FullJid(matcher.group(2), matcher.group(3), matcher.group(5), doUnescape, null);
|
||||
if (doUnescape) {
|
||||
UNESCAPED_CACHE.put(jid, jidValue);
|
||||
} else {
|
||||
ESCAPED_CACHE.put(jid, jidValue);
|
||||
}
|
||||
return jidValue;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Could not parse JID: " + jid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a local part. The characters {@code "&'/:<>@} (+ whitespace) are replaced with their respective escape characters.
|
||||
*
|
||||
* @param localPart The local part.
|
||||
* @return The escaped local part or null.
|
||||
* @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
|
||||
*/
|
||||
private static String escape(final CharSequence localPart) {
|
||||
if (localPart != null) {
|
||||
final Matcher matcher = ESCAPE_PATTERN.matcher(localPart);
|
||||
final StringBuffer sb = new StringBuffer();
|
||||
while (matcher.find()) {
|
||||
matcher.appendReplacement(sb, "\\\\" + Integer.toHexString(matcher.group().charAt(0)));
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String unescape(final CharSequence localPart) {
|
||||
if (localPart != null) {
|
||||
final Matcher matcher = UNESCAPE_PATTERN.matcher(localPart);
|
||||
final StringBuffer sb = new StringBuffer();
|
||||
while (matcher.find()) {
|
||||
final char c = (char) Integer.parseInt(matcher.group(1), 16);
|
||||
if (c == '\\') {
|
||||
matcher.appendReplacement(sb, "\\\\");
|
||||
} else {
|
||||
matcher.appendReplacement(sb, String.valueOf(c));
|
||||
}
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void validateDomain(String domain) {
|
||||
if (domain == null) {
|
||||
throw new NullPointerException("domain must not be null.");
|
||||
}
|
||||
if (domain.contains("@")) {
|
||||
// Prevent misuse of API.
|
||||
throw new IllegalArgumentException("domain must not contain a '@' sign");
|
||||
}
|
||||
validateLength(domain, "domain");
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the length of a local, domain or resource part is not longer than 1023 characters.
|
||||
*
|
||||
* @param value The value.
|
||||
* @param part The part, only used to produce an exception message.
|
||||
*/
|
||||
private static void validateLength(CharSequence value, CharSequence part) {
|
||||
if (value != null) {
|
||||
if (value.length() == 0) {
|
||||
throw new IllegalArgumentException(part + " must not be empty.");
|
||||
}
|
||||
if (value.toString().getBytes(Charset.forName("UTF-8")).length > 1023) {
|
||||
throw new IllegalArgumentException(part + " must not be greater than 1023 bytes.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this JID into a bare JID, i.e. removes the resource part.
|
||||
* <blockquote>
|
||||
* <p>The term "bare JID" refers to an XMPP address of the form <localpart@domainpart> (for an account at a server) or of the form <domainpart> (for a server).</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return The bare JID.
|
||||
* @see #withResource(CharSequence)
|
||||
*/
|
||||
@Override
|
||||
public final Jid asBareJid() {
|
||||
return bareJid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local part of the JID, also known as the name or node.
|
||||
* <blockquote>
|
||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.3">3.3. Localpart</a></cite></p>
|
||||
* <p>The localpart of a JID is an optional identifier placed before the
|
||||
* domainpart and separated from the latter by the '@' character.
|
||||
* Typically, a localpart uniquely identifies the entity requesting and
|
||||
* using network access provided by a server (i.e., a local account),
|
||||
* although it can also represent other kinds of entities (e.g., a
|
||||
* chatroom associated with a multi-user chat service [XEP-0045]). The
|
||||
* entity represented by an XMPP localpart is addressed within the
|
||||
* context of a specific domain (i.e., <localpart@domainpart>).</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return The local part or null.
|
||||
*/
|
||||
@Override
|
||||
public final String getLocal() {
|
||||
return local;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getEscapedLocal() {
|
||||
return escapedLocal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the domain part.
|
||||
* <blockquote>
|
||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.2">3.2. Domainpart</a></cite></p>
|
||||
* <p>The domainpart is the primary identifier and is the only REQUIRED
|
||||
* element of a JID (a mere domainpart is a valid JID). Typically,
|
||||
* a domainpart identifies the "home" server to which clients connect
|
||||
* for XML routing and data management functionality.</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return The domain part.
|
||||
*/
|
||||
@Override
|
||||
public final String getDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the resource part.
|
||||
* <blockquote>
|
||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.4">3.4. Resourcepart</a></cite></p>
|
||||
* <p>The resourcepart of a JID is an optional identifier placed after the
|
||||
* domainpart and separated from the latter by the '/' character. A
|
||||
* resourcepart can modify either a <localpart@domainpart> address or a
|
||||
* mere <domainpart> address. Typically, a resourcepart uniquely
|
||||
* identifies a specific connection (e.g., a device or location) or
|
||||
* object (e.g., an occupant in a multi-user chatroom [XEP-0045])
|
||||
* belonging to the entity associated with an XMPP localpart at a domain
|
||||
* (i.e., <localpart@domainpart/resourcepart>).</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return The resource part or null.
|
||||
*/
|
||||
@Override
|
||||
public final String getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new JID with a new local part and the same domain and resource part of the current JID.
|
||||
*
|
||||
* @param local The local part.
|
||||
* @return The JID with a new local part.
|
||||
* @throws IllegalArgumentException If the local is not a valid local part.
|
||||
* @see #withResource(CharSequence)
|
||||
*/
|
||||
@Override
|
||||
public final Jid withLocal(CharSequence local) {
|
||||
if (local == this.getLocal() || local != null && local.equals(this.getLocal())) {
|
||||
return this;
|
||||
}
|
||||
return new FullJid(local, getDomain(), getResource(), false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new full JID with a resource and the same local and domain part of the current JID.
|
||||
*
|
||||
* @param resource The resource.
|
||||
* @return The full JID with a resource.
|
||||
* @throws IllegalArgumentException If the resource is not a valid resource part.
|
||||
* @see #asBareJid()
|
||||
* @see #withLocal(CharSequence)
|
||||
*/
|
||||
@Override
|
||||
public final Jid withResource(CharSequence resource) {
|
||||
if (resource == this.getResource() || resource != null && resource.equals(this.getResource())) {
|
||||
return this;
|
||||
}
|
||||
return new FullJid(getLocal(), getDomain(), resource, false, asBareJid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new JID at a subdomain and at the same domain as this JID.
|
||||
*
|
||||
* @param subdomain The subdomain.
|
||||
* @return The JID at a subdomain.
|
||||
* @throws NullPointerException If subdomain is null.
|
||||
* @throws IllegalArgumentException If subdomain is not a valid subdomain name.
|
||||
*/
|
||||
@Override
|
||||
public final Jid atSubdomain(CharSequence subdomain) {
|
||||
if (subdomain != null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return new FullJid(getLocal(), subdomain + "." + getDomain(), getResource(), false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A profile for applying the rules for IDN as in RFC 5895. Although IDN doesn't use Precis, it's still very similar so that we can use the base class.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc5895#section-2">RFC 5895</a>
|
||||
*/
|
||||
private static final class IDNProfile extends PrecisProfile {
|
||||
|
||||
private IDNProfile() {
|
||||
super(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String prepare(CharSequence input) {
|
||||
return IDN.toUnicode(input.toString(), IDN.USE_STD3_ASCII_RULES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String enforce(CharSequence input) {
|
||||
// 4. Map IDEOGRAPHIC FULL STOP character (U+3002) to dot.
|
||||
return applyAdditionalMappingRule(
|
||||
// 3. All characters are mapped using Unicode Normalization Form C (NFC).
|
||||
applyNormalizationRule(
|
||||
// 2. Fullwidth and halfwidth characters (those defined with
|
||||
// Decomposition Types <wide> and <narrow>) are mapped to their
|
||||
// decomposition mappings
|
||||
applyWidthMappingRule(
|
||||
// 1. Uppercase characters are mapped to their lowercase equivalents
|
||||
applyCaseMappingRule(prepare(input))))).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharSequence applyWidthMappingRule(CharSequence charSequence) {
|
||||
return widthMap(charSequence);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharSequence applyAdditionalMappingRule(CharSequence charSequence) {
|
||||
return LABEL_SEPARATOR.matcher(charSequence).replaceAll(".");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharSequence applyCaseMappingRule(CharSequence charSequence) {
|
||||
return charSequence.toString().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharSequence applyNormalizationRule(CharSequence charSequence) {
|
||||
return Normalizer.normalize(charSequence, Normalizer.Form.NFC);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharSequence applyDirectionalityRule(CharSequence charSequence) {
|
||||
return charSequence;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,314 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2017 Christian Schudt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rocks.xmpp.addr;
|
||||
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represents the JID as described in <a href="https://tools.ietf.org/html/rfc7622">Extensible Messaging and Presence Protocol (XMPP): Address Format</a>.
|
||||
* <p>
|
||||
* A JID consists of three parts:
|
||||
* <p>
|
||||
* [ localpart "@" ] domainpart [ "/" resourcepart ]
|
||||
* </p>
|
||||
* The easiest way to create a JID is to use the {@link #of(CharSequence)} method:
|
||||
* ```java
|
||||
* Jid jid = Jid.of("juliet@capulet.lit/balcony");
|
||||
* ```
|
||||
* You can then get the parts from it via the respective methods:
|
||||
* ```java
|
||||
* String local = jid.getLocal(); // juliet
|
||||
* String domain = jid.getDomain(); // capulet.lit
|
||||
* String resource = jid.getResource(); // balcony
|
||||
* ```
|
||||
* Implementations of this interface should override <code>equals()</code> and <code>hashCode()</code>, so that different instances with the same value are equal:
|
||||
* ```java
|
||||
* Jid.of("romeo@capulet.lit/balcony").equals(Jid.of("romeo@capulet.lit/balcony")); // true
|
||||
* ```
|
||||
* The default implementation of this class also supports <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>, i.e.
|
||||
* ```java
|
||||
* Jid.of("d'artagnan@musketeers.lit")
|
||||
* ```
|
||||
* is escaped as <code>d\\27artagnan@musketeers.lit</code>.
|
||||
* <p>
|
||||
* Implementations of this interface should be thread-safe and immutable.
|
||||
*
|
||||
* @author Christian Schudt
|
||||
* @see <a href="https://tools.ietf.org/html/rfc7622">RFC 7622 - Extensible Messaging and Presence Protocol (XMPP): Address Format</a>
|
||||
*/
|
||||
@XmlJavaTypeAdapter(JidAdapter.class)
|
||||
public interface Jid extends Comparable<Jid>, Serializable, CharSequence {
|
||||
|
||||
/**
|
||||
* The maximal length of a full JID, which is 3071.
|
||||
* <blockquote>
|
||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.1">3.1. Fundamentals</a></cite></p>
|
||||
* <p>Each allowable portion of a JID (localpart, domainpart, and
|
||||
* resourcepart) is 1 to 1023 octets in length, resulting in a maximum
|
||||
* total size (including the '@' and '/' separators) of 3071 octets.
|
||||
* </p>
|
||||
* </blockquote>
|
||||
* Note that the length is based on bytes, not characters.
|
||||
*
|
||||
* @see #MAX_BARE_JID_LENGTH
|
||||
*/
|
||||
int MAX_FULL_JID_LENGTH = 3071;
|
||||
|
||||
/**
|
||||
* The maximal length of a bare JID, which is 2047 (1023 + 1 + 1023).
|
||||
* Note that the length is based on bytes, not characters.
|
||||
*
|
||||
* @see #MAX_FULL_JID_LENGTH
|
||||
*/
|
||||
int MAX_BARE_JID_LENGTH = 2047;
|
||||
|
||||
/**
|
||||
* The service discovery feature used for determining support of JID escaping (<code>jid\20escaping</code>).
|
||||
*/
|
||||
String ESCAPING_FEATURE = "jid\\20escaping";
|
||||
|
||||
/**
|
||||
* Returns a full JID with a domain and resource part, e.g. <code>capulet.com/balcony</code>
|
||||
*
|
||||
* @param local The local part.
|
||||
* @param domain The domain.
|
||||
* @param resource The resource part.
|
||||
* @return The JID.
|
||||
* @throws NullPointerException If the domain is null.
|
||||
* @throws IllegalArgumentException If the domain, local or resource part are not valid.
|
||||
*/
|
||||
static Jid of(CharSequence local, CharSequence domain, CharSequence resource) {
|
||||
return new FullJid(local, domain, resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a bare JID with only the domain part, e.g. <code>capulet.com</code>
|
||||
*
|
||||
* @param domain The domain.
|
||||
* @return The JID.
|
||||
* @throws NullPointerException If the domain is null.
|
||||
* @throws IllegalArgumentException If the domain or local part are not valid.
|
||||
*/
|
||||
static Jid ofDomain(CharSequence domain) {
|
||||
return new FullJid(null, domain, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a bare JID with a local and domain part, e.g. <code>juliet@capulet.com</code>
|
||||
*
|
||||
* @param local The local part.
|
||||
* @param domain The domain.
|
||||
* @return The JID.
|
||||
* @throws NullPointerException If the domain is null.
|
||||
* @throws IllegalArgumentException If the domain or local part are not valid.
|
||||
*/
|
||||
static Jid ofLocalAndDomain(CharSequence local, CharSequence domain) {
|
||||
return new FullJid(local, domain, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a full JID with a domain and resource part, e.g. <code>capulet.com/balcony</code>
|
||||
*
|
||||
* @param domain The domain.
|
||||
* @param resource The resource part.
|
||||
* @return The JID.
|
||||
* @throws NullPointerException If the domain is null.
|
||||
* @throws IllegalArgumentException If the domain or resource are not valid.
|
||||
*/
|
||||
static Jid ofDomainAndResource(CharSequence domain, CharSequence resource) {
|
||||
return new FullJid(null, domain, resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JID from an unescaped string. The format must be
|
||||
* <blockquote><p>[ localpart "@" ] domainpart [ "/" resourcepart ]</p></blockquote>
|
||||
* The input string will be escaped.
|
||||
*
|
||||
* @param jid The JID.
|
||||
* @return The JID.
|
||||
* @throws NullPointerException If the jid is null.
|
||||
* @throws IllegalArgumentException If the jid could not be parsed or is not valid.
|
||||
* @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
|
||||
*/
|
||||
static Jid of(CharSequence jid) {
|
||||
if (jid instanceof Jid) {
|
||||
return (Jid) jid;
|
||||
}
|
||||
return FullJid.of(jid.toString(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JID from a escaped JID string. The format must be
|
||||
* <blockquote><p>[ localpart "@" ] domainpart [ "/" resourcepart ]</p></blockquote>
|
||||
* This method should be used, when parsing JIDs from the XMPP stream.
|
||||
*
|
||||
* @param jid The JID.
|
||||
* @return The JID.
|
||||
* @throws NullPointerException If the jid is null.
|
||||
* @throws IllegalArgumentException If the jid could not be parsed or is not valid.
|
||||
* @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
|
||||
*/
|
||||
static Jid ofEscaped(CharSequence jid) {
|
||||
return FullJid.of(jid.toString(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the JID is a full JID.
|
||||
* <blockquote>
|
||||
* <p>The term "full JID" refers to an XMPP address of the form <localpart@domainpart/resourcepart> (for a particular authorized client or device associated with an account) or of the form <domainpart/resourcepart> (for a particular resource or script associated with a server).</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return True, if the JID is a full JID; otherwise false.
|
||||
*/
|
||||
boolean isFullJid();
|
||||
|
||||
/**
|
||||
* Checks if the JID is a bare JID.
|
||||
* <blockquote>
|
||||
* <p>The term "bare JID" refers to an XMPP address of the form <localpart@domainpart> (for an account at a server) or of the form <domainpart> (for a server).</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return True, if the JID is a bare JID; otherwise false.
|
||||
*/
|
||||
boolean isBareJid();
|
||||
|
||||
/**
|
||||
* Checks if the JID is a domain JID, i.e. if it has no local part.
|
||||
*
|
||||
* @return True, if the JID is a domain JID, i.e. if it has no local part.
|
||||
*/
|
||||
boolean isDomainJid();
|
||||
|
||||
/**
|
||||
* Gets the bare JID representation of this JID, i.e. removes the resource part.
|
||||
* <blockquote>
|
||||
* <p>The term "bare JID" refers to an XMPP address of the form <localpart@domainpart> (for an account at a server) or of the form <domainpart> (for a server).</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return The bare JID.
|
||||
* @see #withResource(CharSequence)
|
||||
*/
|
||||
Jid asBareJid();
|
||||
|
||||
/**
|
||||
* Creates a new JID with a new local part and the same domain and resource part of the current JID.
|
||||
*
|
||||
* @param local The local part.
|
||||
* @return The JID with a new local part.
|
||||
* @throws IllegalArgumentException If the local is not a valid local part.
|
||||
* @see #withResource(CharSequence)
|
||||
*/
|
||||
Jid withLocal(CharSequence local);
|
||||
|
||||
/**
|
||||
* Creates a new full JID with a resource and the same local and domain part of the current JID.
|
||||
*
|
||||
* @param resource The resource.
|
||||
* @return The full JID with a resource.
|
||||
* @throws IllegalArgumentException If the resource is not a valid resource part.
|
||||
* @see #asBareJid()
|
||||
* @see #withLocal(CharSequence)
|
||||
*/
|
||||
Jid withResource(CharSequence resource);
|
||||
|
||||
/**
|
||||
* Creates a new JID at a subdomain and at the same domain as this JID.
|
||||
*
|
||||
* @param subdomain The subdomain.
|
||||
* @return The JID at a subdomain.
|
||||
* @throws NullPointerException If subdomain is null.
|
||||
* @throws IllegalArgumentException If subdomain is not a valid subdomain name.
|
||||
*/
|
||||
Jid atSubdomain(CharSequence subdomain);
|
||||
|
||||
/**
|
||||
* Gets the local part of the JID, also known as the name or node.
|
||||
* <blockquote>
|
||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.3">3.3. Localpart</a></cite></p>
|
||||
* <p>The localpart of a JID is an optional identifier placed before the
|
||||
* domainpart and separated from the latter by the '@' character.
|
||||
* Typically, a localpart uniquely identifies the entity requesting and
|
||||
* using network access provided by a server (i.e., a local account),
|
||||
* although it can also represent other kinds of entities (e.g., a
|
||||
* chatroom associated with a multi-user chat service [XEP-0045]). The
|
||||
* entity represented by an XMPP localpart is addressed within the
|
||||
* context of a specific domain (i.e., <localpart@domainpart>).</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return The local part or null.
|
||||
* @see #getEscapedLocal()
|
||||
*/
|
||||
String getLocal();
|
||||
|
||||
/**
|
||||
* Gets the escaped local part of the JID.
|
||||
*
|
||||
* @return The escaped local part or null.
|
||||
* @see #getLocal()
|
||||
* @since 0.8.0
|
||||
*/
|
||||
String getEscapedLocal();
|
||||
|
||||
/**
|
||||
* Gets the domain part.
|
||||
* <blockquote>
|
||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.2">3.2. Domainpart</a></cite></p>
|
||||
* <p>The domainpart is the primary identifier and is the only REQUIRED
|
||||
* element of a JID (a mere domainpart is a valid JID). Typically,
|
||||
* a domainpart identifies the "home" server to which clients connect
|
||||
* for XML routing and data management functionality.</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return The domain part.
|
||||
*/
|
||||
String getDomain();
|
||||
|
||||
/**
|
||||
* Gets the resource part.
|
||||
* <blockquote>
|
||||
* <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.4">3.4. Resourcepart</a></cite></p>
|
||||
* <p>The resourcepart of a JID is an optional identifier placed after the
|
||||
* domainpart and separated from the latter by the '/' character. A
|
||||
* resourcepart can modify either a <localpart@domainpart> address or a
|
||||
* mere <domainpart> address. Typically, a resourcepart uniquely
|
||||
* identifies a specific connection (e.g., a device or location) or
|
||||
* object (e.g., an occupant in a multi-user chatroom [XEP-0045])
|
||||
* belonging to the entity associated with an XMPP localpart at a domain
|
||||
* (i.e., <localpart@domainpart/resourcepart>).</p>
|
||||
* </blockquote>
|
||||
*
|
||||
* @return The resource part or null.
|
||||
*/
|
||||
String getResource();
|
||||
|
||||
/**
|
||||
* Returns the JID in escaped form as described in <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>.
|
||||
*
|
||||
* @return The escaped JID.
|
||||
* @see #toString()
|
||||
*/
|
||||
String toEscapedString();
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2016 Christian Schudt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rocks.xmpp.addr;
|
||||
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
|
||||
/**
|
||||
* Converts a String representation of a JID to JID object and vice a versa.
|
||||
*/
|
||||
final class JidAdapter extends XmlAdapter<String, Jid> {
|
||||
|
||||
@Override
|
||||
public Jid unmarshal(String v) {
|
||||
if (v != null) {
|
||||
try {
|
||||
return Jid.ofEscaped(v);
|
||||
} catch (Exception e) {
|
||||
return MalformedJid.of(v, e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String marshal(Jid v) {
|
||||
if (v != null) {
|
||||
return v.toEscapedString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2017 Christian Schudt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rocks.xmpp.addr;
|
||||
|
||||
/**
|
||||
* Represents a malformed JID in order to handle the <code>jid-malformed</code> error.
|
||||
* <p>
|
||||
* This class is not intended to be publicly instantiable, but is used for malformed JIDs during parsing automatically.
|
||||
*
|
||||
* @author Christian Schudt
|
||||
* @see <a href="https://xmpp.org/rfcs/rfc6120.html#stanzas-error-conditions-jid-malformed">RFC 6120, 8.3.3.8. jid-malformed</a>
|
||||
*/
|
||||
public final class MalformedJid extends AbstractJid {
|
||||
|
||||
private static final long serialVersionUID = -2896737611021417985L;
|
||||
|
||||
private final String localPart;
|
||||
|
||||
private final String domainPart;
|
||||
|
||||
private final String resourcePart;
|
||||
|
||||
private final Throwable cause;
|
||||
|
||||
static MalformedJid of(final String jid, final Throwable cause) {
|
||||
// Do some basic parsing without any further checks or validation.
|
||||
final StringBuilder sb = new StringBuilder(jid);
|
||||
// 1. Remove any portion from the first '/' character to the end of the
|
||||
// string (if there is a '/' character present).
|
||||
final int indexOfResourceDelimiter = jid.indexOf('/');
|
||||
final String resourcePart;
|
||||
if (indexOfResourceDelimiter > -1) {
|
||||
resourcePart = sb.substring(indexOfResourceDelimiter + 1);
|
||||
sb.delete(indexOfResourceDelimiter, sb.length());
|
||||
} else {
|
||||
resourcePart = null;
|
||||
}
|
||||
// 2. Remove any portion from the beginning of the string to the first
|
||||
// '@' character (if there is an '@' character present).
|
||||
final int indexOfAt = jid.indexOf('@');
|
||||
final String localPart;
|
||||
if (indexOfAt > -1) {
|
||||
localPart = sb.substring(0, indexOfAt);
|
||||
sb.delete(0, indexOfAt + 1);
|
||||
} else {
|
||||
localPart = null;
|
||||
}
|
||||
return new MalformedJid(localPart, sb.toString(), resourcePart, cause);
|
||||
}
|
||||
|
||||
private MalformedJid(final String localPart, final String domainPart, final String resourcePart, final Throwable cause) {
|
||||
this.localPart = localPart;
|
||||
this.domainPart = domainPart;
|
||||
this.resourcePart = resourcePart;
|
||||
this.cause = cause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Jid asBareJid() {
|
||||
return new MalformedJid(localPart, domainPart, null, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jid withLocal(CharSequence local) {
|
||||
return new MalformedJid(local.toString(), domainPart, resourcePart, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jid withResource(CharSequence resource) {
|
||||
return new MalformedJid(localPart, domainPart, resource.toString(), cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jid atSubdomain(CharSequence subdomain) {
|
||||
if (subdomain == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return new MalformedJid(localPart, subdomain + "." + domainPart, resourcePart, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getLocal() {
|
||||
return localPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getEscapedLocal() {
|
||||
return localPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getDomain() {
|
||||
return domainPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getResource() {
|
||||
return resourcePart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cause why the JID is malformed.
|
||||
*
|
||||
* @return The cause.
|
||||
*/
|
||||
public final Throwable getCause() {
|
||||
return cause;
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2016 Christian Schudt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides classes for the <a href="https://tools.ietf.org/html/rfc7622">XMPP Address Format</a> (JID).
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc7622">Extensible Messaging and Presence Protocol (XMPP): Address Format</a>
|
||||
*/
|
||||
package rocks.xmpp.addr;
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2016 Christian Schudt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rocks.xmpp.util.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A simple directory based cache for caching of persistent items like avatars or entity capabilities.
|
||||
*
|
||||
* @author Christian Schudt
|
||||
*/
|
||||
public final class DirectoryCache implements Map<String, byte[]> {
|
||||
|
||||
private final Path cacheDirectory;
|
||||
|
||||
public DirectoryCache(Path cacheDirectory) {
|
||||
this.cacheDirectory = cacheDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int size() {
|
||||
try (final Stream<Path> files = cacheContent()) {
|
||||
return (int) Math.min(files.count(), Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isEmpty() {
|
||||
try (final Stream<Path> files = cacheContent()) {
|
||||
return files.findAny().map(file -> Boolean.FALSE).orElse(Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean containsKey(Object key) {
|
||||
return Files.exists(cacheDirectory.resolve(key.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean containsValue(Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final byte[] get(final Object key) {
|
||||
return Optional.ofNullable(key).map(Object::toString).filter(((Predicate<String>) String::isEmpty).negate()).map(cacheDirectory::resolve).filter(Files::isReadable).map(file -> {
|
||||
try {
|
||||
return Files.readAllBytes(file);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final byte[] put(String key, byte[] value) {
|
||||
// Make sure the directory exists.
|
||||
byte[] data = get(key);
|
||||
if (!Arrays.equals(data, value))
|
||||
try {
|
||||
if (Files.notExists(cacheDirectory)) {
|
||||
Files.createDirectories(cacheDirectory);
|
||||
}
|
||||
Path file = cacheDirectory.resolve(key);
|
||||
Files.write(file, value);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final byte[] remove(Object key) {
|
||||
byte[] data = get(key);
|
||||
try {
|
||||
Files.deleteIfExists(cacheDirectory.resolve(key.toString()));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void putAll(Map<? extends String, ? extends byte[]> m) {
|
||||
m.forEach(this::put);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void clear() {
|
||||
try {
|
||||
Files.walkFileTree(cacheDirectory, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
Files.deleteIfExists(file);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
||||
// Don't delete the cache directory itself.
|
||||
if (!Files.isSameFile(dir, cacheDirectory)) {
|
||||
Files.deleteIfExists(dir);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Set<String> keySet() {
|
||||
try (final Stream<Path> files = Files.list(cacheDirectory)) {
|
||||
return Collections.unmodifiableSet(files.map(Path::getFileName).map(Path::toString).collect(Collectors.toSet()));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Collection<byte[]> values() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Set<Entry<String, byte[]>> entrySet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void forEach(final BiConsumer<? super String, ? super byte[]> action) {
|
||||
if (Files.exists(cacheDirectory))
|
||||
try (final Stream<Path> files = cacheContent().filter(Files::isReadable)) {
|
||||
files.forEach(file -> {
|
||||
try {
|
||||
action.accept(file.getFileName().toString(), Files.readAllBytes(file));
|
||||
} catch (final IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("StreamResourceLeak")
|
||||
private final Stream<Path> cacheContent() {
|
||||
try {
|
||||
return Files.walk(cacheDirectory).filter(Files::isRegularFile);
|
||||
} catch (final IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,228 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2016 Christian Schudt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rocks.xmpp.util.cache;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A simple concurrent implementation of a least-recently-used cache.
|
||||
* <p>
|
||||
* This cache is keeps a maximal number of items in memory and removes the least-recently-used item, when new items are added.
|
||||
*
|
||||
* @param <K> The key.
|
||||
* @param <V> The value.
|
||||
* @author Christian Schudt
|
||||
* @see <a href="http://javadecodedquestions.blogspot.de/2013/02/java-cache-static-data-loading.html">http://javadecodedquestions.blogspot.de/2013/02/java-cache-static-data-loading.html</a>
|
||||
* @see <a href="http://stackoverflow.com/a/22891780">http://stackoverflow.com/a/22891780</a>
|
||||
*/
|
||||
public final class LruCache<K, V> implements Map<K, V> {
|
||||
private final int maxEntries;
|
||||
|
||||
private final Map<K, V> map;
|
||||
|
||||
final Queue<K> queue;
|
||||
|
||||
public LruCache(final int maxEntries) {
|
||||
this.maxEntries = maxEntries;
|
||||
this.map = new ConcurrentHashMap<>(maxEntries);
|
||||
// Don't use a ConcurrentLinkedQueue here.
|
||||
// There's a JDK bug, leading to OutOfMemoryError and high CPU usage:
|
||||
// https://bugs.openjdk.java.net/browse/JDK-8054446
|
||||
this.queue = new ConcurrentLinkedDeque<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean containsKey(final Object key) {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean containsValue(final Object value) {
|
||||
return map.containsValue(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public final V get(final Object key) {
|
||||
final V v = map.get(key);
|
||||
if (v != null) {
|
||||
// Remove the key from the queue and re-add it to the tail. It is now the most recently used key.
|
||||
keyUsed((K) key);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final V put(final K key, final V value) {
|
||||
V v = map.put(key, value);
|
||||
keyUsed(key);
|
||||
limit();
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final V remove(final Object key) {
|
||||
queue.remove(key);
|
||||
return map.remove(key);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void putAll(final Map<? extends K, ? extends V> m) {
|
||||
for (Map.Entry<? extends K, ? extends V> entry : m.entrySet()) {
|
||||
put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void clear() {
|
||||
queue.clear();
|
||||
map.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Set<K> keySet() {
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Collection<V> values() {
|
||||
return map.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Set<Entry<K, V>> entrySet() {
|
||||
return map.entrySet();
|
||||
}
|
||||
|
||||
|
||||
// Default methods
|
||||
|
||||
@Override
|
||||
public final V putIfAbsent(final K key, final V value) {
|
||||
final V v = map.putIfAbsent(key, value);
|
||||
if (v == null) {
|
||||
keyUsed(key);
|
||||
}
|
||||
limit();
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean remove(final Object key, final Object value) {
|
||||
final boolean removed = map.remove(key, value);
|
||||
if (removed) {
|
||||
queue.remove(key);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean replace(final K key, final V oldValue, final V newValue) {
|
||||
final boolean replaced = map.replace(key, oldValue, newValue);
|
||||
if (replaced) {
|
||||
keyUsed(key);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final V replace(final K key, final V value) {
|
||||
final V v = map.replace(key, value);
|
||||
if (v != null) {
|
||||
keyUsed(key);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final V computeIfAbsent(final K key, final Function<? super K, ? extends V> mappingFunction) {
|
||||
return map.computeIfAbsent(key, mappingFunction.<V>andThen(v -> {
|
||||
keyUsed(key);
|
||||
limit();
|
||||
return v;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final V computeIfPresent(final K key, final BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||
return map.computeIfPresent(key, remappingFunction.<V>andThen(v -> {
|
||||
keyUsed(key);
|
||||
limit();
|
||||
return v;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final V compute(final K key, final BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||
return map.compute(key, remappingFunction.<V>andThen(v -> {
|
||||
keyUsed(key);
|
||||
limit();
|
||||
return v;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
|
||||
return map.merge(key, value, remappingFunction.<V>andThen(v -> {
|
||||
keyUsed(key);
|
||||
limit();
|
||||
return v;
|
||||
}));
|
||||
}
|
||||
|
||||
private void limit() {
|
||||
while (queue.size() > maxEntries) {
|
||||
final K oldestKey = queue.poll();
|
||||
if (oldestKey != null) {
|
||||
map.remove(oldestKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void keyUsed(final K key) {
|
||||
// remove it from the queue and re-add it, to make it the most recently used key.
|
||||
queue.remove(key);
|
||||
queue.offer(key);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2016 Christian Schudt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides simple cache implementations.
|
||||
*/
|
||||
package rocks.xmpp.util.cache;
|
|
@ -0,0 +1,2 @@
|
|||
• bug fixes for peer to peer file transfer (Jingle)
|
||||
• fixed server info for unlimited/unknown max file size
|
|
@ -0,0 +1 @@
|
|||
• stability improvements for group chats and channels
|
|
@ -0,0 +1,2 @@
|
|||
• allow backups to be restored from anywhere
|
||||
• bug fixes
|
|
@ -0,0 +1,3 @@
|
|||
• fix light themen composing fied
|
||||
• fixes for Jingle file transfer
|
||||
• fixed some rare crashes
|
|
@ -0,0 +1,3 @@
|
|||
• fixed crash when scanning QR codes on Android 6 and lower
|
||||
• when sharing a message from and to Conversations insert it as quote
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
• fixed connection issues over Tor
|
||||
• P2P file transfer (Jingle) now offers direct candidates
|
||||
• Support XEP-0396: Jingle Encrypted Transports - OMEMO
|
|
@ -0,0 +1,4 @@
|
|||
• Fixed crash on Android <5.0
|
||||
• Fixed crash on Xiaomi devices running Android 8.0 + 8.1
|
||||
• fixed minor security issues
|
||||
• Share XMPP uri from channel search by long pressing a result
|
|
@ -0,0 +1 @@
|
|||
• Fixed crash on internal database update
|
|
@ -0,0 +1,3 @@
|
|||
• rename app 'Conversations with IPv6' to 'Conv6ations for Sum7'
|
||||
• Jingle file transfer fixes
|
||||
• Fixed OMEMO self healing (after backup restore) on servers w/o MAM
|
|
@ -0,0 +1,4 @@
|
|||
• Introduce expert setting to perform channel discovery on local server instead of [search.jabber.network](https://search.jabber.network)
|
||||
• Enable delivery check marks by default and remove setting
|
||||
• Enable ‘Send button indicates status’ by default and remove setting
|
||||
• Move Backup and Foreground Service settings to main screen
|
|
@ -0,0 +1 @@
|
|||
• changes in Networkstack 'let OS decide IPv4 or IPv6' to own 'Happy Eyeball' for faster connection and fair to both IP version.
|
|
@ -0,0 +1,3 @@
|
|||
• fixes for Jingle IBB file transfer
|
||||
• fixes for repeated corrections filling up the database
|
||||
• switched to Last Message Correction v1.1
|
|
@ -0,0 +1,4 @@
|
|||
• support for ?register and ?register;preauth XMPP uri parameters
|
||||
• let users set their own nick name
|
||||
• resume download of OMEMO encrypted files
|
||||
• channels now use '#' as symbol in avatar
|
|
@ -0,0 +1 @@
|
|||
• Support automatic theme switching on Android 10
|
|
@ -0,0 +1,2 @@
|
|||
• improve logging of happy eyeball
|
||||
• fix several NullPointer bugs
|
|
@ -0,0 +1,5 @@
|
|||
• Provide PDF preview on Android 5+
|
||||
• Use 12 byte IVs for OMEMO
|
||||
• Happy Eyeball: cacheing of addresses
|
||||
• Happy Eyeball: fix DNSSEC im special cases and NPE
|
||||
• Happy Eyeball: revert dns-server selection
|
|
@ -0,0 +1,2 @@
|
|||
• Fix avatar selection on some Android 10 devices
|
||||
• Fix file transfer for larger files
|
|
@ -0,0 +1,2 @@
|
|||
• Audio/Video calls (Requires server support in form of STUN and TURN servers discoverable via XEP-0215)
|
||||
• Rename App to only Conv6sation
|
|
@ -0,0 +1,2 @@
|
|||
• Audible feedback (dialing, call started, call ended) for voice calls.
|
||||
• Fixed issue with retrying failed video call
|
|
@ -0,0 +1,2 @@
|
|||
• Add button to switch camea during video call
|
||||
• Fixed voice calls on tablets
|
|
@ -0,0 +1,3 @@
|
|||
• Move call icon to the left in order to keep other toolbar icons in a consistent place
|
||||
• Show call duration during audio calls
|
||||
• Tie breaking for A/V calls (the same two people calling each other at the same time)
|
|
@ -0,0 +1,2 @@
|
|||
• Rework Login with certificate UI
|
||||
• Add ability to pin chats on top (add to favorites)
|
|
@ -0,0 +1,3 @@
|
|||
• Reduce echo during calls on some devices
|
||||
• Fix login when passwords contains special characters
|
||||
• Play dial and busy tones on speaker during video calls
|
|
@ -0,0 +1 @@
|
|||
• Offer to record voice message when callee is busy
|
|
@ -0,0 +1,3 @@
|
|||
• Show help button if A/V call fails
|
||||
• Fixed some annoying crashes
|
||||
• Fixed Jingle connections (file transfer + calls) with bare JIDs
|
|
@ -0,0 +1,2 @@
|
|||
• Fixed notifications not showing up under certain conditions
|
||||
• Fixed compatibility issues and crashes related to A/V calls
|
|
@ -0,0 +1,3 @@
|
|||
• add 'Return to chat' to audio call screen
|
||||
• Improve keyboard shortcuts
|
||||
• bug fixes
|
|
@ -0,0 +1,3 @@
|
|||
• Handle GPX files
|
||||
• Improve performance for backup restore
|
||||
• bug fixes
|
|
@ -0,0 +1 @@
|
|||
• WebRTC update (with security fixes)
|
|
@ -0,0 +1,4 @@
|
|||
• Search individual conversations
|
||||
• Notify user if message delivery fails
|
||||
• Remember display names (nicks) from Quicksy users across restarts
|
||||
• Add button to start Orbot (Tor) from notification if necessary
|
|
@ -0,0 +1,3 @@
|
|||
• Offer Easy Invite generation on supporting servers
|
||||
• Display GIFs send from Movim
|
||||
• store avatars in cache
|
|
@ -0,0 +1,4 @@
|
|||
• Fixed connectivity issues when different accounts used different SCRAM mechanisms
|
||||
• Add support for SCRAM-SHA-512
|
||||
• Allow P2P (Jingle) file transfer with self contact
|
||||
• minor stability improvements for A/V calls
|
|
@ -0,0 +1,3 @@
|
|||
• Show call button for offline contacts if they previously announced support
|
||||
• Back button no longer ends call when call is connected
|
||||
• bug fixes
|
|
@ -0,0 +1 @@
|
|||
• fix crashes (error on internal database migration)
|
|
@ -0,0 +1,4 @@
|
|||
• Ability to select incoming call ringtone
|
||||
• Fix OpenPGP key id discovery for OpenKeychain 5.6+
|
||||
• Properly verify punycode TLS certificates
|
||||
• Improve stability of RTP session establishment (calling)
|
|
@ -0,0 +1,2 @@
|
|||
• Verify A/V calls with preexisting OMEMO sessions
|
||||
• Improve compatibility with non libwebrtc WebRTC implementations
|
|
@ -0,0 +1 @@
|
|||
• Various bug fixes around Tor support
|
|
@ -0,0 +1,3 @@
|
|||
• Improve call compatibility with Dino
|
||||
• fix HTTP up/download for users that don’t trust system CAs
|
||||
• Fixed 'No Connectivity' issues on Android 7.1
|
|
@ -0,0 +1,3 @@
|
|||
• Always verify domain name. No user overwrite
|
||||
• Support roster pre authentication
|
||||
• minor A/V improvements
|