forked from I2P_Developers/i2p.i2p
Compare commits
442 Commits
i2p-0.9.46
...
test-conte
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c4611c0bd | |||
| 44c3d8cc0c | |||
| d888eee6d1 | |||
|
|
ee06171a2f | ||
|
|
335409f1d2 | ||
|
|
d6edb9e96c | ||
| f150855f1c | |||
|
|
655ce09796 | ||
|
|
91ebec15d5 | ||
|
|
b17d321503 | ||
|
|
a6398d88a9 | ||
|
|
59969db16c | ||
|
|
b68a5ea7fd | ||
|
|
c2234685b9 | ||
|
|
ce7daaa02a | ||
|
|
b19999f95a | ||
|
|
92ecc9f8e8 | ||
|
|
aa2ba92db8 | ||
|
|
5f3c41244b | ||
|
|
bf29132898 | ||
|
|
a424331b78 | ||
|
|
ccb0c279f7 | ||
|
|
7fe01fb9a7 | ||
|
|
66c4c10a78 | ||
|
|
163967311e | ||
|
|
75734448c5 | ||
|
|
aed1de84b8 | ||
|
|
51560a8ec8 | ||
|
|
ec89a80e80 | ||
|
|
41c7b7382a | ||
|
|
b4e1fbd857 | ||
|
|
517ff4fa24 | ||
|
|
106b1a696d | ||
|
|
6cab545c45 | ||
|
|
619923dbf8 | ||
|
|
ed0ecdf253 | ||
|
|
d42ef2223d | ||
|
|
e461004ed9 | ||
|
|
2e180d4c60 | ||
|
|
152ad1659b | ||
|
|
888311e34f | ||
|
|
2df5fb972a | ||
|
|
a481255adb | ||
|
|
139594df8f | ||
|
|
659ab97f69 | ||
|
|
963a4fe89c | ||
|
|
4c4dbae107 | ||
|
|
6978049416 | ||
|
|
46fe1ba74a | ||
|
|
13bd5e4938 | ||
|
|
bbacf85245 | ||
|
|
68f011f344 | ||
|
|
8bd2384ac8 | ||
|
|
54dda1a15f | ||
|
|
3f44a555ba | ||
|
|
86cbb2ed4e | ||
|
|
2569123055 | ||
|
|
afa4b9e66d | ||
|
|
67bd5a32fd | ||
|
|
ada3629507 | ||
|
|
dcb7314306 | ||
|
|
e3c2ad6354 | ||
|
|
178ea252d5 | ||
|
|
7e4ba4eb31 | ||
|
|
de43de17f6 | ||
|
|
2ceb9c429a | ||
|
|
0b59f53fe9 | ||
|
|
62fce859b9 | ||
|
|
9fc97764c5 | ||
|
|
2813d9412d | ||
|
|
a0bf76a4b1 | ||
|
|
d2a79e8837 | ||
|
|
738ef496d4 | ||
|
|
a2734ffa72 | ||
|
|
8606d30e9a | ||
|
|
a45084cfc3 | ||
|
|
eeaf6f3514 | ||
|
|
9e18ff1cd1 | ||
|
|
665239fd37 | ||
|
|
12f9a7187e | ||
|
|
8835351b99 | ||
|
|
a3c44912f2 | ||
|
|
db9f735376 | ||
|
|
875a7242d4 | ||
|
|
51ecdc64a4 | ||
|
|
7b785ea454 | ||
|
|
8f5fc44755 | ||
|
|
010dbfa6f2 | ||
|
|
e20a19c358 | ||
|
|
387e513949 | ||
|
|
5e005e6520 | ||
|
|
e88f40cd95 | ||
|
|
82e93a53a3 | ||
| fee5668c1c | |||
|
|
abb8cbe75d | ||
|
|
340df51429 | ||
|
|
bec8feb05a | ||
|
|
d86ccded53 | ||
|
|
db7d92a5cd | ||
|
|
30ffdd03c7 | ||
| 251d8de943 | |||
|
|
5e8de68746 | ||
|
|
8ae29c8c00 | ||
|
|
542efa0d9a | ||
|
|
23c80accfa | ||
|
|
b909430725 | ||
|
|
20b413bc67 | ||
|
|
a9b6b86183 | ||
|
|
66b724759d | ||
|
|
56059448c5 | ||
|
|
1c52eeb910 | ||
|
|
4aefe4bf7a | ||
|
|
b9444cdc51 | ||
|
|
eb72e4c9f5 | ||
|
|
aa181ee43f | ||
|
|
ab04f92072 | ||
|
|
0830329eaf | ||
|
|
2d154cc90e | ||
|
|
183280871f | ||
|
|
067ee80ba0 | ||
|
|
804e2f39f9 | ||
|
|
0ad7e52b71 | ||
|
|
e15110bbe1 | ||
|
|
2cffda6974 | ||
| 2300f6c226 | |||
| 1ed8a1b6f3 | |||
| c4ed7719e8 | |||
| a98fe45204 | |||
| 5a3e26453f | |||
| c259000cdb | |||
| d683f0d9eb | |||
| 48b8886224 | |||
| 1097220d31 | |||
| fdeae72d38 | |||
| f870bc2ccd | |||
| ec3bfa3cb7 | |||
| c3f7c5d154 | |||
| 127b93c1e2 | |||
| cd019f258f | |||
| 889b7361fe | |||
| 99f6d4aba4 | |||
| 69deddcbc7 | |||
| 58020b4b58 | |||
| df43e72a08 | |||
| 326e2c630c | |||
| 36fdfd529f | |||
| 94bdc9c5b3 | |||
| c60e51514c | |||
| 7dcbbf17c3 | |||
| 5551deb246 | |||
| 6e8fd42efd | |||
| 5020100ef8 | |||
| 6c2c6abfb9 | |||
|
|
4940c34779 | ||
|
|
6d5aebeaa0 | ||
| d8924119b5 | |||
| 4b445e7d35 | |||
| 17e47a0c93 | |||
| 2ffb570850 | |||
| aef2fb8ce0 | |||
| 875fcdfb94 | |||
|
|
151f856b0a | ||
| 337787be0e | |||
| 798521466d | |||
| 678c035fa3 | |||
| ccb4210f8b | |||
| 7e5dc6ad64 | |||
| 31622d0458 | |||
| f9b18545f9 | |||
|
|
e67eccd1eb | ||
|
|
cefe212a17 | ||
|
|
8a76d71bd5 | ||
|
|
806df95114 | ||
|
|
c6c0b9ce8a | ||
| 00a0970c95 | |||
| cb1bd95f2b | |||
| d12b52f82a | |||
| 891ffaac09 | |||
| 36fbf0e332 | |||
| e811238d60 | |||
| c9e6bef825 | |||
| 0f002b9b69 | |||
| f179a057bc | |||
| 6f5042be8f | |||
| 2044474549 | |||
| 0b0b93f26f | |||
| 595f8762ab | |||
| 8644eb431e | |||
| 223afdfc7e | |||
| de41cab08e | |||
| 3606a42ea8 | |||
| 6887c7edae | |||
|
|
4a00691385 | ||
|
|
1d0a2c4fac | ||
|
|
d0016380e5 | ||
| 29dc311c6a | |||
| 7aa78a1aed | |||
| 989f64192f | |||
| c908c6bd05 | |||
|
|
9f51b72cab | ||
| a2fd817915 | |||
| 5bafdd05a9 | |||
|
|
e18708bdbe | ||
|
|
f6687c1f88 | ||
|
|
b9eabca403 | ||
|
|
9ec2c62f2f | ||
| d4152ea546 | |||
| 8cc62b5b42 | |||
| e242015145 | |||
| 35da97936d | |||
| bfe21176ea | |||
| d1dd9ab517 | |||
| c18dbe974a | |||
| f69563da75 | |||
| 057eca56d5 | |||
| a21a64e0c6 | |||
| 751af5bcd8 | |||
| c8605009ba | |||
| 5625caebda | |||
| fc0a78dd7b | |||
| 90aab37002 | |||
| 5c1a529df0 | |||
| 6fa015c410 | |||
| 2d1e68b53b | |||
| 35012a3bad | |||
| 190b76d7fd | |||
|
|
8d0b1214d2 | ||
| 70eb2a49f9 | |||
| f231ea0951 | |||
| f9ffdd5137 | |||
|
|
38f9955391 | ||
| 517ff9af28 | |||
| 62a91acb40 | |||
| 69a5266675 | |||
| e671741329 | |||
| ab55f27ea4 | |||
| cf88b3057a | |||
| af97eedcbb | |||
| 7823001594 | |||
| a49f87179a | |||
| b52f85ac38 | |||
| 470bc77551 | |||
| a0822a6b71 | |||
| 15da2f85ad | |||
| 9b3ff9e615 | |||
| df1db163f0 | |||
| 4a4d814a17 | |||
|
|
c84360ba4b | ||
| 6a6064d614 | |||
| 49565a99f9 | |||
| ee27bc3bbf | |||
| 25899d41d5 | |||
| 35f6a2e2bf | |||
| 9ae5cbbc87 | |||
| 0ace93cec7 | |||
| d387448794 | |||
| 4d82917b94 | |||
|
|
7a77f48963 | ||
| dee5dfc682 | |||
| 5ed6f834c1 | |||
| 3b8e5f0763 | |||
| 7c1798513d | |||
| e54950e02e | |||
| b2f060795c | |||
| 940ad61ccc | |||
| c1f531ea92 | |||
| 0ebca7e8e3 | |||
| d301669726 | |||
| 010bb0a2fe | |||
| f028002c11 | |||
| 11e1747ffc | |||
| 5dc9333bb6 | |||
| f77acb6db6 | |||
| 22abf09bd7 | |||
| 9a1d7a2ae3 | |||
| 98e5908557 | |||
| 9e36fe090c | |||
| b4b6968ede | |||
| 999c4c51a2 | |||
| 8737a6a4fd | |||
| a9a5d13e06 | |||
|
|
ca1e2ba91e | ||
| 2e34969bbc | |||
| cead0b2fb8 | |||
|
|
9d566aea68 | ||
| 2d9933a4a9 | |||
| cd699c587b | |||
| 4108007b26 | |||
| b31b42a557 | |||
| c3f187abcb | |||
| 2989d955d9 | |||
| ea4409897d | |||
| 7dd7f021b0 | |||
| 2cb53ec45c | |||
|
|
8fa3e45e47 | ||
| c4a5d111e7 | |||
| dca45a9b18 | |||
| 6ffebbd5c1 | |||
| aa07775a32 | |||
| 30244f9d9b | |||
| 19d4a5ce26 | |||
| e4cb730c1b | |||
| 3b18e54545 | |||
| 2fbbd8e7d1 | |||
| e466331407 | |||
| 5d1f46e6c4 | |||
| 36318def69 | |||
| 72e4b16c1a | |||
| 8a10c3a097 | |||
| d402300dba | |||
| ada6753255 | |||
| ceb0749e0d | |||
| 4863ab3711 | |||
| c745cc8aa1 | |||
| 273902f616 | |||
| bb761aea96 | |||
| d13a7d2872 | |||
| 49b2ca061c | |||
|
|
3e23ec8d27 | ||
| 22eeb90b81 | |||
| 6a69cef2a8 | |||
| c1fef302f3 | |||
| bd370cf407 | |||
| feba993019 | |||
| 623a11dd8f | |||
| ba7fb00450 | |||
| 20b4186331 | |||
| 2479645d22 | |||
|
|
8585e2e955 | ||
|
|
14518dc396 | ||
| ccd64b6f07 | |||
| 21efdb9bd0 | |||
| 94778c74dc | |||
|
|
929c09fecc | ||
| c067f38123 | |||
| 046d1e01b0 | |||
| cc6247fe7e | |||
|
|
797a31924d | ||
| 87f9b619e5 | |||
|
|
4ac89e7024 | ||
| fceda68cd8 | |||
| 07fc66ccff | |||
| d7b512ca9a | |||
|
|
926f88585a | ||
| 717e1c58fa | |||
| 4b3dbd8915 | |||
|
|
9d31a41ffe | ||
|
|
217571118b | ||
|
|
b03e919cbe | ||
|
|
482b305065 | ||
|
|
27776cddb2 | ||
|
|
029e082cfc | ||
|
|
6087a46a0b | ||
| b78f6a645c | |||
| f8b04e398e | |||
| 097f178e2a | |||
| d221846c31 | |||
| fa08d2f946 | |||
| 336563e7c0 | |||
| f4ac8e02f6 | |||
| 29d2051a34 | |||
| e52359c4c0 | |||
| d73b327fd0 | |||
|
|
d1bdeae596 | ||
|
|
fa8bd4310c | ||
| 4f8f8b659b | |||
| 5a9eb68160 | |||
|
|
b97ec8da90 | ||
| a3fe0092ac | |||
| 896dbfbacf | |||
| 4d3561c92a | |||
|
|
3c7b658a59 | ||
|
|
6482437795 | ||
| 12e2dabaa8 | |||
| e05545ab7c | |||
| f0bcab2e2c | |||
| 075ac7ab43 | |||
| 31d7d7d9bb | |||
|
|
ed14aa130c | ||
| 81007c1a03 | |||
| 2e3ff679f3 | |||
| a84996399e | |||
|
|
7b872474fd | ||
|
|
531b7c2ae9 | ||
|
|
95f16c99bd | ||
|
|
462180f9a4 | ||
|
|
505c49ad01 | ||
|
|
16d6cf0177 | ||
| 112beb552b | |||
|
|
b53cdafc84 | ||
| 365b9053ec | |||
|
|
aadc9a13aa | ||
|
|
39f3e3a92c | ||
|
|
9a6374c79b | ||
| 3a392e84a9 | |||
| c119de6188 | |||
| 066833819b | |||
| c840f223cd | |||
| 4c2bf3e42f | |||
| 6ec95a7f13 | |||
| 670e57b9e5 | |||
|
|
d441ead884 | ||
|
|
38f654edd9 | ||
| 25b4d136b8 | |||
| 2b9783028d | |||
| 6c0e18d3e2 | |||
| e23f671ca3 | |||
| 2af7066074 | |||
| 220f641ba6 | |||
| 76493b398f | |||
| f1a277c4d7 | |||
| ac76d544b9 | |||
| cd77461fba | |||
| 326178ad47 | |||
| 0fce24479f | |||
| 3f895d32dd | |||
| 2af26f7d5b | |||
| 765d4ea725 | |||
| ec231ecd78 | |||
| 957767c985 | |||
| 3cc7374984 | |||
| 6461c8e880 | |||
| edfbc4081b | |||
| 317bf1e9db | |||
| f985004be0 | |||
| 4fd834d13e | |||
| 370f96acfb | |||
| d8b308dd9d | |||
| 3ad8f9b9a5 | |||
| 4fe9a27e2e | |||
| 686fe88e61 | |||
| 9b5e4373d4 | |||
| 03b1a4dfc0 | |||
| 27e422f81d | |||
| f3e821a65d | |||
| 3fac44874e | |||
| f8df7eba7f | |||
| 4574ebd8a9 | |||
| a00b9bb0c7 | |||
| e091eeae90 | |||
| 0a98147315 | |||
|
|
1154d28be7 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -54,4 +54,10 @@ sloccount.sc
|
||||
.settings/
|
||||
# IDEA
|
||||
*.iml
|
||||
.idea
|
||||
|
||||
# Gradle
|
||||
.gradle
|
||||
|
||||
# TODO: why does this file appear?
|
||||
apps/routerconsole/jsp/favicon.ico
|
||||
|
||||
24
.gitlab-ci.yml
Normal file
24
.gitlab-ci.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
image: openjdk:8-alpine
|
||||
|
||||
stages:
|
||||
- test
|
||||
|
||||
cache:
|
||||
key: ${CI_COMMIT_REF_SLUG}
|
||||
paths:
|
||||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
- .gradle
|
||||
|
||||
test:
|
||||
stage: test
|
||||
coverage: '/Total.*?([0-9]{1,3})%/'
|
||||
before_script:
|
||||
- apk add --no-cache grep
|
||||
script:
|
||||
- ./gradlew codeCoverageReport
|
||||
# The actual output that will be parsed by the code coverage
|
||||
- grep -oP "Total.*?%" build/reports/jacoco/html/index.html
|
||||
only:
|
||||
- merge_requests
|
||||
- tags
|
||||
6
.idea/ant.xml
generated
6
.idea/ant.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AntConfiguration">
|
||||
<buildFile url="file://$PROJECT_DIR$/build.xml" />
|
||||
</component>
|
||||
</project>
|
||||
41
.idea/compiler.xml
generated
41
.idea/compiler.xml
generated
@@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel>
|
||||
<module name="addressbook_main" target="1.7" />
|
||||
<module name="addressbook_test" target="1.7" />
|
||||
<module name="BOB_main" target="1.7" />
|
||||
<module name="BOB_test" target="1.7" />
|
||||
<module name="core_main" target="1.7" />
|
||||
<module name="core_test" target="1.7" />
|
||||
<module name="desktopgui_main" target="1.7" />
|
||||
<module name="desktopgui_test" target="1.7" />
|
||||
<module name="i2psnark_main" target="1.7" />
|
||||
<module name="i2psnark_test" target="1.7" />
|
||||
<module name="i2ptunnel_main" target="1.7" />
|
||||
<module name="i2ptunnel_test" target="1.7" />
|
||||
<module name="installer_main" target="1.7" />
|
||||
<module name="installer_test" target="1.7" />
|
||||
<module name="jetty_main" target="1.7" />
|
||||
<module name="jetty_test" target="1.7" />
|
||||
<module name="jrobin_main" target="1.7" />
|
||||
<module name="jrobin_test" target="1.7" />
|
||||
<module name="ministreaming_main" target="1.7" />
|
||||
<module name="ministreaming_test" target="1.7" />
|
||||
<module name="router_main" target="1.7" />
|
||||
<module name="router_test" target="1.7" />
|
||||
<module name="routerconsole_main" target="1.7" />
|
||||
<module name="routerconsole_test" target="1.7" />
|
||||
<module name="sam_main" target="1.7" />
|
||||
<module name="sam_test" target="1.7" />
|
||||
<module name="streaming_main" target="1.7" />
|
||||
<module name="streaming_test" target="1.7" />
|
||||
<module name="susidns_main" target="1.7" />
|
||||
<module name="susidns_test" target="1.7" />
|
||||
<module name="susimail_main" target="1.7" />
|
||||
<module name="susimail_test" target="1.7" />
|
||||
<module name="systray_main" target="1.7" />
|
||||
<module name="systray_test" target="1.7" />
|
||||
</bytecodeTargetLevel>
|
||||
</component>
|
||||
</project>
|
||||
3
.idea/copyright/profiles_settings.xml
generated
3
.idea/copyright/profiles_settings.xml
generated
@@ -1,3 +0,0 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings default="" />
|
||||
</component>
|
||||
@@ -1,9 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="javax.servlet.jsp-2.2.0.v201112011158">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jsp/javax.servlet.jsp-2.2.0.v201112011158.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
22
.idea/libraries/jettylib.xml
generated
22
.idea/libraries/jettylib.xml
generated
@@ -1,22 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="jettylib">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-security-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-servlets-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-deploy-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-util-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-servlet-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-http-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-xml-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-server-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/servlet-api-3.0.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-jmx-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-webapp-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-io-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-continuation-8.1.17.v20150415.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/lib/jetty-rewrite-8.1.17.v20150415.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
9
.idea/libraries/jrobin_1_5_9_1.xml
generated
9
.idea/libraries/jrobin_1_5_9_1.xml
generated
@@ -1,9 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="jrobin-1.5.9.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/apps/jrobin/jrobin-1.5.9.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
10
.idea/libraries/lib.xml
generated
10
.idea/libraries/lib.xml
generated
@@ -1,10 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="lib">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/apps/susidns/src/lib/jstl.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/susidns/src/lib/standard.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
9
.idea/libraries/start.xml
generated
9
.idea/libraries/start.xml
generated
@@ -1,9 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="start">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/jetty-distribution-8.1.17.v20150415/start.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
9
.idea/libraries/systray4j.xml
generated
9
.idea/libraries/systray4j.xml
generated
@@ -1,9 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="systray4j">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/apps/systray/java/lib/systray4j.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
9
.idea/libraries/tomcat_coyote_util.xml
generated
9
.idea/libraries/tomcat_coyote_util.xml
generated
@@ -1,9 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="tomcat-coyote-util">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/apache-tomcat/lib/tomcat-coyote-util.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
12
.idea/libraries/tomcat_lib.xml
generated
12
.idea/libraries/tomcat_lib.xml
generated
@@ -1,12 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="tomcat-lib">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/apache-tomcat-deployer/lib/tomcat-juli.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/apache-tomcat-deployer/lib/el-api.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/apache-tomcat-deployer/lib/jasper.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/apps/jetty/apache-tomcat-deployer/lib/jasper-el.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
9
.idea/libraries/wrapper.xml
generated
9
.idea/libraries/wrapper.xml
generated
@@ -1,9 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="wrapper">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/installer/lib/wrapper/all/wrapper.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
9
.idea/libraries/wrapper_win.xml
generated
9
.idea/libraries/wrapper_win.xml
generated
@@ -1,9 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="wrapper-win">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/installer/lib/wrapper/win-all/wrapper.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
57
.idea/misc.xml
generated
57
.idea/misc.xml
generated
@@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ClientPropertiesManager">
|
||||
<properties class="javax.swing.AbstractButton">
|
||||
<property name="hideActionText" class="java.lang.Boolean" />
|
||||
</properties>
|
||||
<properties class="javax.swing.JComponent">
|
||||
<property name="html.disable" class="java.lang.Boolean" />
|
||||
</properties>
|
||||
<properties class="javax.swing.JEditorPane">
|
||||
<property name="JEditorPane.w3cLengthUnits" class="java.lang.Boolean" />
|
||||
<property name="JEditorPane.honorDisplayProperties" class="java.lang.Boolean" />
|
||||
<property name="charset" class="java.lang.String" />
|
||||
</properties>
|
||||
<properties class="javax.swing.JList">
|
||||
<property name="List.isFileList" class="java.lang.Boolean" />
|
||||
</properties>
|
||||
<properties class="javax.swing.JPasswordField">
|
||||
<property name="JPasswordField.cutCopyAllowed" class="java.lang.Boolean" />
|
||||
</properties>
|
||||
<properties class="javax.swing.JSlider">
|
||||
<property name="Slider.paintThumbArrowShape" class="java.lang.Boolean" />
|
||||
<property name="JSlider.isFilled" class="java.lang.Boolean" />
|
||||
</properties>
|
||||
<properties class="javax.swing.JTable">
|
||||
<property name="Table.isFileList" class="java.lang.Boolean" />
|
||||
<property name="JTable.autoStartsEdit" class="java.lang.Boolean" />
|
||||
<property name="terminateEditOnFocusLost" class="java.lang.Boolean" />
|
||||
</properties>
|
||||
<properties class="javax.swing.JToolBar">
|
||||
<property name="JToolBar.isRollover" class="java.lang.Boolean" />
|
||||
</properties>
|
||||
<properties class="javax.swing.JTree">
|
||||
<property name="JTree.lineStyle" class="java.lang.String" />
|
||||
</properties>
|
||||
<properties class="javax.swing.text.JTextComponent">
|
||||
<property name="caretAspectRatio" class="java.lang.Double" />
|
||||
<property name="caretWidth" class="java.lang.Integer" />
|
||||
</properties>
|
||||
</component>
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||
<OptionsSetting value="true" id="Add" />
|
||||
<OptionsSetting value="true" id="Remove" />
|
||||
<OptionsSetting value="true" id="Checkout" />
|
||||
<OptionsSetting value="true" id="Update" />
|
||||
<OptionsSetting value="true" id="Status" />
|
||||
<OptionsSetting value="true" id="Edit" />
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build" />
|
||||
</component>
|
||||
</project>
|
||||
80
.idea/modules.xml
generated
80
.idea/modules.xml
generated
@@ -1,80 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/BOB/BOB.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/BOB/BOB.iml" group="apps/BOB" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/BOB/BOB.iml" filepath="$PROJECT_DIR$/apps/BOB/BOB.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/BOB/BOB_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/BOB/BOB_main.iml" group="apps/BOB" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/BOB/BOB_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/BOB/BOB_test.iml" group="apps/BOB" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/addressbook/addressbook.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/addressbook/addressbook.iml" group="apps/addressbook" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/addressbook/addressbook.iml" filepath="$PROJECT_DIR$/apps/addressbook/addressbook.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/addressbook/addressbook_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/addressbook/addressbook_main.iml" group="apps/addressbook" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/addressbook/addressbook_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/addressbook/addressbook_test.iml" group="apps/addressbook" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/admin/admin.iml" filepath="$PROJECT_DIR$/apps/admin/admin.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/apps.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/apps.iml" group="apps" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/core/core.iml" filepath="$PROJECT_DIR$/.idea/modules/core/core.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/core/core.iml" filepath="$PROJECT_DIR$/core/core.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/core/core_main.iml" filepath="$PROJECT_DIR$/.idea/modules/core/core_main.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/core/core_test.iml" filepath="$PROJECT_DIR$/.idea/modules/core/core_test.iml" group="core" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/desktopgui/desktopgui.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/desktopgui/desktopgui.iml" group="apps/desktopgui" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/desktopgui/desktopgui.iml" filepath="$PROJECT_DIR$/apps/desktopgui/desktopgui.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/desktopgui/desktopgui_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/desktopgui/desktopgui_main.iml" group="apps/desktopgui" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/desktopgui/desktopgui_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/desktopgui/desktopgui_test.iml" group="apps/desktopgui" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/i2p.i2p.sl.iml" filepath="$PROJECT_DIR$/.idea/modules/i2p.i2p.sl.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/i2psnark/i2psnark.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/i2psnark/i2psnark.iml" group="apps/i2psnark" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/i2psnark/i2psnark.iml" filepath="$PROJECT_DIR$/apps/i2psnark/i2psnark.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/i2psnark/i2psnark_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/i2psnark/i2psnark_main.iml" group="apps/i2psnark" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/i2psnark/i2psnark_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/i2psnark/i2psnark_test.iml" group="apps/i2psnark" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/i2ptunnel/i2ptunnel.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/i2ptunnel/i2ptunnel.iml" group="apps/i2ptunnel" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/i2ptunnel/i2ptunnel.iml" filepath="$PROJECT_DIR$/apps/i2ptunnel/i2ptunnel.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/i2ptunnel/i2ptunnel_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/i2ptunnel/i2ptunnel_main.iml" group="apps/i2ptunnel" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/i2ptunnel/i2ptunnel_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/i2ptunnel/i2ptunnel_test.iml" group="apps/i2ptunnel" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/imagegen/identicon/identicon.iml" filepath="$PROJECT_DIR$/apps/imagegen/identicon/identicon.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/imagegen/imagegen/imagegen.iml" filepath="$PROJECT_DIR$/apps/imagegen/imagegen/imagegen.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/installer/installer.iml" filepath="$PROJECT_DIR$/.idea/modules/installer/installer.iml" group="installer" />
|
||||
<module fileurl="file://$PROJECT_DIR$/installer/installer.iml" filepath="$PROJECT_DIR$/installer/installer.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/installer/installer_main.iml" filepath="$PROJECT_DIR$/.idea/modules/installer/installer_main.iml" group="installer" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/installer/installer_test.iml" filepath="$PROJECT_DIR$/.idea/modules/installer/installer_test.iml" group="installer" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/jetty/jetty.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/jetty/jetty.iml" group="apps/jetty" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/jetty/jetty.iml" filepath="$PROJECT_DIR$/apps/jetty/jetty.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/jetty/jetty_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/jetty/jetty_main.iml" group="apps/jetty" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/jetty/jetty_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/jetty/jetty_test.iml" group="apps/jetty" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/jrobin/jrobin.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/jrobin/jrobin.iml" group="apps/jrobin" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/jrobin/jrobin_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/jrobin/jrobin_main.iml" group="apps/jrobin" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/jrobin/jrobin_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/jrobin/jrobin_test.iml" group="apps/jrobin" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/ministreaming/ministreaming.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/ministreaming/ministreaming.iml" group="apps/ministreaming" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/ministreaming/ministreaming.iml" filepath="$PROJECT_DIR$/apps/ministreaming/ministreaming.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/ministreaming/ministreaming_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/ministreaming/ministreaming_main.iml" group="apps/ministreaming" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/ministreaming/ministreaming_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/ministreaming/ministreaming_test.iml" group="apps/ministreaming" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/router/router.iml" filepath="$PROJECT_DIR$/.idea/modules/router/router.iml" group="router" />
|
||||
<module fileurl="file://$PROJECT_DIR$/router/router.iml" filepath="$PROJECT_DIR$/router/router.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/router/router_main.iml" filepath="$PROJECT_DIR$/.idea/modules/router/router_main.iml" group="router" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/router/router_test.iml" filepath="$PROJECT_DIR$/.idea/modules/router/router_test.iml" group="router" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/routerconsole/routerconsole.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/routerconsole/routerconsole.iml" group="apps/routerconsole" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/routerconsole/routerconsole.iml" filepath="$PROJECT_DIR$/apps/routerconsole/routerconsole.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/routerconsole/routerconsole_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/routerconsole/routerconsole_main.iml" group="apps/routerconsole" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/routerconsole/routerconsole_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/routerconsole/routerconsole_test.iml" group="apps/routerconsole" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/sam/sam.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/sam/sam.iml" group="apps/sam" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/sam/sam.iml" filepath="$PROJECT_DIR$/apps/sam/sam.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/sam/sam_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/sam/sam_main.iml" group="apps/sam" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/sam/sam_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/sam/sam_test.iml" group="apps/sam" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/streaming/streaming.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/streaming/streaming.iml" group="apps/streaming" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/streaming/streaming.iml" filepath="$PROJECT_DIR$/apps/streaming/streaming.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/streaming/streaming_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/streaming/streaming_main.iml" group="apps/streaming" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/streaming/streaming_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/streaming/streaming_test.iml" group="apps/streaming" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/susidns/susidns.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/susidns/susidns.iml" group="apps/susidns" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/susidns/susidns.iml" filepath="$PROJECT_DIR$/apps/susidns/susidns.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/susidns/susidns_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/susidns/susidns_main.iml" group="apps/susidns" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/susidns/susidns_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/susidns/susidns_test.iml" group="apps/susidns" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/susimail/susimail.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/susimail/susimail.iml" group="apps/susimail" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/susimail/susimail.iml" filepath="$PROJECT_DIR$/apps/susimail/susimail.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/susimail/susimail_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/susimail/susimail_main.iml" group="apps/susimail" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/susimail/susimail_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/susimail/susimail_test.iml" group="apps/susimail" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/systray/systray.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/systray/systray.iml" group="apps/systray" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/systray/systray.iml" filepath="$PROJECT_DIR$/apps/systray/systray.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/systray/systray_main.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/systray/systray_main.iml" group="apps/systray" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/apps/systray/systray_test.iml" filepath="$PROJECT_DIR$/.idea/modules/apps/systray/systray_test.iml" group="apps/systray" />
|
||||
<module fileurl="file://$PROJECT_DIR$/apps/imagegen/zxing/zxing.iml" filepath="$PROJECT_DIR$/apps/imagegen/zxing/zxing.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/runConfigurations/updater.xml
generated
6
.idea/runConfigurations/updater.xml
generated
@@ -1,6 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="updater" type="AntRunConfiguration" factoryName="Ant Target">
|
||||
<antsettings antfile="file://$PROJECT_DIR$/build.xml" target="updater" />
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
||||
37
.travis.yml
37
.travis.yml
@@ -1,39 +1,18 @@
|
||||
language: java
|
||||
dist: trusty
|
||||
dist: bionic
|
||||
|
||||
jdk:
|
||||
- oraclejdk11
|
||||
- oraclejdk9
|
||||
- openjdk12
|
||||
- openjdk11
|
||||
- openjdk10
|
||||
- openjdk9
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- jdk: oraclejdk8
|
||||
- jdk: oraclejdk11
|
||||
addons:
|
||||
sonarcloud:
|
||||
organization: "i2p"
|
||||
before_install:
|
||||
- export JAVA7_HOME=$(jdk_switcher home openjdk7)
|
||||
- sed -i "1iplugins {\n id 'org.sonarqube' version '2.6.1'\n}\n" build.gradle
|
||||
- sed -i "1iplugins {\n id 'org.sonarqube' version '3.0'\n}\n" build.gradle
|
||||
- jdk: openjdk8
|
||||
before_install:
|
||||
- export JAVA7_HOME=$(jdk_switcher home openjdk7)
|
||||
- jdk: openjdk7
|
||||
sudo: required
|
||||
before_install: # Work around missing crypto in openjdk7
|
||||
- export JAVA7_HOME=$(jdk_switcher home openjdk7)
|
||||
- sudo wget "https://bouncycastle.org/download/bcprov-ext-jdk15on-158.jar" -O "${JAVA_HOME}/jre/lib/ext/bcprov-ext-jdk15on-158.jar"
|
||||
- sudo perl -pi.bak -e 's/^(security\.provider\.)([0-9]+)/$1.($2+1)/ge' /etc/java-7-openjdk/security/java.security
|
||||
- echo "security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider" | sudo tee -a /etc/java-7-openjdk/security/java.security
|
||||
install:
|
||||
- export TARGET_JAVA_HOME=$JAVA_HOME
|
||||
- jdk_switcher use oraclejdk8
|
||||
- ./gradlew assemble
|
||||
allow_failures:
|
||||
- jdk: openjdk12
|
||||
|
||||
before_cache:
|
||||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||
@@ -45,13 +24,11 @@ cache:
|
||||
- $HOME/.sonar/cache/
|
||||
- .gradle
|
||||
|
||||
env:
|
||||
- SONAR_SCANNER_OPTS="-Xmx2048m"
|
||||
|
||||
script:
|
||||
- |
|
||||
if [ "$TRAVIS_JDK_VERSION" == "oraclejdk8" ]; then
|
||||
./gradlew sonarqube codeCoverageReport
|
||||
else
|
||||
./gradlew check codeCoverageReport
|
||||
fi
|
||||
- travis_wait 45 ./tests/scripts/travis.sh
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
40
.tx/config
40
.tx/config
@@ -87,6 +87,7 @@ trans.id = core/locale/messages_in.po
|
||||
trans.it = core/locale/messages_it.po
|
||||
trans.ja = core/locale/messages_ja.po
|
||||
trans.ko = core/locale/messages_ko.po
|
||||
trans.ku = core/locale/messages_ku.po
|
||||
trans.nb = core/locale/messages_nb.po
|
||||
trans.nl = core/locale/messages_nl.po
|
||||
trans.pl = core/locale/messages_pl.po
|
||||
@@ -95,6 +96,7 @@ trans.pt_BR = core/locale/messages_pt_BR.po
|
||||
trans.ro = core/locale/messages_ro.po
|
||||
trans.ru_RU = core/locale/messages_ru.po
|
||||
trans.sv_SE = core/locale/messages_sv.po
|
||||
trans.tk = core/locale/messages_tk.po
|
||||
trans.tr_TR = core/locale/messages_tr.po
|
||||
trans.uk_UA = core/locale/messages_uk.po
|
||||
trans.vi = core/locale/messages_vi.po
|
||||
@@ -122,6 +124,7 @@ trans.id = router/locale/messages_in.po
|
||||
trans.it = router/locale/messages_it.po
|
||||
trans.ja = router/locale/messages_ja.po
|
||||
trans.ko = router/locale/messages_ko.po
|
||||
trans.ku = router/locale/messages_ku.po
|
||||
trans.nb = router/locale/messages_nb.po
|
||||
trans.nl = router/locale/messages_nl.po
|
||||
trans.pl = router/locale/messages_pl.po
|
||||
@@ -130,6 +133,7 @@ trans.pt_BR = router/locale/messages_pt_BR.po
|
||||
trans.ro = router/locale/messages_ro.po
|
||||
trans.ru_RU = router/locale/messages_ru.po
|
||||
trans.sv_SE = router/locale/messages_sv.po
|
||||
trans.tk = router/locale/messages_tk.po
|
||||
trans.tr_TR = router/locale/messages_tr.po
|
||||
trans.uk_UA = router/locale/messages_uk.po
|
||||
trans.vi = router/locale/messages_vi.po
|
||||
@@ -190,6 +194,7 @@ trans.id = apps/routerconsole/locale-news/messages_in.po
|
||||
trans.it = apps/routerconsole/locale-news/messages_it.po
|
||||
trans.ja = apps/routerconsole/locale-news/messages_ja.po
|
||||
trans.ko = apps/routerconsole/locale-news/messages_ko.po
|
||||
trans.ku = apps/routerconsole/locale-news/messages_ku.po
|
||||
trans.mg = apps/routerconsole/locale-news/messages_mg.po
|
||||
trans.nb = apps/routerconsole/locale-news/messages_nb.po
|
||||
trans.nl = apps/routerconsole/locale-news/messages_nl.po
|
||||
@@ -202,6 +207,7 @@ trans.sk = apps/routerconsole/locale-news/messages_sk.po
|
||||
trans.sq = apps/routerconsole/locale-news/messages_sq.po
|
||||
trans.sr = apps/routerconsole/locale-news/messages_sr.po
|
||||
trans.sv_SE = apps/routerconsole/locale-news/messages_sv.po
|
||||
trans.tk = apps/routerconsole/locale-news/messages_tk.po
|
||||
trans.tr_TR = apps/routerconsole/locale-news/messages_tr.po
|
||||
trans.uk_UA = apps/routerconsole/locale-news/messages_uk.po
|
||||
trans.zh_CN = apps/routerconsole/locale-news/messages_zh.po
|
||||
@@ -235,6 +241,7 @@ trans.id = apps/routerconsole/locale-countries/messages_in.po
|
||||
trans.it = apps/routerconsole/locale-countries/messages_it.po
|
||||
trans.ja = apps/routerconsole/locale-countries/messages_ja.po
|
||||
trans.ko = apps/routerconsole/locale-countries/messages_ko.po
|
||||
trans.ku = apps/routerconsole/locale-countries/messages_ku.po
|
||||
trans.mg = apps/routerconsole/locale-countries/messages_mg.po
|
||||
trans.nb = apps/routerconsole/locale-countries/messages_nb.po
|
||||
trans.nl = apps/routerconsole/locale-countries/messages_nl.po
|
||||
@@ -247,6 +254,7 @@ trans.sk = apps/routerconsole/locale-countries/messages_sk.po
|
||||
trans.sq = apps/routerconsole/locale-countries/messages_sq.po
|
||||
trans.sr = apps/routerconsole/locale-countries/messages_sr.po
|
||||
trans.sv_SE = apps/routerconsole/locale-countries/messages_sv.po
|
||||
trans.tk = apps/routerconsole/locale-countries/messages_tk.po
|
||||
trans.tr_TR = apps/routerconsole/locale-countries/messages_tr.po
|
||||
trans.uk_UA = apps/routerconsole/locale-countries/messages_uk.po
|
||||
trans.vi = apps/routerconsole/locale-countries/messages_vi.po
|
||||
@@ -330,6 +338,7 @@ trans.da = apps/desktopgui/locale/messages_da.po
|
||||
trans.de = apps/desktopgui/locale/messages_de.po
|
||||
trans.el = apps/desktopgui/locale/messages_el.po
|
||||
trans.es = apps/desktopgui/locale/messages_es.po
|
||||
trans.es_AR = apps/desktopgui/locale/messages_es_AR.po
|
||||
trans.fa = apps/desktopgui/locale/messages_fa.po
|
||||
trans.fi = apps/desktopgui/locale/messages_fi.po
|
||||
trans.fr = apps/desktopgui/locale/messages_fr.po
|
||||
@@ -340,6 +349,7 @@ trans.id = apps/desktopgui/locale/messages_in.po
|
||||
trans.it = apps/desktopgui/locale/messages_it.po
|
||||
trans.ja = apps/desktopgui/locale/messages_ja.po
|
||||
trans.ko = apps/desktopgui/locale/messages_ko.po
|
||||
trans.ku = apps/desktopgui/locale/messages_ku.po
|
||||
trans.mg = apps/desktopgui/locale/messages_mg.po
|
||||
trans.nb = apps/desktopgui/locale/messages_nb.po
|
||||
trans.nl = apps/desktopgui/locale/messages_nl.po
|
||||
@@ -353,6 +363,7 @@ trans.sr = apps/desktopgui/locale/messages_sr.po
|
||||
trans.sv_SE = apps/desktopgui/locale/messages_sv.po
|
||||
trans.sq = apps/desktopgui/locale/messages_sq.po
|
||||
trans.uk_UA = apps/desktopgui/locale/messages_uk.po
|
||||
trans.tk = apps/desktopgui/locale/messages_tk.po
|
||||
trans.tr_TR = apps/desktopgui/locale/messages_tr.po
|
||||
trans.vi = apps/desktopgui/locale/messages_vi.po
|
||||
trans.zh_CN = apps/desktopgui/locale/messages_zh.po
|
||||
@@ -428,6 +439,7 @@ trans.ru_RU = debian/po/ru.po
|
||||
trans.sk = debian/po/sk.po
|
||||
trans.sq = debian/po/sq.po
|
||||
trans.sv_SE = debian/po/sv.po
|
||||
trans.tk = debian/po/tk.po
|
||||
trans.tr_TR = debian/po/tr.po
|
||||
trans.uk_UA = debian/po/uk.po
|
||||
trans.zh_CN = debian/po/zh.po
|
||||
@@ -494,6 +506,7 @@ trans.id = core/java/src/gnu/getopt/MessagesBundle_in.properties
|
||||
trans.it = core/java/src/gnu/getopt/MessagesBundle_it.properties
|
||||
trans.ja = core/java/src/gnu/getopt/MessagesBundle_ja.properties
|
||||
trans.ko = core/java/src/gnu/getopt/MessagesBundle_ko.properties
|
||||
trans.ku = core/java/src/gnu/getopt/MessagesBundle_ku.properties
|
||||
trans.nb = core/java/src/gnu/getopt/MessagesBundle_nb.properties
|
||||
trans.nl = core/java/src/gnu/getopt/MessagesBundle_nl.properties
|
||||
trans.pl = core/java/src/gnu/getopt/MessagesBundle_pl.properties
|
||||
@@ -536,6 +549,7 @@ trans.pt_BR = apps/ministreaming/locale/messages_pt_BR.po
|
||||
trans.ro = apps/ministreaming/locale/messages_ro.po
|
||||
trans.ru_RU = apps/ministreaming/locale/messages_ru.po
|
||||
trans.sv_SE = apps/ministreaming/locale/messages_sv.po
|
||||
trans.tk = apps/ministreaming/locale/messages_tk.po
|
||||
trans.tr_TR = apps/ministreaming/locale/messages_tr.po
|
||||
trans.uk_UA = apps/ministreaming/locale/messages_uk.po
|
||||
trans.zh_CN = apps/ministreaming/locale/messages_zh.po
|
||||
@@ -605,21 +619,21 @@ trans.tr_TR = installer/resources/eepsite/docroot/help/index_tr.html
|
||||
;; Text on /console
|
||||
;;
|
||||
type = HTML
|
||||
source_file = installer/resources/readme/readme.html
|
||||
source_file = apps/routerconsole/resources/docs/readme.html
|
||||
source_lang = en
|
||||
trans.ar = installer/resources/readme/readme_ar.html
|
||||
trans.de = installer/resources/readme/readme_de.html
|
||||
trans.fr = installer/resources/readme/readme_fr.html
|
||||
trans.ar = apps/routerconsole/resources/docs/readme_ar.html
|
||||
trans.de = apps/routerconsole/resources/docs/readme_de.html
|
||||
trans.fr = apps/routerconsole/resources/docs/readme_fr.html
|
||||
;; Java converts id to in
|
||||
trans.id = installer/resources/readme/readme_in.html
|
||||
trans.it = installer/resources/readme/readme_it.html
|
||||
trans.ja = installer/resources/readme/readme_ja.html
|
||||
trans.pl = installer/resources/readme/readme_pl.html
|
||||
trans.pt = installer/resources/readme/readme_pt.html
|
||||
trans.ro = installer/resources/readme/readme_ro.html
|
||||
trans.ru_RU = installer/resources/readme/readme_ru.html
|
||||
trans.tr_TR = installer/resources/readme/readme_tr.html
|
||||
trans.zh_CN = installer/resources/readme/readme_zh.html
|
||||
trans.id = apps/routerconsole/resources/docs/readme_in.html
|
||||
trans.it = apps/routerconsole/resources/docs/readme_it.html
|
||||
trans.ja = apps/routerconsole/resources/docs/readme_ja.html
|
||||
trans.pl = apps/routerconsole/resources/docs/readme_pl.html
|
||||
trans.pt = apps/routerconsole/resources/docs/readme_pt.html
|
||||
trans.ro = apps/routerconsole/resources/docs/readme_ro.html
|
||||
trans.ru_RU = apps/routerconsole/resources/docs/readme_ru.html
|
||||
trans.tr_TR = apps/routerconsole/resources/docs/readme_tr.html
|
||||
trans.zh_CN = apps/routerconsole/resources/docs/readme_zh.html
|
||||
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
@@ -40,7 +40,7 @@ To uninstall I2P:
|
||||
rm -rf $I2PInstallDir ~/.i2p
|
||||
|
||||
Supported JVMs:
|
||||
All platforms: Java 1.7 or higher required
|
||||
All platforms: Java 1.8 or higher required
|
||||
Windows: OpenJDK or Oracle from http://java.com/download
|
||||
Linux: OpenJDK or Oracle from http://java.com/download
|
||||
FreeBSD: OpenJDK or Oracle from http://java.com/download
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
I2P source installation instructions
|
||||
|
||||
Prerequisites to build from source:
|
||||
Java SDK (preferably Oracle/Sun or OpenJDK) 1.7.0 or higher
|
||||
Java SDK (preferably Oracle or OpenJDK) 8 or higher
|
||||
Non-linux operating systems and JVMs: See https://trac.i2p2.de/wiki/java
|
||||
Certain subsystems for embedded (core, router, mstreaming, streaming, i2ptunnel) require only Java 1.6
|
||||
Apache Ant 1.7.0 or higher
|
||||
Apache Ant 1.9.8 or higher
|
||||
The xgettext, msgfmt, and msgmerge tools installed
|
||||
from the GNU gettext package http://www.gnu.org/software/gettext/
|
||||
Build environment must use a UTF-8 locale.
|
||||
|
||||
38
LICENSE.txt
38
LICENSE.txt
@@ -36,10 +36,6 @@ Public domain except as listed below:
|
||||
Copyright (c) 2003, TheCrypto
|
||||
See licenses/LICENSE-ElGamalDSA.txt
|
||||
|
||||
HMAC:
|
||||
Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
|
||||
See licenses/LICENSE-SHA256.txt
|
||||
|
||||
ElGamal:
|
||||
Copyright (c) 2000 - 2013 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org)
|
||||
See licenses/LICENSE-SHA256.txt
|
||||
@@ -89,14 +85,21 @@ Public domain except as listed below:
|
||||
From Apache HttpClient 4.4.1 and HttpCore 4.4.1
|
||||
See licenses/LICENSE-Apache2.0.txt
|
||||
|
||||
json-simple 1.1.1
|
||||
json-simple 2.3.0
|
||||
(not included in most distribution packages)
|
||||
Copyright 2016 Clifton Labs
|
||||
See licenses/LICENSE-Apache2.0.txt
|
||||
|
||||
Noise library:
|
||||
Copyright (C) 2016 Southern Storm Software, Pty Ltd.
|
||||
See licenses/LICENSE-Noise.txt
|
||||
|
||||
MiniDNS library 1.0.0
|
||||
This software may be used under the terms of (at your choice)
|
||||
- LGPL version 2 (or later) (see licenses/LICENSE-LGPL2.1.txt)
|
||||
- Apache Software licence (see licenses/LICENSE-Apache2.0.txt)
|
||||
- DWTFYWTPL
|
||||
|
||||
|
||||
Router (router.jar):
|
||||
Public domain except as listed below:
|
||||
@@ -125,6 +128,10 @@ Public domain except as listed below:
|
||||
Copyright (C) 2006 The Android Open Source Project
|
||||
See licenses/LICENSE-Apache2.0.txt
|
||||
|
||||
SSU HMAC:
|
||||
Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
|
||||
See licenses/LICENSE-SHA256.txt
|
||||
|
||||
|
||||
Installer:
|
||||
(not included in distribution packages)
|
||||
@@ -171,18 +178,18 @@ Installer:
|
||||
|
||||
GeoIP Data:
|
||||
(not included in most distribution packages)
|
||||
This product includes GeoLite2 data created by MaxMind, available from http://www.maxmind.com/
|
||||
See licenses/LICENSE-GeoIP.txt
|
||||
IP Geolocation by DB-IP https://db-ip.com/
|
||||
See https://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
Launchers:
|
||||
(not included in distribution packages)
|
||||
Copyright (c) 2002-2018 EPFL, Lausanne / Lightbend, Inc. , unless otherwise specified.
|
||||
See licenses/LICENSE-Scala.md
|
||||
|
||||
Java Service Wrapper Community Edition 3.5.39:
|
||||
Java Service Wrapper Community Edition 3.5.44:
|
||||
(Windows: 3.5.25)
|
||||
(not included in most distribution packages)
|
||||
Copyright (C) 1999-2019 Tanuki Software, Ltd. All Rights Reserved.
|
||||
Copyright (C) 1999-2020 Tanuki Software, Ltd. All Rights Reserved.
|
||||
See licenses/LICENSE-Wrapper.txt
|
||||
|
||||
|
||||
@@ -192,7 +199,7 @@ Jbigi Libraries (jbigi.jar):
|
||||
GMP 4.3.2 / 5.0.2:
|
||||
Copyright 1991, 1996, 1999, 2000, 2007 Free Software Foundation, Inc.
|
||||
See licenses/LICENSE-LGPLv3.txt
|
||||
GMP 6.0.0 / 6.1.2:
|
||||
GMP 6.0.0 / 6.1.2 / 6.2.0:
|
||||
See licenses/LICENSE-GPLv2.txt
|
||||
|
||||
|
||||
@@ -254,17 +261,17 @@ Applications:
|
||||
Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
||||
See licenses/LICENSE-BSD.txt
|
||||
Zxing 3.3.0:
|
||||
Zxing 3.4.1:
|
||||
See licenses/LICENSE-Apache2.0.txt
|
||||
|
||||
Jetty 9.2.29.v20191105 (jetty-*.jar, org.mortbay.*.jar):
|
||||
Jetty 9.3.29.v20201019 (jetty-*.jar, org.mortbay.*.jar):
|
||||
(not included in most distribution packages, except for jetty-i2p.jar)
|
||||
See licenses/ABOUT-Jetty.html
|
||||
See licenses/NOTICE-Jetty.html
|
||||
See licenses/LICENSE-Apache2.0.txt
|
||||
See licenses/LICENSE-ECLIPSE-1.0.html
|
||||
|
||||
RRD4J 3.5 (jrobin.jar):
|
||||
RRD4J 3.6 (jrobin.jar):
|
||||
Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
|
||||
Copyright (c) 2011 The OpenNMS Group, Inc.
|
||||
Copyright 2011 The RRD4J Authors.
|
||||
@@ -293,6 +300,7 @@ Applications:
|
||||
FatCow icons: See licenses/LICENSE-FatCowIcons.txt
|
||||
Fugue Icons: See licenses/LICENSE-FugueIcons.txt
|
||||
Feather icons: Copyright (c) 2013-2017 Cole Bemis; see licenses/LICENSE-Feather.txt
|
||||
Fontawesome icons: Copyright (c) 2018 @fontawesome(company) see licenses/LICENSE-fontawesome.txt
|
||||
|
||||
Router Console unthemed, light, and dark theme logos:
|
||||
Copyright (c) 2019 The Invisible Internet Project. All rights reserved.
|
||||
@@ -331,9 +339,9 @@ Applications:
|
||||
Systray (systray.jar):
|
||||
Public domain.
|
||||
|
||||
Tomcat 8.5.50 (jasper-runtime.jar):
|
||||
Tomcat 9.0.40 (jasper-runtime.jar):
|
||||
(not included in most distribution packages)
|
||||
Copyright 1999-2019 The Apache Software Foundation
|
||||
Copyright 1999-2020 The Apache Software Foundation
|
||||
See licenses/LICENSE-Apache2.0.txt
|
||||
See licenses/NOTICE-Tomcat.txt
|
||||
|
||||
|
||||
30
README.md
30
README.md
@@ -2,19 +2,19 @@
|
||||
|
||||
This is the source code for the reference Java implementation of I2P.
|
||||
|
||||
Latest release: https://geti2p.net/download
|
||||
Latest release: [https://geti2p.net/download](https://geti2p.net/download)
|
||||
|
||||
## Installing
|
||||
|
||||
See INSTALL.txt or https://geti2p.net/download for installation instructions.
|
||||
See [INSTALL.txt](INSTALL.txt) or [https://geti2p.net/download](https://geti2p.net/download) for installation instructions.
|
||||
|
||||
## Documentation
|
||||
|
||||
https://geti2p.net/how
|
||||
[https://geti2p.net/how](https://geti2p.net/how)
|
||||
|
||||
FAQ: https://geti2p.net/faq
|
||||
FAQ: [https://geti2p.net/faq](https://geti2p.net/faq)
|
||||
|
||||
API: http://docs.i2p-projekt.de/javadoc/
|
||||
API: [http://docs.i2p-projekt.de/javadoc/](http://docs.i2p-projekt.de/javadoc/)
|
||||
or run 'ant javadoc' then start at build/javadoc/index.html
|
||||
|
||||
## How to contribute / Hack on I2P
|
||||
@@ -23,17 +23,17 @@ Please check out [HACKING.md](docs/HACKING.md) and other documents in the docs d
|
||||
|
||||
## Building packages from source
|
||||
|
||||
To get development branch from source control: https://geti2p.net/newdevelopers
|
||||
To get development branch from source control: [https://geti2p.net/newdevelopers](https://geti2p.net/newdevelopers)
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Java SDK (preferably Oracle/Sun or OpenJDK) 1.7.0 or higher
|
||||
- Non-linux operating systems and JVMs: See https://trac.i2p2.de/wiki/java
|
||||
- Java SDK (preferably Oracle or OpenJDK) 8 or higher
|
||||
- Non-linux operating systems and JVMs: See [https://trac.i2p2.de/wiki/java](https://trac.i2p2.de/wiki/java)
|
||||
- Certain subsystems for embedded (core, router, mstreaming, streaming, i2ptunnel)
|
||||
require only Java 1.6
|
||||
- Apache Ant 1.7.0 or higher
|
||||
require only Java 6
|
||||
- Apache Ant 1.9.8 or higher
|
||||
- The xgettext, msgfmt, and msgmerge tools installed from the GNU gettext package
|
||||
http://www.gnu.org/software/gettext/
|
||||
[http://www.gnu.org/software/gettext/](http://www.gnu.org/software/gettext/)
|
||||
- Build environment must use a UTF-8 locale.
|
||||
|
||||
### Ant build process
|
||||
@@ -68,13 +68,13 @@ your `~/.gradle/gradle.properties`:
|
||||
|
||||
Need help? See the IRC channel #i2p on irc.freenode.net
|
||||
|
||||
Bug reports: https://trac.i2p2.de/report/1
|
||||
Bug reports: [https://trac.i2p2.de/report/1](https://trac.i2p2.de/report/1)
|
||||
|
||||
Contact information, security issues, press inquiries: https://geti2p.net/en/contact
|
||||
Contact information, security issues, press inquiries: [https://geti2p.net/en/contact](https://geti2p.net/en/contact)
|
||||
|
||||
Twitter: @i2p, @geti2p
|
||||
Twitter: [@i2p](https://twitter.com/i2p), [@geti2p](https://twitter.com/GetI2P)
|
||||
|
||||
## Licenses
|
||||
|
||||
See LICENSE.txt
|
||||
See [LICENSE.txt](LICENSE.txt)
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Prerequisites to build from source:
|
||||
Java SDK (preferably Oracle/Sun or OpenJDK) 1.7.0 or higher
|
||||
Java SDK (preferably Oracle or OpenJDK) 8 or higher
|
||||
Non-linux operating systems and JVMs: See https://trac.i2p2.de/wiki/java
|
||||
Certain subsystems for embedded (core, router, mstreaming, streaming, i2ptunnel) require only Java 1.6
|
||||
Apache Ant 1.7.0 or higher
|
||||
Certain subsystems for embedded (core, router, mstreaming, streaming, i2ptunnel) require only Java 6
|
||||
Apache Ant 1.9.8 or higher
|
||||
The xgettext, msgfmt, and msgmerge tools installed
|
||||
from the GNU gettext package http://www.gnu.org/software/gettext/
|
||||
Build environment must use a UTF-8 locale.
|
||||
|
||||
@@ -39,8 +39,9 @@ is divided into following sections:
|
||||
<property file="${user.properties.file}"/>
|
||||
<!-- The two properties below are usually overridden -->
|
||||
<!-- by the active platform. Just a fallback. -->
|
||||
<property name="default.javac.source" value="1.4"/>
|
||||
<property name="default.javac.target" value="1.4"/>
|
||||
<property name="default.javac.source" value="1.8"/>
|
||||
<property name="default.javac.target" value="1.8"/>
|
||||
<property name="javac.release" value="8"/>
|
||||
</target>
|
||||
<target depends="-pre-init,-init-private,-init-user" name="-init-project">
|
||||
<property file="nbproject/configs/${config}.properties"/>
|
||||
@@ -155,7 +156,7 @@ is divided into following sections:
|
||||
<attribute default="/does/not/exist" name="sourcepath"/>
|
||||
<element name="customize" optional="true"/>
|
||||
<sequential>
|
||||
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
|
||||
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" release="${javac.release}">
|
||||
<classpath>
|
||||
<path path="@{classpath}"/>
|
||||
</classpath>
|
||||
|
||||
@@ -29,28 +29,19 @@ endorsed.classpath=
|
||||
excludes=**/*.html,**/*.txt
|
||||
file.reference.build-javadoc=../../i2p.i2p/build/javadoc
|
||||
file.reference.i2p.jar=../../core/java/build/i2p.jar
|
||||
file.reference.i2ptunnel.jar=../i2ptunnel/java/build/i2ptunnel.jar
|
||||
file.reference.jbigi.jar=../../build/jbigi.jar
|
||||
file.reference.mstreaming.jar=../ministreaming/java/build/mstreaming.jar
|
||||
file.reference.router.jar=../../router/java/build/router.jar
|
||||
file.reference.streaming.jar=../streaming/java/build/streaming.jar
|
||||
file.reference.wrapper.jar=../../installer/lib/wrapper/all/wrapper.jar
|
||||
includes=**
|
||||
jar.compress=true
|
||||
javac.classpath=\
|
||||
${file.reference.router.jar}:\
|
||||
${file.reference.i2ptunnel.jar}:\
|
||||
${file.reference.mstreaming.jar}:\
|
||||
${file.reference.streaming.jar}:\
|
||||
${file.reference.wrapper.jar}:\
|
||||
${file.reference.i2p.jar}:\
|
||||
${file.reference.router.jar}
|
||||
${file.reference.i2p.jar}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.version=1.7
|
||||
javac.version=1.8
|
||||
javac.source=${javac.version}
|
||||
javac.target=${javac.version}
|
||||
javac.release=8
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}:\
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>BOB</name>
|
||||
<minimum-ant-version>1.6.5</minimum-ant-version>
|
||||
<minimum-ant-version>1.9.8</minimum-ant-version>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
|
||||
@@ -38,6 +38,7 @@ import net.i2p.I2PAppContext;
|
||||
import net.i2p.app.*;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.PortMapper;
|
||||
import net.i2p.util.SimpleTimer2;
|
||||
|
||||
@@ -111,7 +112,9 @@ import net.i2p.util.SimpleTimer2;
|
||||
* BOB, main command socket listener, launches the command parser engine.
|
||||
*
|
||||
* @author sponge
|
||||
* @deprecated Please port applications to SAMv3
|
||||
*/
|
||||
@Deprecated
|
||||
public class BOB implements Runnable, ClientApp {
|
||||
|
||||
public final static String PROP_CONFIG_LOCATION = "BOB.config";
|
||||
@@ -140,6 +143,7 @@ public class BOB implements Runnable, ClientApp {
|
||||
|
||||
private volatile ServerSocket listener;
|
||||
private volatile Thread _runner;
|
||||
private volatile boolean _warned;
|
||||
|
||||
/**
|
||||
* Stop BOB gracefully
|
||||
@@ -342,6 +346,12 @@ public class BOB implements Runnable, ClientApp {
|
||||
}
|
||||
|
||||
if (g) {
|
||||
if (!_warned) {
|
||||
_warned = true;
|
||||
String s = "BOB is deprecated. Please port applications to SAMv3.";
|
||||
_context.logManager().getLog(BOB.class).logAlways(Log.WARN, s);
|
||||
_log.warn(s);
|
||||
}
|
||||
DoCMDS conn_c = new DoCMDS(spin, lock, server, props, database, _log);
|
||||
Thread t = new I2PAppThread(conn_c);
|
||||
t.setName("BOB.DoCMDS " + i);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>BOB, the Basic Open Bridge, allows TCP applications to talk over I2P.</p>
|
||||
<p>BOB, the Basic Open Bridge, allows TCP applications to talk over I2P - DEPRECATED - Please port applications to SAMv3.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
addressbook v2.0.2 - A simple name resolution mechanism for I2P
|
||||
|
||||
addressbook is a simple implementation of subscribable address books for I2P.
|
||||
Addresses are stored in userhosts.txt and a second copy of the address book is
|
||||
placed on your eepsite as hosts.txt.
|
||||
|
||||
subscriptions.txt contains a list of urls to check for new addresses.
|
||||
Since the urls are checked in order, and conflicting addresses are not added,
|
||||
addressbook.subscriptions can be considered to be ranked in order of trust.
|
||||
|
||||
The system created by addressbook is similar to the early days of DNS,
|
||||
when everyone ran a local name server. The major difference is the lack of
|
||||
authority. Name cannot be guaranteed to be globally unique, but in practise
|
||||
they probably will be, for a variety of social reasons.
|
||||
|
||||
Requirements
|
||||
************
|
||||
|
||||
i2p with a running http proxy
|
||||
|
||||
Installation and Usage
|
||||
**********************
|
||||
|
||||
1. Unzip addressbook-%ver.zip into your i2p directory.
|
||||
2. Restart your router.
|
||||
|
||||
The addressbook daemon will automatically run while the router is up.
|
||||
|
||||
Aside from the daemon itself, the other elements of the addressbook interface
|
||||
are the config.txt, myhosts.txt, and subscriptions.txt files found in the addressbook
|
||||
directory.
|
||||
|
||||
config.txt is the configuration file for addressbook.
|
||||
|
||||
myhosts.txt is the addressbook master address book. Addresses placed in this file
|
||||
take precidence over those in the router address book and in remote address books.
|
||||
If changes are made to this file, they will be reflected in the router address book
|
||||
and published address book after the next update. Do not make changes directly to the
|
||||
router address book, as they could be lost during an update.
|
||||
|
||||
subscriptions.txt is the subscription list for addressbook. Each entry is an absolute
|
||||
url to a file in hosts.txt format. Since the list is checked in order, url's should be
|
||||
listed in order of trust.
|
||||
@@ -7,7 +7,8 @@
|
||||
<property name="jar" value="addressbook.jar"/>
|
||||
<property name="war" value="addressbook.war"/>
|
||||
<property name="javac.compilerargs" value="" />
|
||||
<property name="javac.version" value="1.7" />
|
||||
<property name="javac.version" value="1.8" />
|
||||
<property name="javac.release" value="8" />
|
||||
|
||||
<target name="all" depends="jar, emptyWar"/>
|
||||
|
||||
@@ -40,6 +41,7 @@
|
||||
|
||||
<target name="compile" depends="init, depend, warUpToDate">
|
||||
<javac debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
|
||||
release="${javac.release}"
|
||||
includeAntRuntime="false"
|
||||
encoding="UTF-8"
|
||||
srcdir="${src}" destdir="${build}">
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
# This is the configuration file for addressbook.
|
||||
#
|
||||
# Options
|
||||
# *******
|
||||
# All paths are realitive to i2p/addressbook. Default value for
|
||||
# each option is given in parentheses.
|
||||
#
|
||||
# proxy_host The hostname of your I2P http proxy.
|
||||
# (localhost)
|
||||
#
|
||||
# proxy_port The port of your I2P http proxy. (4444)
|
||||
#
|
||||
# master_addressbook The path to your master address book, used for local
|
||||
# changes only. (myhosts.txt)
|
||||
#
|
||||
# router_addressbook The path to the address book used by the router.
|
||||
# Contains the addresses from your master address book
|
||||
# and your subscribed address books. (../userhosts.txt)
|
||||
#
|
||||
# private_addressbook The path to the private address book used by the router.
|
||||
# This is used only by the router and SusiDNS.
|
||||
# It is not published by addressbook. (../privatehosts.txt)
|
||||
#
|
||||
# published_addressbook The path to the copy of your address book made
|
||||
# available on i2p. (../eepsite/docroot/hosts.txt)
|
||||
#
|
||||
# log The path to your addressbook log. (log.txt)
|
||||
#
|
||||
# subscriptions The path to your subscription file. (subscriptions.txt)
|
||||
#
|
||||
# etags The path to the etags header storage file. (etags)
|
||||
#
|
||||
# last_modified The path to the last-modified header storage file.
|
||||
# (last_modified)
|
||||
#
|
||||
# update_delay The time (in hours) between each update. (1)
|
||||
|
||||
proxy_host=localhost
|
||||
proxy_port=4444
|
||||
master_addressbook=myhosts.txt
|
||||
router_addressbook=../userhosts.txt
|
||||
private_addressbook=../privatehosts.txt
|
||||
published_addressbook=../eepsite/docroot/hosts.txt
|
||||
log=log.txt
|
||||
subscriptions=subscriptions.txt
|
||||
etags=etags
|
||||
last_modified=last_modified
|
||||
update_delay=1
|
||||
@@ -166,6 +166,10 @@ class ConfigParser {
|
||||
Map<String, String> result;
|
||||
try {
|
||||
result = parse(file);
|
||||
// migrate
|
||||
String local = result.remove("master_addressbook");
|
||||
if (local != null)
|
||||
result.put("local_addressbook", local);
|
||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||
if (!result.containsKey(entry.getKey()))
|
||||
result.put(entry.getKey(), entry.getValue());
|
||||
|
||||
@@ -67,8 +67,8 @@ class Daemon {
|
||||
* Update the router and published address books using remote data from the
|
||||
* subscribed address books listed in subscriptions.
|
||||
*
|
||||
* @param master
|
||||
* The master AddressBook. This address book is never
|
||||
* @param local
|
||||
* The local AddressBook. This address book is never
|
||||
* overwritten, so it is safe for the user to write to.
|
||||
* It is only merged to the published addressbook.
|
||||
* May be null.
|
||||
@@ -77,7 +77,7 @@ class Daemon {
|
||||
* client applications.
|
||||
* @param published
|
||||
* The published AddressBook. This address book is published on
|
||||
* the user's eepsite so that others may subscribe to it.
|
||||
* the user's I2P Site so that others may subscribe to it.
|
||||
* May be null.
|
||||
* If non-null, overwrite with the new addressbook.
|
||||
* @param subscriptions
|
||||
@@ -87,7 +87,7 @@ class Daemon {
|
||||
* The log to write changes and conflicts to.
|
||||
* May be null.
|
||||
*/
|
||||
public static void update(AddressBook master, AddressBook router,
|
||||
public static void update(AddressBook local, AddressBook router,
|
||||
File published, SubscriptionList subscriptions, Log log) {
|
||||
for (AddressBook book : subscriptions) {
|
||||
// yes, the EepGet fetch() is done in next()
|
||||
@@ -95,8 +95,8 @@ class Daemon {
|
||||
}
|
||||
router.write();
|
||||
if (published != null) {
|
||||
if (master != null)
|
||||
router.merge(master, true, null);
|
||||
if (local != null)
|
||||
router.merge(local, true, null);
|
||||
router.write(published);
|
||||
}
|
||||
subscriptions.write();
|
||||
@@ -105,13 +105,13 @@ class Daemon {
|
||||
/**
|
||||
* Update the router and published address books using remote data from the
|
||||
* subscribed address books listed in subscriptions.
|
||||
* Merging of the "master" addressbook is NOT supported.
|
||||
* Merging of the "local" addressbook is NOT supported.
|
||||
*
|
||||
* @param router
|
||||
* The NamingService to update, generally the root NamingService from the context.
|
||||
* @param published
|
||||
* The published AddressBook. This address book is published on
|
||||
* the user's eepsite so that others may subscribe to it.
|
||||
* the user's I2P Site so that others may subscribe to it.
|
||||
* May be null.
|
||||
* If non-null, overwrite with the new addressbook.
|
||||
* @param subscriptions
|
||||
@@ -751,17 +751,17 @@ class Daemon {
|
||||
if (Boolean.parseBoolean(settings.get("update_direct"))) {
|
||||
// Direct hosts.txt access
|
||||
File routerFile = new File(home, settings.get("router_addressbook"));
|
||||
AddressBook master;
|
||||
AddressBook local;
|
||||
if (should_publish) {
|
||||
File masterFile = new File(home, settings.get("master_addressbook"));
|
||||
master = new AddressBook(masterFile);
|
||||
File localFile = new File(home, settings.get("local_addressbook"));
|
||||
local = new AddressBook(localFile);
|
||||
} else {
|
||||
master = null;
|
||||
local = null;
|
||||
}
|
||||
AddressBook router = new AddressBook(routerFile);
|
||||
update(master, router, published, subscriptions, log);
|
||||
update(local, router, published, subscriptions, log);
|
||||
} else {
|
||||
// Naming service - no merging of master to router and published is supported.
|
||||
// Naming service - no merging of local to router and published is supported.
|
||||
update(getNamingService(settings.get("naming_service")), published, subscriptions, log);
|
||||
}
|
||||
}
|
||||
@@ -841,7 +841,7 @@ class Daemon {
|
||||
Map<String, String> defaultSettings = new HashMap<String, String>();
|
||||
defaultSettings.put("proxy_host", "127.0.0.1");
|
||||
defaultSettings.put("proxy_port", "4444");
|
||||
defaultSettings.put("master_addressbook", "../userhosts.txt");
|
||||
defaultSettings.put("local_addressbook", "../userhosts.txt");
|
||||
defaultSettings.put("router_addressbook", "../hosts.txt");
|
||||
defaultSettings.put("published_addressbook", "../eepsite/docroot/hosts.txt");
|
||||
defaultSettings.put("should_publish", "false");
|
||||
@@ -868,7 +868,7 @@ class Daemon {
|
||||
// wait
|
||||
try {
|
||||
Thread.sleep(5*60*1000 + I2PAppContext.getGlobalContext().random().nextLong(5*60*1000));
|
||||
// Static method, and redundent Thread.currentThread().sleep(5*60*1000);
|
||||
// Static method, and redundant Thread.currentThread().sleep(5*60*1000);
|
||||
} catch (InterruptedException ie) {}
|
||||
|
||||
while (_running) {
|
||||
|
||||
@@ -2069,9 +2069,8 @@ public class BlockfileNamingService extends DummyNamingService {
|
||||
}
|
||||
if (baos.size() > 65535)
|
||||
throw new DataFormatException("Properties too big (65535 max): " + baos.size());
|
||||
byte propBytes[] = baos.toByteArray();
|
||||
DataHelper.writeLong(rawStream, 2, propBytes.length);
|
||||
rawStream.write(propBytes);
|
||||
DataHelper.writeLong(rawStream, 2, baos.size());
|
||||
baos.writeTo(rawStream);
|
||||
} else {
|
||||
DataHelper.writeLong(rawStream, 2, 0);
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# addressbook master address book. Addresses placed in this file take precidence
|
||||
# over those in the router address book and in remote address books. If changes
|
||||
# are made to this file, they will be reflected in the router address book and
|
||||
# published address book after the next update.
|
||||
#
|
||||
# Do not make changes directly to the router address book, as they could be lost
|
||||
# during an update.
|
||||
#
|
||||
# This file takes addresses in the hosts.txt format, i.e.
|
||||
# example.i2p=somereallylongbase64thingAAAA
|
||||
@@ -1,7 +0,0 @@
|
||||
# Subscription list for addressbook
|
||||
#
|
||||
# Each entry is an absolute url to a file in hosts.txt format.
|
||||
# Since the list is checked in order, url's should be listed in order of trust.
|
||||
#
|
||||
http://dev.i2p/i2p/hosts.txt
|
||||
http://duck.i2p/hosts.txt
|
||||
@@ -2,6 +2,7 @@ sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir 'src'
|
||||
srcDir 'build/messages-src'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,3 +13,14 @@ dependencies {
|
||||
compile project(':installer')
|
||||
compile project(':apps:systray')
|
||||
}
|
||||
|
||||
// Create the java files from the po files. The jar task will compile them.
|
||||
// This requires gettext 0.19 or higher.
|
||||
// We don't support the "slow way"
|
||||
task bundle {
|
||||
doLast {
|
||||
if (!(new File("$buildDir/classes/java/main/net/i2p/desktopgui/messages_de.class")).exists())
|
||||
println "apps/desktopgui/bundle-messages.sh".execute().text
|
||||
}
|
||||
}
|
||||
jar.dependsOn bundle
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
<property name="jar" value="desktopgui.jar"/>
|
||||
<property name="javadoc" value="javadoc"/>
|
||||
<property name="javac.compilerargs" value=""/>
|
||||
<property name="javac.version" value="1.7" />
|
||||
<property name="javac.version" value="1.8" />
|
||||
<property name="javac.release" value="8" />
|
||||
<property name="require.gettext" value="true" />
|
||||
|
||||
<condition property="no.bundle">
|
||||
@@ -27,6 +28,7 @@
|
||||
|
||||
<target name="compile" depends="init">
|
||||
<javac debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
|
||||
release="${javac.release}"
|
||||
includeAntRuntime="false"
|
||||
encoding="UTF-8"
|
||||
srcdir="${src}" destdir="${build}">
|
||||
@@ -52,6 +54,7 @@
|
||||
<arg value="./bundle-messages.sh" />
|
||||
</exec>
|
||||
<javac source="${javac.version}" target="${javac.version}"
|
||||
release="${javac.release}"
|
||||
includeAntRuntime="false"
|
||||
encoding="UTF-8"
|
||||
srcdir="${build}/messages-src" destdir="${build}">
|
||||
@@ -77,12 +80,14 @@
|
||||
<!-- set if unset -->
|
||||
<property name="workspace.changes.tr" value="" />
|
||||
<!-- ideal for linux: 24x24, but transparency doesn't work -->
|
||||
<copy tofile="${build}/desktopgui/resources/images/logo.png" file="../../installer/resources/themes/console/images/itoopie_xsm.png" />
|
||||
<copy tofile="${build}/desktopgui/resources/images/logo.png" file="../../apps/routerconsole/jsp/themes/console/images/itoopie_xsm.png" />
|
||||
<copy todir="${build}/desktopgui/resources/images" file="images/itoopie_black_24.png" />
|
||||
<copy todir="${build}/desktopgui/resources/images" file="images/itoopie_white_24.png" />
|
||||
<jar basedir="${build}" excludes="messages-src/**" destfile="${dist}/${jar}">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="net.i2p.desktopgui.Main"/>
|
||||
<attribute name="Implementation-Version" value="${full.version}" />
|
||||
<attribute name="Built-By" value="${build.built-by}" />
|
||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||
|
||||
1
apps/desktopgui/bundle-messages.sh
Normal file → Executable file
1
apps/desktopgui/bundle-messages.sh
Normal file → Executable file
@@ -11,6 +11,7 @@
|
||||
# zzz - public domain
|
||||
# Mathiasdm - modifications for desktopgui
|
||||
#
|
||||
cd `dirname $0`
|
||||
CLASS=net.i2p.desktopgui.messages
|
||||
TMPFILE=build/javafiles.txt
|
||||
export TZ=UTC
|
||||
|
||||
94
apps/desktopgui/locale/messages_es_AR.po
Normal file
94
apps/desktopgui/locale/messages_es_AR.po
Normal file
@@ -0,0 +1,94 @@
|
||||
# I2P
|
||||
# Copyright (C) 2009 The I2P Project
|
||||
# This file is distributed under the same license as the desktopgui package.
|
||||
# To contribute translations, see http://www.i2p2.de/newdevelopers
|
||||
#
|
||||
# Translators:
|
||||
# kaze kaze <kaze@rlab.be>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: I2P\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
|
||||
"PO-Revision-Date: 2017-11-16 15:29+0000\n"
|
||||
"Last-Translator: kaze kaze <kaze@rlab.be>\n"
|
||||
"Language-Team: Spanish (Argentina) (http://www.transifex.com/otf/I2P/language/es_AR/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: es_AR\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
|
||||
msgid "Start I2P"
|
||||
msgstr "Iniciando I2P..."
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
|
||||
msgid "I2P is starting!"
|
||||
msgstr "I2P esta iniciando!"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
|
||||
msgid "Starting"
|
||||
msgstr "Iniciando"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
|
||||
msgid "Launch I2P Browser"
|
||||
msgstr "Lanzar el Navegador I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
|
||||
msgid "Configure I2P System Tray"
|
||||
msgstr "Configurar la Bandeja de Sistema de I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
|
||||
msgid "Disable"
|
||||
msgstr "Deshabilitar"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
|
||||
msgid "Restart I2P"
|
||||
msgstr "Riniciar I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
|
||||
msgid "Stop I2P"
|
||||
msgstr "Detener I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
|
||||
msgid "Restart I2P Immediately"
|
||||
msgstr " Reiniciar I2P inmediatamente "
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
|
||||
msgid "Stop I2P Immediately"
|
||||
msgstr " Detener I2P inmediatamente "
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
|
||||
msgid "Cancel I2P Shutdown"
|
||||
msgstr "Cancelar el Apagado de I2P"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "Apagar en {0}"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "Apagado inminente"
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
|
||||
msgid "Network"
|
||||
msgstr "Red"
|
||||
|
||||
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:63
|
||||
msgid "I2P: Right-click for menu"
|
||||
msgstr "I2P Clic derecho para el menú"
|
||||
94
apps/desktopgui/locale/messages_ku.po
Normal file
94
apps/desktopgui/locale/messages_ku.po
Normal file
@@ -0,0 +1,94 @@
|
||||
# I2P
|
||||
# Copyright (C) 2009 The I2P Project
|
||||
# This file is distributed under the same license as the desktopgui package.
|
||||
# To contribute translations, see http://www.i2p2.de/newdevelopers
|
||||
#
|
||||
# Translators:
|
||||
# Zagros <zagros21@cmail.nu>, 2020
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: I2P\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
|
||||
"PO-Revision-Date: 2020-09-23 21:02+0000\n"
|
||||
"Last-Translator: Zagros <zagros21@cmail.nu>\n"
|
||||
"Language-Team: Kurdish (http://www.transifex.com/otf/I2P/language/ku/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ku\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
|
||||
msgid "Start I2P"
|
||||
msgstr "I2P بەکاربخە"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
|
||||
msgid "I2P is starting!"
|
||||
msgstr "وا I2P دەستپێدەکات!"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
|
||||
msgid "Starting"
|
||||
msgstr "دەستپێکردن"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
|
||||
msgid "Launch I2P Browser"
|
||||
msgstr "وێبگەڕی I2P بکەوە"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
|
||||
msgid "Configure I2P System Tray"
|
||||
msgstr ""
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
|
||||
msgid "Disable"
|
||||
msgstr "ناچالاکبکە"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
|
||||
msgid "Restart I2P"
|
||||
msgstr "I2P بەکاربخەوە"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
|
||||
msgid "Stop I2P"
|
||||
msgstr "I2P بوەستێنە"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
|
||||
msgid "Restart I2P Immediately"
|
||||
msgstr "دەستبەجێ I2P بەکاربخەوە"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
|
||||
msgid "Stop I2P Immediately"
|
||||
msgstr "دەستبەجێ I2P بوەستێنە"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
|
||||
msgid "Cancel I2P Shutdown"
|
||||
msgstr "کووژاندنەوە I2P هەڵبوەشێنەوە"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "دەکووژێتەوە لە {0}"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "دەستبەجێ کووژانەوە"
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
|
||||
msgid "Network"
|
||||
msgstr "ڕایەڵە"
|
||||
|
||||
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:63
|
||||
msgid "I2P: Right-click for menu"
|
||||
msgstr "I2P: کرتەی ڕاست بکە بۆ لیستەکان"
|
||||
94
apps/desktopgui/locale/messages_tk.po
Normal file
94
apps/desktopgui/locale/messages_tk.po
Normal file
@@ -0,0 +1,94 @@
|
||||
# I2P
|
||||
# Copyright (C) 2009 The I2P Project
|
||||
# This file is distributed under the same license as the desktopgui package.
|
||||
# To contribute translations, see http://www.i2p2.de/newdevelopers
|
||||
#
|
||||
# Translators:
|
||||
# Alperen Yavuz <mingyu@yaani.com>, 2020
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: I2P\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
|
||||
"PO-Revision-Date: 2020-08-26 20:48+0000\n"
|
||||
"Last-Translator: Alperen Yavuz <mingyu@yaani.com>\n"
|
||||
"Language-Team: Turkmen (http://www.transifex.com/otf/I2P/language/tk/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: tk\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
|
||||
msgid "Start I2P"
|
||||
msgstr "I2P başlaň"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
|
||||
msgid "I2P is starting!"
|
||||
msgstr "I2P başlaýar!"
|
||||
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
|
||||
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
|
||||
msgid "Starting"
|
||||
msgstr "Başlamak"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
|
||||
msgid "Launch I2P Browser"
|
||||
msgstr "I2P brauzerini işe giriziň"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
|
||||
msgid "Configure I2P System Tray"
|
||||
msgstr "I2P ulgam lýubkasyny sazlaň"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
|
||||
msgid "Disable"
|
||||
msgstr "Öçüriň"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
|
||||
msgid "Restart I2P"
|
||||
msgstr "I2P-i täzeden açyň"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
|
||||
msgid "Stop I2P"
|
||||
msgstr "I2P bes et"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
|
||||
msgid "Restart I2P Immediately"
|
||||
msgstr "I2P derrew täzeden açyň"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
|
||||
msgid "Stop I2P Immediately"
|
||||
msgstr "Derrew I2P duruzyň"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
|
||||
msgid "Cancel I2P Shutdown"
|
||||
msgstr "I2P ýapmagy ýatyryň"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
|
||||
#, java-format
|
||||
msgid "Shutdown in {0}"
|
||||
msgstr "{0} in ýapmak"
|
||||
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
|
||||
msgid "Shutdown imminent"
|
||||
msgstr "Öçürmek ýakyn"
|
||||
|
||||
#. status translations are in the console bundle
|
||||
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
|
||||
msgid "Network"
|
||||
msgstr "Tor"
|
||||
|
||||
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
|
||||
#: src/net/i2p/desktopgui/TrayManager.java:63
|
||||
msgid "I2P: Right-click for menu"
|
||||
msgstr "I2P: Menýu üçin sag basyň"
|
||||
22
apps/i2pcontrol/build.gradle
Normal file
22
apps/i2pcontrol/build.gradle
Normal file
@@ -0,0 +1,22 @@
|
||||
plugins {
|
||||
id 'war'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir 'java'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
providedCompile project(':router')
|
||||
providedCompile project(':apps:jetty')
|
||||
providedCompile files('../../installer/lib/wrapper/all/wrapper.jar')
|
||||
}
|
||||
|
||||
war {
|
||||
archiveName 'jsonrpc.war'
|
||||
webXml = file('web.xml')
|
||||
}
|
||||
@@ -50,7 +50,8 @@
|
||||
</target>
|
||||
|
||||
<property name="javac.compilerargs" value="" />
|
||||
<property name="javac.version" value="1.7" />
|
||||
<property name="javac.version" value="1.8" />
|
||||
<property name="javac.release" value="8" />
|
||||
|
||||
<target name="compile" depends="builddep" >
|
||||
<mkdir dir="./build" />
|
||||
@@ -58,6 +59,7 @@
|
||||
<javac
|
||||
srcdir="./java"
|
||||
debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
|
||||
release="${javac.release}"
|
||||
includeAntRuntime="false"
|
||||
encoding="UTF-8"
|
||||
destdir="./build/obj"
|
||||
@@ -77,6 +79,7 @@
|
||||
sourcepath=""
|
||||
srcdir="./java"
|
||||
debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
|
||||
release="${javac.release}"
|
||||
includeAntRuntime="false"
|
||||
encoding="UTF-8"
|
||||
destdir="./build/obj"
|
||||
@@ -90,6 +93,8 @@
|
||||
</target>
|
||||
|
||||
<target name="jar" depends="compile">
|
||||
<!-- set if unset -->
|
||||
<property name="workspace.changes.tr" value="" />
|
||||
<jar destfile="build/i2pcontrol.jar" basedir="./build/obj" includes="**/*.class" >
|
||||
<manifest>
|
||||
<attribute name="Implementation-Version" value="${full.version}" />
|
||||
@@ -104,6 +109,8 @@
|
||||
</target>
|
||||
|
||||
<target name="socketJar" depends="compileSocketJar">
|
||||
<!-- set if unset -->
|
||||
<property name="workspace.changes.tr" value="" />
|
||||
<jar destfile="build/i2pcontrol.jar" basedir="./build/obj" includes="**/*.class" >
|
||||
<manifest>
|
||||
<attribute name="Implementation-Version" value="${full.version}" />
|
||||
@@ -118,6 +125,8 @@
|
||||
</target>
|
||||
|
||||
<target name="war" depends="compile" >
|
||||
<!-- set if unset -->
|
||||
<property name="workspace.changes.tr" value="" />
|
||||
<war destfile="build/jsonrpc.war" webxml="web.xml" >
|
||||
<classes dir="./build/obj" excludes="net/i2p/i2pcontrol/I2PControlController.class net/i2p/i2pcontrol/HostCheckHandler.class net/i2p/i2pcontrol/SocketController*.class" />
|
||||
<manifest>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.thetransactioncompany.jsonrpc2;
|
||||
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JsonObject;
|
||||
|
||||
|
||||
/**
|
||||
@@ -220,7 +220,7 @@ public class JSONRPC2Error extends Exception {
|
||||
* @see #toJSONObject
|
||||
*/
|
||||
@Deprecated
|
||||
public JSONObject toJSON() {
|
||||
public JsonObject toJSON() {
|
||||
|
||||
return toJSONObject();
|
||||
}
|
||||
@@ -231,9 +231,9 @@ public class JSONRPC2Error extends Exception {
|
||||
*
|
||||
* @return A JSON object representing this error object.
|
||||
*/
|
||||
public JSONObject toJSONObject() {
|
||||
public JsonObject toJSONObject() {
|
||||
|
||||
JSONObject out = new JSONObject();
|
||||
JsonObject out = new JsonObject();
|
||||
|
||||
out.put("code", code);
|
||||
out.put("message", super.getMessage());
|
||||
|
||||
@@ -5,8 +5,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.JSONAware;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JsonObject;
|
||||
|
||||
|
||||
/**
|
||||
@@ -54,7 +53,7 @@ import org.json.simple.JSONObject;
|
||||
*
|
||||
* @author Vladimir Dzhuvinov
|
||||
*/
|
||||
public abstract class JSONRPC2Message implements JSONAware {
|
||||
public abstract class JSONRPC2Message {
|
||||
|
||||
|
||||
/**
|
||||
@@ -220,7 +219,7 @@ public abstract class JSONRPC2Message implements JSONAware {
|
||||
*
|
||||
* @return The JSON object.
|
||||
*/
|
||||
public abstract JSONObject toJSONObject();
|
||||
public abstract JsonObject toJSONObject();
|
||||
|
||||
|
||||
/**
|
||||
@@ -246,6 +245,6 @@ public abstract class JSONRPC2Message implements JSONAware {
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
return toJSONObject().toString();
|
||||
return toJSONObject().toJson();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package com.thetransactioncompany.jsonrpc2;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JsonObject;
|
||||
|
||||
|
||||
/**
|
||||
@@ -414,9 +414,9 @@ public class JSONRPC2Notification extends JSONRPC2Message {
|
||||
|
||||
|
||||
@Override
|
||||
public JSONObject toJSONObject() {
|
||||
public JsonObject toJSONObject() {
|
||||
|
||||
JSONObject notf = new JSONObject();
|
||||
JsonObject notf = new JsonObject();
|
||||
|
||||
notf.put("method", method);
|
||||
|
||||
|
||||
@@ -4,9 +4,8 @@ package com.thetransactioncompany.jsonrpc2;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.parser.ContainerFactory;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.json.simple.Jsoner;
|
||||
import org.json.simple.DeserializationException;
|
||||
|
||||
|
||||
/**
|
||||
@@ -56,12 +55,6 @@ import org.json.simple.parser.ParseException;
|
||||
public class JSONRPC2Parser {
|
||||
|
||||
|
||||
/**
|
||||
* Reusable JSON parser. Not thread-safe!
|
||||
*/
|
||||
private final JSONParser parser;
|
||||
|
||||
|
||||
/**
|
||||
* If {@code true} the order of the parsed JSON object members must be
|
||||
* preserved.
|
||||
@@ -153,10 +146,7 @@ public class JSONRPC2Parser {
|
||||
public JSONRPC2Parser(final boolean preserveOrder,
|
||||
final boolean ignoreVersion,
|
||||
final boolean parseNonStdAttributes) {
|
||||
|
||||
// Numbers parsed as long/double, requires JSON Smart 1.0.9+
|
||||
parser = new JSONParser();
|
||||
|
||||
|
||||
this.preserveOrder = preserveOrder;
|
||||
this.ignoreVersion = ignoreVersion;
|
||||
this.parseNonStdAttributes = parseNonStdAttributes;
|
||||
@@ -189,13 +179,9 @@ public class JSONRPC2Parser {
|
||||
|
||||
// Parse the JSON string
|
||||
try {
|
||||
//if (preserveOrder)
|
||||
// json = parser.parse(jsonString, ContainerFactory.FACTORY_ORDERED);
|
||||
|
||||
//else
|
||||
json = parser.parse(jsonString);
|
||||
json = Jsoner.deserialize(jsonString);
|
||||
|
||||
} catch (ParseException e) {
|
||||
} catch (DeserializationException e) {
|
||||
|
||||
// Terse message, do not include full parse exception message
|
||||
throw new JSONRPC2ParseException("Invalid JSON",
|
||||
|
||||
@@ -4,7 +4,7 @@ package com.thetransactioncompany.jsonrpc2;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JsonObject;
|
||||
|
||||
|
||||
/**
|
||||
@@ -472,9 +472,9 @@ public class JSONRPC2Request extends JSONRPC2Message {
|
||||
|
||||
|
||||
@Override
|
||||
public JSONObject toJSONObject() {
|
||||
public JsonObject toJSONObject() {
|
||||
|
||||
JSONObject req = new JSONObject();
|
||||
JsonObject req = new JsonObject();
|
||||
|
||||
req.put("method", method);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.thetransactioncompany.jsonrpc2;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JsonObject;
|
||||
|
||||
|
||||
/**
|
||||
@@ -384,9 +384,9 @@ public class JSONRPC2Response extends JSONRPC2Message {
|
||||
|
||||
|
||||
@Override
|
||||
public JSONObject toJSONObject() {
|
||||
public JsonObject toJSONObject() {
|
||||
|
||||
JSONObject out = new JSONObject();
|
||||
JsonObject out = new JsonObject();
|
||||
|
||||
// Result and error are mutually exclusive
|
||||
if (error != null) {
|
||||
|
||||
@@ -55,7 +55,7 @@ import java.util.StringTokenizer;
|
||||
* This handles the starting and stopping of Jetty
|
||||
* from a single static class so it can be called via clients.config.
|
||||
*
|
||||
* This makes installation of a new eepsite a turnkey operation.
|
||||
* This makes installation of a new I2P Site a turnkey operation.
|
||||
*
|
||||
* Usage: I2PControlController -d $PLUGIN [start|stop]
|
||||
*
|
||||
|
||||
@@ -37,8 +37,8 @@ import net.i2p.util.I2PSSLSocketFactory;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.PortMapper;
|
||||
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.json.simple.Jsoner;
|
||||
import org.json.simple.DeserializationException;
|
||||
|
||||
import net.i2p.i2pcontrol.security.KeyStoreProvider;
|
||||
import net.i2p.i2pcontrol.security.SecurityManager;
|
||||
@@ -194,13 +194,12 @@ public class SocketController implements RouterApp {
|
||||
public void run() {
|
||||
try {
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
|
||||
final JSONParser parser = new JSONParser();
|
||||
while (true) {
|
||||
Object o = parser.parse(reader);
|
||||
Object o = Jsoner.deserialize(reader);
|
||||
// TODO
|
||||
System.out.println("i2pcontrol got: " + o);
|
||||
}
|
||||
} catch (ParseException pe) {
|
||||
} catch (DeserializationException pe) {
|
||||
_log.error("i2pcontrol handler", pe);
|
||||
return;
|
||||
} catch (IOException ioe) {
|
||||
|
||||
@@ -186,17 +186,18 @@ public class KeyStoreProvider {
|
||||
if (_keystore == null) {
|
||||
File keyStoreFile = new File(getKeyStoreLocation());
|
||||
|
||||
InputStream is = null;
|
||||
try {
|
||||
_keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
if (keyStoreFile.exists()) {
|
||||
InputStream is = new FileInputStream(keyStoreFile);
|
||||
is = new FileInputStream(keyStoreFile);
|
||||
_keystore.load(is, DEFAULT_KEYSTORE_PASSWORD.toCharArray());
|
||||
return _keystore;
|
||||
}
|
||||
|
||||
initialize();
|
||||
if (keyStoreFile.exists()) {
|
||||
InputStream is = new FileInputStream(keyStoreFile);
|
||||
is = new FileInputStream(keyStoreFile);
|
||||
_keystore.load(is, DEFAULT_KEYSTORE_PASSWORD.toCharArray());
|
||||
return _keystore;
|
||||
} else {
|
||||
@@ -204,6 +205,8 @@ public class KeyStoreProvider {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignore. Not an issue. Let's just create a new keystore instead.
|
||||
} finally {
|
||||
if (is != null) try { is.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
|
||||
@@ -145,8 +145,9 @@ public class JSONRPC2Servlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {
|
||||
httpServletResponse.setContentType("text/html");
|
||||
setHeaders(httpServletResponse);
|
||||
PrintWriter out = httpServletResponse.getWriter();
|
||||
out.println("<html><head></head><body>");
|
||||
out.println("<p>I2PControl RPC Service version " + I2PControlVersion.VERSION + " : Running");
|
||||
if ("/password".equals(httpServletRequest.getServletPath())) {
|
||||
out.println("<form method=\"POST\" action=\"password\">");
|
||||
@@ -160,16 +161,19 @@ public class JSONRPC2Servlet extends HttpServlet {
|
||||
"<input name=\"save\" type=\"submit\" value=\"Change API Password\">" +
|
||||
"<p>If you forget the API password, stop i2pcontrol, delete the file <tt>" + _conf.getConfFile() +
|
||||
"</tt>, and restart i2pcontrol.");
|
||||
out.println("</form>");
|
||||
} else {
|
||||
out.println("<p><a href=\"password\">Change API Password</a>");
|
||||
}
|
||||
out.println("</body></html>");
|
||||
out.close();
|
||||
}
|
||||
|
||||
/** @since 0.12 */
|
||||
private void doPasswordChange(HttpServletRequest req, HttpServletResponse httpServletResponse) throws ServletException, IOException {
|
||||
httpServletResponse.setContentType("text/html");
|
||||
setHeaders(httpServletResponse);
|
||||
PrintWriter out = httpServletResponse.getWriter();
|
||||
out.println("<html><head></head><body>");
|
||||
String pw = req.getParameter("password");
|
||||
if (pw == null)
|
||||
pw = _secMan.DEFAULT_AUTH_PASSWORD;
|
||||
@@ -194,6 +198,21 @@ public class JSONRPC2Servlet extends HttpServlet {
|
||||
}
|
||||
}
|
||||
out.println("<p><a href=\"password\">Change API Password</a>");
|
||||
out.println("</body></html>");
|
||||
out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.9.48
|
||||
*/
|
||||
private static void setHeaders(HttpServletResponse resp) {
|
||||
resp.setContentType("text/html");
|
||||
resp.setHeader("X-Frame-Options", "SAMEORIGIN");
|
||||
resp.setHeader("Content-Security-Policy", "default-src 'self'; style-src 'self'; script-src 'self'; form-action 'self'; frame-ancestors 'self'; object-src 'none'; media-src 'none'");
|
||||
resp.setHeader("X-XSS-Protection", "1; mode=block");
|
||||
resp.setHeader("X-Content-Type-Options", "nosniff");
|
||||
resp.setHeader("Pragma", "no-cache");
|
||||
resp.setHeader("Cache-Control","no-cache");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -86,7 +86,7 @@ public class AuthenticateHandler implements RequestHandler {
|
||||
|
||||
Integer apiVersion;
|
||||
try {
|
||||
apiVersion = ((Long) api).intValue();
|
||||
apiVersion = ((Number) api).intValue();
|
||||
} catch (ClassCastException e) {
|
||||
e.printStackTrace();
|
||||
return JSONRPC2ExtendedError.UNSPECIFIED_API_VERSION;
|
||||
|
||||
@@ -56,12 +56,10 @@ public class GetRateHandler implements RequestHandler {
|
||||
if (input == null) {
|
||||
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
|
||||
}
|
||||
long period;
|
||||
try {
|
||||
period = (Long) inParams.get("Period");
|
||||
} catch (NumberFormatException e) {
|
||||
Number p = (Number) inParams.get("Period");
|
||||
if (p == null)
|
||||
return new JSONRPC2Response(JSONRPC2Error.INVALID_PARAMS, req.getID());
|
||||
}
|
||||
long period = p.longValue();
|
||||
|
||||
RateStat rateStat = I2PAppContext.getGlobalContext().statManager().getRate(input);
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.i2p.i2pcontrol.servlets.jsonrpc2handlers;
|
||||
|
||||
import com.thetransactioncompany.jsonrpc2.JSONRPC2Error;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
/*
|
||||
* Copyright 2011 hottuna (dev@robertfoss.se)
|
||||
|
||||
@@ -6,13 +6,14 @@ sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir 'java/src'
|
||||
srcDir 'java/build/messages-src'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile project(':apps:systray')
|
||||
providedCompile project(':apps:systray')
|
||||
compile 'gnu.getopt:java-getopt:1.0.13'
|
||||
providedCompile project(':apps:ministreaming')
|
||||
providedCompile project(':apps:jetty')
|
||||
@@ -34,10 +35,26 @@ artifacts {
|
||||
archives i2psnarkJar
|
||||
}
|
||||
|
||||
war {
|
||||
into '.icons', {
|
||||
from 'icons'
|
||||
// Create the java files from the po files. The jar task will compile them.
|
||||
// This requires gettext 0.19 or higher.
|
||||
// We don't support the "slow way"
|
||||
task bundle {
|
||||
doLast {
|
||||
if (!(new File("$buildDir/classes/java/main/org/klomp/snark/web/messages_de.class")).exists())
|
||||
println "apps/i2psnark/java/bundle-messages.sh".execute().text
|
||||
}
|
||||
}
|
||||
war.dependsOn bundle
|
||||
|
||||
war {
|
||||
rootSpec.exclude('/org/klomp/snark/*.class')
|
||||
rootSpec.exclude('/org/klomp/snark/bencode/**')
|
||||
rootSpec.exclude('/org/klomp/snark/comments/**')
|
||||
rootSpec.exclude('/org/klomp/snark/dht/**')
|
||||
rootSpec.exclude('/org/klomp/snark/standalone/**')
|
||||
from ('resources', {
|
||||
into ".resources"
|
||||
})
|
||||
webInf {
|
||||
into 'classes/org/klomp/snark/web'
|
||||
from 'mime.properties'
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
|
||||
<!-- only used if not set by a higher build.xml -->
|
||||
<property name="javac.compilerargs" value="" />
|
||||
<property name="javac.version" value="1.7" />
|
||||
<property name="javac.version" value="1.8" />
|
||||
<property name="javac.release" value="8" />
|
||||
<property name="require.gettext" value="true" />
|
||||
<property name="manifest.classpath.name" value="Class-Path" />
|
||||
|
||||
@@ -41,6 +42,7 @@
|
||||
<javac
|
||||
srcdir="./src"
|
||||
debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
|
||||
release="${javac.release}"
|
||||
destdir="./build/obj"
|
||||
encoding="UTF-8"
|
||||
includeAntRuntime="false" >
|
||||
@@ -164,6 +166,7 @@
|
||||
<arg value="./bundle-messages.sh" />
|
||||
</exec>
|
||||
<javac source="${javac.version}" target="${javac.version}"
|
||||
release="${javac.release}"
|
||||
includeAntRuntime="false"
|
||||
encoding="UTF-8"
|
||||
srcdir="build/messages-src" destdir="build/obj">
|
||||
@@ -247,53 +250,51 @@
|
||||
|
||||
<!-- add css, image, and js files for standalone snark to the war -->
|
||||
<target name="standalone_war" depends="war">
|
||||
<mkdir dir="build/standalone-resources/.resources/themes/snark" />
|
||||
<copy todir="build/standalone-resources/.resources/themes/snark" >
|
||||
<fileset dir="../../../installer/resources/themes/snark/" />
|
||||
<mkdir dir="build/standalone-resources/.resources/themes/" />
|
||||
<copy todir="build/standalone-resources/.resources/themes/" >
|
||||
<fileset dir="../resources/themes/" />
|
||||
</copy>
|
||||
|
||||
<replace dir="build/standalone-resources/.resources/themes/snark"
|
||||
<replace dir="build/standalone-resources/.resources/themes"
|
||||
summary="true"
|
||||
token="url(/themes/console/dark/images/"
|
||||
value="url(/i2psnark/.resources/themes/snark/dark/images/" >
|
||||
value="url(/i2psnark/.resources/themes/dark/images/" >
|
||||
<include name="**/*.css" />
|
||||
</replace>
|
||||
<replace dir="build/standalone-resources/.resources/themes/snark"
|
||||
<replace dir="build/standalone-resources/.resources/themes"
|
||||
summary="true"
|
||||
token="url(../../console/light/images/"
|
||||
value="url(/i2psnark/.resources/themes/snark/light/images/" >
|
||||
value="url(/i2psnark/.resources/themes/light/images/" >
|
||||
<include name="**/*.css" />
|
||||
</replace>
|
||||
<replace dir="build/standalone-resources/.resources/themes/snark"
|
||||
<replace dir="build/standalone-resources/.resources/themes"
|
||||
summary="true"
|
||||
token="url(/themes/console/light/images/"
|
||||
value="url(/i2psnark/.resources/themes/snark/light/images/" >
|
||||
value="url(/i2psnark/.resources/themes/light/images/" >
|
||||
<include name="**/*.css" />
|
||||
</replace>
|
||||
<replace dir="build/standalone-resources/.resources/themes/snark"
|
||||
<replace dir="build/standalone-resources/.resources/themes"
|
||||
summary="true"
|
||||
token="url(/themes/console/images/transparent.gif"
|
||||
value="url(/i2psnark/.resources/themes/snark/ubergine/images/transparent.gif" >
|
||||
value="url(/i2psnark/.resources/themes/ubergine/images/transparent.gif" >
|
||||
<include name="**/*.css" />
|
||||
</replace>
|
||||
<replace dir="build/standalone-resources/.resources/themes/snark"
|
||||
<replace dir="build/standalone-resources/.resources/themes"
|
||||
summary="true"
|
||||
token="url(/themes/console/images/info/"
|
||||
value="url(/i2psnark/.resources/themes/snark/ubergine/images/" >
|
||||
value="url(/i2psnark/.resources/themes/ubergine/images/" >
|
||||
<include name="**/*.css" />
|
||||
</replace>
|
||||
|
||||
<!-- Rather than pulling in all the console theme images, let's just specify the ones we need -->
|
||||
<copy file="../../../installer/resources/themes/console/images/transparent.gif"
|
||||
todir="build/standalone-resources/.resources/themes/snark/ubergine/images" />
|
||||
<copy file="../../../installer/resources/themes/console/dark/images/header.png"
|
||||
todir="build/standalone-resources/.resources/themes/snark/dark/images" />
|
||||
<copy file="../../../installer/resources/themes/console/light/images/header.png"
|
||||
todir="build/standalone-resources/.resources/themes/snark/light/images" />
|
||||
<copy file="../../../installer/resources/themes/console/dark/images/camotile2.png"
|
||||
todir="build/standalone-resources/.resources/themes/snark/dark/images" />
|
||||
<copy file="../../../installer/resources/themes/console/images/info/errortriangle.png"
|
||||
todir="build/standalone-resources/.resources/themes/snark/ubergine/images" />
|
||||
<copy file="../../routerconsole/jsp/themes/console/images/transparent.gif"
|
||||
todir="build/standalone-resources/.resources/themes/ubergine/images" />
|
||||
<copy file="../../routerconsole/jsp/themes/console/dark/images/header.png"
|
||||
todir="build/standalone-resources/.resources/themes/dark/images" />
|
||||
<copy file="../../routerconsole/jsp/themes/console/light/images/header.png"
|
||||
todir="build/standalone-resources/.resources/themes/light/images" />
|
||||
<copy file="../../routerconsole/jsp/themes/console/images/info/errortriangle.png"
|
||||
todir="build/standalone-resources/.resources/themes/ubergine/images" />
|
||||
|
||||
<mkdir dir="build/standalone-resources/.resources/js" />
|
||||
<copy file="../../routerconsole/jsp/js/ajax.js" todir="build/standalone-resources/.resources/js" />
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#
|
||||
# zzz - public domain
|
||||
#
|
||||
cd `dirname $0`
|
||||
CLASS=org.klomp.snark.web.messages
|
||||
TMPFILE=build/javafiles.txt
|
||||
export TZ=UTC
|
||||
|
||||
@@ -43,12 +43,12 @@ interface CoordinatorListener
|
||||
public boolean overUploadLimit(int uploaders);
|
||||
|
||||
/**
|
||||
* Are we currently over the upstream bandwidth limit?
|
||||
* Is i2psnark as a whole over its limit?
|
||||
*/
|
||||
public boolean overUpBWLimit();
|
||||
|
||||
/**
|
||||
* Is the total (in Bps) over the upstream bandwidth limit?
|
||||
* Is a particular peer who has this recent download rate (in Bps) over our upstream bandwidth limit?
|
||||
*/
|
||||
public boolean overUpBWLimit(long total);
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ abstract class ExtensionHandler {
|
||||
handshake.put("m", m);
|
||||
handshake.put("p", Integer.valueOf(TrackerClient.PORT));
|
||||
handshake.put("v", "I2PSnark");
|
||||
handshake.put("reqq", Integer.valueOf(5));
|
||||
handshake.put("reqq", Integer.valueOf(PeerState.MAX_PIPELINE));
|
||||
// BEP 21
|
||||
if (uploadOnly)
|
||||
handshake.put("upload_only", Integer.valueOf(1));
|
||||
|
||||
@@ -5,8 +5,10 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
@@ -57,7 +59,6 @@ public class I2PSnarkUtil {
|
||||
private int _i2cpPort;
|
||||
private final Map<String, String> _opts;
|
||||
private volatile I2PSocketManager _manager;
|
||||
private boolean _configured;
|
||||
private volatile boolean _connecting;
|
||||
private final Set<Hash> _banlist;
|
||||
private int _maxUploaders;
|
||||
@@ -84,6 +85,10 @@ public class I2PSnarkUtil {
|
||||
public static final String PROP_MAX_BW = "i2cp.outboundBytesPerSecond";
|
||||
public static final boolean DEFAULT_USE_DHT = true;
|
||||
public static final String EEPGET_USER_AGENT = "I2PSnark";
|
||||
private static final List<String> HIDDEN_I2CP_OPTS = Arrays.asList(new String[] {
|
||||
PROP_MAX_BW, "inbound.length", "outbound.length", "inbound.quantity", "outbound.quantity"
|
||||
});
|
||||
|
||||
|
||||
public I2PSnarkUtil(I2PAppContext ctx) {
|
||||
this(ctx, "i2psnark");
|
||||
@@ -142,25 +147,34 @@ public class I2PSnarkUtil {
|
||||
/** @since 0.9.1 */
|
||||
public I2PAppContext getContext() { return _context; }
|
||||
|
||||
public boolean configured() { return _configured; }
|
||||
|
||||
/**
|
||||
* @param i2cpHost may be null for no change
|
||||
* @param i2cpPort may be 0 for no change
|
||||
* @param opts may be null for no change
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public void setI2CPConfig(String i2cpHost, int i2cpPort, Map opts) {
|
||||
if (i2cpHost != null)
|
||||
_i2cpHost = i2cpHost;
|
||||
if (i2cpPort > 0)
|
||||
_i2cpPort = i2cpPort;
|
||||
// can't remove any options this way...
|
||||
if (opts != null)
|
||||
_opts.putAll(opts);
|
||||
if (opts != null) {
|
||||
synchronized(_opts) {
|
||||
// removed options...
|
||||
for (Iterator<String> iter = _opts.keySet().iterator(); iter.hasNext(); ) {
|
||||
String k = iter.next();
|
||||
if (!HIDDEN_I2CP_OPTS.contains(k) && !opts.containsKey(k))
|
||||
iter.remove();
|
||||
}
|
||||
_opts.putAll(opts);
|
||||
}
|
||||
}
|
||||
// this updates the session options and tells the router
|
||||
setMaxUpBW(_maxUpBW);
|
||||
_configured = true;
|
||||
}
|
||||
|
||||
public void setMaxUploaders(int limit) {
|
||||
_maxUploaders = limit;
|
||||
_configured = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,13 +183,16 @@ public class I2PSnarkUtil {
|
||||
*/
|
||||
public void setMaxUpBW(int limit) {
|
||||
_maxUpBW = limit;
|
||||
_opts.put(PROP_MAX_BW, Integer.toString(limit * (1024 * 6 / 5))); // add a little for overhead
|
||||
_configured = true;
|
||||
synchronized(_opts) {
|
||||
_opts.put(PROP_MAX_BW, Integer.toString(limit * (1024 * 6 / 5))); // add a little for overhead
|
||||
}
|
||||
if (_manager != null) {
|
||||
I2PSession sess = _manager.getSession();
|
||||
if (sess != null) {
|
||||
Properties newProps = new Properties();
|
||||
newProps.putAll(_opts);
|
||||
synchronized(_opts) {
|
||||
newProps.putAll(_opts);
|
||||
}
|
||||
sess.updateOptions(newProps);
|
||||
}
|
||||
}
|
||||
@@ -183,17 +200,24 @@ public class I2PSnarkUtil {
|
||||
|
||||
public void setMaxConnections(int limit) {
|
||||
_maxConnections = limit;
|
||||
_configured = true;
|
||||
}
|
||||
|
||||
public void setStartupDelay(int minutes) {
|
||||
_startupDelay = minutes;
|
||||
_configured = true;
|
||||
}
|
||||
|
||||
public String getI2CPHost() { return _i2cpHost; }
|
||||
public int getI2CPPort() { return _i2cpPort; }
|
||||
public Map<String, String> getI2CPOptions() { return _opts; }
|
||||
|
||||
/**
|
||||
* @return a copy
|
||||
*/
|
||||
public Map<String, String> getI2CPOptions() {
|
||||
synchronized(_opts) {
|
||||
return new HashMap<String, String>(_opts);
|
||||
}
|
||||
}
|
||||
|
||||
public String getEepProxyHost() { return _proxyHost; }
|
||||
public int getEepProxyPort() { return _proxyPort; }
|
||||
public boolean getEepProxySet() { return _shouldProxy; }
|
||||
@@ -225,9 +249,8 @@ public class I2PSnarkUtil {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Connecting to I2P", new Exception("I did it"));
|
||||
Properties opts = _context.getProperties();
|
||||
if (_opts != null) {
|
||||
for (Map.Entry<String, String> entry : _opts.entrySet() )
|
||||
opts.setProperty(entry.getKey(), entry.getValue());
|
||||
synchronized(_opts) {
|
||||
opts.putAll(_opts);
|
||||
}
|
||||
// override preference and start with two tunnels. IdleChecker will ramp up/down as necessary
|
||||
String sin = opts.getProperty("inbound.quantity");
|
||||
@@ -295,6 +318,8 @@ public class I2PSnarkUtil {
|
||||
opts.setProperty("i2p.streaming.answerPings", "false");
|
||||
if (opts.getProperty(I2PClient.PROP_SIGTYPE) == null)
|
||||
opts.setProperty(I2PClient.PROP_SIGTYPE, "EdDSA_SHA512_Ed25519");
|
||||
if (opts.getProperty("i2cp.leaseSetEncType") == null)
|
||||
opts.setProperty("i2cp.leaseSetEncType", "4,0");
|
||||
// assume compressed content
|
||||
if (opts.getProperty(I2PClient.PROP_GZIP) == null)
|
||||
opts.setProperty(I2PClient.PROP_GZIP, "false");
|
||||
|
||||
@@ -49,7 +49,7 @@ class MagnetState {
|
||||
infohash = iHash;
|
||||
if (meta != null) {
|
||||
metainfo = meta;
|
||||
initialize(meta.getInfoBytes().length);
|
||||
initialize(meta.getInfoBytesLength());
|
||||
complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,13 @@ public class MagnetURI {
|
||||
public static final String MAGNET_FULL = MAGNET + "?xt=urn:btih:";
|
||||
/** http://sponge.i2p/files/maggotspec.txt */
|
||||
public static final String MAGGOT = "maggot://";
|
||||
/**
|
||||
* https://blog.libtorrent.org/2020/09/bittorrent-v2/
|
||||
* TODO, dup param parsing, as a dual v1/v2 link
|
||||
* will contain two xt params
|
||||
* @since 0.9.48
|
||||
*/
|
||||
public static final String MAGNET_FULL_V2 = MAGNET + "?xt=urn:btmh:";
|
||||
|
||||
/**
|
||||
* @param url non-null
|
||||
@@ -35,6 +42,7 @@ public class MagnetURI {
|
||||
if (url.startsWith(MAGNET)) {
|
||||
// magnet:?xt=urn:btih:0691e40aae02e552cfcb57af1dca56214680c0c5&tr=http://tracker2.postman.i2p/announce.php
|
||||
String xt = getParam("xt", url);
|
||||
// TODO btmh
|
||||
if (xt == null || !xt.startsWith("urn:btih:"))
|
||||
throw new IllegalArgumentException();
|
||||
ihash = xt.substring("urn:btih:".length());
|
||||
|
||||
@@ -49,6 +49,9 @@ class Message
|
||||
final static byte REJECT = 16; // Fast (BEP 6)
|
||||
final static byte ALLOWED_FAST = 17; // Fast (BEP 6)
|
||||
final static byte EXTENSION = 20; // BEP 10
|
||||
final static byte HASH_REQUEST = 21; // BEP 52
|
||||
final static byte HASHES = 22; // BEP 52
|
||||
final static byte HASH_REJECT = 23; // BEP 52
|
||||
|
||||
// Not all fields are used for every message.
|
||||
// KEEP_ALIVE doesn't have a real wire representation
|
||||
@@ -278,6 +281,13 @@ class Message
|
||||
return "REJECT(" + piece + ',' + begin + ',' + length + ')';
|
||||
case ALLOWED_FAST:
|
||||
return "ALLOWED_FAST(" + piece + ')';
|
||||
// BEP 52 below here
|
||||
case HASH_REQUEST:
|
||||
return "HASH_REQUEST";
|
||||
case HASHES:
|
||||
return "HASHES";
|
||||
case HASH_REJECT:
|
||||
return "HASH_REJECT";
|
||||
default:
|
||||
return "UNKNOWN (" + type + ')';
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ public class MetaInfo
|
||||
private final String name_utf8;
|
||||
private final List<List<String>> files;
|
||||
private final List<List<String>> files_utf8;
|
||||
private final List<String> attributes;
|
||||
private final List<Long> lengths;
|
||||
private final int piece_length;
|
||||
private final byte[] piece_hashes;
|
||||
@@ -67,7 +68,9 @@ public class MetaInfo
|
||||
private final String comment;
|
||||
private final String created_by;
|
||||
private final long creation_date;
|
||||
private final List<String> url_list;
|
||||
private Map<String, BEValue> infoMap;
|
||||
private int infoBytesLength;
|
||||
|
||||
/**
|
||||
* Called by Storage when creating a new torrent from local data
|
||||
@@ -77,10 +80,12 @@ public class MetaInfo
|
||||
* @param lengths null for single-file torrent
|
||||
* @param announce_list may be null
|
||||
* @param created_by may be null
|
||||
* @param url_list may be null
|
||||
* @param comment may be null
|
||||
*/
|
||||
MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
|
||||
int piece_length, byte[] piece_hashes, long length, boolean privateTorrent,
|
||||
List<List<String>> announce_list, String created_by)
|
||||
List<List<String>> announce_list, String created_by, List<String> url_list, String comment)
|
||||
{
|
||||
this.announce = announce;
|
||||
this.name = name;
|
||||
@@ -93,9 +98,13 @@ public class MetaInfo
|
||||
this.length = length;
|
||||
this.privateTorrent = privateTorrent;
|
||||
this.announce_list = announce_list;
|
||||
this.comment = null;
|
||||
this.comment = comment;
|
||||
this.created_by = created_by;
|
||||
this.creation_date = I2PAppContext.getGlobalContext().clock().now();
|
||||
this.url_list = url_list;
|
||||
|
||||
// TODO BEP 52 hybrid torrent with piece layers, meta version and file tree
|
||||
this.attributes = null;
|
||||
|
||||
// TODO if we add a parameter for other keys
|
||||
//if (other != null) {
|
||||
@@ -171,6 +180,18 @@ public class MetaInfo
|
||||
}
|
||||
}
|
||||
|
||||
// BEP 19
|
||||
val = m.get("url-list");
|
||||
if (val == null) {
|
||||
this.url_list = null;
|
||||
} else {
|
||||
List<BEValue> bl1 = val.getList();
|
||||
this.url_list = new ArrayList<String>(bl1.size());
|
||||
for (BEValue bev : bl1) {
|
||||
this.url_list.add(bev.getString());
|
||||
}
|
||||
}
|
||||
|
||||
// misc. optional top-level stuff
|
||||
val = m.get("comment");
|
||||
String st = null;
|
||||
@@ -238,8 +259,18 @@ public class MetaInfo
|
||||
piece_length = val.getInt();
|
||||
|
||||
val = info.get("pieces");
|
||||
if (val == null)
|
||||
if (val == null) {
|
||||
// BEP 52
|
||||
// We do the check here because a torrent file could be combined v1/v2,
|
||||
// so a version 2 value isn't by itself fatal
|
||||
val = info.get("meta version");
|
||||
if (val != null) {
|
||||
int version = val.getInt();
|
||||
if (version != 1)
|
||||
throw new InvalidBEncodingException("Version " + version + " torrent file not supported");
|
||||
}
|
||||
throw new InvalidBEncodingException("Missing piece bytes");
|
||||
}
|
||||
piece_hashes = val.getBytes();
|
||||
|
||||
val = info.get("length");
|
||||
@@ -250,6 +281,7 @@ public class MetaInfo
|
||||
files = null;
|
||||
files_utf8 = null;
|
||||
lengths = null;
|
||||
attributes = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -265,8 +297,9 @@ public class MetaInfo
|
||||
throw new InvalidBEncodingException("zero size files list");
|
||||
|
||||
List<List<String>> m_files = new ArrayList<List<String>>(size);
|
||||
List<List<String>> m_files_utf8 = new ArrayList<List<String>>(size);
|
||||
List<List<String>> m_files_utf8 = null;
|
||||
List<Long> m_lengths = new ArrayList<Long>(size);
|
||||
List<String> m_attributes = null;
|
||||
long l = 0;
|
||||
for (int i = 0; i < list.size(); i++)
|
||||
{
|
||||
@@ -312,6 +345,7 @@ public class MetaInfo
|
||||
|
||||
val = desc.get("path.utf-8");
|
||||
if (val != null) {
|
||||
m_files_utf8 = new ArrayList<List<String>>(size);
|
||||
path_list = val.getList();
|
||||
path_length = path_list.size();
|
||||
if (path_length > 0) {
|
||||
@@ -322,11 +356,28 @@ public class MetaInfo
|
||||
m_files_utf8.add(Collections.unmodifiableList(file));
|
||||
}
|
||||
}
|
||||
|
||||
// BEP 47
|
||||
val = desc.get("attr");
|
||||
if (val != null) {
|
||||
String s = val.getString();
|
||||
if (m_attributes == null) {
|
||||
m_attributes = new ArrayList<String>(size);
|
||||
for (int j = 0; j < i; j++) {
|
||||
m_attributes.add("");
|
||||
}
|
||||
m_attributes.add(s);
|
||||
}
|
||||
} else {
|
||||
if (m_attributes != null)
|
||||
m_attributes.add("");
|
||||
}
|
||||
}
|
||||
files = Collections.unmodifiableList(m_files);
|
||||
files_utf8 = Collections.unmodifiableList(m_files_utf8);
|
||||
files_utf8 = m_files_utf8 != null ? Collections.unmodifiableList(m_files_utf8) : null;
|
||||
lengths = Collections.unmodifiableList(m_lengths);
|
||||
length = l;
|
||||
attributes = m_attributes;
|
||||
}
|
||||
|
||||
info_hash = calculateInfoHash();
|
||||
@@ -372,6 +423,15 @@ public class MetaInfo
|
||||
return announce_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of urls or null.
|
||||
*
|
||||
* @since 0.9.48
|
||||
*/
|
||||
public List<String> getWebSeedURLs() {
|
||||
return url_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the original 20 byte SHA1 hash over the bencoded info map.
|
||||
*/
|
||||
@@ -417,6 +477,16 @@ public class MetaInfo
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this file a padding file?
|
||||
* @since 0.9.48
|
||||
*/
|
||||
public boolean isPaddingFile(int filenum) {
|
||||
if (attributes == null)
|
||||
return false;
|
||||
return attributes.get(filenum).indexOf('p') >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of Longs indication the size of the individual
|
||||
* files, or null if it is a single file. It has the same size as
|
||||
@@ -552,6 +622,7 @@ public class MetaInfo
|
||||
|
||||
/**
|
||||
* Returns the total length of the torrent in bytes.
|
||||
* This includes any padding files.
|
||||
*/
|
||||
public long getTotalLength()
|
||||
{
|
||||
@@ -599,6 +670,8 @@ public class MetaInfo
|
||||
if (announce_list != null)
|
||||
m.put("announce-list", announce_list);
|
||||
// misc. optional top-level stuff
|
||||
if (url_list != null)
|
||||
m.put("url-list", url_list);
|
||||
if (comment != null)
|
||||
m.put("comment", comment);
|
||||
if (created_by != null)
|
||||
@@ -612,11 +685,27 @@ public class MetaInfo
|
||||
return BEncoder.bencode(m);
|
||||
}
|
||||
|
||||
/** @since 0.8.4 */
|
||||
/**
|
||||
* Side effect: Caches infoBytesLength.
|
||||
* @since 0.8.4
|
||||
*/
|
||||
public synchronized byte[] getInfoBytes() {
|
||||
if (infoMap == null)
|
||||
createInfoMap();
|
||||
return BEncoder.bencode(infoMap);
|
||||
byte[] rv = BEncoder.bencode(infoMap);
|
||||
infoBytesLength = rv.length;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* The size of getInfoBytes().
|
||||
* Cached.
|
||||
* @since 0.9.48
|
||||
*/
|
||||
public synchronized int getInfoBytesLength() {
|
||||
if (infoBytesLength > 0)
|
||||
return infoBytesLength;
|
||||
return getInfoBytes().length;
|
||||
}
|
||||
|
||||
/** @return an unmodifiable view of the Map */
|
||||
@@ -665,11 +754,19 @@ public class MetaInfo
|
||||
file.put("path.utf-8", new BEValue(beufiles));
|
||||
}
|
||||
file.put("length", new BEValue(lengths.get(i)));
|
||||
String attr = null;
|
||||
if (attributes != null) {
|
||||
attr = attributes.get(i);
|
||||
if (attr.length() > 0)
|
||||
file.put("attr", new BEValue(DataHelper.getASCII(attr)));
|
||||
}
|
||||
l.add(new BEValue(file));
|
||||
}
|
||||
info.put("files", new BEValue(l));
|
||||
}
|
||||
|
||||
// TODO BEP 52 meta version and file tree
|
||||
|
||||
// TODO if we add the ability for other keys in the first constructor
|
||||
//if (otherInfo != null)
|
||||
// info.putAll(otherInfo);
|
||||
@@ -706,7 +803,9 @@ public class MetaInfo
|
||||
boolean error = false;
|
||||
String created_by = null;
|
||||
String announce = null;
|
||||
Getopt g = new Getopt("Storage", args, "a:c:");
|
||||
List<String> url_list = null;
|
||||
String comment = null;
|
||||
Getopt g = new Getopt("Storage", args, "a:c:m:w:");
|
||||
try {
|
||||
int c;
|
||||
while ((c = g.getopt()) != -1) {
|
||||
@@ -719,6 +818,16 @@ public class MetaInfo
|
||||
created_by = g.getOptarg();
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
comment = g.getOptarg();
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if (url_list == null)
|
||||
url_list = new ArrayList<String>();
|
||||
url_list.add(g.getOptarg());
|
||||
break;
|
||||
|
||||
case '?':
|
||||
case ':':
|
||||
default:
|
||||
@@ -731,7 +840,8 @@ public class MetaInfo
|
||||
error = true;
|
||||
}
|
||||
if (error || args.length - g.getOptind() <= 0) {
|
||||
System.err.println("Usage: MetaInfo [-a announceURL] [-c created-by] file.torrent [file2.torrent...]");
|
||||
System.err.println("Usage: MetaInfo [-a announceURL] [-c created-by] [-m comment] [-w webseed-url]* file.torrent [file2.torrent...]");
|
||||
System.exit(1);
|
||||
}
|
||||
for (int i = g.getOptind(); i < args.length; i++) {
|
||||
InputStream in = null;
|
||||
@@ -739,16 +849,21 @@ public class MetaInfo
|
||||
try {
|
||||
in = new FileInputStream(args[i]);
|
||||
MetaInfo meta = new MetaInfo(in);
|
||||
System.out.println(args[i] + "\nInfoHash: " + I2PSnarkUtil.toHex(meta.getInfoHash()) +
|
||||
"\nAnnounce: " + meta.getAnnounce() +
|
||||
"\nCreated By: " + meta.getCreatedBy());
|
||||
if (created_by != null || announce != null) {
|
||||
System.out.println(args[i] +
|
||||
"\nInfoHash: " + I2PSnarkUtil.toHex(meta.getInfoHash()) +
|
||||
"\nAnnounce: " + meta.getAnnounce() +
|
||||
"\nWebSeed URLs: " + meta.getWebSeedURLs() +
|
||||
"\nCreated By: " + meta.getCreatedBy() +
|
||||
"\nComment: " + meta.getComment());
|
||||
if (created_by != null || announce != null || url_list != null || comment != null) {
|
||||
String cb = created_by != null ? created_by : meta.getCreatedBy();
|
||||
String an = announce != null ? announce : meta.getAnnounce();
|
||||
// changes/adds creation date, loses comment
|
||||
String cm = comment != null ? comment : meta.getComment();
|
||||
List<String> urls = url_list != null ? url_list : meta.getWebSeedURLs();
|
||||
// changes/adds creation date
|
||||
MetaInfo meta2 = new MetaInfo(an, meta.getName(), null, meta.getFiles(), meta.getLengths(),
|
||||
meta.getPieceLength(0), meta.getPieceHashes(), meta.getTotalLength(), meta.isPrivate(),
|
||||
meta.getAnnounceList(), cb);
|
||||
meta.getAnnounceList(), cb, urls, cm);
|
||||
java.io.File from = new java.io.File(args[i]);
|
||||
java.io.File to = new java.io.File(args[i] + ".bak");
|
||||
if (net.i2p.util.FileUtil.copy(from, to, true, false)) {
|
||||
@@ -756,9 +871,12 @@ public class MetaInfo
|
||||
out.write(meta2.getTorrentData());
|
||||
out.close();
|
||||
System.out.println("Modified " + from + " and backed up old file to " + to);
|
||||
System.out.println(args[i] + "\nInfoHash: " + I2PSnarkUtil.toHex(meta2.getInfoHash()) +
|
||||
"\nAnnounce: " + meta2.getAnnounce() +
|
||||
"\nCreated By: " + meta2.getCreatedBy());
|
||||
System.out.println(args[i] +
|
||||
"\nInfoHash: " + I2PSnarkUtil.toHex(meta2.getInfoHash()) +
|
||||
"\nAnnounce: " + meta2.getAnnounce() +
|
||||
"\nWebSeed URLs: " + meta2.getWebSeedURLs() +
|
||||
"\nCreated By: " + meta2.getCreatedBy() +
|
||||
"\nComment: " + meta2.getComment());
|
||||
} else {
|
||||
System.out.println("Failed backup of " + from + " to " + to);
|
||||
}
|
||||
|
||||
@@ -38,17 +38,18 @@ import net.i2p.data.Destination;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import org.klomp.snark.bencode.BEValue;
|
||||
import org.klomp.snark.bencode.InvalidBEncodingException;
|
||||
|
||||
public class Peer implements Comparable<Peer>
|
||||
{
|
||||
private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(Peer.class);
|
||||
protected final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
|
||||
// Identifying property, the peer id of the other side.
|
||||
private final PeerID peerID;
|
||||
|
||||
private final byte[] my_id;
|
||||
private final byte[] infohash;
|
||||
/** will start out null in magnet mode */
|
||||
private MetaInfo metainfo;
|
||||
protected MetaInfo metainfo;
|
||||
private Map<String, BEValue> handshakeMap;
|
||||
|
||||
// The data in/output streams set during the handshake and used by
|
||||
@@ -60,8 +61,11 @@ public class Peer implements Comparable<Peer>
|
||||
private final AtomicLong downloaded = new AtomicLong();
|
||||
private final AtomicLong uploaded = new AtomicLong();
|
||||
|
||||
// Keeps state for in/out connections. Non-null when the handshake
|
||||
// was successful, the connection setup and runs
|
||||
/** `
|
||||
* Keeps state for in/out connections. Non-null when the handshake
|
||||
* was successful, the connection setup and runs.
|
||||
* Do not access directly. All actions should be through Peer methods.
|
||||
*/
|
||||
volatile PeerState state;
|
||||
|
||||
/** shared across all peers on this torrent */
|
||||
@@ -76,22 +80,22 @@ public class Peer implements Comparable<Peer>
|
||||
|
||||
final static long CHECK_PERIOD = PeerCoordinator.CHECK_PERIOD; // 40 seconds
|
||||
final static int RATE_DEPTH = PeerCoordinator.RATE_DEPTH; // make following arrays RATE_DEPTH long
|
||||
private long uploaded_old[] = {-1,-1,-1};
|
||||
private long downloaded_old[] = {-1,-1,-1};
|
||||
private final long uploaded_old[] = {-1,-1,-1};
|
||||
private final long downloaded_old[] = {-1,-1,-1};
|
||||
|
||||
private static final byte[] HANDSHAKE = DataHelper.getASCII("BitTorrent protocol");
|
||||
// See BEP 4 for definitions
|
||||
// bytes per bt spec: 0011223344556677
|
||||
private static final long OPTION_EXTENSION = 0x0000000000100000l;
|
||||
private static final long OPTION_FAST = 0x0000000000000004l;
|
||||
//private static final long OPTION_DHT = 0x0000000000000001l;
|
||||
/** we use a different bit since the compact format is different */
|
||||
/* no, let's use an extension message
|
||||
static final long OPTION_I2P_DHT = 0x0000000040000000l;
|
||||
*/
|
||||
//private static final long OPTION_AZMP = 0x1000000000000000l;
|
||||
// hybrid support TODO
|
||||
private static final long OPTION_V2 = 0x0000000000000010L;
|
||||
private long options;
|
||||
private final boolean _isIncoming;
|
||||
private int _totalCommentsSent;
|
||||
private int _maxPipeline = PeerState.MIN_PIPELINE;
|
||||
|
||||
/**
|
||||
* Outgoing connection.
|
||||
@@ -289,7 +293,7 @@ public class Peer implements Comparable<Peer>
|
||||
if ((options & OPTION_EXTENSION) != 0) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Peer supports extensions, sending reply message");
|
||||
int metasize = metainfo != null ? metainfo.getInfoBytes().length : -1;
|
||||
int metasize = metainfo != null ? metainfo.getInfoBytesLength() : -1;
|
||||
boolean pexAndMetadata = metainfo == null || !metainfo.isPrivate();
|
||||
boolean dht = util.getDHT() != null;
|
||||
boolean comment = util.utCommentsEnabled();
|
||||
@@ -340,7 +344,6 @@ public class Peer implements Comparable<Peer>
|
||||
private byte[] handshake(InputStream in, OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
din = new DataInputStream(in);
|
||||
dout = new DataOutputStream(out);
|
||||
|
||||
// Handshake write - header
|
||||
@@ -365,6 +368,7 @@ public class Peer implements Comparable<Peer>
|
||||
_log.debug("Wrote my shared hash and ID to " + toString());
|
||||
|
||||
// Handshake read - header
|
||||
din = new DataInputStream(in);
|
||||
byte b = din.readByte();
|
||||
if (b != HANDSHAKE.length)
|
||||
throw new IOException("Handshake failure, expected 19, got "
|
||||
@@ -428,9 +432,30 @@ public class Peer implements Comparable<Peer>
|
||||
return handshakeMap;
|
||||
}
|
||||
|
||||
/** @since 0.8.4 */
|
||||
/**
|
||||
* @param map non-null
|
||||
* @since 0.8.4
|
||||
*/
|
||||
public void setHandshakeMap(Map<String, BEValue> map) {
|
||||
handshakeMap = map;
|
||||
BEValue bev = map.get("reqq");
|
||||
if (bev != null) {
|
||||
try {
|
||||
int reqq = bev.getInt();
|
||||
_maxPipeline = Math.min(PeerState.MAX_PIPELINE, Math.max(PeerState.MIN_PIPELINE, reqq));
|
||||
} catch (InvalidBEncodingException ibee) {}
|
||||
} else {
|
||||
// BEP 10 "The default in libtorrent is 250"
|
||||
_maxPipeline = PeerState.MAX_PIPELINE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return min of PeerState.MIN_PIPELINE, max of PeerState.MAX_PIPELINE
|
||||
* @since 0.9.47
|
||||
*/
|
||||
public int getMaxPipeline() {
|
||||
return _maxPipeline;
|
||||
}
|
||||
|
||||
/** @since 0.8.4 */
|
||||
@@ -644,7 +669,8 @@ public class Peer implements Comparable<Peer>
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that have been downloaded.
|
||||
* Can be reset to zero with <code>resetCounters()</code>/
|
||||
* Can be reset to zero with <code>resetCounters()</code>
|
||||
* which is called every CHECK_PERIOD by PeerCheckerTask.
|
||||
*/
|
||||
public long getDownloaded()
|
||||
{
|
||||
@@ -653,7 +679,8 @@ public class Peer implements Comparable<Peer>
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that have been uploaded.
|
||||
* Can be reset to zero with <code>resetCounters()</code>/
|
||||
* Can be reset to zero with <code>resetCounters()</code>
|
||||
* which is called every CHECK_PERIOD by PeerCheckerTask.
|
||||
*/
|
||||
public long getUploaded()
|
||||
{
|
||||
@@ -765,4 +792,12 @@ public class Peer implements Comparable<Peer>
|
||||
void setTotalCommentsSent(int count) {
|
||||
_totalCommentsSent = count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false
|
||||
* @since 0.9.49
|
||||
*/
|
||||
public boolean isWebPeer() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -152,6 +153,10 @@ class PeerCoordinator implements PeerListener
|
||||
private static final long COMMENT_REQ_INTERVAL = 12*60*60*1000L;
|
||||
private static final long COMMENT_REQ_DELAY = 60*60*1000L;
|
||||
private static final int MAX_COMMENT_NOT_REQ = 10;
|
||||
|
||||
/** hostname to expire time, sync on this */
|
||||
private Map<String, Long> _webPeerBans;
|
||||
private static final long WEBPEER_BAN_TIME = 30*60*1000L;
|
||||
|
||||
/**
|
||||
* @param metainfo null if in magnet mode
|
||||
@@ -916,6 +921,7 @@ class PeerCoordinator implements PeerListener
|
||||
// As connections are already up, new Pieces will
|
||||
// not have their PeerID list populated, so do that.
|
||||
for (Peer p : peers) {
|
||||
// TODO don't access state directly
|
||||
PeerState s = p.state;
|
||||
if (s != null) {
|
||||
BitField bf = s.bitfield;
|
||||
@@ -1062,7 +1068,8 @@ class PeerCoordinator implements PeerListener
|
||||
// just in case
|
||||
removePartialPiece(piece);
|
||||
// Oops. We didn't actually download this then... :(
|
||||
downloaded.addAndGet(0 - metainfo.getPieceLength(piece));
|
||||
// Reports of counter going negative?
|
||||
//downloaded.addAndGet(0 - metainfo.getPieceLength(piece));
|
||||
// Mark this peer as not having the piece. PeerState will update its bitfield.
|
||||
for (Piece pc : wantedPieces) {
|
||||
if (pc.getId() == piece) {
|
||||
@@ -1299,6 +1306,7 @@ class PeerCoordinator implements PeerListener
|
||||
if (++seeds >= 4)
|
||||
break;
|
||||
} else {
|
||||
// TODO don't access state directly
|
||||
PeerState state = pr.state;
|
||||
if (state == null) continue;
|
||||
BitField bf = state.bitfield;
|
||||
@@ -1336,6 +1344,7 @@ class PeerCoordinator implements PeerListener
|
||||
// Temporary? So PeerState never calls wantPiece() directly for now...
|
||||
Piece piece = wantPiece(peer, havePieces, true);
|
||||
if (piece != null) {
|
||||
// TODO padding
|
||||
return new PartialPiece(piece, metainfo.getPieceLength(piece.getId()), _util.getTempDir());
|
||||
}
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
@@ -1452,6 +1461,10 @@ class PeerCoordinator implements PeerListener
|
||||
if (bev.getMap().get(ExtensionHandler.TYPE_PEX) != null) {
|
||||
List<Peer> pList = peerList();
|
||||
pList.remove(peer);
|
||||
for (Iterator<Peer> iter = pList.iterator(); iter.hasNext(); ) {
|
||||
if (iter.next().isWebPeer())
|
||||
iter.remove();
|
||||
}
|
||||
if (!pList.isEmpty())
|
||||
ExtensionHandler.sendPEX(peer, pList);
|
||||
}
|
||||
@@ -1749,5 +1762,43 @@ class PeerCoordinator implements PeerListener
|
||||
public I2PSnarkUtil getUtil() {
|
||||
return _util;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ban a web peer for this torrent, for while or permanently.
|
||||
* @param host the host name
|
||||
* @since 0.9.49
|
||||
*/
|
||||
public synchronized void banWebPeer(String host, boolean isPermanent) {
|
||||
if (_webPeerBans == null)
|
||||
_webPeerBans = new HashMap<String, Long>(4);
|
||||
Long time;
|
||||
if (isPermanent) {
|
||||
time = Long.valueOf(Long.MAX_VALUE);
|
||||
} else {
|
||||
long now = _util.getContext().clock().now();
|
||||
time = Long.valueOf(now + WEBPEER_BAN_TIME);
|
||||
}
|
||||
Long old = _webPeerBans.put(host, time);
|
||||
if (old != null && old.longValue() > time)
|
||||
_webPeerBans.put(host, old);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a web peer banned?
|
||||
* @param host the host name
|
||||
* @since 0.9.49
|
||||
*/
|
||||
public synchronized boolean isWebPeerBanned(String host) {
|
||||
if (_webPeerBans == null)
|
||||
return false;
|
||||
Long time = _webPeerBans.get(host);
|
||||
if (time == null)
|
||||
return false;
|
||||
long now = _util.getContext().clock().now();
|
||||
boolean rv = time.longValue() > now;
|
||||
if (!rv)
|
||||
_webPeerBans.remove(host);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -227,6 +227,10 @@ public class PeerID implements Comparable<PeerID>
|
||||
{
|
||||
if (_toStringCache != null)
|
||||
return _toStringCache;
|
||||
if (id != null && DataHelper.eq(id, 0, WebPeer.IDBytes, 0, WebPeer.IDBytes.length)) {
|
||||
_toStringCache = "WebSeed@" + Base32.encode(destHash) + ".b32.i2p";
|
||||
return _toStringCache;
|
||||
}
|
||||
if (id == null || address == null)
|
||||
return "unkn@" + Base64.encode(destHash).substring(0, 6);
|
||||
int nonZero = 0;
|
||||
|
||||
@@ -69,9 +69,12 @@ class PeerState implements DataLoader
|
||||
private Request lastRequest = null;
|
||||
|
||||
// FIXME if piece size < PARTSIZE, pipeline could be bigger
|
||||
private final static int MAX_PIPELINE = 5; // this is for outbound requests
|
||||
private final static int MAX_PIPELINE_BYTES = 128*1024; // this is for inbound requests
|
||||
/** @since 0.9.47 */
|
||||
public static final int MIN_PIPELINE = 5; // this is for outbound requests
|
||||
/** @since public since 0.9.47 */
|
||||
public static final int MAX_PIPELINE = 8; // this is for outbound requests
|
||||
public final static int PARTSIZE = 16*1024; // outbound request
|
||||
private final static int MAX_PIPELINE_BYTES = (MAX_PIPELINE + 2) * PARTSIZE; // this is for inbound requests
|
||||
private final static int MAX_PARTSIZE = 64*1024; // Don't let anybody request more than this
|
||||
private static final Integer PIECE_ALL = Integer.valueOf(-1);
|
||||
|
||||
@@ -259,9 +262,9 @@ class PeerState implements DataLoader
|
||||
if (bev != null) {
|
||||
try {
|
||||
if (bev.getMap().get(ExtensionHandler.TYPE_COMMENT) != null) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Allowing seed that connects to seeds for comments: " + peer);
|
||||
setInteresting(interest);
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Allowing seed that connects to seeds for comments: " + peer);
|
||||
setInteresting(false);
|
||||
return;
|
||||
}
|
||||
} catch (InvalidBEncodingException ibee) {}
|
||||
@@ -880,7 +883,7 @@ class PeerState implements DataLoader
|
||||
boolean more_pieces = true;
|
||||
while (more_pieces)
|
||||
{
|
||||
more_pieces = outstandingRequests.size() < MAX_PIPELINE;
|
||||
more_pieces = outstandingRequests.size() < peer.getMaxPipeline();
|
||||
// We want something and we don't have outstanding requests?
|
||||
if (more_pieces && lastRequest == null) {
|
||||
// we have nothing in the queue right now
|
||||
|
||||
@@ -195,8 +195,10 @@ public class SnarkManager implements CompleteListener, ClientApp {
|
||||
// ,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
|
||||
,"DgTrack", "http://w7tpbzncbcocrqtwwm3nezhnnsw4ozadvi2hmvzdhrqzfxfum7wa.b32.i2p/a=http://opentracker.dg2.i2p/"
|
||||
// The following is ECDSA_SHA256_P256
|
||||
,"TheBland", "http://s5ikrdyjwbcgxmqetxb3nyheizftms7euacuub2hic7defkh3xhq.b32.i2p/a=http://tracker.thebland.i2p/tracker/index.jsp"
|
||||
,"psi's open tracker", "http://uajd4nctepxpac4c4bdyrdw7qvja2a5u3x25otfhkptcjgd53ioq.b32.i2p/announce=http://uajd4nctepxpac4c4bdyrdw7qvja2a5u3x25otfhkptcjgd53ioq.b32.i2p/"
|
||||
//last up Sep. 19 2020
|
||||
//,"TheBland", "http://s5ikrdyjwbcgxmqetxb3nyheizftms7euacuub2hic7defkh3xhq.b32.i2p/a=http://tracker.thebland.i2p/tracker/index.jsp"
|
||||
//down for good
|
||||
//,"psi's open tracker", "http://uajd4nctepxpac4c4bdyrdw7qvja2a5u3x25otfhkptcjgd53ioq.b32.i2p/announce=http://uajd4nctepxpac4c4bdyrdw7qvja2a5u3x25otfhkptcjgd53ioq.b32.i2p/"
|
||||
//last up May 21 2019
|
||||
// ,"C.Tracker", "http://ri5a27ioqd4vkik72fawbcryglkmwyy4726uu5j3eg6zqh2jswfq.b32.i2p/announce=http://tracker.crypthost.i2p/tracker/index.jsp",
|
||||
};
|
||||
@@ -205,8 +207,8 @@ public class SnarkManager implements CompleteListener, ClientApp {
|
||||
public static final String DEFAULT_BACKUP_TRACKER = "http://opentracker.dg2.i2p/a";
|
||||
|
||||
/** URLs, comma-separated. Used for "announce to open trackers also" */
|
||||
private static final String DEFAULT_OPENTRACKERS = DEFAULT_BACKUP_TRACKER +
|
||||
(SigType.ECDSA_SHA256_P256.isAvailable() ? ",http://tracker.thebland.i2p/a" : "");
|
||||
private static final String DEFAULT_OPENTRACKERS = DEFAULT_BACKUP_TRACKER; // +
|
||||
//(SigType.ECDSA_SHA256_P256.isAvailable() ? ",http://tracker.thebland.i2p/a" : "");
|
||||
|
||||
public static final Set<String> DEFAULT_TRACKER_ANNOUNCES;
|
||||
|
||||
@@ -881,6 +883,31 @@ public class SnarkManager implements CompleteListener, ClientApp {
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the preferred embedded icons for toImg, "solid/" for
|
||||
* dark and light, "" for everything else.
|
||||
*
|
||||
* If you add a theme with a new icon set, then you need to add a
|
||||
* corresponding condition here.
|
||||
*
|
||||
* @return String "solid/" or ""
|
||||
* @since 0.9.48
|
||||
*/
|
||||
public String getThemeIconSet() {
|
||||
String iconset;
|
||||
String theme = getTheme();
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Theme was: " + theme);
|
||||
if (theme.equals("dark") || theme.equals("light")) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Using solid iconset.");
|
||||
iconset = "solid/";
|
||||
} else {
|
||||
iconset = "";
|
||||
}
|
||||
return iconset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all themes
|
||||
|
||||
@@ -144,6 +144,30 @@ public class Storage implements Closeable
|
||||
String created_by,
|
||||
boolean privateTorrent, StorageListener listener)
|
||||
throws IOException
|
||||
{
|
||||
this(util, baseFile, announce, announce_list, created_by, privateTorrent, null, null, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a storage from the existing file or directory.
|
||||
* Creates an in-memory metainfo but does not save it to
|
||||
* a file, caller must do that.
|
||||
*
|
||||
* Creates the metainfo, this may take a LONG time. BLOCKING.
|
||||
*
|
||||
* @param announce may be null
|
||||
* @param listener may be null
|
||||
* @param created_by may be null
|
||||
* @param url_list may be null
|
||||
* @param comment may be null
|
||||
* @throws IOException when creating and/or checking files fails.
|
||||
* @since 0.9.48
|
||||
*/
|
||||
public Storage(I2PSnarkUtil util, File baseFile, String announce,
|
||||
List<List<String>> announce_list,
|
||||
String created_by,
|
||||
boolean privateTorrent, List<String> url_list, String comment, StorageListener listener)
|
||||
throws IOException
|
||||
{
|
||||
_util = util;
|
||||
_base = baseFile;
|
||||
@@ -210,7 +234,7 @@ public class Storage implements Closeable
|
||||
byte[] piece_hashes = fast_digestCreate();
|
||||
metainfo = new MetaInfo(announce, baseFile.getName(), null, files,
|
||||
lengthsList, piece_size, piece_hashes, total, privateTorrent,
|
||||
announce_list, created_by);
|
||||
announce_list, created_by, url_list, comment);
|
||||
|
||||
}
|
||||
|
||||
@@ -1364,6 +1388,7 @@ public class Storage implements Closeable
|
||||
//rafs[i].write(bs, off + written, len);
|
||||
pp.write(raf, written, len);
|
||||
} catch (IOException ioe) {
|
||||
try { tf.closeRAF(); } catch (IOException ioe2) {}
|
||||
// get the file name in the logs
|
||||
IOException ioe2 = new IOException("Error writing " + tf.RAFfile.getAbsolutePath());
|
||||
ioe2.initCause(ioe);
|
||||
@@ -1470,6 +1495,7 @@ public class Storage implements Closeable
|
||||
raf.seek(start);
|
||||
raf.readFully(bs, read, len);
|
||||
} catch (IOException ioe) {
|
||||
try { tf.closeRAF(); } catch (IOException ioe2) {}
|
||||
// get the file name in the logs
|
||||
IOException ioe2 = new IOException("Error reading " + tf.RAFfile.getAbsolutePath());
|
||||
ioe2.initCause(ioe);
|
||||
@@ -1685,7 +1711,9 @@ public class Storage implements Closeable
|
||||
boolean error = false;
|
||||
String created_by = null;
|
||||
String announce = null;
|
||||
Getopt g = new Getopt("Storage", args, "a:c:");
|
||||
List<String> url_list = null;
|
||||
String comment = null;
|
||||
Getopt g = new Getopt("Storage", args, "a:c:m:w:");
|
||||
try {
|
||||
int c;
|
||||
while ((c = g.getopt()) != -1) {
|
||||
@@ -1698,6 +1726,16 @@ public class Storage implements Closeable
|
||||
created_by = g.getOptarg();
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
comment = g.getOptarg();
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if (url_list == null)
|
||||
url_list = new ArrayList<String>();
|
||||
url_list.add(g.getOptarg());
|
||||
break;
|
||||
|
||||
case '?':
|
||||
case ':':
|
||||
default:
|
||||
@@ -1710,7 +1748,7 @@ public class Storage implements Closeable
|
||||
error = true;
|
||||
}
|
||||
if (error || args.length - g.getOptind() != 1) {
|
||||
System.err.println("Usage: Storage [-a announceURL] [-c created-by] file-or-dir");
|
||||
System.err.println("Usage: Storage [-a announceURL] [-c created-by] [-m comment] [-w webseed-url]* file-or-dir");
|
||||
System.exit(1);
|
||||
}
|
||||
File base = new File(args[g.getOptind()]);
|
||||
@@ -1719,7 +1757,7 @@ public class Storage implements Closeable
|
||||
File file = null;
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
Storage storage = new Storage(util, base, announce, null, created_by, false, null);
|
||||
Storage storage = new Storage(util, base, announce, null, created_by, false, url_list, comment, null);
|
||||
MetaInfo meta = storage.getMetaInfo();
|
||||
file = new File(storage.getBaseName() + ".torrent");
|
||||
out = new FileOutputStream(file);
|
||||
|
||||
@@ -407,6 +407,8 @@ public class TrackerClient implements Runnable {
|
||||
return;
|
||||
}
|
||||
|
||||
int webPeers = getWebPeers();
|
||||
|
||||
// Local DHT tracker announce
|
||||
DHT dht = _util.getDHT();
|
||||
if (dht != null && (meta == null || !meta.isPrivate()))
|
||||
@@ -438,7 +440,7 @@ public class TrackerClient implements Runnable {
|
||||
}
|
||||
|
||||
// we could try and total the unique peers but that's too hard for now
|
||||
snark.setTrackerSeenPeers(maxSeenPeers);
|
||||
snark.setTrackerSeenPeers(maxSeenPeers + webPeers);
|
||||
|
||||
if (stop)
|
||||
return;
|
||||
@@ -720,6 +722,62 @@ public class TrackerClient implements Runnable {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return valid web peers from metainfo
|
||||
* @since 0.9.49
|
||||
*/
|
||||
private int getWebPeers() {
|
||||
if (meta == null)
|
||||
return 0;
|
||||
// prevent connecting out to a webseed for comments only
|
||||
if (coordinator.getNeededLength() <= 0)
|
||||
return 0;
|
||||
List<String> urls = meta.getWebSeedURLs();
|
||||
if (urls == null || urls.isEmpty())
|
||||
return 0;
|
||||
// Uncomment to skip multifile torrents
|
||||
//if (meta.getLengths() != null)
|
||||
// return 0;
|
||||
List<Peer> peers = new ArrayList<Peer>(urls.size());
|
||||
for (String url : urls) {
|
||||
Hash h = getHostHash(url);
|
||||
if (h == null)
|
||||
continue;
|
||||
try {
|
||||
PeerID pID = new PeerID(h.getData(), _util);
|
||||
byte[] id = new byte[20];
|
||||
System.arraycopy(WebPeer.IDBytes, 0, id, 0, 12);
|
||||
System.arraycopy(h.getData(), 0, id, 12, 8);
|
||||
pID.setID(id);
|
||||
URI uri = new URI(url);
|
||||
String host = uri.getHost();
|
||||
if (host == null)
|
||||
continue;
|
||||
if (coordinator.isWebPeerBanned(host)) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Skipping banned webseed " + url);
|
||||
continue;
|
||||
}
|
||||
peers.add(new WebPeer(coordinator, uri, pID, snark.getMetaInfo()));
|
||||
} catch (InvalidBEncodingException ibe) {
|
||||
} catch (URISyntaxException use) {
|
||||
}
|
||||
}
|
||||
if (peers.isEmpty())
|
||||
return 0;
|
||||
Random r = _util.getContext().random();
|
||||
if (peers.size() > 1)
|
||||
Collections.shuffle(peers, r);
|
||||
Iterator<Peer> it = peers.iterator();
|
||||
while ((!stop) && it.hasNext() && coordinator.needOutboundPeers()) {
|
||||
Peer cur = it.next();
|
||||
if (coordinator.addPeer(cur) && it.hasNext()) {
|
||||
int delay = r.nextInt(DELAY_RAND) + DELAY_MIN;
|
||||
try { Thread.sleep(delay); } catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
return peers.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a thread for each tracker in parallel if tunnel is still open
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.klomp.snark.web;
|
||||
package org.klomp.snark;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
@@ -35,9 +35,9 @@ import net.i2p.data.DataHelper;
|
||||
* see UrlEncoded
|
||||
*
|
||||
* I2P modded from Jetty 8.1.15
|
||||
* @since 0.9.15
|
||||
* @since 0.9.15, moved from web in 0.9.49
|
||||
*/
|
||||
class URIUtil
|
||||
public class URIUtil
|
||||
{
|
||||
|
||||
/** Encode a URI path.
|
||||
667
apps/i2psnark/java/src/org/klomp/snark/WebPeer.java
Normal file
667
apps/i2psnark/java/src/org/klomp/snark/WebPeer.java
Normal file
@@ -0,0 +1,667 @@
|
||||
package org.klomp.snark;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.I2PSocketEepGet;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.EepGet;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* BEP 19.
|
||||
* Does not have an associated PeerState.
|
||||
* All request tracking is done here.
|
||||
* @since 0.9.49
|
||||
*/
|
||||
class WebPeer extends Peer implements EepGet.StatusListener {
|
||||
|
||||
private final PeerCoordinator _coordinator;
|
||||
private final URI _uri;
|
||||
// as received from coordinator
|
||||
private final List<Request> outstandingRequests = new ArrayList<Request>();
|
||||
private final boolean isMultiFile;
|
||||
// needed?
|
||||
private Request lastRequest;
|
||||
private PeerListener listener;
|
||||
private BitField bitfield;
|
||||
private Thread thread;
|
||||
private boolean connected;
|
||||
private long lastRcvd;
|
||||
private int maxRequests;
|
||||
|
||||
// to be recognized by the UI
|
||||
public static final byte[] IDBytes = DataHelper.getASCII("WebSeedBEP19");
|
||||
private static final long HEADER_TIMEOUT = 60*1000;
|
||||
private static final long TOTAL_TIMEOUT = 10*60*1000;
|
||||
private static final long INACTIVITY_TIMEOUT = 2*60*1000;
|
||||
private static final long TARGET_FETCH_TIME = 2*60*1000;
|
||||
// 128 KB
|
||||
private static final int ABSOLUTE_MIN_REQUESTS = 8;
|
||||
// 2 MB
|
||||
private static final int ABSOLUTE_MAX_REQUESTS = 128;
|
||||
private final int MIN_REQUESTS;
|
||||
private final int MAX_REQUESTS;
|
||||
|
||||
/**
|
||||
* Outgoing connection.
|
||||
* Creates a disconnected peer given a PeerID, your own id and the
|
||||
* relevant MetaInfo.
|
||||
* @param uri must be http with .i2p host
|
||||
* @param metainfo non-null
|
||||
*/
|
||||
public WebPeer(PeerCoordinator coord, URI uri, PeerID peerID, MetaInfo metainfo) {
|
||||
super(peerID, null, null, metainfo);
|
||||
// no use asking for more than the number of chunks in a piece
|
||||
MAX_REQUESTS = Math.max(1, Math.min(ABSOLUTE_MAX_REQUESTS, metainfo.getPieceLength(0) / PeerState.PARTSIZE));
|
||||
MIN_REQUESTS = Math.min(ABSOLUTE_MIN_REQUESTS, MAX_REQUESTS);
|
||||
maxRequests = MIN_REQUESTS;
|
||||
isMultiFile = metainfo.getLengths() != null;
|
||||
_coordinator = coord;
|
||||
// We'll assume the base path is already encoded, because
|
||||
// it would have failed the checks in TrackerClient.getHostHash()
|
||||
_uri = uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WebSeed " + _uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return socket debug string (for debug printing)
|
||||
*/
|
||||
@Override
|
||||
public synchronized String getSocket() {
|
||||
return toString() + ' ' + outstandingRequests.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* The hash code of a Peer is the hash code of the peerID.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Two Peers are equal when they have the same PeerID.
|
||||
* All other properties are ignored.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof WebPeer) {
|
||||
WebPeer p = (WebPeer)o;
|
||||
// TODO
|
||||
return getPeerID().equals(p.getPeerID());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the connection to the other peer. This method does not
|
||||
* return until the connection is terminated.
|
||||
*
|
||||
* @param ignore our bitfield, ignore
|
||||
* @param uploadOnly if we are complete with skipped files, i.e. a partial seed
|
||||
*/
|
||||
@Override
|
||||
public void runConnection(I2PSnarkUtil util, PeerListener listener, BitField ignore,
|
||||
MagnetState mState, boolean uploadOnly) {
|
||||
if (uploadOnly)
|
||||
return;
|
||||
int fails = 0;
|
||||
int successes = 0;
|
||||
long dl = 0;
|
||||
boolean notify = true;
|
||||
ByteArrayOutputStream out = null;
|
||||
// current requests per-loop
|
||||
List<Request> requests = new ArrayList<Request>(8);
|
||||
try {
|
||||
if (!util.connected()) {
|
||||
boolean ok = util.connect();
|
||||
if (!ok)
|
||||
return;
|
||||
}
|
||||
|
||||
// This breaks out of the loop after any failure. TrackerClient will requeue eventually.
|
||||
loop:
|
||||
while (true) {
|
||||
I2PSocketManager mgr = util.getSocketManager();
|
||||
if (mgr == null)
|
||||
return;
|
||||
if (notify) {
|
||||
synchronized(this) {
|
||||
this.listener = listener;
|
||||
bitfield = new BitField(metainfo.getPieces());
|
||||
bitfield.setAll();
|
||||
thread = Thread.currentThread();
|
||||
connected = true;
|
||||
}
|
||||
listener.connected(this);
|
||||
boolean want = listener.gotBitField(this, bitfield);
|
||||
if (!want)
|
||||
return;
|
||||
listener.gotChoke(this, false);
|
||||
notify = false;
|
||||
}
|
||||
|
||||
synchronized(this) {
|
||||
// clear out previous requests
|
||||
if (!requests.isEmpty()) {
|
||||
outstandingRequests.removeAll(requests);
|
||||
requests.clear();
|
||||
}
|
||||
addRequest();
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Requests: " + outstandingRequests);
|
||||
while (outstandingRequests.isEmpty()) {
|
||||
if (_coordinator.getNeededLength() <= 0) {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Complete: " + this);
|
||||
break loop;
|
||||
}
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("No requests, sleeping: " + this);
|
||||
connected = false;
|
||||
out = null;
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException ie) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Interrupted: " + this, ie);
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
connected = true;
|
||||
// Add current requests from outstandingRequests list and add to requests list.
|
||||
// Do not remove from outstandingRequests until success.
|
||||
lastRequest = outstandingRequests.get(0);
|
||||
requests.add(lastRequest);
|
||||
int piece = lastRequest.getPiece();
|
||||
|
||||
// Glue together additional requests if consecutive for a single piece.
|
||||
// This will never glue together requests from different pieces,
|
||||
// and the coordinator generally won't give us consecutive pieces anyway.
|
||||
// Servers generally won't support multiple byte ranges anymore.
|
||||
for (int i = 1; i < outstandingRequests.size(); i++) {
|
||||
if (i >= maxRequests)
|
||||
break;
|
||||
Request r = outstandingRequests.get(i);
|
||||
if (r.getPiece() == piece &&
|
||||
lastRequest.off + lastRequest.len == r.off) {
|
||||
requests.add(r);
|
||||
lastRequest = r;
|
||||
} else {
|
||||
// all requests for a piece should be together, but not in practice
|
||||
// as orphaned requests can get in-between
|
||||
//break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// total values
|
||||
Request first = requests.get(0);
|
||||
Request last = requests.get(requests.size() - 1);
|
||||
int piece = first.getPiece();
|
||||
int off = first.off;
|
||||
long toff = (((long) piece) * metainfo.getPieceLength(0)) + off;
|
||||
int tlen = (last.off - first.off) + last.len;
|
||||
long start = System.currentTimeMillis();
|
||||
///// TODO direct to file, not in-memory
|
||||
if (out == null)
|
||||
out = new ByteArrayOutputStream(tlen);
|
||||
else
|
||||
out.reset();
|
||||
int filenum = -1;
|
||||
|
||||
// Loop for each file if multifile and crosses file boundaries.
|
||||
// Once only for single file.
|
||||
while (out.size() < tlen) {
|
||||
|
||||
// need these three things:
|
||||
// url to fetch
|
||||
String url;
|
||||
// offset in fetched file
|
||||
long foff;
|
||||
// length to fetch, will be adjusted if crossing a file boundary
|
||||
int flen = tlen - out.size();
|
||||
|
||||
if (isMultiFile) {
|
||||
// multifile
|
||||
List<Long> lengths = metainfo.getLengths();
|
||||
long limit = 0;
|
||||
if (filenum < 0) {
|
||||
// find the first file number and limit
|
||||
// inclusive
|
||||
long fstart = 0;
|
||||
// exclusive
|
||||
long fend = 0;
|
||||
foff = 0; // keep compiler happy, will always be re-set
|
||||
for (int f = 0; f < lengths.size(); f++) {
|
||||
long filelen = lengths.get(f).longValue();
|
||||
fend = fstart + filelen;
|
||||
if (toff < fend) {
|
||||
filenum = f;
|
||||
foff = toff - fstart;
|
||||
limit = fend - toff;
|
||||
break;
|
||||
}
|
||||
fstart += filelen;
|
||||
}
|
||||
if (filenum < 0)
|
||||
throw new IllegalStateException(lastRequest.toString());
|
||||
} else {
|
||||
// next file
|
||||
filenum++;
|
||||
foff = 0;
|
||||
limit = lengths.get(filenum).longValue();
|
||||
}
|
||||
|
||||
if (limit > 0 && flen > limit)
|
||||
flen = (int) limit;
|
||||
|
||||
if (metainfo.isPaddingFile(filenum)) {
|
||||
for (int i = 0; i < flen; i++) {
|
||||
out.write((byte) 0);
|
||||
}
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Skipped padding file " + filenum);
|
||||
continue;
|
||||
}
|
||||
|
||||
// build url
|
||||
String uri = _uri.toString();
|
||||
StringBuilder buf = new StringBuilder(uri.length() + 128);
|
||||
buf.append(uri);
|
||||
if (!uri.endsWith("/"))
|
||||
buf.append('/');
|
||||
// See BEP 19 rules
|
||||
URIUtil.encodePath(buf, metainfo.getName());
|
||||
List<String> path = metainfo.getFiles().get(filenum);
|
||||
for (int i = 0; i < path.size(); i++) {
|
||||
buf.append('/');
|
||||
URIUtil.encodePath(buf, path.get(i));
|
||||
}
|
||||
url = buf.toString();
|
||||
} else {
|
||||
// single file
|
||||
// See BEP 19 rules
|
||||
String uri = _uri.toString();
|
||||
if (uri.endsWith("/"))
|
||||
url = uri + URIUtil.encodePath(metainfo.getName());
|
||||
else
|
||||
url = uri;
|
||||
foff = toff;
|
||||
flen = tlen;
|
||||
}
|
||||
|
||||
// do the fetch
|
||||
EepGet get = new I2PSocketEepGet(util.getContext(), mgr, 0, flen, flen, null, out, url);
|
||||
get.addHeader("User-Agent", I2PSnarkUtil.EEPGET_USER_AGENT);
|
||||
get.addHeader("Range", "bytes=" + foff + '-' + (foff + flen - 1));
|
||||
get.addStatusListener(this);
|
||||
int osz = out.size();
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Fetching piece: " + piece + " offset: " + off + " file offset: " + foff + " len: " + flen + " from " + url);
|
||||
if (get.fetch(HEADER_TIMEOUT, TOTAL_TIMEOUT, INACTIVITY_TIMEOUT)) {
|
||||
int resp = get.getStatusCode();
|
||||
if (resp != 200 && resp != 206) {
|
||||
fail(url, resp);
|
||||
return;
|
||||
}
|
||||
int sz = out.size() - osz;
|
||||
if (sz != flen) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Fetch of " + url + " received: " + sz + " expected: " + flen);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (out.size() > 0) {
|
||||
// save any complete chunks received
|
||||
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(out.toByteArray()));
|
||||
for (Iterator<Request> iter = requests.iterator(); iter.hasNext(); ) {
|
||||
Request req = iter.next();
|
||||
if (dis.available() < req.len)
|
||||
break;
|
||||
req.read(dis);
|
||||
iter.remove();
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Saved chunk " + req + " recvd before failure");
|
||||
}
|
||||
}
|
||||
int resp = get.getStatusCode();
|
||||
fail(url, resp);
|
||||
return;
|
||||
}
|
||||
|
||||
successes++;
|
||||
dl += flen;
|
||||
|
||||
if (!isMultiFile)
|
||||
break;
|
||||
} // for each file
|
||||
|
||||
// all data received successfully, now process it
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Fetch of piece: " + piece + " chunks: " + requests.size() + " offset: " + off + " torrent offset: " + toff + " len: " + tlen + " successful");
|
||||
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(out.toByteArray()));
|
||||
for (Request req : requests) {
|
||||
req.read(dis);
|
||||
}
|
||||
|
||||
PartialPiece pp = last.getPartialPiece();
|
||||
synchronized(pp) {
|
||||
// Last chunk needed for this piece?
|
||||
if (pp.getLength() == pp.getDownloaded()) {
|
||||
if (listener.gotPiece(this, pp)) {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Got " + piece + ": " + this);
|
||||
} else {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Got BAD " + piece + " from " + this);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// piece not complete
|
||||
}
|
||||
}
|
||||
|
||||
long time = lastRcvd - start;
|
||||
if (time < TARGET_FETCH_TIME)
|
||||
maxRequests = Math.min(MAX_REQUESTS, 2 * maxRequests);
|
||||
else if (time > 2 * TARGET_FETCH_TIME)
|
||||
maxRequests = Math.max(MIN_REQUESTS, maxRequests / 2);
|
||||
} // request loop
|
||||
} catch(IOException eofe) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn(toString(), eofe);
|
||||
} finally {
|
||||
List<Request> pcs = returnPartialPieces();
|
||||
synchronized(this) {
|
||||
connected = false;
|
||||
outstandingRequests.clear();
|
||||
}
|
||||
requests.clear();
|
||||
if (!pcs.isEmpty())
|
||||
listener.savePartialPieces(this, pcs);
|
||||
listener.disconnected(this);
|
||||
disconnect();
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Completed, successful fetches: " + successes + " downloaded: " + dl + " for " + this);
|
||||
}
|
||||
}
|
||||
|
||||
private void fail(String url, int resp) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Fetch of " + url + " failed, rc: " + resp);
|
||||
if (resp == 301 || resp == 308 ||
|
||||
resp == 401 || resp == 403 || resp == 404 || resp == 410 || resp == 414 || resp == 416 || resp == 451) {
|
||||
// ban forever
|
||||
_coordinator.banWebPeer(_uri.getHost(), true);
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Permanently banning the webseed " + url);
|
||||
} else if (resp == 429 || resp == 503) {
|
||||
// ban for a while
|
||||
_coordinator.banWebPeer(_uri.getHost(), false);
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Temporarily banning the webseed " + url);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxPipeline() {
|
||||
return maxRequests;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
synchronized(this) {
|
||||
return connected;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void disconnect() {
|
||||
if (thread != null)
|
||||
thread.interrupt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void have(int piece) {}
|
||||
|
||||
@Override
|
||||
void cancel(int piece) {}
|
||||
|
||||
@Override
|
||||
void request() {
|
||||
addRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInterested() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setInteresting(boolean interest) {}
|
||||
|
||||
@Override
|
||||
public boolean isInteresting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChoking(boolean choke) {}
|
||||
|
||||
@Override
|
||||
public boolean isChoking() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChoked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getInactiveTime() {
|
||||
if (lastRcvd <= 0)
|
||||
return -1;
|
||||
long now = System.currentTimeMillis();
|
||||
return now - lastRcvd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxInactiveTime() {
|
||||
return PeerCoordinator.MAX_INACTIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keepAlive() {}
|
||||
|
||||
@Override
|
||||
public void retransmitRequests() {}
|
||||
|
||||
@Override
|
||||
public int completed() {
|
||||
return metainfo.getPieces();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompleted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true
|
||||
* @since 0.9.49
|
||||
*/
|
||||
@Override
|
||||
public boolean isWebPeer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// private methods below here implementing parts of PeerState
|
||||
|
||||
private synchronized void addRequest() {
|
||||
boolean more_pieces = true;
|
||||
while (more_pieces) {
|
||||
more_pieces = outstandingRequests.size() < getMaxPipeline();
|
||||
// We want something and we don't have outstanding requests?
|
||||
if (more_pieces && lastRequest == null) {
|
||||
// we have nothing in the queue right now
|
||||
more_pieces = requestNextPiece();
|
||||
} else if (more_pieces) {
|
||||
// We want something
|
||||
int pieceLength;
|
||||
boolean isLastChunk;
|
||||
pieceLength = metainfo.getPieceLength(lastRequest.getPiece());
|
||||
isLastChunk = lastRequest.off + lastRequest.len == pieceLength;
|
||||
|
||||
// Last part of a piece?
|
||||
if (isLastChunk) {
|
||||
more_pieces = requestNextPiece();
|
||||
} else {
|
||||
PartialPiece nextPiece = lastRequest.getPartialPiece();
|
||||
int nextBegin = lastRequest.off + PeerState.PARTSIZE;
|
||||
int maxLength = pieceLength - nextBegin;
|
||||
int nextLength = maxLength > PeerState.PARTSIZE ? PeerState.PARTSIZE
|
||||
: maxLength;
|
||||
Request req = new Request(nextPiece,nextBegin, nextLength);
|
||||
outstandingRequests.add(req);
|
||||
lastRequest = req;
|
||||
this.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts requesting first chunk of next piece. Returns true if
|
||||
* something has been added to the requests, false otherwise.
|
||||
*/
|
||||
private synchronized boolean requestNextPiece() {
|
||||
// Check for adopting an orphaned partial piece
|
||||
PartialPiece pp = listener.getPartialPiece(this, bitfield);
|
||||
if (pp != null) {
|
||||
// Double-check that r not already in outstandingRequests
|
||||
if (!getRequestedPieces().contains(Integer.valueOf(pp.getPiece()))) {
|
||||
Request r = pp.getRequest();
|
||||
outstandingRequests.add(r);
|
||||
lastRequest = r;
|
||||
this.notifyAll();
|
||||
return true;
|
||||
} else {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Got dup from coord: " + pp);
|
||||
pp.release();
|
||||
}
|
||||
}
|
||||
|
||||
// failsafe
|
||||
// However this is bad as it thrashes the peer when we change our mind
|
||||
// Ticket 691 cause here?
|
||||
if (outstandingRequests.isEmpty())
|
||||
lastRequest = null;
|
||||
|
||||
/*
|
||||
// If we are not in the end game, we may run out of things to request
|
||||
// because we are asking other peers. Set not-interesting now rather than
|
||||
// wait for those other requests to be satisfied via havePiece()
|
||||
if (interesting && lastRequest == null) {
|
||||
interesting = false;
|
||||
out.sendInterest(false);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug(peer + " nothing more to request, now uninteresting");
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all pieces we are currently requesting, or empty Set
|
||||
*/
|
||||
private synchronized Set<Integer> getRequestedPieces() {
|
||||
Set<Integer> rv = new HashSet<Integer>(outstandingRequests.size() + 1);
|
||||
for (Request req : outstandingRequests) {
|
||||
rv.add(Integer.valueOf(req.getPiece()));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return index in outstandingRequests or -1
|
||||
*/
|
||||
private synchronized int getFirstOutstandingRequest(int piece) {
|
||||
for (int i = 0; i < outstandingRequests.size(); i++) {
|
||||
if (outstandingRequests.get(i).getPiece() == piece)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private synchronized List<Request> returnPartialPieces() {
|
||||
Set<Integer> pcs = getRequestedPieces();
|
||||
List<Request> rv = new ArrayList<Request>(pcs.size());
|
||||
for (Integer p : pcs) {
|
||||
Request req = getLowestOutstandingRequest(p.intValue());
|
||||
if (req != null) {
|
||||
PartialPiece pp = req.getPartialPiece();
|
||||
synchronized(pp) {
|
||||
int dl = pp.getDownloaded();
|
||||
if (req.off != dl)
|
||||
req = new Request(pp, dl);
|
||||
}
|
||||
rv.add(req);
|
||||
}
|
||||
}
|
||||
outstandingRequests.clear();
|
||||
return rv;
|
||||
}
|
||||
|
||||
private synchronized Request getLowestOutstandingRequest(int piece) {
|
||||
Request rv = null;
|
||||
int lowest = Integer.MAX_VALUE;
|
||||
for (Request r : outstandingRequests) {
|
||||
if (r.getPiece() == piece && r.off < lowest) {
|
||||
lowest = r.off;
|
||||
rv = r;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// EepGet status listeners to maintain the state for the web page
|
||||
|
||||
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {
|
||||
lastRcvd = System.currentTimeMillis();
|
||||
downloaded(currentWrite);
|
||||
listener.downloaded(this, currentWrite);
|
||||
}
|
||||
|
||||
public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause) {}
|
||||
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {}
|
||||
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {}
|
||||
public void headerReceived(String url, int attemptNum, String key, String val) {}
|
||||
public void attempting(String url) {}
|
||||
|
||||
// End of EepGet status listeners
|
||||
}
|
||||
@@ -37,20 +37,6 @@ import net.i2p.data.DataHelper;
|
||||
public class BEncoder
|
||||
{
|
||||
|
||||
public static byte[] bencode(Object o) throws IllegalArgumentException
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
bencode(o, baos);
|
||||
return baos.toByteArray();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new InternalError(ioe.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void bencode(Object o, OutputStream out)
|
||||
throws IOException, IllegalArgumentException
|
||||
{
|
||||
@@ -72,40 +58,12 @@ public class BEncoder
|
||||
throw new IllegalArgumentException("Cannot bencode: " + o.getClass());
|
||||
}
|
||||
|
||||
public static byte[] bencode(String s)
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
bencode(s, baos);
|
||||
return baos.toByteArray();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new InternalError(ioe.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void bencode(String s, OutputStream out) throws IOException
|
||||
{
|
||||
byte[] bs = s.getBytes("UTF-8");
|
||||
bencode(bs, out);
|
||||
}
|
||||
|
||||
public static byte[] bencode(Number n)
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
bencode(n, baos);
|
||||
return baos.toByteArray();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new InternalError(ioe.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void bencode(Number n, OutputStream out) throws IOException
|
||||
{
|
||||
out.write('i');
|
||||
@@ -114,20 +72,6 @@ public class BEncoder
|
||||
out.write('e');
|
||||
}
|
||||
|
||||
public static byte[] bencode(List<?> l)
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
bencode(l, baos);
|
||||
return baos.toByteArray();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new InternalError(ioe.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void bencode(List<?> l, OutputStream out) throws IOException
|
||||
{
|
||||
out.write('l');
|
||||
@@ -137,20 +81,6 @@ public class BEncoder
|
||||
out.write('e');
|
||||
}
|
||||
|
||||
public static byte[] bencode(byte[] bs)
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
bencode(bs, baos);
|
||||
return baos.toByteArray();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new InternalError(ioe.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void bencode(byte[] bs, OutputStream out) throws IOException
|
||||
{
|
||||
String l = Integer.toString(bs.length);
|
||||
@@ -216,7 +146,8 @@ public class BEncoder
|
||||
if (l != null) {
|
||||
// Keys must be sorted. XXX - This is not the correct order.
|
||||
// Spec says to sort by bytes, not lexically
|
||||
Collections.sort(l);
|
||||
if (l.size() > 1)
|
||||
Collections.sort(l);
|
||||
for (String key : l) {
|
||||
bencode(key, out);
|
||||
bencode(m.get(key), out);
|
||||
@@ -224,7 +155,8 @@ public class BEncoder
|
||||
} else if (b != null) {
|
||||
// Works for arrays of equal lengths, otherwise is probably not
|
||||
// what the bittorrent spec intends.
|
||||
Collections.sort(b, new BAComparator());
|
||||
if (b.size() > 1)
|
||||
Collections.sort(b, new BAComparator());
|
||||
for (byte[] key : b) {
|
||||
bencode(key, out);
|
||||
bencode(m.get(key), out);
|
||||
|
||||
@@ -42,6 +42,8 @@ import net.i2p.util.Log;
|
||||
import net.i2p.util.SecureFile;
|
||||
import net.i2p.util.SystemVersion;
|
||||
|
||||
import org.klomp.snark.URIUtil;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
@@ -472,6 +474,8 @@ class BasicServlet extends HttpServlet
|
||||
/* ------------------------------------------------------------ */
|
||||
public InputStream getInputStream() throws IOException
|
||||
{
|
||||
if (getContentLength() > 4*1024*1024)
|
||||
return new BufferedInputStream(new FileInputStream(_file), 64*1024);
|
||||
return new BufferedInputStream(new FileInputStream(_file));
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ import org.klomp.snark.SnarkManager;
|
||||
import org.klomp.snark.Storage;
|
||||
import org.klomp.snark.Tracker;
|
||||
import org.klomp.snark.TrackerClient;
|
||||
import org.klomp.snark.URIUtil;
|
||||
import org.klomp.snark.dht.DHT;
|
||||
import org.klomp.snark.comments.Comment;
|
||||
import org.klomp.snark.comments.CommentSet;
|
||||
@@ -201,10 +202,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_context.isRouterContext())
|
||||
_themePath = "/themes/snark/" + _manager.getTheme() + '/';
|
||||
else
|
||||
_themePath = _contextPath + WARBASE + "themes/snark/" + _manager.getTheme() + '/';
|
||||
_themePath = _contextPath + WARBASE + "themes/" + _manager.getTheme() + '/';
|
||||
_imgPath = _themePath + "images/";
|
||||
req.setCharacterEncoding("UTF-8");
|
||||
|
||||
@@ -463,7 +461,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
*/
|
||||
private boolean writeTorrents(PrintWriter out, HttpServletRequest req, boolean canWrite) throws IOException {
|
||||
/** dl, ul, down rate, up rate, peers, size */
|
||||
final long stats[] = {0,0,0,0,0,0};
|
||||
final long stats[] = new long[6];
|
||||
String peerParam = req.getParameter("p");
|
||||
String stParam = req.getParameter("st");
|
||||
|
||||
@@ -564,7 +562,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
out.write("</th>\n<th class=\"snarkTorrentETA\" align=\"right\">");
|
||||
if (_manager.util().connected() && !snarks.isEmpty()) {
|
||||
if (showSort) {
|
||||
sort = ("-4".equals(currentSort)) ? "4" : "-4";
|
||||
sort = ("4".equals(currentSort)) ? "-4" : "4";
|
||||
out.write("<a href=\"" + _contextPath + '/' + getQueryString(req, null, null, sort));
|
||||
out.write("\">");
|
||||
}
|
||||
@@ -1088,6 +1086,12 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
// b32
|
||||
newURL = newURL.toUpperCase(Locale.US);
|
||||
addMagnet(MagnetURI.MAGNET_FULL + newURL, dir);
|
||||
} else if (newURL.length() == 68 && newURL.startsWith("1220") &&
|
||||
newURL.replaceAll("[a-fA-F0-9]", "").length() == 0) {
|
||||
// hex v2 multihash
|
||||
// TODO
|
||||
_manager.addMessage("Version 2 info hashes are not supported");
|
||||
//addMagnet(MagnetURI.MAGNET_FULL_V2 + newURL, dir);
|
||||
} else {
|
||||
// try as file path, hopefully we're on the same box
|
||||
if (newURL.startsWith("file://"))
|
||||
@@ -1141,8 +1145,8 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
try { if (in != null) in.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
} else {
|
||||
_manager.addMessage(_t("Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"",
|
||||
MagnetURI.MAGNET, MagnetURI.MAGGOT));
|
||||
_manager.addMessage(_t("Invalid URL: Must start with \"{0}\" or \"{1}\"",
|
||||
"http://", MagnetURI.MAGNET));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1989,33 +1993,38 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
out.write(_t("Peer attached to swarm"));
|
||||
out.write("\"></td><td colspan=\"5\">");
|
||||
PeerID pid = peer.getPeerID();
|
||||
String ch = pid != null ? pid.toString().substring(0, 4) : "????";
|
||||
String client;
|
||||
if ("AwMD".equals(ch))
|
||||
client = _t("I2PSnark");
|
||||
else if ("LUJJ".equals(ch))
|
||||
client = "BiglyBT" + getAzVersion(pid.getID());
|
||||
else if ("LUFa".equals(ch))
|
||||
client = "Vuze" + getAzVersion(pid.getID());
|
||||
else if ("LVhE".equals(ch))
|
||||
client = "XD" + getAzVersion(pid.getID());
|
||||
else if ("ZV".equals(ch.substring(2,4)) || "VUZP".equals(ch))
|
||||
client = "Robert" + getRobtVersion(pid.getID());
|
||||
else if (ch.startsWith("LV")) // LVCS 1.0.2?; LVRS 1.0.4
|
||||
client = "Transmission" + getAzVersion(pid.getID());
|
||||
else if ("LUtU".equals(ch))
|
||||
client = "KTorrent" + getAzVersion(pid.getID());
|
||||
else if ("CwsL".equals(ch))
|
||||
client = "I2PSnarkXL";
|
||||
else if ("BFJT".equals(ch))
|
||||
client = "I2PRufus";
|
||||
else if ("TTMt".equals(ch))
|
||||
client = "I2P-BT";
|
||||
else
|
||||
client = _t("Unknown") + " (" + ch + ')';
|
||||
out.write(client + " <tt title=\"");
|
||||
out.write(_t("Destination (identity) of peer"));
|
||||
out.write("\">" + peer.toString().substring(5, 9)+ "</tt>");
|
||||
String ch = pid != null ? pid.toString() : "????";
|
||||
if (ch.startsWith("WebSeed@")) {
|
||||
out.write(ch);
|
||||
} else {
|
||||
ch = ch.substring(0, 4);
|
||||
String client;
|
||||
if ("AwMD".equals(ch))
|
||||
client = _t("I2PSnark");
|
||||
else if ("LUJJ".equals(ch))
|
||||
client = "BiglyBT" + getAzVersion(pid.getID());
|
||||
else if ("LUFa".equals(ch))
|
||||
client = "Vuze" + getAzVersion(pid.getID());
|
||||
else if ("LVhE".equals(ch))
|
||||
client = "XD" + getAzVersion(pid.getID());
|
||||
else if ("ZV".equals(ch.substring(2,4)) || "VUZP".equals(ch))
|
||||
client = "Robert" + getRobtVersion(pid.getID());
|
||||
else if (ch.startsWith("LV")) // LVCS 1.0.2?; LVRS 1.0.4
|
||||
client = "Transmission" + getAzVersion(pid.getID());
|
||||
else if ("LUtU".equals(ch))
|
||||
client = "KTorrent" + getAzVersion(pid.getID());
|
||||
else if ("CwsL".equals(ch))
|
||||
client = "I2PSnarkXL";
|
||||
else if ("BFJT".equals(ch))
|
||||
client = "I2PRufus";
|
||||
else if ("TTMt".equals(ch))
|
||||
client = "I2P-BT";
|
||||
else
|
||||
client = _t("Unknown") + " (" + ch + ')';
|
||||
out.write(client + " <tt title=\"");
|
||||
out.write(_t("Destination (identity) of peer"));
|
||||
out.write("\">" + peer.toString().substring(5, 9)+ "</tt>");
|
||||
}
|
||||
if (showDebug) {
|
||||
long t = peer.getInactiveTime();
|
||||
if (t >= 5000)
|
||||
@@ -2298,7 +2307,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
out.write(_t("From URL"));
|
||||
out.write(":<td><input type=\"text\" name=\"nofilter_newURL\" size=\"85\" value=\"" + newURL + "\" spellcheck=\"false\"" +
|
||||
" title=\"");
|
||||
out.write(_t("Enter the torrent file download URL (I2P only), magnet link, maggot link, or info hash"));
|
||||
out.write(_t("Enter the torrent file download URL (I2P only), magnet link, or info hash"));
|
||||
out.write("\">\n");
|
||||
// not supporting from file at the moment, since the file name passed isn't always absolute (so it may not resolve)
|
||||
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>");
|
||||
@@ -2470,8 +2479,8 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
if (!_context.isRouterContext()) {
|
||||
try {
|
||||
// class only in standalone builds
|
||||
Class helper = Class.forName("org.klomp.snark.standalone.ConfigUIHelper");
|
||||
Method getLangSettings = helper.getMethod("getLangSettings", new Class[] {I2PAppContext.class});
|
||||
Class<?> helper = Class.forName("org.klomp.snark.standalone.ConfigUIHelper");
|
||||
Method getLangSettings = helper.getMethod("getLangSettings", I2PAppContext.class);
|
||||
String langSettings = (String) getLangSettings.invoke(null, _context);
|
||||
// If we get to here, we have the language settings
|
||||
out.write("<tr><td>");
|
||||
@@ -2801,6 +2810,10 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
* @since 0.8.4
|
||||
*/
|
||||
private void addMagnet(String url, File dataDir) {
|
||||
if (url.startsWith(MagnetURI.MAGNET_FULL_V2)) {
|
||||
_manager.addMessage("Version 2 magnet links are not supported");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
MagnetURI magnet = new MagnetURI(_manager.util(), url);
|
||||
String name = magnet.getName();
|
||||
@@ -3169,9 +3182,34 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
}
|
||||
buf.append("</td></tr>\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (meta != null) {
|
||||
List<String> weblist = meta.getWebSeedURLs();
|
||||
if (weblist != null) {
|
||||
List<String> wlist = new ArrayList<String>(weblist.size());
|
||||
// strip non-i2p web seeds
|
||||
for (String s : weblist) {
|
||||
if (isI2PTracker(s))
|
||||
wlist.add(s);
|
||||
}
|
||||
if (!wlist.isEmpty()) {
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "details");
|
||||
buf.append("</td><td><b>")
|
||||
.append(_t("Web Seeds")).append("</b></td><td>");
|
||||
boolean more = false;
|
||||
for (String s : wlist) {
|
||||
buf.append("<span class=\"info_tracker\">");
|
||||
if (more)
|
||||
buf.append(' ');
|
||||
else
|
||||
more = true;
|
||||
buf.append(getShortTrackerLink(DataHelper.stripHTML(s), snark.getInfoHash()));
|
||||
buf.append("</span> ");
|
||||
}
|
||||
buf.append("</td></tr>\n");
|
||||
}
|
||||
}
|
||||
|
||||
String com = meta.getComment();
|
||||
if (com != null && com.length() > 0) {
|
||||
if (com.length() > 1024)
|
||||
@@ -3278,6 +3316,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
else
|
||||
buf.append(_t("Complete")).append("</b>");
|
||||
buf.append("</td><td><span>");
|
||||
// TODO adjust for padding files
|
||||
buf.append("<b>")
|
||||
.append(_t("Size"))
|
||||
.append(":</b> ")
|
||||
@@ -3296,6 +3335,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
} else {
|
||||
buf.append('0');
|
||||
}
|
||||
// TODO adjust for padding files
|
||||
// not including skipped files, but -1 when not running
|
||||
long needed = snark.getNeededLength();
|
||||
if (needed < 0) {
|
||||
@@ -3309,6 +3349,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
.append(":</b> ")
|
||||
.append(formatSize(needed));
|
||||
}
|
||||
// TODO adjust for padding files
|
||||
long skipped = snark.getSkippedLength();
|
||||
if (skipped > 0) {
|
||||
buf.append("</span> <span>");
|
||||
@@ -3317,9 +3358,8 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
.append(":</b> ")
|
||||
.append(formatSize(skipped));
|
||||
}
|
||||
if (meta != null) {
|
||||
List<List<String>> files = meta.getFiles();
|
||||
int fileCount = files != null ? files.size() : 1;
|
||||
if (storage != null) {
|
||||
int fileCount = storage.getFileCount();
|
||||
buf.append("</span> <span>");
|
||||
buf.append("<b>")
|
||||
.append(_t("Files"))
|
||||
@@ -3427,14 +3467,14 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
if (isAudio)
|
||||
buf.append("<audio");
|
||||
else
|
||||
buf.append("<video");
|
||||
buf.append("<div class=\"video-wrapper\"><video class=\"video\"");
|
||||
// strip trailing slash
|
||||
String path = base.substring(0, base.length() - 1);
|
||||
buf.append(" controls><source src=\"").append(path).append("\" type=\"").append(mime).append("\">");
|
||||
if (isAudio)
|
||||
buf.append("</audio>");
|
||||
else
|
||||
buf.append("</video>");
|
||||
buf.append("</video></div>");
|
||||
}
|
||||
}
|
||||
if (er || ec)
|
||||
@@ -3451,7 +3491,16 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
long[] remainingArray = (arrays != null) ? arrays[0] : null;
|
||||
long[] previewArray = (arrays != null) ? arrays[1] : null;
|
||||
for (int i = 0; i < ls.length; i++) {
|
||||
fileList.add(new Sorters.FileAndIndex(ls[i], storage, remainingArray, previewArray));
|
||||
File f = ls[i];
|
||||
if (isTopLevel) {
|
||||
// Hide (assumed) padding directory if it's in the filesystem.
|
||||
// Storage now will not create padding files, but
|
||||
// may have been created by an old version or other client.
|
||||
String n = f.getName();
|
||||
if ((n.equals(".pad") || n.equals("_pad")) && f.isDirectory())
|
||||
continue;
|
||||
}
|
||||
fileList.add(new Sorters.FileAndIndex(f, storage, remainingArray, previewArray));
|
||||
}
|
||||
|
||||
boolean showSort = fileList.size() > 1;
|
||||
@@ -3612,7 +3661,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
}
|
||||
|
||||
String path = addPaths(decodedBase, item.getName());
|
||||
if (item.isDirectory() && !path.endsWith("/"))
|
||||
if (fai.isDirectory && !path.endsWith("/"))
|
||||
path=addPaths(path,"/");
|
||||
path = encodePath(path);
|
||||
String icon = toIcon(item);
|
||||
@@ -3638,7 +3687,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
if (isAudio)
|
||||
buf.append("<audio");
|
||||
else
|
||||
buf.append("<video");
|
||||
buf.append("<div class=\"video-wrapper\"><video class=\"video\"");
|
||||
buf.append(" controls><source src=\"").append(ppath).append("\" type=\"").append(mime).append("\">");
|
||||
}
|
||||
buf.append("<a href=\"").append(ppath).append("\">");
|
||||
@@ -3652,7 +3701,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
if (isAudio)
|
||||
buf.append("</audio>");
|
||||
else if (isVideo)
|
||||
buf.append("</video>");
|
||||
buf.append("</video></div>");
|
||||
} else {
|
||||
buf.append(toImg(icon));
|
||||
}
|
||||
@@ -3672,14 +3721,14 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
if (preview != null)
|
||||
buf.append(preview);
|
||||
buf.append("</td><td align=right class=\"snarkFileSize\">");
|
||||
if (!item.isDirectory())
|
||||
if (!fai.isDirectory)
|
||||
buf.append(formatSize(length));
|
||||
buf.append("</td><td class=\"snarkFileStatus\">");
|
||||
buf.append(status);
|
||||
buf.append("</td>");
|
||||
if (showPriority) {
|
||||
buf.append("<td class=\"priority\">");
|
||||
if ((!complete) && (!item.isDirectory())) {
|
||||
if ((!complete) && (!fai.isDirectory)) {
|
||||
if (!inOrder) {
|
||||
buf.append("<label class=\"priorityHigh\" title=\"").append(_t("Download file at high priority")).append("\">" +
|
||||
"\n<input type=\"radio\" class=\"prihigh\" value=\"5\" name=\"pri.").append(fileIndex).append("\" ");
|
||||
@@ -4141,6 +4190,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
if (mime.equals("text/html"))
|
||||
icon = "html";
|
||||
else if (mime.equals("text/plain") ||
|
||||
mime.equals("text/markdown") ||
|
||||
mime.equals("text/x-sfv") ||
|
||||
mime.equals("application/rtf"))
|
||||
icon = "page";
|
||||
@@ -4201,7 +4251,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
* @since 0.8.2
|
||||
*/
|
||||
private String toImg(String icon, String altText) {
|
||||
return "<img alt=\"" + altText + "\" height=\"16\" width=\"16\" src=\"" + _contextPath + WARBASE + "icons/" + icon + ".png\">";
|
||||
return "<img alt=\"" + altText + "\" height=\"16\" width=\"16\" src=\"" + _contextPath + WARBASE + "icons/" + _manager.getThemeIconSet() + icon + ".png?" + CoreVersion.VERSION + "\">";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user