Compare commits
336 Commits
i2p-0.9.47
...
build-debi
Author | SHA1 | Date | |
---|---|---|---|
c0a0aa7700 | |||
4a9131c39d | |||
b47269f14e | |||
fb317b44ba | |||
e64e12b3fb | |||
f71e59a049 | |||
169fb59d7d | |||
![]() |
922178b2c7 | ||
![]() |
74a9193ba5 | ||
![]() |
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 | ||
![]() |
1154d28be7 |
31
.dockerignore
Normal file
@@ -0,0 +1,31 @@
|
||||
.idea
|
||||
.git
|
||||
Dockerfile
|
||||
|
||||
|
||||
# Gradle
|
||||
.gradle
|
||||
build
|
||||
apps/BOB/build
|
||||
apps/addressbook/build
|
||||
apps/desktopgui/build
|
||||
apps/i2pcontrol/build
|
||||
apps/i2psnark/build
|
||||
apps/i2ptunnel/build
|
||||
apps/imagegen/build
|
||||
apps/jetty/build
|
||||
apps/jrobin/build
|
||||
apps/ministreaming/java/build
|
||||
apps/ministreaming/build
|
||||
apps/routerconsole/build
|
||||
apps/sam/build
|
||||
apps/streaming/build
|
||||
apps/susidns/build
|
||||
apps/susimail/build
|
||||
apps/systray/build
|
||||
core/java/build
|
||||
core/build
|
||||
installer/build
|
||||
router/java/build
|
||||
router/build
|
||||
|
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
|
||||
|
66
.gitlab-ci.yml
Normal file
@@ -0,0 +1,66 @@
|
||||
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
|
||||
|
||||
# Make sure we can build a docker image
|
||||
# It's cached for later jobs
|
||||
build_docker:
|
||||
stage: test
|
||||
image: docker:19.03.12
|
||||
services:
|
||||
- docker:19.03.12-dind
|
||||
script:
|
||||
# Try to load latest branch image from local tar or from registry
|
||||
- docker load -i ci-exports/$CI_COMMIT_REF_SLUG.tar || docker pull $CI_REGISTRY_IMAGE:latest || true
|
||||
- docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:latest .
|
||||
- mkdir -p ci-exports/
|
||||
- docker save $CI_REGISTRY_IMAGE:latest > ci-exports/$CI_COMMIT_REF_SLUG.tar
|
||||
variables:
|
||||
# When using dind service, we need to instruct docker to talk with
|
||||
# the daemon started inside of the service. The daemon is available
|
||||
# with a network connection instead of the default
|
||||
# /var/run/docker.sock socket. Docker 19.03 does this automatically
|
||||
# by setting the DOCKER_HOST in
|
||||
# https://github.com/docker-library/docker/blob/d45051476babc297257df490d22cbd806f1b11e4/19.03/docker-entrypoint.sh#L23-L29
|
||||
#
|
||||
# The 'docker' hostname is the alias of the service container as described at
|
||||
# https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services.
|
||||
#
|
||||
# Specify to Docker where to create the certificates, Docker will
|
||||
# create them automatically on boot, and will create
|
||||
# `/certs/client` that will be shared between the service and job
|
||||
# container, thanks to volume mount from config.toml
|
||||
DOCKER_TLS_CERTDIR: "/certs"
|
||||
# Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
|
||||
DOCKER_HOST: tcp://docker:2376
|
||||
cache:
|
||||
# The same key should be used across branches
|
||||
key: "$CI_COMMIT_REF_SLUG"
|
||||
paths:
|
||||
- ci-exports/*.tar
|
||||
only:
|
||||
- master
|
||||
- merge_requests
|
||||
- tags
|
||||
|
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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>
|
16
.travis.yml
@@ -1,17 +1,17 @@
|
||||
language: java
|
||||
dist: xenial
|
||||
dist: bionic
|
||||
|
||||
jdk:
|
||||
- oraclejdk11
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- jdk: oraclejdk8
|
||||
- jdk: oraclejdk11
|
||||
addons:
|
||||
sonarcloud:
|
||||
organization: "i2p"
|
||||
before_install:
|
||||
- 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_cache:
|
||||
@@ -24,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
@@ -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
|
||||
|
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
export JAVA_HOME=/opt/jdk/jre
|
||||
|
||||
# Ensure user rights
|
||||
chown -R i2p:nobody /opt/i2p
|
||||
chmod -R u+rwx /opt/i2p
|
||||
|
||||
gosu i2p /opt/i2p/i2psvc /opt/i2p/wrapper.config wrapper.pidfile=/var/tmp/i2p.pid \
|
||||
wrapper.name=i2p \
|
||||
wrapper.displayname="I2P Service" \
|
||||
wrapper.statusfile=/var/tmp/i2p.status \
|
||||
wrapper.java.statusfile=/var/tmp/i2p.java.status \
|
||||
wrapper.logfile=/var/tmp/wrapper.log
|
80
Dockerfile
@@ -1,62 +1,40 @@
|
||||
FROM meeh/java8server:latest
|
||||
# Docker image based on Alpine with Java.
|
||||
# Use a multi-stage build to reduce the size of the resulting image
|
||||
# We need alpine >v3 in order to install an apache-ant > 1.9
|
||||
FROM debian:buster-slim as builder
|
||||
|
||||
# We use Oracle Java to run I2P, but uses the openjdk to build it.
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Build installer
|
||||
RUN apt-get update \
|
||||
# Workaround for installing openjdk-11-jre-headless
|
||||
&& mkdir -p /usr/share/man/man1 \
|
||||
&& apt-get -qqqy install debhelper ant debconf gettext libgmp-dev po-debconf fakeroot \
|
||||
build-essential quilt dh-apparmor dh-systemd libservice-wrapper-java libjson-simple-java \
|
||||
devscripts libjetty9-java libtomcat9-java libtaglibs-standard-jstlel-java libgetopt-java \
|
||||
bash-completion
|
||||
|
||||
MAINTAINER Mikal Villa <mikal@sigterm.no>
|
||||
WORKDIR /tmp/build
|
||||
COPY . ./
|
||||
|
||||
ENV GIT_BRANCH="master"
|
||||
ENV I2P_PREFIX="/opt/i2p"
|
||||
ENV PATH=${I2P_PREFIX}/bin:$PATH
|
||||
ENV JAVA_HOME=/usr/lib/jvm/default-jvm
|
||||
RUN ant debian
|
||||
|
||||
ENV GOSU_VERSION=1.7
|
||||
ENV GOSU_SHASUM="34049cfc713e8b74b90d6de49690fa601dc040021980812b2f1f691534be8a50 /usr/local/bin/gosu"
|
||||
|
||||
RUN mkdir /user && adduser -S -h /user i2p && chown -R i2p:nobody /user
|
||||
|
||||
# Adding files first, since Docker.expt is required for installation
|
||||
ADD Docker.expt /tmp/Docker.expt
|
||||
ADD Docker.entrypoint.sh /entrypoint.sh
|
||||
|
||||
# Required for wget https
|
||||
RUN apk add --no-cache openssl
|
||||
# Gosu is a replacement for su/sudo in docker and not a backdoor :) See https://github.com/tianon/gosu
|
||||
RUN wget -O /usr/local/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64 \
|
||||
&& echo "${GOSU_SHASUM}" | sha256sum -c && chmod +x /usr/local/bin/gosu
|
||||
|
||||
#
|
||||
# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the
|
||||
# image under 200mb we need to remove all the build dependencies in the same "RUN" / layer.
|
||||
#
|
||||
|
||||
# The main layer
|
||||
RUN apk --no-cache add build-base git gettext tar bzip2 apache-ant openjdk8 expect \
|
||||
&& mkdir -p /usr/src/build \
|
||||
&& cd /usr/src/build \
|
||||
&& git clone -b ${GIT_BRANCH} https://github.com/i2p/i2p.i2p.git \
|
||||
&& cd /usr/src/build/i2p.i2p \
|
||||
&& echo "noExe=true" >> build.properties \
|
||||
&& ant installer-linux \
|
||||
&& cp i2pinstall*.jar /tmp/i2pinstall.jar \
|
||||
&& mkdir -p /opt \
|
||||
&& chown i2p:root /opt \
|
||||
&& chmod u+rw /opt \
|
||||
&& gosu i2p expect -f /tmp/Docker.expt \
|
||||
&& cd ${I2P_PREFIX} \
|
||||
&& rm -fr man docs *.bat *.command *.app /tmp/i2pinstall.jar /tmp/Docker.expt \
|
||||
&& rm -fr /usr/src/build \
|
||||
&& apk --purge del build-base apache-ant expect tcl expat git openjdk8 openjdk8-jre openjdk8-jre-base openjdk8-jre-lib bzip2 tar \
|
||||
binutils-libs binutils pkgconfig libcurl libc-dev musl-dev g++ make fortify-headers pkgconf giflib libssh2 libxdmcp libxcb \
|
||||
libx11 pcre alsa-lib libxi libxrender libxml2 readline bash openssl \
|
||||
&& rm -fr /usr/lib/jvm/default-jre \
|
||||
&& ln -sf /opt/jdk/jre /usr/lib/jvm/default-jre \
|
||||
&& chmod a+x /entrypoint.sh
|
||||
# Second stage only using the installer from the last stage
|
||||
# ---------------------------------------------------------
|
||||
# We can't use alpine here as the java service wrapper is built with glibc
|
||||
# alpine uses musl
|
||||
FROM openjdk:11.0-jre-slim
|
||||
|
||||
# "install" i2p by copying over installed files
|
||||
COPY --from=builder /tmp/*.deb /tmp/
|
||||
|
||||
# Install and configure
|
||||
RUN apt-get update -qqq \
|
||||
&& apt-get -qqqy install geoip-database famfamfam-flag-png \
|
||||
&& dpkb -i /tmp/*
|
||||
|
||||
EXPOSE 7654 7656 7657 7658 4444 6668 8998 7659 7660 4445 15000-20000
|
||||
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||
USER i2psvc
|
||||
ENTRYPOINT [ "/usr/bin/i2prouter" ]
|
||||
CMD start
|
||||
|
||||
|
@@ -1,10 +1,10 @@
|
||||
I2P source installation instructions
|
||||
|
||||
Prerequisites to build from source:
|
||||
Java SDK (preferably Oracle/Sun or OpenJDK) 1.8.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.
|
||||
|
26
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
|
||||
@@ -98,6 +94,12 @@ Public domain except as listed below:
|
||||
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:
|
||||
@@ -126,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)
|
||||
@@ -180,10 +186,10 @@ Launchers:
|
||||
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
|
||||
|
||||
|
||||
@@ -193,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
|
||||
|
||||
|
||||
@@ -255,10 +261,10 @@ 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.3.28.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
|
||||
@@ -333,7 +339,7 @@ Applications:
|
||||
Systray (systray.jar):
|
||||
Public domain.
|
||||
|
||||
Tomcat 9.0.35 (jasper-runtime.jar):
|
||||
Tomcat 9.0.40 (jasper-runtime.jar):
|
||||
(not included in most distribution packages)
|
||||
Copyright 1999-2020 The Apache Software Foundation
|
||||
See licenses/LICENSE-Apache2.0.txt
|
||||
|
@@ -27,11 +27,11 @@ To get development branch from source control: [https://geti2p.net/newdevelopers
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Java SDK (preferably Oracle/Sun or OpenJDK) 1.8.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](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/)
|
||||
- Build environment must use a UTF-8 locale.
|
||||
|
@@ -1,8 +1,8 @@
|
||||
Prerequisites to build from source:
|
||||
Java SDK (preferably Oracle/Sun or OpenJDK) 1.8.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>
|
||||
|
@@ -8,6 +8,7 @@
|
||||
<property name="war" value="addressbook.war"/>
|
||||
<property name="javac.compilerargs" value="" />
|
||||
<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}">
|
||||
|
@@ -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
|
||||
@@ -111,7 +111,7 @@ class Daemon {
|
||||
* 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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -8,6 +8,7 @@
|
||||
<property name="javadoc" value="javadoc"/>
|
||||
<property name="javac.compilerargs" value=""/>
|
||||
<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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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')
|
||||
}
|
@@ -51,6 +51,7 @@
|
||||
|
||||
<property name="javac.compilerargs" value="" />
|
||||
<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>
|
||||
|
@@ -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]
|
||||
*
|
||||
|
@@ -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
|
||||
|
@@ -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'
|
||||
|
@@ -28,6 +28,7 @@
|
||||
<!-- only used if not set by a higher build.xml -->
|
||||
<property name="javac.compilerargs" value="" />
|
||||
<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
|
||||
|
@@ -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");
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -42,14 +42,14 @@ 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
|
||||
@@ -61,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 */
|
||||
@@ -77,19 +80,18 @@ 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;
|
||||
@@ -291,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();
|
||||
@@ -342,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
|
||||
@@ -367,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 "
|
||||
@@ -790,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;
|
||||
|
@@ -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
@@ -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");
|
||||
|
||||
@@ -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("\" ");
|
||||
@@ -4202,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 + "\">";
|
||||
}
|
||||
|
||||
/**
|
||||
|
Before Width: | Height: | Size: 502 B After Width: | Height: | Size: 464 B |
Before Width: | Height: | Size: 513 B After Width: | Height: | Size: 842 B |
Before Width: | Height: | Size: 599 B After Width: | Height: | Size: 476 B |
Before Width: | Height: | Size: 605 B After Width: | Height: | Size: 810 B |
Before Width: | Height: | Size: 580 B After Width: | Height: | Size: 882 B |
Before Width: | Height: | Size: 530 B After Width: | Height: | Size: 704 B |
Before Width: | Height: | Size: 407 B After Width: | Height: | Size: 613 B |